diff --git a/src/client.cpp b/src/client.cpp
index d5abcd7debfd59ae5d11d69fd53110d7504322ca..1daeeba36fde0f73130885204d8c5465d3604958 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -452,7 +452,7 @@ void Client::step(float dtime)
 			snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str());
 			
 			// This should be incremented in each version
-			writeU16(&data[51], 3);
+			writeU16(&data[51], PROTOCOL_VERSION);
 
 			// Send as unreliable
 			Send(0, data, false);
@@ -1506,6 +1506,23 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
 		event.deathscreen.camera_point_target_z = camera_point_target.Z;
 		m_client_event_queue.push_back(event);
 	}
+	else if(command == TOCLIENT_TOOLDEF)
+	{
+		infostream<<"Client: Received tool definitions"<<std::endl;
+
+		std::string datastring((char*)&data[2], datasize-2);
+		std::istringstream is(datastring, std::ios_base::binary);
+
+		// Stop threads while updating content definitions
+		m_mesh_update_thread.stop();
+
+		std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
+		m_tooldef->deSerialize(tmp_is);
+		
+		// Resume threads
+		m_mesh_update_thread.setRun(true);
+		m_mesh_update_thread.Start();
+	}
 	else
 	{
 		infostream<<"Client: Ignoring unknown command "
diff --git a/src/clientserver.h b/src/clientserver.h
index 0f6925696c636c418671b14884874174b38095bf..ef8188b2a44476acd8787db2d784b07aa924cb52 100644
--- a/src/clientserver.h
+++ b/src/clientserver.h
@@ -22,7 +22,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "utility.h"
 
-#define PROTOCOL_VERSION 3
+/*
+	changes by PROTOCOL_VERSION:
+
+	PROTOCOL_VERSION 3:
+		Base for writing changes here
+	PROTOCOL_VERSION 4:
+		Add TOCLIENT_TOOLDEF
+*/
+
+#define PROTOCOL_VERSION 4
 
 #define PROTOCOL_ID 0x4f457403
 
@@ -181,6 +190,19 @@ enum ToClientCommand
 		u8 bool set camera point target
 		v3f1000 camera point target (to point the death cause or whatever)
 	*/
+
+	TOCLIENT_TOOLDEF = 0x38,
+	/*
+		u16 command
+		u32 length of the next item
+		serialized ToolDefManager
+	*/
+	
+	//TOCLIENT_CONTENT_SENDING_MODE = 0x38,
+	/*
+		u16 command
+		u8 mode (0 = off, 1 = on)
+	*/
 };
 
 enum ToServerCommand
diff --git a/src/game.cpp b/src/game.cpp
index bf601dd2106a04d3b98b6e415bceb4aa7f230761..ae45e514613c9d199b79c6d39d64fc8e75668fd6 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -660,6 +660,8 @@ void the_game(
 		server = new Server(map_dir, configpath);
 		server->start(port);
 	}
+
+	{ // Client scope
 	
 	/*
 		Create client
@@ -2341,8 +2343,11 @@ void the_game(
 		gui_shuttingdowntext->remove();*/
 	}
 
+	} // Client scope (must be destructed before destructing *def and tsrc
+
 	delete tooldef;
 	delete tsrc;
+	delete nodedef;
 }
 
 
diff --git a/src/server.cpp b/src/server.cpp
index 75fb7cd72f87f33de51f16e1d07e940162e3b7cc..ca00ed29d8cf410d30b64e584a656c71ece6bbad 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -2106,6 +2106,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 			Send some initialization data
 		*/
 		
+		// Send tool definitions
+		SendToolDef(m_con, peer_id, m_toolmgr);
+		
 		// Send player info to all players
 		SendPlayerInfos();
 
@@ -3594,6 +3597,29 @@ void Server::SendDeathscreen(con::Connection &con, u16 peer_id,
 	con.Send(peer_id, 0, data, true);
 }
 
+void Server::SendToolDef(con::Connection &con, u16 peer_id,
+		IToolDefManager *tooldef)
+{
+	DSTACK(__FUNCTION_NAME);
+	std::ostringstream os(std::ios_base::binary);
+
+	/*
+		u16 command
+		u32 length of the next item
+		serialized ToolDefManager
+	*/
+	writeU16(os, TOCLIENT_TOOLDEF);
+	std::ostringstream tmp_os(std::ios::binary);
+	tooldef->serialize(tmp_os);
+	os<<serializeLongString(tmp_os.str());
+
+	// Make data buffer
+	std::string s = os.str();
+	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
+	// Send as reliable
+	con.Send(peer_id, 0, data, true);
+}
+
 /*
 	Non-static send methods
 */
diff --git a/src/server.h b/src/server.h
index e1a5838260815cd9c1d782df870f660f1c5e7e1e..4b17887e8451daff601ed0b22189bdde8f143427 100644
--- a/src/server.h
+++ b/src/server.h
@@ -508,6 +508,8 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 			const std::wstring &reason);
 	static void SendDeathscreen(con::Connection &con, u16 peer_id,
 			bool set_camera_point_target, v3f camera_point_target);
+	static void SendToolDef(con::Connection &con, u16 peer_id,
+			IToolDefManager *tooldef);
 	
 	/*
 		Non-static send methods
diff --git a/src/tooldef.cpp b/src/tooldef.cpp
index 1c85dbd8eccd98436c8b596946d7f46a6ace0337..1284a52abed0c867de9ef393d0f9e46c8510d212 100644
--- a/src/tooldef.cpp
+++ b/src/tooldef.cpp
@@ -85,11 +85,7 @@ class CToolDefManager: public IWritableToolDefManager
 public:
 	virtual ~CToolDefManager()
 	{
-		for(core::map<std::string, ToolDefinition*>::Iterator
-				i = m_tool_definitions.getIterator();
-				i.atEnd() == false; i++){
-			delete i.getNode()->getValue();
-		}
+		clear();
 	}
 	virtual const ToolDefinition* getToolDefinition(const std::string &toolname) const
 	{
@@ -123,16 +119,25 @@ class CToolDefManager: public IWritableToolDefManager
 	virtual bool registerTool(std::string toolname, const ToolDefinition &def)
 	{
 		infostream<<"registerTool: registering tool \""<<toolname<<"\""<<std::endl;
-		core::map<std::string, ToolDefinition*>::Node *n;
+		/*core::map<std::string, ToolDefinition*>::Node *n;
 		n = m_tool_definitions.find(toolname);
 		if(n != NULL){
 			errorstream<<"registerTool: registering tool \""<<toolname
 					<<"\" failed: name is already registered"<<std::endl;
 			return false;
-		}
+		}*/
 		m_tool_definitions[toolname] = new ToolDefinition(def);
 		return true;
 	}
+	virtual void clear()
+	{
+		for(core::map<std::string, ToolDefinition*>::Iterator
+				i = m_tool_definitions.getIterator();
+				i.atEnd() == false; i++){
+			delete i.getNode()->getValue();
+		}
+		m_tool_definitions.clear();
+	}
 	virtual void serialize(std::ostream &os)
 	{
 		writeU8(os, 0); // version
@@ -153,6 +158,9 @@ class CToolDefManager: public IWritableToolDefManager
 	}
 	virtual void deSerialize(std::istream &is)
 	{
+		// Clear everything
+		clear();
+		// Deserialize
 		int version = readU8(is);
 		if(version != 0) throw SerializationError(
 				"unsupported ToolDefManager version");
diff --git a/src/tooldef.h b/src/tooldef.h
index 2c758d902466b97bd8917b8230bc77de1d4d6cbf..41ee1154cabbe398882e273a2e9f29f0d629e16f 100644
--- a/src/tooldef.h
+++ b/src/tooldef.h
@@ -72,6 +72,8 @@ class IToolDefManager
 	virtual std::string getImagename(const std::string &toolname) const =0;
 	virtual ToolDiggingProperties getDiggingProperties(
 			const std::string &toolname) const =0;
+	
+	virtual void serialize(std::ostream &os)=0;
 };
 
 class IWritableToolDefManager : public IToolDefManager
@@ -85,6 +87,7 @@ class IWritableToolDefManager : public IToolDefManager
 			const std::string &toolname) const =0;
 			
 	virtual bool registerTool(std::string toolname, const ToolDefinition &def)=0;
+	virtual void clear()=0;
 
 	virtual void serialize(std::ostream &os)=0;
 	virtual void deSerialize(std::istream &is)=0;