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 | # Also remember to set PROTOCOL_VERSION in clientserver.h when releasing | ||||||
| set(VERSION_MAJOR 0) | set(VERSION_MAJOR 0) | ||||||
| set(VERSION_MINOR 4) | set(VERSION_MINOR 4) | ||||||
| set(VERSION_PATCH 3) | set(VERSION_PATCH 4-dev) | ||||||
| if(VERSION_EXTRA) | if(VERSION_EXTRA) | ||||||
| 	set(VERSION_PATCH ${VERSION_PATCH}-${VERSION_EXTRA}) | 	set(VERSION_PATCH ${VERSION_PATCH}-${VERSION_EXTRA}) | ||||||
| endif() | endif() | ||||||
|   | |||||||
| @@ -138,6 +138,7 @@ minetest.register_chatcommand("grant", { | |||||||
| 			return | 			return | ||||||
| 		end | 		end | ||||||
| 		minetest.set_player_privs(grantname, privs) | 		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), ' ')) | 		minetest.chat_send_player(name, "Privileges of "..grantname..": "..minetest.privs_to_string(minetest.get_player_privs(grantname), ' ')) | ||||||
| 		if grantname ~= name then | 		if grantname ~= name then | ||||||
| 			minetest.chat_send_player(grantname, name.." granted you privileges: "..minetest.privs_to_string(grantprivs, ' ')) | 			minetest.chat_send_player(grantname, name.." granted you privileges: "..minetest.privs_to_string(grantprivs, ' ')) | ||||||
| @@ -175,6 +176,7 @@ minetest.register_chatcommand("revoke", { | |||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
| 		minetest.set_player_privs(revokename, privs) | 		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), ' ')) | 		minetest.chat_send_player(name, "Privileges of "..revokename..": "..minetest.privs_to_string(minetest.get_player_privs(revokename), ' ')) | ||||||
| 		if revokename ~= name then | 		if revokename ~= name then | ||||||
| 			minetest.chat_send_player(revokename, name.." revoked privileges from you: "..minetest.privs_to_string(revokeprivs, ' ')) | 			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_on_chat_messages, minetest.register_on_chat_message = make_registration() | ||||||
| minetest.registered_globalsteps, minetest.register_globalstep = 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_punchnodes, minetest.register_on_punchnode = make_registration() | ||||||
| minetest.registered_on_placenodes, minetest.register_on_placenode = make_registration() | minetest.registered_on_placenodes, minetest.register_on_placenode = make_registration() | ||||||
| minetest.registered_on_dignodes, minetest.register_on_dignode = 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/ | 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) | Global callback registration functions: (Call these only at load time) | ||||||
| minetest.register_globalstep(func(dtime)) | minetest.register_globalstep(func(dtime)) | ||||||
| ^ Called every server step, usually interval of 0.05s | ^ 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)) | minetest.register_on_placenode(func(pos, newnode, placer, oldnode)) | ||||||
| ^ Called when a node has been placed | ^ Called when a node has been placed | ||||||
| ^ Deprecated: Use on_construct or after_place_node in node definition instead | ^ Deprecated: Use on_construct or after_place_node in node definition instead | ||||||
|   | |||||||
| @@ -139,8 +139,8 @@ | |||||||
| #motd = Welcome to this awesome Minetest server! | #motd = Welcome to this awesome Minetest server! | ||||||
| # Maximum number of players connected simultaneously | # Maximum number of players connected simultaneously | ||||||
| #max_users = 100 | #max_users = 100 | ||||||
| # Set to false to allow old clients to connect | # Set to true to disallow old clients from connecting | ||||||
| #strict_protocol_version_checking = true | #strict_protocol_version_checking = false | ||||||
| # Set to true to enable creative mode (unlimited inventory) | # Set to true to enable creative mode (unlimited inventory) | ||||||
| #creative_mode = false | #creative_mode = false | ||||||
| # Enable players getting damage and dying | # Enable players getting damage and dying | ||||||
| @@ -194,7 +194,12 @@ | |||||||
| # To reduce lag, block transfers are slowed down when a player is building something. | # 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. | # This determines how long they are slowed down after placing or removing a node. | ||||||
| #full_block_send_enable_min_time_from_building = 2.0 | #full_block_send_enable_min_time_from_building = 2.0 | ||||||
| # Length of a server tick in dedicated server | # Length of a server tick and the interval at which objects are generally updated over network | ||||||
| #dedicated_server_step = 0.05 | #dedicated_server_step = 0.1 | ||||||
| # Can be set to true to disable shutting down on invalid world data | # Can be set to true to disable shutting down on invalid world data | ||||||
| #ignore_world_load_errors = false | #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 | 	sha1.cpp | ||||||
| 	base64.cpp | 	base64.cpp | ||||||
| 	ban.cpp | 	ban.cpp | ||||||
|  | 	clientserver.cpp | ||||||
|  | 	staticobject.cpp | ||||||
| 	util/serialize.cpp | 	util/serialize.cpp | ||||||
| 	util/directiontables.cpp | 	util/directiontables.cpp | ||||||
| 	util/numeric.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 "util/string.h" | ||||||
| #include "hex.h" | #include "hex.h" | ||||||
| #include "IMeshCache.h" | #include "IMeshCache.h" | ||||||
|  | #include "util/serialize.h" | ||||||
| 
 | 
 | ||||||
| static std::string getMediaCacheDir() | static std::string getMediaCacheDir() | ||||||
| { | { | ||||||
| @@ -266,6 +267,7 @@ Client::Client( | |||||||
| 	m_time_of_day_set(false), | 	m_time_of_day_set(false), | ||||||
| 	m_last_time_of_day_f(-1), | 	m_last_time_of_day_f(-1), | ||||||
| 	m_time_of_day_update_timer(0), | 	m_time_of_day_update_timer(0), | ||||||
|  | 	m_recommended_send_interval(0.1), | ||||||
| 	m_removed_sounds_check_timer(0) | 	m_removed_sounds_check_timer(0) | ||||||
| { | { | ||||||
| 	m_packetcounter_timer = 0.0; | 	m_packetcounter_timer = 0.0; | ||||||
| @@ -499,8 +501,9 @@ void Client::step(float dtime) | |||||||
| 			// [2] u8 SER_FMT_VER_HIGHEST
 | 			// [2] u8 SER_FMT_VER_HIGHEST
 | ||||||
| 			// [3] u8[20] player_name
 | 			// [3] u8[20] player_name
 | ||||||
| 			// [23] u8[28] password (new in some version)
 | 			// [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)
 | ||||||
| 			SharedBuffer<u8> data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2); | 			// [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); | 			writeU16(&data[0], TOSERVER_INIT); | ||||||
| 			writeU8(&data[2], SER_FMT_VER_HIGHEST); | 			writeU8(&data[2], SER_FMT_VER_HIGHEST); | ||||||
| 
 | 
 | ||||||
| @@ -513,8 +516,8 @@ void Client::step(float dtime) | |||||||
| 			memset((char*)&data[23], 0, PASSWORD_SIZE); | 			memset((char*)&data[23], 0, PASSWORD_SIZE); | ||||||
| 			snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str()); | 			snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str()); | ||||||
| 			 | 			 | ||||||
| 			// This should be incremented in each version
 | 			writeU16(&data[51], CLIENT_PROTOCOL_VERSION_MIN); | ||||||
| 			writeU16(&data[51], PROTOCOL_VERSION); | 			writeU16(&data[53], CLIENT_PROTOCOL_VERSION_MAX); | ||||||
| 
 | 
 | ||||||
| 			// Send as unreliable
 | 			// Send as unreliable
 | ||||||
| 			Send(0, data, false); | 			Send(0, data, false); | ||||||
| @@ -656,7 +659,7 @@ void Client::step(float dtime) | |||||||
| 	{ | 	{ | ||||||
| 		float &counter = m_playerpos_send_timer; | 		float &counter = m_playerpos_send_timer; | ||||||
| 		counter += dtime; | 		counter += dtime; | ||||||
| 		if(counter >= 0.2) | 		if(counter >= m_recommended_send_interval) | ||||||
| 		{ | 		{ | ||||||
| 			counter = 0.0; | 			counter = 0.0; | ||||||
| 			sendPlayerPos(); | 			sendPlayerPos(); | ||||||
| @@ -1020,6 +1023,14 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) | |||||||
| 			m_map_seed = readU64(&data[2+1+6]); | 			m_map_seed = readU64(&data[2+1+6]); | ||||||
| 			infostream<<"Client: received map seed: "<<m_map_seed<<std::endl; | 			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
 | 		// Reply to server
 | ||||||
| 		u32 replysize = 2; | 		u32 replysize = 2; | ||||||
|   | |||||||
| @@ -382,6 +382,9 @@ private: | |||||||
| 	float m_last_time_of_day_f; | 	float m_last_time_of_day_f; | ||||||
| 	float m_time_of_day_update_timer; | 	float m_time_of_day_update_timer; | ||||||
| 
 | 
 | ||||||
|  | 	// An interval for generally sending object positions and stuff
 | ||||||
|  | 	float m_recommended_send_interval; | ||||||
|  | 
 | ||||||
| 	// Sounds
 | 	// Sounds
 | ||||||
| 	float m_removed_sounds_check_timer; | 	float m_removed_sounds_check_timer; | ||||||
| 	// Mapping from server sound ids to our sound ids
 | 	// 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 | 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 | 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 | 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 | #ifndef CLIENTSERVER_HEADER | ||||||
| #define 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: | 	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_ANIMATION | ||||||
| 		GENERIC_CMD_SET_BONE_POSITION | 		GENERIC_CMD_SET_BONE_POSITION | ||||||
| 		GENERIC_CMD_SET_ATTACHMENT | 		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 PROTOCOL_ID 0x4f457403 | ||||||
| 
 | 
 | ||||||
| #define PASSWORD_SIZE 28       // Maximum password length. Allows for
 | #define PASSWORD_SIZE 28       // Maximum password length. Allows for
 | ||||||
| @@ -95,6 +108,7 @@ enum ToClientCommand | |||||||
| 		[2] u8 deployed version | 		[2] u8 deployed version | ||||||
| 		[3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd  | 		[3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd  | ||||||
| 		[12] u64 map seed (new as of 2011-02-27) | 		[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 | 		NOTE: The position in here is deprecated; position is | ||||||
| 		      explicitly sent afterwards | 		      explicitly sent afterwards | ||||||
| @@ -350,7 +364,8 @@ enum ToServerCommand | |||||||
| 		[2] u8 SER_FMT_VER_HIGHEST | 		[2] u8 SER_FMT_VER_HIGHEST | ||||||
| 		[3] u8[20] player_name | 		[3] u8[20] player_name | ||||||
| 		[23] u8[28] password (new in some version) | 		[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, | 	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 | #endif | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., | |||||||
| #include "util/serialize.h" | #include "util/serialize.h" | ||||||
| #include "util/numeric.h" | #include "util/numeric.h" | ||||||
| #include "util/string.h" | #include "util/string.h" | ||||||
|  | #include "settings.h" | ||||||
| 
 | 
 | ||||||
| namespace con | namespace con | ||||||
| { | { | ||||||
| @@ -466,7 +467,10 @@ Peer::Peer(u16 a_id, Address a_address): | |||||||
| 	m_sendtime_accu(0), | 	m_sendtime_accu(0), | ||||||
| 	m_max_packets_per_second(10), | 	m_max_packets_per_second(10), | ||||||
| 	m_num_sent(0), | 	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() | Peer::~Peer() | ||||||
| @@ -477,15 +481,15 @@ void Peer::reportRTT(float rtt) | |||||||
| { | { | ||||||
| 	if(rtt >= 0.0){ | 	if(rtt >= 0.0){ | ||||||
| 		if(rtt < 0.01){ | 		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; | 				m_max_packets_per_second += 10; | ||||||
| 		} else if(rtt < 0.2){ | 		} else if(rtt < congestion_control_aim_rtt){ | ||||||
| 			if(m_max_packets_per_second < 100) | 			if(m_max_packets_per_second < congestion_control_max_rate) | ||||||
| 				m_max_packets_per_second += 2; | 				m_max_packets_per_second += 2; | ||||||
| 		} else { | 		} else { | ||||||
| 			m_max_packets_per_second *= 0.8; | 			m_max_packets_per_second *= 0.8; | ||||||
| 			if(m_max_packets_per_second < 10) | 			if(m_max_packets_per_second < congestion_control_min_rate) | ||||||
| 				m_max_packets_per_second = 10; | 				m_max_packets_per_second = congestion_control_min_rate; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @@ -891,12 +895,24 @@ void Connection::receive() | |||||||
| 
 | 
 | ||||||
| void Connection::runTimeouts(float dtime) | 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::list<u16> timeouted_peers; | ||||||
| 	core::map<u16, Peer*>::Iterator j; | 	core::map<u16, Peer*>::Iterator j; | ||||||
| 	j = m_peers.getIterator(); | 	j = m_peers.getIterator(); | ||||||
| 	for(; j.atEnd() == false; j++) | 	for(; j.atEnd() == false; j++) | ||||||
| 	{ | 	{ | ||||||
| 		Peer *peer = j.getNode()->getValue(); | 		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 | 			Check peer timeout | ||||||
|   | |||||||
| @@ -394,7 +394,11 @@ public: | |||||||
| 	float m_max_packets_per_second; | 	float m_max_packets_per_second; | ||||||
| 	int m_num_sent; | 	int m_num_sent; | ||||||
| 	int m_max_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: | private: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -647,22 +647,36 @@ public: | |||||||
| 	{ | 	{ | ||||||
| 		infostream<<"GenericCAO: Got init data"<<std::endl; | 		infostream<<"GenericCAO: Got init data"<<std::endl; | ||||||
| 		std::istringstream is(data, std::ios::binary); | 		std::istringstream is(data, std::ios::binary); | ||||||
|  | 		int num_messages = 0; | ||||||
| 		// version
 | 		// version
 | ||||||
| 		u8 version = readU8(is); | 		u8 version = readU8(is); | ||||||
| 		// check version
 | 		// check version
 | ||||||
| 		if(version != 0){ | 		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" | 			errorstream<<"GenericCAO: Unsupported init data version" | ||||||
| 					<<std::endl; | 					<<std::endl; | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		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); |  | ||||||
| 		 |  | ||||||
| 		int num_messages = readU8(is); |  | ||||||
| 		for(int i=0; i<num_messages; i++){ | 		for(int i=0; i<num_messages; i++){ | ||||||
| 			std::string message = deSerializeLongString(is); | 			std::string message = deSerializeLongString(is); | ||||||
| 			processMessage(message); | 			processMessage(message); | ||||||
| @@ -909,6 +923,11 @@ public: | |||||||
| 					m_prop.visual_size.X)); | 					m_prop.visual_size.X)); | ||||||
| 			u8 li = m_last_light; | 			u8 li = m_last_light; | ||||||
| 			setMeshColor(m_meshnode->getMesh(), video::SColor(255,li,li,li)); | 			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"){ | 		else if(m_prop.visual == "mesh"){ | ||||||
| 			infostream<<"GenericCAO::addToScene(): mesh"<<std::endl; | 			infostream<<"GenericCAO::addToScene(): mesh"<<std::endl; | ||||||
| @@ -922,6 +941,11 @@ public: | |||||||
| 						m_prop.visual_size.X)); | 						m_prop.visual_size.X)); | ||||||
| 				u8 li = m_last_light; | 				u8 li = m_last_light; | ||||||
| 				setMeshColor(m_animated_meshnode->getMesh(), video::SColor(255,li,li,li)); | 				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 | 			else | ||||||
| 				errorstream<<"GenericCAO::addToScene(): Could not load mesh "<<m_prop.mesh<<std::endl; | 				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 "tile.h" | ||||||
| #include "gamedef.h" | #include "gamedef.h" | ||||||
| #include "util/numeric.h" | #include "util/numeric.h" | ||||||
| #include "util/serialize.h" |  | ||||||
| #include "util/directiontables.h" | #include "util/directiontables.h" | ||||||
| 
 | 
 | ||||||
| // Create a cuboid.
 | // Create a cuboid.
 | ||||||
|   | |||||||
| @@ -245,7 +245,7 @@ public: | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	std::string getClientInitializationData() | 	std::string getClientInitializationData(u16 protocol_version) | ||||||
| 	{ | 	{ | ||||||
| 		std::ostringstream os(std::ios::binary); | 		std::ostringstream os(std::ios::binary); | ||||||
| 		// version
 | 		// version
 | ||||||
| @@ -564,25 +564,41 @@ 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); | 	std::ostringstream os(std::ios::binary); | ||||||
| 	writeU8(os, 0); // version
 |  | ||||||
| 	os<<serializeString(""); // name
 |  | ||||||
| 	writeS16(os, getId()); //id
 |  | ||||||
| 	writeU8(os, 0); // is_player
 |  | ||||||
| 	writeV3F1000(os, m_base_position); |  | ||||||
| 	writeF1000(os, m_yaw); |  | ||||||
| 	writeS16(os, m_hp); |  | ||||||
| 
 | 
 | ||||||
| 	writeU8(os, 4 + m_bone_position.size()); // number of messages stuffed in here
 | 	if(protocol_version >= 14) | ||||||
| 	os<<serializeLongString(getPropertyPacket()); // message 1
 | 	{ | ||||||
| 	os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
 | 		writeU8(os, 1); // version
 | ||||||
| 	os<<serializeLongString(gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend)); // 3
 | 		os<<serializeString(""); // name
 | ||||||
| 	for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ | 		writeU8(os, 0); // is_player
 | ||||||
| 		os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
 | 		writeS16(os, getId()); //id
 | ||||||
|  | 		writeV3F1000(os, m_base_position); | ||||||
|  | 		writeF1000(os, m_yaw); | ||||||
|  | 		writeS16(os, m_hp); | ||||||
|  | 
 | ||||||
|  | 		writeU8(os, 4 + m_bone_position.size()); // number of messages stuffed in here
 | ||||||
|  | 		os<<serializeLongString(getPropertyPacket()); // message 1
 | ||||||
|  | 		os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
 | ||||||
|  | 		os<<serializeLongString(gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend)); // 3
 | ||||||
|  | 		for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ | ||||||
|  | 			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
 | ||||||
| 	} | 	} | ||||||
| 	os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4
 |  | ||||||
| 
 | 
 | ||||||
| 	// return result
 | 	// return result
 | ||||||
| 	return os.str(); | 	return os.str(); | ||||||
| @@ -962,25 +978,41 @@ bool PlayerSAO::unlimitedTransferDistance() const | |||||||
| 	return g_settings->getBool("unlimited_player_transfer_distance"); | 	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); | 	std::ostringstream os(std::ios::binary); | ||||||
| 	writeU8(os, 0); // version
 |  | ||||||
| 	os<<serializeString(m_player->getName()); // name
 |  | ||||||
| 	writeU8(os, 1); // is_player
 |  | ||||||
| 	writeS16(os, getId()); //id
 |  | ||||||
| 	writeV3F1000(os, m_player->getPosition() + v3f(0,BS*1,0)); |  | ||||||
| 	writeF1000(os, m_player->getYaw()); |  | ||||||
| 	writeS16(os, getHP()); |  | ||||||
| 
 | 
 | ||||||
| 	writeU8(os, 4 + m_bone_position.size()); // number of messages stuffed in here
 | 	if(protocol_version >= 15) | ||||||
| 	os<<serializeLongString(getPropertyPacket()); // message 1
 | 	{ | ||||||
| 	os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
 | 		writeU8(os, 1); // version
 | ||||||
| 	os<<serializeLongString(gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend)); // 3
 | 		os<<serializeString(m_player->getName()); // name
 | ||||||
| 	for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ | 		writeU8(os, 1); // is_player
 | ||||||
| 		os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
 | 		writeS16(os, getId()); //id
 | ||||||
|  | 		writeV3F1000(os, m_player->getPosition() + v3f(0,BS*1,0)); | ||||||
|  | 		writeF1000(os, m_player->getYaw()); | ||||||
|  | 		writeS16(os, getHP()); | ||||||
|  | 
 | ||||||
|  | 		writeU8(os, 4 + m_bone_position.size()); // number of messages stuffed in here
 | ||||||
|  | 		os<<serializeLongString(getPropertyPacket()); // message 1
 | ||||||
|  | 		os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
 | ||||||
|  | 		os<<serializeLongString(gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend)); // 3
 | ||||||
|  | 		for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ | ||||||
|  | 			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
 | ||||||
| 	} | 	} | ||||||
| 	os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4
 |  | ||||||
| 
 | 
 | ||||||
| 	// return result
 | 	// return result
 | ||||||
| 	return os.str(); | 	return os.str(); | ||||||
|   | |||||||
| @@ -48,7 +48,7 @@ public: | |||||||
| 			const std::string &data); | 			const std::string &data); | ||||||
| 	bool isAttached(); | 	bool isAttached(); | ||||||
| 	void step(float dtime, bool send_recommended); | 	void step(float dtime, bool send_recommended); | ||||||
| 	std::string getClientInitializationData(); | 	std::string getClientInitializationData(u16 protocol_version); | ||||||
| 	std::string getStaticData(); | 	std::string getStaticData(); | ||||||
| 	int punch(v3f dir, | 	int punch(v3f dir, | ||||||
| 			const ToolCapabilities *toolcap=NULL, | 			const ToolCapabilities *toolcap=NULL, | ||||||
| @@ -140,7 +140,7 @@ public: | |||||||
| 	void removingFromEnvironment(); | 	void removingFromEnvironment(); | ||||||
| 	bool isStaticAllowed() const; | 	bool isStaticAllowed() const; | ||||||
| 	bool unlimitedTransferDistance() const; | 	bool unlimitedTransferDistance() const; | ||||||
| 	std::string getClientInitializationData(); | 	std::string getClientInitializationData(u16 protocol_version); | ||||||
| 	std::string getStaticData(); | 	std::string getStaticData(); | ||||||
| 	bool isAttached(); | 	bool isAttached(); | ||||||
| 	void step(float dtime, bool send_recommended); | 	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("sound_volume", "0.8"); | ||||||
| 	settings->setDefault("desynchronize_mapblock_texture_animation", "true"); | 	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
 | 	// Server stuff
 | ||||||
| 	// "map-dir" doesn't exist by default.
 | 	// "map-dir" doesn't exist by default.
 | ||||||
| 	settings->setDefault("default_game", "minetest"); | 	settings->setDefault("default_game", "minetest"); | ||||||
| 	settings->setDefault("motd", ""); | 	settings->setDefault("motd", ""); | ||||||
| 	settings->setDefault("max_users", "100"); | 	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("creative_mode", "false"); | ||||||
| 	settings->setDefault("enable_damage", "true"); | 	settings->setDefault("enable_damage", "true"); | ||||||
| 	settings->setDefault("only_peaceful_mobs", "false"); | 	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_unload_unused_data_timeout", "29"); | ||||||
| 	settings->setDefault("server_map_save_interval", "5.3"); | 	settings->setDefault("server_map_save_interval", "5.3"); | ||||||
| 	settings->setDefault("full_block_send_enable_min_time_from_building", "2.0"); | 	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("ignore_world_load_errors", "false"); | ||||||
| 	settings->setDefault("mip_map", "false"); | 	settings->setDefault("congestion_control_aim_rtt", "0.2"); | ||||||
| 	settings->setDefault("anisotropic_filter", "false"); | 	settings->setDefault("congestion_control_max_rate", "400"); | ||||||
| 	settings->setDefault("bilinear_filter", "false"); | 	settings->setDefault("congestion_control_min_rate", "10"); | ||||||
| 	settings->setDefault("trilinear_filter", "false"); |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -43,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc., | |||||||
| #endif | #endif | ||||||
| #include "daynightratio.h" | #include "daynightratio.h" | ||||||
| #include "map.h" | #include "map.h" | ||||||
|  | #include "util/serialize.h" | ||||||
| 
 | 
 | ||||||
| #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" | #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_send_recommended_timer(0), | ||||||
| 	m_active_block_interval_overload_skip(0), | 	m_active_block_interval_overload_skip(0), | ||||||
| 	m_game_time(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 */ | 	/* Step time of day */ | ||||||
| 	stepTimeOfDay(dtime); | 	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 | 		Increment game time | ||||||
| 	*/ | 	*/ | ||||||
| @@ -2296,8 +2303,9 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type, | |||||||
| 	{ | 	{ | ||||||
| 		errorstream<<"ClientEnvironment::addActiveObject():" | 		errorstream<<"ClientEnvironment::addActiveObject():" | ||||||
| 				<<" id="<<id<<" type="<<type | 				<<" id="<<id<<" type="<<type | ||||||
| 				<<": SerializationError in initialize()," | 				<<": SerializationError in initialize(): " | ||||||
| 				<<" init_data="<<serializeJsonString(init_data) | 				<<e.what() | ||||||
|  | 				<<": init_data="<<serializeJsonString(init_data) | ||||||
| 				<<std::endl; | 				<<std::endl; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -205,9 +205,7 @@ public: | |||||||
| 		{ return m_gamedef; } | 		{ return m_gamedef; } | ||||||
| 
 | 
 | ||||||
| 	float getSendRecommendedInterval() | 	float getSendRecommendedInterval() | ||||||
| 	{ | 		{ return m_recommended_send_interval; } | ||||||
| 		return 0.10; |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 		Save players | 		Save players | ||||||
| @@ -367,6 +365,8 @@ private: | |||||||
| 	// A helper variable for incrementing the latter
 | 	// A helper variable for incrementing the latter
 | ||||||
| 	float m_game_time_fraction_counter; | 	float m_game_time_fraction_counter; | ||||||
| 	core::list<ABMWithState> m_abms; | 	core::list<ABMWithState> m_abms; | ||||||
|  | 	// An interval for generally sending object positions and stuff
 | ||||||
|  | 	float m_recommended_send_interval; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #ifndef SERVER | #ifndef SERVER | ||||||
|   | |||||||
| @@ -1513,7 +1513,7 @@ void the_game( | |||||||
| 					<<"Launching inventory"<<std::endl; | 					<<"Launching inventory"<<std::endl; | ||||||
| 			 | 			 | ||||||
| 			GUIFormSpecMenu *menu = | 			GUIFormSpecMenu *menu = | ||||||
| 				new GUIFormSpecMenu(guienv, guiroot, -1, | 				new GUIFormSpecMenu(device, guiroot, -1, | ||||||
| 					&g_menumgr, | 					&g_menumgr, | ||||||
| 					&client, gamedef); | 					&client, gamedef); | ||||||
| 
 | 
 | ||||||
| @@ -2296,7 +2296,7 @@ void the_game( | |||||||
| 					/* Create menu */ | 					/* Create menu */ | ||||||
| 
 | 
 | ||||||
| 					GUIFormSpecMenu *menu = | 					GUIFormSpecMenu *menu = | ||||||
| 						new GUIFormSpecMenu(guienv, guiroot, -1, | 						new GUIFormSpecMenu(device, guiroot, -1, | ||||||
| 							&g_menumgr, | 							&g_menumgr, | ||||||
| 							&client, gamedef); | 							&client, gamedef); | ||||||
| 					menu->setFormSpec(meta->getString("formspec"), | 					menu->setFormSpec(meta->getString("formspec"), | ||||||
|   | |||||||
| @@ -92,6 +92,31 @@ std::string gob_cmd_set_sprite( | |||||||
| 	return os.str(); | 	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::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_blend) | ||||||
| { | { | ||||||
| 	std::ostringstream os(std::ios::binary); | 	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(); | 	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_UPDATE_POSITION 1 | ||||||
| #define GENERIC_CMD_SET_TEXTURE_MOD 2 | #define GENERIC_CMD_SET_TEXTURE_MOD 2 | ||||||
| #define GENERIC_CMD_SET_SPRITE 3 | #define GENERIC_CMD_SET_SPRITE 3 | ||||||
| #define GENERIC_CMD_SET_ANIMATION 4 | #define GENERIC_CMD_PUNCHED 4 | ||||||
| #define GENERIC_CMD_SET_BONE_POSITION 5 | #define GENERIC_CMD_UPDATE_ARMOR_GROUPS 5 | ||||||
| #define GENERIC_CMD_SET_ATTACHMENT 6 | #define GENERIC_CMD_SET_ANIMATION 6 | ||||||
| #define GENERIC_CMD_PUNCHED 7 | #define GENERIC_CMD_SET_BONE_POSITION 7 | ||||||
| #define GENERIC_CMD_UPDATE_ARMOR_GROUPS 8 | #define GENERIC_CMD_SET_ATTACHMENT 8 | ||||||
| 
 | 
 | ||||||
| #include "object_properties.h" | #include "object_properties.h" | ||||||
| std::string gob_cmd_set_properties(const ObjectProperties &prop); | std::string gob_cmd_set_properties(const ObjectProperties &prop); | ||||||
| @@ -57,16 +57,16 @@ std::string gob_cmd_set_sprite( | |||||||
| 	bool select_horiz_by_yawpitch | 	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_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_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_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 | #endif | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -125,13 +125,14 @@ void drawItemStack(video::IVideoDriver *driver, | |||||||
| 	GUIFormSpecMenu | 	GUIFormSpecMenu | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| GUIFormSpecMenu::GUIFormSpecMenu(gui::IGUIEnvironment* env, | GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, | ||||||
| 		gui::IGUIElement* parent, s32 id, | 		gui::IGUIElement* parent, s32 id, | ||||||
| 		IMenuManager *menumgr, | 		IMenuManager *menumgr, | ||||||
| 		InventoryManager *invmgr, | 		InventoryManager *invmgr, | ||||||
| 		IGameDef *gamedef | 		IGameDef *gamedef | ||||||
| ): | ): | ||||||
| 	GUIModalMenu(env, parent, id, menumgr), | 	GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr), | ||||||
|  | 	m_device(dev), | ||||||
| 	m_invmgr(invmgr), | 	m_invmgr(invmgr), | ||||||
| 	m_gamedef(gamedef), | 	m_gamedef(gamedef), | ||||||
| 	m_form_src(NULL), | 	m_form_src(NULL), | ||||||
| @@ -698,6 +699,8 @@ void GUIFormSpecMenu::drawMenu() | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	m_pointer = m_device->getCursorControl()->getPosition(); | ||||||
|  | 
 | ||||||
| 	updateSelectedItem(); | 	updateSelectedItem(); | ||||||
| 
 | 
 | ||||||
| 	gui::IGUISkin* skin = Environment->getSkin(); | 	gui::IGUISkin* skin = Environment->getSkin(); | ||||||
| @@ -937,24 +940,15 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) | |||||||
| 			return true; | 			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 | 	if(event.EventType==EET_MOUSE_INPUT_EVENT | ||||||
| 			&& event.MouseInput.Event != EMIE_MOUSE_MOVED) | 			&& event.MouseInput.Event != EMIE_MOUSE_MOVED) | ||||||
| 	{ | 	{ | ||||||
| 		// Mouse event other than movement
 | 		// Mouse event other than movement
 | ||||||
| 
 | 
 | ||||||
| 		v2s32 p(event.MouseInput.X, event.MouseInput.Y); |  | ||||||
| 		m_pointer = p; |  | ||||||
| 
 |  | ||||||
| 		// Get selected item and hovered/clicked item (s)
 | 		// Get selected item and hovered/clicked item (s)
 | ||||||
| 
 | 
 | ||||||
| 		updateSelectedItem(); | 		updateSelectedItem(); | ||||||
| 		ItemSpec s = getItemAtPos(p); | 		ItemSpec s = getItemAtPos(m_pointer); | ||||||
| 
 | 
 | ||||||
| 		Inventory *inv_selected = NULL; | 		Inventory *inv_selected = NULL; | ||||||
| 		Inventory *inv_s = NULL; | 		Inventory *inv_s = NULL; | ||||||
|   | |||||||
| @@ -144,7 +144,7 @@ class GUIFormSpecMenu : public GUIModalMenu | |||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
| 	GUIFormSpecMenu(gui::IGUIEnvironment* env, | 	GUIFormSpecMenu(irr::IrrlichtDevice* dev, | ||||||
| 			gui::IGUIElement* parent, s32 id, | 			gui::IGUIElement* parent, s32 id, | ||||||
| 			IMenuManager *menumgr, | 			IMenuManager *menumgr, | ||||||
| 			InventoryManager *invmgr, | 			InventoryManager *invmgr, | ||||||
| @@ -197,6 +197,7 @@ protected: | |||||||
| 	v2s32 spacing; | 	v2s32 spacing; | ||||||
| 	v2s32 imgsize; | 	v2s32 imgsize; | ||||||
| 	 | 	 | ||||||
|  | 	irr::IrrlichtDevice* m_device; | ||||||
| 	InventoryManager *m_invmgr; | 	InventoryManager *m_invmgr; | ||||||
| 	IGameDef *m_gamedef; | 	IGameDef *m_gamedef; | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -323,7 +323,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, | |||||||
| 		v3s16 camera_np = floatToInt(getEyePosition(), BS); | 		v3s16 camera_np = floatToInt(getEyePosition(), BS); | ||||||
| 		MapNode n = map.getNodeNoEx(camera_np); | 		MapNode n = map.getNodeNoEx(camera_np); | ||||||
| 		if(n.getContent() != CONTENT_IGNORE){ | 		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; | 				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" | #include "mapblock_mesh.h" | ||||||
| #endif | #endif | ||||||
| #include "util/string.h" | #include "util/string.h" | ||||||
|  | #include "util/serialize.h" | ||||||
| 
 | 
 | ||||||
| #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" | #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -77,9 +77,9 @@ void MeshMakeData::fill(MapBlock *block) | |||||||
| 		// Get map
 | 		// Get map
 | ||||||
| 		Map *map = block->getParent(); | 		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; | 			v3s16 bp = m_blockpos + dir; | ||||||
| 			MapBlock *b = map->getBlockNoCreateNoEx(bp); | 			MapBlock *b = map->getBlockNoCreateNoEx(bp); | ||||||
| 			if(b) | 			if(b) | ||||||
|   | |||||||
| @@ -39,6 +39,10 @@ static void collectMods(const std::string &modspath, | |||||||
| 		if(!dirlist[j].dir) | 		if(!dirlist[j].dir) | ||||||
| 			continue; | 			continue; | ||||||
| 		std::string modname = dirlist[j].name; | 		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; | 		std::string modpath = modspath + DIR_DELIM + modname; | ||||||
| 		TRACESTREAM(<<indentation<<"collectMods: "<<modname<<" at \""<<modpath<<"\""<<std::endl); | 		TRACESTREAM(<<indentation<<"collectMods: "<<modname<<" at \""<<modpath<<"\""<<std::endl); | ||||||
| 		// Handle modpacks (defined by containing modpack.txt)
 | 		// 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(); | 	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
 | 	writeU8(os, 6); // version
 | ||||||
| 	os<<serializeString(name); | 	os<<serializeString(name); | ||||||
| 	writeU16(os, groups.size()); | 	writeU16(os, groups.size()); | ||||||
| @@ -271,8 +276,11 @@ void ContentFeatures::serialize(std::ostream &os) | |||||||
| void ContentFeatures::deSerialize(std::istream &is) | void ContentFeatures::deSerialize(std::istream &is) | ||||||
| { | { | ||||||
| 	int version = readU8(is); | 	int version = readU8(is); | ||||||
| 	if(version != 6) | 	if(version != 6){ | ||||||
| 		throw SerializationError("unsupported ContentFeatures version"); | 		deSerializeOld(is, version); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	name = deSerializeString(is); | 	name = deSerializeString(is); | ||||||
| 	groups.clear(); | 	groups.clear(); | ||||||
| 	u32 groups_size = readU16(is); | 	u32 groups_size = readU16(is); | ||||||
| @@ -693,7 +701,7 @@ public: | |||||||
| 		} | 		} | ||||||
| #endif | #endif | ||||||
| 	} | 	} | ||||||
| 	void serialize(std::ostream &os) | 	void serialize(std::ostream &os, u16 protocol_version) | ||||||
| 	{ | 	{ | ||||||
| 		writeU8(os, 1); // version
 | 		writeU8(os, 1); // version
 | ||||||
| 		u16 count = 0; | 		u16 count = 0; | ||||||
| @@ -709,7 +717,7 @@ public: | |||||||
| 			// Wrap it in a string to allow different lengths without
 | 			// Wrap it in a string to allow different lengths without
 | ||||||
| 			// strict version incompatibilities
 | 			// strict version incompatibilities
 | ||||||
| 			std::ostringstream wrapper_os(std::ios::binary); | 			std::ostringstream wrapper_os(std::ios::binary); | ||||||
| 			f->serialize(wrapper_os); | 			f->serialize(wrapper_os, protocol_version); | ||||||
| 			os2<<serializeString(wrapper_os.str()); | 			os2<<serializeString(wrapper_os.str()); | ||||||
| 			count++; | 			count++; | ||||||
| 		} | 		} | ||||||
| @@ -766,3 +774,122 @@ IWritableNodeDefManager* createNodeDefManager() | |||||||
| 	return new CNodeDefManager(); | 	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(); | ||||||
| 	~ContentFeatures(); | 	~ContentFeatures(); | ||||||
| 	void reset(); | 	void reset(); | ||||||
| 	void serialize(std::ostream &os); | 	void serialize(std::ostream &os, u16 protocol_version); | ||||||
| 	void deSerialize(std::istream &is); | 	void deSerialize(std::istream &is); | ||||||
|  | 	void serializeOld(std::ostream &os, u16 protocol_version); | ||||||
|  | 	void deSerializeOld(std::istream &is, int version); | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 		Some handy methods | 		Some handy methods | ||||||
| @@ -264,7 +266,7 @@ public: | |||||||
| 			const=0; | 			const=0; | ||||||
| 	virtual const ContentFeatures& get(const std::string &name) 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 | class IWritableNodeDefManager : public INodeDefManager | ||||||
| @@ -305,7 +307,7 @@ public: | |||||||
| 	*/ | 	*/ | ||||||
| 	virtual void updateTextures(ITextureSource *tsrc)=0; | 	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; | 	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.MinEdge); | ||||||
| 	writeV3F1000(os, collisionbox.MaxEdge); | 	writeV3F1000(os, collisionbox.MaxEdge); | ||||||
| 	os<<serializeString(visual); | 	os<<serializeString(visual); | ||||||
| 	os<<serializeString(mesh); |  | ||||||
| 	writeV2F1000(os, visual_size); | 	writeV2F1000(os, visual_size); | ||||||
| 	writeU16(os, textures.size()); | 	writeU16(os, textures.size()); | ||||||
| 	for(u32 i=0; i<textures.size(); i++){ | 	for(u32 i=0; i<textures.size(); i++){ | ||||||
| 		os<<serializeString(textures[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, spritediv); | ||||||
| 	writeV2S16(os, initial_sprite_basepos); | 	writeV2S16(os, initial_sprite_basepos); | ||||||
| 	writeU8(os, is_visible); | 	writeU8(os, is_visible); | ||||||
| 	writeU8(os, makes_footstep_sound); | 	writeU8(os, makes_footstep_sound); | ||||||
| 	writeF1000(os, automatic_rotate); | 	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) | void ObjectProperties::deSerialize(std::istream &is) | ||||||
| { | { | ||||||
| 	int version = readU8(is); | 	int version = readU8(is); | ||||||
| 	if(version != 1) throw SerializationError( | 	if(version == 1) | ||||||
| 			"unsupported ObjectProperties version"); | 	{ | ||||||
| 	hp_max = readS16(is); | 		try{ | ||||||
| 	physical = readU8(is); | 			hp_max = readS16(is); | ||||||
| 	weight = readF1000(is); | 			physical = readU8(is); | ||||||
| 	collisionbox.MinEdge = readV3F1000(is); | 			weight = readF1000(is); | ||||||
| 	collisionbox.MaxEdge = readV3F1000(is); | 			collisionbox.MinEdge = readV3F1000(is); | ||||||
| 	visual = deSerializeString(is); | 			collisionbox.MaxEdge = readV3F1000(is); | ||||||
| 	mesh = deSerializeString(is); | 			visual = deSerializeString(is); | ||||||
| 	visual_size = readV2F1000(is); | 			visual_size = readV2F1000(is); | ||||||
| 	textures.clear(); | 			textures.clear(); | ||||||
| 	u32 texture_count = readU16(is); | 			u32 texture_count = readU16(is); | ||||||
| 	for(u32 i=0; i<texture_count; i++){ | 			for(u32 i=0; i<texture_count; i++){ | ||||||
| 		textures.push_back(deSerializeString(is)); | 				textures.push_back(deSerializeString(is)); | ||||||
|  | 			} | ||||||
|  | 			spritediv = readV2S16(is); | ||||||
|  | 			initial_sprite_basepos = readV2S16(is); | ||||||
|  | 			is_visible = readU8(is); | ||||||
|  | 			makes_footstep_sound = readU8(is); | ||||||
|  | 			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){} | ||||||
| 	} | 	} | ||||||
| 	u32 color_count = readU16(is); | 	else | ||||||
| 	for(u32 i=0; i<color_count; i++){ | 	{ | ||||||
| 		colors.push_back(readARGB8(is)); | 		throw SerializationError("unsupported ObjectProperties version"); | ||||||
| 	} | 	} | ||||||
| 	spritediv = readV2S16(is); |  | ||||||
| 	initial_sprite_basepos = readV2S16(is); |  | ||||||
| 	is_visible = readU8(is); |  | ||||||
| 	makes_footstep_sound = readU8(is); |  | ||||||
| 	try{ |  | ||||||
| 		automatic_rotate = readF1000(is); |  | ||||||
| 	}catch(SerializationError &e){} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|   | |||||||
| @@ -5576,6 +5576,19 @@ bool scriptapi_on_chat_message(lua_State *L, const std::string &name, | |||||||
| 	return ate; | 	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) | void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player) | ||||||
| { | { | ||||||
| 	realitycheck(L); | 	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, | void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp, | ||||||
| 		u32 blockseed); | 		u32 blockseed); | ||||||
| 
 | 
 | ||||||
|  | /* server */ | ||||||
|  | void scriptapi_on_shutdown(lua_State *L); | ||||||
|  | 
 | ||||||
| /* misc */ | /* misc */ | ||||||
| void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player); | void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player); | ||||||
| void scriptapi_on_dieplayer(lua_State *L, ServerActiveObject *player); | void scriptapi_on_dieplayer(lua_State *L, ServerActiveObject *player); | ||||||
|   | |||||||
							
								
								
									
										104
									
								
								src/server.cpp
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								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/pointedthing.h" | ||||||
| #include "util/mathconstants.h" | #include "util/mathconstants.h" | ||||||
| #include "rollback.h" | #include "rollback.h" | ||||||
|  | #include "util/serialize.h" | ||||||
| 
 | 
 | ||||||
| #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" | #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" | ||||||
| 
 | 
 | ||||||
| @@ -1111,7 +1112,17 @@ 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); | 		JMutexAutoLock envlock(m_env_mutex); | ||||||
| 
 | 
 | ||||||
| @@ -1143,14 +1154,6 @@ Server::~Server() | |||||||
| 			i = m_clients.getIterator(); | 			i = m_clients.getIterator(); | ||||||
| 			i.atEnd() == false; i++) | 			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 client
 | ||||||
| 			delete i.getNode()->getValue(); | 			delete i.getNode()->getValue(); | ||||||
| 		} | 		} | ||||||
| @@ -1567,7 +1570,7 @@ void Server::AsyncRunStep() | |||||||
| 				 | 				 | ||||||
| 				if(obj) | 				if(obj) | ||||||
| 					data_buffer.append(serializeLongString( | 					data_buffer.append(serializeLongString( | ||||||
| 							obj->getClientInitializationData())); | 							obj->getClientInitializationData(client->net_proto_version))); | ||||||
| 				else | 				else | ||||||
| 					data_buffer.append(serializeLongString("")); | 					data_buffer.append(serializeLongString("")); | ||||||
| 
 | 
 | ||||||
| @@ -2037,40 +2040,74 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |||||||
| 			Read and check network protocol version | 			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) | 		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; | 		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; | 					<<std::endl; | ||||||
| 			SendAccessDenied(m_con, peer_id, std::wstring( | 			SendAccessDenied(m_con, peer_id, std::wstring( | ||||||
| 					L"Your client's version is not supported.\n" | 					L"Your client's version is not supported.\n" | ||||||
| 					L"Server version is ") | 					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; | 			return; | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		if(g_settings->getBool("strict_protocol_version_checking")) | 		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" | 				actionstream<<"Server: A mismatched (strict) client tried to " | ||||||
| 						<<" from "<<addr_s<<std::endl; | 						<<"connect from "<<addr_s<<std::endl; | ||||||
| 				SendAccessDenied(m_con, peer_id, std::wstring( | 				SendAccessDenied(m_con, peer_id, std::wstring( | ||||||
| 						L"Your client's version is not supported.\n" | 						L"Your client's version is not supported.\n" | ||||||
| 						L"Server version is ") | 						L"Server version is ") | ||||||
| 						+ narrow_to_wide(VERSION_STRING) + L",\n" | 						+ narrow_to_wide(VERSION_STRING) + L",\n" | ||||||
| 						+ L"server's PROTOCOL_VERSION is " | 						+ L"server's PROTOCOL_VERSION (strict) is " | ||||||
| 						+ narrow_to_wide(itos(PROTOCOL_VERSION)) | 						+ narrow_to_wide(itos(LATEST_PROTOCOL_VERSION)) | ||||||
| 						+ L", client's PROTOCOL_VERSION is " | 						+ 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; | 				return; | ||||||
| 			} | 			} | ||||||
| @@ -2212,11 +2249,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |||||||
| 			Answer with a TOCLIENT_INIT | 			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); | 			writeU16(&reply[0], TOCLIENT_INIT); | ||||||
| 			writeU8(&reply[2], deployed); | 			writeU8(&reply[2], deployed); | ||||||
| 			writeV3S16(&reply[2+1], floatToInt(playersao->getPlayer()->getPosition()+v3f(0,BS/2,0), BS)); | 			writeV3S16(&reply[2+1], floatToInt(playersao->getPlayer()->getPosition()+v3f(0,BS/2,0), BS)); | ||||||
| 			writeU64(&reply[2+1+6], m_env->getServerMap().getSeed()); | 			writeU64(&reply[2+1+6], m_env->getServerMap().getSeed()); | ||||||
|  | 			writeF1000(&reply[2+1+6+8], g_settings->getFloat("dedicated_server_step")); | ||||||
| 			 | 			 | ||||||
| 			// Send as reliable
 | 			// Send as reliable
 | ||||||
| 			m_con.Send(peer_id, 0, reply, true); | 			m_con.Send(peer_id, 0, reply, true); | ||||||
| @@ -2242,8 +2280,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		getClient(peer_id)->serialization_version | 		RemoteClient *client = getClient(peer_id); | ||||||
| 				= getClient(peer_id)->pending_serialization_version; | 		client->serialization_version = | ||||||
|  | 				getClient(peer_id)->pending_serialization_version; | ||||||
| 
 | 
 | ||||||
| 		/*
 | 		/*
 | ||||||
| 			Send some initialization data | 			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); | 		SendItemDef(m_con, peer_id, m_itemdef); | ||||||
| 		 | 		 | ||||||
| 		// Send node definitions
 | 		// Send node definitions
 | ||||||
| 		SendNodeDef(m_con, peer_id, m_nodedef); | 		SendNodeDef(m_con, peer_id, m_nodedef, client->net_proto_version); | ||||||
| 		 | 		 | ||||||
| 		// Send media announcement
 | 		// Send media announcement
 | ||||||
| 		sendMediaAnnouncement(peer_id); | 		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
 | 		// 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(command == TOSERVER_PLAYERPOS) | ||||||
| 	{ | 	{ | ||||||
| 		if(datasize < 2+12+12+4+4+4) | 		if(datasize < 2+12+12+4+4) | ||||||
| 			return; | 			return; | ||||||
| 	 | 	 | ||||||
| 		u32 start = 0; | 		u32 start = 0; | ||||||
| @@ -2377,7 +2417,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |||||||
| 		v3s32 ss = readV3S32(&data[start+2+12]); | 		v3s32 ss = readV3S32(&data[start+2+12]); | ||||||
| 		f32 pitch = (f32)readS32(&data[2+12+12]) / 100.0; | 		f32 pitch = (f32)readS32(&data[2+12+12]) / 100.0; | ||||||
| 		f32 yaw = (f32)readS32(&data[2+12+12+4]) / 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 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.); | 		v3f speed((f32)ss.X/100., (f32)ss.Y/100., (f32)ss.Z/100.); | ||||||
| 		pitch = wrapDegrees(pitch); | 		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, | void Server::SendNodeDef(con::Connection &con, u16 peer_id, | ||||||
| 		INodeDefManager *nodedef) | 		INodeDefManager *nodedef, u16 protocol_version) | ||||||
| { | { | ||||||
| 	DSTACK(__FUNCTION_NAME); | 	DSTACK(__FUNCTION_NAME); | ||||||
| 	std::ostringstream os(std::ios_base::binary); | 	std::ostringstream os(std::ios_base::binary); | ||||||
| @@ -3520,7 +3562,7 @@ void Server::SendNodeDef(con::Connection &con, u16 peer_id, | |||||||
| 	*/ | 	*/ | ||||||
| 	writeU16(os, TOCLIENT_NODEDEF); | 	writeU16(os, TOCLIENT_NODEDEF); | ||||||
| 	std::ostringstream tmp_os(std::ios::binary); | 	std::ostringstream tmp_os(std::ios::binary); | ||||||
| 	nodedef->serialize(tmp_os); | 	nodedef->serialize(tmp_os, protocol_version); | ||||||
| 	std::ostringstream tmp_os2(std::ios::binary); | 	std::ostringstream tmp_os2(std::ios::binary); | ||||||
| 	compressZlib(tmp_os.str(), tmp_os2); | 	compressZlib(tmp_os.str(), tmp_os2); | ||||||
| 	os<<serializeLongString(tmp_os2.str()); | 	os<<serializeLongString(tmp_os2.str()); | ||||||
|   | |||||||
| @@ -602,7 +602,7 @@ private: | |||||||
| 	static void SendItemDef(con::Connection &con, u16 peer_id, | 	static void SendItemDef(con::Connection &con, u16 peer_id, | ||||||
| 			IItemDefManager *itemdef); | 			IItemDefManager *itemdef); | ||||||
| 	static void SendNodeDef(con::Connection &con, u16 peer_id, | 	static void SendNodeDef(con::Connection &con, u16 peer_id, | ||||||
| 			INodeDefManager *nodedef); | 			INodeDefManager *nodedef, u16 protocol_version); | ||||||
| 	 | 	 | ||||||
| 	/*
 | 	/*
 | ||||||
| 		Non-static send methods. | 		Non-static send methods. | ||||||
|   | |||||||
| @@ -118,7 +118,7 @@ public: | |||||||
| 		The return value of this is passed to the client-side object | 		The return value of this is passed to the client-side object | ||||||
| 		when it is created | 		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 | 		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 "irrlichttypes_bloated.h" | ||||||
| #include <string> | #include <string> | ||||||
| #include <sstream> | #include <sstream> | ||||||
| #include "util/serialize.h" | #include "debug.h" | ||||||
| 
 | 
 | ||||||
| struct StaticObject | struct StaticObject | ||||||
| { | { | ||||||
| @@ -43,33 +43,8 @@ struct StaticObject | |||||||
| 	{ | 	{ | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void serialize(std::ostream &os) | 	void serialize(std::ostream &os); | ||||||
| 	{ | 	void deSerialize(std::istream &is, u8 version); | ||||||
| 		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); |  | ||||||
| 	} |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class StaticObjectList | class StaticObjectList | ||||||
| @@ -110,47 +85,8 @@ public: | |||||||
| 		m_active.remove(id); | 		m_active.remove(id); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void serialize(std::ostream &os) | 	void serialize(std::ostream &os); | ||||||
| 	{ | 	void deSerialize(std::istream &is); | ||||||
| 		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); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	 | 	 | ||||||
| 	/*
 | 	/*
 | ||||||
| 		NOTE: When an object is transformed to active, it is removed | 		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/numeric.h" | ||||||
| #include "util/serialize.h" | #include "util/serialize.h" | ||||||
| #include "noise.h" // PseudoRandom used for random data for compression
 | #include "noise.h" // PseudoRandom used for random data for compression
 | ||||||
|  | #include "clientserver.h" // LATEST_PROTOCOL_VERSION
 | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
| 	Asserts that the exception occurs | 	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 | struct TestCompress: public TestBase | ||||||
| { | { | ||||||
| 	void Run() | 	void Run() | ||||||
| @@ -1736,6 +1757,7 @@ void run_tests() | |||||||
| 	TEST(TestSettings); | 	TEST(TestSettings); | ||||||
| 	TEST(TestCompress); | 	TEST(TestCompress); | ||||||
| 	TEST(TestSerialization); | 	TEST(TestSerialization); | ||||||
|  | 	TEST(TestNodedefSerialization); | ||||||
| 	TESTPARAMS(TestMapNode, ndef); | 	TESTPARAMS(TestMapNode, ndef); | ||||||
| 	TESTPARAMS(TestVoxelManipulator, ndef); | 	TESTPARAMS(TestVoxelManipulator, ndef); | ||||||
| 	TESTPARAMS(TestVoxelAlgorithms, ndef); | 	TESTPARAMS(TestVoxelAlgorithms, ndef); | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								src/tile.cpp
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/tile.cpp
									
									
									
									
									
								
							| @@ -372,6 +372,18 @@ public: | |||||||
| 	// Update new texture pointer and texture coordinates to an
 | 	// Update new texture pointer and texture coordinates to an
 | ||||||
| 	// AtlasPointer based on it's texture id
 | 	// AtlasPointer based on it's texture id
 | ||||||
| 	void updateAP(AtlasPointer &ap); | 	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.
 | 	// Processes queued texture requests from other threads.
 | ||||||
| 	// Shall be called from the main thread.
 | 	// Shall be called from the main thread.
 | ||||||
| @@ -400,6 +412,9 @@ private: | |||||||
| 	// This should be only accessed from the main thread
 | 	// This should be only accessed from the main thread
 | ||||||
| 	SourceImageCache m_sourcecache; | 	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.
 | 	// A texture id is index in this array.
 | ||||||
| 	// The first position contains a NULL texture.
 | 	// The first position contains a NULL texture.
 | ||||||
| 	core::array<SourceAtlasPointer> m_atlaspointer_cache; | 	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); | 	assert(get_current_thread_id() == m_main_thread); | ||||||
| 	 | 	 | ||||||
| 	m_sourcecache.insert(name, img, true, m_device->getVideoDriver()); | 	m_sourcecache.insert(name, img, true, m_device->getVideoDriver()); | ||||||
|  | 	m_source_image_existence.set(name, true); | ||||||
| } | } | ||||||
| 	 | 	 | ||||||
| void TextureSource::rebuildImagesAndTextures() | void TextureSource::rebuildImagesAndTextures() | ||||||
|   | |||||||
| @@ -131,6 +131,7 @@ public: | |||||||
| 	virtual IrrlichtDevice* getDevice() | 	virtual IrrlichtDevice* getDevice() | ||||||
| 		{return NULL;} | 		{return NULL;} | ||||||
| 	virtual void updateAP(AtlasPointer &ap){}; | 	virtual void updateAP(AtlasPointer &ap){}; | ||||||
|  | 	virtual bool isKnownSourceImage(const std::string &name)=0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class IWritableTextureSource : public ITextureSource | class IWritableTextureSource : public ITextureSource | ||||||
| @@ -149,6 +150,7 @@ public: | |||||||
| 	virtual IrrlichtDevice* getDevice() | 	virtual IrrlichtDevice* getDevice() | ||||||
| 		{return NULL;} | 		{return NULL;} | ||||||
| 	virtual void updateAP(AtlasPointer &ap){}; | 	virtual void updateAP(AtlasPointer &ap){}; | ||||||
|  | 	virtual bool isKnownSourceImage(const std::string &name)=0; | ||||||
| 
 | 
 | ||||||
| 	virtual void processQueue()=0; | 	virtual void processQueue()=0; | ||||||
| 	virtual void insertSourceImage(const std::string &name, video::IImage *img)=0; | 	virtual void insertSourceImage(const std::string &name, video::IImage *img)=0; | ||||||
|   | |||||||
| @@ -222,7 +222,7 @@ public: | |||||||
| 	/*
 | 	/*
 | ||||||
| 		Copies whole buffer | 		Copies whole buffer | ||||||
| 	*/ | 	*/ | ||||||
| 	SharedBuffer(T *t, unsigned int size) | 	SharedBuffer(const T *t, unsigned int size) | ||||||
| 	{ | 	{ | ||||||
| 		m_size = size; | 		m_size = size; | ||||||
| 		if(m_size != 0) | 		if(m_size != 0) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user