diff --git a/doc/changelog.txt b/doc/changelog.txt
index 424f98bcfd01a63c500b1f9f4df06746ea40fe8e..a8722f1c9bb2c16a2cde7758ec43fec6a69bb819 100644
--- a/doc/changelog.txt
+++ b/doc/changelog.txt
@@ -1,5 +1,7 @@
 Minetest-c55 changelog
 ----------------------
+This should contain all the major changes.
+For minor stuff, refer to the commit log of the repository.
 
 2011-02-14:
 - Created changelog.txt
diff --git a/minetest.conf.example b/minetest.conf.example
index 264d77e5a36d10db198db42e7daa23a253442344..37c93a5a2479a1a26bd9163479cf873bd73f32d6 100644
--- a/minetest.conf.example
+++ b/minetest.conf.example
@@ -31,6 +31,8 @@
 
 #map-dir = /home/palle/custom_map
 
+#operator_name = 
+
 #plants_amount = 1.0
 #ravines_amount = 1.0
 #coal_amount = 1.0
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7fefc0238d91b298dc11396a58fcaecbff671e4d..6d9601c6548f7916a1654c9224aca80e634e6999 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -5,6 +5,8 @@ if(RUN_IN_PLACE)
 	add_definitions ( -DRUN_IN_PLACE )
 endif(RUN_IN_PLACE)
 
+set(USE_GPROF 0 CACHE BOOL "Use -pg flag for g++")
+
 # Use cmake_config.h
 add_definitions ( -DUSE_CMAKE_CONFIG_H )
 
@@ -161,6 +163,10 @@ else()
 
 	set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${WARNING_FLAGS} -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops")
 	set(CMAKE_CXX_FLAGS_DEBUG "-g -O1 -Wall")
+
+	if(USE_GPROF)
+		set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg")
+	endif()
 	
 	if(BUILD_SERVER)
 		set_target_properties(minetestserver PROPERTIES
diff --git a/src/guiPauseMenu.cpp b/src/guiPauseMenu.cpp
index b6f913d6be6a2a432b8fb899b81d2c8dde24bedf..2d42fdb77dec4189933ed5de7f3fd7f1a2043277 100644
--- a/src/guiPauseMenu.cpp
+++ b/src/guiPauseMenu.cpp
@@ -174,10 +174,18 @@ bool GUIPauseMenu::OnEvent(const SEvent& event)
 {
 	if(event.EventType==EET_KEY_INPUT_EVENT)
 	{
-		if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
+		if(event.KeyInput.PressedDown)
 		{
-			quitMenu();
-			return true;
+			if(event.KeyInput.Key==KEY_ESCAPE)
+			{
+				quitMenu();
+				return true;
+			}
+			else if(event.KeyInput.Key==KEY_RETURN)
+			{
+				quitMenu();
+				return true;
+			}
 		}
 	}
 	if(event.EventType==EET_GUI_EVENT)
diff --git a/src/main.cpp b/src/main.cpp
index bcc8dc446c256d6ef3a9fef8d3f353c0fd546ee7..452030a24454501c55f067c1e5676d540420f081 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -268,7 +268,7 @@ Doing now (most important at the top):
 # maybe done
 * not done
 
-=== Stuff to do before release
+=== Fixmes
 * Make server find the spawning place from the real map data, not from
   the heightmap
   - But the changing borders of chunk have to be avoided, because
@@ -277,15 +277,15 @@ Doing now (most important at the top):
   placement and transfer
 * only_from_disk might not work anymore - check and fix it.
 * Check the fixmes in the list above
-* FIXME: Sneaking doesn't switch sneak node when moving sideways
+* When sending blocks to the client, the server takes way too much
+  CPU time (20-30% for single player), find out what it is doing.
+  - Make a simple profiler
 
 === Making it more portable
 * Some MSVC: std::sto* are defined without a namespace and collide
   with the ones in utility.h
-* On Kray's machine, the new find_library(XXF86VM_LIBRARY, Xxf86vm)
-  line doesn't find the library.
 
-=== Stuff to do after release
+=== Features
 * Make an "environment metafile" to store at least time of day
 * Move digging property stuff from material.{h,cpp} to mapnode.cpp...
   - Or maybe move content_features to material.{h,cpp}?
@@ -567,7 +567,25 @@ struct TextDestChat : public TextDest
 	}
 	void gotText(std::wstring text)
 	{
+		// Discard empty line
+		if(text == L"")
+			return;
+		
+		// Parse command (server command starts with "/#")
+		if(text[0] == L'/' && text[1] != L'#')
+		{
+			std::wstring reply = L"Local: ";
+
+			reply += L"Local commands not yet supported. "
+					"Server prefix is \"/#\".";
+			
+			m_client->addChatMessage(reply);
+			return;
+		}
+
+		// Send to others
 		m_client->sendChatMessage(text);
+		// Show locally
 		m_client->addChatMessage(text);
 	}
 
@@ -1546,6 +1564,9 @@ int main(int argc, char *argv[])
 
 	DSTACK(__FUNCTION_NAME);
 
+	porting::signal_handler_init();
+	bool &kill = *porting::signal_handler_killstatus();
+	
 	porting::initializePaths();
 	// Create user data directory
 	fs::CreateDir(porting::path_userdata);
@@ -1681,7 +1702,7 @@ int main(int argc, char *argv[])
 		server.start(port);
 		
 		// Run server
-		dedicated_server_loop(server);
+		dedicated_server_loop(server, kill);
 
 		return 0;
 	}
diff --git a/src/mapblock.cpp b/src/mapblock.cpp
index 422d3b531296e2b4ac6aca0e2ba472f9927a6862..1dbbe5c4ef43122b35a54e6abac7071e32c78005 100644
--- a/src/mapblock.cpp
+++ b/src/mapblock.cpp
@@ -1771,11 +1771,11 @@ void MapBlock::serialize(std::ostream &os, u8 version)
 		// First byte
 		u8 flags = 0;
 		if(is_underground)
-			flags |= 1;
+			flags |= 0x01;
 		if(m_day_night_differs)
-			flags |= 2;
+			flags |= 0x02;
 		if(m_lighting_expired)
-			flags |= 3;
+			flags |= 0x04;
 		os.write((char*)&flags, 1);
 
 		u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
@@ -1895,9 +1895,9 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
 
 		u8 flags;
 		is.read((char*)&flags, 1);
-		is_underground = (flags & 1) ? true : false;
-		m_day_night_differs = (flags & 2) ? true : false;
-		m_lighting_expired = (flags & 3) ? true : false;
+		is_underground = (flags & 0x01) ? true : false;
+		m_day_night_differs = (flags & 0x02) ? true : false;
+		m_lighting_expired = (flags & 0x04) ? true : false;
 
 		// Uncompress data
 		std::ostringstream os(std::ios_base::binary);
diff --git a/src/porting.cpp b/src/porting.cpp
index 592636336f14ef215e5636dc5a5b8bf54bb28ea4..f92b291acd5059ca35c6fc257746afb5e7760a0b 100644
--- a/src/porting.cpp
+++ b/src/porting.cpp
@@ -29,6 +29,53 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 namespace porting
 {
 
+/*
+	Signal handler (grabs Ctrl-C on POSIX systems)
+*/
+
+#if !defined(_WIN32) // POSIX
+	#include <signal.h>
+
+bool g_killed = false;
+
+void sigint_handler(int sig)
+{
+	if(g_killed == false)
+	{
+		dstream<<DTIME<<"sigint_handler(): "
+				<<"Ctrl-C pressed, shutting down."<<std::endl;
+		g_killed = true;
+	}
+	else
+	{
+		(void)signal(SIGINT, SIG_DFL);
+	}
+}
+
+void signal_handler_init(void)
+{
+	dstream<<"signal_handler_init()"<<std::endl;
+	(void)signal(SIGINT, sigint_handler);
+}
+
+#else // _WIN32
+
+void signal_handler_init(void)
+{
+	// No-op
+}
+
+#endif
+
+bool * signal_handler_killstatus(void)
+{
+	return &g_killed;
+}
+
+/*
+	Path mangler
+*/
+
 std::string path_data = "../data";
 std::string path_userdata = "../";
 
diff --git a/src/porting.h b/src/porting.h
index 3133fcc804e275b6fb81b21e88b72b092dc18932..3cf8df594b82d66f5710c6c24c50317d29cf914d 100644
--- a/src/porting.h
+++ b/src/porting.h
@@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define PORTING_HEADER
 
 #include <string>
-// Included for u64 and such
+// Included for u32 and such
 #include "common_irrlicht.h"
 #include "debug.h"
 #include "constants.h"
@@ -47,6 +47,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 namespace porting
 {
 
+/*
+	Signal handler (grabs Ctrl-C on POSIX systems)
+*/
+
+void signal_handler_init(void);
+// Returns a pointer to a bool.
+// When the bool is true, program should quit.
+bool * signal_handler_killstatus(void);
+
 /*
 	Path of static data directory.
 */
diff --git a/src/server.cpp b/src/server.cpp
index dc72661fff9c1871f6dc0f38b4be9e475a61b99f..31ebfacbb5d888294f6c09cb65351e38116f5866 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -46,7 +46,12 @@ void * ServerThread::Thread()
 	while(getRun())
 	{
 		try{
-			m_server->AsyncRunStep();
+			//TimeTaker timer("AsyncRunStep() + Receive()");
+
+			{
+				//TimeTaker timer("AsyncRunStep()");
+				m_server->AsyncRunStep();
+			}
 		
 			//dout_server<<"Running m_server->Receive()"<<std::endl;
 			m_server->Receive();
@@ -967,7 +972,8 @@ Server::Server(
 	m_time_counter(0),
 	m_time_of_day_send_timer(0),
 	m_uptime(0),
-	m_mapsavedir(mapsavedir)
+	m_mapsavedir(mapsavedir),
+	m_shutdown_requested(false)
 {
 	//m_flowwater_timer = 0.0;
 	m_liquid_transform_timer = 0.0;
@@ -987,28 +993,62 @@ Server::Server(
 
 Server::~Server()
 {
-	// Save players
+	/*
+		Send shutdown message
+	*/
+	{
+		JMutexAutoLock conlock(m_con_mutex);
+		
+		std::wstring line = L"*** Server shutting down";
+
+		/*
+			Send the message to clients
+		*/
+		for(core::map<u16, RemoteClient*>::Iterator
+			i = m_clients.getIterator();
+			i.atEnd() == false; i++)
+		{
+			// Get client and check that it is valid
+			RemoteClient *client = i.getNode()->getValue();
+			assert(client->peer_id == i.getNode()->getKey());
+			if(client->serialization_version == SER_FMT_VER_INVALID)
+				continue;
+
+			SendChatMessage(client->peer_id, line);
+		}
+	}
+
+	/*
+		Save players
+	*/
 	m_env.serializePlayers(m_mapsavedir);
 	
-	// Stop threads
+	/*
+		Stop threads
+	*/
 	stop();
-
-	JMutexAutoLock clientslock(m_con_mutex);
-
-	for(core::map<u16, RemoteClient*>::Iterator
-		i = m_clients.getIterator();
-		i.atEnd() == false; i++)
+	
+	/*
+		Delete clients
+	*/
 	{
-		/*// Delete player
-		// NOTE: These are removed by env destructor
+		JMutexAutoLock clientslock(m_con_mutex);
+
+		for(core::map<u16, RemoteClient*>::Iterator
+			i = m_clients.getIterator();
+			i.atEnd() == false; i++)
 		{
-			u16 peer_id = i.getNode()->getKey();
-			JMutexAutoLock envlock(m_env_mutex);
-			m_env.removePlayer(peer_id);
-		}*/
-		
-		// Delete client
-		delete i.getNode()->getValue();
+			/*// Delete player
+			// NOTE: These are removed by env destructor
+			{
+				u16 peer_id = i.getNode()->getKey();
+				JMutexAutoLock envlock(m_env_mutex);
+				m_env.removePlayer(peer_id);
+			}*/
+			
+			// Delete client
+			delete i.getNode()->getValue();
+		}
 	}
 }
 
@@ -1586,39 +1626,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 					m_time_of_day.get());
 			m_con.Send(peer->id, 0, data, true);
 		}
-
+		
 		// Send information about server to player in chat
-		{
-			std::wostringstream os(std::ios_base::binary);
-			os<<L"# Server: ";
-			// Uptime
-			os<<L"uptime="<<m_uptime.get();
-			// Information about clients
-			os<<L", clients={";
-			for(core::map<u16, RemoteClient*>::Iterator
-				i = m_clients.getIterator();
-				i.atEnd() == false; i++)
-			{
-				// Get client and check that it is valid
-				RemoteClient *client = i.getNode()->getValue();
-				assert(client->peer_id == i.getNode()->getKey());
-				if(client->serialization_version == SER_FMT_VER_INVALID)
-					continue;
-				// Get player
-				Player *player = m_env.getPlayer(client->peer_id);
-				// Get name of player
-				std::wstring name = L"unknown";
-				if(player != NULL)
-					name = narrow_to_wide(player->getName());
-				// Add name to information string
-				os<<name<<L",";
-			}
-			os<<L"}";
-			if(((ServerMap*)(&m_env.getMap()))->isSavingEnabled() == false)
-				os<<" WARNING: Map saving is disabled."<<std::endl;
-			// Send message
-			SendChatMessage(peer_id, os.str());
-		}
+		SendChatMessage(peer_id, getStatusString());
 		
 		// Send information about joining in chat
 		{
@@ -2461,29 +2471,115 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 
 		// Get player name of this client
 		std::wstring name = narrow_to_wide(player->getName());
-
-		std::wstring line = std::wstring(L"<")+name+L"> "+message;
 		
-		dstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
-
-		/*
-			Send the message to all other clients
-		*/
-		for(core::map<u16, RemoteClient*>::Iterator
-			i = m_clients.getIterator();
-			i.atEnd() == false; i++)
+		// Line to send to players
+		std::wstring line;
+		// Whether to send to the player that sent the line
+		bool send_to_sender = false;
+		// Whether to send to other players
+		bool send_to_others = false;
+		
+		// Parse commands
+		std::wstring commandprefix = L"/#";
+		if(message.substr(0, commandprefix.size()) == commandprefix)
+		{
+			line += L"Server: ";
+
+			message = message.substr(commandprefix.size());
+			// Get player name as narrow string
+			std::string name_s = player->getName();
+			// Convert message to narrow string
+			std::string message_s = wide_to_narrow(message);
+			// Operator is the single name defined in config.
+			std::string operator_name = g_settings.get("name");
+			bool is_operator = (operator_name != "" &&
+					wide_to_narrow(name) == operator_name);
+			bool valid_command = false;
+			if(message_s == "help")
+			{
+				line += L"-!- Available commands: ";
+				line += L"status ";
+				if(is_operator)
+				{
+					line += L"shutdown setting ";
+				}
+				else
+				{
+				}
+				send_to_sender = true;
+				valid_command = true;
+			}
+			else if(message_s == "status")
+			{
+				line = getStatusString();
+				send_to_sender = true;
+				valid_command = true;
+			}
+			else if(is_operator)
+			{
+				if(message_s == "shutdown")
+				{
+					dstream<<DTIME<<" Server: Operator requested shutdown."
+							<<std::endl;
+					m_shutdown_requested.set(true);
+					
+					line += L"*** Server shutting down (operator request)";
+					send_to_sender = true;
+					valid_command = true;
+				}
+				else if(message_s.substr(0,8) == "setting ")
+				{
+					std::string confline = message_s.substr(8);
+					g_settings.parseConfigLine(confline);
+					line += L"-!- Setting changed.";
+					send_to_sender = true;
+					valid_command = true;
+				}
+			}
+			
+			if(valid_command == false)
+			{
+				line += L"-!- Invalid command: " + message;
+				send_to_sender = true;
+			}
+		}
+		else
 		{
-			// Get client and check that it is valid
-			RemoteClient *client = i.getNode()->getValue();
-			assert(client->peer_id == i.getNode()->getKey());
-			if(client->serialization_version == SER_FMT_VER_INVALID)
-				continue;
+			line += L"<";
+			/*if(is_operator)
+				line += L"@";*/
+			line += name;
+			line += L"> ";
+			line += message;
+			send_to_others = true;
+		}
+		
+		if(line != L"")
+		{
+			dstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
 
-			// Don't send if it's the same one
-			if(peer_id == client->peer_id)
-				continue;
+			/*
+				Send the message to clients
+			*/
+			for(core::map<u16, RemoteClient*>::Iterator
+				i = m_clients.getIterator();
+				i.atEnd() == false; i++)
+			{
+				// Get client and check that it is valid
+				RemoteClient *client = i.getNode()->getValue();
+				assert(client->peer_id == i.getNode()->getKey());
+				if(client->serialization_version == SER_FMT_VER_INVALID)
+					continue;
 
-			SendChatMessage(client->peer_id, line);
+				// Filter recipient
+				bool sender_selected = (peer_id == client->peer_id);
+				if(sender_selected == true && send_to_sender == false)
+					continue;
+				if(sender_selected == false && send_to_others == false)
+					continue;
+
+				SendChatMessage(client->peer_id, line);
+			}
 		}
 	}
 	else
@@ -2580,6 +2676,7 @@ core::list<PlayerInfo> Server::getPlayerInfo()
 	return list;
 }
 
+
 void Server::peerAdded(con::Peer *peer)
 {
 	DSTACK(__FUNCTION_NAME);
@@ -3020,6 +3117,8 @@ void Server::SendBlocks(float dtime)
 
 	JMutexAutoLock envlock(m_env_mutex);
 
+	//TimeTaker timer("Server::SendBlocks");
+
 	core::array<PrioritySortedBlockTransfer> queue;
 
 	s32 total_sending = 0;
@@ -3087,6 +3186,39 @@ RemoteClient* Server::getClient(u16 peer_id)
 	return n->getValue();
 }
 
+std::wstring Server::getStatusString()
+{
+	std::wostringstream os(std::ios_base::binary);
+	os<<L"# Server: ";
+	// Uptime
+	os<<L"uptime="<<m_uptime.get();
+	// Information about clients
+	os<<L", clients={";
+	for(core::map<u16, RemoteClient*>::Iterator
+		i = m_clients.getIterator();
+		i.atEnd() == false; i++)
+	{
+		// Get client and check that it is valid
+		RemoteClient *client = i.getNode()->getValue();
+		assert(client->peer_id == i.getNode()->getKey());
+		if(client->serialization_version == SER_FMT_VER_INVALID)
+			continue;
+		// Get player
+		Player *player = m_env.getPlayer(client->peer_id);
+		// Get name of player
+		std::wstring name = L"unknown";
+		if(player != NULL)
+			name = narrow_to_wide(player->getName());
+		// Add name to information string
+		os<<name<<L",";
+	}
+	os<<L"}";
+	if(((ServerMap*)(&m_env.getMap()))->isSavingEnabled() == false)
+		os<<" WARNING: Map saving is disabled."<<std::endl;
+	return os.str();
+}
+
+
 void setCreativeInventory(Player *player)
 {
 	player->resetInventory();
@@ -3455,11 +3587,11 @@ void Server::handlePeerChanges()
 	}
 }
 
-void dedicated_server_loop(Server &server)
+void dedicated_server_loop(Server &server, bool &kill)
 {
 	DSTACK(__FUNCTION_NAME);
 	
-	std::cout<<std::endl;
+	std::cout<<DTIME<<std::endl;
 	std::cout<<"========================"<<std::endl;
 	std::cout<<"Running dedicated server"<<std::endl;
 	std::cout<<"========================"<<std::endl;
@@ -3472,6 +3604,12 @@ void dedicated_server_loop(Server &server)
 		sleep_ms(30);
 		server.step(0.030);
 
+		if(server.getShutdownRequested() || kill)
+		{
+			std::cout<<DTIME<<" dedicated_server_loop(): Quitting."<<std::endl;
+			break;
+		}
+
 		static int counter = 0;
 		counter--;
 		if(counter <= 0)
diff --git a/src/server.h b/src/server.h
index d19a440d726a7ad630dcaf7b95cafb23be1528ea..9582c99dd0ffd96e93523359827e23b001af5b20 100644
--- a/src/server.h
+++ b/src/server.h
@@ -390,15 +390,11 @@ class Server : public con::PeerHandler
 	void Receive();
 	void ProcessData(u8 *data, u32 datasize, u16 peer_id);
 
-	/*void Send(u16 peer_id, u16 channelnum,
-			SharedBuffer<u8> data, bool reliable);*/
-
-	// Environment and Connection must be locked when called
+	// Environment and Connection must be locked when  called
 	void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
 	
-	// Environment and Connection must be locked when called
-	//void SendSectorMeta(u16 peer_id, core::list<v2s16> ps, u8 ver);
-
+	//
+	
 	core::list<PlayerInfo> getPlayerInfo();
 
 	u32 getDayNightRatio()
@@ -412,7 +408,12 @@ class Server : public con::PeerHandler
 		else
 			return 1000;
 	}
-	
+
+	bool getShutdownRequested()
+	{
+		return m_shutdown_requested.get();
+	}
+
 private:
 
 	// Virtual methods from con::PeerHandler.
@@ -432,7 +433,10 @@ class Server : public con::PeerHandler
 	
 	// When called, connection mutex should be locked
 	RemoteClient* getClient(u16 peer_id);
-
+	
+	// Connection must be locked when called
+	std::wstring getStatusString();
+	
 	/*
 		Get a player from memory or creates one.
 		If player is already connected, return NULL
@@ -490,7 +494,7 @@ class Server : public con::PeerHandler
 	float m_time_of_day_send_timer;
 	
 	MutexedVariable<double> m_uptime;
-
+	
 	enum PeerChangeType
 	{
 		PEER_ADDED,
@@ -508,14 +512,18 @@ class Server : public con::PeerHandler
 
 	std::string m_mapsavedir;
 
+	MutexedVariable<bool> m_shutdown_requested;
+
 	friend class EmergeThread;
 	friend class RemoteClient;
 };
 
 /*
-	Runs a simple dedicated server loop
+	Runs a simple dedicated server loop.
+
+	Shuts down when run is set to false.
 */
-void dedicated_server_loop(Server &server);
+void dedicated_server_loop(Server &server, bool &run);
 
 #endif
 
diff --git a/src/servermain.cpp b/src/servermain.cpp
index 1c301d4f59af8dce1cd79d76a38c5e53aecb8798..254b1f28aade159080df0d2f6eaa26d6e037e2c6 100644
--- a/src/servermain.cpp
+++ b/src/servermain.cpp
@@ -98,7 +98,6 @@ std::ostream *derr_server_ptr = &dstream;
 std::ostream *dout_client_ptr = &dstream;
 std::ostream *derr_client_ptr = &dstream;
 
-
 /*
 	gettime.h implementation
 */
@@ -129,6 +128,9 @@ int main(int argc, char *argv[])
 
 	DSTACK(__FUNCTION_NAME);
 
+	porting::signal_handler_init();
+	bool &kill = *porting::signal_handler_killstatus();
+	
 	porting::initializePaths();
 
 	initializeMaterialProperties();
@@ -251,6 +253,11 @@ int main(int argc, char *argv[])
 	srand(time(0));
 	mysrand(time(0));
 
+	// Initialize stuff
+	
+	init_mapnode();
+	init_mineral();
+
 	/*
 		Run unit tests
 	*/
@@ -260,11 +267,6 @@ int main(int argc, char *argv[])
 		run_tests();
 	}
 
-	// Initialize stuff
-	
-	init_mapnode();
-	init_mineral();
-
 	/*
 		Check parameters
 	*/
@@ -308,9 +310,9 @@ int main(int argc, char *argv[])
 	// Create server
 	Server server(map_dir.c_str());
 	server.start(port);
-	
+
 	// Run server
-	dedicated_server_loop(server);
+	dedicated_server_loop(server, kill);
 	
 	} //try
 	catch(con::PeerNotFoundException &e)
diff --git a/src/test.cpp b/src/test.cpp
index e5b22a978570420ce7e454ad7b15137de561a003..1de902787987e72acfdd280e0ffbfe2f8bf835cb 100644
--- a/src/test.cpp
+++ b/src/test.cpp
@@ -192,7 +192,7 @@ struct TestMapNode
 		// Transparency
 		n.d = CONTENT_AIR;
 		assert(n.light_propagates() == true);
-		n.d = 0;
+		n.d = CONTENT_STONE;
 		assert(n.light_propagates() == false);
 	}
 };
diff --git a/src/utility.h b/src/utility.h
index 46277cd4240ec2ffcb33c28de40ecd3828cbe69d..8c81aba9170c8c8f1f3a5b7e72646dc5760dc50d 100644
--- a/src/utility.h
+++ b/src/utility.h
@@ -802,9 +802,15 @@ struct ValueSpec
 class Settings
 {
 public:
+	Settings()
+	{
+		m_mutex.Init();
+	}
 
 	void writeLines(std::ostream &os)
 	{
+		JMutexAutoLock lock(m_mutex);
+		
 		for(core::map<std::string, std::string>::Iterator
 				i = m_settings.getIterator();
 				i.atEnd() == false; i++)
@@ -817,6 +823,8 @@ class Settings
 
 	bool parseConfigLine(const std::string &line)
 	{
+		JMutexAutoLock lock(m_mutex);
+		
 		std::string trimmedline = trim(line);
 		
 		// Ignore comments
@@ -899,6 +907,8 @@ class Settings
 			core::list<std::string> &dst,
 			core::map<std::string, bool> &updated)
 	{
+		JMutexAutoLock lock(m_mutex);
+		
 		if(is.eof())
 			return false;
 		
@@ -981,6 +991,8 @@ class Settings
 			}
 		}
 		
+		JMutexAutoLock lock(m_mutex);
+		
 		// Write stuff back
 		{
 			std::ofstream os(filename);
@@ -1087,21 +1099,29 @@ class Settings
 
 	void set(std::string name, std::string value)
 	{
+		JMutexAutoLock lock(m_mutex);
+		
 		m_settings[name] = value;
 	}
 
 	void setDefault(std::string name, std::string value)
 	{
+		JMutexAutoLock lock(m_mutex);
+		
 		m_defaults[name] = value;
 	}
 
 	bool exists(std::string name)
 	{
+		JMutexAutoLock lock(m_mutex);
+		
 		return (m_settings.find(name) || m_defaults.find(name));
 	}
 
 	std::string get(std::string name)
 	{
+		JMutexAutoLock lock(m_mutex);
+		
 		core::map<std::string, std::string>::Node *n;
 		n = m_settings.find(name);
 		if(n == NULL)
@@ -1139,7 +1159,7 @@ class Settings
 	bool getBoolAsk(std::string name, std::string question, bool def)
 	{
 		// If it is in settings
-		if(m_settings.find(name))
+		if(exists(name))
 			return getBool(name);
 		
 		std::string s;
@@ -1167,7 +1187,7 @@ class Settings
 	u16 getU16Ask(std::string name, std::string question, u16 def)
 	{
 		// If it is in settings
-		if(m_settings.find(name))
+		if(exists(name))
 			return getU16(name);
 		
 		std::string s;
@@ -1238,12 +1258,17 @@ class Settings
 
 	void clear()
 	{
+		JMutexAutoLock lock(m_mutex);
+		
 		m_settings.clear();
 		m_defaults.clear();
 	}
 
 	Settings & operator+=(Settings &other)
 	{
+		JMutexAutoLock lock(m_mutex);
+		JMutexAutoLock lock2(other.m_mutex);
+		
 		if(&other == this)
 			return *this;
 
@@ -1267,6 +1292,9 @@ class Settings
 
 	Settings & operator=(Settings &other)
 	{
+		JMutexAutoLock lock(m_mutex);
+		JMutexAutoLock lock2(other.m_mutex);
+		
 		if(&other == this)
 			return *this;
 
@@ -1279,6 +1307,8 @@ class Settings
 private:
 	core::map<std::string, std::string> m_settings;
 	core::map<std::string, std::string> m_defaults;
+	// All methods that access m_settings/m_defaults directly should lock this.
+	JMutex m_mutex;
 };
 
 /*