From 6da8cb00e27106221e013aa6d93965b95e630a18 Mon Sep 17 00:00:00 2001
From: Perttu Ahola <celeron55@gmail.com>
Date: Tue, 15 Nov 2011 20:32:56 +0200
Subject: [PATCH] Node definitions transfer

---
 src/client.cpp     | 28 +++++++++++++++++++++++++++-
 src/clientserver.h | 12 ++++++++++++
 src/nodedef.cpp    |  6 +++++-
 src/nodedef.h      |  2 ++
 src/server.cpp     | 32 ++++++++++++++++++++++++++++++++
 src/server.h       |  2 ++
 6 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/src/client.cpp b/src/client.cpp
index 7093a5190..4d9233d66 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 0d553f769..cd54fe239 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 996b20781..c86a3aefc 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 43bd1966d..b78b09d4c 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 698174e0a..45630d301 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 e53bf9c9a..a8cdd1a85 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.
-- 
GitLab