mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-10-31 15:35:21 +01:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/master'
This commit is contained in:
		| @@ -12,7 +12,7 @@ set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string") | ||||
| # Also remember to set PROTOCOL_VERSION in clientserver.h when releasing | ||||
| set(VERSION_MAJOR 0) | ||||
| set(VERSION_MINOR 4) | ||||
| set(VERSION_PATCH 3) | ||||
| set(VERSION_PATCH 4-dev) | ||||
| if(VERSION_EXTRA) | ||||
| 	set(VERSION_PATCH ${VERSION_PATCH}-${VERSION_EXTRA}) | ||||
| endif() | ||||
|   | ||||
| @@ -138,6 +138,7 @@ minetest.register_chatcommand("grant", { | ||||
| 			return | ||||
| 		end | ||||
| 		minetest.set_player_privs(grantname, privs) | ||||
| 		minetest.log(name..' granted ('..minetest.privs_to_string(grantprivs, ', ')..') privileges to '..grantname) | ||||
| 		minetest.chat_send_player(name, "Privileges of "..grantname..": "..minetest.privs_to_string(minetest.get_player_privs(grantname), ' ')) | ||||
| 		if grantname ~= name then | ||||
| 			minetest.chat_send_player(grantname, name.." granted you privileges: "..minetest.privs_to_string(grantprivs, ' ')) | ||||
| @@ -175,6 +176,7 @@ minetest.register_chatcommand("revoke", { | ||||
| 			end | ||||
| 		end | ||||
| 		minetest.set_player_privs(revokename, privs) | ||||
| 		minetest.log(name..' revoked ('..minetest.privs_to_string(revokeprivs, ', ')..') privileges from '..revokename) | ||||
| 		minetest.chat_send_player(name, "Privileges of "..revokename..": "..minetest.privs_to_string(minetest.get_player_privs(revokename), ' ')) | ||||
| 		if revokename ~= name then | ||||
| 			minetest.chat_send_player(revokename, name.." revoked privileges from you: "..minetest.privs_to_string(revokeprivs, ' ')) | ||||
|   | ||||
| @@ -303,6 +303,7 @@ end | ||||
|  | ||||
| minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration() | ||||
| minetest.registered_globalsteps, minetest.register_globalstep = make_registration() | ||||
| minetest.registered_on_shutdown, minetest.register_on_shutdown = make_registration() | ||||
| minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration() | ||||
| minetest.registered_on_placenodes, minetest.register_on_placenode = make_registration() | ||||
| minetest.registered_on_dignodes, minetest.register_on_dignode = make_registration() | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| Minetest Lua Modding API Reference 0.4.3 | ||||
| Minetest Lua Modding API Reference 0.4.4 | ||||
| ========================================== | ||||
| More information at http://c55.me/minetest/ | ||||
|  | ||||
| @@ -792,6 +792,11 @@ minetest.register_craft(recipe) | ||||
| Global callback registration functions: (Call these only at load time) | ||||
| minetest.register_globalstep(func(dtime)) | ||||
| ^ Called every server step, usually interval of 0.05s | ||||
| minetest.register_on_shutdown(func()) | ||||
| ^ Called before server shutdown | ||||
| ^ WARNING: If the server terminates abnormally (i.e. crashes), the registered | ||||
|            callbacks WILL LIKELY NOT BE RUN.  Data should be saved at | ||||
|            semi-frequent intervals as well as on server shutdown. | ||||
| minetest.register_on_placenode(func(pos, newnode, placer, oldnode)) | ||||
| ^ Called when a node has been placed | ||||
| ^ Deprecated: Use on_construct or after_place_node in node definition instead | ||||
|   | ||||
| @@ -139,8 +139,8 @@ | ||||
| #motd = Welcome to this awesome Minetest server! | ||||
| # Maximum number of players connected simultaneously | ||||
| #max_users = 100 | ||||
| # Set to false to allow old clients to connect | ||||
| #strict_protocol_version_checking = true | ||||
| # Set to true to disallow old clients from connecting | ||||
| #strict_protocol_version_checking = false | ||||
| # Set to true to enable creative mode (unlimited inventory) | ||||
| #creative_mode = false | ||||
| # Enable players getting damage and dying | ||||
| @@ -194,7 +194,12 @@ | ||||
| # To reduce lag, block transfers are slowed down when a player is building something. | ||||
| # This determines how long they are slowed down after placing or removing a node. | ||||
| #full_block_send_enable_min_time_from_building = 2.0 | ||||
| # Length of a server tick in dedicated server | ||||
| #dedicated_server_step = 0.05 | ||||
| # Length of a server tick and the interval at which objects are generally updated over network | ||||
| #dedicated_server_step = 0.1 | ||||
| # Can be set to true to disable shutting down on invalid world data | ||||
| #ignore_world_load_errors = false | ||||
| # Congestion control parameters | ||||
| # time in seconds, rate in ~500B packets | ||||
| #congestion_control_aim_rtt = 0.2 | ||||
| #congestion_control_max_rate = 400 | ||||
| #congestion_control_min_rate = 10 | ||||
|   | ||||
| @@ -202,6 +202,8 @@ set(common_SRCS | ||||
| 	sha1.cpp | ||||
| 	base64.cpp | ||||
| 	ban.cpp | ||||
| 	clientserver.cpp | ||||
| 	staticobject.cpp | ||||
| 	util/serialize.cpp | ||||
| 	util/directiontables.cpp | ||||
| 	util/numeric.cpp | ||||
|   | ||||
| @@ -42,6 +42,7 @@ with this program; if not, write to the Free Software Foundation, Inc., | ||||
| #include "util/string.h" | ||||
| #include "hex.h" | ||||
| #include "IMeshCache.h" | ||||
| #include "util/serialize.h" | ||||
| 
 | ||||
| static std::string getMediaCacheDir() | ||||
| { | ||||
| @@ -266,6 +267,7 @@ Client::Client( | ||||
| 	m_time_of_day_set(false), | ||||
| 	m_last_time_of_day_f(-1), | ||||
| 	m_time_of_day_update_timer(0), | ||||
| 	m_recommended_send_interval(0.1), | ||||
| 	m_removed_sounds_check_timer(0) | ||||
| { | ||||
| 	m_packetcounter_timer = 0.0; | ||||
| @@ -499,8 +501,9 @@ void Client::step(float dtime) | ||||
| 			// [2] u8 SER_FMT_VER_HIGHEST
 | ||||
| 			// [3] u8[20] player_name
 | ||||
| 			// [23] u8[28] password (new in some version)
 | ||||
| 			// [51] u16 client network protocol version (new in some version)
 | ||||
| 			SharedBuffer<u8> data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2); | ||||
| 			// [51] u16 minimum supported network protocol version (added sometime)
 | ||||
| 			// [53] u16 maximum supported network protocol version (added later than the previous one)
 | ||||
| 			SharedBuffer<u8> data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2); | ||||
| 			writeU16(&data[0], TOSERVER_INIT); | ||||
| 			writeU8(&data[2], SER_FMT_VER_HIGHEST); | ||||
| 
 | ||||
| @@ -513,8 +516,8 @@ void Client::step(float dtime) | ||||
| 			memset((char*)&data[23], 0, PASSWORD_SIZE); | ||||
| 			snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str()); | ||||
| 			 | ||||
| 			// This should be incremented in each version
 | ||||
| 			writeU16(&data[51], PROTOCOL_VERSION); | ||||
| 			writeU16(&data[51], CLIENT_PROTOCOL_VERSION_MIN); | ||||
| 			writeU16(&data[53], CLIENT_PROTOCOL_VERSION_MAX); | ||||
| 
 | ||||
| 			// Send as unreliable
 | ||||
| 			Send(0, data, false); | ||||
| @@ -656,7 +659,7 @@ void Client::step(float dtime) | ||||
| 	{ | ||||
| 		float &counter = m_playerpos_send_timer; | ||||
| 		counter += dtime; | ||||
| 		if(counter >= 0.2) | ||||
| 		if(counter >= m_recommended_send_interval) | ||||
| 		{ | ||||
| 			counter = 0.0; | ||||
| 			sendPlayerPos(); | ||||
| @@ -1021,6 +1024,14 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) | ||||
| 			infostream<<"Client: received map seed: "<<m_map_seed<<std::endl; | ||||
| 		} | ||||
| 
 | ||||
| 		if(datasize >= 2+1+6+8+4) | ||||
| 		{ | ||||
| 			// Get map seed
 | ||||
| 			m_recommended_send_interval = readF1000(&data[2+1+6+8]); | ||||
| 			infostream<<"Client: received recommended send interval " | ||||
| 					<<m_recommended_send_interval<<std::endl; | ||||
| 		} | ||||
| 		 | ||||
| 		// Reply to server
 | ||||
| 		u32 replysize = 2; | ||||
| 		SharedBuffer<u8> reply(replysize); | ||||
|   | ||||
| @@ -382,6 +382,9 @@ private: | ||||
| 	float m_last_time_of_day_f; | ||||
| 	float m_time_of_day_update_timer; | ||||
| 
 | ||||
| 	// An interval for generally sending object positions and stuff
 | ||||
| 	float m_recommended_send_interval; | ||||
| 
 | ||||
| 	// Sounds
 | ||||
| 	float m_removed_sounds_check_timer; | ||||
| 	// Mapping from server sound ids to our sound ids
 | ||||
|   | ||||
							
								
								
									
										31
									
								
								src/clientserver.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/clientserver.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| /*
 | ||||
| Minetest-c55 | ||||
| Copyright (C) 2010-2012 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 "clientserver.h" | ||||
| #include "util/serialize.h" | ||||
| 
 | ||||
| SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed) | ||||
| { | ||||
| 	SharedBuffer<u8> data(2+2+4); | ||||
| 	writeU16(&data[0], TOCLIENT_TIME_OF_DAY); | ||||
| 	writeU16(&data[2], time); | ||||
| 	writeF1000(&data[4], time_speed); | ||||
| 	return data; | ||||
| } | ||||
| 
 | ||||
| @@ -1,6 +1,6 @@ | ||||
| /*
 | ||||
| Minetest-c55 | ||||
| Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com> | ||||
| Copyright (C) 2010-2012 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 | ||||
| @@ -20,7 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc., | ||||
| #ifndef CLIENTSERVER_HEADER | ||||
| #define CLIENTSERVER_HEADER | ||||
| 
 | ||||
| #include "util/serialize.h" | ||||
| #include "util/pointer.h" | ||||
| 
 | ||||
| SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed); | ||||
| 
 | ||||
| /*
 | ||||
| 	changes by PROTOCOL_VERSION: | ||||
| @@ -73,10 +75,21 @@ with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 		GENERIC_CMD_SET_ANIMATION | ||||
| 		GENERIC_CMD_SET_BONE_POSITION | ||||
| 		GENERIC_CMD_SET_ATTACHMENT | ||||
| 	PROTOCOL_VERSION 15: | ||||
| 		Serialization format changes | ||||
| */ | ||||
| 
 | ||||
| #define PROTOCOL_VERSION 14 | ||||
| #define LATEST_PROTOCOL_VERSION 15 | ||||
| 
 | ||||
| // Server's supported network protocol range
 | ||||
| #define SERVER_PROTOCOL_VERSION_MIN 13 | ||||
| #define SERVER_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION | ||||
| 
 | ||||
| // Client's supported network protocol range
 | ||||
| #define CLIENT_PROTOCOL_VERSION_MIN 13 | ||||
| #define CLIENT_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION | ||||
| 
 | ||||
| // Constant that differentiates the protocol from random data and other protocols
 | ||||
| #define PROTOCOL_ID 0x4f457403 | ||||
| 
 | ||||
| #define PASSWORD_SIZE 28       // Maximum password length. Allows for
 | ||||
| @@ -95,6 +108,7 @@ enum ToClientCommand | ||||
| 		[2] u8 deployed version | ||||
| 		[3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd  | ||||
| 		[12] u64 map seed (new as of 2011-02-27) | ||||
| 		[20] f1000 recommended send interval (in seconds) (new as of 14) | ||||
| 
 | ||||
| 		NOTE: The position in here is deprecated; position is | ||||
| 		      explicitly sent afterwards | ||||
| @@ -350,7 +364,8 @@ enum ToServerCommand | ||||
| 		[2] u8 SER_FMT_VER_HIGHEST | ||||
| 		[3] u8[20] player_name | ||||
| 		[23] u8[28] password (new in some version) | ||||
| 		[51] u16 client network protocol version (new in some version) | ||||
| 		[51] u16 minimum supported network protocol version (added sometime) | ||||
| 		[53] u16 maximum supported network protocol version (added later than the previous one) | ||||
| 	*/ | ||||
| 
 | ||||
| 	TOSERVER_INIT2 = 0x11, | ||||
| @@ -558,14 +573,5 @@ enum ToServerCommand | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed) | ||||
| { | ||||
| 	SharedBuffer<u8> data(2+2+4); | ||||
| 	writeU16(&data[0], TOCLIENT_TIME_OF_DAY); | ||||
| 	writeU16(&data[2], time); | ||||
| 	writeF1000(&data[4], time_speed); | ||||
| 	return data; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|   | ||||
| @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., | ||||
| #include "util/serialize.h" | ||||
| #include "util/numeric.h" | ||||
| #include "util/string.h" | ||||
| #include "settings.h" | ||||
| 
 | ||||
| namespace con | ||||
| { | ||||
| @@ -466,7 +467,10 @@ Peer::Peer(u16 a_id, Address a_address): | ||||
| 	m_sendtime_accu(0), | ||||
| 	m_max_packets_per_second(10), | ||||
| 	m_num_sent(0), | ||||
| 	m_max_num_sent(0) | ||||
| 	m_max_num_sent(0), | ||||
| 	congestion_control_aim_rtt(0.2), | ||||
| 	congestion_control_max_rate(400), | ||||
| 	congestion_control_min_rate(10) | ||||
| { | ||||
| } | ||||
| Peer::~Peer() | ||||
| @@ -477,15 +481,15 @@ void Peer::reportRTT(float rtt) | ||||
| { | ||||
| 	if(rtt >= 0.0){ | ||||
| 		if(rtt < 0.01){ | ||||
| 			if(m_max_packets_per_second < 400) | ||||
| 			if(m_max_packets_per_second < congestion_control_max_rate) | ||||
| 				m_max_packets_per_second += 10; | ||||
| 		} else if(rtt < 0.2){ | ||||
| 			if(m_max_packets_per_second < 100) | ||||
| 		} else if(rtt < congestion_control_aim_rtt){ | ||||
| 			if(m_max_packets_per_second < congestion_control_max_rate) | ||||
| 				m_max_packets_per_second += 2; | ||||
| 		} else { | ||||
| 			m_max_packets_per_second *= 0.8; | ||||
| 			if(m_max_packets_per_second < 10) | ||||
| 				m_max_packets_per_second = 10; | ||||
| 			if(m_max_packets_per_second < congestion_control_min_rate) | ||||
| 				m_max_packets_per_second = congestion_control_min_rate; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| @@ -891,6 +895,13 @@ void Connection::receive() | ||||
| 
 | ||||
| void Connection::runTimeouts(float dtime) | ||||
| { | ||||
| 	float congestion_control_aim_rtt | ||||
| 			= g_settings->getFloat("congestion_control_aim_rtt"); | ||||
| 	float congestion_control_max_rate | ||||
| 			= g_settings->getFloat("congestion_control_max_rate"); | ||||
| 	float congestion_control_min_rate | ||||
| 			= g_settings->getFloat("congestion_control_min_rate"); | ||||
| 
 | ||||
| 	core::list<u16> timeouted_peers; | ||||
| 	core::map<u16, Peer*>::Iterator j; | ||||
| 	j = m_peers.getIterator(); | ||||
| @@ -898,6 +909,11 @@ void Connection::runTimeouts(float dtime) | ||||
| 	{ | ||||
| 		Peer *peer = j.getNode()->getValue(); | ||||
| 
 | ||||
| 		// Update congestion control values
 | ||||
| 		peer->congestion_control_aim_rtt = congestion_control_aim_rtt; | ||||
| 		peer->congestion_control_max_rate = congestion_control_max_rate; | ||||
| 		peer->congestion_control_min_rate = congestion_control_min_rate; | ||||
| 		 | ||||
| 		/*
 | ||||
| 			Check peer timeout | ||||
| 		*/ | ||||
|   | ||||
| @@ -395,6 +395,10 @@ public: | ||||
| 	int m_num_sent; | ||||
| 	int m_max_num_sent; | ||||
| 
 | ||||
| 	// Updated from configuration by Connection
 | ||||
| 	float congestion_control_aim_rtt; | ||||
| 	float congestion_control_max_rate; | ||||
| 	float congestion_control_min_rate; | ||||
| private: | ||||
| }; | ||||
| 
 | ||||
|   | ||||
| @@ -647,22 +647,36 @@ public: | ||||
| 	{ | ||||
| 		infostream<<"GenericCAO: Got init data"<<std::endl; | ||||
| 		std::istringstream is(data, std::ios::binary); | ||||
| 		int num_messages = 0; | ||||
| 		// version
 | ||||
| 		u8 version = readU8(is); | ||||
| 		// check version
 | ||||
| 		if(version != 0){ | ||||
| 			errorstream<<"GenericCAO: Unsupported init data version" | ||||
| 					<<std::endl; | ||||
| 			return; | ||||
| 		} | ||||
| 		if(version == 1) // In PROTOCOL_VERSION 14
 | ||||
| 		{ | ||||
| 			m_name = deSerializeString(is); | ||||
| 			m_is_player = readU8(is); | ||||
| 			m_id = readS16(is); | ||||
| 			m_position = readV3F1000(is); | ||||
| 			m_yaw = readF1000(is); | ||||
| 			m_hp = readS16(is); | ||||
| 			num_messages = readU8(is); | ||||
| 		} | ||||
| 		else if(version == 0) // In PROTOCOL_VERSION 13
 | ||||
| 		{ | ||||
| 			m_name = deSerializeString(is); | ||||
| 			m_is_player = readU8(is); | ||||
| 			m_position = readV3F1000(is); | ||||
| 			m_yaw = readF1000(is); | ||||
| 			m_hp = readS16(is); | ||||
| 			num_messages = readU8(is); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			errorstream<<"GenericCAO: Unsupported init data version" | ||||
| 					<<std::endl; | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		int num_messages = readU8(is); | ||||
| 		for(int i=0; i<num_messages; i++){ | ||||
| 			std::string message = deSerializeLongString(is); | ||||
| 			processMessage(message); | ||||
| @@ -909,6 +923,11 @@ public: | ||||
| 					m_prop.visual_size.X)); | ||||
| 			u8 li = m_last_light; | ||||
| 			setMeshColor(m_meshnode->getMesh(), video::SColor(255,li,li,li)); | ||||
| 
 | ||||
| 			m_meshnode->setMaterialFlag(video::EMF_LIGHTING, false); | ||||
| 			m_meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); | ||||
| 			m_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF); | ||||
| 			m_meshnode->setMaterialFlag(video::EMF_FOG_ENABLE, true); | ||||
| 		} | ||||
| 		else if(m_prop.visual == "mesh"){ | ||||
| 			infostream<<"GenericCAO::addToScene(): mesh"<<std::endl; | ||||
| @@ -922,6 +941,11 @@ public: | ||||
| 						m_prop.visual_size.X)); | ||||
| 				u8 li = m_last_light; | ||||
| 				setMeshColor(m_animated_meshnode->getMesh(), video::SColor(255,li,li,li)); | ||||
| 
 | ||||
| 				m_animated_meshnode->setMaterialFlag(video::EMF_LIGHTING, false); | ||||
| 				m_animated_meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); | ||||
| 				m_animated_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF); | ||||
| 				m_animated_meshnode->setMaterialFlag(video::EMF_FOG_ENABLE, true); | ||||
| 			} | ||||
| 			else | ||||
| 				errorstream<<"GenericCAO::addToScene(): Could not load mesh "<<m_prop.mesh<<std::endl; | ||||
|   | ||||
| @@ -26,7 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc., | ||||
| #include "tile.h" | ||||
| #include "gamedef.h" | ||||
| #include "util/numeric.h" | ||||
| #include "util/serialize.h" | ||||
| #include "util/directiontables.h" | ||||
| 
 | ||||
| // Create a cuboid.
 | ||||
|   | ||||
| @@ -245,7 +245,7 @@ public: | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	std::string getClientInitializationData() | ||||
| 	std::string getClientInitializationData(u16 protocol_version) | ||||
| 	{ | ||||
| 		std::ostringstream os(std::ios::binary); | ||||
| 		// version
 | ||||
| @@ -564,13 +564,16 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| std::string LuaEntitySAO::getClientInitializationData() | ||||
| std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version) | ||||
| { | ||||
| 	std::ostringstream os(std::ios::binary); | ||||
| 	writeU8(os, 0); // version
 | ||||
| 
 | ||||
| 	if(protocol_version >= 14) | ||||
| 	{ | ||||
| 		writeU8(os, 1); // version
 | ||||
| 		os<<serializeString(""); // name
 | ||||
| 	writeS16(os, getId()); //id
 | ||||
| 		writeU8(os, 0); // is_player
 | ||||
| 		writeS16(os, getId()); //id
 | ||||
| 		writeV3F1000(os, m_base_position); | ||||
| 		writeF1000(os, m_yaw); | ||||
| 		writeS16(os, m_hp); | ||||
| @@ -583,6 +586,19 @@ std::string LuaEntitySAO::getClientInitializationData() | ||||
| 			os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
 | ||||
| 		} | ||||
| 		os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4
 | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		writeU8(os, 0); // version
 | ||||
| 		os<<serializeString(""); // name
 | ||||
| 		writeU8(os, 0); // is_player
 | ||||
| 		writeV3F1000(os, m_base_position); | ||||
| 		writeF1000(os, m_yaw); | ||||
| 		writeS16(os, m_hp); | ||||
| 		writeU8(os, 2); // number of messages stuffed in here
 | ||||
| 		os<<serializeLongString(getPropertyPacket()); // message 1
 | ||||
| 		os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
 | ||||
| 	} | ||||
| 
 | ||||
| 	// return result
 | ||||
| 	return os.str(); | ||||
| @@ -962,10 +978,13 @@ bool PlayerSAO::unlimitedTransferDistance() const | ||||
| 	return g_settings->getBool("unlimited_player_transfer_distance"); | ||||
| } | ||||
| 
 | ||||
| std::string PlayerSAO::getClientInitializationData() | ||||
| std::string PlayerSAO::getClientInitializationData(u16 protocol_version) | ||||
| { | ||||
| 	std::ostringstream os(std::ios::binary); | ||||
| 	writeU8(os, 0); // version
 | ||||
| 
 | ||||
| 	if(protocol_version >= 15) | ||||
| 	{ | ||||
| 		writeU8(os, 1); // version
 | ||||
| 		os<<serializeString(m_player->getName()); // name
 | ||||
| 		writeU8(os, 1); // is_player
 | ||||
| 		writeS16(os, getId()); //id
 | ||||
| @@ -981,6 +1000,19 @@ std::string PlayerSAO::getClientInitializationData() | ||||
| 			os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
 | ||||
| 		} | ||||
| 		os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4
 | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		writeU8(os, 0); // version
 | ||||
| 		os<<serializeString(m_player->getName()); // name
 | ||||
| 		writeU8(os, 1); // is_player
 | ||||
| 		writeV3F1000(os, m_player->getPosition() + v3f(0,BS*1,0)); | ||||
| 		writeF1000(os, m_player->getYaw()); | ||||
| 		writeS16(os, getHP()); | ||||
| 		writeU8(os, 2); // number of messages stuffed in here
 | ||||
| 		os<<serializeLongString(getPropertyPacket()); // message 1
 | ||||
| 		os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
 | ||||
| 	} | ||||
| 
 | ||||
| 	// return result
 | ||||
| 	return os.str(); | ||||
|   | ||||
| @@ -48,7 +48,7 @@ public: | ||||
| 			const std::string &data); | ||||
| 	bool isAttached(); | ||||
| 	void step(float dtime, bool send_recommended); | ||||
| 	std::string getClientInitializationData(); | ||||
| 	std::string getClientInitializationData(u16 protocol_version); | ||||
| 	std::string getStaticData(); | ||||
| 	int punch(v3f dir, | ||||
| 			const ToolCapabilities *toolcap=NULL, | ||||
| @@ -140,7 +140,7 @@ public: | ||||
| 	void removingFromEnvironment(); | ||||
| 	bool isStaticAllowed() const; | ||||
| 	bool unlimitedTransferDistance() const; | ||||
| 	std::string getClientInitializationData(); | ||||
| 	std::string getClientInitializationData(u16 protocol_version); | ||||
| 	std::string getStaticData(); | ||||
| 	bool isAttached(); | ||||
| 	void step(float dtime, bool send_recommended); | ||||
|   | ||||
| @@ -106,12 +106,17 @@ void set_default_settings(Settings *settings) | ||||
| 	settings->setDefault("sound_volume", "0.8"); | ||||
| 	settings->setDefault("desynchronize_mapblock_texture_animation", "true"); | ||||
| 
 | ||||
| 	settings->setDefault("mip_map", "false"); | ||||
| 	settings->setDefault("anisotropic_filter", "false"); | ||||
| 	settings->setDefault("bilinear_filter", "false"); | ||||
| 	settings->setDefault("trilinear_filter", "false"); | ||||
| 
 | ||||
| 	// Server stuff
 | ||||
| 	// "map-dir" doesn't exist by default.
 | ||||
| 	settings->setDefault("default_game", "minetest"); | ||||
| 	settings->setDefault("motd", ""); | ||||
| 	settings->setDefault("max_users", "100"); | ||||
| 	settings->setDefault("strict_protocol_version_checking", "true"); | ||||
| 	settings->setDefault("strict_protocol_version_checking", "false"); | ||||
| 	settings->setDefault("creative_mode", "false"); | ||||
| 	settings->setDefault("enable_damage", "true"); | ||||
| 	settings->setDefault("only_peaceful_mobs", "false"); | ||||
| @@ -140,12 +145,10 @@ void set_default_settings(Settings *settings) | ||||
| 	settings->setDefault("server_unload_unused_data_timeout", "29"); | ||||
| 	settings->setDefault("server_map_save_interval", "5.3"); | ||||
| 	settings->setDefault("full_block_send_enable_min_time_from_building", "2.0"); | ||||
| 	settings->setDefault("dedicated_server_step", "0.05"); | ||||
| 	settings->setDefault("dedicated_server_step", "0.1"); | ||||
| 	settings->setDefault("ignore_world_load_errors", "false"); | ||||
| 	settings->setDefault("mip_map", "false"); | ||||
| 	settings->setDefault("anisotropic_filter", "false"); | ||||
| 	settings->setDefault("bilinear_filter", "false"); | ||||
| 	settings->setDefault("trilinear_filter", "false"); | ||||
| 
 | ||||
| 	settings->setDefault("congestion_control_aim_rtt", "0.2"); | ||||
| 	settings->setDefault("congestion_control_max_rate", "400"); | ||||
| 	settings->setDefault("congestion_control_min_rate", "10"); | ||||
| } | ||||
| 
 | ||||
|   | ||||
| @@ -43,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc., | ||||
| #endif | ||||
| #include "daynightratio.h" | ||||
| #include "map.h" | ||||
| #include "util/serialize.h" | ||||
| 
 | ||||
| #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" | ||||
| 
 | ||||
| @@ -328,7 +329,8 @@ ServerEnvironment::ServerEnvironment(ServerMap *map, lua_State *L, | ||||
| 	m_send_recommended_timer(0), | ||||
| 	m_active_block_interval_overload_skip(0), | ||||
| 	m_game_time(0), | ||||
| 	m_game_time_fraction_counter(0) | ||||
| 	m_game_time_fraction_counter(0), | ||||
| 	m_recommended_send_interval(0.1) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| @@ -939,6 +941,11 @@ void ServerEnvironment::step(float dtime) | ||||
| 	/* Step time of day */ | ||||
| 	stepTimeOfDay(dtime); | ||||
| 
 | ||||
| 	// Update this one
 | ||||
| 	// NOTE: This is kind of funny on a singleplayer game, but doesn't
 | ||||
| 	// really matter that much.
 | ||||
| 	m_recommended_send_interval = g_settings->getFloat("dedicated_server_step"); | ||||
| 
 | ||||
| 	/*
 | ||||
| 		Increment game time | ||||
| 	*/ | ||||
| @@ -2296,8 +2303,9 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type, | ||||
| 	{ | ||||
| 		errorstream<<"ClientEnvironment::addActiveObject():" | ||||
| 				<<" id="<<id<<" type="<<type | ||||
| 				<<": SerializationError in initialize()," | ||||
| 				<<" init_data="<<serializeJsonString(init_data) | ||||
| 				<<": SerializationError in initialize(): " | ||||
| 				<<e.what() | ||||
| 				<<": init_data="<<serializeJsonString(init_data) | ||||
| 				<<std::endl; | ||||
| 	} | ||||
| 
 | ||||
|   | ||||
| @@ -205,9 +205,7 @@ public: | ||||
| 		{ return m_gamedef; } | ||||
| 
 | ||||
| 	float getSendRecommendedInterval() | ||||
| 	{ | ||||
| 		return 0.10; | ||||
| 	} | ||||
| 		{ return m_recommended_send_interval; } | ||||
| 
 | ||||
| 	/*
 | ||||
| 		Save players | ||||
| @@ -367,6 +365,8 @@ private: | ||||
| 	// A helper variable for incrementing the latter
 | ||||
| 	float m_game_time_fraction_counter; | ||||
| 	core::list<ABMWithState> m_abms; | ||||
| 	// An interval for generally sending object positions and stuff
 | ||||
| 	float m_recommended_send_interval; | ||||
| }; | ||||
| 
 | ||||
| #ifndef SERVER | ||||
|   | ||||
| @@ -1513,7 +1513,7 @@ void the_game( | ||||
| 					<<"Launching inventory"<<std::endl; | ||||
| 			 | ||||
| 			GUIFormSpecMenu *menu = | ||||
| 				new GUIFormSpecMenu(guienv, guiroot, -1, | ||||
| 				new GUIFormSpecMenu(device, guiroot, -1, | ||||
| 					&g_menumgr, | ||||
| 					&client, gamedef); | ||||
| 
 | ||||
| @@ -2296,7 +2296,7 @@ void the_game( | ||||
| 					/* Create menu */ | ||||
| 
 | ||||
| 					GUIFormSpecMenu *menu = | ||||
| 						new GUIFormSpecMenu(guienv, guiroot, -1, | ||||
| 						new GUIFormSpecMenu(device, guiroot, -1, | ||||
| 							&g_menumgr, | ||||
| 							&client, gamedef); | ||||
| 					menu->setFormSpec(meta->getString("formspec"), | ||||
|   | ||||
| @@ -92,6 +92,31 @@ std::string gob_cmd_set_sprite( | ||||
| 	return os.str(); | ||||
| } | ||||
| 
 | ||||
| std::string gob_cmd_punched(s16 damage, s16 result_hp) | ||||
| { | ||||
| 	std::ostringstream os(std::ios::binary); | ||||
| 	// command 
 | ||||
| 	writeU8(os, GENERIC_CMD_PUNCHED); | ||||
| 	// damage
 | ||||
| 	writeS16(os, damage); | ||||
| 	// result_hp
 | ||||
| 	writeS16(os, result_hp); | ||||
| 	return os.str(); | ||||
| } | ||||
| 
 | ||||
| std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups) | ||||
| { | ||||
| 	std::ostringstream os(std::ios::binary); | ||||
| 	writeU8(os, GENERIC_CMD_UPDATE_ARMOR_GROUPS); | ||||
| 	writeU16(os, armor_groups.size()); | ||||
| 	for(ItemGroupList::const_iterator i = armor_groups.begin(); | ||||
| 			i != armor_groups.end(); i++){ | ||||
| 		os<<serializeString(i->first); | ||||
| 		writeS16(os, i->second); | ||||
| 	} | ||||
| 	return os.str(); | ||||
| } | ||||
| 
 | ||||
| std::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_blend) | ||||
| { | ||||
| 	std::ostringstream os(std::ios::binary); | ||||
| @@ -129,29 +154,3 @@ std::string gob_cmd_update_attachment(int parent_id, std::string bone, v3f posit | ||||
| 	return os.str(); | ||||
| } | ||||
| 
 | ||||
| std::string gob_cmd_punched(s16 damage, s16 result_hp) | ||||
| { | ||||
| 	std::ostringstream os(std::ios::binary); | ||||
| 	// command 
 | ||||
| 	writeU8(os, GENERIC_CMD_PUNCHED); | ||||
| 	// damage
 | ||||
| 	writeS16(os, damage); | ||||
| 	// result_hp
 | ||||
| 	writeS16(os, result_hp); | ||||
| 	return os.str(); | ||||
| } | ||||
| 
 | ||||
| std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups) | ||||
| { | ||||
| 	std::ostringstream os(std::ios::binary); | ||||
| 	writeU8(os, GENERIC_CMD_UPDATE_ARMOR_GROUPS); | ||||
| 	writeU16(os, armor_groups.size()); | ||||
| 	for(ItemGroupList::const_iterator i = armor_groups.begin(); | ||||
| 			i != armor_groups.end(); i++){ | ||||
| 		os<<serializeString(i->first); | ||||
| 		writeS16(os, i->second); | ||||
| 	} | ||||
| 	return os.str(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|   | ||||
| @@ -28,11 +28,11 @@ with this program; if not, write to the Free Software Foundation, Inc., | ||||
| #define GENERIC_CMD_UPDATE_POSITION 1 | ||||
| #define GENERIC_CMD_SET_TEXTURE_MOD 2 | ||||
| #define GENERIC_CMD_SET_SPRITE 3 | ||||
| #define GENERIC_CMD_SET_ANIMATION 4 | ||||
| #define GENERIC_CMD_SET_BONE_POSITION 5 | ||||
| #define GENERIC_CMD_SET_ATTACHMENT 6 | ||||
| #define GENERIC_CMD_PUNCHED 7 | ||||
| #define GENERIC_CMD_UPDATE_ARMOR_GROUPS 8 | ||||
| #define GENERIC_CMD_PUNCHED 4 | ||||
| #define GENERIC_CMD_UPDATE_ARMOR_GROUPS 5 | ||||
| #define GENERIC_CMD_SET_ANIMATION 6 | ||||
| #define GENERIC_CMD_SET_BONE_POSITION 7 | ||||
| #define GENERIC_CMD_SET_ATTACHMENT 8 | ||||
| 
 | ||||
| #include "object_properties.h" | ||||
| std::string gob_cmd_set_properties(const ObjectProperties &prop); | ||||
| @@ -57,16 +57,16 @@ std::string gob_cmd_set_sprite( | ||||
| 	bool select_horiz_by_yawpitch | ||||
| ); | ||||
| 
 | ||||
| std::string gob_cmd_punched(s16 damage, s16 result_hp); | ||||
| 
 | ||||
| #include "itemgroup.h" | ||||
| std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups); | ||||
| 
 | ||||
| std::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_blend); | ||||
| 
 | ||||
| std::string gob_cmd_update_bone_position(std::string bone, v3f position, v3f rotation); | ||||
| 
 | ||||
| std::string gob_cmd_update_attachment(int parent_id, std::string bone, v3f position, v3f rotation); | ||||
| 
 | ||||
| std::string gob_cmd_punched(s16 damage, s16 result_hp); | ||||
| 
 | ||||
| #include "itemgroup.h" | ||||
| std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups); | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|   | ||||
| @@ -125,13 +125,14 @@ void drawItemStack(video::IVideoDriver *driver, | ||||
| 	GUIFormSpecMenu | ||||
| */ | ||||
| 
 | ||||
| GUIFormSpecMenu::GUIFormSpecMenu(gui::IGUIEnvironment* env, | ||||
| GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, | ||||
| 		gui::IGUIElement* parent, s32 id, | ||||
| 		IMenuManager *menumgr, | ||||
| 		InventoryManager *invmgr, | ||||
| 		IGameDef *gamedef | ||||
| ): | ||||
| 	GUIModalMenu(env, parent, id, menumgr), | ||||
| 	GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr), | ||||
| 	m_device(dev), | ||||
| 	m_invmgr(invmgr), | ||||
| 	m_gamedef(gamedef), | ||||
| 	m_form_src(NULL), | ||||
| @@ -698,6 +699,8 @@ void GUIFormSpecMenu::drawMenu() | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	m_pointer = m_device->getCursorControl()->getPosition(); | ||||
| 
 | ||||
| 	updateSelectedItem(); | ||||
| 
 | ||||
| 	gui::IGUISkin* skin = Environment->getSkin(); | ||||
| @@ -937,24 +940,15 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
| 	if(event.EventType==EET_MOUSE_INPUT_EVENT | ||||
| 			&& event.MouseInput.Event == EMIE_MOUSE_MOVED) | ||||
| 	{ | ||||
| 		// Mouse moved
 | ||||
| 		m_pointer = v2s32(event.MouseInput.X, event.MouseInput.Y); | ||||
| 	} | ||||
| 	if(event.EventType==EET_MOUSE_INPUT_EVENT | ||||
| 			&& event.MouseInput.Event != EMIE_MOUSE_MOVED) | ||||
| 	{ | ||||
| 		// Mouse event other than movement
 | ||||
| 
 | ||||
| 		v2s32 p(event.MouseInput.X, event.MouseInput.Y); | ||||
| 		m_pointer = p; | ||||
| 
 | ||||
| 		// Get selected item and hovered/clicked item (s)
 | ||||
| 
 | ||||
| 		updateSelectedItem(); | ||||
| 		ItemSpec s = getItemAtPos(p); | ||||
| 		ItemSpec s = getItemAtPos(m_pointer); | ||||
| 
 | ||||
| 		Inventory *inv_selected = NULL; | ||||
| 		Inventory *inv_s = NULL; | ||||
|   | ||||
| @@ -144,7 +144,7 @@ class GUIFormSpecMenu : public GUIModalMenu | ||||
| 	}; | ||||
| 
 | ||||
| public: | ||||
| 	GUIFormSpecMenu(gui::IGUIEnvironment* env, | ||||
| 	GUIFormSpecMenu(irr::IrrlichtDevice* dev, | ||||
| 			gui::IGUIElement* parent, s32 id, | ||||
| 			IMenuManager *menumgr, | ||||
| 			InventoryManager *invmgr, | ||||
| @@ -197,6 +197,7 @@ protected: | ||||
| 	v2s32 spacing; | ||||
| 	v2s32 imgsize; | ||||
| 	 | ||||
| 	irr::IrrlichtDevice* m_device; | ||||
| 	InventoryManager *m_invmgr; | ||||
| 	IGameDef *m_gamedef; | ||||
| 
 | ||||
|   | ||||
| @@ -323,7 +323,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, | ||||
| 		v3s16 camera_np = floatToInt(getEyePosition(), BS); | ||||
| 		MapNode n = map.getNodeNoEx(camera_np); | ||||
| 		if(n.getContent() != CONTENT_IGNORE){ | ||||
| 			if(nodemgr->get(n).walkable){ | ||||
| 			if(nodemgr->get(n).walkable && nodemgr->get(n).solidness == 2){ | ||||
| 				camera_barely_in_ceiling = true; | ||||
| 			} | ||||
| 		} | ||||
|   | ||||
| @@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc., | ||||
| #include "mapblock_mesh.h" | ||||
| #endif | ||||
| #include "util/string.h" | ||||
| #include "util/serialize.h" | ||||
| 
 | ||||
| #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" | ||||
| 
 | ||||
|   | ||||
| @@ -77,9 +77,9 @@ void MeshMakeData::fill(MapBlock *block) | ||||
| 		// Get map
 | ||||
| 		Map *map = block->getParent(); | ||||
| 
 | ||||
| 		for(u16 i=0; i<6; i++) | ||||
| 		for(u16 i=0; i<26; i++) | ||||
| 		{ | ||||
| 			const v3s16 &dir = g_6dirs[i]; | ||||
| 			const v3s16 &dir = g_26dirs[i]; | ||||
| 			v3s16 bp = m_blockpos + dir; | ||||
| 			MapBlock *b = map->getBlockNoCreateNoEx(bp); | ||||
| 			if(b) | ||||
|   | ||||
| @@ -39,6 +39,10 @@ static void collectMods(const std::string &modspath, | ||||
| 		if(!dirlist[j].dir) | ||||
| 			continue; | ||||
| 		std::string modname = dirlist[j].name; | ||||
| 		// Ignore all directories beginning with a ".", especially
 | ||||
| 		// VCS directories like ".git" or ".svn"
 | ||||
| 		if(modname[0] == '.') | ||||
| 			continue; | ||||
| 		std::string modpath = modspath + DIR_DELIM + modname; | ||||
| 		TRACESTREAM(<<indentation<<"collectMods: "<<modname<<" at \""<<modpath<<"\""<<std::endl); | ||||
| 		// Handle modpacks (defined by containing modpack.txt)
 | ||||
|   | ||||
							
								
								
									
										137
									
								
								src/nodedef.cpp
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								src/nodedef.cpp
									
									
									
									
									
								
							| @@ -215,8 +215,13 @@ void ContentFeatures::reset() | ||||
| 	sound_dug = SimpleSoundSpec(); | ||||
| } | ||||
| 
 | ||||
| void ContentFeatures::serialize(std::ostream &os) | ||||
| void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) | ||||
| { | ||||
| 	if(protocol_version < 14){ | ||||
| 		serializeOld(os, protocol_version); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	writeU8(os, 6); // version
 | ||||
| 	os<<serializeString(name); | ||||
| 	writeU16(os, groups.size()); | ||||
| @@ -271,8 +276,11 @@ void ContentFeatures::serialize(std::ostream &os) | ||||
| void ContentFeatures::deSerialize(std::istream &is) | ||||
| { | ||||
| 	int version = readU8(is); | ||||
| 	if(version != 6) | ||||
| 		throw SerializationError("unsupported ContentFeatures version"); | ||||
| 	if(version != 6){ | ||||
| 		deSerializeOld(is, version); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	name = deSerializeString(is); | ||||
| 	groups.clear(); | ||||
| 	u32 groups_size = readU16(is); | ||||
| @@ -693,7 +701,7 @@ public: | ||||
| 		} | ||||
| #endif | ||||
| 	} | ||||
| 	void serialize(std::ostream &os) | ||||
| 	void serialize(std::ostream &os, u16 protocol_version) | ||||
| 	{ | ||||
| 		writeU8(os, 1); // version
 | ||||
| 		u16 count = 0; | ||||
| @@ -709,7 +717,7 @@ public: | ||||
| 			// Wrap it in a string to allow different lengths without
 | ||||
| 			// strict version incompatibilities
 | ||||
| 			std::ostringstream wrapper_os(std::ios::binary); | ||||
| 			f->serialize(wrapper_os); | ||||
| 			f->serialize(wrapper_os, protocol_version); | ||||
| 			os2<<serializeString(wrapper_os.str()); | ||||
| 			count++; | ||||
| 		} | ||||
| @@ -766,3 +774,122 @@ IWritableNodeDefManager* createNodeDefManager() | ||||
| 	return new CNodeDefManager(); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| 	Serialization of old ContentFeatures formats | ||||
| */ | ||||
| 
 | ||||
| void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) | ||||
| { | ||||
| 	if(protocol_version == 13) | ||||
| 	{ | ||||
| 		writeU8(os, 5); // version
 | ||||
| 		os<<serializeString(name); | ||||
| 		writeU16(os, groups.size()); | ||||
| 		for(ItemGroupList::const_iterator | ||||
| 				i = groups.begin(); i != groups.end(); i++){ | ||||
| 			os<<serializeString(i->first); | ||||
| 			writeS16(os, i->second); | ||||
| 		} | ||||
| 		writeU8(os, drawtype); | ||||
| 		writeF1000(os, visual_scale); | ||||
| 		writeU8(os, 6); | ||||
| 		for(u32 i=0; i<6; i++) | ||||
| 			tiledef[i].serialize(os); | ||||
| 		writeU8(os, CF_SPECIAL_COUNT); | ||||
| 		for(u32 i=0; i<CF_SPECIAL_COUNT; i++){ | ||||
| 			tiledef_special[i].serialize(os); | ||||
| 		} | ||||
| 		writeU8(os, alpha); | ||||
| 		writeU8(os, post_effect_color.getAlpha()); | ||||
| 		writeU8(os, post_effect_color.getRed()); | ||||
| 		writeU8(os, post_effect_color.getGreen()); | ||||
| 		writeU8(os, post_effect_color.getBlue()); | ||||
| 		writeU8(os, param_type); | ||||
| 		writeU8(os, param_type_2); | ||||
| 		writeU8(os, is_ground_content); | ||||
| 		writeU8(os, light_propagates); | ||||
| 		writeU8(os, sunlight_propagates); | ||||
| 		writeU8(os, walkable); | ||||
| 		writeU8(os, pointable); | ||||
| 		writeU8(os, diggable); | ||||
| 		writeU8(os, climbable); | ||||
| 		writeU8(os, buildable_to); | ||||
| 		os<<serializeString(""); // legacy: used to be metadata_name
 | ||||
| 		writeU8(os, liquid_type); | ||||
| 		os<<serializeString(liquid_alternative_flowing); | ||||
| 		os<<serializeString(liquid_alternative_source); | ||||
| 		writeU8(os, liquid_viscosity); | ||||
| 		writeU8(os, light_source); | ||||
| 		writeU32(os, damage_per_second); | ||||
| 		node_box.serialize(os); | ||||
| 		selection_box.serialize(os); | ||||
| 		writeU8(os, legacy_facedir_simple); | ||||
| 		writeU8(os, legacy_wallmounted); | ||||
| 		serializeSimpleSoundSpec(sound_footstep, os); | ||||
| 		serializeSimpleSoundSpec(sound_dig, os); | ||||
| 		serializeSimpleSoundSpec(sound_dug, os); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		throw SerializationError("ContentFeatures::serialize(): Unsupported version requested"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void ContentFeatures::deSerializeOld(std::istream &is, int version) | ||||
| { | ||||
| 	if(version == 5) // In PROTOCOL_VERSION 13
 | ||||
| 	{ | ||||
| 		name = deSerializeString(is); | ||||
| 		groups.clear(); | ||||
| 		u32 groups_size = readU16(is); | ||||
| 		for(u32 i=0; i<groups_size; i++){ | ||||
| 			std::string name = deSerializeString(is); | ||||
| 			int value = readS16(is); | ||||
| 			groups[name] = value; | ||||
| 		} | ||||
| 		drawtype = (enum NodeDrawType)readU8(is); | ||||
| 		visual_scale = readF1000(is); | ||||
| 		if(readU8(is) != 6) | ||||
| 			throw SerializationError("unsupported tile count"); | ||||
| 		for(u32 i=0; i<6; i++) | ||||
| 			tiledef[i].deSerialize(is); | ||||
| 		if(readU8(is) != CF_SPECIAL_COUNT) | ||||
| 			throw SerializationError("unsupported CF_SPECIAL_COUNT"); | ||||
| 		for(u32 i=0; i<CF_SPECIAL_COUNT; i++) | ||||
| 			tiledef_special[i].deSerialize(is); | ||||
| 		alpha = readU8(is); | ||||
| 		post_effect_color.setAlpha(readU8(is)); | ||||
| 		post_effect_color.setRed(readU8(is)); | ||||
| 		post_effect_color.setGreen(readU8(is)); | ||||
| 		post_effect_color.setBlue(readU8(is)); | ||||
| 		param_type = (enum ContentParamType)readU8(is); | ||||
| 		param_type_2 = (enum ContentParamType2)readU8(is); | ||||
| 		is_ground_content = readU8(is); | ||||
| 		light_propagates = readU8(is); | ||||
| 		sunlight_propagates = readU8(is); | ||||
| 		walkable = readU8(is); | ||||
| 		pointable = readU8(is); | ||||
| 		diggable = readU8(is); | ||||
| 		climbable = readU8(is); | ||||
| 		buildable_to = readU8(is); | ||||
| 		deSerializeString(is); // legacy: used to be metadata_name
 | ||||
| 		liquid_type = (enum LiquidType)readU8(is); | ||||
| 		liquid_alternative_flowing = deSerializeString(is); | ||||
| 		liquid_alternative_source = deSerializeString(is); | ||||
| 		liquid_viscosity = readU8(is); | ||||
| 		light_source = readU8(is); | ||||
| 		damage_per_second = readU32(is); | ||||
| 		node_box.deSerialize(is); | ||||
| 		selection_box.deSerialize(is); | ||||
| 		legacy_facedir_simple = readU8(is); | ||||
| 		legacy_wallmounted = readU8(is); | ||||
| 		deSerializeSimpleSoundSpec(sound_footstep, is); | ||||
| 		deSerializeSimpleSoundSpec(sound_dig, is); | ||||
| 		deSerializeSimpleSoundSpec(sound_dug, is); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		throw SerializationError("unsupported ContentFeatures version"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|   | ||||
| @@ -234,8 +234,10 @@ struct ContentFeatures | ||||
| 	ContentFeatures(); | ||||
| 	~ContentFeatures(); | ||||
| 	void reset(); | ||||
| 	void serialize(std::ostream &os); | ||||
| 	void serialize(std::ostream &os, u16 protocol_version); | ||||
| 	void deSerialize(std::istream &is); | ||||
| 	void serializeOld(std::ostream &os, u16 protocol_version); | ||||
| 	void deSerializeOld(std::istream &is, int version); | ||||
| 
 | ||||
| 	/*
 | ||||
| 		Some handy methods | ||||
| @@ -264,7 +266,7 @@ public: | ||||
| 			const=0; | ||||
| 	virtual const ContentFeatures& get(const std::string &name) const=0; | ||||
| 	 | ||||
| 	virtual void serialize(std::ostream &os)=0; | ||||
| 	virtual void serialize(std::ostream &os, u16 protocol_version)=0; | ||||
| }; | ||||
| 
 | ||||
| class IWritableNodeDefManager : public INodeDefManager | ||||
| @@ -305,7 +307,7 @@ public: | ||||
| 	*/ | ||||
| 	virtual void updateTextures(ITextureSource *tsrc)=0; | ||||
| 
 | ||||
| 	virtual void serialize(std::ostream &os)=0; | ||||
| 	virtual void serialize(std::ostream &os, u16 protocol_version)=0; | ||||
| 	virtual void deSerialize(std::istream &is)=0; | ||||
| }; | ||||
| 
 | ||||
|   | ||||
| @@ -81,52 +81,59 @@ void ObjectProperties::serialize(std::ostream &os) const | ||||
| 	writeV3F1000(os, collisionbox.MinEdge); | ||||
| 	writeV3F1000(os, collisionbox.MaxEdge); | ||||
| 	os<<serializeString(visual); | ||||
| 	os<<serializeString(mesh); | ||||
| 	writeV2F1000(os, visual_size); | ||||
| 	writeU16(os, textures.size()); | ||||
| 	for(u32 i=0; i<textures.size(); i++){ | ||||
| 		os<<serializeString(textures[i]); | ||||
| 	} | ||||
| 	writeU16(os, colors.size()); | ||||
| 	for(u32 i=0; i<colors.size(); i++){ | ||||
| 		writeARGB8(os, colors[i]); | ||||
| 	} | ||||
| 	writeV2S16(os, spritediv); | ||||
| 	writeV2S16(os, initial_sprite_basepos); | ||||
| 	writeU8(os, is_visible); | ||||
| 	writeU8(os, makes_footstep_sound); | ||||
| 	writeF1000(os, automatic_rotate); | ||||
| 	// Added in protocol version 14
 | ||||
| 	os<<serializeString(mesh); | ||||
| 	writeU16(os, colors.size()); | ||||
| 	for(u32 i=0; i<colors.size(); i++){ | ||||
| 		writeARGB8(os, colors[i]); | ||||
| 	} | ||||
| 	// Add stuff only at the bottom.
 | ||||
| 	// Never remove anything, because we don't want new versions of this
 | ||||
| } | ||||
| 
 | ||||
| void ObjectProperties::deSerialize(std::istream &is) | ||||
| { | ||||
| 	int version = readU8(is); | ||||
| 	if(version != 1) throw SerializationError( | ||||
| 			"unsupported ObjectProperties version"); | ||||
| 	if(version == 1) | ||||
| 	{ | ||||
| 		try{ | ||||
| 			hp_max = readS16(is); | ||||
| 			physical = readU8(is); | ||||
| 			weight = readF1000(is); | ||||
| 			collisionbox.MinEdge = readV3F1000(is); | ||||
| 			collisionbox.MaxEdge = readV3F1000(is); | ||||
| 			visual = deSerializeString(is); | ||||
| 	mesh = deSerializeString(is); | ||||
| 			visual_size = readV2F1000(is); | ||||
| 			textures.clear(); | ||||
| 			u32 texture_count = readU16(is); | ||||
| 			for(u32 i=0; i<texture_count; i++){ | ||||
| 				textures.push_back(deSerializeString(is)); | ||||
| 			} | ||||
| 	u32 color_count = readU16(is); | ||||
| 	for(u32 i=0; i<color_count; i++){ | ||||
| 		colors.push_back(readARGB8(is)); | ||||
| 	} | ||||
| 			spritediv = readV2S16(is); | ||||
| 			initial_sprite_basepos = readV2S16(is); | ||||
| 			is_visible = readU8(is); | ||||
| 			makes_footstep_sound = readU8(is); | ||||
| 	try{ | ||||
| 			automatic_rotate = readF1000(is); | ||||
| 			mesh = deSerializeString(is); | ||||
| 			u32 color_count = readU16(is); | ||||
| 			for(u32 i=0; i<color_count; i++){ | ||||
| 				colors.push_back(readARGB8(is)); | ||||
| 			} | ||||
| 		}catch(SerializationError &e){} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		throw SerializationError("unsupported ObjectProperties version"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|   | ||||
| @@ -5576,6 +5576,19 @@ bool scriptapi_on_chat_message(lua_State *L, const std::string &name, | ||||
| 	return ate; | ||||
| } | ||||
| 
 | ||||
| void scriptapi_on_shutdown(lua_State *L) | ||||
| { | ||||
| 	realitycheck(L); | ||||
| 	assert(lua_checkstack(L, 20)); | ||||
| 	StackUnroller stack_unroller(L); | ||||
| 
 | ||||
| 	// Get registered shutdown hooks
 | ||||
| 	lua_getglobal(L, "minetest"); | ||||
| 	lua_getfield(L, -1, "registered_on_shutdown"); | ||||
| 	// Call callbacks
 | ||||
| 	scriptapi_run_callbacks(L, 0, RUN_CALLBACKS_MODE_FIRST); | ||||
| } | ||||
| 
 | ||||
| void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player) | ||||
| { | ||||
| 	realitycheck(L); | ||||
|   | ||||
| @@ -55,6 +55,9 @@ void scriptapi_environment_step(lua_State *L, float dtime); | ||||
| void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp, | ||||
| 		u32 blockseed); | ||||
| 
 | ||||
| /* server */ | ||||
| void scriptapi_on_shutdown(lua_State *L); | ||||
| 
 | ||||
| /* misc */ | ||||
| void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player); | ||||
| void scriptapi_on_dieplayer(lua_State *L, ServerActiveObject *player); | ||||
|   | ||||
							
								
								
									
										102
									
								
								src/server.cpp
									
									
									
									
									
								
							
							
						
						
									
										102
									
								
								src/server.cpp
									
									
									
									
									
								
							| @@ -54,6 +54,7 @@ with this program; if not, write to the Free Software Foundation, Inc., | ||||
| #include "util/pointedthing.h" | ||||
| #include "util/mathconstants.h" | ||||
| #include "rollback.h" | ||||
| #include "util/serialize.h" | ||||
| 
 | ||||
| #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" | ||||
| 
 | ||||
| @@ -1112,6 +1113,16 @@ Server::~Server() | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	{ | ||||
| 		JMutexAutoLock envlock(m_env_mutex); | ||||
| 		JMutexAutoLock conlock(m_con_mutex); | ||||
| 
 | ||||
| 		/*
 | ||||
| 			Execute script shutdown hooks | ||||
| 		*/ | ||||
| 		scriptapi_on_shutdown(m_lua); | ||||
| 	} | ||||
| 
 | ||||
| 	{ | ||||
| 		JMutexAutoLock envlock(m_env_mutex); | ||||
| 
 | ||||
| @@ -1143,14 +1154,6 @@ Server::~Server() | ||||
| 			i = m_clients.getIterator(); | ||||
| 			i.atEnd() == false; i++) | ||||
| 		{ | ||||
| 			/*// 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(); | ||||
| 		} | ||||
| @@ -1567,7 +1570,7 @@ void Server::AsyncRunStep() | ||||
| 				 | ||||
| 				if(obj) | ||||
| 					data_buffer.append(serializeLongString( | ||||
| 							obj->getClientInitializationData())); | ||||
| 							obj->getClientInitializationData(client->net_proto_version))); | ||||
| 				else | ||||
| 					data_buffer.append(serializeLongString("")); | ||||
| 
 | ||||
| @@ -2037,40 +2040,74 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | ||||
| 			Read and check network protocol version | ||||
| 		*/ | ||||
| 
 | ||||
| 		u16 net_proto_version = 0; | ||||
| 		u16 min_net_proto_version = 0; | ||||
| 		if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2) | ||||
| 			min_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]); | ||||
| 
 | ||||
| 		// Use same version as minimum and maximum if maximum version field
 | ||||
| 		// doesn't exist (backwards compatibility)
 | ||||
| 		u16 max_net_proto_version = min_net_proto_version; | ||||
| 		if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2) | ||||
| 			max_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2]); | ||||
| 
 | ||||
| 		// Start with client's maximum version
 | ||||
| 		u16 net_proto_version = max_net_proto_version; | ||||
| 
 | ||||
| 		// Figure out a working version if it is possible at all
 | ||||
| 		if(max_net_proto_version >= SERVER_PROTOCOL_VERSION_MIN || | ||||
| 				min_net_proto_version <= SERVER_PROTOCOL_VERSION_MAX) | ||||
| 		{ | ||||
| 			net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]); | ||||
| 			// If maximum is larger than our maximum, go with our maximum
 | ||||
| 			if(max_net_proto_version > SERVER_PROTOCOL_VERSION_MAX) | ||||
| 				net_proto_version = SERVER_PROTOCOL_VERSION_MAX; | ||||
| 			// Else go with client's maximum
 | ||||
| 			else | ||||
| 				net_proto_version = max_net_proto_version; | ||||
| 		} | ||||
| 
 | ||||
| 		verbosestream<<"Server: "<<peer_id<<" Protocol version: min: " | ||||
| 				<<min_net_proto_version<<", max: "<<max_net_proto_version | ||||
| 				<<", chosen: "<<net_proto_version<<std::endl; | ||||
| 
 | ||||
| 		getClient(peer_id)->net_proto_version = net_proto_version; | ||||
| 
 | ||||
| 		if(net_proto_version == 0) | ||||
| 		if(net_proto_version < SERVER_PROTOCOL_VERSION_MIN || | ||||
| 				net_proto_version > SERVER_PROTOCOL_VERSION_MAX) | ||||
| 		{ | ||||
| 			actionstream<<"Server: An old tried to connect from "<<addr_s | ||||
| 			actionstream<<"Server: A mismatched client tried to connect from "<<addr_s | ||||
| 					<<std::endl; | ||||
| 			SendAccessDenied(m_con, peer_id, std::wstring( | ||||
| 					L"Your client's version is not supported.\n" | ||||
| 					L"Server version is ") | ||||
| 					+ narrow_to_wide(VERSION_STRING) + L"." | ||||
| 					+ narrow_to_wide(VERSION_STRING) + L",\n" | ||||
| 					+ L"server's PROTOCOL_VERSION is " | ||||
| 					+ narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MIN)) | ||||
| 					+ L"..." | ||||
| 					+ narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MAX)) | ||||
| 					+ L", client's PROTOCOL_VERSION is " | ||||
| 					+ narrow_to_wide(itos(min_net_proto_version)) | ||||
| 					+ L"..." | ||||
| 					+ narrow_to_wide(itos(max_net_proto_version)) | ||||
| 			); | ||||
| 			return; | ||||
| 		} | ||||
| 		 | ||||
| 		if(g_settings->getBool("strict_protocol_version_checking")) | ||||
| 		{ | ||||
| 			if(net_proto_version != PROTOCOL_VERSION) | ||||
| 			if(net_proto_version != LATEST_PROTOCOL_VERSION) | ||||
| 			{ | ||||
| 				actionstream<<"Server: A mismatched client tried to connect" | ||||
| 						<<" from "<<addr_s<<std::endl; | ||||
| 				actionstream<<"Server: A mismatched (strict) client tried to " | ||||
| 						<<"connect from "<<addr_s<<std::endl; | ||||
| 				SendAccessDenied(m_con, peer_id, std::wstring( | ||||
| 						L"Your client's version is not supported.\n" | ||||
| 						L"Server version is ") | ||||
| 						+ narrow_to_wide(VERSION_STRING) + L",\n" | ||||
| 						+ L"server's PROTOCOL_VERSION is " | ||||
| 						+ narrow_to_wide(itos(PROTOCOL_VERSION)) | ||||
| 						+ L"server's PROTOCOL_VERSION (strict) is " | ||||
| 						+ narrow_to_wide(itos(LATEST_PROTOCOL_VERSION)) | ||||
| 						+ L", client's PROTOCOL_VERSION is " | ||||
| 						+ narrow_to_wide(itos(net_proto_version)) | ||||
| 						+ narrow_to_wide(itos(min_net_proto_version)) | ||||
| 						+ L"..." | ||||
| 						+ narrow_to_wide(itos(max_net_proto_version)) | ||||
| 				); | ||||
| 				return; | ||||
| 			} | ||||
| @@ -2212,11 +2249,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | ||||
| 			Answer with a TOCLIENT_INIT | ||||
| 		*/ | ||||
| 		{ | ||||
| 			SharedBuffer<u8> reply(2+1+6+8); | ||||
| 			SharedBuffer<u8> reply(2+1+6+8+4); | ||||
| 			writeU16(&reply[0], TOCLIENT_INIT); | ||||
| 			writeU8(&reply[2], deployed); | ||||
| 			writeV3S16(&reply[2+1], floatToInt(playersao->getPlayer()->getPosition()+v3f(0,BS/2,0), BS)); | ||||
| 			writeU64(&reply[2+1+6], m_env->getServerMap().getSeed()); | ||||
| 			writeF1000(&reply[2+1+6+8], g_settings->getFloat("dedicated_server_step")); | ||||
| 			 | ||||
| 			// Send as reliable
 | ||||
| 			m_con.Send(peer_id, 0, reply, true); | ||||
| @@ -2242,8 +2280,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		getClient(peer_id)->serialization_version | ||||
| 				= getClient(peer_id)->pending_serialization_version; | ||||
| 		RemoteClient *client = getClient(peer_id); | ||||
| 		client->serialization_version = | ||||
| 				getClient(peer_id)->pending_serialization_version; | ||||
| 
 | ||||
| 		/*
 | ||||
| 			Send some initialization data | ||||
| @@ -2256,7 +2295,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | ||||
| 		SendItemDef(m_con, peer_id, m_itemdef); | ||||
| 		 | ||||
| 		// Send node definitions
 | ||||
| 		SendNodeDef(m_con, peer_id, m_nodedef); | ||||
| 		SendNodeDef(m_con, peer_id, m_nodedef, client->net_proto_version); | ||||
| 		 | ||||
| 		// Send media announcement
 | ||||
| 		sendMediaAnnouncement(peer_id); | ||||
| @@ -2310,9 +2349,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | ||||
| 		} | ||||
| 		 | ||||
| 		// Warnings about protocol version can be issued here
 | ||||
| 		if(getClient(peer_id)->net_proto_version < PROTOCOL_VERSION) | ||||
| 		if(getClient(peer_id)->net_proto_version < LATEST_PROTOCOL_VERSION) | ||||
| 		{ | ||||
| 			SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD AND MAY WORK PROPERLY WITH THIS SERVER!"); | ||||
| 			SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT'S " | ||||
| 					L"VERSION MAY NOT BE FULLY COMPATIBLE WITH THIS SERVER!"); | ||||
| 		} | ||||
| 
 | ||||
| 		/*
 | ||||
| @@ -2369,7 +2409,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | ||||
| 
 | ||||
| 	if(command == TOSERVER_PLAYERPOS) | ||||
| 	{ | ||||
| 		if(datasize < 2+12+12+4+4+4) | ||||
| 		if(datasize < 2+12+12+4+4) | ||||
| 			return; | ||||
| 	 | ||||
| 		u32 start = 0; | ||||
| @@ -2377,7 +2417,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | ||||
| 		v3s32 ss = readV3S32(&data[start+2+12]); | ||||
| 		f32 pitch = (f32)readS32(&data[2+12+12]) / 100.0; | ||||
| 		f32 yaw = (f32)readS32(&data[2+12+12+4]) / 100.0; | ||||
| 		u32 keyPressed = (u32)readU32(&data[2+12+12+4+4]); | ||||
| 		u32 keyPressed = 0; | ||||
| 		if(datasize >= 2+12+12+4+4+4) | ||||
| 			keyPressed = (u32)readU32(&data[2+12+12+4+4]); | ||||
| 		v3f position((f32)ps.X/100., (f32)ps.Y/100., (f32)ps.Z/100.); | ||||
| 		v3f speed((f32)ss.X/100., (f32)ss.Y/100., (f32)ss.Z/100.); | ||||
| 		pitch = wrapDegrees(pitch); | ||||
| @@ -3508,7 +3550,7 @@ void Server::SendItemDef(con::Connection &con, u16 peer_id, | ||||
| } | ||||
| 
 | ||||
| void Server::SendNodeDef(con::Connection &con, u16 peer_id, | ||||
| 		INodeDefManager *nodedef) | ||||
| 		INodeDefManager *nodedef, u16 protocol_version) | ||||
| { | ||||
| 	DSTACK(__FUNCTION_NAME); | ||||
| 	std::ostringstream os(std::ios_base::binary); | ||||
| @@ -3520,7 +3562,7 @@ void Server::SendNodeDef(con::Connection &con, u16 peer_id, | ||||
| 	*/ | ||||
| 	writeU16(os, TOCLIENT_NODEDEF); | ||||
| 	std::ostringstream tmp_os(std::ios::binary); | ||||
| 	nodedef->serialize(tmp_os); | ||||
| 	nodedef->serialize(tmp_os, protocol_version); | ||||
| 	std::ostringstream tmp_os2(std::ios::binary); | ||||
| 	compressZlib(tmp_os.str(), tmp_os2); | ||||
| 	os<<serializeLongString(tmp_os2.str()); | ||||
|   | ||||
| @@ -602,7 +602,7 @@ private: | ||||
| 	static void SendItemDef(con::Connection &con, u16 peer_id, | ||||
| 			IItemDefManager *itemdef); | ||||
| 	static void SendNodeDef(con::Connection &con, u16 peer_id, | ||||
| 			INodeDefManager *nodedef); | ||||
| 			INodeDefManager *nodedef, u16 protocol_version); | ||||
| 	 | ||||
| 	/*
 | ||||
| 		Non-static send methods. | ||||
|   | ||||
| @@ -118,7 +118,7 @@ public: | ||||
| 		The return value of this is passed to the client-side object | ||||
| 		when it is created | ||||
| 	*/ | ||||
| 	virtual std::string getClientInitializationData(){return "";} | ||||
| 	virtual std::string getClientInitializationData(u16 protocol_version){return "";} | ||||
| 	 | ||||
| 	/*
 | ||||
| 		The return value of this is passed to the server-side object | ||||
|   | ||||
							
								
								
									
										92
									
								
								src/staticobject.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/staticobject.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| /*
 | ||||
| Minetest-c55 | ||||
| Copyright (C) 2010-2012 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 "staticobject.h" | ||||
| #include "util/serialize.h" | ||||
| 
 | ||||
| void StaticObject::serialize(std::ostream &os) | ||||
| { | ||||
| 	char buf[12]; | ||||
| 	// type
 | ||||
| 	buf[0] = type; | ||||
| 	os.write(buf, 1); | ||||
| 	// pos
 | ||||
| 	writeV3S32((u8*)buf, v3s32(pos.X*1000,pos.Y*1000,pos.Z*1000)); | ||||
| 	os.write(buf, 12); | ||||
| 	// data
 | ||||
| 	os<<serializeString(data); | ||||
| } | ||||
| void StaticObject::deSerialize(std::istream &is, u8 version) | ||||
| { | ||||
| 	char buf[12]; | ||||
| 	// type
 | ||||
| 	is.read(buf, 1); | ||||
| 	type = buf[0]; | ||||
| 	// pos
 | ||||
| 	is.read(buf, 12); | ||||
| 	v3s32 intp = readV3S32((u8*)buf); | ||||
| 	pos.X = (f32)intp.X/1000; | ||||
| 	pos.Y = (f32)intp.Y/1000; | ||||
| 	pos.Z = (f32)intp.Z/1000; | ||||
| 	// data
 | ||||
| 	data = deSerializeString(is); | ||||
| } | ||||
| 
 | ||||
| void StaticObjectList::serialize(std::ostream &os) | ||||
| { | ||||
| 	char buf[12]; | ||||
| 	// version
 | ||||
| 	buf[0] = 0; | ||||
| 	os.write(buf, 1); | ||||
| 	// count
 | ||||
| 	u16 count = m_stored.size() + m_active.size(); | ||||
| 	writeU16((u8*)buf, count); | ||||
| 	os.write(buf, 2); | ||||
| 	for(core::list<StaticObject>::Iterator | ||||
| 			i = m_stored.begin(); | ||||
| 			i != m_stored.end(); i++) | ||||
| 	{ | ||||
| 		StaticObject &s_obj = *i; | ||||
| 		s_obj.serialize(os); | ||||
| 	} | ||||
| 	for(core::map<u16, StaticObject>::Iterator | ||||
| 			i = m_active.getIterator(); | ||||
| 			i.atEnd()==false; i++) | ||||
| 	{ | ||||
| 		StaticObject s_obj = i.getNode()->getValue(); | ||||
| 		s_obj.serialize(os); | ||||
| 	} | ||||
| } | ||||
| void StaticObjectList::deSerialize(std::istream &is) | ||||
| { | ||||
| 	char buf[12]; | ||||
| 	// version
 | ||||
| 	is.read(buf, 1); | ||||
| 	u8 version = buf[0]; | ||||
| 	// count
 | ||||
| 	is.read(buf, 2); | ||||
| 	u16 count = readU16((u8*)buf); | ||||
| 	for(u16 i=0; i<count; i++) | ||||
| 	{ | ||||
| 		StaticObject s_obj; | ||||
| 		s_obj.deSerialize(is, version); | ||||
| 		m_stored.push_back(s_obj); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., | ||||
| #include "irrlichttypes_bloated.h" | ||||
| #include <string> | ||||
| #include <sstream> | ||||
| #include "util/serialize.h" | ||||
| #include "debug.h" | ||||
| 
 | ||||
| struct StaticObject | ||||
| { | ||||
| @@ -43,33 +43,8 @@ struct StaticObject | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| 	void serialize(std::ostream &os) | ||||
| 	{ | ||||
| 		char buf[12]; | ||||
| 		// type
 | ||||
| 		buf[0] = type; | ||||
| 		os.write(buf, 1); | ||||
| 		// pos
 | ||||
| 		writeV3S32((u8*)buf, v3s32(pos.X*1000,pos.Y*1000,pos.Z*1000)); | ||||
| 		os.write(buf, 12); | ||||
| 		// data
 | ||||
| 		os<<serializeString(data); | ||||
| 	} | ||||
| 	void deSerialize(std::istream &is, u8 version) | ||||
| 	{ | ||||
| 		char buf[12]; | ||||
| 		// type
 | ||||
| 		is.read(buf, 1); | ||||
| 		type = buf[0]; | ||||
| 		// pos
 | ||||
| 		is.read(buf, 12); | ||||
| 		v3s32 intp = readV3S32((u8*)buf); | ||||
| 		pos.X = (f32)intp.X/1000; | ||||
| 		pos.Y = (f32)intp.Y/1000; | ||||
| 		pos.Z = (f32)intp.Z/1000; | ||||
| 		// data
 | ||||
| 		data = deSerializeString(is); | ||||
| 	} | ||||
| 	void serialize(std::ostream &os); | ||||
| 	void deSerialize(std::istream &is, u8 version); | ||||
| }; | ||||
| 
 | ||||
| class StaticObjectList | ||||
| @@ -110,47 +85,8 @@ public: | ||||
| 		m_active.remove(id); | ||||
| 	} | ||||
| 
 | ||||
| 	void serialize(std::ostream &os) | ||||
| 	{ | ||||
| 		char buf[12]; | ||||
| 		// version
 | ||||
| 		buf[0] = 0; | ||||
| 		os.write(buf, 1); | ||||
| 		// count
 | ||||
| 		u16 count = m_stored.size() + m_active.size(); | ||||
| 		writeU16((u8*)buf, count); | ||||
| 		os.write(buf, 2); | ||||
| 		for(core::list<StaticObject>::Iterator | ||||
| 				i = m_stored.begin(); | ||||
| 				i != m_stored.end(); i++) | ||||
| 		{ | ||||
| 			StaticObject &s_obj = *i; | ||||
| 			s_obj.serialize(os); | ||||
| 		} | ||||
| 		for(core::map<u16, StaticObject>::Iterator | ||||
| 				i = m_active.getIterator(); | ||||
| 				i.atEnd()==false; i++) | ||||
| 		{ | ||||
| 			StaticObject s_obj = i.getNode()->getValue(); | ||||
| 			s_obj.serialize(os); | ||||
| 		} | ||||
| 	} | ||||
| 	void deSerialize(std::istream &is) | ||||
| 	{ | ||||
| 		char buf[12]; | ||||
| 		// version
 | ||||
| 		is.read(buf, 1); | ||||
| 		u8 version = buf[0]; | ||||
| 		// count
 | ||||
| 		is.read(buf, 2); | ||||
| 		u16 count = readU16((u8*)buf); | ||||
| 		for(u16 i=0; i<count; i++) | ||||
| 		{ | ||||
| 			StaticObject s_obj; | ||||
| 			s_obj.deSerialize(is, version); | ||||
| 			m_stored.push_back(s_obj); | ||||
| 		} | ||||
| 	} | ||||
| 	void serialize(std::ostream &os); | ||||
| 	void deSerialize(std::istream &is); | ||||
| 	 | ||||
| 	/*
 | ||||
| 		NOTE: When an object is transformed to active, it is removed | ||||
|   | ||||
							
								
								
									
										22
									
								
								src/test.cpp
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								src/test.cpp
									
									
									
									
									
								
							| @@ -41,6 +41,7 @@ with this program; if not, write to the Free Software Foundation, Inc., | ||||
| #include "util/numeric.h" | ||||
| #include "util/serialize.h" | ||||
| #include "noise.h" // PseudoRandom used for random data for compression
 | ||||
| #include "clientserver.h" // LATEST_PROTOCOL_VERSION
 | ||||
| 
 | ||||
| /*
 | ||||
| 	Asserts that the exception occurs | ||||
| @@ -314,6 +315,26 @@ struct TestSerialization: public TestBase | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| struct TestNodedefSerialization: public TestBase | ||||
| { | ||||
| 	void Run() | ||||
| 	{ | ||||
| 		ContentFeatures f; | ||||
| 		f.name = "default:stone"; | ||||
| 		for(int i = 0; i < 6; i++) | ||||
| 			f.tiledef[i].name = "default_stone.png"; | ||||
| 		f.is_ground_content = true; | ||||
| 		std::ostringstream os(std::ios::binary); | ||||
| 		f.serialize(os, LATEST_PROTOCOL_VERSION); | ||||
| 		verbosestream<<"Test ContentFeatures size: "<<os.str().size()<<std::endl; | ||||
| 		std::istringstream is(os.str(), std::ios::binary); | ||||
| 		ContentFeatures f2; | ||||
| 		f2.deSerialize(is); | ||||
| 		UASSERT(f.walkable == f2.walkable); | ||||
| 		UASSERT(f.node_box.type == f2.node_box.type); | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| struct TestCompress: public TestBase | ||||
| { | ||||
| 	void Run() | ||||
| @@ -1736,6 +1757,7 @@ void run_tests() | ||||
| 	TEST(TestSettings); | ||||
| 	TEST(TestCompress); | ||||
| 	TEST(TestSerialization); | ||||
| 	TEST(TestNodedefSerialization); | ||||
| 	TESTPARAMS(TestMapNode, ndef); | ||||
| 	TESTPARAMS(TestVoxelManipulator, ndef); | ||||
| 	TESTPARAMS(TestVoxelAlgorithms, ndef); | ||||
|   | ||||
							
								
								
									
										16
									
								
								src/tile.cpp
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/tile.cpp
									
									
									
									
									
								
							| @@ -373,6 +373,18 @@ public: | ||||
| 	// AtlasPointer based on it's texture id
 | ||||
| 	void updateAP(AtlasPointer &ap); | ||||
|   | ||||
| 	bool isKnownSourceImage(const std::string &name) | ||||
| 	{ | ||||
| 		bool is_known = false; | ||||
| 		bool cache_found = m_source_image_existence.get(name, &is_known); | ||||
| 		if(cache_found) | ||||
| 			return is_known; | ||||
| 		// Not found in cache; find out if a local file exists
 | ||||
| 		is_known = (getTexturePath(name) != ""); | ||||
| 		m_source_image_existence.set(name, is_known); | ||||
| 		return is_known; | ||||
| 	} | ||||
| 
 | ||||
| 	// Processes queued texture requests from other threads.
 | ||||
| 	// Shall be called from the main thread.
 | ||||
| 	void processQueue(); | ||||
| @@ -400,6 +412,9 @@ private: | ||||
| 	// This should be only accessed from the main thread
 | ||||
| 	SourceImageCache m_sourcecache; | ||||
| 
 | ||||
| 	// Thread-safe cache of what source images are known (true = known)
 | ||||
| 	MutexedMap<std::string, bool> m_source_image_existence; | ||||
| 
 | ||||
| 	// A texture id is index in this array.
 | ||||
| 	// The first position contains a NULL texture.
 | ||||
| 	core::array<SourceAtlasPointer> m_atlaspointer_cache; | ||||
| @@ -781,6 +796,7 @@ void TextureSource::insertSourceImage(const std::string &name, video::IImage *im | ||||
| 	assert(get_current_thread_id() == m_main_thread); | ||||
| 	 | ||||
| 	m_sourcecache.insert(name, img, true, m_device->getVideoDriver()); | ||||
| 	m_source_image_existence.set(name, true); | ||||
| } | ||||
| 	 | ||||
| void TextureSource::rebuildImagesAndTextures() | ||||
|   | ||||
| @@ -131,6 +131,7 @@ public: | ||||
| 	virtual IrrlichtDevice* getDevice() | ||||
| 		{return NULL;} | ||||
| 	virtual void updateAP(AtlasPointer &ap){}; | ||||
| 	virtual bool isKnownSourceImage(const std::string &name)=0; | ||||
| }; | ||||
| 
 | ||||
| class IWritableTextureSource : public ITextureSource | ||||
| @@ -149,6 +150,7 @@ public: | ||||
| 	virtual IrrlichtDevice* getDevice() | ||||
| 		{return NULL;} | ||||
| 	virtual void updateAP(AtlasPointer &ap){}; | ||||
| 	virtual bool isKnownSourceImage(const std::string &name)=0; | ||||
| 
 | ||||
| 	virtual void processQueue()=0; | ||||
| 	virtual void insertSourceImage(const std::string &name, video::IImage *img)=0; | ||||
|   | ||||
| @@ -222,7 +222,7 @@ public: | ||||
| 	/*
 | ||||
| 		Copies whole buffer | ||||
| 	*/ | ||||
| 	SharedBuffer(T *t, unsigned int size) | ||||
| 	SharedBuffer(const T *t, unsigned int size) | ||||
| 	{ | ||||
| 		m_size = size; | ||||
| 		if(m_size != 0) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user