diff --git a/src/client.cpp b/src/client.cpp
index 7093a5190a2c40d176bf8279bb1437c2ba9cdba5..4d9233d66d6590c760b596ccc8e79527b9da4445 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -1507,7 +1507,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
 	}
 	else if(command == TOCLIENT_TOOLDEF)
 	{
-		infostream<<"Client: Received tool definitions"<<std::endl;
+		infostream<<"Client: Received tool definitions: packet size: "
+				<<datasize<<std::endl;
 
 		std::string datastring((char*)&data[2], datasize-2);
 		std::istringstream is(datastring, std::ios_base::binary);
@@ -1589,6 +1590,31 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
 		event.type = CE_TEXTURES_UPDATED;
 		m_client_event_queue.push_back(event);
 	}
+	else if(command == TOCLIENT_NODEDEF)
+	{
+		infostream<<"Client: Received node definitions: packet size: "
+				<<datasize<<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_nodedef->deSerialize(tmp_is, this);
+		
+		// Update texture atlas
+		if(g_settings->getBool("enable_texture_atlas"))
+			m_tsrc->buildMainAtlas(this);
+		
+		// Update node textures
+		m_nodedef->updateTextures(m_tsrc);
+
+		// 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 0d553f7697b1ccd7f077b465cf57ecb39a64bc44..cd54fe239749a9836641f9a975d2148ad3923b21 100644
--- a/src/clientserver.h
+++ b/src/clientserver.h
@@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 	PROTOCOL_VERSION 4:
 		Add TOCLIENT_TOOLDEF
 		Add TOCLIENT_TEXTURES
+		Add TOCLIENT_NODEDEF
 */
 
 #define PROTOCOL_VERSION 4
@@ -119,6 +120,8 @@ enum ToClientCommand
 		u16 time (0-23999)
 	*/
 
+	// (oops, there is some gap here)
+
 	TOCLIENT_CHAT_MESSAGE = 0x30,
 	/*
 		u16 command
@@ -211,6 +214,13 @@ enum ToClientCommand
 		}
 	*/
 	
+	TOCLIENT_NODEDEF = 0x3a,
+	/*
+		u16 command
+		u32 length of the next item
+		serialized NodeDefManager
+	*/
+	
 	//TOCLIENT_CONTENT_SENDING_MODE = 0x38,
 	/*
 		u16 command
@@ -304,6 +314,8 @@ enum ToServerCommand
 	
 	TOSERVER_RELEASE = 0x29, // Obsolete
 
+	// (oops, there is some gap here)
+
 	TOSERVER_SIGNTEXT = 0x30, // Old signs
 	/*
 		u16 command
diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index 996b20781944a70fd7ba4fc34dc1a6bd3c0561d1..c86a3aefcb8528071f6158a47a8a6aa4b942f86b 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -451,6 +451,7 @@ class CNodeDefManager: public IWritableNodeDefManager
 	}
 	void serialize(std::ostream &os)
 	{
+		u16 count = 0;
 		std::ostringstream tmp_os(std::ios::binary);
 		for(u16 i=0; i<=MAX_CONTENT; i++)
 		{
@@ -459,14 +460,17 @@ class CNodeDefManager: public IWritableNodeDefManager
 				continue;
 			writeU16(tmp_os, i);
 			f->serialize(tmp_os);
+			count++;
 		}
+		writeU16(os, count);
 		os<<serializeLongString(tmp_os.str());
 	}
 	void deSerialize(std::istream &is, IGameDef *gamedef)
 	{
 		clear();
+		u16 count = readU16(is);
 		std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
-		while(!tmp_is.eof()){
+		for(u16 n=0; n<count; n++){
 			u16 i = readU16(tmp_is);
 			if(i > MAX_CONTENT){
 				errorstream<<"ContentFeatures::deSerialize(): "
diff --git a/src/nodedef.h b/src/nodedef.h
index 43bd1966d9673a8dcb3699fc7aefe4ff880a8cca..b78b09d4c558448f725f7159657552f7ed378d09 100644
--- a/src/nodedef.h
+++ b/src/nodedef.h
@@ -278,6 +278,8 @@ class INodeDefManager
 	// Get node definition
 	virtual const ContentFeatures& get(content_t c) const=0;
 	virtual const ContentFeatures& get(const MapNode &n) const=0;
+	
+	virtual void serialize(std::ostream &os)=0;
 };
 
 class IWritableNodeDefManager : public INodeDefManager
diff --git a/src/server.cpp b/src/server.cpp
index 698174e0a5db0159ddc469230875df8fd0d7bb0a..45630d3012ba9de9bc8c087ab8dd326059a0c0c6 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -2145,6 +2145,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 		// Send tool definitions
 		SendToolDef(m_con, peer_id, m_toolmgr);
 		
+		// Send node definitions
+		SendNodeDef(m_con, peer_id, m_nodemgr);
+		
 		// Send player info to all players
 		SendPlayerInfos();
 
@@ -3637,6 +3640,7 @@ void Server::SendToolDef(con::Connection &con, u16 peer_id,
 		IToolDefManager *tooldef)
 {
 	DSTACK(__FUNCTION_NAME);
+	infostream<<"Server: Sending tool definitions"<<std::endl;
 	std::ostringstream os(std::ios_base::binary);
 
 	/*
@@ -3651,6 +3655,34 @@ void Server::SendToolDef(con::Connection &con, u16 peer_id,
 
 	// Make data buffer
 	std::string s = os.str();
+	infostream<<"Server: Sending tool definitions: data size: "
+			<<s.size()<<std::endl;
+	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
+	// Send as reliable
+	con.Send(peer_id, 0, data, true);
+}
+
+void Server::SendNodeDef(con::Connection &con, u16 peer_id,
+		INodeDefManager *nodedef)
+{
+	DSTACK(__FUNCTION_NAME);
+	infostream<<"Server: Sending node definitions"<<std::endl;
+	std::ostringstream os(std::ios_base::binary);
+
+	/*
+		u16 command
+		u32 length of the next item
+		serialized NodeDefManager
+	*/
+	writeU16(os, TOCLIENT_NODEDEF);
+	std::ostringstream tmp_os(std::ios::binary);
+	nodedef->serialize(tmp_os);
+	os<<serializeLongString(tmp_os.str());
+
+	// Make data buffer
+	std::string s = os.str();
+	infostream<<"Server: Sending node definitions: data size: "
+			<<s.size()<<std::endl;
 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
 	// Send as reliable
 	con.Send(peer_id, 0, data, true);
diff --git a/src/server.h b/src/server.h
index e53bf9c9aecb9d7a07976fd0920bbc89902815c3..a8cdd1a85ef080b231b28364aca1670807f6ec78 100644
--- a/src/server.h
+++ b/src/server.h
@@ -513,6 +513,8 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 			bool set_camera_point_target, v3f camera_point_target);
 	static void SendToolDef(con::Connection &con, u16 peer_id,
 			IToolDefManager *tooldef);
+	static void SendNodeDef(con::Connection &con, u16 peer_id,
+			INodeDefManager *nodedef);
 	
 	/*
 		Non-static send methods.