aboutsummaryrefslogtreecommitdiff
path: root/src
ModeNameSize
-rw-r--r--CMakeLists.txt15931logplain
-rw-r--r--activeobject.h1555logplain
-rw-r--r--ban.cpp3938logplain
-rw-r--r--ban.h1489logplain
-rw-r--r--base64.cpp3900logplain
-rw-r--r--base64.h250logplain
-rw-r--r--biome.cpp4568logplain
-rw-r--r--biome.h1998logplain
-rw-r--r--camera.cpp18025logplain
-rw-r--r--camera.h4780logplain
-rw-r--r--cavegen.cpp14434logplain
-rw-r--r--cavegen.h2737logplain
d---------cguittfont248logplain
-rw-r--r--chat.cpp17077logplain
-rw-r--r--chat.h7215logplain
-rw-r--r--client.cpp73363logplain
-rw-r--r--client.h12095logplain
-rw-r--r--clientmap.cpp24248logplain
-rw-r--r--clientmap.h3440logplain
-rw-r--r--clientobject.cpp1773logplain
-rw-r--r--clientobject.h3637logplain
-rw-r--r--clientserver.cpp1077logplain
-rw-r--r--clientserver.h13656logplain
-rw-r--r--clientsimpleobject.h1113logplain
-rw-r--r--clouds.cpp9656logplain
-rw-r--r--clouds.h1678logplain
-rw-r--r--cmake_config.h.in698logplain
-rw-r--r--collision.cpp17012logplain
-rw-r--r--collision.h2729logplain
-rw-r--r--config.h979logplain
-rw-r--r--connection.cpp41581logplain
-rw-r--r--connection.h14939logplain
-rw-r--r--constants.h2660logplain
-rw-r--r--content_abm.cpp6329logplain
-rw-r--r--content_abm.h1006logplain
-rw-r--r--content_cao.cpp51701logplain
-rw-r--r--content_cao.h853logplain
-rw-r--r--content_cso.cpp2892logplain
-rw-r--r--content_cso.h1032logplain
-rw-r--r--content_mapblock.cpp42143logplain
-rw-r--r--content_mapblock.h992logplain
-rw-r--r--content_mapnode.cpp8109logplain
-rw-r--r--content_mapnode.h1510logplain
-rw-r--r--content_nodemeta.cpp5465logplain
-rw-r--r--content_nodemeta.h1163logplain
-rw-r--r--content_object.h1263logplain
-rw-r--r--content_sao.cpp38162logplain
-rw-r--r--content_sao.h7525logplain
-rw-r--r--craftdef.cpp27486logplain
-rw-r--r--craftdef.h11691logplain
-rw-r--r--daynightratio.h1841logplain
-rw-r--r--debug.cpp5617logplain
-rw-r--r--debug.h6263logplain
-rw-r--r--defaultsettings.cpp12877logplain
-rw-r--r--defaultsettings.h989logplain
-rw-r--r--dungeongen.cpp16866logplain
-rw-r--r--dungeongen.h3283logplain
-rw-r--r--emerge.cpp13498logplain
-rw-r--r--emerge.h3405logplain
-rw-r--r--environment.cpp64851logplain
-rw-r--r--environment.h12205logplain
-rw-r--r--event.h1912logplain
-rw-r--r--event_manager.h2964logplain
-rw-r--r--exceptions.h3297logplain
-rw-r--r--farmesh.cpp11566logplain
-rw-r--r--farmesh.h1827logplain
-rw-r--r--filecache.cpp3145logplain
-rw-r--r--filecache.h1466logplain
-rw-r--r--filesys.cpp10190logplain
-rw-r--r--filesys.h1967logplain
-rw-r--r--game.cpp84049logplain
-rw-r--r--game.h3147logplain
-rw-r--r--gamedef.h2677logplain
-rw-r--r--genericobject.cpp4381logplain
-rw-r--r--genericobject.h2372logplain
-rw-r--r--gettext.h2090logplain
-rw-r--r--gettime.h1568logplain
-rw-r--r--guiChatConsole.cpp13930logplain
-rw-r--r--guiChatConsole.h3481logplain
-rw-r--r--guiConfigureWorld.cpp21156logplain
-rw-r--r--guiConfigureWorld.h3156logplain
-rw-r--r--guiConfirmMenu.cpp4678logplain
-rw-r--r--guiConfirmMenu.h1522logplain
-rw-r--r--guiCreateWorld.cpp6268logplain
-rw-r--r--guiCreateWorld.h1602logplain
-rw-r--r--guiDeathScreen.cpp4143logplain
-rw-r--r--guiDeathScreen.h1504logplain
-rw-r--r--guiFormSpecMenu.cpp41028logplain
-rw-r--r--guiFormSpecMenu.h5083logplain
-rw-r--r--guiKeyChangeMenu.cpp11860logplain
-rw-r--r--guiKeyChangeMenu.h1946logplain
-rw-r--r--guiMainMenu.cpp44480logplain
-rw-r--r--guiMainMenu.h3507logplain
-rw-r--r--guiMessageMenu.cpp3946logplain
-rw-r--r--guiMessageMenu.h1444logplain
-rw-r--r--guiPasswordChange.cpp6414logplain
-rw-r--r--guiPasswordChange.h1459logplain
-rw-r--r--guiPauseMenu.cpp6536logplain
-rw-r--r--guiPauseMenu.h1572logplain
-rw-r--r--guiTextInputMenu.cpp4652logplain
-rw-r--r--guiTextInputMenu.h1461logplain
-rw-r--r--guiVolumeChange.cpp4653logplain
-rw-r--r--guiVolumeChange.h1497logplain
-rw-r--r--hex.h1357logplain
-rw-r--r--hud.cpp10521logplain
-rw-r--r--hud.h3032logplain
-rw-r--r--intlGUIEditBox.cpp34197logplain
-rw-r--r--intlGUIEditBox.h5777logplain
-rw-r--r--inventory.cpp19074logplain
-rw-r--r--inventory.h7702logplain
-rw-r--r--inventorymanager.cpp21154logplain
-rw-r--r--inventorymanager.h5068logplain
-rw-r--r--irr_aabb3d.h939logplain
-rw-r--r--irr_v2d.h1070logplain
-rw-r--r--irr_v3d.h996logplain
-rw-r--r--irrlichttypes.h1209logplain
-rw-r--r--irrlichttypes_bloated.h1052logplain
-rw-r--r--irrlichttypes_extrabloated.h1292logplain
-rw-r--r--itemdef.cpp18476logplain
-rw-r--r--itemdef.h4652logplain
-rw-r--r--itemgroup.h1183logplain
d---------json151logplain
d---------jthread264logplain
-rw-r--r--keycode.cpp11714logplain
-rw-r--r--keycode.h1724logplain
-rw-r--r--light.cpp3873logplain
-rw-r--r--light.h3228logplain
-rw-r--r--localplayer.cpp15101logplain
-rw-r--r--localplayer.h2016logplain
-rw-r--r--log.cpp3689logplain
-rw-r--r--log.h2490logplain
-rw-r--r--logoutputbuffer.h1351logplain
d---------lua109logplain
-rw-r--r--luaentity_common.h1050logplain
-rw-r--r--main.cpp50522logplain
-rw-r--r--main.h1441logplain
-rw-r--r--mainmenumanager.h2828logplain
-rw-r--r--map.cpp104389logplain
-rw-r--r--map.h13717logplain
-rw-r--r--mapblock.cpp25612logplain
-rw-r--r--mapblock.h13559logplain
-rw-r--r--mapblock_mesh.cpp36133logplain
-rw-r--r--mapblock_mesh.h4812logplain
-rw-r--r--mapchunk.h1831logplain
-rw-r--r--mapgen.cpp13523logplain
-rw-r--r--mapgen.h4632logplain
-rw-r--r--mapgen_indev.cpp17317logplain
-rw-r--r--mapgen_indev.h5434logplain
-rw-r--r--mapgen_singlenode.cpp3103logplain
-rw-r--r--mapgen_singlenode.h1569logplain
-rw-r--r--mapgen_v6.cpp27512logplain
-rw-r--r--mapgen_v6.h4841logplain
-rw-r--r--mapgen_v7.cpp16413logplain
-rw-r--r--mapgen_v7.h3312logplain
-rw-r--r--mapnode.cpp12697logplain
-rw-r--r--mapnode.h5656logplain
-rw-r--r--mapsector.cpp4913logplain
-rw-r--r--mapsector.h2784logplain
-rw-r--r--mesh.cpp14266logplain
-rw-r--r--mesh.h2628logplain
-rw-r--r--modalMenu.h3410logplain
-rw-r--r--modifiedstate.h1171logplain
-rw-r--r--mods.cpp8171logplain
-rw-r--r--mods.h3693logplain
-rw-r--r--nameidmapping.cpp1529logplain
-rw-r--r--nameidmapping.h2137logplain
-rw-r--r--nodedef.cpp26865logplain
-rw-r--r--nodedef.h9000logplain
-rw-r--r--nodemetadata.cpp4058logplain
-rw-r--r--nodemetadata.h2804logplain
-rw-r--r--nodetimer.cpp3656logplain
-rw-r--r--nodetimer.h2230logplain
-rw-r--r--noise.cpp14915logplain
-rw-r--r--noise.h4463logplain
-rw-r--r--object_properties.cpp4059logplain
-rw-r--r--object_properties.h1468logplain
-rw-r--r--particles.cpp10345logplain
-rw-r--r--particles.h3733logplain
-rw-r--r--pathfinder.cpp28672logplain
-rw-r--r--pathfinder.h9852logplain
-rw-r--r--player.cpp6317logplain
-rw-r--r--player.h5244logplain
-rw-r--r--porting.cpp10508logplain
-rw-r--r--porting.h5298logplain
-rw-r--r--profiler.h4954logplain
-rw-r--r--quicktune.cpp2621logplain
-rw-r--r--quicktune.h2837logplain
-rw-r--r--quicktune_shortcutter.h2148logplain
-rw-r--r--rollback.cpp9817logplain
-rw-r--r--rollback.h1855logplain
-rw-r--r--rollback_interface.cpp11741logplain
-rw-r--r--rollback_interface.h3659logplain
-rw-r--r--script.cpp2991logplain
-rw-r--r--script.h1352logplain
-rw-r--r--scriptapi.cpp32394logplain
-rw-r--r--scriptapi.h2500logplain
-rw-r--r--scriptapi_common.cpp8178logplain
-rw-r--r--scriptapi_common.h3641logplain
-rw-r--r--scriptapi_content.cpp9450logplain
-rw-r--r--scriptapi_content.h1299logplain
-rw-r--r--scriptapi_craft.cpp12024logplain
-rw-r--r--scriptapi_craft.h1903logplain
-rw-r--r--scriptapi_entity.cpp8330logplain
-rw-r--r--scriptapi_entity.h2253logplain
-rw-r--r--scriptapi_env.cpp26134logplain
-rw-r--r--scriptapi_env.h4859logplain
-rw-r--r--scriptapi_inventory.cpp18925logplain
-rw-r--r--scriptapi_inventory.h5593logplain
-rw-r--r--scriptapi_item.cpp19047logplain
-rw-r--r--scriptapi_item.h5428logplain
-rw-r--r--scriptapi_node.cpp6309logplain
-rw-r--r--scriptapi_node.h2091logplain
-rw-r--r--scriptapi_nodemeta.cpp15535logplain
-rw-r--r--scriptapi_nodemeta.h3771logplain
-rw-r--r--scriptapi_nodetimer.cpp4297logplain
-rw-r--r--scriptapi_nodetimer.h1767logplain
-rw-r--r--scriptapi_noise.cpp9896logplain
-rw-r--r--scriptapi_noise.h2946logplain
-rw-r--r--scriptapi_object.cpp29806logplain
-rw-r--r--scriptapi_object.h6633logplain
-rw-r--r--scriptapi_particles.cpp4176logplain
-rw-r--r--scriptapi_particles.h1021logplain
-rw-r--r--scriptapi_types.cpp8655logplain
-rw-r--r--scriptapi_types.h4011logplain
-rw-r--r--serialization.cpp6079logplain
-rw-r--r--serialization.h3051logplain
-rw-r--r--server.cpp136121logplain
-rw-r--r--server.h22432logplain
-rw-r--r--serverlist.cpp8060logplain
-rw-r--r--serverlist.h1553logplain
-rw-r--r--serverobject.cpp2476logplain
-rw-r--r--serverobject.h7118logplain
-rw-r--r--settings.h20308logplain
-rw-r--r--sha1.cpp5679logplain
-rw-r--r--sha1.h1623logplain
-rw-r--r--shader.cpp22448logplain
-rw-r--r--shader.h2985logplain
-rw-r--r--sky.cpp17775logplain
-rw-r--r--sky.h2486logplain
-rw-r--r--socket.cpp8655logplain
-rw-r--r--socket.h2510logplain
-rw-r--r--sound.cpp882logplain
-rw-r--r--sound.h3234logplain
-rw-r--r--sound_openal.cpp14385logplain
-rw-r--r--sound_openal.h943logplain
d---------sqlite116logplain
-rw-r--r--staticobject.cpp2224logplain
-rw-r--r--staticobject.h2243logplain
-rw-r--r--strfnd.h5836logplain
-rw-r--r--subgame.cpp8009logplain
-rw-r--r--subgame.h3031logplain
-rw-r--r--test.cpp48589logplain
-rw-r--r--test.h853logplain
-rw-r--r--threads.h1304logplain
-rw-r--r--tile.cpp52765logplain
-rw-r--r--tile.h7739logplain
-rw-r--r--tool.cpp6203logplain
-rw-r--r--tool.h3166logplain
-rw-r--r--treegen.cpp19238logplain
-rw-r--r--treegen.h2703logplain
d---------util643logplain
-rw-r--r--voxel.cpp15892logplain
-rw-r--r--voxel.h13166logplain
-rw-r--r--voxelalgorithms.cpp4681logplain
-rw-r--r--voxelalgorithms.h1678logplain
3592'>3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "server.h"
#include <iostream>
#include <queue>
#include <algorithm>
#include "network/networkprotocol.h"
#include "network/serveropcodes.h"
#include "ban.h"
#include "environment.h"
#include "map.h"
#include "threading/mutex_auto_lock.h"
#include "constants.h"
#include "voxel.h"
#include "config.h"
#include "version.h"
#include "filesys.h"
#include "mapblock.h"
#include "serverobject.h"
#include "genericobject.h"
#include "settings.h"
#include "profiler.h"
#include "log.h"
#include "serverscripting.h"
#include "nodedef.h"
#include "itemdef.h"
#include "craftdef.h"
#include "emerge.h"
#include "mapgen.h"
#include "mg_biome.h"
#include "content_mapnode.h"
#include "content_nodemeta.h"
#include "content_abm.h"
#include "content_sao.h"
#include "mods.h"
#include "event_manager.h"
#include "serverlist.h"
#include "util/string.h"
#include "rollback.h"
#include "util/serialize.h"
#include "util/thread.h"
#include "defaultsettings.h"
#include "util/base64.h"
#include "util/sha1.h"
#include "util/hex.h"

class ClientNotFoundException : public BaseException
{
public:
	ClientNotFoundException(const char *s):
		BaseException(s)
	{}
};

class ServerThread : public Thread
{
public:

	ServerThread(Server *server):
		Thread("Server"),
		m_server(server)
	{}

	void *run();

private:
	Server *m_server;
};

void *ServerThread::run()
{
	DSTACK(FUNCTION_NAME);
	BEGIN_DEBUG_EXCEPTION_HANDLER

	m_server->AsyncRunStep(true);

	while (!stopRequested()) {
		try {
			//TimeTaker timer("AsyncRunStep() + Receive()");

			m_server->AsyncRunStep();

			m_server->Receive();

		} catch (con::NoIncomingDataException &e) {
		} catch (con::PeerNotFoundException &e) {
			infostream<<"Server: PeerNotFoundException"<<std::endl;
		} catch (ClientNotFoundException &e) {
		} catch (con::ConnectionBindFailed &e) {
			m_server->setAsyncFatalError(e.what());
		} catch (LuaError &e) {
			m_server->setAsyncFatalError(
					"ServerThread::run Lua: " + std::string(e.what()));
		}
	}

	END_DEBUG_EXCEPTION_HANDLER

	return NULL;
}

v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
{
	if(pos_exists) *pos_exists = false;
	switch(type){
	case SSP_LOCAL:
		return v3f(0,0,0);
	case SSP_POSITIONAL:
		if(pos_exists) *pos_exists = true;
		return pos;
	case SSP_OBJECT: {
		if(object == 0)
			return v3f(0,0,0);
		ServerActiveObject *sao = env->getActiveObject(object);
		if(!sao)
			return v3f(0,0,0);
		if(pos_exists) *pos_exists = true;
		return sao->getBasePosition(); }
	}
	return v3f(0,0,0);
}



/*
	Server
*/

Server::Server(
		const std::string &path_world,
		const SubgameSpec &gamespec,
		bool simple_singleplayer_mode,
		bool ipv6,
		bool dedicated,
		ChatInterface *iface
	):
	m_path_world(path_world),
	m_gamespec(gamespec),
	m_simple_singleplayer_mode(simple_singleplayer_mode),
	m_dedicated(dedicated),
	m_async_fatal_error(""),
	m_env(NULL),
	m_con(PROTOCOL_ID,
			512,
			CONNECTION_TIMEOUT,
			ipv6,
			this),
	m_banmanager(NULL),
	m_rollback(NULL),
	m_enable_rollback_recording(false),
	m_emerge(NULL),
	m_script(NULL),
	m_itemdef(createItemDefManager()),
	m_nodedef(createNodeDefManager()),
	m_craftdef(createCraftDefManager()),
	m_event(new EventManager()),
	m_thread(NULL),
	m_time_of_day_send_timer(0),
	m_uptime(0),
	m_clients(&m_con),
	m_shutdown_requested(false),
	m_shutdown_ask_reconnect(false),
	m_shutdown_timer(0.0f),
	m_admin_chat(iface),
	m_ignore_map_edit_events(false),
	m_ignore_map_edit_events_peer_id(0),
	m_next_sound_id(0),
	m_mod_storage_save_timer(10.0f)
{
	m_liquid_transform_timer = 0.0;
	m_liquid_transform_every = 1.0;
	m_masterserver_timer = 0.0;
	m_emergethread_trigger_timer = 0.0;
	m_savemap_timer = 0.0;

	m_step_dtime = 0.0;
	m_lag = g_settings->getFloat("dedicated_server_step");

	if(path_world == "")
		throw ServerError("Supplied empty world path");

	if(!gamespec.isValid())
		throw ServerError("Supplied invalid gamespec");

	infostream<<"Server created for gameid \""<<m_gamespec.id<<"\"";
	if(m_simple_singleplayer_mode)
		infostream<<" in simple singleplayer mode"<<std::endl;
	else
		infostream<<std::endl;
	infostream<<"- world:  "<<m_path_world<<std::endl;
	infostream<<"- game:   "<<m_gamespec.path<<std::endl;

	// Create world if it doesn't exist
	if(!loadGameConfAndInitWorld(m_path_world, m_gamespec))
		throw ServerError("Failed to initialize world");

	// Create server thread
	m_thread = new ServerThread(this);

	// Create emerge manager
	m_emerge = new EmergeManager(this);

	// Create ban manager
	std::string ban_path = m_path_world + DIR_DELIM "ipban.txt";
	m_banmanager = new BanManager(ban_path);

	ServerModConfiguration modconf(m_path_world);
	m_mods = modconf.getMods();
	std::vector<ModSpec> unsatisfied_mods = modconf.getUnsatisfiedMods();
	// complain about mods with unsatisfied dependencies
	if (!modconf.isConsistent()) {
		modconf.printUnsatisfiedModsError();
	}

	Settings worldmt_settings;
	std::string worldmt = m_path_world + DIR_DELIM + "world.mt";
	worldmt_settings.readConfigFile(worldmt.c_str());
	std::vector<std::string> names = worldmt_settings.getNames();
	std::set<std::string> load_mod_names;
	for(std::vector<std::string>::iterator it = names.begin();
		it != names.end(); ++it) {
		std::string name = *it;
		if(name.compare(0,9,"load_mod_")==0 && worldmt_settings.getBool(name))
			load_mod_names.insert(name.substr(9));
	}
	// complain about mods declared to be loaded, but not found
	for(std::vector<ModSpec>::iterator it = m_mods.begin();
			it != m_mods.end(); ++it)
		load_mod_names.erase((*it).name);
	for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
			it != unsatisfied_mods.end(); ++it)
		load_mod_names.erase((*it).name);
	if(!load_mod_names.empty()) {
		errorstream << "The following mods could not be found:";
		for(std::set<std::string>::iterator it = load_mod_names.begin();
			it != load_mod_names.end(); ++it)
			errorstream << " \"" << (*it) << "\"";
		errorstream << std::endl;
	}

	//lock environment
	MutexAutoLock envlock(m_env_mutex);

	// Create the Map (loads map_meta.txt, overriding configured mapgen params)
	ServerMap *servermap = new ServerMap(path_world, this, m_emerge);

	// Initialize scripting
	infostream<<"Server: Initializing Lua"<<std::endl;

	m_script = new ServerScripting(this);

	m_script->loadMod(getBuiltinLuaPath() + DIR_DELIM "init.lua", BUILTIN_MOD_NAME);

	// Print mods
	infostream << "Server: Loading mods: ";
	for (std::vector<ModSpec>::const_iterator i = m_mods.begin();
			i != m_mods.end(); ++i) {
		infostream << (*i).name << " ";
	}
	infostream << std::endl;
	// Load and run "mod" scripts
	for (std::vector<ModSpec>::const_iterator it = m_mods.begin();
			it != m_mods.end(); ++it) {
		const ModSpec &mod = *it;
		if (!string_allowed(mod.name, MODNAME_ALLOWED_CHARS)) {
			throw ModError("Error loading mod \"" + mod.name +
				"\": Mod name does not follow naming conventions: "
				"Only chararacters [a-z0-9_] are allowed.");
		}
		std::string script_path = mod.path + DIR_DELIM + "init.lua";
		infostream << "  [" << padStringRight(mod.name, 12) << "] [\""
				<< script_path << "\"]" << std::endl;
		m_script->loadMod(script_path, mod.name);
	}

	// Read Textures and calculate sha1 sums
	fillMediaCache();

	// Apply item aliases in the node definition manager
	m_nodedef->updateAliases(m_itemdef);

	// Apply texture overrides from texturepack/override.txt
	std::string texture_path = g_settings->get("texture_path");
	if (texture_path != "" && fs::IsDir(texture_path))
		m_nodedef->applyTextureOverrides(texture_path + DIR_DELIM + "override.txt");

	m_nodedef->setNodeRegistrationStatus(true);

	// Perform pending node name resolutions
	m_nodedef->runNodeResolveCallbacks();

	// unmap node names for connected nodeboxes
	m_nodedef->mapNodeboxConnections();

	// init the recipe hashes to speed up crafting
	m_craftdef->initHashes(this);

	// Initialize Environment
	m_env = new ServerEnvironment(servermap, m_script, this, m_path_world);

	m_clients.setEnv(m_env);

	if (!servermap->settings_mgr.makeMapgenParams())
		FATAL_ERROR("Couldn't create any mapgen type");

	// Initialize mapgens
	m_emerge->initMapgens(servermap->getMapgenParams());

	m_enable_rollback_recording = g_settings->getBool("enable_rollback_recording");
	if (m_enable_rollback_recording) {
		// Create rollback manager
		m_rollback = new RollbackManager(m_path_world, this);
	}

	// Give environment reference to scripting api
	m_script->initializeEnvironment(m_env);

	// Register us to receive map edit events
	servermap->addEventReceiver(this);

	// If file exists, load environment metadata
	if (fs::PathExists(m_path_world + DIR_DELIM "env_meta.txt")) {
		infostream << "Server: Loading environment metadata" << std::endl;
		m_env->loadMeta();
	} else {
		m_env->loadDefaultMeta();
	}

	// Add some test ActiveBlockModifiers to environment
	add_legacy_abms(m_env, m_nodedef);

	m_liquid_transform_every = g_settings->getFloat("liquid_update");
	m_max_chatmessage_length = g_settings->getU16("chat_message_max_size");
}

Server::~Server()
{
	infostream<<"Server destructing"<<std::endl;

	// Send shutdown message
	SendChatMessage(PEER_ID_INEXISTENT, L"*** Server shutting down");

	{
		MutexAutoLock envlock(m_env_mutex);

		// Execute script shutdown hooks
		m_script->on_shutdown();

		infostream << "Server: Saving players" << std::endl;
		m_env->saveLoadedPlayers();

		infostream << "Server: Kicking players" << std::endl;
		std::string kick_msg;
		bool reconnect = false;
		if (getShutdownRequested()) {
			reconnect = m_shutdown_ask_reconnect;
			kick_msg = m_shutdown_msg;
		}
		if (kick_msg == "") {
			kick_msg = g_settings->get("kick_msg_shutdown");
		}
		m_env->kickAllPlayers(SERVER_ACCESSDENIED_SHUTDOWN,
			kick_msg, reconnect);

		infostream << "Server: Saving environment metadata" << std::endl;
		m_env->saveMeta();
	}

	// Stop threads
	stop();
	delete m_thread;

	// stop all emerge threads before deleting players that may have
	// requested blocks to be emerged
	m_emerge->stopThreads();

	// Delete things in the reverse order of creation
	delete m_emerge;
	delete m_env;
	delete m_rollback;
	delete m_banmanager;
	delete m_event;
	delete m_itemdef;
	delete m_nodedef;
	delete m_craftdef;

	// Deinitialize scripting
	infostream<<"Server: Deinitializing scripting"<<std::endl;
	delete m_script;

	// Delete detached inventories
	for (std::map<std::string, Inventory*>::iterator
			i = m_detached_inventories.begin();
			i != m_detached_inventories.end(); ++i) {
		delete i->second;
	}
}

void Server::start(Address bind_addr)
{
	DSTACK(FUNCTION_NAME);

	m_bind_addr = bind_addr;

	infostream<<"Starting server on "
			<< bind_addr.serializeString() <<"..."<<std::endl;

	// Stop thread if already running
	m_thread->stop();

	// Initialize connection
	m_con.SetTimeoutMs(30);
	m_con.Serve(bind_addr);

	// Start thread
	m_thread->start();

	// ASCII art for the win!
	actionstream
	<<"        .__               __                   __   "<<std::endl
	<<"  _____ |__| ____   _____/  |_  ____   _______/  |_ "<<std::endl
	<<" /     \\|  |/    \\_/ __ \\   __\\/ __ \\ /  ___/\\   __\\"<<std::endl
	<<"|  Y Y  \\  |   |  \\  ___/|  | \\  ___/ \\___ \\  |  |  "<<std::endl
	<<"|__|_|  /__|___|  /\\___  >__|  \\___  >____  > |__|  "<<std::endl
	<<"      \\/        \\/     \\/          \\/     \\/        "<<std::endl;
	actionstream<<"World at ["<<m_path_world<<"]"<<std::endl;
	actionstream<<"Server for gameid=\""<<m_gamespec.id