diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e7c1f761..0bce897bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string") # Also remember to set PROTOCOL_VERSION in clientserver.h when releasing set(VERSION_MAJOR 0) set(VERSION_MINOR 4) -set(VERSION_PATCH 3) +set(VERSION_PATCH 4-dev) if(VERSION_EXTRA) set(VERSION_PATCH ${VERSION_PATCH}-${VERSION_EXTRA}) endif() diff --git a/builtin/chatcommands.lua b/builtin/chatcommands.lua index f25a276ea..f41f9afe4 100644 --- a/builtin/chatcommands.lua +++ b/builtin/chatcommands.lua @@ -138,6 +138,7 @@ minetest.register_chatcommand("grant", { return end minetest.set_player_privs(grantname, privs) + minetest.log(name..' granted ('..minetest.privs_to_string(grantprivs, ', ')..') privileges to '..grantname) minetest.chat_send_player(name, "Privileges of "..grantname..": "..minetest.privs_to_string(minetest.get_player_privs(grantname), ' ')) if grantname ~= name then minetest.chat_send_player(grantname, name.." granted you privileges: "..minetest.privs_to_string(grantprivs, ' ')) @@ -175,6 +176,7 @@ minetest.register_chatcommand("revoke", { end end minetest.set_player_privs(revokename, privs) + minetest.log(name..' revoked ('..minetest.privs_to_string(revokeprivs, ', ')..') privileges from '..revokename) minetest.chat_send_player(name, "Privileges of "..revokename..": "..minetest.privs_to_string(minetest.get_player_privs(revokename), ' ')) if revokename ~= name then minetest.chat_send_player(revokename, name.." revoked privileges from you: "..minetest.privs_to_string(revokeprivs, ' ')) diff --git a/builtin/misc_register.lua b/builtin/misc_register.lua index 77c594de2..f9c06a02a 100644 --- a/builtin/misc_register.lua +++ b/builtin/misc_register.lua @@ -303,6 +303,7 @@ end minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration() minetest.registered_globalsteps, minetest.register_globalstep = make_registration() +minetest.registered_on_shutdown, minetest.register_on_shutdown = make_registration() minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration() minetest.registered_on_placenodes, minetest.register_on_placenode = make_registration() minetest.registered_on_dignodes, minetest.register_on_dignode = make_registration() diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 0c093b7ee..e32efc6df 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1,4 +1,4 @@ -Minetest Lua Modding API Reference 0.4.3 +Minetest Lua Modding API Reference 0.4.4 ========================================== More information at http://c55.me/minetest/ @@ -792,6 +792,11 @@ minetest.register_craft(recipe) Global callback registration functions: (Call these only at load time) minetest.register_globalstep(func(dtime)) ^ Called every server step, usually interval of 0.05s +minetest.register_on_shutdown(func()) +^ Called before server shutdown +^ WARNING: If the server terminates abnormally (i.e. crashes), the registered + callbacks WILL LIKELY NOT BE RUN. Data should be saved at + semi-frequent intervals as well as on server shutdown. minetest.register_on_placenode(func(pos, newnode, placer, oldnode)) ^ Called when a node has been placed ^ Deprecated: Use on_construct or after_place_node in node definition instead diff --git a/minetest.conf.example b/minetest.conf.example index 3f292c01e..071b97c65 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -139,8 +139,8 @@ #motd = Welcome to this awesome Minetest server! # Maximum number of players connected simultaneously #max_users = 100 -# Set to false to allow old clients to connect -#strict_protocol_version_checking = true +# Set to true to disallow old clients from connecting +#strict_protocol_version_checking = false # Set to true to enable creative mode (unlimited inventory) #creative_mode = false # Enable players getting damage and dying @@ -194,7 +194,12 @@ # To reduce lag, block transfers are slowed down when a player is building something. # This determines how long they are slowed down after placing or removing a node. #full_block_send_enable_min_time_from_building = 2.0 -# Length of a server tick in dedicated server -#dedicated_server_step = 0.05 +# Length of a server tick and the interval at which objects are generally updated over network +#dedicated_server_step = 0.1 # Can be set to true to disable shutting down on invalid world data #ignore_world_load_errors = false +# Congestion control parameters +# time in seconds, rate in ~500B packets +#congestion_control_aim_rtt = 0.2 +#congestion_control_max_rate = 400 +#congestion_control_min_rate = 10 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8cdaa510d..e1639b46f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -202,6 +202,8 @@ set(common_SRCS sha1.cpp base64.cpp ban.cpp + clientserver.cpp + staticobject.cpp util/serialize.cpp util/directiontables.cpp util/numeric.cpp diff --git a/src/client.cpp b/src/client.cpp index f72c4b654..4117a9130 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -42,6 +42,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/string.h" #include "hex.h" #include "IMeshCache.h" +#include "util/serialize.h" static std::string getMediaCacheDir() { @@ -266,6 +267,7 @@ Client::Client( m_time_of_day_set(false), m_last_time_of_day_f(-1), m_time_of_day_update_timer(0), + m_recommended_send_interval(0.1), m_removed_sounds_check_timer(0) { m_packetcounter_timer = 0.0; @@ -499,8 +501,9 @@ void Client::step(float dtime) // [2] u8 SER_FMT_VER_HIGHEST // [3] u8[20] player_name // [23] u8[28] password (new in some version) - // [51] u16 client network protocol version (new in some version) - SharedBuffer data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2); + // [51] u16 minimum supported network protocol version (added sometime) + // [53] u16 maximum supported network protocol version (added later than the previous one) + SharedBuffer data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2); writeU16(&data[0], TOSERVER_INIT); writeU8(&data[2], SER_FMT_VER_HIGHEST); @@ -513,8 +516,8 @@ void Client::step(float dtime) memset((char*)&data[23], 0, PASSWORD_SIZE); snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str()); - // This should be incremented in each version - writeU16(&data[51], PROTOCOL_VERSION); + writeU16(&data[51], CLIENT_PROTOCOL_VERSION_MIN); + writeU16(&data[53], CLIENT_PROTOCOL_VERSION_MAX); // Send as unreliable Send(0, data, false); @@ -656,7 +659,7 @@ void Client::step(float dtime) { float &counter = m_playerpos_send_timer; counter += dtime; - if(counter >= 0.2) + if(counter >= m_recommended_send_interval) { counter = 0.0; sendPlayerPos(); @@ -1020,6 +1023,14 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) m_map_seed = readU64(&data[2+1+6]); infostream<<"Client: received map seed: "<= 2+1+6+8+4) + { + // Get map seed + m_recommended_send_interval = readF1000(&data[2+1+6+8]); + infostream<<"Client: received recommended send interval " + < + +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 makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed) +{ + SharedBuffer data(2+2+4); + writeU16(&data[0], TOCLIENT_TIME_OF_DAY); + writeU16(&data[2], time); + writeF1000(&data[4], time_speed); + return data; +} + diff --git a/src/clientserver.h b/src/clientserver.h index ba535a66b..6f9396c02 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -1,6 +1,6 @@ /* Minetest-c55 -Copyright (C) 2010 celeron55, Perttu Ahola +Copyright (C) 2010-2012 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -20,7 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef CLIENTSERVER_HEADER #define CLIENTSERVER_HEADER -#include "util/serialize.h" +#include "util/pointer.h" + +SharedBuffer makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed); /* changes by PROTOCOL_VERSION: @@ -73,10 +75,21 @@ with this program; if not, write to the Free Software Foundation, Inc., GENERIC_CMD_SET_ANIMATION GENERIC_CMD_SET_BONE_POSITION GENERIC_CMD_SET_ATTACHMENT + PROTOCOL_VERSION 15: + Serialization format changes */ -#define PROTOCOL_VERSION 14 +#define LATEST_PROTOCOL_VERSION 15 +// Server's supported network protocol range +#define SERVER_PROTOCOL_VERSION_MIN 13 +#define SERVER_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION + +// Client's supported network protocol range +#define CLIENT_PROTOCOL_VERSION_MIN 13 +#define CLIENT_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION + +// Constant that differentiates the protocol from random data and other protocols #define PROTOCOL_ID 0x4f457403 #define PASSWORD_SIZE 28 // Maximum password length. Allows for @@ -95,6 +108,7 @@ enum ToClientCommand [2] u8 deployed version [3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd [12] u64 map seed (new as of 2011-02-27) + [20] f1000 recommended send interval (in seconds) (new as of 14) NOTE: The position in here is deprecated; position is explicitly sent afterwards @@ -350,7 +364,8 @@ enum ToServerCommand [2] u8 SER_FMT_VER_HIGHEST [3] u8[20] player_name [23] u8[28] password (new in some version) - [51] u16 client network protocol version (new in some version) + [51] u16 minimum supported network protocol version (added sometime) + [53] u16 maximum supported network protocol version (added later than the previous one) */ TOSERVER_INIT2 = 0x11, @@ -558,14 +573,5 @@ enum ToServerCommand }; -inline SharedBuffer makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed) -{ - SharedBuffer data(2+2+4); - writeU16(&data[0], TOCLIENT_TIME_OF_DAY); - writeU16(&data[2], time); - writeF1000(&data[4], time_speed); - return data; -} - #endif diff --git a/src/connection.cpp b/src/connection.cpp index 4f5d095e5..ed5a752be 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/serialize.h" #include "util/numeric.h" #include "util/string.h" +#include "settings.h" namespace con { @@ -466,7 +467,10 @@ Peer::Peer(u16 a_id, Address a_address): m_sendtime_accu(0), m_max_packets_per_second(10), m_num_sent(0), - m_max_num_sent(0) + m_max_num_sent(0), + congestion_control_aim_rtt(0.2), + congestion_control_max_rate(400), + congestion_control_min_rate(10) { } Peer::~Peer() @@ -477,15 +481,15 @@ void Peer::reportRTT(float rtt) { if(rtt >= 0.0){ if(rtt < 0.01){ - if(m_max_packets_per_second < 400) + if(m_max_packets_per_second < congestion_control_max_rate) m_max_packets_per_second += 10; - } else if(rtt < 0.2){ - if(m_max_packets_per_second < 100) + } else if(rtt < congestion_control_aim_rtt){ + if(m_max_packets_per_second < congestion_control_max_rate) m_max_packets_per_second += 2; } else { m_max_packets_per_second *= 0.8; - if(m_max_packets_per_second < 10) - m_max_packets_per_second = 10; + if(m_max_packets_per_second < congestion_control_min_rate) + m_max_packets_per_second = congestion_control_min_rate; } } @@ -891,12 +895,24 @@ void Connection::receive() void Connection::runTimeouts(float dtime) { + float congestion_control_aim_rtt + = g_settings->getFloat("congestion_control_aim_rtt"); + float congestion_control_max_rate + = g_settings->getFloat("congestion_control_max_rate"); + float congestion_control_min_rate + = g_settings->getFloat("congestion_control_min_rate"); + core::list timeouted_peers; core::map::Iterator j; j = m_peers.getIterator(); for(; j.atEnd() == false; j++) { 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 diff --git a/src/connection.h b/src/connection.h index f88e813a3..f99cd1bf9 100644 --- a/src/connection.h +++ b/src/connection.h @@ -394,7 +394,11 @@ public: float m_max_packets_per_second; int m_num_sent; int m_max_num_sent; - + + // Updated from configuration by Connection + float congestion_control_aim_rtt; + float congestion_control_max_rate; + float congestion_control_min_rate; private: }; diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 339c9f248..8229ded62 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -647,22 +647,36 @@ public: { infostream<<"GenericCAO: Got init data"<getMesh(), video::SColor(255,li,li,li)); + + m_meshnode->setMaterialFlag(video::EMF_LIGHTING, false); + m_meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); + m_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF); + m_meshnode->setMaterialFlag(video::EMF_FOG_ENABLE, true); } else if(m_prop.visual == "mesh"){ infostream<<"GenericCAO::addToScene(): mesh"<getMesh(), video::SColor(255,li,li,li)); + + m_animated_meshnode->setMaterialFlag(video::EMF_LIGHTING, false); + m_animated_meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); + m_animated_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF); + m_animated_meshnode->setMaterialFlag(video::EMF_FOG_ENABLE, true); } else errorstream<<"GenericCAO::addToScene(): Could not load mesh "< >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ - os<= 14) + { + writeU8(os, 1); // version + os< >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ + os<getBool("unlimited_player_transfer_distance"); } -std::string PlayerSAO::getClientInitializationData() +std::string PlayerSAO::getClientInitializationData(u16 protocol_version) { std::ostringstream os(std::ios::binary); - writeU8(os, 0); // version - os<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 - os< >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ - os<= 15) + { + writeU8(os, 1); // version + os<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 + os< >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ + os<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<setDefault("sound_volume", "0.8"); settings->setDefault("desynchronize_mapblock_texture_animation", "true"); + settings->setDefault("mip_map", "false"); + settings->setDefault("anisotropic_filter", "false"); + settings->setDefault("bilinear_filter", "false"); + settings->setDefault("trilinear_filter", "false"); + // Server stuff // "map-dir" doesn't exist by default. settings->setDefault("default_game", "minetest"); settings->setDefault("motd", ""); settings->setDefault("max_users", "100"); - settings->setDefault("strict_protocol_version_checking", "true"); + settings->setDefault("strict_protocol_version_checking", "false"); settings->setDefault("creative_mode", "false"); settings->setDefault("enable_damage", "true"); settings->setDefault("only_peaceful_mobs", "false"); @@ -140,12 +145,10 @@ void set_default_settings(Settings *settings) settings->setDefault("server_unload_unused_data_timeout", "29"); settings->setDefault("server_map_save_interval", "5.3"); settings->setDefault("full_block_send_enable_min_time_from_building", "2.0"); - settings->setDefault("dedicated_server_step", "0.05"); + settings->setDefault("dedicated_server_step", "0.1"); settings->setDefault("ignore_world_load_errors", "false"); - settings->setDefault("mip_map", "false"); - settings->setDefault("anisotropic_filter", "false"); - settings->setDefault("bilinear_filter", "false"); - settings->setDefault("trilinear_filter", "false"); - + settings->setDefault("congestion_control_aim_rtt", "0.2"); + settings->setDefault("congestion_control_max_rate", "400"); + settings->setDefault("congestion_control_min_rate", "10"); } diff --git a/src/environment.cpp b/src/environment.cpp index 2ca4841f6..0473c71e2 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -43,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #endif #include "daynightratio.h" #include "map.h" +#include "util/serialize.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" @@ -328,7 +329,8 @@ ServerEnvironment::ServerEnvironment(ServerMap *map, lua_State *L, m_send_recommended_timer(0), m_active_block_interval_overload_skip(0), m_game_time(0), - m_game_time_fraction_counter(0) + m_game_time_fraction_counter(0), + m_recommended_send_interval(0.1) { } @@ -939,6 +941,11 @@ void ServerEnvironment::step(float dtime) /* Step time of day */ stepTimeOfDay(dtime); + // Update this one + // NOTE: This is kind of funny on a singleplayer game, but doesn't + // really matter that much. + m_recommended_send_interval = g_settings->getFloat("dedicated_server_step"); + /* Increment game time */ @@ -2296,8 +2303,9 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type, { errorstream<<"ClientEnvironment::addActiveObject():" <<" id="<setFormSpec(meta->getString("formspec"), diff --git a/src/genericobject.cpp b/src/genericobject.cpp index 654548fa1..398b07feb 100644 --- a/src/genericobject.cpp +++ b/src/genericobject.cpp @@ -92,6 +92,31 @@ std::string gob_cmd_set_sprite( return os.str(); } +std::string gob_cmd_punched(s16 damage, s16 result_hp) +{ + std::ostringstream os(std::ios::binary); + // command + writeU8(os, GENERIC_CMD_PUNCHED); + // damage + writeS16(os, damage); + // result_hp + writeS16(os, result_hp); + return os.str(); +} + +std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups) +{ + std::ostringstream os(std::ios::binary); + writeU8(os, GENERIC_CMD_UPDATE_ARMOR_GROUPS); + writeU16(os, armor_groups.size()); + for(ItemGroupList::const_iterator i = armor_groups.begin(); + i != armor_groups.end(); i++){ + os<first); + writeS16(os, i->second); + } + return os.str(); +} + std::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_blend) { std::ostringstream os(std::ios::binary); @@ -129,29 +154,3 @@ std::string gob_cmd_update_attachment(int parent_id, std::string bone, v3f posit return os.str(); } -std::string gob_cmd_punched(s16 damage, s16 result_hp) -{ - std::ostringstream os(std::ios::binary); - // command - writeU8(os, GENERIC_CMD_PUNCHED); - // damage - writeS16(os, damage); - // result_hp - writeS16(os, result_hp); - return os.str(); -} - -std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups) -{ - std::ostringstream os(std::ios::binary); - writeU8(os, GENERIC_CMD_UPDATE_ARMOR_GROUPS); - writeU16(os, armor_groups.size()); - for(ItemGroupList::const_iterator i = armor_groups.begin(); - i != armor_groups.end(); i++){ - os<first); - writeS16(os, i->second); - } - return os.str(); -} - - diff --git a/src/genericobject.h b/src/genericobject.h index a46a9474f..b69c24b48 100644 --- a/src/genericobject.h +++ b/src/genericobject.h @@ -28,11 +28,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #define GENERIC_CMD_UPDATE_POSITION 1 #define GENERIC_CMD_SET_TEXTURE_MOD 2 #define GENERIC_CMD_SET_SPRITE 3 -#define GENERIC_CMD_SET_ANIMATION 4 -#define GENERIC_CMD_SET_BONE_POSITION 5 -#define GENERIC_CMD_SET_ATTACHMENT 6 -#define GENERIC_CMD_PUNCHED 7 -#define GENERIC_CMD_UPDATE_ARMOR_GROUPS 8 +#define GENERIC_CMD_PUNCHED 4 +#define GENERIC_CMD_UPDATE_ARMOR_GROUPS 5 +#define GENERIC_CMD_SET_ANIMATION 6 +#define GENERIC_CMD_SET_BONE_POSITION 7 +#define GENERIC_CMD_SET_ATTACHMENT 8 #include "object_properties.h" std::string gob_cmd_set_properties(const ObjectProperties &prop); @@ -57,16 +57,16 @@ std::string gob_cmd_set_sprite( bool select_horiz_by_yawpitch ); +std::string gob_cmd_punched(s16 damage, s16 result_hp); + +#include "itemgroup.h" +std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups); + std::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_blend); std::string gob_cmd_update_bone_position(std::string bone, v3f position, v3f rotation); std::string gob_cmd_update_attachment(int parent_id, std::string bone, v3f position, v3f rotation); -std::string gob_cmd_punched(s16 damage, s16 result_hp); - -#include "itemgroup.h" -std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups); - #endif diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 4db020c11..618141d24 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -125,13 +125,14 @@ void drawItemStack(video::IVideoDriver *driver, GUIFormSpecMenu */ -GUIFormSpecMenu::GUIFormSpecMenu(gui::IGUIEnvironment* env, +GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, InventoryManager *invmgr, IGameDef *gamedef ): - GUIModalMenu(env, parent, id, menumgr), + GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr), + m_device(dev), m_invmgr(invmgr), m_gamedef(gamedef), m_form_src(NULL), @@ -698,6 +699,8 @@ void GUIFormSpecMenu::drawMenu() } } + m_pointer = m_device->getCursorControl()->getPosition(); + updateSelectedItem(); gui::IGUISkin* skin = Environment->getSkin(); @@ -937,24 +940,15 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) return true; } } - if(event.EventType==EET_MOUSE_INPUT_EVENT - && event.MouseInput.Event == EMIE_MOUSE_MOVED) - { - // Mouse moved - m_pointer = v2s32(event.MouseInput.X, event.MouseInput.Y); - } if(event.EventType==EET_MOUSE_INPUT_EVENT && event.MouseInput.Event != EMIE_MOUSE_MOVED) { // Mouse event other than movement - v2s32 p(event.MouseInput.X, event.MouseInput.Y); - m_pointer = p; - // Get selected item and hovered/clicked item (s) updateSelectedItem(); - ItemSpec s = getItemAtPos(p); + ItemSpec s = getItemAtPos(m_pointer); Inventory *inv_selected = NULL; Inventory *inv_s = NULL; diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 890b54d61..e6a2efe42 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -144,7 +144,7 @@ class GUIFormSpecMenu : public GUIModalMenu }; public: - GUIFormSpecMenu(gui::IGUIEnvironment* env, + GUIFormSpecMenu(irr::IrrlichtDevice* dev, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, InventoryManager *invmgr, @@ -197,6 +197,7 @@ protected: v2s32 spacing; v2s32 imgsize; + irr::IrrlichtDevice* m_device; InventoryManager *m_invmgr; IGameDef *m_gamedef; diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 63400cc29..17c4cdeb9 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -323,7 +323,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, v3s16 camera_np = floatToInt(getEyePosition(), BS); MapNode n = map.getNodeNoEx(camera_np); if(n.getContent() != CONTENT_IGNORE){ - if(nodemgr->get(n).walkable){ + if(nodemgr->get(n).walkable && nodemgr->get(n).solidness == 2){ camera_barely_in_ceiling = true; } } diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 2ae6e9bd7..e9c8fadff 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapblock_mesh.h" #endif #include "util/string.h" +#include "util/serialize.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp index 9ae9b21c0..fdeb31f4d 100644 --- a/src/mapblock_mesh.cpp +++ b/src/mapblock_mesh.cpp @@ -77,9 +77,9 @@ void MeshMakeData::fill(MapBlock *block) // Get map Map *map = block->getParent(); - for(u16 i=0; i<6; i++) + for(u16 i=0; i<26; i++) { - const v3s16 &dir = g_6dirs[i]; + const v3s16 &dir = g_26dirs[i]; v3s16 bp = m_blockpos + dir; MapBlock *b = map->getBlockNoCreateNoEx(bp); if(b) diff --git a/src/mods.cpp b/src/mods.cpp index c2bb907c2..08e8e276f 100644 --- a/src/mods.cpp +++ b/src/mods.cpp @@ -39,6 +39,10 @@ static void collectMods(const std::string &modspath, if(!dirlist[j].dir) continue; std::string modname = dirlist[j].name; + // Ignore all directories beginning with a ".", especially + // VCS directories like ".git" or ".svn" + if(modname[0] == '.') + continue; std::string modpath = modspath + DIR_DELIM + modname; TRACESTREAM(<serialize(wrapper_os); + f->serialize(wrapper_os, protocol_version); os2<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; igetKey(); - JMutexAutoLock envlock(m_env_mutex); - m_env->removePlayer(peer_id); - }*/ - // Delete client delete i.getNode()->getValue(); } @@ -1567,7 +1570,7 @@ void Server::AsyncRunStep() if(obj) data_buffer.append(serializeLongString( - obj->getClientInitializationData())); + obj->getClientInitializationData(client->net_proto_version))); else data_buffer.append(serializeLongString("")); @@ -2037,40 +2040,74 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) Read and check network protocol version */ - u16 net_proto_version = 0; + u16 min_net_proto_version = 0; if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2) + min_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]); + + // Use same version as minimum and maximum if maximum version field + // doesn't exist (backwards compatibility) + u16 max_net_proto_version = min_net_proto_version; + if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2) + max_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2]); + + // Start with client's maximum version + u16 net_proto_version = max_net_proto_version; + + // Figure out a working version if it is possible at all + if(max_net_proto_version >= SERVER_PROTOCOL_VERSION_MIN || + min_net_proto_version <= SERVER_PROTOCOL_VERSION_MAX) { - net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]); + // If maximum is larger than our maximum, go with our maximum + if(max_net_proto_version > SERVER_PROTOCOL_VERSION_MAX) + net_proto_version = SERVER_PROTOCOL_VERSION_MAX; + // Else go with client's maximum + else + net_proto_version = max_net_proto_version; } + verbosestream<<"Server: "<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 "<getBool("strict_protocol_version_checking")) { - if(net_proto_version != PROTOCOL_VERSION) + if(net_proto_version != LATEST_PROTOCOL_VERSION) { - actionstream<<"Server: A mismatched client tried to connect" - <<" from "< reply(2+1+6+8); + SharedBuffer reply(2+1+6+8+4); writeU16(&reply[0], TOCLIENT_INIT); writeU8(&reply[2], deployed); writeV3S16(&reply[2+1], floatToInt(playersao->getPlayer()->getPosition()+v3f(0,BS/2,0), BS)); writeU64(&reply[2+1+6], m_env->getServerMap().getSeed()); + writeF1000(&reply[2+1+6+8], g_settings->getFloat("dedicated_server_step")); // Send as reliable m_con.Send(peer_id, 0, reply, true); @@ -2242,8 +2280,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) return; } - getClient(peer_id)->serialization_version - = getClient(peer_id)->pending_serialization_version; + RemoteClient *client = getClient(peer_id); + client->serialization_version = + getClient(peer_id)->pending_serialization_version; /* Send some initialization data @@ -2256,7 +2295,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) SendItemDef(m_con, peer_id, m_itemdef); // Send node definitions - SendNodeDef(m_con, peer_id, m_nodedef); + SendNodeDef(m_con, peer_id, m_nodedef, client->net_proto_version); // Send media announcement sendMediaAnnouncement(peer_id); @@ -2310,9 +2349,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } // Warnings about protocol version can be issued here - if(getClient(peer_id)->net_proto_version < PROTOCOL_VERSION) + if(getClient(peer_id)->net_proto_version < LATEST_PROTOCOL_VERSION) { - SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD AND MAY WORK PROPERLY WITH THIS SERVER!"); + SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT'S " + L"VERSION MAY NOT BE FULLY COMPATIBLE WITH THIS SERVER!"); } /* @@ -2369,7 +2409,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(command == TOSERVER_PLAYERPOS) { - if(datasize < 2+12+12+4+4+4) + if(datasize < 2+12+12+4+4) return; u32 start = 0; @@ -2377,7 +2417,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) v3s32 ss = readV3S32(&data[start+2+12]); f32 pitch = (f32)readS32(&data[2+12+12]) / 100.0; f32 yaw = (f32)readS32(&data[2+12+12+4]) / 100.0; - u32 keyPressed = (u32)readU32(&data[2+12+12+4+4]); + u32 keyPressed = 0; + if(datasize >= 2+12+12+4+4+4) + keyPressed = (u32)readU32(&data[2+12+12+4+4]); v3f position((f32)ps.X/100., (f32)ps.Y/100., (f32)ps.Z/100.); v3f speed((f32)ss.X/100., (f32)ss.Y/100., (f32)ss.Z/100.); pitch = wrapDegrees(pitch); @@ -3508,7 +3550,7 @@ void Server::SendItemDef(con::Connection &con, u16 peer_id, } void Server::SendNodeDef(con::Connection &con, u16 peer_id, - INodeDefManager *nodedef) + INodeDefManager *nodedef, u16 protocol_version) { DSTACK(__FUNCTION_NAME); std::ostringstream os(std::ios_base::binary); @@ -3520,7 +3562,7 @@ void Server::SendNodeDef(con::Connection &con, u16 peer_id, */ writeU16(os, TOCLIENT_NODEDEF); std::ostringstream tmp_os(std::ios::binary); - nodedef->serialize(tmp_os); + nodedef->serialize(tmp_os, protocol_version); std::ostringstream tmp_os2(std::ios::binary); compressZlib(tmp_os.str(), tmp_os2); os< + +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<::Iterator + i = m_stored.begin(); + i != m_stored.end(); i++) + { + StaticObject &s_obj = *i; + s_obj.serialize(os); + } + for(core::map::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 #include -#include "util/serialize.h" +#include "debug.h" struct StaticObject { @@ -43,33 +43,8 @@ struct StaticObject { } - void serialize(std::ostream &os) - { - char buf[12]; - // type - buf[0] = type; - os.write(buf, 1); - // pos - writeV3S32((u8*)buf, v3s32(pos.X*1000,pos.Y*1000,pos.Z*1000)); - os.write(buf, 12); - // data - os<::Iterator - i = m_stored.begin(); - i != m_stored.end(); i++) - { - StaticObject &s_obj = *i; - s_obj.serialize(os); - } - for(core::map::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 m_source_image_existence; + // A texture id is index in this array. // The first position contains a NULL texture. core::array m_atlaspointer_cache; @@ -781,6 +796,7 @@ void TextureSource::insertSourceImage(const std::string &name, video::IImage *im assert(get_current_thread_id() == m_main_thread); m_sourcecache.insert(name, img, true, m_device->getVideoDriver()); + m_source_image_existence.set(name, true); } void TextureSource::rebuildImagesAndTextures() diff --git a/src/tile.h b/src/tile.h index ae986e797..12c40c833 100644 --- a/src/tile.h +++ b/src/tile.h @@ -131,6 +131,7 @@ public: virtual IrrlichtDevice* getDevice() {return NULL;} virtual void updateAP(AtlasPointer &ap){}; + virtual bool isKnownSourceImage(const std::string &name)=0; }; class IWritableTextureSource : public ITextureSource @@ -149,6 +150,7 @@ public: virtual IrrlichtDevice* getDevice() {return NULL;} virtual void updateAP(AtlasPointer &ap){}; + virtual bool isKnownSourceImage(const std::string &name)=0; virtual void processQueue()=0; virtual void insertSourceImage(const std::string &name, video::IImage *img)=0; diff --git a/src/util/pointer.h b/src/util/pointer.h index 766cc2328..775f0a336 100644 --- a/src/util/pointer.h +++ b/src/util/pointer.h @@ -222,7 +222,7 @@ public: /* Copies whole buffer */ - SharedBuffer(T *t, unsigned int size) + SharedBuffer(const T *t, unsigned int size) { m_size = size; if(m_size != 0)