From 32352e90da2ebe104ffca34c9191a23359386a4d Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sat, 7 Mar 2015 16:16:25 -0500 Subject: [PATCH] Revert all commits up to (including) a704c04f --- .gitignore | 2 - CMakeLists.txt | 2 +- README.txt | 31 +- build/android/Makefile | 2 +- build/android/jni/Android.mk | 19 +- builtin/common/misc_helpers.lua | 13 +- builtin/common/serialize.lua | 11 +- builtin/game/chatcommands.lua | 41 +- builtin/game/item.lua | 52 +- builtin/mainmenu/common.lua | 56 +- builtin/mainmenu/dlg_config_world.lua | 11 +- builtin/mainmenu/dlg_create_world.lua | 4 +- builtin/mainmenu/init.lua | 6 +- builtin/mainmenu/store.lua | 46 +- builtin/mainmenu/tab_mods.lua | 4 +- builtin/mainmenu/tab_multiplayer.lua | 24 +- builtin/mainmenu/tab_simple_main.lua | 13 +- cmake/Modules/FindIrrlicht.cmake | 2 +- doc/lua_api.txt | 273 +- doc/menu_lua_api.txt | 14 +- minetest.conf.example | 55 +- misc/minetest.desktop | 2 - po/cs/minetest.po | 706 ++--- po/es/minetest.po | 580 ++-- po/ja/minetest.po | 748 ++--- po/tr/minetest.po | 1248 -------- src/CMakeLists.txt | 19 +- src/activeobject.h | 19 +- src/{util => }/base64.cpp | 0 src/{util => }/base64.h | 0 src/camera.h | 2 +- src/cavegen.cpp | 466 +-- src/cavegen.h | 49 +- src/cguittfont/CGUITTFont.cpp | 26 +- src/cguittfont/irrUString.h | 2 +- src/client.cpp | 1691 ++++++++-- src/client.h | 71 +- src/client/CMakeLists.txt | 5 - src/client/clientlauncher.cpp | 709 ----- src/client/clientlauncher.h | 129 - src/client/inputhandler.h | 428 --- src/clientiface.cpp | 55 +- src/clientiface.h | 9 +- src/clientmap.cpp | 95 +- src/clientmedia.cpp | 12 +- src/clientobject.cpp | 7 +- src/clientobject.h | 2 +- .../networkprotocol.h => clientserver.h} | 11 +- src/collision.cpp | 24 +- src/{network => }/connection.cpp | 526 ++-- src/{network => }/connection.h | 38 +- src/constants.h | 8 +- src/content_cao.cpp | 9 +- src/content_cao.h | 3 +- src/content_cso.cpp | 2 +- src/content_mapblock.cpp | 156 +- src/{gameparams.h => content_object.h} | 26 +- src/content_sao.cpp | 340 +- src/content_sao.h | 20 +- src/craftdef.cpp | 31 +- src/database-dummy.cpp | 52 +- src/database-dummy.h | 21 +- src/database-leveldb.cpp | 56 +- src/database-leveldb.h | 25 +- src/database-redis.cpp | 129 +- src/database-redis.h | 24 +- src/database-sqlite3.cpp | 370 ++- src/database-sqlite3.h | 44 +- src/database.cpp | 4 +- src/database.h | 28 +- src/defaultsettings.cpp | 5 - src/dungeongen.cpp | 9 +- src/emerge.cpp | 5 +- src/environment.cpp | 254 +- src/environment.h | 30 +- src/filecache.cpp | 2 +- src/game.cpp | 86 +- src/gettext.cpp | 26 +- src/gettext.h | 7 +- src/guiChatConsole.cpp | 9 +- src/guiChatConsole.h | 3 + src/guiEngine.cpp | 2 +- src/guiEngine.h | 2 +- src/guiFormSpecMenu.cpp | 16 +- src/guiFormSpecMenu.h | 12 +- src/guiKeyChangeMenu.cpp | 52 +- src/guiPasswordChange.cpp | 12 +- src/guiTable.cpp | 2 +- src/{util => }/hex.h | 0 src/httpfetch.cpp | 17 +- src/hud.cpp | 2 +- src/itemdef.cpp | 17 +- src/jthread/jevent.h | 4 +- src/jthread/jsemaphore.h | 4 +- src/jthread/pthread/jevent.cpp | 2 +- src/jthread/pthread/jsemaphore.cpp | 20 +- src/keycode.cpp | 2 +- src/localplayer.cpp | 7 +- src/localplayer.h | 2 +- src/log.cpp | 35 +- src/lua/CMakeLists.txt | 8 +- src/lua/src/lauxlib.c | 3 +- src/main.cpp | 1370 +++++++- src/map.cpp | 226 +- src/map.h | 24 +- src/mapblock.cpp | 29 +- src/mapblock.h | 2 - src/mapblock_mesh.cpp | 33 +- src/mapblock_mesh.h | 5 +- src/mapgen.cpp | 25 +- src/mapgen.h | 3 +- src/mapgen_v5.cpp | 153 +- src/mapgen_v5.h | 13 +- src/mapgen_v6.cpp | 9 - src/mapgen_v7.cpp | 46 +- src/mapgen_v7.h | 2 +- src/mapnode.cpp | 18 +- src/mapnode.h | 10 +- src/mapsector.cpp | 2 +- src/mapsector.h | 6 +- src/mg_biome.cpp | 7 + src/mg_biome.h | 4 + src/mg_decoration.cpp | 6 +- src/mg_decoration.h | 9 +- src/mods.cpp | 5 - src/network/CMakeLists.txt | 15 - src/network/clientopcodes.cpp | 184 -- src/network/clientopcodes.h | 52 - src/network/networkpacket.cpp | 523 ---- src/network/networkpacket.h | 129 - src/network/packethandlers/client.cpp | 1024 ------ src/network/packethandlers/server.cpp | 1549 --------- src/network/serveropcodes.cpp | 184 -- src/network/serveropcodes.h | 52 - src/nodedef.cpp | 14 +- src/nodedef.h | 4 +- src/particles.cpp | 11 +- src/particles.h | 2 +- src/porting.h | 8 +- src/script/lua_api/l_env.cpp | 78 +- src/script/lua_api/l_env.h | 4 - src/script/lua_api/l_mainmenu.cpp | 40 +- src/script/lua_api/l_mainmenu.h | 6 - src/script/lua_api/l_mapgen.cpp | 8 +- src/script/lua_api/l_object.cpp | 32 +- src/script/lua_api/l_rollback.cpp | 10 - src/script/lua_api/l_server.cpp | 27 +- src/server.cpp | 2766 ++++++++++++++--- src/server.h | 70 +- src/serverlist.cpp | 11 +- src/serverobject.cpp | 19 +- src/serverobject.h | 6 +- src/{util => }/sha1.cpp | 0 src/{util => }/sha1.h | 0 src/shader.cpp | 2 +- src/sky.cpp | 2 +- src/staticobject.cpp | 8 +- src/staticobject.h | 4 +- src/subgame.cpp | 2 +- src/test.cpp | 282 +- src/{client => }/tile.cpp | 7 +- src/{client => }/tile.h | 0 src/touchscreengui.h | 2 +- src/util/CMakeLists.txt | 2 - src/util/container.h | 67 +- src/util/numeric.cpp | 114 +- src/util/numeric.h | 100 +- src/util/string.cpp | 59 +- src/voxel.cpp | 2 - src/voxel.h | 15 +- src/wieldmesh.cpp | 6 +- util/travis/before_install.sh | 9 +- util/travis/script.sh | 6 +- 173 files changed, 8751 insertions(+), 11138 deletions(-) delete mode 100644 po/tr/minetest.po rename src/{util => }/base64.cpp (100%) rename src/{util => }/base64.h (100%) delete mode 100644 src/client/CMakeLists.txt delete mode 100644 src/client/clientlauncher.cpp delete mode 100644 src/client/clientlauncher.h delete mode 100644 src/client/inputhandler.h rename src/{network/networkprotocol.h => clientserver.h} (98%) rename src/{network => }/connection.cpp (90%) rename src/{network => }/connection.h (97%) rename src/{gameparams.h => content_object.h} (63%) rename src/{util => }/hex.h (100%) delete mode 100644 src/network/CMakeLists.txt delete mode 100644 src/network/clientopcodes.cpp delete mode 100644 src/network/clientopcodes.h delete mode 100644 src/network/networkpacket.cpp delete mode 100644 src/network/networkpacket.h delete mode 100644 src/network/packethandlers/client.cpp delete mode 100644 src/network/packethandlers/server.cpp delete mode 100644 src/network/serveropcodes.cpp delete mode 100644 src/network/serveropcodes.h rename src/{util => }/sha1.cpp (100%) rename src/{util => }/sha1.h (100%) rename src/{client => }/tile.cpp (99%) rename src/{client => }/tile.h (100%) diff --git a/.gitignore b/.gitignore index 46146df14..680a44158 100644 --- a/.gitignore +++ b/.gitignore @@ -59,8 +59,6 @@ src/json/CMakeFiles/ src/json/libjsoncpp.a src/sqlite/CMakeFiles/* src/sqlite/libsqlite3.a -src/client/CMakeFiles/ -src/network/CMakeFiles/ CMakeCache.txt CPackConfig.cmake CPackSourceConfig.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 3065710ab..5c64b2e76 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 12) +set(VERSION_PATCH 11) set(VERSION_PATCH_ORIG ${VERSION_PATCH}) if(VERSION_EXTRA) diff --git a/README.txt b/README.txt index a3aa9e6b3..0999bd165 100644 --- a/README.txt +++ b/README.txt @@ -103,30 +103,18 @@ Compiling on GNU/Linux: ----------------------- Install dependencies. Here's an example for Debian/Ubuntu: -$ sudo apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libjsoncpp-dev +$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev -You can install git for easily keeping your copy up to date. -If you dont want git, read below on how to get the source without git. -This is an example for installing git on Debian/Ubuntu: -$ sudo apt-get install git-core - -Download source (this is the URL to the latest of source repository, which might not work at all times) using git: -$ git clone --depth 1 https://github.com/minetest/minetest.git -$ cd minetest - -Download minetest_game (otherwise only the "Minimal development test" game is available) using git: -$ git clone --depth 1 https://github.com/minetest/minetest_game.git games/minetest_game - -Download source, without using git: -$ wget https://github.com/minetest/minetest/archive/master.tar.gz +Download source, extract (this is the URL to the latest of source repository, which might not work at all times): +$ wget https://github.com/minetest/minetest/tarball/master -O master.tar.gz $ tar xf master.tar.gz -$ cd minetest-master +$ cd minetest-minetest-286edd4 (or similar) -Download minetest_game, without using git: +Download minetest_game (otherwise only the "Minimal development test" game is available) $ cd games/ -$ wget https://github.com/minetest/minetest_game/archive/master.tar.gz -$ tar xf master.tar.gz -$ mv minetest_game-master minetest_game +$ wget https://github.com/minetest/minetest_game/tarball/master -O minetest_game.tar.gz +$ tar xf minetest_game.tar.gz +$ mv minetest-minetest_game-* minetest_game $ cd .. Build a version that runs directly from the source directory: @@ -134,7 +122,8 @@ $ cmake . -DRUN_IN_PLACE=1 $ make -j2 Run it: -$ ./bin/minetest +$ cd bin +$ ./minetest - Use cmake . -LH to see all CMake options and their current state - If you want to install it system-wide (or are making a distribution package), you will want to use -DRUN_IN_PLACE=0 diff --git a/build/android/Makefile b/build/android/Makefile index 6027982ed..68625b6a7 100644 --- a/build/android/Makefile +++ b/build/android/Makefile @@ -26,7 +26,7 @@ GAMES_TO_COPY = minetest_game # Android Version code # Increase for each build! ################################################################################ -ANDROID_VERSION_CODE = 6 +ANDROID_VERSION_CODE = 5 ################################################################################ # toolchain config for arm old processors diff --git a/build/android/jni/Android.mk b/build/android/jni/Android.mk index a35084433..7546626b2 100644 --- a/build/android/jni/Android.mk +++ b/build/android/jni/Android.mk @@ -102,6 +102,7 @@ LOCAL_C_INCLUDES := \ LOCAL_SRC_FILES := \ jni/src/ban.cpp \ + jni/src/base64.cpp \ jni/src/camera.cpp \ jni/src/cavegen.cpp \ jni/src/chat.cpp \ @@ -112,6 +113,7 @@ LOCAL_SRC_FILES := \ jni/src/clientobject.cpp \ jni/src/clouds.cpp \ jni/src/collision.cpp \ + jni/src/connection.cpp \ jni/src/content_abm.cpp \ jni/src/content_cao.cpp \ jni/src/content_cso.cpp \ @@ -188,6 +190,7 @@ LOCAL_SRC_FILES := \ jni/src/server.cpp \ jni/src/serverlist.cpp \ jni/src/serverobject.cpp \ + jni/src/sha1.cpp \ jni/src/shader.cpp \ jni/src/sky.cpp \ jni/src/socket.cpp \ @@ -196,34 +199,22 @@ LOCAL_SRC_FILES := \ jni/src/staticobject.cpp \ jni/src/subgame.cpp \ jni/src/test.cpp \ + jni/src/tile.cpp \ jni/src/tool.cpp \ jni/src/treegen.cpp \ jni/src/version.cpp \ jni/src/voxel.cpp \ jni/src/voxelalgorithms.cpp \ - jni/src/util/base64.cpp \ jni/src/util/directiontables.cpp \ jni/src/util/numeric.cpp \ jni/src/util/pointedthing.cpp \ jni/src/util/serialize.cpp \ - jni/src/util/sha1.cpp \ jni/src/util/string.cpp \ jni/src/util/timetaker.cpp \ jni/src/touchscreengui.cpp \ jni/src/database-leveldb.cpp \ jni/src/settings.cpp \ - jni/src/wieldmesh.cpp \ - jni/src/client/clientlauncher.cpp \ - jni/src/client/tile.cpp - -# Network -LOCAL_SRC_FILES += \ - jni/src/network/connection.cpp \ - jni/src/network/networkpacket.cpp \ - jni/src/network/clientopcodes.cpp \ - jni/src/network/serveropcodes.cpp \ - jni/src/network/packethandlers/server.cpp \ - jni/src/network/packethandlers/client.cpp + jni/src/wieldmesh.cpp # lua api LOCAL_SRC_FILES += \ diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index 39fca7d1e..deeba788e 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -545,11 +545,12 @@ function table.copy(t, seen) seen = seen or {} seen[t] = n for k, v in pairs(t) do - n[(type(k) == "table" and (seen[k] or table.copy(k, seen))) or k] = - (type(v) == "table" and (seen[v] or table.copy(v, seen))) or v + n[type(k) ~= "table" and k or seen[k] or table.copy(k, seen)] = + type(v) ~= "table" and v or seen[v] or table.copy(v, seen) end return n end + -------------------------------------------------------------------------------- -- mainmenu only functions -------------------------------------------------------------------------------- @@ -564,7 +565,7 @@ if INIT == "mainmenu" then return nil end - function fgettext_ne(text, ...) + function fgettext(text, ...) text = core.gettext(text) local arg = {n=select('#', ...), ...} if arg.n >= 1 then @@ -586,11 +587,7 @@ if INIT == "mainmenu" then end text = result end - return text - end - - function fgettext(text, ...) - return core.formspec_escape(fgettext_ne(text, ...)) + return core.formspec_escape(text) end end diff --git a/builtin/common/serialize.lua b/builtin/common/serialize.lua index 90b8b2ad6..24b2a12ee 100644 --- a/builtin/common/serialize.lua +++ b/builtin/common/serialize.lua @@ -115,20 +115,11 @@ function core.serialize(x) function dump_val(x) local tp = type(x) if x == nil then return "nil" + elseif tp == "number" then return string.format("%d", x) elseif tp == "string" then return string.format("%q", x) elseif tp == "boolean" then return x and "true" or "false" elseif tp == "function" then return string.format("loadstring(%q)", string.dump(x)) - elseif tp == "number" then - -- Serialize integers with string.format to prevent - -- scientific notation, which doesn't preserve - -- precision and breaks things like node position - -- hashes. Serialize floats normally. - if math.floor(x) == x then - return string.format("%d", x) - else - return tostring(x) - end elseif tp == "table" then local vals = {} local idx_dumped = {} diff --git a/builtin/game/chatcommands.lua b/builtin/game/chatcommands.lua index 210117884..2d94817e8 100644 --- a/builtin/game/chatcommands.lua +++ b/builtin/game/chatcommands.lua @@ -229,28 +229,21 @@ core.register_chatcommand("setpassword", { if not toname then return false, "Name field required" end - local act_str_past = "?" - local act_str_pres = "?" + local actstr = "?" if not raw_password then core.set_player_password(toname, "") - act_str_past = "cleared" - act_str_pres = "clears" + actstr = "cleared" else core.set_player_password(toname, core.get_password_hash(toname, raw_password)) - act_str_past = "set" - act_str_pres = "sets" + actstr = "set" end if toname ~= name then core.chat_send_player(toname, "Your password was " - .. act_str_past .. " by " .. name) + .. actstr .. " by " .. name) end - - core.log("action", name .. " " .. act_str_pres - .. " password of " .. toname .. ".") - - return true, "Password of player \"" .. toname .. "\" " .. act_str_past + return true, "Password of player \"" .. toname .. "\" " .. actstr end, }) @@ -264,9 +257,6 @@ core.register_chatcommand("clearpassword", { return false, "Name field required" end core.set_player_password(toname, '') - - core.log("action", name .. " clears password of " .. toname .. ".") - return true, "Password of player \"" .. toname .. "\" cleared" end, }) @@ -414,14 +404,13 @@ core.register_chatcommand("set", { }) core.register_chatcommand("deleteblocks", { - params = "(here [radius]) | ( )", + params = "[here] [ ]", description = "delete map blocks contained in area pos1 to pos2", privs = {server=true}, func = function(name, param) local p1 = {} local p2 = {} - local args = param:split(" ") - if args[1] == "here" then + if param == "here" then local player = core.get_player_by_name(name) if player == nil then core.log("error", "player is nil") @@ -429,12 +418,6 @@ core.register_chatcommand("deleteblocks", { end p1 = player:getpos() p2 = p1 - - if #args >= 2 then - local radius = tonumber(args[2]) or 0 - p1 = vector.add(p1, radius) - p2 = vector.subtract(p2, radius) - end else local pos1, pos2 = unpack(param:split(") (")) if pos1 == nil or pos2 == nil then @@ -587,9 +570,6 @@ core.register_chatcommand("rollback_check", { .. " seconds=86400=24h, limit=5)", privs = {rollback=true}, func = function(name, param) - if not core.setting_getbool("enable_rollback_recording") then - return false, "Rollback functions are disabled." - end local range, seconds, limit = param:match("(%d+) *(%d*) *(%d*)") range = tonumber(range) or 0 @@ -603,10 +583,6 @@ core.register_chatcommand("rollback_check", { local name = puncher:get_player_name() core.chat_send_player(name, "Checking " .. core.pos_to_string(pos) .. "...") local actions = core.rollback_get_node_actions(pos, range, seconds, limit) - if not actions then - core.chat_send_player(name, "Rollback functions are disabled") - return - end local num_actions = #actions if num_actions == 0 then core.chat_send_player(name, "Nobody has touched" @@ -638,9 +614,6 @@ core.register_chatcommand("rollback", { description = "revert actions of a player; default for is 60", privs = {rollback=true}, func = function(name, param) - if not core.setting_getbool("enable_rollback_recording") then - return false, "Rollback functions are disabled." - end local target_name, seconds = string.match(param, ":([^ ]+) *(%d*)") if not target_name then local player_name = nil diff --git a/builtin/game/item.lua b/builtin/game/item.lua index d25f4eff0..e136d4f4c 100644 --- a/builtin/game/item.lua +++ b/builtin/game/item.lua @@ -106,7 +106,7 @@ function core.facedir_to_dir(facedir) {x=0, y=1, z=0}}) --indexed into by a table of correlating facedirs - [({[0]=1, 2, 3, 4, + [({[0]=1, 2, 3, 4, 5, 2, 6, 4, 6, 2, 5, 4, 1, 5, 3, 6, @@ -238,7 +238,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2) core.log("action", placer:get_player_name() .. " places node " .. def.name .. " at " .. core.pos_to_string(place_to)) - + local oldnode = core.get_node(place_to) local newnode = {name = def.name, param1 = 0, param2 = param2} @@ -357,37 +357,19 @@ function core.item_drop(itemstack, dropper, pos) return itemstack end -function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing) - for _, callback in pairs(core.registered_on_item_eats) do - local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing) - if result then - return result - end - end - if itemstack:take_item() ~= nil then - user:set_hp(user:get_hp() + hp_change) - - if replace_with_item then - if itemstack:is_empty() then - itemstack:add_item(replace_with_item) - else - local inv = user:get_inventory() - if inv:room_for_item("main", {name=replace_with_item}) then - inv:add_item("main", replace_with_item) - else - local pos = user:getpos() - pos.y = math.floor(pos.y + 0.5) - core.add_item(pos, replace_with_item) - end - end - end - end - return itemstack -end - function core.item_eat(hp_change, replace_with_item) return function(itemstack, user, pointed_thing) -- closure - return core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing) + for _, callback in pairs(core.registered_on_item_eats) do + local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing) + if result then + return result + end + end + if itemstack:take_item() ~= nil then + user:set_hp(user:get_hp() + hp_change) + itemstack:add_item(replace_with_item) -- note: replace_with_item is optional + end + return itemstack end end @@ -443,7 +425,7 @@ function core.node_dig(pos, node, digger) local wielded = digger:get_wielded_item() local drops = core.get_node_drops(node.name, wielded:get_name()) - + local wdef = wielded:get_definition() local tp = wielded:get_tool_capabilities() local dp = core.get_dig_params(def.groups, tp) @@ -456,7 +438,7 @@ function core.node_dig(pos, node, digger) end end digger:set_wielded_item(wielded) - + -- Handle drops core.handle_node_drops(pos, drops, digger) @@ -467,7 +449,7 @@ function core.node_dig(pos, node, digger) -- Remove node and update core.remove_node(pos) - + -- Run callback if def.after_dig_node then -- Copy pos and node because callback can modify them @@ -525,7 +507,7 @@ core.nodedef_default = { on_dig = redef_wrapper(core, 'node_dig'), -- core.node_dig on_receive_fields = nil, - + on_metadata_inventory_move = core.node_metadata_inventory_move_allow_all, on_metadata_inventory_offer = core.node_metadata_inventory_offer_allow_all, on_metadata_inventory_take = core.node_metadata_inventory_take_allow_all, diff --git a/builtin/mainmenu/common.lua b/builtin/mainmenu/common.lua index f32d77f2a..549c0967b 100644 --- a/builtin/mainmenu/common.lua +++ b/builtin/mainmenu/common.lua @@ -16,15 +16,9 @@ --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -------------------------------------------------------------------------------- -- Global menu data --------------------------------------------------------------------------------- +--------------------------------------------------------------------------------- menudata = {} --------------------------------------------------------------------------------- --- Local cached values --------------------------------------------------------------------------------- -local min_supp_proto = core.get_min_supp_proto() -local max_supp_proto = core.get_max_supp_proto() - -------------------------------------------------------------------------------- -- Menu helper functions -------------------------------------------------------------------------------- @@ -48,25 +42,6 @@ function image_column(tooltip, flagname) "1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_" .. flagname .. ".png") end --------------------------------------------------------------------------------- -function order_favorite_list(list) - local res = {} - --orders the favorite list after support - for i=1,#list,1 do - local fav = list[i] - if is_server_protocol_compat(fav.proto_min, fav.proto_max) then - table.insert(res, fav) - end - end - for i=1,#list,1 do - local fav = list[i] - if not is_server_protocol_compat(fav.proto_min, fav.proto_max) then - table.insert(res, fav) - end - end - return res -end - -------------------------------------------------------------------------------- function render_favorite(spec,render_details) local text = "" @@ -93,7 +68,6 @@ function render_favorite(spec,render_details) end local details = "" - local grey_out = not is_server_protocol_compat(spec.proto_max, spec.proto_min) if spec.clients ~= nil and spec.clients_max ~= nil then local clients_color = '' @@ -113,17 +87,11 @@ function render_favorite(spec,render_details) clients_color = '#ffba97' -- 90-100%: orange end - if grey_out then - clients_color = '#aaaaaa' - end - details = details .. clients_color .. ',' .. render_client_count(spec.clients) .. ',' .. '/,' .. render_client_count(spec.clients_max) .. ',' - elseif grey_out then - details = details .. '#aaaaaa,?,/,?,' else details = details .. ',?,/,?,' end @@ -146,7 +114,7 @@ function render_favorite(spec,render_details) details = details .. "0," end - return details .. (grey_out and '#aaaaaa,' or ',') .. text + return details .. text end -------------------------------------------------------------------------------- @@ -227,7 +195,7 @@ function asyncOnlineFavourites() nil, function(result) if core.setting_getbool("public_serverlist") then - menudata.favorites = order_favorite_list(result) + menudata.favorites = result core.event_handler("Refresh") end end @@ -257,21 +225,3 @@ function text2textlist(xpos,ypos,width,height,tl_name,textlen,text,transparency) return retval end - --------------------------------------------------------------------------------- -function is_server_protocol_compat(proto_min, proto_max) - return not ((min_supp_proto > (proto_max or 24)) or (max_supp_proto < (proto_min or 13))) -end --------------------------------------------------------------------------------- -function is_server_protocol_compat_or_error(proto_min, proto_max) - if not is_server_protocol_compat(proto_min, proto_max) then - gamedata.errormessage = fgettext_ne("Protocol version mismatch, server " .. - ((proto_min ~= proto_max) and "supports protocols between $1 and $2" or "enforces protocol version $1") .. - ", we " .. - ((min_supp_proto ~= max_supp_proto) and "support protocols between version $3 and $4." or "only support protocol version $3"), - proto_min or 13, proto_max or 24, min_supp_proto, max_supp_proto) - return false - end - - return true -end diff --git a/builtin/mainmenu/dlg_config_world.lua b/builtin/mainmenu/dlg_config_world.lua index 4d13faea8..a15e4c11f 100644 --- a/builtin/mainmenu/dlg_config_world.lua +++ b/builtin/mainmenu/dlg_config_world.lua @@ -16,9 +16,6 @@ --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -------------------------------------------------------------------------------- -local function modname_valid(name) - return not name:find("[^a-z0-9_]") -end local function get_formspec(data) @@ -198,12 +195,10 @@ local function handle_buttons(this, fields) for i,mod in ipairs(rawlist) do if not mod.is_modpack and mod.typ ~= "game_mod" then - if modname_valid(mod.name) then - worldfile:set("load_mod_"..mod.name, tostring(mod.enabled)) + if mod.enabled then + worldfile:set("load_mod_"..mod.name, "true") else - if mod.enabled then - gamedata.errormessage = fgettext_ne("Failed to enable mod \"$1\" as it contains disallowed characters. Only chararacters [a-z0-9_] are allowed.", mod.name) - end + worldfile:set("load_mod_"..mod.name, "false") end mods["load_mod_"..mod.name] = nil end diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua index b42d119e0..32e1fbf83 100644 --- a/builtin/mainmenu/dlg_create_world.lua +++ b/builtin/mainmenu/dlg_create_world.lua @@ -90,8 +90,6 @@ local function create_world_buttonhandler(this, fields) local message = nil - core.setting_set("fixed_map_seed", fields["te_seed"]) - if not menudata.worldlist:uid_exists_raw(worldname) then core.setting_set("mg_name",fields["dd_mapgen"]) message = core.create_world(worldname,gameindex) @@ -99,6 +97,8 @@ local function create_world_buttonhandler(this, fields) message = fgettext("A world named \"$1\" already exists", worldname) end + core.setting_set("fixed_map_seed", fields["te_seed"]) + if message ~= nil then gamedata.errormessage = message else diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua index d008ec8b0..dfaa04d3c 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -139,11 +139,7 @@ local function init_globals() tv_main:add(tab_credits) tv_main:set_global_event_handler(main_event_handler) - if PLATFORM ~= "Android" then - tv_main:set_fixed_size(true) - else - tv_main:set_fixed_size(false) - end + tv_main:set_fixed_size(false) if not (PLATFORM == "Android") then tv_main:set_tab(core.setting_get("maintab_LAST")) diff --git a/builtin/mainmenu/store.lua b/builtin/mainmenu/store.lua index ad861082d..f0ddfce8f 100644 --- a/builtin/mainmenu/store.lua +++ b/builtin/mainmenu/store.lua @@ -122,36 +122,35 @@ end function modstore.showdownloading(title) local new_dlg = dialog_create("store_downloading", function(data) - return "size[6,2]label[0.25,0.75;" .. - fgettext("Downloading $1, please wait...", data.title) .. "]" + return "size[6,2]label[0.25,0.75;" .. fgettext("Downloading") .. + " " .. data.title .. " " .. + fgettext("please wait...") .. "]" end, function(this,fields) if fields["btn_hidden_close_download"] ~= nil then if fields["btn_hidden_close_download"].successfull then modstore.lastmodentry = fields["btn_hidden_close_download"] - modstore.successfulldialog(this) + modstore.successfulldialog() else - this.parent:show() - this:delete() modstore.lastmodtitle = "" end + this:delete() return true end return false end, - nil) + nil, + modstore.tv_store) - new_dlg:set_parent(modstore.tv_store) - modstore.tv_store:hide() new_dlg.data.title = title new_dlg:show() end -------------------------------------------------------------------------------- -- @function [parent=#modstore] successfulldialog -function modstore.successfulldialog(downloading_dlg) +function modstore.successfulldialog() local new_dlg = dialog_create("store_downloading", function(data) local retval = "" @@ -159,16 +158,18 @@ function modstore.successfulldialog(downloading_dlg) if modstore.lastmodentry ~= nil then retval = retval .. "label[0,0.25;" .. fgettext("Successfully installed:") .. "]" retval = retval .. "label[3,0.25;" .. modstore.lastmodentry.moddetails.title .. "]" + + retval = retval .. "label[0,0.75;" .. fgettext("Shortname:") .. "]" retval = retval .. "label[3,0.75;" .. core.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]" + end - retval = retval .. "button[2.2,1.5;1.5,0.5;btn_confirm_mod_successfull;" .. fgettext("Ok") .. "]" - return retval + retval = retval .. "button[2.5,1.5;1,0.5;btn_confirm_mod_successfull;" .. fgettext("ok") .. "]" end, function(this,fields) if fields["btn_confirm_mod_successfull"] ~= nil then this.parent:show() - downloading_dlg:delete() + this:hide() this:delete() return true @@ -176,10 +177,10 @@ function modstore.successfulldialog(downloading_dlg) return false end, - nil) + nil, + modstore.tv_store) - new_dlg:set_parent(modstore.tv_store) - modstore.tv_store:hide() + new_dlg.data.title = title new_dlg:show() end @@ -216,9 +217,7 @@ function modstore.handle_buttons(parent, fields, name, data) end if fields["btn_modstore_close"] then - local maintab = ui.find_by_name("maintab") parent:hide() - maintab:show() return true end @@ -229,7 +228,12 @@ function modstore.handle_buttons(parent, fields, name, data) for i=1,#modstore.modlist_unsorted.data,1 do if modstore.modlist_unsorted.data[i].id == modid then local moddetails = modstore.modlist_unsorted.data[i].details - modstore.lastmodtitle = moddetails.title + + if modstore.lastmodtitle ~= "" then + modstore.lastmodtitle = modstore.lastmodtitle .. ", " + end + + modstore.lastmodtitle = modstore.lastmodtitle .. moddetails.title if not core.handle_async( function(param) @@ -277,7 +281,7 @@ function modstore.handle_buttons(parent, fields, name, data) texturename = modstore.modlist_unsorted.data[i].texturename }, function(result) - --print("Result from async: " .. dump(result.successfull)) + print("Result from async: " .. dump(result.successfull)) if result.successfull then modmgr.installmod(result.filename,result.moddetails.basename) os.remove(result.filename) @@ -295,7 +299,7 @@ function modstore.handle_buttons(parent, fields, name, data) print("ERROR: async event failed") gamedata.errormessage = "Failed to download " .. modstore.lastmodtitle end - + parent:hide() modstore.showdownloading(modstore.lastmodtitle) return true end @@ -387,7 +391,7 @@ function modstore.getscreenshot(ypos,listentry) listentry.details.screenshot_url == "") then if listentry.texturename == nil then - listentry.texturename = defaulttexturedir .. "no_screenshot.png" + listentry.texturename = modstore.basetexturedir .. "no_screenshot.png" end return "image[0,".. ypos .. ";3,2;" .. diff --git a/builtin/mainmenu/tab_mods.lua b/builtin/mainmenu/tab_mods.lua index 901f14553..d16ecca8c 100644 --- a/builtin/mainmenu/tab_mods.lua +++ b/builtin/mainmenu/tab_mods.lua @@ -57,7 +57,7 @@ local function get_formspec(tabview, name, tabdata) end if modscreenshot == nil then - modscreenshot = defaulttexturedir .. "no_screenshot.png" + modscreenshot = modstore.basetexturedir .. "no_screenshot.png" end retval = retval @@ -96,7 +96,7 @@ local function get_formspec(tabview, name, tabdata) else --show dependencies - retval = retval .. "," .. fgettext("Depends:") .. "," + retval = retval .. ",Depends:," local toadd = modmgr.get_dependencies(selected_mod.path) diff --git a/builtin/mainmenu/tab_multiplayer.lua b/builtin/mainmenu/tab_multiplayer.lua index 570259718..c44fd0144 100644 --- a/builtin/mainmenu/tab_multiplayer.lua +++ b/builtin/mainmenu/tab_multiplayer.lua @@ -59,10 +59,9 @@ local function get_formspec(tabview, name, tabdata) "text,align=right;" .. -- clients "text,align=center,padding=0.25;" .. -- "/" "text,align=right,padding=0.25;" .. -- clients_max - image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" .. - image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" .. - image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" .. - "color,span=1;" .. + image_column("Creative mode", "creative") .. ",padding=1;" .. + image_column("Damage enabled", "damage") .. ",padding=0.25;" .. + image_column("PvP enabled", "pvp") .. ",padding=0.25;" .. "text,padding=1]" -- name else retval = retval .. "tablecolumns[text]" @@ -89,6 +88,7 @@ end -------------------------------------------------------------------------------- local function main_button_handler(tabview, fields, name, tabdata) + if fields["te_name"] ~= nil then gamedata.playername = fields["te_name"] core.setting_set("name", fields["te_name"]) @@ -98,10 +98,6 @@ local function main_button_handler(tabview, fields, name, tabdata) local event = core.explode_table_event(fields["favourites"]) if event.type == "DCL" then if event.row <= #menudata.favorites then - if not is_server_protocol_compat_or_error(menudata.favorites[event.row].proto_min, - menudata.favorites[event.row].proto_max) then - return true - end gamedata.address = menudata.favorites[event.row].address gamedata.port = menudata.favorites[event.row].port gamedata.playername = fields["te_name"] @@ -193,7 +189,7 @@ local function main_button_handler(tabview, fields, name, tabdata) local current_favourite = core.get_table_index("favourites") if current_favourite == nil then return end core.delete_favorite(current_favourite) - menudata.favorites = order_favorite_list(core.get_favorites()) + menudata.favorites = core.get_favorites() tabdata.fav_selected = nil core.setting_set("address","") @@ -202,9 +198,8 @@ local function main_button_handler(tabview, fields, name, tabdata) return true end - if (fields["btn_mp_connect"] ~= nil or - fields["key_enter"] ~= nil) and fields["te_address"] ~= nil and - fields["te_port"] ~= nil then + if fields["btn_mp_connect"] ~= nil or + fields["key_enter"] ~= nil then gamedata.playername = fields["te_name"] gamedata.password = fields["te_pwd"] @@ -219,11 +214,6 @@ local function main_button_handler(tabview, fields, name, tabdata) gamedata.servername = menudata.favorites[fav_idx].name gamedata.serverdescription = menudata.favorites[fav_idx].description - - if not is_server_protocol_compat_or_error(menudata.favorites[fav_idx].proto_min, - menudata.favorites[fav_idx].proto_max)then - return true - end else gamedata.servername = "" gamedata.serverdescription = "" diff --git a/builtin/mainmenu/tab_simple_main.lua b/builtin/mainmenu/tab_simple_main.lua index b9a6b650f..cab1702cf 100644 --- a/builtin/mainmenu/tab_simple_main.lua +++ b/builtin/mainmenu/tab_simple_main.lua @@ -42,10 +42,9 @@ local function get_formspec(tabview, name, tabdata) "text,align=right;" .. -- clients "text,align=center,padding=0.25;" .. -- "/" "text,align=right,padding=0.25;" .. -- clients_max - image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" .. - image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" .. - image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" .. - "color,span=1;" .. + image_column("Creative mode", "creative") .. ",padding=1;" .. + image_column("Damage enabled", "damage") .. ",padding=0.25;" .. + image_column("PvP enabled", "pvp") .. ",padding=0.25;" .. "text,padding=1]" -- name else retval = retval .. "tablecolumns[text]" @@ -88,6 +87,7 @@ local function get_formspec(tabview, name, tabdata) end -------------------------------------------------------------------------------- + local function main_button_handler(tabview, fields, name, tabdata) if fields["btn_start_singleplayer"] then @@ -159,11 +159,6 @@ local function main_button_handler(tabview, fields, name, tabdata) gamedata.servername = menudata.favorites[fav_idx].name gamedata.serverdescription = menudata.favorites[fav_idx].description - - if not is_server_protocol_compat_or_error(menudata.favorites[fav_idx].proto_min, - menudata.favorites[fav_idx].proto_max) then - return true - end else gamedata.servername = "" gamedata.serverdescription = "" diff --git a/cmake/Modules/FindIrrlicht.cmake b/cmake/Modules/FindIrrlicht.cmake index a84765d4e..dce78fbaa 100644 --- a/cmake/Modules/FindIrrlicht.cmake +++ b/cmake/Modules/FindIrrlicht.cmake @@ -44,7 +44,7 @@ else() /usr/include/irrlicht ) - FIND_LIBRARY(IRRLICHT_LIBRARY NAMES libIrrlicht.so libIrrlicht.a Irrlicht + FIND_LIBRARY(IRRLICHT_LIBRARY NAMES libIrrlicht.a Irrlicht PATHS /usr/local/lib /usr/lib diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 5fa164e6b..586c520fc 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1,4 +1,4 @@ -Minetest Lua Modding API Reference 0.4.12 +Minetest Lua Modding API Reference 0.4.11 ========================================= * More information at * Developer Wiki: @@ -20,8 +20,7 @@ source code patches to . Programming in Lua ------------------ -If you have any difficulty in understanding this, please read -[Programming in Lua](http://www.lua.org/pil/). +If you have any difficulty in understanding this, please read [Programming in Lua](http://www.lua.org/pil/). Startup ------- @@ -594,14 +593,13 @@ set to level from `param2`. Meshes ------ If drawtype `mesh` is used, tiles should hold model materials textures. -Only static meshes are implemented. +Only static meshes are implemented. For supported model formats see Irrlicht engine documentation. Noise Parameters ---------------- -Noise Parameters, or commonly called "`NoiseParams`", define the properties of -perlin noise. +Noise Parameters, or commonly called "`NoiseParams`", define the properties of perlin noise. ### `offset` Offset that the noise is translated by (i.e. added) after calculation. @@ -681,26 +679,24 @@ All default ores are of the uniformly-distributed scatter type. Randomly chooses a location and generates a cluster of ore. If `noise_params` is specified, the ore will be placed if the 3D perlin noise at -that point is greater than the `noise_threshold`, giving the ability to create -a non-equal distribution of ore. +that point is greater than the `noise_threshold`, giving the ability to create a non-equal +distribution of ore. ### `sheet` -Creates a sheet of ore in a blob shape according to the 2D perlin noise -described by `noise_params`. The relative height of the sheet can be -controlled by the same perlin noise as well, by specifying a non-zero -`scale` parameter in `noise_params`. +Creates a sheet of ore in a blob shape according to the 2D perlin noise described by `noise_params`. +The relative height of the sheet can be controlled by the same perlin noise as well, by specifying +a non-zero `scale` parameter in `noise_params`. -**IMPORTANT**: The noise is not transformed by `offset` or `scale` when comparing -against the noise threshold, but scale is used to determine relative height. +**IMPORTANT**: The noise is not transformed by `offset` or `scale` when comparing against the noise +threshold, but scale is used to determine relative height. The height of the blob is randomly scattered, with a maximum height of `clust_size`. `clust_scarcity` and `clust_num_ores` are ignored. -This is essentially an improved version of the so-called "stratus" ore seen in -some unofficial mods. +This is essentially an improved version of the so-called "stratus" ore seen in some unofficial mods. ### `blob` -Creates a deformed sphere of ore according to 3d perlin noise described by +Creates a deformed sphere of ore according to 3d perlin noise described by `noise_params`. The maximum size of the blob is `clust_size`, and `clust_scarcity` has the same meaning as with the `scatter` type. ### `vein @@ -745,75 +741,64 @@ The varying types of decorations that can be placed. The default value is `simple`, and is currently the only type supported. ### `simple` -Creates a 1 times `H` times 1 column of a specified node (or a random node from -a list, if a decoration list is specified). Can specify a certain node it must -spawn next to, such as water or lava, for example. Can also generate a -decoration of random height between a specified lower and upper bound. -This type of decoration is intended for placement of grass, flowers, cacti, -papyri, and so on. +Creates a 1 times `H` times 1 column of a specified node (or a random node from a list, if a +decoration list is specified). Can specify a certain node it must spawn next to, such as water or +lava, for example. Can also generate a decoration of random height between a specified lower and +upper bound. This type of decoration is intended for placement of grass, flowers, cacti, papyri, +and so on. ### `schematic` -Copies a box of `MapNodes` from a specified schematic file (or raw description). -Can specify a probability of a node randomly appearing when placed. -This decoration type is intended to be used for multi-node sized discrete -structures, such as trees, cave spikes, rocks, and so on. +Copies a box of `MapNodes` from a specified schematic file (or raw description). Can specify a +probability of a node randomly appearing when placed. This decoration type is intended to be used +for multi-node sized discrete structures, such as trees, cave spikes, rocks, and so on. Schematic specifier -------------------- -A schematic specifier identifies a schematic by either a filename to a -Minetest Schematic file (`.mts`) or through raw data supplied through Lua, -in the form of a table. This table must specify two fields: +A schematic specifier identifies a schematic by either a filename to a Minetest Schematic file (`.mts`) +or through raw data supplied through Lua, in the form of a table. This table must specify two fields: * The `size` field is a 3D vector containing the dimensions of the provided schematic. -* The `data` field is a flat table of MapNodes making up the schematic, - in the order of `[z [y [x]]]`. +* The `data` field is a flat table of MapNodes making up the schematic, in the order of `[z [y [x]]]`. -**Important**: The default value for `param1` in MapNodes here is `255`, -which represents "always place". +**Important**: The default value for `param1` in MapNodes here is `255`, which represents "always place". -In the bulk `MapNode` data, `param1`, instead of the typical light values, -instead represents the probability of that node appearing in the structure. +In the bulk `MapNode` data, `param1`, instead of the typical light values, instead represents the +probability of that node appearing in the structure. -When passed to `minetest.create_schematic`, probability is an integer value -ranging from `0` to `255`: +When passed to `minetest.create_schematic`, probability is an integer value ranging from `0` to `255`: * A probability value of `0` means that node will never appear (0% chance). * A probability value of `255` means the node will always appear (100% chance). -* If the probability value `p` is greater than `0`, then there is a - `(p / 256 * 100)`% chance that node will appear when the schematic is - placed on the map. +* If the probability value `p` is greater than `0`, then there is a `(p / 256 * 100)`% chance that node + will appear when the schematic is placed on the map. -**Important note**: Node aliases cannot be used for a raw schematic provided - when registering as a decoration. +**Important note**: Node aliases cannot be used for a raw schematic provided when registering as a decoration. Schematic attributes -------------------- See section "Flag Specifier Format". -Currently supported flags: `place_center_x`, `place_center_y`, - `place_center_z`, `force_placement`. +Currently supported flags: `place_center_x`, `place_center_y`, `place_center_z`. * `place_center_x`: Placement of this decoration is centered along the X axis. * `place_center_y`: Placement of this decoration is centered along the Y axis. * `place_center_z`: Placement of this decoration is centered along the Z axis. -* `force_placement`: Schematic nodes other than "ignore" will replace existing nodes. HUD element types ----------------- The position field is used for all element types. -To account for differing resolutions, the position coordinates are the percentage -of the screen, ranging in value from `0` to `1`. +To account for differing resolutions, the position coordinates are the percentage of the screen, +ranging in value from `0` to `1`. -The name field is not yet used, but should contain a description of what the -HUD element represents. The direction field is the direction in which something -is drawn. +The name field is not yet used, but should contain a description of what the HUD element represents. +The direction field is the direction in which something is drawn. -`0` draws from left to right, `1` draws from right to left, `2` draws from -top to bottom, and `3` draws from bottom to top. +`0` draws from left to right, `1` draws from right to left, `2` draws from top to bottom, +and `3` draws from bottom to top. The `alignment` field specifies how the item will be aligned. It ranges from `-1` to `1`, with `0` being the center, `-1` is moved to the left/up, and `1` is to the right/down. @@ -827,8 +812,7 @@ items in the HUD. Below are the specific uses for fields in each type; fields not listed for that type are ignored. -**Note**: Future revisions to the HUD API may be incompatible; the HUD API is still -in the experimental stages. +**Note**: Future revisions to the HUD API may be incompatible; the HUD API is still in the experimental stages. ### `image` Displays an image on the HUD. @@ -892,18 +876,15 @@ For helper functions see "Vector helpers". Flag Specifier Format --------------------- -Flags using the standardized flag specifier format can be specified in either of -two ways, by string or table. +Flags using the standardized flag specifier format can be specified in either of two ways, by string or table. -The string format is a comma-delimited set of flag names; whitespace and -unrecognized flag fields are ignored. Specifying a flag in the string sets the -flag, and specifying a flag prefixed by the string `"no"` explicitly +The string format is a comma-delimited set of flag names; whitespace and unrecognized flag fields are ignored. +Specifying a flag in the string sets the flag, and specifying a flag prefixed by the string `"no"` explicitly clears the flag from whatever the default may be. -In addition to the standard string flag format, the schematic flags field can -also be a table of flag names to boolean values representing whether or not the -flag is set. Additionally, if a field with the flag name prefixed with `"no"` -is present, mapped to a boolean of any value, the specified flag is unset. +In addition to the standard string flag format, the schematic flags field can also be a table of flag names +to boolean values representing whether or not the flag is set. Additionally, if a field with the flag name +prefixed with `"no"` is present, mapped to a boolean of any value, the specified flag is unset. E.g. A flag field of value @@ -1055,8 +1036,8 @@ Another example: Make red wool from white wool and red dye: dropped as an item. If the node is wallmounted the wallmounted direction is checked. * `soil`: saplings will grow on nodes in this group -* `connect_to_raillike`: makes nodes of raillike drawtype with same group value - connect to each other +* `connect_to_raillike`: makes nodes of raillike drawtype connect to + other group members with same drawtype ### Known damage and digging time defining groups * `crumbly`: dirt, sand @@ -1196,8 +1177,7 @@ Damage calculation: damage = 0 foreach group in cap.damage_groups: - damage += cap.damage_groups[group] * limit(actual_interval / - cap.full_punch_interval, 0.0, 1.0) + damage += cap.damage_groups[group] * limit(actual_interval / cap.full_punch_interval, 0.0, 1.0) * (object.armor_groups[group] / 100.0) -- Where object.armor_groups[group] is 0 for inexistent values return damage @@ -1205,7 +1185,7 @@ Damage calculation: Client predicts damage based on damage groups. Because of this, it is able to give an immediate response when an entity is damaged or dies; the response is pre-defined somehow (e.g. by defining a sprite animation) (not implemented; -TODO). +TODO). Currently a smoke puff will appear when an entity dies. The group `immortal` completely disables normal damage. @@ -1218,8 +1198,8 @@ On the Lua side, every punch calls: entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) -This should never be called directly, because damage is usually not handled by -the entity itself. +This should never be called directly, because damage is usually not handled by the entity +itself. * `puncher` is the object performing the punch. Can be `nil`. Should never be accessed unless absolutely required, to encourage interoperability. @@ -1264,14 +1244,12 @@ Example stuff: print(dump(meta:to_table())) meta:from_table({ inventory = { - main = {[1] = "default:dirt", [2] = "", [3] = "", [4] = "", - [5] = "", [6] = "", [7] = "", [8] = "", [9] = "", - [10] = "", [11] = "", [12] = "", [13] = "", - [14] = "default:cobble", [15] = "", [16] = "", [17] = "", - [18] = "", [19] = "", [20] = "default:cobble", [21] = "", - [22] = "", [23] = "", [24] = "", [25] = "", [26] = "", - [27] = "", [28] = "", [29] = "", [30] = "", [31] = "", - [32] = ""} + main = {[1] = "default:dirt", [2] = "", [3] = "", [4] = "", [5] = "", [6] = "", + [7] = "", [8] = "", [9] = "", [10] = "", [11] = "", [12] = "", [13] = "", + [14] = "default:cobble", [15] = "", [16] = "", [17] = "", [18] = "", + [19] = "", [20] = "default:cobble", [21] = "", [22] = "", [23] = "", + [24] = "", [25] = "", [26] = "", [27] = "", [28] = "", [29] = "", [30] = "", + [31] = "", [32] = ""} }, fields = { formspec = "size[8,9]list[context;main;0,0;8,4;]list[current_player;main;0,5;8,4;]", @@ -1871,9 +1849,6 @@ and `minetest.auth_reload` call the authetification handler. * `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"` * `minetest.find_nodes_in_area(minp, maxp, nodenames)`: returns a list of positions * `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"` -* `minetest.find_nodes_in_area_under_air(minp, maxp, nodenames)`: returns a list of positions - * returned positions are nodes with a node air above - * `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"` * `minetest.get_perlin(noiseparams)` * `minetest.get_perlin(seeddiff, octaves, persistence, scale)` * Return world-specific perlin noise (`int(worldseed)+seeddiff`) @@ -1891,10 +1866,8 @@ and `minetest.auth_reload` call the authetification handler. `mgname`, `seed`, `chunksize`, `water_level`, and `flags`. * `minetest.set_mapgen_params(MapgenParams)` * Set map generation parameters - * Function cannot be called after the registration period; only initialization - and `on_mapgen_init` - * Takes a table as an argument with the fields `mgname`, `seed`, `water_level`, - and `flags`. + * Function cannot be called after the registration period; only initialization and `on_mapgen_init` + * Takes a table as an argument with the fields `mgname`, `seed`, `water_level`, and `flags`. * Leave field unset to leave that parameter unchanged * `flags` contains a comma-delimited string of flags to set, or if the prefix `"no"` is attached, clears instead. @@ -1953,9 +1926,6 @@ and `minetest.auth_reload` call the authetification handler. * `minetest.create_detached_inventory(name, callbacks)`: returns an `InvRef` * callbacks: See "Detached inventory callbacks" * Creates a detached inventory. If it already exists, it is cleared. -* `minetest.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)`: - returns left over ItemStack - * See `minetest.item_eat` and `minetest.register_on_item_eat` ### Formspec * `minetest.show_formspec(playername, formname, formspec)` @@ -2067,11 +2037,7 @@ These functions return the leftover itemstack. * `minetest.item_drop(itemstack, dropper, pos)` * Drop the item * `minetest.item_eat(hp_change, replace_with_item)` - * Eat the item. - * `replace_with_item` is the itemstring which is added to the inventory. - If the player is eating a stack, then replace_with_item goes to a - different spot. Can be `nil` - * See `minetest.do_item_eat` + * Eat the item. `replace_with_item` can be `nil`. ### Defaults for the `on_punch` and `on_dig` node definition callbacks * `minetest.node_punch(pos, node, puncher, pointed_thing)` @@ -2128,15 +2094,12 @@ These functions return the leftover itemstack. * Create a schematic from the volume of map specified by the box formed by p1 and p2. * Apply the specified probability values to the specified nodes in `probability_list`. * `probability_list` is an array of tables containing two fields, `pos` and `prob`. - * `pos` is the 3D vector specifying the absolute coordinates of the - node being modified, + * `pos` is the 3D vector specifying the absolute coordinates of the node being modified, * `prob` is the integer value from `0` to `255` of the probability (see: Schematic specifier). - * If there are two or more entries with the same pos value, the - last entry is used. + * If there are two or more entries with the same pos value, the last entry is used. * If `pos` is not inside the box formed by `p1` and `p2`, it is ignored. * If `probability_list` equals `nil`, no probabilities are applied. - * Slice probability works in the same manner, except takes a field - called `ypos` instead which + * Slice probability works in the same manner, except takes a field called `ypos` instead which indicates the y position of the slice with a probability applied. * If slice probability list equals `nil`, no slice probabilities are applied. * Saves schematic in the Minetest Schematic format to filename. @@ -2281,7 +2244,7 @@ Class reference --------------- ### `NodeMetaRef` -Node metadata: reference extra data and functionality stored in a node. +Node metadata: reference extra data and functionality stored in a node. Can be gotten via `minetest.get_meta(pos)`. #### Methods @@ -2297,7 +2260,7 @@ Can be gotten via `minetest.get_meta(pos)`. * See "Node Metadata" ### `NoteTimerRef` -Node Timers: a high resolution persistent per-node timer. +Node Timers: a high resolution persistent per-node timer. Can be gotten via `minetest.get_node_timer(pos)`. #### Methods @@ -2325,7 +2288,6 @@ This is basically a reference to a C++ `ServerActiveObject` #### Methods * `remove()`: remove object (after returning from Lua) - * Note: Doesn't work on players, use minetest.kick_player instead * `getpos()`: returns `{x=num, y=num, z=num}` * `setpos(pos)`; `pos`=`{x=num, y=num, z=num}` * `moveto(pos, continuous=false)`: interpolated move @@ -2398,8 +2360,7 @@ This is basically a reference to a C++ `ServerActiveObject` * `gravity`: multiplier to default gravity value (default: `1`) * `sneak`: whether player can sneak (default: `true`) * `sneak_glitch`: whether player can use the sneak glitch (default: `true`) -* `hud_add(hud definition)`: add a HUD element described by HUD def, returns ID - number on success +* `hud_add(hud definition)`: add a HUD element described by HUD def, returns ID number on success * `hud_remove(id)`: remove the HUD element of the specified id * `hud_change(id, stat, value)`: change a value of a previously added HUD element * element `stat` values: `position`, `name`, `scale`, `text`, `number`, `item`, `dir` @@ -2431,16 +2392,13 @@ This is basically a reference to a C++ `ServerActiveObject` * `override_day_night_ratio(ratio or nil)` * `0`...`1`: Overrides day-night ratio, controlling sunlight to a specific amount * `nil`: Disables override, defaulting to sunlight based on day-night cycle -* `set_local_animation(walk, dig, walk+dig, frame_speed=frame_speed)` - - set animation for player model in third person view - - set_local_animation({x=0, y=79}, -- < stand/idle animation key frames - {x=168, y=187}, -- < walk animation key frames - {x=189, y=198}, -- < dig animation key frames - {x=200, y=219}, -- < walk+dig animation key frames - frame_speed=30): -- < animation frame speed - +* `set_local_animation({x=0, y=79}, {x=168, y=187}, {x=189, y=198}, {x=200, y=219}, frame_speed=30)`: + set animation for player model in third person view + * stand/idle animation key frames + * walk animation key frames + * dig animation key frames + * walk+dig animation key frames + * animation frame speed * `set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})`: defines offset value for camera per player * in first person view * in third person view (max. values `{x=-10/10,y=-10,15,z=-5/5}`) @@ -2527,7 +2485,7 @@ It can be created via `PseudoRandom(seed)`. ### `PerlinNoise` A perlin noise generator. It can be created via `PerlinNoise(seed, octaves, persistence, scale)` -or `PerlinNoise(noiseparams)`. +or `PerlinNoise(noiseparams)`. Alternatively with `minetest.get_perlin(seeddiff, octaves, persistence, scale)` or `minetest.get_perlin(noiseparams)`. @@ -2561,43 +2519,36 @@ It can be created via `VoxelManip()` or `minetest.get_voxel_manip()`. The map will be pre-loaded if two positions are passed to either. #### Methods -* `read_from_map(p1, p2)`: Reads a chunk of map from the map containing the - region formed by `p1` and `p2`. +* `read_from_map(p1, p2)`: Reads a chunk of map from the map containing the region formed by `p1` and `p2`. * returns actual emerged `pmin`, actual emerged `pmax` * `write_to_map()`: Writes the data loaded from the `VoxelManip` back to the map. * **important**: data must be set using `VoxelManip:set_data` before calling this -* `get_node_at(pos)`: Returns a `MapNode` table of the node currently loaded in - the `VoxelManip` at that position -* `set_node_at(pos, node)`: Sets a specific `MapNode` in the `VoxelManip` at - that position +* `get_node_at(pos)`: Returns a `MapNode` table of the node currently loaded in the `VoxelManip` at that position +* `set_node_at(pos, node)`: Sets a specific `MapNode` in the `VoxelManip` at that position * `get_data()`: Gets the data read into the `VoxelManip` object * returns raw node data is in the form of an array of node content IDs * `set_data(data)`: Sets the data contents of the `VoxelManip` object * `update_map()`: Update map after writing chunk back to map. - * To be used only by `VoxelManip` objects created by the mod itself; - not a `VoxelManip` that was retrieved from `minetest.get_mapgen_object` + * To be used only by `VoxelManip` objects created by the mod itself; not a `VoxelManip` that was + retrieved from `minetest.get_mapgen_object` * `set_lighting(light, p1, p2)`: Set the lighting within the `VoxelManip` to a uniform value * `light` is a table, `{day=<0...15>, night=<0...15>}` * To be used only by a `VoxelManip` object from `minetest.get_mapgen_object` - * (`p1`, `p2`) is the area in which lighting is set; - defaults to the whole area if left out + * (`p1`, `p2`) is the area in which lighting is set; defaults to the whole area if left out * `get_light_data()`: Gets the light data read into the `VoxelManip` object * Returns an array (indices 1 to volume) of integers ranging from `0` to `255` * Each value is the bitwise combination of day and night light values (`0` to `15` each) * `light = day + (night * 16)` -* `set_light_data(light_data)`: Sets the `param1` (light) contents of each node - in the `VoxelManip` +* `set_light_data(light_data)`: Sets the `param1` (light) contents of each node in the `VoxelManip` * expects lighting data in the same format that `get_light_data()` returns * `get_param2_data()`: Gets the raw `param2` data read into the `VoxelManip` object * `set_param2_data(param2_data)`: Sets the `param2` contents of each node in the `VoxelManip` * `calc_lighting(p1, p2)`: Calculate lighting within the `VoxelManip` * To be used only by a `VoxelManip` object from `minetest.get_mapgen_object` - * (`p1`, `p2`) is the area in which lighting is set; defaults to the whole area - if left out + * (`p1`, `p2`) is the area in which lighting is set; defaults to the whole area if left out * `update_liquids()`: Update liquid flow -* `was_modified()`: Returns `true` or `false` if the data in the voxel manipulator - had been modified since the last read from map, due to a call to - `minetest.set_data()` on the loaded area elsewhere +* `was_modified()`: Returns `true` or `false` if the data in the voxel manipulator had been modified since + the last read from map, due to a call to `minetest.set_data()` on the loaded area elsewhere * `get_emerged_area()`: Returns actual emerged minimum and maximum positions. ### `VoxelArea` @@ -2606,12 +2557,10 @@ It can be created via `VoxelArea:new{MinEdge=pmin, MaxEdge=pmax}`. The coordinates are *inclusive*, like most other things in Minetest. #### Methods -* `getExtent()`: returns a 3D vector containing the size of the area formed by - `MinEdge` and `MaxEdge` +* `getExtent()`: returns a 3D vector containing the size of the area formed by `MinEdge` and `MaxEdge` * `getVolume()`: returns the volume of the area formed by `MinEdge` and `MaxEdge` * `index(x, y, z)`: returns the index of an absolute position in a flat array starting at `1` - * useful for things like `VoxelManip`, raw Schematic specifiers, - `PerlinNoiseMap:get2d`/`3dMap`, and so on + * useful for things like `VoxelManip`, raw Schematic specifiers, `PerlinNoiseMap:get2d`/`3dMap`, and so on * `indexp(p)`: same as above, except takes a vector * `position(i)`: returns the absolute position vector corresponding to index `i` * `contains(x, y, z)`: check if (`x`,`y`,`z`) is inside area formed by `MinEdge` and `MaxEdge` @@ -2638,39 +2587,37 @@ It can be created via `Settings(filename)`. Mapgen objects -------------- -A mapgen object is a construct used in map generation. Mapgen objects can be used -by an `on_generate` callback to speed up operations by avoiding unnecessary -recalculations; these can be retrieved using the `minetest.get_mapgen_object()` -function. If the requested Mapgen object is unavailable, or `get_mapgen_object()` -was called outside of an `on_generate()` callback, `nil` is returned. +A mapgen object is a construct used in map generation. Mapgen objects can be used by an `on_generate` +callback to speed up operations by avoiding unnecessary recalculations; these can be retrieved using the +`minetest.get_mapgen_object()` function. If the requested Mapgen object is unavailable, or +`get_mapgen_object()` was called outside of an `on_generate()` callback, `nil` is returned. The following Mapgen objects are currently available: ### `voxelmanip` -This returns three values; the `VoxelManip` object to be used, minimum and maximum -emerged position, in that order. All mapgens support this object. +This returns three values; the `VoxelManip` object to be used, minimum and maximum emerged position, in that +order. All mapgens support this object. ### `heightmap` -Returns an array containing the y coordinates of the ground levels of nodes in -the most recently generated chunk by the current mapgen. +Returns an array containing the y coordinates of the ground levels of nodes in the most recently +generated chunk by the current mapgen. ### `biomemap` -Returns an array containing the biome IDs of nodes in the most recently -generated chunk by the current mapgen. +Returns an array containing the biome IDs of nodes in the most recently generated chunk by the +current mapgen. ### `heatmap` -Returns an array containing the temperature values of nodes in the most -recently generated chunk by the current mapgen. +Returns an array containing the temperature values of nodes in the most recently generated chunk by +the current mapgen. ### `humiditymap` -Returns an array containing the humidity values of nodes in the most recently -generated chunk by the current mapgen. +Returns an array containing the humidity values of nodes in the most recently generated chunk by the +current mapgen. ### `gennotify` -Returns a table mapping requested generation notification types to arrays of -positions at which the corresponding generated structures are located at within -the current chunk. To set the capture of positions of interest to be recorded -on generate, use `minetest.set_gen_notify()`. +Returns a table mapping requested generation notification types to arrays of positions at which the +corresponding generated structures are located at within the current chunk. To set the capture of positions +of interest to be recorded on generate, use `minetest.set_gen_notify()`. Possible fields of the table returned are: @@ -2682,8 +2629,7 @@ Possible fields of the table returned are: * `large_cave_end` * `decoration` -Decorations have a key in the format of `"decoration#id"`, where `id` is the -numeric unique decoration ID. +Decorations have a key in the format of `"decoration#id"`, where `id` is the numeric unique decoration ID. Registered entities ------------------- @@ -2730,8 +2676,7 @@ L-system trees angle, --num angle in deg iterations, --num max # of iterations, usually 2 -5 random_level, --num factor to lower nr of iterations, usually 0 - 3 - trunk_type, --string single/double/crossed) type of trunk: 1 node, - -- 2x2 nodes or 3x3 in cross shape + trunk_type, --string single/double/crossed) type of trunk: 1 node, 2x2 nodes or 3x3 in cross shape thin_branches, --boolean true -> use thin (1 node) branches fruit, --string fruit node name fruit_chance, --num chance (0-100) to replace leaves with fruit node @@ -3193,10 +3138,8 @@ Definition tables schematic = { size = {x=4, y=6, z=4}, data = { - {name="default:cobble", param1=255, param2=0}, - {name="default:dirt_with_grass", param1=255, param2=0}, - {name="ignore", param1=255, param2=0}, - {name="air", param1=255, param2=0}, + {name="cobble", param1=255, param2=0}, + {name="dirt_with_grass", param1=255, param2=0}, ... }, yslice_prob = { @@ -3207,7 +3150,7 @@ Definition tables }, -- ^ See 'Schematic specifier' for details. replacements = {["oldname"] = "convert_to", ...}, - flags = "place_center_x, place_center_y, place_center_z, force_placement", + flags = "place_center_x, place_center_z", -- ^ Flags for schematic decorations. See 'Schematic attributes'. rotation = "90" -- rotate schematic 90 degrees on placement -- ^ Rotation can be "0", "90", "180", "270", or "random". diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index e5ba46d4c..5c0f90df6 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -1,4 +1,4 @@ -Minetest Lua Mainmenu API Reference 0.4.12 +Minetest Lua Mainmenu API Reference 0.4.11 ======================================== Introduction @@ -197,11 +197,9 @@ core.delete_world(index) Helpers: core.gettext(string) -> string ^ look up the translation of a string in the gettext message catalog -fgettext_ne(string, ...) -^ call core.gettext(string), replace "$1"..."$9" with the given -^ extra arguments and return the result fgettext(string, ...) -> string -^ same as fgettext_ne(), but calls core.formspec_escape before returning result +^ call core.gettext(string), replace "$1"..."$9" with the given +^ extra arguments, call core.formspec_escape and return the result core.parse_json(string[, nullvalue]) -> something (possible in async calls) ^ see core.parse_json (lua_api.txt) dump(obj, dumped={}) @@ -213,12 +211,6 @@ string:trim() core.is_yes(arg) (possible in async calls) ^ returns whether arg can be interpreted as yes -Version compat: -core.get_min_supp_proto() -^ returns the minimum supported network protocol version -core.get_max_supp_proto() -^ returns the maximum supported network protocol version - Async: core.handle_async(async_job,parameters,finished) ^ execute a function asynchronously diff --git a/minetest.conf.example b/minetest.conf.example index 5e8637897..eb883fa8e 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -48,7 +48,6 @@ #keymap_rangeselect = KEY_KEY_R #keymap_freemove = KEY_KEY_K #keymap_fastmove = KEY_KEY_J -#keymap_cinematic = KEY_F8 #keymap_screenshot = KEY_F12 # If true, keymap_special1 instead of keymap_sneak is used for climbing down and descending #aux1_descends = false @@ -128,13 +127,6 @@ #free_move = false # Continuous forward movement (for testing) #continuous_forward = false -# Enable cinematic mode -#cinematic = false -# Camera smoothing - smooths rotation of camera. 0 is no smoothing. -# Must be equal to or greater than 0, and less than 1. -#camera_smoothing = 0.0 -# Camera smoothing when in cinematic mode -#cinematic_camera_smoothing = 0.7 # Fast movement (keymap_special1) #fast_move = false # Invert mouse @@ -260,16 +252,16 @@ #freetype = true # Path to TrueTypeFont or bitmap #font_path = fonts/liberationsans.ttf -#font_size = 15 +#font_size = 13 # Font shadow offset, if 0 then shadow will not be drawn #font_shadow = 1 # Font shadow alpha (opaqueness, between 0 and 255) #font_shadow_alpha = 128 #mono_font_path = fonts/liberationmono.ttf -#mono_font_size = 15 +#mono_font_size = 13 # This font will be used for certain languages #fallback_font_path = fonts/DroidSansFallbackFull.ttf -#fallback_font_size = 15 +#fallback_font_size = 13 #fallback_font_shadow = 1 #fallback_font_shadow_alpha = 128 # Override language. When no value is provided (default) system language is used. @@ -345,7 +337,6 @@ # If true, disable cheat prevention in multiplayer #disable_anticheat = false # If true, actions are recorded for rollback -# This option is only read when server starts #enable_rollback_recording = false # Handling for deprecated lua api calls: # "legacy" = (try to) mimic old behaviour (default for release). @@ -469,8 +460,6 @@ # Controls size of deserts and beaches in Mapgen V6 #mgv6_freq_desert = 0.45 #mgv6_freq_beach = 0.15 -# Enable/disable floating dungeons and dungeon slices -#enable_floating_dungeons = true # Perlin noise attributes for different map generation parameters. # Noise parameters can be specified as a set of positional values: @@ -488,14 +477,33 @@ # flags = "defaults" #} # Only the group format supports noise flags which are needed for eased noise. -# Mgv5 uses eased noise for np_ground so this is shown in group format, -# other noise parameters are shown in positional format to save space. +# Mgv5 uses eased noise for np_cave1, np_cave2, np_ground and np_crumble, so these are shown in +# group format, other noise parameters are shown in positional format to save space. +#mgv5_spflags = blobs #mgv5_np_filler_depth = 0, 1, (150, 150, 150), 261, 4, 0.7, 2.0 #mgv5_np_factor = 0, 1, (250, 250, 250), 920381, 3, 0.45, 2.0 #mgv5_np_height = 0, 10, (250, 250, 250), 84174, 4, 0.5, 2.0 -#mgv5_np_cave1 = 0, 12, (50, 50, 50), 52534, 4, 0.5, 2.0 -#mgv5_np_cave2 = 0, 12, (50, 50, 50), 10325, 4, 0.5, 2.0 +#mgv5_np_cave1 = { +# offset = 0 +# scale = 6 +# spread = (50, 50, 50) +# seed = 52534 +# octaves = 4 +# persistence = 0.5 +# lacunarity = 2.0 +# flags = "eased" +#} +#mgv5_np_cave2 = { +# offset = 0 +# scale = 6 +# spread = (50, 50, 50) +# seed = 10325 +# octaves = 4 +# persistence = 0.5 +# lacunarity = 2.0 +# flags = "eased" +#} #mgv5_np_ground = { # offset = 0 # scale = 40 @@ -506,6 +514,17 @@ # lacunarity = 2.0 # flags = "eased" #} +#mgv5_np_crumble = { +# offset = 0 +# scale = 1 +# spread = (20, 20, 20) +# seed = 34413 +# octaves = 3 +# persistence = 1.3 +# lacunarity = 2.0 +# flags = "eased" +#} +#mgv5_np_wetness = 0, 1, (40, 40, 40), 32474, 4, 1.1, 2.0 #mgv6_spflags = biomeblend, jungles, mudflow #mgv6_np_terrain_base = -4, 20, (250, 250, 250), 82341, 5, 0.6, 2.0 diff --git a/misc/minetest.desktop b/misc/minetest.desktop index 896404789..36decb43f 100644 --- a/misc/minetest.desktop +++ b/misc/minetest.desktop @@ -2,8 +2,6 @@ Name=Minetest GenericName=Minetest Comment=Multiplayer infinite-world block sandbox -Comment[fr]=Jeu multijoueurs de type bac à sable avec des mondes infinis -Comment[de]=Mehrspieler-Sandkastenspiel mit unendlichen Blockwelten Exec=minetest Icon=minetest-icon Terminal=false diff --git a/po/cs/minetest.po b/po/cs/minetest.po index 563275b01..ce24e54ae 100644 --- a/po/cs/minetest.po +++ b/po/cs/minetest.po @@ -1,23 +1,24 @@ -# Czech translations for minetest. -# Copyright (C) 2011 celeron -# This file is distributed under the same license as the minetest. +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: minetest\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-02-12 13:13+0100\n" -"PO-Revision-Date: 2015-02-12 16:16+0100\n" -"Last-Translator: Jakub Vanek \n" -"Language-Team: Czech <>\n" +"POT-Creation-Date: 2014-12-13 15:24+0100\n" +"PO-Revision-Date: 2013-12-04 11:23+0200\n" +"Last-Translator: Jakub Vaněk \n" +"Language-Team: LANGUAGE \n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: Weblate 1.7-dev\n" -#: builtin/fstk/ui.lua:67 builtin/mainmenu/store.lua:165 +#: builtin/fstk/ui.lua:67 msgid "Ok" msgstr "OK" @@ -28,18 +29,18 @@ msgstr "Svět:" #: builtin/mainmenu/dlg_config_world.lua:30 #: builtin/mainmenu/dlg_config_world.lua:32 msgid "Hide Game" -msgstr "Skrýt vnitřní" +msgstr "Skrýt interní" #: builtin/mainmenu/dlg_config_world.lua:36 #: builtin/mainmenu/dlg_config_world.lua:38 msgid "Hide mp content" -msgstr "Skrýt obsahy balíčků" +msgstr "Skrýt obsah balíčku" #: builtin/mainmenu/dlg_config_world.lua:46 msgid "Mod:" -msgstr "Mod:" +msgstr "Mody:" -#: builtin/mainmenu/dlg_config_world.lua:48 builtin/mainmenu/tab_mods.lua:99 +#: builtin/mainmenu/dlg_config_world.lua:48 msgid "Depends:" msgstr "Závislosti:" @@ -81,7 +82,7 @@ msgstr "Seedové číslo" #: builtin/mainmenu/dlg_create_world.lua:56 msgid "Mapgen" -msgstr "Generátor mapy" +msgstr "Generátor světa" #: builtin/mainmenu/dlg_create_world.lua:59 msgid "Game" @@ -93,19 +94,19 @@ msgstr "Vytvořit" #: builtin/mainmenu/dlg_create_world.lua:68 msgid "You have no subgames installed." -msgstr "Nemáte nainstalované žádné podhry." +msgstr "" #: builtin/mainmenu/dlg_create_world.lua:69 msgid "Download one from minetest.net" -msgstr "Stáhněte si jednu z minetest.net" +msgstr "" #: builtin/mainmenu/dlg_create_world.lua:72 msgid "Warning: The minimal development test is meant for developers." -msgstr "Varování: \"Minimal development test\" je zamýšlen pouze pro vývojáře." +msgstr "" #: builtin/mainmenu/dlg_create_world.lua:73 msgid "Download a subgame, such as minetest_game, from minetest.net" -msgstr "Stáhněte si z minetest.net podhru, například minetest_game." +msgstr "" #: builtin/mainmenu/dlg_create_world.lua:97 msgid "A world named \"$1\" already exists" @@ -113,7 +114,7 @@ msgstr "Svět s názvem \"$1\" už existuje" #: builtin/mainmenu/dlg_create_world.lua:116 msgid "No worldname given or no game selected" -msgstr "Nebyla vybrána podhra nebo název" +msgstr "Nebyla vybrána žádná hra" #: builtin/mainmenu/dlg_delete_mod.lua:26 msgid "Are you sure you want to delete \"$1\"?" @@ -121,7 +122,7 @@ msgstr "Skutečně chcete odstranit \"$1\"?" #: builtin/mainmenu/dlg_delete_mod.lua:27 #: builtin/mainmenu/dlg_delete_world.lua:25 -#: builtin/mainmenu/tab_settings.lua:79 +#: builtin/mainmenu/tab_settings.lua:25 msgid "Yes" msgstr "Ano" @@ -155,15 +156,16 @@ msgstr "Přijmout" #: builtin/mainmenu/modmgr.lua:342 msgid "Install Mod: file: \"$1\"" -msgstr "Instalace modu: ze souboru: \"$1\"" +msgstr "Instalace Modu: ze souboru: \"$1\"" #: builtin/mainmenu/modmgr.lua:343 +#, fuzzy msgid "" "\n" "Install Mod: unsupported filetype \"$1\" or broken archive" msgstr "" "\n" -"Instalace modu: špatný archiv nebo nepodporovaný typ souboru \"$1\"" +"Instalace Modu: nepodporovaný typ souboru \"$1\"" #: builtin/mainmenu/modmgr.lua:363 msgid "Failed to install $1 to $2" @@ -171,49 +173,60 @@ msgstr "Selhala instalace $1 do $2" #: builtin/mainmenu/modmgr.lua:366 msgid "Install Mod: unable to find suitable foldername for modpack $1" -msgstr "Instalace modu: nenalezen vhodný adresář s příslušným názvem pro balíček $1" +msgstr "" +"Install Mod: nenalezen vhodný adresář s příslušným názvem pro balíček modů $1" #: builtin/mainmenu/modmgr.lua:386 msgid "Install Mod: unable to find real modname for: $1" -msgstr "Instalace modu: nenašel jsem skutečné jméno modu: $1" +msgstr "Install Mod: Nenašel jsem skutečné jméno modu: $1" #: builtin/mainmenu/store.lua:88 msgid "Unsorted" -msgstr "Neřazené" +msgstr "" -#: builtin/mainmenu/store.lua:99 builtin/mainmenu/store.lua:580 +#: builtin/mainmenu/store.lua:99 builtin/mainmenu/store.lua:584 msgid "Search" -msgstr "Hledání" +msgstr "" -#: builtin/mainmenu/store.lua:126 -msgid "Downloading $1, please wait..." -msgstr "Stahuji $1, prosím čekejte..." +#: builtin/mainmenu/store.lua:125 +#, fuzzy +msgid "Downloading" +msgstr "Stáhnout" -#: builtin/mainmenu/store.lua:160 +#: builtin/mainmenu/store.lua:127 +msgid "please wait..." +msgstr "" + +#: builtin/mainmenu/store.lua:159 msgid "Successfully installed:" -msgstr "Úspěšně nainstalováno:" +msgstr "" -#: builtin/mainmenu/store.lua:162 +#: builtin/mainmenu/store.lua:163 +#, fuzzy msgid "Shortname:" -msgstr "Zkratka:" +msgstr "Název světa" -#: builtin/mainmenu/store.lua:472 +#: builtin/mainmenu/store.lua:167 src/guiFormSpecMenu.cpp:2866 +msgid "ok" +msgstr "" + +#: builtin/mainmenu/store.lua:476 msgid "Rating" msgstr "Hodnocení" -#: builtin/mainmenu/store.lua:497 +#: builtin/mainmenu/store.lua:501 msgid "re-Install" -msgstr "Přeinstalovat" +msgstr "přeinstalovat" -#: builtin/mainmenu/store.lua:499 +#: builtin/mainmenu/store.lua:503 msgid "Install" msgstr "Instalovat" -#: builtin/mainmenu/store.lua:518 +#: builtin/mainmenu/store.lua:522 msgid "Close store" -msgstr "Zavřít obchod" +msgstr "" -#: builtin/mainmenu/store.lua:526 +#: builtin/mainmenu/store.lua:530 msgid "Page $1 of $2" msgstr "Strana $1 z $2" @@ -235,7 +248,7 @@ msgstr "Bývalí přispěvatelé" #: builtin/mainmenu/tab_mods.lua:30 msgid "Installed Mods:" -msgstr "Nainstalované mody:" +msgstr "Nainstalované Mody:" #: builtin/mainmenu/tab_mods.lua:39 msgid "Online mod repository" @@ -255,7 +268,7 @@ msgstr "Přejmenovat" #: builtin/mainmenu/tab_mods.lua:95 msgid "Uninstall selected modpack" -msgstr "Odinstalovat označený balíček" +msgstr "Odinstalovat označený balíček modů" #: builtin/mainmenu/tab_mods.lua:106 msgid "Uninstall selected mod" @@ -263,53 +276,39 @@ msgstr "Odinstalovat vybraný mod" #: builtin/mainmenu/tab_mods.lua:121 msgid "Select Mod File:" -msgstr "Vybrat soubor s modem:" +msgstr "Vybrat Soubor s Modem:" #: builtin/mainmenu/tab_mods.lua:165 msgid "Mods" msgstr "Mody" #: builtin/mainmenu/tab_multiplayer.lua:23 -msgid "Address / Port :" -msgstr "Adresa / Port :" +msgid "Address/Port" +msgstr "Adresa/port" -#: builtin/mainmenu/tab_multiplayer.lua:24 -msgid "Name / Password :" -msgstr "Jméno / Heslo :" +#: builtin/mainmenu/tab_multiplayer.lua:24 builtin/mainmenu/tab_server.lua:37 +#: builtin/mainmenu/tab_simple_main.lua:25 +msgid "Name/Password" +msgstr "Jméno/Heslo" #: builtin/mainmenu/tab_multiplayer.lua:29 #: builtin/mainmenu/tab_simple_main.lua:30 msgid "Public Serverlist" -msgstr "Seznam veřejných serverů" +msgstr "Veřejný seznam serverů" #: builtin/mainmenu/tab_multiplayer.lua:34 builtin/mainmenu/tab_server.lua:26 #: builtin/mainmenu/tab_singleplayer.lua:85 src/keycode.cpp:230 msgid "Delete" -msgstr "Smazat" +msgstr "Vymazat" #: builtin/mainmenu/tab_multiplayer.lua:38 #: builtin/mainmenu/tab_simple_main.lua:34 msgid "Connect" msgstr "Připojit" -#: builtin/mainmenu/tab_multiplayer.lua:62 -#: builtin/mainmenu/tab_simple_main.lua:45 -msgid "Creative mode" -msgstr "Kreativní mód" - -#: builtin/mainmenu/tab_multiplayer.lua:63 -#: builtin/mainmenu/tab_simple_main.lua:46 -msgid "Damage enabled" -msgstr "Poškození povoleno" - -#: builtin/mainmenu/tab_multiplayer.lua:64 -#: builtin/mainmenu/tab_simple_main.lua:47 -msgid "PvP enabled" -msgstr "PvP povoleno" - -#: builtin/mainmenu/tab_multiplayer.lua:247 +#: builtin/mainmenu/tab_multiplayer.lua:252 msgid "Client" -msgstr "Klient" +msgstr "Hra více hráčů" #: builtin/mainmenu/tab_server.lua:27 builtin/mainmenu/tab_singleplayer.lua:86 msgid "New" @@ -321,18 +320,18 @@ msgstr "Nastavit" #: builtin/mainmenu/tab_server.lua:29 msgid "Start Game" -msgstr "Spustit hru" +msgstr "Začít hru" #: builtin/mainmenu/tab_server.lua:30 builtin/mainmenu/tab_singleplayer.lua:89 msgid "Select World:" msgstr "Vyber svět:" -#: builtin/mainmenu/tab_server.lua:31 builtin/mainmenu/tab_simple_main.lua:75 +#: builtin/mainmenu/tab_server.lua:31 builtin/mainmenu/tab_simple_main.lua:63 #: builtin/mainmenu/tab_singleplayer.lua:90 msgid "Creative Mode" msgstr "Kreativní mód" -#: builtin/mainmenu/tab_server.lua:33 builtin/mainmenu/tab_simple_main.lua:77 +#: builtin/mainmenu/tab_server.lua:33 builtin/mainmenu/tab_simple_main.lua:65 #: builtin/mainmenu/tab_singleplayer.lua:92 msgid "Enable Damage" msgstr "Povolit poškození" @@ -341,17 +340,13 @@ msgstr "Povolit poškození" msgid "Public" msgstr "Veřejný" -#: builtin/mainmenu/tab_server.lua:37 builtin/mainmenu/tab_simple_main.lua:25 -msgid "Name/Password" -msgstr "Jméno/Heslo" - #: builtin/mainmenu/tab_server.lua:45 msgid "Bind Address" -msgstr "Svázat adresu" +msgstr "" #: builtin/mainmenu/tab_server.lua:47 msgid "Port" -msgstr "Port" +msgstr "" #: builtin/mainmenu/tab_server.lua:51 msgid "Server Port" @@ -359,153 +354,140 @@ msgstr "Port serveru" #: builtin/mainmenu/tab_server.lua:174 msgid "Server" -msgstr "Server" - -#: builtin/mainmenu/tab_settings.lua:21 -msgid "No Filter" -msgstr "Žádný filtr" - -#: builtin/mainmenu/tab_settings.lua:22 -msgid "Bilinear Filter" -msgstr "Bilineární filtr" +msgstr "Místní server" #: builtin/mainmenu/tab_settings.lua:23 -msgid "Trilinear Filter" -msgstr "Trilineární filtr" - -#: builtin/mainmenu/tab_settings.lua:32 -msgid "No Mipmap" -msgstr "Žádné Mipmapy" - -#: builtin/mainmenu/tab_settings.lua:33 -msgid "Mipmap" -msgstr "Mipmapa" - -#: builtin/mainmenu/tab_settings.lua:34 -msgid "Mipmap + Aniso. Filter" -msgstr "Mipmapa + Anizo. filtr" - -#: builtin/mainmenu/tab_settings.lua:77 msgid "Are you sure to reset your singleplayer world?" -msgstr "Jste si jisti, že chcete resetovat místní svět?" +msgstr "" -#: builtin/mainmenu/tab_settings.lua:81 +#: builtin/mainmenu/tab_settings.lua:27 msgid "No!!!" -msgstr "Ne!!!" +msgstr "" -#: builtin/mainmenu/tab_settings.lua:181 +#: builtin/mainmenu/tab_settings.lua:134 msgid "Smooth Lighting" -msgstr "Plynulé osvětlení" +msgstr "Hladké osvětlení" -#: builtin/mainmenu/tab_settings.lua:183 +#: builtin/mainmenu/tab_settings.lua:136 msgid "Enable Particles" -msgstr "Povolit částice" +msgstr "Povolit Částice" -#: builtin/mainmenu/tab_settings.lua:185 +#: builtin/mainmenu/tab_settings.lua:138 msgid "3D Clouds" -msgstr "3D mraky" +msgstr "3D Mraky" -#: builtin/mainmenu/tab_settings.lua:187 +#: builtin/mainmenu/tab_settings.lua:140 +#, fuzzy msgid "Fancy Trees" -msgstr "Ozdobné stromy" +msgstr "Pěkné stromy" -#: builtin/mainmenu/tab_settings.lua:189 +#: builtin/mainmenu/tab_settings.lua:142 msgid "Opaque Water" msgstr "Neprůhledná voda" -#: builtin/mainmenu/tab_settings.lua:191 +#: builtin/mainmenu/tab_settings.lua:144 +#, fuzzy msgid "Connected Glass" -msgstr "Propojené sklo" +msgstr "Připojit" -#: builtin/mainmenu/tab_settings.lua:193 -msgid "Node Highlighting" -msgstr "Zvýraznění bloků" - -#: builtin/mainmenu/tab_settings.lua:196 -msgid "Texturing:" -msgstr "Texturování:" - -#: builtin/mainmenu/tab_settings.lua:201 -msgid "Rendering:" -msgstr "Renderování:" - -#: builtin/mainmenu/tab_settings.lua:205 +#: builtin/mainmenu/tab_settings.lua:149 msgid "Restart minetest for driver change to take effect" -msgstr "Aby se změna ovladače projevila, restartujte Minetest." +msgstr "" -#: builtin/mainmenu/tab_settings.lua:207 +#: builtin/mainmenu/tab_settings.lua:151 +msgid "Mip-Mapping" +msgstr "Mip-Mapování" + +#: builtin/mainmenu/tab_settings.lua:153 +msgid "Anisotropic Filtering" +msgstr "Anizotropní filtrování" + +#: builtin/mainmenu/tab_settings.lua:155 +msgid "Bi-Linear Filtering" +msgstr "Bilineární filtrování" + +#: builtin/mainmenu/tab_settings.lua:157 +msgid "Tri-Linear Filtering" +msgstr "Trilineární filtrování" + +#: builtin/mainmenu/tab_settings.lua:160 msgid "Shaders" msgstr "Shadery" -#: builtin/mainmenu/tab_settings.lua:212 +#: builtin/mainmenu/tab_settings.lua:164 msgid "Change keys" msgstr "Změnit nastavení kláves" -#: builtin/mainmenu/tab_settings.lua:215 +#: builtin/mainmenu/tab_settings.lua:167 +#, fuzzy msgid "Reset singleplayer world" -msgstr "Reset místního světa" +msgstr "Hra jednoho hráče" -#: builtin/mainmenu/tab_settings.lua:219 +#: builtin/mainmenu/tab_settings.lua:171 msgid "GUI scale factor" -msgstr "Měřítko GUI" +msgstr "" -#: builtin/mainmenu/tab_settings.lua:223 +#: builtin/mainmenu/tab_settings.lua:175 msgid "Scaling factor applied to menu elements: " -msgstr "Měřítko aplikované na prvky menu: " +msgstr "" -#: builtin/mainmenu/tab_settings.lua:229 +#: builtin/mainmenu/tab_settings.lua:181 msgid "Touch free target" -msgstr "Středový kurzor" +msgstr "" -#: builtin/mainmenu/tab_settings.lua:235 +#: builtin/mainmenu/tab_settings.lua:187 msgid "Touchthreshold (px)" -msgstr "Dosah dotyku (px)" +msgstr "" -#: builtin/mainmenu/tab_settings.lua:242 builtin/mainmenu/tab_settings.lua:256 +#: builtin/mainmenu/tab_settings.lua:194 builtin/mainmenu/tab_settings.lua:208 +#, fuzzy msgid "Bumpmapping" -msgstr "Bump mapování" +msgstr "Mip-Mapování" -#: builtin/mainmenu/tab_settings.lua:244 builtin/mainmenu/tab_settings.lua:257 +#: builtin/mainmenu/tab_settings.lua:196 builtin/mainmenu/tab_settings.lua:209 msgid "Generate Normalmaps" -msgstr "Generovat normálové mapy" +msgstr "" -#: builtin/mainmenu/tab_settings.lua:246 builtin/mainmenu/tab_settings.lua:258 +#: builtin/mainmenu/tab_settings.lua:198 builtin/mainmenu/tab_settings.lua:210 msgid "Parallax Occlusion" -msgstr "Parallax Occlusion" +msgstr "" -#: builtin/mainmenu/tab_settings.lua:248 builtin/mainmenu/tab_settings.lua:259 +#: builtin/mainmenu/tab_settings.lua:200 builtin/mainmenu/tab_settings.lua:211 msgid "Waving Water" -msgstr "Vlnění vody" +msgstr "" -#: builtin/mainmenu/tab_settings.lua:250 builtin/mainmenu/tab_settings.lua:260 +#: builtin/mainmenu/tab_settings.lua:202 builtin/mainmenu/tab_settings.lua:212 msgid "Waving Leaves" -msgstr "Vlnění listů" +msgstr "" -#: builtin/mainmenu/tab_settings.lua:252 builtin/mainmenu/tab_settings.lua:261 +#: builtin/mainmenu/tab_settings.lua:204 builtin/mainmenu/tab_settings.lua:213 msgid "Waving Plants" -msgstr "Vlnění rostlin" +msgstr "" -#: builtin/mainmenu/tab_settings.lua:287 +#: builtin/mainmenu/tab_settings.lua:255 msgid "To enable shaders the OpenGL driver needs to be used." -msgstr "Pro povolení shaderů musíte používat OpenGL ovladač." +msgstr "Pro povolení shaderů je nutné používat OpenGL ovladač." -#: builtin/mainmenu/tab_settings.lua:398 +#: builtin/mainmenu/tab_settings.lua:330 msgid "Settings" msgstr "Nastavení" -#: builtin/mainmenu/tab_simple_main.lua:79 +#: builtin/mainmenu/tab_simple_main.lua:67 msgid "Fly mode" -msgstr "Létací režim" +msgstr "" -#: builtin/mainmenu/tab_simple_main.lua:83 +#: builtin/mainmenu/tab_simple_main.lua:71 +#, fuzzy msgid "Start Singleplayer" -msgstr "Start místní hry" +msgstr "Hra jednoho hráče" -#: builtin/mainmenu/tab_simple_main.lua:84 +#: builtin/mainmenu/tab_simple_main.lua:72 +#, fuzzy msgid "Config mods" -msgstr "Nastavení modů" +msgstr "Nastavit" -#: builtin/mainmenu/tab_simple_main.lua:203 +#: builtin/mainmenu/tab_simple_main.lua:191 +#, fuzzy msgid "Main" msgstr "Hlavní nabídka" @@ -515,7 +497,7 @@ msgstr "Hrát" #: builtin/mainmenu/tab_singleplayer.lua:224 msgid "Singleplayer" -msgstr "Místní hra" +msgstr "Hra jednoho hráče" #: builtin/mainmenu/tab_texturepacks.lua:49 msgid "Select texture pack:" @@ -526,168 +508,43 @@ msgid "No information available" msgstr "Informace nejsou dostupné" #: builtin/mainmenu/tab_texturepacks.lua:114 +#, fuzzy msgid "Texturepacks" msgstr "Balíčky textur" -#: src/client.cpp:2788 -msgid "Loading textures..." -msgstr "Načítám textury..." - -#: src/client.cpp:2798 -msgid "Rebuilding shaders..." -msgstr "Sestavuji shadery..." - -#: src/client.cpp:2805 -msgid "Initializing nodes..." -msgstr "Inicializuji bloky..." - -#: src/client.cpp:2820 +#: src/client.cpp:2726 msgid "Item textures..." -msgstr "Textury věcí..." - -#: src/client.cpp:2845 -msgid "Done!" -msgstr "Hotovo!" +msgstr "Textury předmětů..." #: src/fontengine.cpp:70 src/fontengine.cpp:226 msgid "needs_fallback_font" msgstr "no" -#: src/game.cpp:1057 src/guiFormSpecMenu.cpp:2006 -msgid "Proceed" -msgstr "Pokračovat" - -#: src/game.cpp:1077 -msgid "You died." -msgstr "Zemřel jsi." - -#: src/game.cpp:1078 +#: src/game.cpp:1063 msgid "Respawn" -msgstr "Znovu stvořit" +msgstr "Oživení" -#: src/game.cpp:1097 -msgid "" -"Default Controls:\n" -"No menu visible:\n" -"- single tap: button activate\n" -"- double tap: place/use\n" -"- slide finger: look around\n" -"Menu/Inventory visible:\n" -"- double tap (outside):\n" -" -->close\n" -"- touch stack, touch slot:\n" -" --> move stack\n" -"- touch&drag, tap 2nd finger\n" -" --> place single item to slot\n" -msgstr "" -"Výchozí ovládání:\n" -"Bez menu:\n" -"- klik: aktivace tlačítka\n" -"- dvojklik: položit/použít\n" -"- pohyb prstem: rozhlížení\n" -"Menu/Inventář zobrazen:\n" -"- dvojklik (mimo):\n" -" -->zavřít\n" -"- stisk hromádky, přihrádky :\n" -" --> přesunutí hromádky\n" -"- stisk a přesun, klik druhým prstem\n" -" --> umístit samostatnou věc do přihrádky\n" - -#: src/game.cpp:1111 -msgid "" -"Default Controls:\n" -"- WASD: move\n" -"- Space: jump/climb\n" -"- Shift: sneak/go down\n" -"- Q: drop item\n" -"- I: inventory\n" -"- Mouse: turn/look\n" -"- Mouse left: dig/punch\n" -"- Mouse right: place/use\n" -"- Mouse wheel: select item\n" -"- T: chat\n" -msgstr "" -"Výchozí ovládání:\n" -"- WASD: pohyb\n" -"- Mezera: skákání/šplhání\n" -"- Shift: plížení\n" -"- Q: zahodit věc\n" -"- I: inventář\n" -"- Myš: otáčení,rozhlížení\n" -"- Myš(levé tl.): kopat, štípat\n" -"- Myš(pravé tl.): položit, použít\n" -"- Myš(kolečko): vybrat přihrádku\n" -"- T: chat\n" - -#: src/game.cpp:1130 -msgid "Continue" -msgstr "Pokračovat" - -#: src/game.cpp:1134 -msgid "Change Password" -msgstr "Změnit heslo" - -#: src/game.cpp:1139 -msgid "Sound Volume" -msgstr "Hlasitost" - -#: src/game.cpp:1141 -msgid "Change Keys" -msgstr "Změnit klávesy" - -#: src/game.cpp:1144 -msgid "Exit to Menu" -msgstr "Odejít do nabídky" - -#: src/game.cpp:1146 -msgid "Exit to OS" -msgstr "Ukončit hru" - -#: src/game.cpp:1809 -msgid "Shutting down..." -msgstr "Vypínání..." - -#: src/game.cpp:1858 -msgid "Loading..." -msgstr "Nahrávám..." - -#: src/game.cpp:1915 -msgid "Creating server..." -msgstr "Vytvářím server..." - -#: src/game.cpp:1952 -msgid "Creating client..." -msgstr "Vytvářím klienta..." - -#: src/game.cpp:2125 -msgid "Resolving address..." -msgstr "Překládám adresu..." - -#: src/game.cpp:2216 -msgid "Connecting to server..." -msgstr "Připojuji se k serveru..." - -#: src/game.cpp:2274 +#: src/game.cpp:2250 msgid "Item definitions..." -msgstr "Definice věcí..." +msgstr "Definice předmětů..." -#: src/game.cpp:2279 +#: src/game.cpp:2255 msgid "Node definitions..." msgstr "Definice bloků..." -#: src/game.cpp:2286 +#: src/game.cpp:2262 msgid "Media..." msgstr "Média..." -#: src/game.cpp:2291 +#: src/game.cpp:2267 msgid " KB/s" -msgstr " KB/s" +msgstr "" -#: src/game.cpp:2295 +#: src/game.cpp:2271 msgid " MB/s" -msgstr " MB/s" +msgstr "" -#: src/game.cpp:4210 +#: src/game.cpp:4220 msgid "" "\n" "Check debug.txt for details." @@ -695,17 +552,18 @@ msgstr "" "\n" "Pro detaily se podívejte do debug.txt." -#: src/guiFormSpecMenu.cpp:2797 -msgid "Enter " -msgstr "Zadejte " +#: src/guiFormSpecMenu.cpp:2055 +msgid "Proceed" +msgstr "Pokračovat" -#: src/guiFormSpecMenu.cpp:2817 -msgid "ok" -msgstr "OK" +#: src/guiFormSpecMenu.cpp:2846 +msgid "Enter " +msgstr "" #: src/guiKeyChangeMenu.cpp:125 msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)" -msgstr "Nastavení kláves (Pokud tohle menu nebude v pořádku, odstraňte nastavení z " +msgstr "" +"Nastavení kláves. (Pokud tohle menu nebude v pořádku, odstraňte nastavení z " "minetest.conf)" #: src/guiKeyChangeMenu.cpp:165 @@ -714,7 +572,7 @@ msgstr "\"Použít\" = slézt dolů" #: src/guiKeyChangeMenu.cpp:180 msgid "Double tap \"jump\" to toggle fly" -msgstr "Dvojstisk klávesy \"skok\" zapne létání" +msgstr "Dvě zmáčknutí klávesy \"skok\" zapnou létání" #: src/guiKeyChangeMenu.cpp:296 msgid "Key already in use" @@ -734,11 +592,11 @@ msgstr "Vzad" #: src/guiKeyChangeMenu.cpp:399 src/keycode.cpp:229 msgid "Left" -msgstr "Doleva" +msgstr "Vlevo" #: src/guiKeyChangeMenu.cpp:400 src/keycode.cpp:229 msgid "Right" -msgstr "Doprava" +msgstr "Vpravo" #: src/guiKeyChangeMenu.cpp:401 msgid "Use" @@ -750,7 +608,7 @@ msgstr "Skok" #: src/guiKeyChangeMenu.cpp:403 msgid "Sneak" -msgstr "Plížit se" +msgstr "Plížení" #: src/guiKeyChangeMenu.cpp:404 msgid "Drop" @@ -778,11 +636,11 @@ msgstr "Létání" #: src/guiKeyChangeMenu.cpp:410 msgid "Toggle fast" -msgstr "Turbo" +msgstr "Rychlý pohyb" #: src/guiKeyChangeMenu.cpp:411 msgid "Toggle noclip" -msgstr "Duch" +msgstr "Noclip" #: src/guiKeyChangeMenu.cpp:412 msgid "Range select" @@ -792,25 +650,25 @@ msgstr "Změna dohledu" msgid "Print stacks" msgstr "Vypsat hromádky" -#: src/guiPasswordChange.cpp:108 +#: src/guiPasswordChange.cpp:106 msgid "Old Password" msgstr "Staré heslo" -#: src/guiPasswordChange.cpp:124 +#: src/guiPasswordChange.cpp:122 msgid "New Password" msgstr "Nové heslo" -#: src/guiPasswordChange.cpp:139 +#: src/guiPasswordChange.cpp:137 msgid "Confirm Password" msgstr "Potvrdit heslo" -#: src/guiPasswordChange.cpp:155 +#: src/guiPasswordChange.cpp:153 msgid "Change" msgstr "Změnit" -#: src/guiPasswordChange.cpp:164 +#: src/guiPasswordChange.cpp:162 msgid "Passwords do not match!" -msgstr "Hesla se neshodují!" +msgstr "Hesla si neodpovídají!" #: src/guiVolumeChange.cpp:106 msgid "Sound Volume: " @@ -882,7 +740,7 @@ msgstr "Shift" #: src/keycode.cpp:227 msgid "Convert" -msgstr "Convert" +msgstr "Převádět" #: src/keycode.cpp:227 msgid "Escape" @@ -890,7 +748,7 @@ msgstr "Esc" #: src/keycode.cpp:227 msgid "Final" -msgstr "Final" +msgstr "Konečný" #: src/keycode.cpp:227 msgid "Junja" @@ -902,7 +760,7 @@ msgstr "Kanji" #: src/keycode.cpp:227 msgid "Nonconvert" -msgstr "Nonconvert" +msgstr "Nepřevádět" #: src/keycode.cpp:228 msgid "End" @@ -954,7 +812,7 @@ msgstr "Pomoc" #: src/keycode.cpp:230 msgid "Insert" -msgstr "Insert" +msgstr "Vložit" #: src/keycode.cpp:230 msgid "Snapshot" @@ -1108,111 +966,165 @@ msgstr "PA1" msgid "Zoom" msgstr "Přiblížení" -#: src/main.cpp:1688 +#: src/main.cpp:1681 msgid "Main Menu" msgstr "Hlavní nabídka" -#: src/main.cpp:1726 +#: src/main.cpp:1719 msgid "Player name too long." -msgstr "Jméno hráče je příliš dlouhé." +msgstr "" -#: src/main.cpp:1764 +#: src/main.cpp:1757 msgid "Connection error (timed out?)" msgstr "Chyba spojení (vypršel čas?)" -#: src/main.cpp:1929 +#: src/main.cpp:1919 msgid "No world selected and no address provided. Nothing to do." -msgstr "Nebyl vybrán žádný svět a nebyla poskytnuta žádná adresa. Nemám co dělat." +msgstr "" +"Nebyl vybrán žádný svět a nebyla poskytnuta žádná adresa. Nemám co dělat." -#: src/main.cpp:1936 +#: src/main.cpp:1926 msgid "Provided world path doesn't exist: " -msgstr "Uvedená cesta ke světu neexistuje: " +msgstr "" -#: src/main.cpp:1945 +#: src/main.cpp:1935 msgid "Could not find or load game \"" msgstr "Hru nebylo možné nahrát nebo najít \"" -#: src/main.cpp:1963 +#: src/main.cpp:1953 msgid "Invalid gamespec." msgstr "Neplatná specifikace hry." -msgid "Downloading" -msgstr "Stahuji" +#~ msgid "Left click: Move all items, Right click: Move single item" +#~ msgstr "" +#~ "Levý klik: Přesunout všechny předměty, Pravý klik: Přesunout jeden předmět" -#~ msgid "Game Name" -#~ msgstr "Název hry" +#~ msgid "" +#~ "Default Controls:\n" +#~ "- WASD: move\n" +#~ "- Space: jump/climb\n" +#~ "- Shift: sneak/go down\n" +#~ "- Q: drop item\n" +#~ "- I: inventory\n" +#~ "- Mouse: turn/look\n" +#~ "- Mouse left: dig/punch\n" +#~ "- Mouse right: place/use\n" +#~ "- Mouse wheel: select item\n" +#~ "- T: chat\n" +#~ msgstr "" +#~ "Výchozí ovládání:\n" +#~ "- WASD: pohyb\n" +#~ "- Mezera: skákání/šplhání\n" +#~ "- Shift: plížení\n" +#~ "- Q: zahodit\n" +#~ "- I: inventář\n" +#~ "- Myš: otáčení,rozhlížení\n" +#~ "- Myš(levé tl.): kopat, štípat\n" +#~ "- Myš(pravé tl.): položit, použít\n" +#~ "- Myš(kolečko): vybrat předmět\n" +#~ "- T: chat\n" -#~ msgid "Gamemgr: Unable to copy mod \"$1\" to game \"$2\"" -#~ msgstr "Gamemgr: Nepovedlo se zkopírovat mod \"$1\" do hry \"$2\"" +#~ msgid "Exit to OS" +#~ msgstr "Ukončit hru" -#~ msgid "GAMES" -#~ msgstr "HRY" +#~ msgid "Exit to Menu" +#~ msgstr "Odejít do Nabídky" -#~ msgid "Games" -#~ msgstr "Hry" +#~ msgid "Sound Volume" +#~ msgstr "Hlasitost" -#~ msgid "Mods:" -#~ msgstr "Mody:" +#~ msgid "Change Password" +#~ msgstr "Změnit heslo" -#~ msgid "edit game" -#~ msgstr "upravit hru" +#~ msgid "Continue" +#~ msgstr "Pokračovat" -#~ msgid "new game" -#~ msgstr "nová hra" +#~ msgid "You died." +#~ msgstr "Zemřel jsi." -#~ msgid "EDIT GAME" -#~ msgstr "UPRAVIT HRU" +#~ msgid "Shutting down stuff..." +#~ msgstr "Vypínám to..." -#~ msgid "Remove selected mod" -#~ msgstr "Odstranit vybraný mod" +#~ msgid "Connecting to server..." +#~ msgstr "Připojuji se k serveru..." -#~ msgid "<<-- Add mod" -#~ msgstr "<<-- Přidat mod" +#~ msgid "Resolving address..." +#~ msgstr "Překládám adresu..." -#~ msgid "CLIENT" -#~ msgstr "KLIENT" +#~ msgid "Creating client..." +#~ msgstr "Vytvářím klienta..." -#~ msgid "Favorites:" -#~ msgstr "Oblíbené:" +#~ msgid "Creating server...." +#~ msgstr "Vytvářím server..." -#~ msgid "START SERVER" -#~ msgstr "MÍSTNÍ SERVER" - -#~ msgid "Name" -#~ msgstr "Jméno" - -#~ msgid "Password" -#~ msgstr "Heslo" - -#~ msgid "SETTINGS" -#~ msgstr "NASTAVENÍ" - -#~ msgid "Preload item visuals" -#~ msgstr "Přednačíst textury předmětů" - -#~ msgid "Finite Liquid" -#~ msgstr "Konečná voda" - -#~ msgid "SINGLE PLAYER" -#~ msgstr "HRA JEDNOHO HRÁČE" - -#~ msgid "TEXTURE PACKS" -#~ msgstr "BALÍČKY TEXTUR" - -#~ msgid "MODS" -#~ msgstr "MODY" - -#~ msgid "Add mod:" -#~ msgstr "Přidat mod:" +#~ msgid "Loading..." +#~ msgstr "Nahrávám..." #~ msgid "Local install" #~ msgstr "Místní instalace" -#~ msgid "Left click: Move all items, Right click: Move single item" -#~ msgstr "Levý klik: Přesunout všechny předměty, Pravý klik: Přesunout jeden předmět" +#~ msgid "Add mod:" +#~ msgstr "Přidat mod:" -#~ msgid "Anisotropic Filtering" -#~ msgstr "Anizotropní filtrování" +#~ msgid "MODS" +#~ msgstr "MODY" -#~ msgid "Mip-Mapping" -#~ msgstr "Mip-Mapování" +#~ msgid "TEXTURE PACKS" +#~ msgstr "BALÍČKY TEXTUR" + +#~ msgid "SINGLE PLAYER" +#~ msgstr "HRA JEDNOHO HRÁČE" + +#~ msgid "Finite Liquid" +#~ msgstr "Konečná voda" + +#~ msgid "Preload item visuals" +#~ msgstr "Přednačíst textury předmětů" + +#~ msgid "SETTINGS" +#~ msgstr "NASTAVENÍ" + +#~ msgid "Password" +#~ msgstr "Heslo" + +#~ msgid "Name" +#~ msgstr "Jméno" + +#~ msgid "START SERVER" +#~ msgstr "MÍSTNÍ SERVER" + +#~ msgid "Favorites:" +#~ msgstr "Oblíbené:" + +#~ msgid "CLIENT" +#~ msgstr "KLIENT" + +#~ msgid "<<-- Add mod" +#~ msgstr "<<-- Přidat mod" + +#~ msgid "Remove selected mod" +#~ msgstr "Odstranit vybraný mod" + +#~ msgid "EDIT GAME" +#~ msgstr "UPRAVIT HRU" + +#~ msgid "new game" +#~ msgstr "nová hra" + +#~ msgid "edit game" +#~ msgstr "upravit hru" + +#~ msgid "Mods:" +#~ msgstr "Mody:" + +#~ msgid "Games" +#~ msgstr "Hry" + +#~ msgid "GAMES" +#~ msgstr "HRY" + +#~ msgid "Gamemgr: Unable to copy mod \"$1\" to game \"$2\"" +#~ msgstr "Gamemgr: Nepovedlo se zkopírovat mod \"$1\" do hry \"$2\"" + +#~ msgid "Game Name" +#~ msgstr "Název hry" diff --git a/po/es/minetest.po b/po/es/minetest.po index 5f60213f2..a5380d597 100644 --- a/po/es/minetest.po +++ b/po/es/minetest.po @@ -7,18 +7,18 @@ msgid "" msgstr "" "Project-Id-Version: minetest\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-02-14 13:50+0100\n" -"PO-Revision-Date: 2015-02-14 13:35+0100\n" +"POT-Creation-Date: 2014-12-13 15:24+0100\n" +"PO-Revision-Date: 2015-01-19 09:56+0100\n" "Last-Translator: Diego de las Heras \n" -"Language-Team: \n" +"Language-Team: LANGUAGE \n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Poedit 1.7.4\n" +"X-Generator: Poedit 1.7.3\n" -#: builtin/fstk/ui.lua:67 builtin/mainmenu/store.lua:165 +#: builtin/fstk/ui.lua:67 msgid "Ok" msgstr "Aceptar" @@ -40,7 +40,7 @@ msgstr "Ocultar contenido mp" msgid "Mod:" msgstr "Mod:" -#: builtin/mainmenu/dlg_config_world.lua:48 builtin/mainmenu/tab_mods.lua:99 +#: builtin/mainmenu/dlg_config_world.lua:48 msgid "Depends:" msgstr "Dependencias:" @@ -124,7 +124,7 @@ msgstr "¿Realmente desea borrar \"$1\"?" #: builtin/mainmenu/dlg_delete_mod.lua:27 #: builtin/mainmenu/dlg_delete_world.lua:25 -#: builtin/mainmenu/tab_settings.lua:79 +#: builtin/mainmenu/tab_settings.lua:25 msgid "Yes" msgstr "Sí" @@ -186,40 +186,48 @@ msgstr "Instalar mod: Imposible encontrar el nombre real del mod para: $1" msgid "Unsorted" msgstr "Sin ordenar" -#: builtin/mainmenu/store.lua:99 builtin/mainmenu/store.lua:580 +#: builtin/mainmenu/store.lua:99 builtin/mainmenu/store.lua:584 msgid "Search" msgstr "Buscar" -#: builtin/mainmenu/store.lua:126 -msgid "Downloading $1, please wait..." -msgstr "Descargando $1, por favor espere..." +#: builtin/mainmenu/store.lua:125 +msgid "Downloading" +msgstr "Descargando" -#: builtin/mainmenu/store.lua:160 +#: builtin/mainmenu/store.lua:127 +msgid "please wait..." +msgstr "por favor espere..." + +#: builtin/mainmenu/store.lua:159 msgid "Successfully installed:" msgstr "Instalado con éxito:" -#: builtin/mainmenu/store.lua:162 +#: builtin/mainmenu/store.lua:163 msgid "Shortname:" msgstr "Nombre corto:" -#: builtin/mainmenu/store.lua:472 +#: builtin/mainmenu/store.lua:167 src/guiFormSpecMenu.cpp:2866 +msgid "ok" +msgstr "aceptar" + +#: builtin/mainmenu/store.lua:476 msgid "Rating" msgstr "Clasificación" -#: builtin/mainmenu/store.lua:497 +#: builtin/mainmenu/store.lua:501 msgid "re-Install" msgstr "Reinstalar" -#: builtin/mainmenu/store.lua:499 +#: builtin/mainmenu/store.lua:503 msgid "Install" msgstr "Instalar" # En el menú principal de mods pone repositorio no tienda. -#: builtin/mainmenu/store.lua:518 +#: builtin/mainmenu/store.lua:522 msgid "Close store" msgstr "Cerrar repositorio" -#: builtin/mainmenu/store.lua:526 +#: builtin/mainmenu/store.lua:530 msgid "Page $1 of $2" msgstr "Página $1 de $2" @@ -280,7 +288,8 @@ msgstr "Mods" msgid "Address / Port :" msgstr "Dirección / puerto:" -#: builtin/mainmenu/tab_multiplayer.lua:24 +#: builtin/mainmenu/tab_multiplayer.lua:24 builtin/mainmenu/tab_server.lua:37 +#: builtin/mainmenu/tab_simple_main.lua:25 msgid "Name / Password :" msgstr "Nombre / contraseña:" @@ -299,22 +308,7 @@ msgstr "Borrar" msgid "Connect" msgstr "Conectar" -#: builtin/mainmenu/tab_multiplayer.lua:62 -#: builtin/mainmenu/tab_simple_main.lua:45 -msgid "Creative mode" -msgstr "Modo creativo" - -#: builtin/mainmenu/tab_multiplayer.lua:63 -#: builtin/mainmenu/tab_simple_main.lua:46 -msgid "Damage enabled" -msgstr "Daño activado" - -#: builtin/mainmenu/tab_multiplayer.lua:64 -#: builtin/mainmenu/tab_simple_main.lua:47 -msgid "PvP enabled" -msgstr "PvP activado" - -#: builtin/mainmenu/tab_multiplayer.lua:247 +#: builtin/mainmenu/tab_multiplayer.lua:252 msgid "Client" msgstr "Cliente" @@ -334,12 +328,12 @@ msgstr "Iniciar juego" msgid "Select World:" msgstr "Selecciona un mundo:" -#: builtin/mainmenu/tab_server.lua:31 builtin/mainmenu/tab_simple_main.lua:75 +#: builtin/mainmenu/tab_server.lua:31 builtin/mainmenu/tab_simple_main.lua:63 #: builtin/mainmenu/tab_singleplayer.lua:90 msgid "Creative Mode" msgstr "Modo creativo" -#: builtin/mainmenu/tab_server.lua:33 builtin/mainmenu/tab_simple_main.lua:77 +#: builtin/mainmenu/tab_server.lua:33 builtin/mainmenu/tab_simple_main.lua:65 #: builtin/mainmenu/tab_singleplayer.lua:92 msgid "Enable Damage" msgstr "Permitir daños" @@ -348,11 +342,6 @@ msgstr "Permitir daños" msgid "Public" msgstr "Público" -# Los dos puntos son intencionados. -#: builtin/mainmenu/tab_server.lua:37 builtin/mainmenu/tab_simple_main.lua:25 -msgid "Name/Password" -msgstr "Nombre / contraseña:" - #: builtin/mainmenu/tab_server.lua:45 msgid "Bind Address" msgstr "Asociar dirección" @@ -369,151 +358,133 @@ msgstr "Puerto del servidor:" msgid "Server" msgstr "Servidor" -#: builtin/mainmenu/tab_settings.lua:21 -msgid "No Filter" -msgstr "Sin filtro" - -#: builtin/mainmenu/tab_settings.lua:22 -msgid "Bilinear Filter" -msgstr "Filtro bi-lineal" - #: builtin/mainmenu/tab_settings.lua:23 -msgid "Trilinear Filter" -msgstr "Filtro tri-lineal" - -#: builtin/mainmenu/tab_settings.lua:32 -msgid "No Mipmap" -msgstr "Sin Mipmap" - -#: builtin/mainmenu/tab_settings.lua:33 -msgid "Mipmap" -msgstr "Mipmap" - -#: builtin/mainmenu/tab_settings.lua:34 -msgid "Mipmap + Aniso. Filter" -msgstr "Mipmap + Filtro aniso." - -#: builtin/mainmenu/tab_settings.lua:77 msgid "Are you sure to reset your singleplayer world?" msgstr "¿Estás seguro de querer reiniciar el mundo de un jugador?" -#: builtin/mainmenu/tab_settings.lua:81 +#: builtin/mainmenu/tab_settings.lua:27 msgid "No!!!" msgstr "¡¡¡No!!!" -#: builtin/mainmenu/tab_settings.lua:181 +#: builtin/mainmenu/tab_settings.lua:134 msgid "Smooth Lighting" msgstr "Iluminación suave" -#: builtin/mainmenu/tab_settings.lua:183 +#: builtin/mainmenu/tab_settings.lua:136 msgid "Enable Particles" msgstr "Habilitar partículas" -#: builtin/mainmenu/tab_settings.lua:185 +#: builtin/mainmenu/tab_settings.lua:138 msgid "3D Clouds" msgstr "Nubes 3D" -#: builtin/mainmenu/tab_settings.lua:187 +#: builtin/mainmenu/tab_settings.lua:141 msgid "Fancy Trees" msgstr "Árboles detallados" -#: builtin/mainmenu/tab_settings.lua:189 +#: builtin/mainmenu/tab_settings.lua:142 msgid "Opaque Water" msgstr "Agua opaca" -#: builtin/mainmenu/tab_settings.lua:191 +#: builtin/mainmenu/tab_settings.lua:145 msgid "Connected Glass" msgstr "Vidrios conectados" -#: builtin/mainmenu/tab_settings.lua:193 -msgid "Node Highlighting" -msgstr "Resaltar nodos" - -#: builtin/mainmenu/tab_settings.lua:196 -msgid "Texturing:" -msgstr "Texturizado:" - -#: builtin/mainmenu/tab_settings.lua:201 -msgid "Rendering:" -msgstr "Renderizado:" - -#: builtin/mainmenu/tab_settings.lua:205 +#: builtin/mainmenu/tab_settings.lua:149 msgid "Restart minetest for driver change to take effect" msgstr "Reinicia minetest para que los cambios en el controlador tengan efecto" -#: builtin/mainmenu/tab_settings.lua:207 +#: builtin/mainmenu/tab_settings.lua:151 +msgid "Mip-Mapping" +msgstr "Mip-Mapping" + +#: builtin/mainmenu/tab_settings.lua:153 +msgid "Anisotropic Filtering" +msgstr "Filtrado Anisotrópico" + +#: builtin/mainmenu/tab_settings.lua:155 +msgid "Bi-Linear Filtering" +msgstr "Filtrado Bi-Lineal" + +#: builtin/mainmenu/tab_settings.lua:157 +msgid "Tri-Linear Filtering" +msgstr "Filtrado Tri-Lineal" + +#: builtin/mainmenu/tab_settings.lua:160 msgid "Shaders" msgstr "Sombreadores" -#: builtin/mainmenu/tab_settings.lua:212 +#: builtin/mainmenu/tab_settings.lua:164 msgid "Change keys" msgstr "Configurar teclas" -#: builtin/mainmenu/tab_settings.lua:215 +#: builtin/mainmenu/tab_settings.lua:167 msgid "Reset singleplayer world" msgstr "Reiniciar mundo de un jugador" -#: builtin/mainmenu/tab_settings.lua:219 +#: builtin/mainmenu/tab_settings.lua:171 msgid "GUI scale factor" msgstr "Factor de escala (GUI)" -#: builtin/mainmenu/tab_settings.lua:223 +#: builtin/mainmenu/tab_settings.lua:175 msgid "Scaling factor applied to menu elements: " msgstr "Factor de escala aplicado a los elementos del menú: " -#: builtin/mainmenu/tab_settings.lua:229 +#: builtin/mainmenu/tab_settings.lua:182 +#, fuzzy msgid "Touch free target" msgstr "Tocar para interactuar" -#: builtin/mainmenu/tab_settings.lua:235 +#: builtin/mainmenu/tab_settings.lua:187 msgid "Touchthreshold (px)" msgstr "Umbral táctil (px)" -#: builtin/mainmenu/tab_settings.lua:242 builtin/mainmenu/tab_settings.lua:256 +#: builtin/mainmenu/tab_settings.lua:194 builtin/mainmenu/tab_settings.lua:208 +#, fuzzy msgid "Bumpmapping" msgstr "Mapeado de relieve" -#: builtin/mainmenu/tab_settings.lua:244 builtin/mainmenu/tab_settings.lua:257 +#: builtin/mainmenu/tab_settings.lua:196 builtin/mainmenu/tab_settings.lua:209 msgid "Generate Normalmaps" msgstr "Generar mapas normales" -#: builtin/mainmenu/tab_settings.lua:246 builtin/mainmenu/tab_settings.lua:258 +#: builtin/mainmenu/tab_settings.lua:198 builtin/mainmenu/tab_settings.lua:210 msgid "Parallax Occlusion" msgstr "Oclusión de paralaje" -#: builtin/mainmenu/tab_settings.lua:248 builtin/mainmenu/tab_settings.lua:259 +#: builtin/mainmenu/tab_settings.lua:200 builtin/mainmenu/tab_settings.lua:211 msgid "Waving Water" msgstr "Oleaje en el agua" -#: builtin/mainmenu/tab_settings.lua:250 builtin/mainmenu/tab_settings.lua:260 +#: builtin/mainmenu/tab_settings.lua:202 builtin/mainmenu/tab_settings.lua:212 msgid "Waving Leaves" msgstr "Movimiento de hojas" -#: builtin/mainmenu/tab_settings.lua:252 builtin/mainmenu/tab_settings.lua:261 +#: builtin/mainmenu/tab_settings.lua:204 builtin/mainmenu/tab_settings.lua:213 msgid "Waving Plants" msgstr "Movimiento de plantas" -#: builtin/mainmenu/tab_settings.lua:287 +#: builtin/mainmenu/tab_settings.lua:255 msgid "To enable shaders the OpenGL driver needs to be used." msgstr "Para habilitar los sombreadores debe utilizar el controlador OpenGL." -#: builtin/mainmenu/tab_settings.lua:398 +#: builtin/mainmenu/tab_settings.lua:330 msgid "Settings" msgstr "Configuración" -#: builtin/mainmenu/tab_simple_main.lua:79 +#: builtin/mainmenu/tab_simple_main.lua:67 msgid "Fly mode" msgstr "Modo vuelo" -#: builtin/mainmenu/tab_simple_main.lua:83 +#: builtin/mainmenu/tab_simple_main.lua:71 msgid "Start Singleplayer" msgstr "Comenzar un jugador" -#: builtin/mainmenu/tab_simple_main.lua:84 +#: builtin/mainmenu/tab_simple_main.lua:72 msgid "Config mods" msgstr "Configurar mods" -#: builtin/mainmenu/tab_simple_main.lua:203 +#: builtin/mainmenu/tab_simple_main.lua:191 msgid "Main" msgstr "Principal" @@ -538,195 +509,39 @@ msgstr "Sin información disponible" msgid "Texturepacks" msgstr "Texturas" -#: src/client.cpp:2788 -msgid "Loading textures..." -msgstr "Cargando texturas..." - -#: src/client.cpp:2798 -msgid "Rebuilding shaders..." -msgstr "Reconstruyendo sombreadores..." - -#: src/client.cpp:2805 -msgid "Initializing nodes..." -msgstr "Inicializando nodos..." - -#: src/client.cpp:2820 +#: src/client.cpp:2726 msgid "Item textures..." msgstr "Texturas de objetos..." -#: src/client.cpp:2845 -msgid "Done!" -msgstr "¡Completado!" - -#: src/client/clientlauncher.cpp:171 -msgid "Main Menu" -msgstr "Menú principal" - -#: src/client/clientlauncher.cpp:209 -msgid "Player name too long." -msgstr "Nombre de jugador demasiado largo." - -#: src/client/clientlauncher.cpp:247 -msgid "Connection error (timed out?)" -msgstr "Error de conexión (¿tiempo agotado?)" - -#: src/client/clientlauncher.cpp:412 -msgid "No world selected and no address provided. Nothing to do." -msgstr "" -"No se seleccionó el mundo y no se ha especificado una dirección. Nada que " -"hacer." - -#: src/client/clientlauncher.cpp:419 -msgid "Provided world path doesn't exist: " -msgstr "La ruta del mundo especificada no existe: " - -#: src/client/clientlauncher.cpp:428 -msgid "Could not find or load game \"" -msgstr "No se puede encontrar o cargar el juego \"" - -#: src/client/clientlauncher.cpp:446 -msgid "Invalid gamespec." -msgstr "Juego especificado no válido." - #: src/fontengine.cpp:70 src/fontengine.cpp:226 msgid "needs_fallback_font" msgstr "needs_fallback_font" -#: src/game.cpp:1057 src/guiFormSpecMenu.cpp:2006 -msgid "Proceed" -msgstr "Continuar" - -#: src/game.cpp:1077 -msgid "You died." -msgstr "Has muerto." - -#: src/game.cpp:1078 +#: src/game.cpp:1063 msgid "Respawn" msgstr "Revivir" -#: src/game.cpp:1097 -msgid "" -"Default Controls:\n" -"No menu visible:\n" -"- single tap: button activate\n" -"- double tap: place/use\n" -"- slide finger: look around\n" -"Menu/Inventory visible:\n" -"- double tap (outside):\n" -" -->close\n" -"- touch stack, touch slot:\n" -" --> move stack\n" -"- touch&drag, tap 2nd finger\n" -" --> place single item to slot\n" -msgstr "" -"Controles predeterminados:\n" -"Con el menú oculto:\n" -"- toque simple: botón activar\n" -"- toque doble: colocar/usar\n" -"- deslizar dedo: mirar alrededor\n" -"Con el menú/inventario visible:\n" -"- toque doble (fuera):\n" -" -->cerrar\n" -"- toque en la pila de objetos:\n" -" -->mover la pila\n" -"- toque y arrastrar, toque con 2 dedos:\n" -" -->colocar solamente un objeto\n" - -#: src/game.cpp:1111 -msgid "" -"Default Controls:\n" -"- WASD: move\n" -"- Space: jump/climb\n" -"- Shift: sneak/go down\n" -"- Q: drop item\n" -"- I: inventory\n" -"- Mouse: turn/look\n" -"- Mouse left: dig/punch\n" -"- Mouse right: place/use\n" -"- Mouse wheel: select item\n" -"- T: chat\n" -msgstr "" -"Controles predeterminados:\n" -"- WASD: moverse\n" -"- Espacio: saltar/subir\n" -"- Mayús.: puntillas/bajar\n" -"- Q: soltar objeto\n" -"- I: inventario\n" -"- Ratón: girar/mirar\n" -"- Ratón izq.: cavar/golpear\n" -"- Ratón der.: colocar/usar\n" -"- Ratón rueda: elegir objeto\n" -"- T: chat\n" - -#: src/game.cpp:1130 -msgid "Continue" -msgstr "Continuar" - -#: src/game.cpp:1134 -msgid "Change Password" -msgstr "Cambiar contraseña" - -#: src/game.cpp:1139 -msgid "Sound Volume" -msgstr "Volumen del sonido" - -#: src/game.cpp:1141 -msgid "Change Keys" -msgstr "Configurar teclas" - -#: src/game.cpp:1144 -msgid "Exit to Menu" -msgstr "Salir al menú" - -#: src/game.cpp:1146 -msgid "Exit to OS" -msgstr "Salir al S.O." - -#: src/game.cpp:1809 -msgid "Shutting down..." -msgstr "Cerrando..." - -#: src/game.cpp:1858 -msgid "Loading..." -msgstr "Cargando..." - -#: src/game.cpp:1915 -msgid "Creating server..." -msgstr "Creando servidor..." - -#: src/game.cpp:1952 -msgid "Creating client..." -msgstr "Creando cliente..." - -#: src/game.cpp:2125 -msgid "Resolving address..." -msgstr "Resolviendo dirección..." - -#: src/game.cpp:2216 -msgid "Connecting to server..." -msgstr "Conectando al servidor..." - -#: src/game.cpp:2274 +#: src/game.cpp:2250 msgid "Item definitions..." msgstr "Definiciones de objetos..." -#: src/game.cpp:2279 +#: src/game.cpp:2255 msgid "Node definitions..." msgstr "Definiciones de nodos..." -#: src/game.cpp:2286 +#: src/game.cpp:2262 msgid "Media..." msgstr "Media..." -#: src/game.cpp:2291 +#: src/game.cpp:2267 msgid " KB/s" msgstr " KB/s" -#: src/game.cpp:2295 +#: src/game.cpp:2271 msgid " MB/s" msgstr " MB/s" -#: src/game.cpp:4210 +#: src/game.cpp:4220 msgid "" "\n" "Check debug.txt for details." @@ -734,14 +549,14 @@ msgstr "" "\n" "Consulta debug.txt para obtener más detalles." -#: src/guiFormSpecMenu.cpp:2797 +#: src/guiFormSpecMenu.cpp:2055 +msgid "Proceed" +msgstr "Continuar" + +#: src/guiFormSpecMenu.cpp:2846 msgid "Enter " msgstr "Ingresar " -#: src/guiFormSpecMenu.cpp:2817 -msgid "ok" -msgstr "aceptar" - #: src/guiKeyChangeMenu.cpp:125 msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)" msgstr "" @@ -832,23 +647,23 @@ msgstr "Seleccionar distancia" msgid "Print stacks" msgstr "Imprimir pilas" -#: src/guiPasswordChange.cpp:108 +#: src/guiPasswordChange.cpp:106 msgid "Old Password" msgstr "Contraseña anterior" -#: src/guiPasswordChange.cpp:124 +#: src/guiPasswordChange.cpp:122 msgid "New Password" msgstr "Contraseña nueva" -#: src/guiPasswordChange.cpp:139 +#: src/guiPasswordChange.cpp:137 msgid "Confirm Password" msgstr "Confirmar contraseña" -#: src/guiPasswordChange.cpp:155 +#: src/guiPasswordChange.cpp:153 msgid "Change" msgstr "Cambiar" -#: src/guiPasswordChange.cpp:164 +#: src/guiPasswordChange.cpp:162 msgid "Passwords do not match!" msgstr "¡Las contraseñas no coinciden!" @@ -1148,3 +963,210 @@ msgstr "PA1" #: src/keycode.cpp:249 msgid "Zoom" msgstr "Zoom" + +#: src/main.cpp:1681 +msgid "Main Menu" +msgstr "Menú principal" + +#: src/main.cpp:1719 +msgid "Player name too long." +msgstr "Nombre de jugador demasiado largo." + +#: src/main.cpp:1757 +msgid "Connection error (timed out?)" +msgstr "Error de conexión (¿tiempo agotado?)" + +#: src/main.cpp:1919 +msgid "No world selected and no address provided. Nothing to do." +msgstr "" +"No se seleccionó el mundo y no se ha especificado una dirección. Nada que " +"hacer." + +#: src/main.cpp:1926 +msgid "Provided world path doesn't exist: " +msgstr "La ruta del mundo especificada no existe: " + +#: src/main.cpp:1935 +msgid "Could not find or load game \"" +msgstr "No se puede encontrar o cargar el juego \"" + +#: src/main.cpp:1953 +msgid "Invalid gamespec." +msgstr "Juego especificado no válido." + +msgid "" +"Default Controls:\n" +"- WASD: move\n" +"- Space: jump/climb\n" +"- Shift: sneak/go down\n" +"- Q: drop item\n" +"- I: inventory\n" +"- Mouse: turn/look\n" +"- Mouse left: dig/punch\n" +"- Mouse right: place/use\n" +"- Mouse wheel: select item\n" +"- T: chat\n" +msgstr "" +"Controles predeterminados:\n" +"- WASD: moverse\n" +"- Espacio: saltar/subir\n" +"- Mayús.: puntillas/bajar\n" +"- Q: soltar objeto\n" +"- I: inventario\n" +"- Ratón: girar/mirar\n" +"- Ratón izq.: cavar/golpear\n" +"- Ratón der.: colocar/usar\n" +"- Ratón rueda: elegir objeto\n" +"- T: chat\n" + +msgid "is required by:" +msgstr "es requerido por:" + +msgid "Configuration saved. " +msgstr "Configuración guardada. " + +msgid "Warning: Configuration not consistent. " +msgstr "Advertencia: La configuración no es coherente." + +msgid "Cannot create world: Name contains invalid characters" +msgstr "No se puede crear el mundo: El nombre contiene caracteres no válidos" + +msgid "Multiplayer" +msgstr "Multijugador" + +msgid "Advanced" +msgstr "Avanzado" + +msgid "Show Public" +msgstr "Mostrar público" + +msgid "Show Favorites" +msgstr "Mostrar favoritos" + +msgid "Leave address blank to start a local server." +msgstr "Dejar la dirección en blanco para iniciar un servidor local." + +msgid "Address required." +msgstr "Requiere una dirección." + +msgid "Cannot delete world: Nothing selected" +msgstr "No se puede eliminar el mundo: Ninguno seleccionado" + +msgid "Files to be deleted" +msgstr "Archivos que se eliminarán" + +msgid "Cannot create world: No games found" +msgstr "No se puede crear el mundo: No se encontraron juegos" + +msgid "Cannot configure world: Nothing selected" +msgstr "No se puede configurar el mundo: Ninguno seleccionado" + +msgid "Failed to delete all world files" +msgstr "No se pudo eliminar todos los archivos del mundo" + +msgid "" +"Warning: Some configured mods are missing.\n" +"Their setting will be removed when you save the configuration. " +msgstr "" +"Advertencia: Algunos mods configurados faltan.\n" +"Sus ajustes se eliminarán al guardar la configuración. " + +msgid "" +"Warning: Some mods are not configured yet.\n" +"They will be enabled by default when you save the configuration. " +msgstr "" +"Advertencia: Algunos mods todavía no están configurados.\n" +"Se habilitarán de forma predeterminada al guardar la configuración. " + +msgid "Exit to OS" +msgstr "Salir al S.O." + +msgid "Exit to Menu" +msgstr "Salir al menú" + +msgid "Sound Volume" +msgstr "Volumen del sonido" + +msgid "Change Password" +msgstr "Cambiar contraseña" + +msgid "Continue" +msgstr "Continuar" + +msgid "You died." +msgstr "Has muerto." + +msgid "Shutting down..." +msgstr "Cerrando..." + +msgid "Connecting to server..." +msgstr "Conectando al servidor..." + +msgid "Resolving address..." +msgstr "Resolviendo dirección..." + +msgid "Creating client..." +msgstr "Creando cliente..." + +msgid "Creating server...." +msgstr "Creando servidor..." + +msgid "Loading..." +msgstr "Cargando..." + +msgid "Local install" +msgstr "Instalación local" + +msgid "Preload item visuals" +msgstr "Precarga elementos visuales" + +msgid "Password" +msgstr "Contraseña" + +msgid "Name" +msgstr "Nombre" + +msgid "Favorites:" +msgstr "Favoritos:" + +msgid "<<-- Add mod" +msgstr "<<-- Añadir mod" + +msgid "Remove selected mod" +msgstr "Eliminar el mod seleccionado" + +msgid "Mods:" +msgstr "Mods:" + +msgid "Games" +msgstr "Juegos" + +msgid "Gamemgr: Unable to copy mod \"$1\" to game \"$2\"" +msgstr "Gamemgr: Imposible copiar el mod \"$1\" al juego \"$2\"" + +msgid "Game Name" +msgstr "Nombre del juego" + +msgid "Change Keys" +msgstr "Configurar teclas" + +msgid "Name/Password" +msgstr "Nombre / contraseña:" + +msgid "Node Highlighting" +msgstr "Resaltar nodos" + +msgid "Texturing:" +msgstr "Texturizado:" + +msgid "Rendering:" +msgstr "Renderizado:" + +msgid "Rebuilding shaders..." +msgstr "Reconstruyendo sombreadores..." + +msgid "Initializing nodes..." +msgstr "Inicializando nodos..." + +msgid "Done!" +msgstr "¡Completado!" diff --git a/po/ja/minetest.po b/po/ja/minetest.po index 8dba0dc91..910be7826 100644 --- a/po/ja/minetest.po +++ b/po/ja/minetest.po @@ -1,185 +1,215 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# msgid "" msgstr "" "Project-Id-Version: minetest\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-02-14 23:12+0900\n" -"PO-Revision-Date: 2015-02-22 10:57+0900\n" +"POT-Creation-Date: 2013-11-23 17:37+0100\n" +"PO-Revision-Date: 2014-12-28 15:48+0900\n" "Last-Translator: Rui Takeda \n" -"Language-Team: Japanese \n" -"Language: ja\n" +"Language-Team: Japanese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.6.5\n" +"Language: ja_JP\n" +"X-Poedit-SourceCharset: UTF-8\n" -msgid "Ok" -msgstr "決定" +msgid "Game Name" +msgstr "ゲーム名" -msgid "World:" -msgstr "ワールド:" - -msgid "Hide Game" -msgstr "ゲームを隠す" - -msgid "Hide mp content" -msgstr "Modパックの簡略化" - -msgid "Mod:" -msgstr "Mod名:" - -msgid "Depends:" -msgstr "依存Mod:" - -msgid "Save" -msgstr "保存" +msgid "Create" +msgstr "作成" msgid "Cancel" msgstr "キャンセル" -msgid "Enable MP" -msgstr "有効化" +msgid "Gamemgr: Unable to copy mod \"$1\" to game \"$2\"" +msgstr "Gamemgr: \"$1\"のModを \"$2\" にコピーできません" -msgid "Disable MP" -msgstr "無効化" +msgid "Games" +msgstr "ゲーム" -msgid "enabled" -msgstr "有効化" +msgid "Mods:" +msgstr "Mod:" -msgid "Enable all" -msgstr "すべて有効化" +msgid "edit game" +msgstr "ゲーム編集" + +msgid "new game" +msgstr "新規ゲーム" + +msgid "Remove selected mod" +msgstr "選択したModを削除" + +msgid "Ok" +msgstr "決定" msgid "World name" msgstr "ワールド名" msgid "Seed" -msgstr "Seed値" +msgstr "シード値" msgid "Mapgen" -msgstr "ワールドタイプ" +msgstr "マップ生成" msgid "Game" msgstr "ゲーム" -msgid "Create" -msgstr "作成" - -msgid "You have no subgames installed." -msgstr "ゲームがインストールされていません。" - -msgid "Download one from minetest.net" -msgstr "minetest.netから再ダウンロードしてください。" - -msgid "Warning: The minimal development test is meant for developers." -msgstr "警告:Minimal development testは開発者のためのゲームです。" - -msgid "Download a subgame, such as minetest_game, from minetest.net" -msgstr "minetest.netからminetest_gameのゲームをダウンロードしてください。" - -msgid "A world named \"$1\" already exists" -msgstr "ワールド名\"$1\"はすでに使用されています。" - -msgid "No worldname given or no game selected" -msgstr "ワールド名が入力されていないか、ゲームが選択されていません。" - -msgid "Are you sure you want to delete \"$1\"?" -msgstr "本当に\"$1\"を削除してよろしいですか?" +msgid "Delete World \"$1\"?" +msgstr "\"$1\"のワールドを削除しますか?" msgid "Yes" msgstr "はい" -msgid "No of course not!" -msgstr "いいえ" - -msgid "Modmgr: failed to delete \"$1\"" -msgstr "Modマネージャー:\"$1\"の削除に失敗しました。" - -msgid "Modmgr: invalid modpath \"$1\"" -msgstr "Modマネージャー:Mod\"$1\"の場所が不明です。" - -msgid "Delete World \"$1\"?" -msgstr "ワールド\"$1\"を削除してよろしいですか?" - msgid "No" msgstr "いいえ" -msgid "Rename Modpack:" -msgstr "名前を変更" +msgid "A world named \"$1\" already exists" +msgstr "\"$1\"という名前のワールドを作成できません。同名のワールドが存在しています" -msgid "Accept" -msgstr "決定" +msgid "No worldname given or no game selected" +msgstr "ワールド名が入力されていないか、ゲームが選択されていません" -msgid "Install Mod: file: \"$1\"" -msgstr "Modインストール:ファイル\"$1\"からModをインストールします。" +msgid "To enable shaders the OpenGL driver needs to be used." +msgstr "シェーダーを有効にするには、OpenGLのドライバが必要です" -msgid "" -"\n" -"Install Mod: unsupported filetype \"$1\" or broken archive" -msgstr "" -"\n" -"Modインストール:ファイル\"$1\"は非対応の形式か、壊れています。" +msgid "Address/Port" +msgstr "アドレス/ポート" -msgid "Failed to install $1 to $2" -msgstr "$2へ$1をインストールできませんでした。" +msgid "Name/Password" +msgstr "名前/パスワード" -msgid "Install Mod: unable to find suitable foldername for modpack $1" -msgstr "" -"Modインストール:Modパック$1に適したフォルダ名を見つけることができませんでし" -"た。" +msgid "Public Serverlist" +msgstr "公開されているサーバーリスト" -msgid "Install Mod: unable to find real modname for: $1" -msgstr "Modインストール:$1の本来のMod名が不明です。" +msgid "Delete" +msgstr "削除" -msgid "Unsorted" -msgstr "未分類" +msgid "Connect" +msgstr "接続" -msgid "Search" -msgstr "検索" +msgid "New" +msgstr "作成" -msgid "Downloading $1, please wait..." -msgstr "$1をダウンロードしています。しばらくお待ちください..." +msgid "Configure" +msgstr "設定" -msgid "Successfully installed:" -msgstr "インストールが完了しました。:" +msgid "Start Game" +msgstr "ゲームスタート" -msgid "Shortname:" -msgstr "省略名" +msgid "Select World:" +msgstr "ワールド選択:" -msgid "Rating" -msgstr "評価" +msgid "Creative Mode" +msgstr "クリエイティブモード" -msgid "re-Install" -msgstr "再インストール" +msgid "Enable Damage" +msgstr "ダメージ有効" -msgid "Install" -msgstr "インストール" +msgid "Public" +msgstr "公開する" -msgid "Close store" -msgstr "閉じる" +msgid "Name" +msgstr "名前" -msgid "Page $1 of $2" -msgstr "ページ $1/$2" +msgid "Password" +msgstr "パスワード" -msgid "Credits" -msgstr "クレジット" +msgid "Server Port" +msgstr "ポート" + +msgid "Fancy Trees" +msgstr "きれいな木" + +msgid "Smooth Lighting" +msgstr "自然な光" + +msgid "3D Clouds" +msgstr "立体な雲" + +msgid "Opaque Water" +msgstr "不透明な水面" + +msgid "Mip-Mapping" +msgstr "ミップマップ" + +msgid "Anisotropic Filtering" +msgstr "異方性フィルタリング" + +msgid "Bi-Linear Filtering" +msgstr "バイリニアフィルタリング" + +msgid "Tri-Linear Filtering" +msgstr "トリリニアフィルタリング" + +msgid "Shaders" +msgstr "シェーダー" + +msgid "Connected Glass" +msgstr "ガラスを繋げる" + +msgid "Enable Particles" +msgstr "破片の有効化" + +msgid "Finite Liquid" +msgstr "液体の制限" + +msgid "Change keys" +msgstr "キー割当て変更" + +msgid "Play" +msgstr "ゲームスタート" + +msgid "Select texture pack:" +msgstr "テクスチャパックを選択:" + +msgid "No information available" +msgstr "情報がありません" msgid "Core Developers" msgstr "開発者" msgid "Active Contributors" -msgstr "開発協力者" +msgstr "貢献者" msgid "Previous Contributors" -msgstr "以前の開発協力者" +msgstr "以前の貢献者" + +msgid "Singleplayer" +msgstr "シングルプレイ" + +msgid "Client" +msgstr "クライアント" + +msgid "Server" +msgstr "マルチプレイ" + +msgid "Settings" +msgstr "設定" + +msgid "Texturepacks" +msgstr "テクスチャパック" + +msgid "Mods" +msgstr "Mod" + +msgid "Credits" +msgstr "クレジット" msgid "Installed Mods:" msgstr "インストール済みのMod:" msgid "Online mod repository" -msgstr "オンラインでModを検索" +msgstr "オンラインで検索" msgid "No mod description available" -msgstr "Modの説明がありません。" +msgstr "Modの説明がありません" msgid "Mod information:" msgstr "Modの情報:" @@ -193,376 +223,123 @@ msgstr "選択したModパックを削除" msgid "Uninstall selected mod" msgstr "選択したModを削除" -msgid "Select Mod File:" -msgstr "Modファイルを選択" +msgid "Rename Modpack:" +msgstr "Modパックの名前を変更" -msgid "Mods" -msgstr "Mod" +msgid "Accept" +msgstr "了承" -msgid "Address / Port :" -msgstr "アドレスとポート:" +msgid "World:" +msgstr "ワールド:" -msgid "Name / Password :" -msgstr "名前とパスワード:" +msgid "Hide Game" +msgstr "内部Mod" -msgid "Public Serverlist" -msgstr "公開済みのサーバーの一覧" +msgid "Hide mp content" +msgstr "Modパックの簡略化" -msgid "Delete" -msgstr "削除" +msgid "Mod:" +msgstr "Mod名:" -msgid "Connect" -msgstr "接続" +msgid "Depends:" +msgstr "依存Mod:" -msgid "Creative mode" -msgstr "クリエイティブモード" +msgid "Save" +msgstr "保存" -msgid "Damage enabled" -msgstr "HPあり" +msgid "Enable MP" +msgstr "有効化" -msgid "PvP enabled" -msgstr "PvPあり" +msgid "Disable MP" +msgstr "無効化" -msgid "Client" -msgstr "クライアント" +msgid "enabled" +msgstr "有効化" -msgid "New" -msgstr "作成" +msgid "Enable all" +msgstr "全て有効化" -msgid "Configure" -msgstr "設定" +msgid "Modmgr: failed to delete \"$1\"" +msgstr "Modmgr: \"$1\"の削除に失敗しました" -msgid "Start Game" -msgstr "ゲームスタート" +msgid "Modmgr: invalid modpath \"$1\"" +msgstr "Modmgr: \"$1\"は無効なModパスです" -msgid "Select World:" -msgstr "ワールドを選択:" +msgid "Are you sure you want to delete \"$1\"?" +msgstr "\"$1\"を削除してよろしいですか?" -msgid "Creative Mode" -msgstr "クリエイティブモード" +msgid "No of course not!" +msgstr "違います!" -msgid "Enable Damage" -msgstr "ダメージあり" +msgid "Page $1 of $2" +msgstr "ページ $1/$2" -msgid "Public" -msgstr "サーバーを公開する" +msgid "Rating" +msgstr "評価" -msgid "Name/Password" -msgstr "名前とパスワード" +msgid "re-Install" +msgstr "再インストール" -msgid "Bind Address" -msgstr "バインドアドレス" - -msgid "Port" -msgstr "ポート" - -msgid "Server Port" -msgstr "サーバーのポート" - -msgid "Server" -msgstr "サーバー" - -msgid "No Filter" -msgstr "フィルタ無し" - -msgid "Bilinear Filter" -msgstr "バイリニアフィルタ" - -msgid "Trilinear Filter" -msgstr "トリリニアフィルタ" - -msgid "No Mipmap" -msgstr "ミップマップ無し" - -msgid "Mipmap" -msgstr "ミップマップ" - -msgid "Mipmap + Aniso. Filter" -msgstr "異方性フィルタ" - -msgid "Are you sure to reset your singleplayer world?" -msgstr "シングルプレイヤーのワールドをリセットしてよろしいですか?" - -msgid "No!!!" -msgstr "いいえ" - -msgid "Smooth Lighting" -msgstr "滑らかな光" - -msgid "Enable Particles" -msgstr "パーティクル有効化" - -msgid "3D Clouds" -msgstr "立体の雲" - -msgid "Fancy Trees" -msgstr "綺麗な木" - -msgid "Opaque Water" -msgstr "不透明な水" - -msgid "Connected Glass" -msgstr "ガラスをつなげる" - -msgid "Node Highlighting" -msgstr "ノードの強調" - -msgid "Texturing:" -msgstr "テクスチャリング:" - -msgid "Rendering:" -msgstr "レンダリング:" - -msgid "Restart minetest for driver change to take effect" -msgstr "ドライバーを変更するためMinetesを再起動します" - -msgid "Shaders" -msgstr "シェーダー" - -msgid "Change keys" -msgstr "操作変更" - -msgid "Reset singleplayer world" -msgstr "シングルプレイヤーのワールドをリセット" - -msgid "GUI scale factor" -msgstr "メニューの大きさ" - -msgid "Scaling factor applied to menu elements: " -msgstr "メニューの大きさとして設定する数値:" - -msgid "Touch free target" -msgstr "タッチ位置を自由にする" - -msgid "Touchthreshold (px)" -msgstr "タッチのしきい値(ピクセル単位)" - -msgid "Bumpmapping" -msgstr "バンプマッピング" - -msgid "Generate Normalmaps" -msgstr "ノーマルマップの生成" - -msgid "Parallax Occlusion" -msgstr "視差遮蔽マッピング" - -msgid "Waving Water" -msgstr "揺れる水" - -msgid "Waving Leaves" -msgstr "揺れる葉" - -msgid "Waving Plants" -msgstr "揺れる草花" - -msgid "To enable shaders the OpenGL driver needs to be used." -msgstr "シェーダーを有効にするにはOpenGLを使用する必要があります。" - -msgid "Settings" -msgstr "設定" - -msgid "Fly mode" -msgstr "飛行モード" - -msgid "Start Singleplayer" -msgstr "ゲームスタート" - -msgid "Config mods" -msgstr "Mod設定" - -msgid "Main" -msgstr "メイン" - -msgid "Play" -msgstr "ゲームスタート" - -msgid "Singleplayer" -msgstr "シングルプレイヤー" - -msgid "Select texture pack:" -msgstr "テクスチャパックを選択:" - -msgid "No information available" -msgstr "情報がありません。" - -msgid "Texturepacks" -msgstr "テクスチャパック" - -msgid "Loading textures..." -msgstr "テクスチャ読み込み中..." - -msgid "Rebuilding shaders..." -msgstr "シェーダー構築中..." - -msgid "Initializing nodes..." -msgstr "ノードの設定中..." +msgid "Install" +msgstr "インストール" msgid "Item textures..." -msgstr "アイテムのテクスチャを設定中..." - -msgid "Done!" -msgstr "完了!" - -msgid "Main Menu" -msgstr "メインメニュー" - -msgid "Player name too long." -msgstr "名前が長過ぎます。" - -msgid "Connection error (timed out?)" -msgstr "接続失敗(またはタイムアウト)" - -msgid "No world selected and no address provided. Nothing to do." -msgstr "ワールドが選択されていないアドレスです。続行できません。" - -msgid "Provided world path doesn't exist: " -msgstr "ワールドが存在しません:" - -msgid "Could not find or load game \"" -msgstr "ゲーム\"の読み込みができません。" - -msgid "Invalid gamespec." -msgstr "無効なgamespecです。" - -msgid "needs_fallback_font" -msgstr "yes" - -msgid "Proceed" -msgstr "決定" - -msgid "You died." -msgstr "You died." - -msgid "Respawn" -msgstr "Respawn" - -msgid "" -"Default Controls:\n" -"No menu visible:\n" -"- single tap: button activate\n" -"- double tap: place/use\n" -"- slide finger: look around\n" -"Menu/Inventory visible:\n" -"- double tap (outside):\n" -" -->close\n" -"- touch stack, touch slot:\n" -" --> move stack\n" -"- touch&drag, tap 2nd finger\n" -" --> place single item to slot\n" -msgstr "" -"基本操作:\n" -"タッチによる操作\n" -"- シングルタップ:ブロックの破壊\n" -"- ダブルタップ:設置やアイテムの使用\n" -"- 指でスライド:見回す\n" -"メニュー(インベントリ)の操作\n" -"- ダブルタップ:\n" -"-- 閉じる\n" -"- アイテムスロットをタッチ:\n" -"-- アイテムの移動\n" -"- タッチしてドラッグ:\n" -"-- アイテムを置く\n" - -msgid "" -"Default Controls:\n" -"- WASD: move\n" -"- Space: jump/climb\n" -"- Shift: sneak/go down\n" -"- Q: drop item\n" -"- I: inventory\n" -"- Mouse: turn/look\n" -"- Mouse left: dig/punch\n" -"- Mouse right: place/use\n" -"- Mouse wheel: select item\n" -"- T: chat\n" -msgstr "" -"基本操作:\n" -"- WASD:移動\n" -"- スペース:ジャンプ、登る\n" -"- Shift:スニーク、降りる\n" -"- Q:アイテムを落とす\n" -"- I:インベントリ\n" -"- マウス移動:見回す\n" -"- 左クリック:ブロック破壊\n" -"- 右クリック:設置や使用\n" -"- ホイール:アイテム選択\n" -"- T:チャット画面\n" - -msgid "Continue" -msgstr "再開" - -msgid "Change Password" -msgstr "パスワード変更" - -msgid "Sound Volume" -msgstr "音量" - -msgid "Change Keys" -msgstr "操作変更" - -msgid "Exit to Menu" -msgstr "タイトル" - -msgid "Exit to OS" -msgstr "終了" - -msgid "Shutting down..." -msgstr "終了中..." +msgstr "アイテムのテクスチャ設定中..." msgid "Loading..." -msgstr "読み込み中..." +msgstr "ロード中..." msgid "Creating server..." -msgstr "サーバー作成中..." +msgstr "サーバー構築中..." msgid "Creating client..." -msgstr "クライアント作成中..." +msgstr "クライアント作成中..." msgid "Resolving address..." -msgstr "アドレス解決中..." +msgstr "アドレス解決中..." msgid "Connecting to server..." -msgstr "サーバー接続中..." +msgstr "サーバー接続中..." msgid "Item definitions..." -msgstr "アイテム定義中..." +msgstr "アイテム定義中..." msgid "Node definitions..." -msgstr "ノード定義中..." +msgstr "ノード定義中..." msgid "Media..." msgstr "..." -msgid " KB/s" -msgstr " KB/秒" - -msgid " MB/s" -msgstr " MB/秒" +msgid "Shutting down..." +msgstr "終了中..." msgid "" "\n" "Check debug.txt for details." msgstr "" "\n" -"詳細はdebug.txtをご覧ください。" +"詳細はdebug.txtを御覧ください。" -msgid "Enter " -msgstr "Enter" +msgid "You died." +msgstr "You died!" -msgid "ok" +msgid "Respawn" +msgstr "Respawn" + +msgid "Proceed" msgstr "決定" msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)" -msgstr "操作の設定を変更します。" +msgstr "キーバインド" msgid "\"Use\" = climb down" -msgstr "「使用」で降りる" +msgstr "「使う」キーで降りる" msgid "Double tap \"jump\" to toggle fly" -msgstr "「ジャンプ」二回押しで飛行モード" +msgstr "ジャンプの二回押しで飛行" msgid "Key already in use" -msgstr "すでに使われているキーです。" +msgstr "既に使われているキーです" msgid "press key" msgstr "キー入力待ち" @@ -574,19 +351,19 @@ msgid "Backward" msgstr "後退" msgid "Left" -msgstr "左に進む" +msgstr "左へ進む" msgid "Right" -msgstr "右に進む" +msgstr "右へ進む" msgid "Use" -msgstr "使用" +msgstr "使う" msgid "Jump" msgstr "ジャンプ" msgid "Sneak" -msgstr "スニーク" +msgstr "こっそり進む" msgid "Drop" msgstr "落とす" @@ -604,16 +381,16 @@ msgid "Console" msgstr "コンソール" msgid "Toggle fly" -msgstr "飛行モード" +msgstr "飛行" msgid "Toggle fast" -msgstr "高速移動モード" +msgstr "高速移動" msgid "Toggle noclip" -msgstr "すり抜けモード" +msgstr "すり抜け" msgid "Range select" -msgstr "視野範囲変更" +msgstr "視野切り替え" msgid "Print stacks" msgstr "スタックの表示" @@ -631,13 +408,53 @@ msgid "Change" msgstr "変更" msgid "Passwords do not match!" -msgstr "パスワードが一致しません!" +msgstr "パスワードが一致しません!" + +msgid "Continue" +msgstr "続ける" + +msgid "Change Password" +msgstr "パスワード変更" + +msgid "Sound Volume" +msgstr "音量" + +msgid "Exit to Menu" +msgstr "タイトル" + +msgid "Exit to OS" +msgstr "終了" + +msgid "" +"Default Controls:\n" +"- WASD: move\n" +"- Space: jump/climb\n" +"- Shift: sneak/go down\n" +"- Q: drop item\n" +"- I: inventory\n" +"- Mouse: turn/look\n" +"- Mouse left: dig/punch\n" +"- Mouse right: place/use\n" +"- Mouse wheel: select item\n" +"- T: chat\n" +msgstr "" +"基本操作:\n" +"WASD:移動\n" +"スペース:ジャンプ/登る\n" +"シフト:忍び歩き/降りる\n" +"Q:アイテムを落とす\n" +"I:インベントリ\n" +"マウス:見回す\n" +"左クリック:掘る/パンチ\n" +"右クリック:使う\n" +"マウスホイール:アイテム選択\n" +"T:チャット\n" msgid "Sound Volume: " -msgstr "音量:" +msgstr "音量" msgid "Exit" -msgstr "閉じる" +msgstr "戻る" msgid "Left Button" msgstr "左ボタン" @@ -854,3 +671,56 @@ msgstr "PA1" msgid "Zoom" msgstr "ズーム" + +msgid "needs_fallback_font" +msgstr "yes" + +msgid "Main Menu" +msgstr "メインメニュー" + +msgid "No world selected and no address provided. Nothing to do." +msgstr "" +"ワールドが選択できていないか、アドレスが入力されていません。そのため実行されませ" +"ん。" + +msgid "Could not find or load game \"" +msgstr "読み込みか検索に失敗: \"" + +msgid "Invalid gamespec." +msgstr "無効なgamespecです" + +msgid "Connection error (timed out?)" +msgstr "接続エラー(タイムアウト)" + +msgid "Bumpmapping" +msgstr "バンプマッピング" + +msgid "Generate Normalmaps" +msgstr "法線マッピング" + +msgid "Parallax Occlusion" +msgstr "視差オクルージョンマッピング" + +msgid "Waving Water" +msgstr "揺れる水" + +msgid "Waving Leaves" +msgstr "揺れる葉" + +msgid "Waving Plants" +msgstr "揺れる草花" + +msgid "GUI scale factor" +msgstr "メニューの大きさ" + +msgid "Unsorted" +msgstr "未分類" + +msgid "Search" +msgstr "検索" + +msgid "Close store" +msgstr "閉じる" + +msgid "Change Keys" +msgstr "操作変更" diff --git a/po/tr/minetest.po b/po/tr/minetest.po deleted file mode 100644 index 385ae5bcd..000000000 --- a/po/tr/minetest.po +++ /dev/null @@ -1,1248 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: 0.0.1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-02-24 14:45+0200\n" -"PO-Revision-Date: 2015-02-24 15:11+0200\n" -"Last-Translator: Mahmut Elmas mahmutelmas06@gmail.com\n" -"Language-Team: Türkçe <>\n" -"Language: tr\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Eazy Po 0.9.5.3\n" -"X-Poedit-Language: Turkish\n" -"X-Poedit-Basepath: \n" - -#: builtin/fstk/ui.lua:67 -#, approved -msgid "Ok" -msgstr "Tamam" - -#: builtin/mainmenu/dlg_config_world.lua:26 -#, approved -#| msgid "World:" -msgid "World:" -msgstr "Dünya:" - -#: builtin/mainmenu/dlg_config_world.lua:30 -#: builtin/mainmenu/dlg_config_world.lua:32 -#, approved -#| msgid "Hide Game" -msgid "Hide Game" -msgstr "Kök Eklentiler" - -#: builtin/mainmenu/dlg_config_world.lua:36 -#: builtin/mainmenu/dlg_config_world.lua:38 -#, approved -msgid "Hide mp content" -msgstr "Paket detaylarını gizle" - -#: builtin/mainmenu/dlg_config_world.lua:46 -#, approved -#| msgid "Mod:" -msgid "Mod:" -msgstr "Eklnt: " - -#: builtin/mainmenu/dlg_config_world.lua:48 -#, approved -#| msgid "Depends:" -msgid "Depends:" -msgstr "Bağımlılıklar :" - -#: builtin/mainmenu/dlg_config_world.lua:51 src/guiKeyChangeMenu.cpp:191 -#, approved -msgid "Save" -msgstr "Kaydet" - -#: builtin/mainmenu/dlg_config_world.lua:52 -#: builtin/mainmenu/dlg_create_world.lua:64 -#: builtin/mainmenu/dlg_rename_modpack.lua:33 src/guiKeyChangeMenu.cpp:199 -#: src/keycode.cpp:224 -#, approved -#| msgid "Cancel" -msgid "Cancel" -msgstr "Vazgeç" - -#: builtin/mainmenu/dlg_config_world.lua:68 -#, approved -msgid "Enable MP" -msgstr "Eklenti paketini etkinleştir" - -#: builtin/mainmenu/dlg_config_world.lua:70 -#, approved -#| msgid "Disable MP" -msgid "Disable MP" -msgstr "Eklenti paketini devre dışı bırak" - -#: builtin/mainmenu/dlg_config_world.lua:74 -#: builtin/mainmenu/dlg_config_world.lua:76 -#, approved -#| msgid "enabled" -msgid "enabled" -msgstr "Etkinleştirildi" - -#: builtin/mainmenu/dlg_config_world.lua:82 -#, approved -#| msgid "Enable all" -msgid "Enable all" -msgstr "Hepsini etkinleştir" - -#: builtin/mainmenu/dlg_create_world.lua:50 -#, approved -msgid "World name" -msgstr "Dünya adı" - -#: builtin/mainmenu/dlg_create_world.lua:53 -#, approved -#| msgid "Seed" -msgid "Seed" -msgstr "Çekirdek" - -#: builtin/mainmenu/dlg_create_world.lua:56 -#, approved -#| msgid "Mapgen" -msgid "Mapgen" -msgstr "Mapgen" - -#: builtin/mainmenu/dlg_create_world.lua:59 -#, approved -msgid "Game" -msgstr "Oyun" - -#: builtin/mainmenu/dlg_create_world.lua:63 -#, approved -msgid "Create" -msgstr "Oluştur" - -#: builtin/mainmenu/dlg_create_world.lua:68 -#, approved -#| msgid "You have no subgames installed." -msgid "You have no subgames installed." -msgstr "Ek bir oyun modu yüklü değil." - -#: builtin/mainmenu/dlg_create_world.lua:69 -#, approved -#| msgid "Download one from minetest.net" -msgid "Download one from minetest.net" -msgstr "Minetest.net adresinden indirin" - -#: builtin/mainmenu/dlg_create_world.lua:72 -#, approved -msgid "" -"Warning: The minimal development test is meant for " -"developers." -msgstr "Uyarı : Minimal Development Test geliştiriciler içindir." - -#: builtin/mainmenu/dlg_create_world.lua:73 -#, approved -msgid "" -"Download a subgame, such as minetest_game, from " -"minetest.net" -msgstr "Minetest.net adresinden bir oyun modu indirin" - -#: builtin/mainmenu/dlg_create_world.lua:97 -#, approved -msgid "A world named \"$1\" already exists" -msgstr " \"$1\" isimli dünya zaten var" - -#: builtin/mainmenu/dlg_create_world.lua:116 -#, approved -msgid "No worldname given or no game selected" -msgstr "Dünya seçilmedi ya da adlandırılmadı" - -#: builtin/mainmenu/dlg_delete_mod.lua:26 -#, approved -msgid "Are you sure you want to delete \"$1\"?" -msgstr "" -" \"$1\" 'i silmek istediğinizden emin misiniz " -"?" - -#: builtin/mainmenu/dlg_delete_mod.lua:27 -#: builtin/mainmenu/dlg_delete_world.lua:25 -#: builtin/mainmenu/tab_settings.lua:25 -#, approved -msgid "Yes" -msgstr "Evet" - -#: builtin/mainmenu/dlg_delete_mod.lua:28 -#, approved -msgid "No of course not!" -msgstr "Elbette hayır!" - -#: builtin/mainmenu/dlg_delete_mod.lua:41 -#, approved -msgid "Modmgr: failed to delete \"$1\"" -msgstr "Modmgr:\"$1\" dosyası silerken hata" - -#: builtin/mainmenu/dlg_delete_mod.lua:45 -#, approved -msgid "Modmgr: invalid modpath \"$1\"" -msgstr "Modmgr: \"$1\" eklenti konumu yanlış" - -#: builtin/mainmenu/dlg_delete_world.lua:24 -#, approved -msgid "Delete World \"$1\"?" -msgstr " \"$1\" dünyasını sil ?" - -#: builtin/mainmenu/dlg_delete_world.lua:26 -#, approved -msgid "No" -msgstr "Hayır" - -#: builtin/mainmenu/dlg_rename_modpack.lua:26 -#, approved -msgid "Rename Modpack:" -msgstr "Eklenti paketini yeniden adlandır :" - -#: builtin/mainmenu/dlg_rename_modpack.lua:31 src/keycode.cpp:228 -#, approved -msgid "Accept" -msgstr "Kabul et" - -#: builtin/mainmenu/modmgr.lua:342 -#, approved -msgid "Install Mod: file: \"$1\"" -msgstr "Eklenti yükle: file: \"$1\"" - -#: builtin/mainmenu/modmgr.lua:343 -#, approved -msgid "" -"\n" -"Install Mod: unsupported filetype \"$1\" or broken " -"archive" -msgstr "" -"\n" -"Eklenti yükle: Desteklenmeyen dosya uzantısı \"$1\" veya bozuk " -"dosya" - -#: builtin/mainmenu/modmgr.lua:363 -#, approved -msgid "Failed to install $1 to $2" -msgstr " $1 arası $2 yükleme başarısız" - -#: builtin/mainmenu/modmgr.lua:366 -#, approved -msgid "" -"Install Mod: unable to find suitable foldername for modpack " -"$1" -msgstr "Eklenti yükle:$1 eklenti paketi için uygun bir klasör adı bulunamadı" - -#: builtin/mainmenu/modmgr.lua:386 -#, approved -msgid "" -"Install Mod: unable to find real modname for: " -"$1" -msgstr "Eklenti yükle: $1 için eklenti adı bulunamadı" - -#: builtin/mainmenu/store.lua:88 -#, approved -msgid "Unsorted" -msgstr "Sıralanmamış" - -#: builtin/mainmenu/store.lua:99 builtin/mainmenu/store.lua:584 -#, approved -msgid "Search" -msgstr "Ara" - -#: builtin/mainmenu/store.lua:125 -#, approved -msgid "Downloading" -msgstr "İndiriliyor" - -#: builtin/mainmenu/store.lua:127 -#, approved -msgid "please wait..." -msgstr "lütfen bekleyin..." - -#: builtin/mainmenu/store.lua:159 -#, approved -msgid "Successfully installed:" -msgstr "Yükleme başarılı :" - -#: builtin/mainmenu/store.lua:163 -#, approved -msgid "Shortname:" -msgstr "Takma ad :" - -#: builtin/mainmenu/store.lua:167 src/guiFormSpecMenu.cpp:2866 -#, approved -msgid "ok" -msgstr "tamam" - -#: builtin/mainmenu/store.lua:476 -#, approved -msgid "Rating" -msgstr "Oylama" - -#: builtin/mainmenu/store.lua:501 -#, approved -msgid "re-Install" -msgstr "yeniden yükle" - -#: builtin/mainmenu/store.lua:503 -#, approved -msgid "Install" -msgstr "Yükle" - -#: builtin/mainmenu/store.lua:522 -#, approved -msgid "Close store" -msgstr "Mağazayı kapat" - -#: builtin/mainmenu/store.lua:530 -#, approved -msgid "Page $1 of $2" -msgstr "$2 sayfadan $1 'cisi" - -#: builtin/mainmenu/tab_credits.lua:22 -#, approved -msgid "Credits" -msgstr "Emeği Geçenler" - -#: builtin/mainmenu/tab_credits.lua:29 -#, approved -msgid "Core Developers" -msgstr "Ana geliştiriciler" - -#: builtin/mainmenu/tab_credits.lua:43 -#, approved -msgid "Active Contributors" -msgstr "Aktif katkı sağlayanlar" - -#: builtin/mainmenu/tab_credits.lua:48 -#, approved -msgid "Previous Contributors" -msgstr "Katkı sağlayanlar" - -#: builtin/mainmenu/tab_mods.lua:30 -#, approved -msgid "Installed Mods:" -msgstr "Yüklenen eklentiler :" - -#: builtin/mainmenu/tab_mods.lua:39 -#, approved -msgid "Online mod repository" -msgstr "Çevirimiçi eklenti deposu" - -#: builtin/mainmenu/tab_mods.lua:78 -#, approved -msgid "No mod description available" -msgstr "Eklenti bilgisi yok" - -#: builtin/mainmenu/tab_mods.lua:82 -#, approved -msgid "Mod information:" -msgstr "Eklenti bilgileri:" - -#: builtin/mainmenu/tab_mods.lua:93 -#, approved -msgid "Rename" -msgstr "Adlandır" - -#: builtin/mainmenu/tab_mods.lua:95 -#, approved -msgid "Uninstall selected modpack" -msgstr "Seçilen eklenti paketini sil" - -#: builtin/mainmenu/tab_mods.lua:106 -#, approved -msgid "Uninstall selected mod" -msgstr "Seçili eklentiyi sil" - -#: builtin/mainmenu/tab_mods.lua:121 -#, approved -msgid "Select Mod File:" -msgstr "Eklenti seç :" - -#: builtin/mainmenu/tab_mods.lua:165 -#, approved -msgid "Mods" -msgstr "Eklentiler" - -#: builtin/mainmenu/tab_multiplayer.lua:23 -#, approved -msgid "Address/Port" -msgstr "Adres / Port" - -#: builtin/mainmenu/tab_multiplayer.lua:24 builtin/mainmenu/tab_server.lua:37 -#: builtin/mainmenu/tab_simple_main.lua:25 -#, approved -msgid "Name/Password" -msgstr "Kullanıcı adı/Şifre" - -#: builtin/mainmenu/tab_multiplayer.lua:29 -#: builtin/mainmenu/tab_simple_main.lua:30 -#, approved -msgid "Public Serverlist" -msgstr "Çevirimiçi Oyun Listesi" - -#: builtin/mainmenu/tab_multiplayer.lua:34 builtin/mainmenu/tab_server.lua:26 -#: builtin/mainmenu/tab_singleplayer.lua:85 src/keycode.cpp:230 -#, approved -msgid "Delete" -msgstr "Sil" - -#: builtin/mainmenu/tab_multiplayer.lua:38 -#: builtin/mainmenu/tab_simple_main.lua:34 -#, approved -msgid "Connect" -msgstr "Bağlan" - -#: builtin/mainmenu/tab_multiplayer.lua:252 -#, approved -msgid "Client" -msgstr "Çevirimiçi Oyna" - -#: builtin/mainmenu/tab_server.lua:27 builtin/mainmenu/tab_singleplayer.lua:86 -#, approved -msgid "New" -msgstr "Yeni" - -#: builtin/mainmenu/tab_server.lua:28 builtin/mainmenu/tab_singleplayer.lua:87 -#, approved -msgid "Configure" -msgstr "Ayarla" - -#: builtin/mainmenu/tab_server.lua:29 -#, approved -msgid "Start Game" -msgstr "Oyunu Başlat" - -#: builtin/mainmenu/tab_server.lua:30 builtin/mainmenu/tab_singleplayer.lua:89 -#, approved -msgid "Select World:" -msgstr "Dünya seç :" - -#: builtin/mainmenu/tab_server.lua:31 builtin/mainmenu/tab_simple_main.lua:63 -#: builtin/mainmenu/tab_singleplayer.lua:90 -#, approved -msgid "Creative Mode" -msgstr "Yaratıcı Mod" - -#: builtin/mainmenu/tab_server.lua:33 builtin/mainmenu/tab_simple_main.lua:65 -#: builtin/mainmenu/tab_singleplayer.lua:92 -#, approved -msgid "Enable Damage" -msgstr "Hasarı etkinleştir" - -#: builtin/mainmenu/tab_server.lua:35 -#, approved -msgid "Public" -msgstr "Herkese Açık" - -#: builtin/mainmenu/tab_server.lua:45 -#, approved -msgid "Bind Address" -msgstr "Adresi doğrula" - -#: builtin/mainmenu/tab_server.lua:47 -#, approved -msgid "Port" -msgstr "Port" - -#: builtin/mainmenu/tab_server.lua:51 -#, approved -msgid "Server Port" -msgstr "Sunucu portu" - -#: builtin/mainmenu/tab_server.lua:174 -#, approved -msgid "Server" -msgstr "Sunucu Kur" - -#: builtin/mainmenu/tab_settings.lua:23 -#, approved -msgid "" -"Are you sure to reset your singleplayer " -"world?" -msgstr "" -"Tek kişilik dünyayı sıfırlamak istediğinizden emin misiniz " -"?" - -#: builtin/mainmenu/tab_settings.lua:27 -#, approved -msgid "No!!!" -msgstr "Hayır!!!" - -#: builtin/mainmenu/tab_settings.lua:134 -#, approved -msgid "Smooth Lighting" -msgstr "Pürüzsüz ışıklandırma" - -#: builtin/mainmenu/tab_settings.lua:136 -#, approved -msgid "Enable Particles" -msgstr "Parçacıkları etkinleştir" - -#: builtin/mainmenu/tab_settings.lua:138 -#, approved -msgid "3D Clouds" -msgstr "3 boyutlu bulutlar" - -#, approved -msgid "Fancy Trees" -msgstr "Şık ağaçlar" - -#: builtin/mainmenu/tab_settings.lua:142 -#, approved -msgid "Opaque Water" -msgstr "Şeffaf su" - -#, approved -msgid "Connected Glass" -msgstr "İçiçe geçmiş cam" - -#: builtin/mainmenu/tab_settings.lua:149 -#, approved -msgid "" -"Restart minetest for driver change to take " -"effect" -msgstr "" -"Değişikliklerin etkin olabilmesi için minetesti yeniden " -"başlatın" - -#: builtin/mainmenu/tab_settings.lua:151 -#, approved -msgid "Mip-Mapping" -msgstr "Mip-Mapping" - -#: builtin/mainmenu/tab_settings.lua:153 -#, approved -msgid "Anisotropic Filtering" -msgstr "Eşyönsüz süzme" - -#: builtin/mainmenu/tab_settings.lua:155 -#, approved -msgid "Bi-Linear Filtering" -msgstr "Çift yönlü süzme" - -#: builtin/mainmenu/tab_settings.lua:157 -#, approved -msgid "Tri-Linear Filtering" -msgstr "Üç yönlü süzme" - -#: builtin/mainmenu/tab_settings.lua:160 -#, approved -msgid "Shaders" -msgstr "Shaders" - -#: builtin/mainmenu/tab_settings.lua:164 -#, approved -msgid "Change keys" -msgstr "Tuşları değiştir" - -#: builtin/mainmenu/tab_settings.lua:167 -#, approved -msgid "Reset singleplayer world" -msgstr "Tek kişilik oyunu sıfırlayın" - -#: builtin/mainmenu/tab_settings.lua:171 -#, approved -msgid "GUI scale factor" -msgstr "Menü boyutları" - -#: builtin/mainmenu/tab_settings.lua:175 -#, approved -msgid "Scaling factor applied to menu elements: " -msgstr "Ölçeklendirme menülere işlendi:" - -#: builtin/mainmenu/tab_settings.lua:181 -#, approved -msgid "Touch free target" -msgstr "Touch free target" - -#: builtin/mainmenu/tab_settings.lua:187 -#, approved -msgid "Touchthreshold (px)" -msgstr "Touchthreshold (px)" - -#: builtin/mainmenu/tab_settings.lua:194 builtin/mainmenu/tab_settings.lua:208 -#, approved -msgid "Bumpmapping" -msgstr "Engebeler" - -#: builtin/mainmenu/tab_settings.lua:196 builtin/mainmenu/tab_settings.lua:209 -#, approved -msgid "Generate Normalmaps" -msgstr "Normal haritalar oluştur" - -#: builtin/mainmenu/tab_settings.lua:198 builtin/mainmenu/tab_settings.lua:210 -#, approved -msgid "Parallax Occlusion" -msgstr "Parallax Occlusion" - -#: builtin/mainmenu/tab_settings.lua:200 builtin/mainmenu/tab_settings.lua:211 -#, approved -msgid "Waving Water" -msgstr "Dalgalanan Su" - -#: builtin/mainmenu/tab_settings.lua:202 builtin/mainmenu/tab_settings.lua:212 -#, approved -msgid "Waving Leaves" -msgstr "Dalgalanan Yapraklar" - -#: builtin/mainmenu/tab_settings.lua:204 builtin/mainmenu/tab_settings.lua:213 -#, approved -msgid "Waving Plants" -msgstr "Dalgalanan Bitkiler" - -#: builtin/mainmenu/tab_settings.lua:255 -#, approved -msgid "" -"To enable shaders the OpenGL driver needs to be " -"used." -msgstr "OpenGL sürücüleri seçilmeden Shader etkinleştirilemez." - -#: builtin/mainmenu/tab_settings.lua:330 -#, approved -msgid "Settings" -msgstr "Ayarlar" - -#: builtin/mainmenu/tab_simple_main.lua:67 -#, approved -msgid "Fly mode" -msgstr "Uçuş modu" - -#: builtin/mainmenu/tab_simple_main.lua:71 -#, approved -msgid "Start Singleplayer" -msgstr "Tek kişilik oyunu başlat" - -#, approved -msgid "Config mods" -msgstr "Eklentileri ayarla" - -#: builtin/mainmenu/tab_simple_main.lua:191 -#, approved -msgid "Main" -msgstr "Ana" - -#: builtin/mainmenu/tab_singleplayer.lua:88 src/keycode.cpp:249 -#, approved -msgid "Play" -msgstr "Oyna" - -#: builtin/mainmenu/tab_singleplayer.lua:224 -#, approved -msgid "Singleplayer" -msgstr "Tek Kişilik" - -#: builtin/mainmenu/tab_texturepacks.lua:49 -#, approved -msgid "Select texture pack:" -msgstr "Doku paketi seç :" - -#: builtin/mainmenu/tab_texturepacks.lua:69 -#, approved -msgid "No information available" -msgstr "Bilgi yok" - -#: builtin/mainmenu/tab_texturepacks.lua:114 -#, approved -msgid "Texturepacks" -msgstr "Doku paketleri" - -#: src/client.cpp:2726 -#, approved -msgid "Item textures..." -msgstr "Nesne dokuları ..." - -#: src/fontengine.cpp:70 src/fontengine.cpp:226 -#, approved -msgid "needs_fallback_font" -msgstr "needs_fallback_font" - -#: src/game.cpp:1063 -#, approved -msgid "Respawn" -msgstr "Yeniden Canlan" - -#: src/game.cpp:2250 -#, approved -msgid "Item definitions..." -msgstr "Nesne tanımlamaları..." - -#: src/game.cpp:2255 -#, approved -msgid "Node definitions..." -msgstr "Blok tanımlamaları..." - -#: src/game.cpp:2262 -#, approved -msgid "Media..." -msgstr "Media..." - -#: src/game.cpp:2267 -#, approved -msgid " KB/s" -msgstr " KB/s" - -#: src/game.cpp:2271 -#, approved -msgid " MB/s" -msgstr " MB/s" - -#: src/game.cpp:4220 -#, approved -msgid "" -"\n" -"Check debug.txt for details." -msgstr "" -"\n" -"Hata ayrıntıları için debug.txt dosyasını inceleyin." - -#: src/guiFormSpecMenu.cpp:2055 -#, approved -msgid "Proceed" -msgstr "Uygula" - -#: src/guiFormSpecMenu.cpp:2846 -#, approved -msgid "Enter " -msgstr "Entrer " - -#: src/guiKeyChangeMenu.cpp:125 -#, approved -msgid "" -"Keybindings. (If this menu screws up, remove stuff from " -"minetest.conf)" -msgstr "Tuş ayaları. ( Olağandışı durumlarda minetest.conf 'u düzenleyin )" - -#: src/guiKeyChangeMenu.cpp:165 -#, approved -msgid "\"Use\" = climb down" -msgstr "\"Kullan\" = Aşağı in" - -#: src/guiKeyChangeMenu.cpp:180 -#, approved -msgid "Double tap \"jump\" to toggle fly" -msgstr "Çift zıplayarak uçma modunu aç/kapa" - -#: src/guiKeyChangeMenu.cpp:296 -#, approved -msgid "Key already in use" -msgstr "Tuş zaten kullanımda" - -#: src/guiKeyChangeMenu.cpp:371 -#, approved -msgid "press key" -msgstr "tuşa bas" - -#: src/guiKeyChangeMenu.cpp:397 -#, approved -msgid "Forward" -msgstr "İleri" - -#: src/guiKeyChangeMenu.cpp:398 -#, approved -msgid "Backward" -msgstr "Geri" - -#: src/guiKeyChangeMenu.cpp:399 src/keycode.cpp:229 -#, approved -msgid "Left" -msgstr "Sol" - -#: src/guiKeyChangeMenu.cpp:400 src/keycode.cpp:229 -#, approved -msgid "Right" -msgstr "Sağ" - -#: src/guiKeyChangeMenu.cpp:401 -#, approved -msgid "Use" -msgstr "Kullan" - -#: src/guiKeyChangeMenu.cpp:402 -#, approved -msgid "Jump" -msgstr "Zıpla" - -#: src/guiKeyChangeMenu.cpp:403 -#, approved -msgid "Sneak" -msgstr "Sessiz Yürü" - -#: src/guiKeyChangeMenu.cpp:404 -#, approved -msgid "Drop" -msgstr "Bırak" - -#: src/guiKeyChangeMenu.cpp:405 -#, approved -msgid "Inventory" -msgstr "Envanter" - -#: src/guiKeyChangeMenu.cpp:406 -#, approved -msgid "Chat" -msgstr "Konuşma" - -#: src/guiKeyChangeMenu.cpp:407 -#, approved -msgid "Command" -msgstr "Komut" - -#: src/guiKeyChangeMenu.cpp:408 -#, approved -msgid "Console" -msgstr "Konsol" - -#: src/guiKeyChangeMenu.cpp:409 -#, approved -msgid "Toggle fly" -msgstr "Uçuş modu aç/kapa" - -#: src/guiKeyChangeMenu.cpp:410 -#, approved -msgid "Toggle fast" -msgstr "Hız modu aç/kapa" - -#: src/guiKeyChangeMenu.cpp:411 -#, approved -msgid "Toggle noclip" -msgstr "Noclip aç/kapa" - -#: src/guiKeyChangeMenu.cpp:412 -#, approved -msgid "Range select" -msgstr "Uzaklık seçimi" - -#: src/guiKeyChangeMenu.cpp:413 -#, approved -msgid "Print stacks" -msgstr "Yazdırma yığınları" - -#: src/guiPasswordChange.cpp:106 -#, approved -msgid "Old Password" -msgstr "Eski şifre" - -#: src/guiPasswordChange.cpp:122 -#, approved -msgid "New Password" -msgstr "Yeni şifre" - -#: src/guiPasswordChange.cpp:137 -#, approved -msgid "Confirm Password" -msgstr "Şifreyi doğrulayın" - -#: src/guiPasswordChange.cpp:153 -#, approved -msgid "Change" -msgstr "Değiştir" - -#: src/guiPasswordChange.cpp:162 -#, approved -msgid "Passwords do not match!" -msgstr "Şifreler uyuşmuyor !" - -#: src/guiVolumeChange.cpp:106 -#, approved -msgid "Sound Volume: " -msgstr "Ses yüksekliği :" - -#: src/guiVolumeChange.cpp:120 -#, approved -msgid "Exit" -msgstr "Çıkış" - -#: src/keycode.cpp:224 -#, approved -msgid "Left Button" -msgstr "Sol tuşu" - -#: src/keycode.cpp:224 -#, approved -msgid "Middle Button" -msgstr "Orta Tuş" - -#: src/keycode.cpp:224 -#, approved -msgid "Right Button" -msgstr "Sağ tuş" - -#: src/keycode.cpp:224 -#, approved -msgid "X Button 1" -msgstr "X Button 1" - -#: src/keycode.cpp:225 -#, approved -msgid "Back" -msgstr "Geri" - -#: src/keycode.cpp:225 -#, approved -msgid "Clear" -msgstr "Temizle" - -#: src/keycode.cpp:225 -#, approved -msgid "Return" -msgstr "Return" - -#: src/keycode.cpp:225 -#, approved -msgid "Tab" -msgstr "Tab" - -#: src/keycode.cpp:225 -#, approved -msgid "X Button 2" -msgstr "X Button 2" - -#: src/keycode.cpp:226 -#, approved -msgid "Capital" -msgstr "Büyük" - -#: src/keycode.cpp:226 -#, approved -msgid "Control" -msgstr "Kontroller" - -#: src/keycode.cpp:226 -#, approved -msgid "Kana" -msgstr "Kana" - -#: src/keycode.cpp:226 -#, approved -msgid "Menu" -msgstr "Menü" - -#: src/keycode.cpp:226 -#, approved -msgid "Pause" -msgstr "Beklet" - -#: src/keycode.cpp:226 -#, approved -msgid "Shift" -msgstr "Shift" - -#: src/keycode.cpp:227 -#, approved -msgid "Convert" -msgstr "Dönüştür" - -#: src/keycode.cpp:227 -#, approved -msgid "Escape" -msgstr "Çıkış" - -#: src/keycode.cpp:227 -#, approved -msgid "Final" -msgstr "Bitiş" - -#: src/keycode.cpp:227 -#, approved -msgid "Junja" -msgstr "Junja" - -#: src/keycode.cpp:227 -#, approved -msgid "Kanji" -msgstr "Kanji" - -#: src/keycode.cpp:227 -#, approved -msgid "Nonconvert" -msgstr "Dönüştürme" - -#: src/keycode.cpp:228 -#, approved -msgid "End" -msgstr "Son" - -#: src/keycode.cpp:228 -#, approved -msgid "Home" -msgstr "Ev" - -#: src/keycode.cpp:228 -#, approved -msgid "Mode Change" -msgstr "Mod değiştir" - -#: src/keycode.cpp:228 -#, approved -msgid "Next" -msgstr "İleri" - -#: src/keycode.cpp:228 -#, approved -msgid "Prior" -msgstr "Öncelikli" - -#: src/keycode.cpp:228 -#, approved -msgid "Space" -msgstr "Boşluk" - -#: src/keycode.cpp:229 -#, approved -msgid "Down" -msgstr "Aşağı" - -#: src/keycode.cpp:229 -#, approved -msgid "Execute" -msgstr "Çalıştır" - -#: src/keycode.cpp:229 -#, approved -msgid "Print" -msgstr "Yazdır" - -#: src/keycode.cpp:229 -#, approved -msgid "Select" -msgstr "Seç" - -#: src/keycode.cpp:229 -#, approved -msgid "Up" -msgstr "Yukarı" - -#: src/keycode.cpp:230 -#, approved -msgid "Help" -msgstr "Yardım" - -#: src/keycode.cpp:230 -#, approved -msgid "Insert" -msgstr "Insert" - -#: src/keycode.cpp:230 -#, approved -msgid "Snapshot" -msgstr "Ekran Resmi" - -#: src/keycode.cpp:233 -#, approved -msgid "Left Windows" -msgstr "Sol Windows tuşu" - -#: src/keycode.cpp:234 -#, approved -msgid "Apps" -msgstr "Uygulamalar" - -#: src/keycode.cpp:234 -#, approved -msgid "Numpad 0" -msgstr "Numpad 0" - -#: src/keycode.cpp:234 -#, approved -msgid "Numpad 1" -msgstr "Numpad 1" - -#: src/keycode.cpp:234 -#, approved -msgid "Right Windows" -msgstr "Sağ Windows tuşu" - -#: src/keycode.cpp:234 -#, approved -msgid "Sleep" -msgstr "Uyu" - -#: src/keycode.cpp:235 -#, approved -msgid "Numpad 2" -msgstr "Numpad 2" - -#: src/keycode.cpp:235 -#, approved -msgid "Numpad 3" -msgstr "Numpad 3" - -#: src/keycode.cpp:235 -#, approved -msgid "Numpad 4" -msgstr "Numpad 4" - -#: src/keycode.cpp:235 -#, approved -msgid "Numpad 5" -msgstr "Numpad 5" - -#: src/keycode.cpp:235 -#, approved -msgid "Numpad 6" -msgstr "Numpad 6" - -#: src/keycode.cpp:235 -#, approved -msgid "Numpad 7" -msgstr "Numpad 7" - -#: src/keycode.cpp:236 -#, approved -msgid "Numpad *" -msgstr "Numpad *" - -#: src/keycode.cpp:236 -#, approved -msgid "Numpad +" -msgstr "Numpad +" - -#: src/keycode.cpp:236 -#, approved -msgid "Numpad -" -msgstr "Numpad -" - -#: src/keycode.cpp:236 -#, approved -msgid "Numpad /" -msgstr "Numpad /" - -#: src/keycode.cpp:236 -#, approved -msgid "Numpad 8" -msgstr "Numpad 8" - -#: src/keycode.cpp:236 -#, approved -msgid "Numpad 9" -msgstr "Numpad 9" - -#: src/keycode.cpp:240 -#, approved -msgid "Num Lock" -msgstr "Num Lock" - -#: src/keycode.cpp:240 -#, approved -msgid "Scroll Lock" -msgstr "Scroll Lock" - -#: src/keycode.cpp:241 -#, approved -msgid "Left Shift" -msgstr "Sol Shift" - -#: src/keycode.cpp:241 -#, approved -msgid "Right Shift" -msgstr "Sağ Shift" - -#: src/keycode.cpp:242 -#, approved -msgid "Left Control" -msgstr "Sol CTRL" - -#: src/keycode.cpp:242 -#, approved -msgid "Left Menu" -msgstr "Sol Menu" - -#: src/keycode.cpp:242 -#, approved -msgid "Right Control" -msgstr "Sağ CTRL" - -#: src/keycode.cpp:242 -#, approved -msgid "Right Menu" -msgstr "Sağ Menu" - -#: src/keycode.cpp:244 -#, approved -msgid "Comma" -msgstr "Virgul" - -#: src/keycode.cpp:244 -#, approved -msgid "Minus" -msgstr "Eksi" - -#: src/keycode.cpp:244 -#, approved -msgid "Period" -msgstr "Dönem" - -#: src/keycode.cpp:244 -#, approved -msgid "Plus" -msgstr "Artı" - -#: src/keycode.cpp:248 -#, approved -msgid "Attn" -msgstr "Dikkat" - -#: src/keycode.cpp:248 -#, approved -msgid "CrSel" -msgstr "CrSel" - -#: src/keycode.cpp:249 -#, approved -msgid "Erase OEF" -msgstr "l'OEF 'i sil" - -#: src/keycode.cpp:249 -#, approved -msgid "ExSel" -msgstr "ExSel" - -#: src/keycode.cpp:249 -#, approved -msgid "OEM Clear" -msgstr "OEM Temizle" - -#: src/keycode.cpp:249 -#, approved -msgid "PA1" -msgstr "PA1" - -#: src/keycode.cpp:249 -#, approved -msgid "Zoom" -msgstr "Yakınlaştır" - -#: src/main.cpp:1681 -#, approved -msgid "Main Menu" -msgstr "Ana menu" - -#: src/main.cpp:1719 -#, approved -msgid "Player name too long." -msgstr "Kullanıcı adı çok uzun." - -#: src/main.cpp:1757 -#, approved -msgid "Connection error (timed out?)" -msgstr "Bağlantı hatası ( Zaman aşımı ? )" - -#: src/main.cpp:1919 -#, approved -msgid "" -"No world selected and no address provided. Nothing to " -"do." -msgstr "Dünya veya adres seçilmedi." - -#: src/main.cpp:1926 -#, approved -msgid "Provided world path doesn't exist: " -msgstr "Belirtilen dünya konumu yok:" - -#: src/main.cpp:1935 -#, approved -msgid "Could not find or load game \"" -msgstr "Oyun bulunamıyor veya yüklenemiyor \"" - -#: src/main.cpp:1953 -#, approved -msgid "Invalid gamespec." -msgstr "Geçersiz oyun özellikleri." diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d56ec18c0..93083f369 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -352,19 +352,16 @@ add_custom_target(GenerateVersion WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") add_subdirectory(jthread) -add_subdirectory(network) add_subdirectory(script) add_subdirectory(util) -set (unittests_SRCS - test.cpp -) - set(common_SRCS ban.cpp + base64.cpp cavegen.cpp clientiface.cpp collision.cpp + connection.cpp content_abm.cpp content_mapnode.cpp content_nodemeta.cpp @@ -421,20 +418,20 @@ set(common_SRCS serverlist.cpp serverobject.cpp settings.cpp + sha1.cpp socket.cpp sound.cpp staticobject.cpp subgame.cpp + test.cpp tool.cpp treegen.cpp version.cpp voxel.cpp voxelalgorithms.cpp - ${common_network_SRCS} ${JTHREAD_SRCS} ${common_SCRIPT_SRCS} ${UTIL_SRCS} - ${unittests_SRCS} ) # This gives us the icon and file version information @@ -457,16 +454,9 @@ if(WIN32) endif() # Client sources - -if (BUILD_CLIENT) - add_subdirectory(client) -endif(BUILD_CLIENT) - set(minetest_SRCS ${common_SRCS} ${sound_SRCS} - ${client_SRCS} - ${client_network_SRCS} camera.cpp chat.cpp client.cpp @@ -499,6 +489,7 @@ set(minetest_SRCS particles.cpp shader.cpp sky.cpp + tile.cpp wieldmesh.cpp ${minetest_SCRIPT_SRCS} ) diff --git a/src/activeobject.h b/src/activeobject.h index 48f078d3f..46880fc7f 100644 --- a/src/activeobject.h +++ b/src/activeobject.h @@ -23,22 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irr_aabb3d.h" #include -enum ActiveObjectType { - ACTIVEOBJECT_TYPE_INVALID = 0, - ACTIVEOBJECT_TYPE_TEST = 1, -// Deprecated stuff - ACTIVEOBJECT_TYPE_ITEM = 2, - ACTIVEOBJECT_TYPE_RAT = 3, - ACTIVEOBJECT_TYPE_OERKKI1 = 4, - ACTIVEOBJECT_TYPE_FIREFLY = 5, - ACTIVEOBJECT_TYPE_MOBV2 = 6, -// End deprecated stuff - ACTIVEOBJECT_TYPE_LUAENTITY = 7, -// Special type, not stored as a static object - ACTIVEOBJECT_TYPE_PLAYER = 100, -// Special type, only exists as CAO - ACTIVEOBJECT_TYPE_GENERIC = 101, -}; +#define ACTIVEOBJECT_TYPE_INVALID 0 // Other types are defined in content_object.h struct ActiveObjectMessage @@ -75,7 +60,7 @@ public: m_id = id; } - virtual ActiveObjectType getType() const = 0; + virtual u8 getType() const = 0; virtual bool getCollisionBox(aabb3f *toset) = 0; virtual bool collideWithObjects() = 0; protected: diff --git a/src/util/base64.cpp b/src/base64.cpp similarity index 100% rename from src/util/base64.cpp rename to src/base64.cpp diff --git a/src/util/base64.h b/src/base64.h similarity index 100% rename from src/util/base64.h rename to src/base64.h diff --git a/src/camera.h b/src/camera.h index b53738860..3f10b87d7 100644 --- a/src/camera.h +++ b/src/camera.h @@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes_extrabloated.h" #include "inventory.h" #include "mesh.h" -#include "client/tile.h" +#include "tile.h" #include "util/numeric.h" #include diff --git a/src/cavegen.cpp b/src/cavegen.cpp index 8fb1a7293..22bf03d17 100644 --- a/src/cavegen.cpp +++ b/src/cavegen.cpp @@ -20,7 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/numeric.h" #include "map.h" #include "mapgen.h" -#include "mapgen_v5.h" #include "mapgen_v6.h" #include "mapgen_v7.h" #include "cavegen.h" @@ -28,263 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., NoiseParams nparams_caveliquids(0, 1, v3f(150.0, 150.0, 150.0), 776, 3, 0.6, 2.0); -///////////////////////////////////////// Caves V5 - - -CaveV5::CaveV5(MapgenV5 *mg, PseudoRandom *ps) { - this->mg = mg; - this->vm = mg->vm; - this->ndef = mg->ndef; - this->water_level = mg->water_level; - this->ps = ps; - this->c_water_source = mg->c_water_source; - this->c_lava_source = mg->c_lava_source; - this->c_ice = mg->c_ice; - this->np_caveliquids = &nparams_caveliquids; - - dswitchint = ps->range(1, 14); - flooded = ps->range(1, 2) == 2; - - part_max_length_rs = ps->range(2, 4); - tunnel_routepoints = ps->range(5, ps->range(15, 30)); - min_tunnel_diameter = 5; - max_tunnel_diameter = ps->range(7, ps->range(8, 24)); - - large_cave_is_flat = (ps->range(0, 1) == 0); -} - - -void CaveV5::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height) { - node_min = nmin; - node_max = nmax; - main_direction = v3f(0, 0, 0); - - // Allowed route area size in nodes - ar = node_max - node_min + v3s16(1, 1, 1); - // Area starting point in nodes - of = node_min; - - // Allow a bit more - //(this should be more than the maximum radius of the tunnel) - s16 insure = 10; - s16 more = MYMAX(MAP_BLOCKSIZE - max_tunnel_diameter / 2 - insure, 1); - ar += v3s16(1,0,1) * more * 2; - of -= v3s16(1,0,1) * more; - - route_y_min = 0; - // Allow half a diameter + 7 over stone surface - route_y_max = -of.Y + max_stone_y + max_tunnel_diameter / 2 + 7; - - // Limit maximum to area - route_y_max = rangelim(route_y_max, 0, ar.Y - 1); - - s16 min = 0; - if (node_min.Y < water_level && node_max.Y > water_level) { - min = water_level - max_tunnel_diameter/3 - of.Y; - route_y_max = water_level + max_tunnel_diameter/3 - of.Y; - } - route_y_min = ps->range(min, min + max_tunnel_diameter); - route_y_min = rangelim(route_y_min, 0, route_y_max); - - s16 route_start_y_min = route_y_min; - s16 route_start_y_max = route_y_max; - - route_start_y_min = rangelim(route_start_y_min, 0, ar.Y - 1); - route_start_y_max = rangelim(route_start_y_max, route_start_y_min, ar.Y - 1); - - // Randomize starting position - orp = v3f( - (float)(ps->next() % ar.X) + 0.5, - (float)(ps->range(route_start_y_min, route_start_y_max)) + 0.5, - (float)(ps->next() % ar.Z) + 0.5 - ); - - // Add generation notify begin event - v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); - GenNotifyType notifytype = GENNOTIFY_LARGECAVE_BEGIN; - mg->gennotify.addEvent(notifytype, abs_pos); - - // Generate some tunnel starting from orp - for (u16 j = 0; j < tunnel_routepoints; j++) - makeTunnel(j % dswitchint == 0); - - // Add generation notify end event - abs_pos = v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); - notifytype = GENNOTIFY_LARGECAVE_END; - mg->gennotify.addEvent(notifytype, abs_pos); -} - - -void CaveV5::makeTunnel(bool dirswitch) { - - // Randomize size - s16 min_d = min_tunnel_diameter; - s16 max_d = max_tunnel_diameter; - rs = ps->range(min_d, max_d); - s16 rs_part_max_length_rs = rs * part_max_length_rs; - - v3s16 maxlen; - maxlen = v3s16( - rs_part_max_length_rs, - rs_part_max_length_rs / 2, - rs_part_max_length_rs - ); - - v3f vec; - // Jump downward sometimes - vec = v3f( - (float)(ps->next() % maxlen.X) - (float)maxlen.X / 2, - (float)(ps->next() % maxlen.Y) - (float)maxlen.Y / 2, - (float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2 - ); - - // Do not make large caves that are above ground. - // It is only necessary to check the startpoint and endpoint. - v3s16 orpi(orp.X, orp.Y, orp.Z); - v3s16 veci(vec.X, vec.Y, vec.Z); - v3s16 p; - - p = orpi + veci + of + rs / 2; - if (p.Z >= node_min.Z && p.Z <= node_max.Z && - p.X >= node_min.X && p.X <= node_max.X) { - u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X); - s16 h = mg->heightmap[index]; - if (h < p.Y) - return; - } else if (p.Y > water_level) { - return; // If it's not in our heightmap, use a simple heuristic - } - - p = orpi + of + rs / 2; - if (p.Z >= node_min.Z && p.Z <= node_max.Z && - p.X >= node_min.X && p.X <= node_max.X) { - u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X); - s16 h = mg->heightmap[index]; - if (h < p.Y) - return; - } else if (p.Y > water_level) { - return; - } - - vec += main_direction; - - v3f rp = orp + vec; - if (rp.X < 0) - rp.X = 0; - else if (rp.X >= ar.X) - rp.X = ar.X - 1; - - if (rp.Y < route_y_min) - rp.Y = route_y_min; - else if (rp.Y >= route_y_max) - rp.Y = route_y_max - 1; - - if (rp.Z < 0) - rp.Z = 0; - else if (rp.Z >= ar.Z) - rp.Z = ar.Z - 1; - - vec = rp - orp; - - float veclen = vec.getLength(); - if (veclen < 0.05) - veclen = 1.0; - - // Every second section is rough - bool randomize_xz = (ps->range(1, 2) == 1); - - // Make a ravine every once in a while if it's long enough - //float xylen = vec.X * vec.X + vec.Z * vec.Z; - //disable ravines for now - bool is_ravine = false; //(xylen > 500.0) && !large_cave && (ps->range(1, 8) == 1); - - // Carve routes - for (float f = 0; f < 1.0; f += 1.0 / veclen) - carveRoute(vec, f, randomize_xz, is_ravine); - - orp = rp; -} - - -void CaveV5::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) { - MapNode airnode(CONTENT_AIR); - MapNode waternode(c_water_source); - MapNode lavanode(c_lava_source); - - v3s16 startp(orp.X, orp.Y, orp.Z); - startp += of; - - float nval = NoisePerlin3D(np_caveliquids, startp.X, - startp.Y, startp.Z, mg->seed); - MapNode liquidnode = nval < 0.40 ? lavanode : waternode; - - v3f fp = orp + vec * f; - fp.X += 0.1 * ps->range(-10, 10); - fp.Z += 0.1 * ps->range(-10, 10); - v3s16 cp(fp.X, fp.Y, fp.Z); - - s16 d0 = -rs/2; - s16 d1 = d0 + rs; - if (randomize_xz) { - d0 += ps->range(-1, 1); - d1 += ps->range(-1, 1); - } - - bool should_make_cave_hole = ps->range(1, 10) == 1; - - for (s16 z0 = d0; z0 <= d1; z0++) { - s16 si = rs / 2 - MYMAX(0, abs(z0) - rs / 7 - 1); - for (s16 x0 = -si - ps->range(0,1); x0 <= si - 1 + ps->range(0,1); x0++) { - s16 maxabsxz = MYMAX(abs(x0), abs(z0)); - - s16 si2 = is_ravine ? MYMIN(ps->range(25, 26), ar.Y) : - rs / 2 - MYMAX(0, maxabsxz - rs / 7 - 1); - - for (s16 y0 = -si2; y0 <= si2; y0++) { - if (large_cave_is_flat) { - // Make large caves not so tall - if (rs > 7 && abs(y0) >= rs / 3) - continue; - } - - v3s16 p(cp.X + x0, cp.Y + y0, cp.Z + z0); - p += of; - - if (!is_ravine && mg->heightmap && should_make_cave_hole && - p.X <= node_max.X && p.Z <= node_max.Z) { - int maplen = node_max.X - node_min.X + 1; - int idx = (p.Z - node_min.Z) * maplen + (p.X - node_min.X); - if (p.Y >= mg->heightmap[idx] - 2) - continue; - } - - if (vm->m_area.contains(p) == false) - continue; - - u32 i = vm->m_area.index(p); - - // Don't replace air, water, lava, or ice - content_t c = vm->m_data[i].getContent(); - if (!ndef->get(c).is_ground_content || c == CONTENT_AIR || - c == c_water_source || c == c_lava_source || c == c_ice) - continue; - - int full_ymin = node_min.Y - MAP_BLOCKSIZE; - int full_ymax = node_max.Y + MAP_BLOCKSIZE; - - if (flooded && full_ymin < water_level && full_ymax > water_level) - vm->m_data[i] = (p.Y <= water_level) ? waternode : airnode; - else if (flooded && full_ymax < water_level) - vm->m_data[i] = (p.Y < startp.Y - 4) ? liquidnode : airnode; - else - vm->m_data[i] = airnode; - } - } - } -} - - -///////////////////////////////////////// Caves V6 +/////////////////////////////////////////////////////////////////////////////// CaveV6::CaveV6(MapgenV6 *mg, PseudoRandom *ps, PseudoRandom *ps2, bool is_large_cave) { @@ -398,68 +141,37 @@ void CaveV6::makeTunnel(bool dirswitch) { s16 min_d = min_tunnel_diameter; s16 max_d = max_tunnel_diameter; rs = ps->range(min_d, max_d); - s16 rs_part_max_length_rs = rs * part_max_length_rs; v3s16 maxlen; if (large_cave) { maxlen = v3s16( - rs_part_max_length_rs, - rs_part_max_length_rs / 2, - rs_part_max_length_rs + rs * part_max_length_rs, + rs * part_max_length_rs / 2, + rs * part_max_length_rs ); } else { maxlen = v3s16( - rs_part_max_length_rs, - ps->range(1, rs_part_max_length_rs), - rs_part_max_length_rs + rs * part_max_length_rs, + ps->range(1, rs * part_max_length_rs), + rs * part_max_length_rs ); } v3f vec( - (float)(ps->next() % maxlen.X) - (float)maxlen.X / 2, - (float)(ps->next() % maxlen.Y) - (float)maxlen.Y / 2, - (float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2 + (float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2, + (float)(ps->next() % (maxlen.Y * 1)) - (float)maxlen.Y / 2, + (float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2 ); // Jump downward sometimes if (!large_cave && ps->range(0, 12) == 0) { vec = v3f( - (float)(ps->next() % maxlen.X) - (float)maxlen.X / 2, + (float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2, (float)(ps->next() % (maxlen.Y * 2)) - (float)maxlen.Y, - (float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2 + (float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2 ); } - // Do not make large caves that are entirely above ground. - // It is only necessary to check the startpoint and endpoint. - if (large_cave) { - v3s16 orpi(orp.X, orp.Y, orp.Z); - v3s16 veci(vec.X, vec.Y, vec.Z); - s16 h1; - s16 h2; - - v3s16 p1 = orpi + veci + of + rs / 2; - if (p1.Z >= node_min.Z && p1.Z <= node_max.Z && - p1.X >= node_min.X && p1.X <= node_max.X) { - u32 index1 = (p1.Z - node_min.Z) * mg->ystride + (p1.X - node_min.X); - h1 = mg->heightmap[index1]; - } else { - h1 = water_level; // If not in heightmap - } - - v3s16 p2 = orpi + of + rs / 2; - if (p2.Z >= node_min.Z && p2.Z <= node_max.Z && - p2.X >= node_min.X && p2.X <= node_max.X) { - u32 index2 = (p2.Z - node_min.Z) * mg->ystride + (p2.X - node_min.X); - h2 = mg->heightmap[index2]; - } else { - h2 = water_level; - } - - if (p1.Y > h1 && p2.Y > h2) // If startpoint and endpoint are above ground - return; - } - vec += main_direction; v3f rp = orp + vec; @@ -567,12 +279,12 @@ void CaveV6::carveRoute(v3f vec, float f, bool randomize_xz) { ///////////////////////////////////////// Caves V7 - -CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps) { +CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps, bool is_large_cave) { this->mg = mg; this->vm = mg->vm; this->ndef = mg->ndef; this->water_level = mg->water_level; + this->large_cave = is_large_cave; this->ps = ps; this->c_water_source = mg->c_water_source; this->c_lava_source = mg->c_lava_source; @@ -582,10 +294,17 @@ CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps) { dswitchint = ps->range(1, 14); flooded = ps->range(1, 2) == 2; - part_max_length_rs = ps->range(2, 4); - tunnel_routepoints = ps->range(5, ps->range(15, 30)); - min_tunnel_diameter = 5; - max_tunnel_diameter = ps->range(7, ps->range(8, 24)); + if (large_cave) { + part_max_length_rs = ps->range(2, 4); + tunnel_routepoints = ps->range(5, ps->range(15, 30)); + min_tunnel_diameter = 5; + max_tunnel_diameter = ps->range(7, ps->range(8, 24)); + } else { + part_max_length_rs = ps->range(2, 9); + tunnel_routepoints = ps->range(10, ps->range(15, 30)); + min_tunnel_diameter = 2; + max_tunnel_diameter = ps->range(2, 6); + } large_cave_is_flat = (ps->range(0, 1) == 0); } @@ -616,13 +335,15 @@ void CaveV7::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height) { // Limit maximum to area route_y_max = rangelim(route_y_max, 0, ar.Y - 1); - s16 min = 0; - if (node_min.Y < water_level && node_max.Y > water_level) { - min = water_level - max_tunnel_diameter/3 - of.Y; - route_y_max = water_level + max_tunnel_diameter/3 - of.Y; + if (large_cave) { + s16 min = 0; + if (node_min.Y < water_level && node_max.Y > water_level) { + min = water_level - max_tunnel_diameter/3 - of.Y; + route_y_max = water_level + max_tunnel_diameter/3 - of.Y; + } + route_y_min = ps->range(min, min + max_tunnel_diameter); + route_y_min = rangelim(route_y_min, 0, route_y_max); } - route_y_min = ps->range(min, min + max_tunnel_diameter); - route_y_min = rangelim(route_y_min, 0, route_y_max); s16 route_start_y_min = route_y_min; s16 route_start_y_max = route_y_max; @@ -639,7 +360,8 @@ void CaveV7::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height) { // Add generation notify begin event v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); - GenNotifyType notifytype = GENNOTIFY_LARGECAVE_BEGIN; + GenNotifyType notifytype = large_cave ? + GENNOTIFY_LARGECAVE_BEGIN : GENNOTIFY_CAVE_BEGIN; mg->gennotify.addEvent(notifytype, abs_pos); // Generate some tunnel starting from orp @@ -648,60 +370,86 @@ void CaveV7::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height) { // Add generation notify end event abs_pos = v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); - notifytype = GENNOTIFY_LARGECAVE_END; + notifytype = large_cave ? + GENNOTIFY_LARGECAVE_END : GENNOTIFY_CAVE_END; mg->gennotify.addEvent(notifytype, abs_pos); } void CaveV7::makeTunnel(bool dirswitch) { + if (dirswitch && !large_cave) { + main_direction = v3f( + ((float)(ps->next() % 20) - (float)10) / 10, + ((float)(ps->next() % 20) - (float)10) / 30, + ((float)(ps->next() % 20) - (float)10) / 10 + ); + main_direction *= (float)ps->range(0, 10) / 10; + } // Randomize size s16 min_d = min_tunnel_diameter; s16 max_d = max_tunnel_diameter; rs = ps->range(min_d, max_d); - s16 rs_part_max_length_rs = rs * part_max_length_rs; v3s16 maxlen; - maxlen = v3s16( - rs_part_max_length_rs, - rs_part_max_length_rs / 2, - rs_part_max_length_rs - ); + if (large_cave) { + maxlen = v3s16( + rs * part_max_length_rs, + rs * part_max_length_rs / 2, + rs * part_max_length_rs + ); + } else { + maxlen = v3s16( + rs * part_max_length_rs, + ps->range(1, rs * part_max_length_rs), + rs * part_max_length_rs + ); + } v3f vec; // Jump downward sometimes - vec = v3f( - (float)(ps->next() % maxlen.X) - (float)maxlen.X / 2, - (float)(ps->next() % maxlen.Y) - (float)maxlen.Y / 2, - (float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2 - ); + if (!large_cave && ps->range(0, 12) == 0) { + vec = v3f( + (float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2, + (float)(ps->next() % (maxlen.Y * 2)) - (float)maxlen.Y, + (float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2 + ); + } else { + vec = v3f( + (float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2, + (float)(ps->next() % (maxlen.Y * 1)) - (float)maxlen.Y / 2, + (float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2 + ); + } // Do not make large caves that are above ground. // It is only necessary to check the startpoint and endpoint. - v3s16 orpi(orp.X, orp.Y, orp.Z); - v3s16 veci(vec.X, vec.Y, vec.Z); - v3s16 p; + if (large_cave) { + v3s16 orpi(orp.X, orp.Y, orp.Z); + v3s16 veci(vec.X, vec.Y, vec.Z); + v3s16 p; - p = orpi + veci + of + rs / 2; - if (p.Z >= node_min.Z && p.Z <= node_max.Z && + p = orpi + veci + of + rs / 2; + if (p.Z >= node_min.Z && p.Z <= node_max.Z && p.X >= node_min.X && p.X <= node_max.X) { - u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X); - s16 h = mg->ridge_heightmap[index]; - if (h < p.Y) - return; - } else if (p.Y > water_level) { - return; // If it's not in our heightmap, use a simple heuristic - } + u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X); + s16 h = mg->ridge_heightmap[index]; + if (h < p.Y) + return; + } else if (p.Y > water_level) { + return; // If it's not in our heightmap, use a simple heuristic + } - p = orpi + of + rs / 2; - if (p.Z >= node_min.Z && p.Z <= node_max.Z && + p = orpi + of + rs / 2; + if (p.Z >= node_min.Z && p.Z <= node_max.Z && p.X >= node_min.X && p.X <= node_max.X) { - u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X); - s16 h = mg->ridge_heightmap[index]; - if (h < p.Y) + u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X); + s16 h = mg->ridge_heightmap[index]; + if (h < p.Y) + return; + } else if (p.Y > water_level) { return; - } else if (p.Y > water_level) { - return; + } } vec += main_direction; @@ -754,7 +502,7 @@ void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) { float nval = NoisePerlin3D(np_caveliquids, startp.X, startp.Y, startp.Z, mg->seed); - MapNode liquidnode = (nval < 0.40 && node_max.Y < -256) ? lavanode : waternode; + MapNode liquidnode = nval < 0.40 ? lavanode : waternode; v3f fp = orp + vec * f; fp.X += 0.1 * ps->range(-10, 10); @@ -768,6 +516,7 @@ void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) { d1 += ps->range(-1, 1); } + bool flat_cave_floor = !large_cave && ps->range(0, 2) == 2; bool should_make_cave_hole = ps->range(1, 10) == 1; for (s16 z0 = d0; z0 <= d1; z0++) { @@ -779,6 +528,10 @@ void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) { rs / 2 - MYMAX(0, maxabsxz - rs / 7 - 1); for (s16 y0 = -si2; y0 <= si2; y0++) { + // Make better floors in small caves + if(flat_cave_floor && y0 <= -rs/2 && rs<=7) + continue; + if (large_cave_is_flat) { // Make large caves not so tall if (rs > 7 && abs(y0) >= rs / 3) @@ -807,17 +560,24 @@ void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) { c == c_water_source || c == c_lava_source || c == c_ice) continue; - int full_ymin = node_min.Y - MAP_BLOCKSIZE; - int full_ymax = node_max.Y + MAP_BLOCKSIZE; + if (large_cave) { + int full_ymin = node_min.Y - MAP_BLOCKSIZE; + int full_ymax = node_max.Y + MAP_BLOCKSIZE; + + if (flooded && full_ymin < water_level && full_ymax > water_level) + vm->m_data[i] = (p.Y <= water_level) ? waternode : airnode; + else if (flooded && full_ymax < water_level) + vm->m_data[i] = (p.Y < startp.Y - 4) ? liquidnode : airnode; + else + vm->m_data[i] = airnode; + } else { + if (c == CONTENT_IGNORE) + continue; - if (flooded && full_ymin < water_level && full_ymax > water_level) - vm->m_data[i] = (p.Y <= water_level) ? waternode : airnode; - else if (flooded && full_ymax < water_level) - vm->m_data[i] = (p.Y < startp.Y - 4) ? liquidnode : airnode; - else vm->m_data[i] = airnode; + vm->m_flags[i] |= VMANIP_FLAG_CAVE; + } } } } } - diff --git a/src/cavegen.h b/src/cavegen.h index 27626753a..7371df6fa 100644 --- a/src/cavegen.h +++ b/src/cavegen.h @@ -22,55 +22,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #define VMANIP_FLAG_CAVE VOXELFLAG_CHECKED1 -class MapgenV5; class MapgenV6; class MapgenV7; -class CaveV5 { -public: - MapgenV5 *mg; - MMVManip *vm; - INodeDefManager *ndef; - - NoiseParams *np_caveliquids; - - s16 min_tunnel_diameter; - s16 max_tunnel_diameter; - u16 tunnel_routepoints; - int dswitchint; - int part_max_length_rs; - - bool large_cave_is_flat; - bool flooded; - - s16 max_stone_y; - v3s16 node_min; - v3s16 node_max; - - v3f orp; // starting point, relative to caved space - v3s16 of; // absolute coordinates of caved space - v3s16 ar; // allowed route area - s16 rs; // tunnel radius size - v3f main_direction; - - s16 route_y_min; - s16 route_y_max; - - PseudoRandom *ps; - - content_t c_water_source; - content_t c_lava_source; - content_t c_ice; - - int water_level; - - CaveV5() {} - CaveV5(MapgenV5 *mg, PseudoRandom *ps); - void makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height); - void makeTunnel(bool dirswitch); - void carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine); -}; - class CaveV6 { public: MapgenV6 *mg; @@ -129,6 +83,7 @@ public: int dswitchint; int part_max_length_rs; + bool large_cave; bool large_cave_is_flat; bool flooded; @@ -154,7 +109,7 @@ public: int water_level; CaveV7() {} - CaveV7(MapgenV7 *mg, PseudoRandom *ps); + CaveV7(MapgenV7 *mg, PseudoRandom *ps, bool large_cave); void makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height); void makeTunnel(bool dirswitch); void carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine); diff --git a/src/cguittfont/CGUITTFont.cpp b/src/cguittfont/CGUITTFont.cpp index 2342eb748..f6606996e 100644 --- a/src/cguittfont/CGUITTFont.cpp +++ b/src/cguittfont/CGUITTFont.cpp @@ -29,7 +29,6 @@ */ #include -#include #include "CGUITTFont.h" namespace irr @@ -65,24 +64,8 @@ scene::SMesh CGUITTFont::shared_plane_; // -/** Checks that no dimension of the FT_BitMap object is negative. If either is - * negative, abort execution. - */ -inline void checkFontBitmapSize(const FT_Bitmap &bits) -{ - if ((s32)bits.rows < 0 || (s32)bits.width < 0) { - std::cout << "Insane font glyph size. File: " - << __FILE__ << " Line " << __LINE__ - << std::endl; - abort(); - } -} - video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVideoDriver* driver) const { - // Make sure our casts to s32 in the loops below will not cause problems - checkFontBitmapSize(bits); - // Determine what our texture size should be. // Add 1 because textures are inclusive-exclusive. core::dimension2du d(bits.width + 1, bits.rows + 1); @@ -104,11 +87,10 @@ video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVide const u32 image_pitch = image->getPitch() / sizeof(u16); u16* image_data = (u16*)image->lock(); u8* glyph_data = bits.buffer; - - for (s32 y = 0; y < (s32)bits.rows; ++y) + for (int y = 0; y < bits.rows; ++y) { u16* row = image_data; - for (s32 x = 0; x < (s32)bits.width; ++x) + for (int x = 0; x < bits.width; ++x) { // Monochrome bitmaps store 8 pixels per byte. The left-most pixel is the bit 0x80. // So, we go through the data each bit at a time. @@ -134,10 +116,10 @@ video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVide const u32 image_pitch = image->getPitch() / sizeof(u32); u32* image_data = (u32*)image->lock(); u8* glyph_data = bits.buffer; - for (s32 y = 0; y < (s32)bits.rows; ++y) + for (int y = 0; y < bits.rows; ++y) { u8* row = glyph_data; - for (s32 x = 0; x < (s32)bits.width; ++x) + for (int x = 0; x < bits.width; ++x) { image_data[y * image_pitch + x] |= static_cast(255.0f * (static_cast(*row++) / gray_count)) << 24; //data[y * image_pitch + x] |= ((u32)(*bitsdata++) << 24); diff --git a/src/cguittfont/irrUString.h b/src/cguittfont/irrUString.h index eb7abe5a1..c175c792a 100644 --- a/src/cguittfont/irrUString.h +++ b/src/cguittfont/irrUString.h @@ -45,7 +45,7 @@ #define __BYTE_ORDER 0 #define __LITTLE_ENDIAN 0 #define __BIG_ENDIAN 1 -#elif defined(__MACH__) && defined(__APPLE__) +#elif __MACH__ #include #elif defined(__FreeBSD__) #include diff --git a/src/client.cpp b/src/client.cpp index 00b79e92e..2f70d624c 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -26,11 +26,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/pointedthing.h" #include "util/serialize.h" #include "util/string.h" +#include "strfnd.h" #include "client.h" -#include "network/clientopcodes.h" +#include "clientserver.h" #include "main.h" #include "filesys.h" #include "porting.h" +#include "mapsector.h" #include "mapblock_mesh.h" #include "mapblock.h" #include "settings.h" @@ -38,17 +40,22 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gettext.h" #include "log.h" #include "nodemetadata.h" +#include "nodedef.h" #include "itemdef.h" #include "shader.h" +#include "base64.h" #include "clientmap.h" #include "clientmedia.h" #include "sound.h" #include "IMeshCache.h" +#include "serialization.h" #include "config.h" #include "version.h" #include "drawscene.h" +#include "subgame.h" +#include "server.h" +#include "database.h" #include "database-sqlite3.h" -#include "serialization.h" extern gui::IGUIEnvironment* guienv; @@ -264,26 +271,28 @@ Client::Client( m_time_of_day_update_timer(0), m_recommended_send_interval(0.1), m_removed_sounds_check_timer(0), - m_state(LC_Created), - m_localdb(NULL) + m_state(LC_Created) { - // Add local player - m_env.addPlayer(new LocalPlayer(this, playername)); + /* + Add local player + */ + { + Player *player = new LocalPlayer(this, playername); - m_cache_save_interval = g_settings->getU16("server_map_save_interval"); + m_env.addPlayer(player); + } m_cache_smooth_lighting = g_settings->getBool("smooth_lighting"); - m_cache_enable_shaders = g_settings->getBool("enable_shaders"); } void Client::Stop() { //request all client managed threads to stop m_mesh_update_thread.Stop(); - // Save local server map - if (m_localdb) { - infostream << "Local map saving ended." << std::endl; - m_localdb->endSave(); + if (localdb != NULL) { + actionstream << "Local map saving ended" << std::endl; + localdb->endSave(); + delete localserver; } } @@ -376,18 +385,112 @@ void Client::step(float dtime) } } +#if 0 + { + /* + Delete unused sectors + + NOTE: This jams the game for a while because deleting sectors + clear caches + */ + + float &counter = m_delete_unused_sectors_timer; + counter -= dtime; + if(counter <= 0.0) + { + // 3 minute interval + //counter = 180.0; + counter = 60.0; + + //JMutexAutoLock lock(m_env_mutex); //bulk comment-out + + core::list deleted_blocks; + + float delete_unused_sectors_timeout = + g_settings->getFloat("client_delete_unused_sectors_timeout"); + + // Delete sector blocks + /*u32 num = m_env.getMap().unloadUnusedData + (delete_unused_sectors_timeout, + true, &deleted_blocks);*/ + + // Delete whole sectors + m_env.getMap().unloadUnusedData + (delete_unused_sectors_timeout, + &deleted_blocks); + + if(deleted_blocks.size() > 0) + { + /*infostream<<"Client: Deleted blocks of "<::Iterator i = deleted_blocks.begin(); + core::list sendlist; + for(;;) + { + if(sendlist.size() == 255 || i == deleted_blocks.end()) + { + if(sendlist.size() == 0) + break; + /* + [0] u16 command + [2] u8 count + [3] v3s16 pos_0 + [3+6] v3s16 pos_1 + ... + */ + u32 replysize = 2+1+6*sendlist.size(); + SharedBuffer reply(replysize); + writeU16(&reply[0], TOSERVER_DELETEDBLOCKS); + reply[2] = sendlist.size(); + u32 k = 0; + for(core::list::Iterator + j = sendlist.begin(); + j != sendlist.end(); j++) + { + writeV3S16(&reply[2+1+6*k], *j); + k++; + } + m_con.Send(PEER_ID_SERVER, 1, reply, true); + + if(i == deleted_blocks.end()) + break; + + sendlist.clear(); + } + + sendlist.push_back(*i); + i++; + } + } + } + } +#endif // UGLY hack to fix 2 second startup delay caused by non existent // server client startup synchronization in local server or singleplayer mode static bool initial_step = true; if (initial_step) { initial_step = false; } - else if(m_state == LC_Created) { + else if(m_state == LC_Created) + { float &counter = m_connection_reinit_timer; counter -= dtime; - if(counter <= 0.0) { + if(counter <= 0.0) + { counter = 2.0; + //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out + Player *myplayer = m_env.getLocalPlayer(); assert(myplayer != NULL); // Send TOSERVER_INIT @@ -397,22 +500,24 @@ void Client::step(float dtime) // [23] u8[28] password (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) + SharedBuffer data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2); + writeU16(&data[0], TOSERVER_INIT); + writeU8(&data[2], SER_FMT_VER_HIGHEST_READ); - char pName[PLAYERNAME_SIZE]; - char pPassword[PASSWORD_SIZE]; + memset((char*)&data[3], 0, PLAYERNAME_SIZE); + snprintf((char*)&data[3], PLAYERNAME_SIZE, "%s", myplayer->getName()); - snprintf(pName, PLAYERNAME_SIZE, "%s", myplayer->getName()); - snprintf(pPassword, PASSWORD_SIZE, "%s", m_password.c_str()); + /*infostream<<"Client: sending initial password hash: \""<putRawString(pName,PLAYERNAME_SIZE); - pkt->putRawString(pPassword, PASSWORD_SIZE); - *pkt << (u16) CLIENT_PROTOCOL_VERSION_MIN << (u16) CLIENT_PROTOCOL_VERSION_MAX; + writeU16(&data[51], CLIENT_PROTOCOL_VERSION_MIN); + writeU16(&data[53], CLIENT_PROTOCOL_VERSION_MAX); - Send(pkt); + // Send as unreliable + Send(1, data, false); } // Not connected, return @@ -427,22 +532,29 @@ void Client::step(float dtime) Run Map's timers and unload unused data */ const float map_timer_and_unload_dtime = 5.25; - if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime)) { + if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime)) + { ScopeProfiler sp(g_profiler, "Client: map timer and unload"); - std::vector deleted_blocks; + std::list deleted_blocks; m_env.getMap().timerUpdate(map_timer_and_unload_dtime, g_settings->getFloat("client_unload_unused_data_timeout"), &deleted_blocks); + /*if(deleted_blocks.size() > 0) + infostream<<"Client: Unloaded "<::iterator i = deleted_blocks.begin(); - std::vector sendlist; - for(;;) { - if(sendlist.size() == 255 || i == deleted_blocks.end()) { + std::list::iterator i = deleted_blocks.begin(); + std::list sendlist; + for(;;) + { + if(sendlist.size() == 255 || i == deleted_blocks.end()) + { if(sendlist.empty()) break; /* @@ -452,19 +564,19 @@ void Client::step(float dtime) [3+6] v3s16 pos_1 ... */ - NetworkPacket* pkt = new NetworkPacket(TOSERVER_DELETEDBLOCKS, 1 + sizeof(v3s16) * sendlist.size()); - - *pkt << (u8) sendlist.size(); - + u32 replysize = 2+1+6*sendlist.size(); + SharedBuffer reply(replysize); + writeU16(&reply[0], TOSERVER_DELETEDBLOCKS); + reply[2] = sendlist.size(); u32 k = 0; - for(std::vector::iterator + for(std::list::iterator j = sendlist.begin(); - j != sendlist.end(); ++j) { - *pkt << *j; + j != sendlist.end(); ++j) + { + writeV3S16(&reply[2+1+6*k], *j); k++; } - - Send(pkt); + m_con.Send(PEER_ID_SERVER, 2, reply, true); if(i == deleted_blocks.end()) break; @@ -480,52 +592,62 @@ void Client::step(float dtime) /* Handle environment */ - // Control local player (0ms) - LocalPlayer *player = m_env.getLocalPlayer(); - assert(player != NULL); - player->applyControl(dtime); + { + // Control local player (0ms) + LocalPlayer *player = m_env.getLocalPlayer(); + assert(player != NULL); + player->applyControl(dtime); - // Step environment - m_env.step(dtime); + // Step environment + m_env.step(dtime); - /* - Get events - */ - for(;;) { - ClientEnvEvent event = m_env.getClientEvent(); - if(event.type == CEE_NONE) { - break; - } - else if(event.type == CEE_PLAYER_DAMAGE) { - if(m_ignore_damage_timer <= 0) { - u8 damage = event.player_damage.amount; - - if(event.player_damage.send_to_server) - sendDamage(damage); - - // Add to ClientEvent queue - ClientEvent event; - event.type = CE_PLAYER_DAMAGE; - event.player_damage.amount = damage; - m_client_event_queue.push(event); + /* + Get events + */ + for(;;) + { + ClientEnvEvent event = m_env.getClientEvent(); + if(event.type == CEE_NONE) + { + break; + } + else if(event.type == CEE_PLAYER_DAMAGE) + { + if(m_ignore_damage_timer <= 0) + { + u8 damage = event.player_damage.amount; + + if(event.player_damage.send_to_server) + sendDamage(damage); + + // Add to ClientEvent queue + ClientEvent event; + event.type = CE_PLAYER_DAMAGE; + event.player_damage.amount = damage; + m_client_event_queue.push_back(event); + } + } + else if(event.type == CEE_PLAYER_BREATH) + { + u16 breath = event.player_breath.amount; + sendBreath(breath); } - } - else if(event.type == CEE_PLAYER_BREATH) { - u16 breath = event.player_breath.amount; - sendBreath(breath); } } /* Print some info */ - float &counter = m_avg_rtt_timer; - counter += dtime; - if(counter >= 10) { - counter = 0.0; - // connectedAndInitialized() is true, peer exists. - float avg_rtt = getRTT(); - infostream << "Client: avg_rtt=" << avg_rtt << std::endl; + { + float &counter = m_avg_rtt_timer; + counter += dtime; + if(counter >= 10) + { + counter = 0.0; + // connectedAndInitialized() is true, peer exists. + float avg_rtt = getRTT(); + infostream<<"Client: avg_rtt="<mesh != NULL) { @@ -565,19 +688,27 @@ void Client::step(float dtime) } else { delete r.mesh; } - - if(r.ack_block_to_server) { + if(r.ack_block_to_server) + { /* Acknowledge block - [0] u8 count - [1] v3s16 pos_0 */ - NetworkPacket* pkt = new NetworkPacket(TOSERVER_GOTBLOCKS, 1 + 6); - *pkt << (u8) 1 << r.p; - Send(pkt); + /* + [0] u16 command + [2] u8 count + [3] v3s16 pos_0 + [3+6] v3s16 pos_1 + ... + */ + u32 replysize = 2+1+6; + SharedBuffer reply(replysize); + writeU16(&reply[0], TOSERVER_GOTBLOCKS); + reply[2] = 1; + writeV3S16(&reply[3], r.p); + // Send as reliable + m_con.Send(PEER_ID_SERVER, 2, reply, true); } } - if(num_processed_meshes > 0) g_profiler->graphAdd("num_processed_meshes", num_processed_meshes); } @@ -640,47 +771,42 @@ void Client::step(float dtime) Handle removed remotely initiated sounds */ m_removed_sounds_check_timer += dtime; - if(m_removed_sounds_check_timer >= 2.32) { + if(m_removed_sounds_check_timer >= 2.32) + { m_removed_sounds_check_timer = 0; // Find removed sounds and clear references to them std::set removed_server_ids; for(std::map::iterator i = m_sounds_server_to_client.begin(); - i != m_sounds_server_to_client.end();) { + i != m_sounds_server_to_client.end();) + { s32 server_id = i->first; int client_id = i->second; i++; - if(!m_sound->soundExists(client_id)) { + if(!m_sound->soundExists(client_id)){ m_sounds_server_to_client.erase(server_id); m_sounds_client_to_server.erase(client_id); m_sounds_to_objects.erase(client_id); removed_server_ids.insert(server_id); } } - // Sync to server - if(!removed_server_ids.empty()) { + if(!removed_server_ids.empty()) + { + std::ostringstream os(std::ios_base::binary); + writeU16(os, TOSERVER_REMOVED_SOUNDS); size_t server_ids = removed_server_ids.size(); assert(server_ids <= 0xFFFF); - - NetworkPacket* pkt = new NetworkPacket(TOSERVER_REMOVED_SOUNDS, 2 + server_ids * 4); - - *pkt << (u16) (server_ids & 0xFFFF); - + writeU16(os, (u16) (server_ids & 0xFFFF)); for(std::set::iterator i = removed_server_ids.begin(); i != removed_server_ids.end(); i++) - *pkt << *i; - - Send(pkt); + writeS32(os, *i); + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(1, data, true); } } - - // Write server map - if (m_localdb && m_localdb_save_interval.step(dtime, - m_cache_save_interval)) { - m_localdb->endSave(); - m_localdb->beginSave(); - } } bool Client::loadMedia(const std::string &data, const std::string &filename) @@ -780,33 +906,37 @@ void Client::deletingPeer(con::Peer *peer, bool timeout) string name } */ -void Client::request_media(const std::vector &file_requests) +void Client::request_media(const std::list &file_requests) { std::ostringstream os(std::ios_base::binary); writeU16(os, TOSERVER_REQUEST_MEDIA); size_t file_requests_size = file_requests.size(); assert(file_requests_size <= 0xFFFF); + writeU16(os, (u16) (file_requests_size & 0xFFFF)); - // Packet dynamicly resized - NetworkPacket* pkt = new NetworkPacket(TOSERVER_REQUEST_MEDIA, 2 + 0); - - *pkt << (u16) (file_requests_size & 0xFFFF); - - for(std::vector::const_iterator i = file_requests.begin(); + for(std::list::const_iterator i = file_requests.begin(); i != file_requests.end(); ++i) { - *pkt << (*i); + os< data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(1, data, true); infostream<<"Client: Sending media request list to server (" - < data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(1, data, true); infostream<<"Client: Notifying server that we received all media" <getBool("enable_local_map_saving") || is_local_server) { + localdb = NULL; + + if (!g_settings->getBool("enable_local_map_saving") || is_local_server) return; - } const std::string world_path = porting::path_user + DIR_DELIM + "worlds" + DIR_DELIM + "server_" + hostname + "_" + to_string(address.getPort()); - fs::CreateAllDirs(world_path); + SubgameSpec gamespec; - m_localdb = new Database_SQLite3(world_path); - m_localdb->beginSave(); + if (!getWorldExists(world_path)) { + gamespec = findSubgame(g_settings->get("default_game")); + if (!gamespec.isValid()) + gamespec = findSubgame("minimal"); + } else { + gamespec = findWorldSubgame(world_path); + } + + if (!gamespec.isValid()) { + errorstream << "Couldn't find subgame for local map saving." << std::endl; + return; + } + + localserver = new Server(world_path, gamespec, false, false); + localdb = new Database_SQLite3(&(ServerMap&)localserver->getMap(), world_path); + localdb->beginSave(); actionstream << "Local map saving started, map will be saved at '" << world_path << "'" << std::endl; } @@ -842,14 +987,16 @@ void Client::ReceiveAll() if(porting::getTimeMs() > start_ms + 100) break; - try { + try{ Receive(); g_profiler->graphAdd("client_received_packets", 1); } - catch(con::NoIncomingDataException &e) { + catch(con::NoIncomingDataException &e) + { break; } - catch(con::InvalidIncomingDataException &e) { + catch(con::InvalidIncomingDataException &e) + { infostream<<"Client::ReceiveAll(): " "InvalidIncomingDataException: what()=" <getCommand()]; - (this->*opHandle.handler)(pkt); -} - /* sender_peer_id given to this shall be quaranteed to be a valid peer */ @@ -880,14 +1021,13 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) DSTACK(__FUNCTION_NAME); // Ignore packets that don't even fit a command - if(datasize < 2) { + if(datasize < 2) + { m_packetcounter.add(60000); return; } - NetworkPacket* pkt = new NetworkPacket(data, datasize, sender_peer_id); - - ToClientCommand command = (ToClientCommand) pkt->getCommand(); + ToClientCommand command = (ToClientCommand)readU16(&data[0]); //infostream<<"Client: received command="<= 2+1+6) + playerpos_s16 = readV3S16(&data[2+1]); + v3f playerpos_f = intToFloat(playerpos_s16, BS) - v3f(0, BS/2, 0); + + + // Set player position + Player *player = m_env.getLocalPlayer(); + assert(player != NULL); + player->setPosition(playerpos_f); + + if(datasize >= 2+1+6+8) + { + // Get map seed + 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 " + < reply(replysize); + writeU16(&reply[0], TOSERVER_INIT2); + // Send as reliable + m_con.Send(PEER_ID_SERVER, 1, reply, true); + + m_state = LC_Init; - /* - * Those packets are handled before m_server_ser_ver is set, it's normal - * But we must use the new ToClientConnectionState in the future, - * as a byte mask - */ - if(toClientCommandTable[command].state == TOCLIENT_STATE_NOT_CONNECTED) { - handleCommand(pkt); - delete pkt; return; } - if(m_server_ser_ver == SER_FMT_VER_INVALID) { - infostream << "Client: Server serialization" + if(command == TOCLIENT_ACCESS_DENIED) + { + // The server didn't like our password. Note, this needs + // to be processed even if the serialisation format has + // not been agreed yet, the same as TOCLIENT_INIT. + m_access_denied = true; + m_access_denied_reason = L"Unknown"; + if(datasize >= 4) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + m_access_denied_reason = deSerializeWideString(is); + } + return; + } + + if(ser_version == SER_FMT_VER_INVALID) + { + infostream<<"Client: Server serialization" " format invalid or not initialized." - " Skipping incoming command=" << command << std::endl; - delete pkt; + " Skipping incoming command="<= index+1) && data[index]){ + remove_metadata = false; + } + + addNode(p, n, remove_metadata); + } + else if(command == TOCLIENT_BLOCKDATA) + { + // Ignore too small packet + if(datasize < 8) + return; + + v3s16 p; + p.X = readS16(&data[2]); + p.Y = readS16(&data[4]); + p.Z = readS16(&data[6]); + + std::string datastring((char*)&data[8], datasize-8); + std::istringstream istr(datastring, std::ios_base::binary); + + MapSector *sector; + MapBlock *block; + + v2s16 p2d(p.X, p.Z); + sector = m_env.getMap().emergeSector(p2d); + + assert(sector->getPos() == p2d); + + block = sector->getBlockNoCreateNoEx(p.Y); + if(block) + { + /* + Update an existing block + */ + block->deSerialize(istr, ser_version, false); + block->deSerializeNetworkSpecific(istr); + } + else + { + /* + Create a new block + */ + block = new MapBlock(&m_env.getMap(), p, this); + block->deSerialize(istr, ser_version, false); + block->deSerializeNetworkSpecific(istr); + sector->insertBlock(block); + } + + if (localdb != NULL) { + ((ServerMap&) localserver->getMap()).saveBlock(block, localdb); + } + + /* + Add it to mesh update queue and set it to be acknowledged after update. + */ + addUpdateMeshTaskWithEdge(p, true); + } + else if(command == TOCLIENT_INVENTORY) + { + if(datasize < 3) + return; + + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + player->inventory.deSerialize(is); + + m_inventory_updated = true; + + delete m_inventory_from_server; + m_inventory_from_server = new Inventory(player->inventory); + m_inventory_from_server_age = 0.0; + + } + else if(command == TOCLIENT_TIME_OF_DAY) + { + if(datasize < 4) + return; + + u16 time_of_day = readU16(&data[2]); + time_of_day = time_of_day % 24000; + float time_speed = 0; + + if(datasize >= 2 + 2 + 4) + { + time_speed = readF1000(&data[4]); + } + else { + // Old message; try to approximate speed of time by ourselves + float time_of_day_f = (float)time_of_day / 24000.0; + float tod_diff_f = 0; + + if(time_of_day_f < 0.2 && m_last_time_of_day_f > 0.8) + tod_diff_f = time_of_day_f - m_last_time_of_day_f + 1.0; + else + tod_diff_f = time_of_day_f - m_last_time_of_day_f; + + m_last_time_of_day_f = time_of_day_f; + float time_diff = m_time_of_day_update_timer; + m_time_of_day_update_timer = 0; + + if(m_time_of_day_set){ + time_speed = (3600.0*24.0) * tod_diff_f / time_diff; + infostream<<"Client: Measured time_of_day speed (old format): " + <isStarted()) { + const char *problem = m_media_downloader ? + "we already saw another announcement" : + "all media has been received already"; + errorstream<<"Client: Received media announcement but " + <addRemoteServer(baseurl); + } + } + catch(SerializationError& e) { + // not supported by server or turned off + } + + m_media_downloader->step(this); + } + else if(command == TOCLIENT_MEDIA) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + /* + u16 command + u16 total number of file bunches + u16 index of this bunch + u32 number of files in this bunch + for each file { + u16 length of name + string name + u32 length of data + data + } + */ + int num_bunches = readU16(is); + int bunch_i = readU16(is); + u32 num_files = readU32(is); + infostream<<"Client: Received files: bunch "<deSerialize(tmp_is2); + m_nodedef_received = true; + } + else if(command == TOCLIENT_CRAFTITEMDEF) + { + infostream<<"Client: WARNING: Ignoring TOCLIENT_CRAFTITEMDEF"<deSerialize(tmp_is2); + m_itemdef_received = true; + } + else if(command == TOCLIENT_PLAY_SOUND) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + s32 server_id = readS32(is); + std::string name = deSerializeString(is); + float gain = readF1000(is); + int type = readU8(is); // 0=local, 1=positional, 2=object + v3f pos = readV3F1000(is); + u16 object_id = readU16(is); + bool loop = readU8(is); + // Start playing + int client_id = -1; + switch(type){ + case 0: // local + client_id = m_sound->playSound(name, loop, gain); + break; + case 1: // positional + client_id = m_sound->playSoundAt(name, loop, gain, pos); + break; + case 2: { // object + ClientActiveObject *cao = m_env.getActiveObject(object_id); + if(cao) + pos = cao->getPosition(); + client_id = m_sound->playSoundAt(name, loop, gain, pos); + // TODO: Set up sound to move with object + break; } + default: + break; + } + if(client_id != -1){ + m_sounds_server_to_client[server_id] = client_id; + m_sounds_client_to_server[client_id] = server_id; + if(object_id != 0) + m_sounds_to_objects[client_id] = object_id; + } + } + else if(command == TOCLIENT_STOP_SOUND) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + s32 server_id = readS32(is); + std::map::iterator i = + m_sounds_server_to_client.find(server_id); + if(i != m_sounds_server_to_client.end()){ + int client_id = i->second; + m_sound->stopSound(client_id); + } + } + else if(command == TOCLIENT_PRIVILEGES) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + m_privileges.clear(); + infostream<<"Client: Privileges updated: "; + u16 num_privileges = readU16(is); + for(unsigned int i=0; iinventory_formspec = deSerializeLongString(is); + } + else if(command == TOCLIENT_DETACHED_INVENTORY) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + std::string name = deSerializeString(is); + + infostream<<"Client: Detached inventory update: \""< 0) + inv = m_detached_inventories[name]; + else{ + inv = new Inventory(m_itemdef); + m_detached_inventories[name] = inv; + } + inv->deSerialize(is); + } + else if(command == TOCLIENT_SHOW_FORMSPEC) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + std::string formspec = deSerializeLongString(is); + std::string formname = deSerializeString(is); + + ClientEvent event; + event.type = CE_SHOW_FORMSPEC; + // pointer is required as event is a struct only! + // adding a std:string to a struct isn't possible + event.show_formspec.formspec = new std::string(formspec); + event.show_formspec.formname = new std::string(formname); + m_client_event_queue.push_back(event); + } + else if(command == TOCLIENT_SPAWN_PARTICLE) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + v3f pos = readV3F1000(is); + v3f vel = readV3F1000(is); + v3f acc = readV3F1000(is); + float expirationtime = readF1000(is); + float size = readF1000(is); + bool collisiondetection = readU8(is); + std::string texture = deSerializeLongString(is); + bool vertical = false; + try { + vertical = readU8(is); + } catch (...) {} + + ClientEvent event; + event.type = CE_SPAWN_PARTICLE; + event.spawn_particle.pos = new v3f (pos); + event.spawn_particle.vel = new v3f (vel); + event.spawn_particle.acc = new v3f (acc); + event.spawn_particle.expirationtime = expirationtime; + event.spawn_particle.size = size; + event.spawn_particle.collisiondetection = collisiondetection; + event.spawn_particle.vertical = vertical; + event.spawn_particle.texture = new std::string(texture); + + m_client_event_queue.push_back(event); + } + else if(command == TOCLIENT_ADD_PARTICLESPAWNER) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + u16 amount = readU16(is); + float spawntime = readF1000(is); + v3f minpos = readV3F1000(is); + v3f maxpos = readV3F1000(is); + v3f minvel = readV3F1000(is); + v3f maxvel = readV3F1000(is); + v3f minacc = readV3F1000(is); + v3f maxacc = readV3F1000(is); + float minexptime = readF1000(is); + float maxexptime = readF1000(is); + float minsize = readF1000(is); + float maxsize = readF1000(is); + bool collisiondetection = readU8(is); + std::string texture = deSerializeLongString(is); + u32 id = readU32(is); + bool vertical = false; + try { + vertical = readU8(is); + } catch (...) {} + + ClientEvent event; + event.type = CE_ADD_PARTICLESPAWNER; + event.add_particlespawner.amount = amount; + event.add_particlespawner.spawntime = spawntime; + event.add_particlespawner.minpos = new v3f (minpos); + event.add_particlespawner.maxpos = new v3f (maxpos); + event.add_particlespawner.minvel = new v3f (minvel); + event.add_particlespawner.maxvel = new v3f (maxvel); + event.add_particlespawner.minacc = new v3f (minacc); + event.add_particlespawner.maxacc = new v3f (maxacc); + event.add_particlespawner.minexptime = minexptime; + event.add_particlespawner.maxexptime = maxexptime; + event.add_particlespawner.minsize = minsize; + event.add_particlespawner.maxsize = maxsize; + event.add_particlespawner.collisiondetection = collisiondetection; + event.add_particlespawner.vertical = vertical; + event.add_particlespawner.texture = new std::string(texture); + event.add_particlespawner.id = id; + + m_client_event_queue.push_back(event); + } + else if(command == TOCLIENT_DELETE_PARTICLESPAWNER) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + u32 id = readU16(is); + + ClientEvent event; + event.type = CE_DELETE_PARTICLESPAWNER; + event.delete_particlespawner.id = id; + + m_client_event_queue.push_back(event); + } + else if(command == TOCLIENT_HUDADD) + { + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + u32 id = readU32(is); + u8 type = readU8(is); + v2f pos = readV2F1000(is); + std::string name = deSerializeString(is); + v2f scale = readV2F1000(is); + std::string text = deSerializeString(is); + u32 number = readU32(is); + u32 item = readU32(is); + u32 dir = readU32(is); + v2f align = readV2F1000(is); + v2f offset = readV2F1000(is); + v3f world_pos; + v2s32 size; + try{ + world_pos = readV3F1000(is); + }catch(SerializationError &e) {}; + try{ + size = readV2S32(is); + } catch(SerializationError &e) {}; + + ClientEvent event; + event.type = CE_HUDADD; + event.hudadd.id = id; + event.hudadd.type = type; + event.hudadd.pos = new v2f(pos); + event.hudadd.name = new std::string(name); + event.hudadd.scale = new v2f(scale); + event.hudadd.text = new std::string(text); + event.hudadd.number = number; + event.hudadd.item = item; + event.hudadd.dir = dir; + event.hudadd.align = new v2f(align); + event.hudadd.offset = new v2f(offset); + event.hudadd.world_pos = new v3f(world_pos); + event.hudadd.size = new v2s32(size); + m_client_event_queue.push_back(event); + } + else if(command == TOCLIENT_HUDRM) + { + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + u32 id = readU32(is); + + ClientEvent event; + event.type = CE_HUDRM; + event.hudrm.id = id; + m_client_event_queue.push_back(event); + } + else if(command == TOCLIENT_HUDCHANGE) + { + std::string sdata; + v2f v2fdata; + v3f v3fdata; + u32 intdata = 0; + v2s32 v2s32data; + + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + u32 id = readU32(is); + u8 stat = (HudElementStat)readU8(is); + + if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE || + stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET) + v2fdata = readV2F1000(is); + else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT) + sdata = deSerializeString(is); + else if (stat == HUD_STAT_WORLD_POS) + v3fdata = readV3F1000(is); + else if (stat == HUD_STAT_SIZE ) + v2s32data = readV2S32(is); + else + intdata = readU32(is); + + ClientEvent event; + event.type = CE_HUDCHANGE; + event.hudchange.id = id; + event.hudchange.stat = (HudElementStat)stat; + event.hudchange.v2fdata = new v2f(v2fdata); + event.hudchange.v3fdata = new v3f(v3fdata); + event.hudchange.sdata = new std::string(sdata); + event.hudchange.data = intdata; + event.hudchange.v2s32data = new v2s32(v2s32data); + m_client_event_queue.push_back(event); + } + else if(command == TOCLIENT_HUD_SET_FLAGS) + { + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + u32 flags = readU32(is); + u32 mask = readU32(is); + + player->hud_flags &= ~mask; + player->hud_flags |= flags; + } + else if(command == TOCLIENT_HUD_SET_PARAM) + { + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + u16 param = readU16(is); + std::string value = deSerializeString(is); + + if(param == HUD_PARAM_HOTBAR_ITEMCOUNT && value.size() == 4) { + s32 hotbar_itemcount = readS32((u8*) value.c_str()); + if(hotbar_itemcount > 0 && hotbar_itemcount <= HUD_HOTBAR_ITEMCOUNT_MAX) + player->hud_hotbar_itemcount = hotbar_itemcount; + } + else if (param == HUD_PARAM_HOTBAR_IMAGE) { + ((LocalPlayer *) player)->hotbar_image = value; + } + else if (param == HUD_PARAM_HOTBAR_SELECTED_IMAGE) { + ((LocalPlayer *) player)->hotbar_selected_image = value; + } + } + else if(command == TOCLIENT_SET_SKY) + { + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + video::SColor *bgcolor = new video::SColor(readARGB8(is)); + std::string *type = new std::string(deSerializeString(is)); + u16 count = readU16(is); + std::vector *params = new std::vector; + + for(size_t i=0; ipush_back(deSerializeString(is)); + + ClientEvent event; + event.type = CE_SET_SKY; + event.set_sky.bgcolor = bgcolor; + event.set_sky.type = type; + event.set_sky.params = params; + m_client_event_queue.push_back(event); + } + else if(command == TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO) + { + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + bool do_override = readU8(is); + float day_night_ratio_f = (float)readU16(is) / 65536; + + ClientEvent event; + event.type = CE_OVERRIDE_DAY_NIGHT_RATIO; + event.override_day_night_ratio.do_override = do_override; + event.override_day_night_ratio.ratio_f = day_night_ratio_f; + m_client_event_queue.push_back(event); + } + else if(command == TOCLIENT_LOCAL_PLAYER_ANIMATIONS) + { + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + LocalPlayer *player = m_env.getLocalPlayer(); + assert(player != NULL); + + player->local_animations[0] = readV2S32(is); + player->local_animations[1] = readV2S32(is); + player->local_animations[2] = readV2S32(is); + player->local_animations[3] = readV2S32(is); + player->local_animation_speed = readF1000(is); + } + else if(command == TOCLIENT_EYE_OFFSET) + { + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + LocalPlayer *player = m_env.getLocalPlayer(); + assert(player != NULL); + + player->eye_offset_first = readV3F1000(is); + player->eye_offset_third = readV3F1000(is); + } + else + { + infostream<<"Client: Ignoring unknown command " + < data, bool reliable) { - m_con.Send(PEER_ID_SERVER, - serverCommandFactoryTable[pkt->getCommand()].channel, - pkt, - serverCommandFactoryTable[pkt->getCommand()].reliable); - delete pkt; + //JMutexAutoLock lock(m_con_mutex); //bulk comment-out + m_con.Send(PEER_ID_SERVER, channelnum, data, reliable); } void Client::interact(u8 action, const PointedThing& pointed) { - if(m_state != LC_Ready) { - errorstream << "Client::interact() " + if(m_state != LC_Ready){ + infostream<<"Client::interact() " "cancelled (not connected)" - << std::endl; + <putLongString(tmp_os.str()); + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); - Send(pkt); + // Send as reliable + Send(0, data, true); } void Client::sendNodemetaFields(v3s16 p, const std::string &formname, const std::map &fields) { + std::ostringstream os(std::ios_base::binary); + + writeU16(os, TOSERVER_NODEMETA_FIELDS); + writeV3S16(os, p); + os<::const_iterator - i = fields.begin(); i != fields.end(); i++) { + i = fields.begin(); i != fields.end(); i++){ const std::string &name = i->first; const std::string &value = i->second; - *pkt << name; - pkt->putLongString(value); + os< data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(0, data, true); } void Client::sendInventoryFields(const std::string &formname, const std::map &fields) { + std::ostringstream os(std::ios_base::binary); + + writeU16(os, TOSERVER_INVENTORY_FIELDS); + os<::const_iterator - i = fields.begin(); i != fields.end(); i++) { + i = fields.begin(); i != fields.end(); i++){ const std::string &name = i->first; const std::string &value = i->second; - *pkt << name; - pkt->putLongString(value); + os< data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(0, data, true); } void Client::sendInventoryAction(InventoryAction *a) { std::ostringstream os(std::ios_base::binary); + u8 buf[12]; + + // Write command + writeU16(buf, TOSERVER_INVENTORY_ACTION); + os.write((char*)buf, 2); a->serialize(os); // Make data buffer std::string s = os.str(); - - NetworkPacket* pkt = new NetworkPacket(TOSERVER_INVENTORY_ACTION, s.size()); - pkt->putRawString(s.c_str(),s.size()); - - Send(pkt); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(0, data, true); } void Client::sendChatMessage(const std::wstring &message) { - NetworkPacket* pkt = new NetworkPacket(TOSERVER_CHAT_MESSAGE, 2 + message.size() * sizeof(u16)); + std::ostringstream os(std::ios_base::binary); + u8 buf[12]; - *pkt << message; + // Write command + writeU16(buf, TOSERVER_CHAT_MESSAGE); + os.write((char*)buf, 2); - Send(pkt); + // Write length + size_t messagesize = message.size(); + if (messagesize > 0xFFFF) { + messagesize = 0xFFFF; + } + writeU16(buf, (u16) messagesize); + os.write((char*)buf, 2); + + // Write string + for(unsigned int i=0; i data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(0, data, true); } void Client::sendChangePassword(const std::wstring &oldpassword, - const std::wstring &newpassword) + const std::wstring &newpassword) { Player *player = m_env.getLocalPlayer(); if(player == NULL) @@ -1058,58 +2173,94 @@ void Client::sendChangePassword(const std::wstring &oldpassword, std::string oldpwd = translatePassword(playername, oldpassword); std::string newpwd = translatePassword(playername, newpassword); - NetworkPacket* pkt = new NetworkPacket(TOSERVER_PASSWORD, 2 * PASSWORD_SIZE); + std::ostringstream os(std::ios_base::binary); + u8 buf[2+PASSWORD_SIZE*2]; + /* + [0] u16 TOSERVER_PASSWORD + [2] u8[28] old password + [30] u8[28] new password + */ - for(u8 i = 0; i < PASSWORD_SIZE; i++) { - *pkt << (u8) (i < oldpwd.length() ? oldpwd[i] : 0); + writeU16(buf, TOSERVER_PASSWORD); + for(unsigned int i=0;i data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(0, data, true); } void Client::sendDamage(u8 damage) { DSTACK(__FUNCTION_NAME); + std::ostringstream os(std::ios_base::binary); - NetworkPacket* pkt = new NetworkPacket(TOSERVER_DAMAGE, sizeof(u8)); - *pkt << damage; - Send(pkt); + writeU16(os, TOSERVER_DAMAGE); + writeU8(os, damage); + + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(0, data, true); } void Client::sendBreath(u16 breath) { DSTACK(__FUNCTION_NAME); + std::ostringstream os(std::ios_base::binary); - NetworkPacket* pkt = new NetworkPacket(TOSERVER_BREATH, sizeof(u16)); - *pkt << breath; - Send(pkt); + writeU16(os, TOSERVER_BREATH); + writeU16(os, breath); + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(0, data, true); } void Client::sendRespawn() { DSTACK(__FUNCTION_NAME); + std::ostringstream os(std::ios_base::binary); - NetworkPacket* pkt = new NetworkPacket(TOSERVER_RESPAWN, 0); - Send(pkt); + writeU16(os, TOSERVER_RESPAWN); + + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(0, data, true); } void Client::sendReady() { DSTACK(__FUNCTION_NAME); + std::ostringstream os(std::ios_base::binary); - NetworkPacket* pkt = new NetworkPacket(TOSERVER_CLIENT_READY, - 1 + 1 + 1 + 1 + 2 + sizeof(char) * strlen(minetest_version_hash)); + writeU16(os, TOSERVER_CLIENT_READY); + writeU8(os,VERSION_MAJOR); + writeU8(os,VERSION_MINOR); + writeU8(os,VERSION_PATCH_ORIG); + writeU8(os,0); - *pkt << (u8) VERSION_MAJOR << (u8) VERSION_MINOR << (u8) VERSION_PATCH_ORIG - << (u8) 0 << (u16) strlen(minetest_version_hash); + writeU16(os,strlen(minetest_version_hash)); + os.write(minetest_version_hash,strlen(minetest_version_hash)); - pkt->putRawString(minetest_version_hash, (u16) strlen(minetest_version_hash)); - Send(pkt); + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(0, data, true); } void Client::sendPlayerPos() @@ -1154,18 +2305,22 @@ void Client::sendPlayerPos() v3s32 speed(sf.X*100, sf.Y*100, sf.Z*100); /* Format: - [0] v3s32 position*100 - [12] v3s32 speed*100 - [12+12] s32 pitch*100 - [12+12+4] s32 yaw*100 - [12+12+4+4] u32 keyPressed + [0] u16 command + [2] v3s32 position*100 + [2+12] v3s32 speed*100 + [2+12+12] s32 pitch*100 + [2+12+12+4] s32 yaw*100 + [2+12+12+4+4] u32 keyPressed */ - - NetworkPacket* pkt = new NetworkPacket(TOSERVER_PLAYERPOS, 12 + 12 + 4 + 4 + 4); - - *pkt << position << speed << pitch << yaw << keyPressed; - - Send(pkt); + SharedBuffer data(2+12+12+4+4+4); + writeU16(&data[0], TOSERVER_PLAYERPOS); + writeV3S32(&data[2], position); + writeV3S32(&data[2+12], speed); + writeS32(&data[2+12+12], pitch); + writeS32(&data[2+12+12+4], yaw); + writeU32(&data[2+12+12+4+4], keyPressed); + // Send as unreliable + Send(0, data, false); } void Client::sendPlayerItem(u16 item) @@ -1179,30 +2334,33 @@ void Client::sendPlayerItem(u16 item) // Set peer id if not set already if(myplayer->peer_id == PEER_ID_INEXISTENT) myplayer->peer_id = our_peer_id; - // Check that an existing peer_id is the same as the connection's assert(myplayer->peer_id == our_peer_id); - NetworkPacket* pkt = new NetworkPacket(TOSERVER_PLAYERITEM, 2); + SharedBuffer data(2+2); + writeU16(&data[0], TOSERVER_PLAYERITEM); + writeU16(&data[2], item); - *pkt << item; - - Send(pkt); + // Send as reliable + Send(0, data, true); } void Client::removeNode(v3s16 p) { std::map modified_blocks; - try { + try + { m_env.getMap().removeNodeAndUpdate(p, modified_blocks); } - catch(InvalidPositionException &e) { + catch(InvalidPositionException &e) + { } - for(std::map::iterator + for(std::map::iterator i = modified_blocks.begin(); - i != modified_blocks.end(); ++i) { + i != modified_blocks.end(); ++i) + { addUpdateMeshTaskWithEdge(i->first, false, true); } } @@ -1213,16 +2371,18 @@ void Client::addNode(v3s16 p, MapNode n, bool remove_metadata) std::map modified_blocks; - try { + try + { //TimeTaker timer3("Client::addNode(): addNodeAndUpdate"); m_env.getMap().addNodeAndUpdate(p, n, modified_blocks, remove_metadata); } - catch(InvalidPositionException &e) { - } + catch(InvalidPositionException &e) + {} - for(std::map::iterator + for(std::map::iterator i = modified_blocks.begin(); - i != modified_blocks.end(); ++i) { + i != modified_blocks.end(); ++i) + { addUpdateMeshTaskWithEdge(i->first, false, true); } } @@ -1416,8 +2576,7 @@ bool Client::getChatMessage(std::wstring &message) { if(m_chat_queue.size() == 0) return false; - message = m_chat_queue.front(); - m_chat_queue.pop(); + message = m_chat_queue.pop_front(); return true; } @@ -1433,14 +2592,14 @@ void Client::typeChatMessage(const std::wstring &message) // Show locally if (message[0] == L'/') { - m_chat_queue.push((std::wstring)L"issued command: " + message); + m_chat_queue.push_back((std::wstring)L"issued command: " + message); } else { LocalPlayer *player = m_env.getLocalPlayer(); assert(player != NULL); std::wstring name = narrow_to_wide(player->getName()); - m_chat_queue.push((std::wstring)L"<" + name + L"> " + message); + m_chat_queue.push_back((std::wstring)L"<" + name + L"> " + message); } } @@ -1454,7 +2613,7 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server, bool urgent) Create a task to update the mesh of the block */ - MeshMakeData *data = new MeshMakeData(this, m_cache_enable_shaders); + MeshMakeData *data = new MeshMakeData(this); { //TimeTaker timer("data fill"); @@ -1503,7 +2662,7 @@ void Client::addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server, bool ur try{ addUpdateMeshTask(blockpos, ack_to_server, urgent); } - catch(InvalidPositionException &e) {} + catch(InvalidPositionException &e){} // Leading edge if(nodepos.X == blockpos_relative.X){ @@ -1533,15 +2692,13 @@ void Client::addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server, bool ur ClientEvent Client::getClientEvent() { - ClientEvent event; - if(m_client_event_queue.size() == 0) { + if(m_client_event_queue.size() == 0) + { + ClientEvent event; event.type = CE_NONE; + return event; } - else { - event = m_client_event_queue.front(); - m_client_event_queue.pop(); - } - return event; + return m_client_event_queue.pop_front(); } float Client::mediaReceiveProgress() @@ -1650,8 +2807,7 @@ void Client::makeScreenshot(IrrlichtDevice *device) if (image) { raw_image->copyTo(image); irr::c8 filename[256]; - snprintf(filename, sizeof(filename), - (std::string("%s") + DIR_DELIM + "screenshot_%u.png").c_str(), + snprintf(filename, sizeof(filename), "%s" DIR_DELIM "screenshot_%u.png", g_settings->get("screenshot_path").c_str(), device->getTimer()->getRealTime()); std::ostringstream sstr; @@ -1660,7 +2816,7 @@ void Client::makeScreenshot(IrrlichtDevice *device) } else { sstr << "Failed to save screenshot '" << filename << "'"; } - m_chat_queue.push(narrow_to_wide(sstr.str())); + m_chat_queue.push_back(narrow_to_wide(sstr.str())); infostream << sstr.str() << std::endl; image->drop(); } @@ -1744,3 +2900,4 @@ scene::IAnimatedMesh* Client::getMesh(const std::string &filename) smgr->getMeshCache()->removeMesh(mesh); return mesh; } + diff --git a/src/client.h b/src/client.h index a0add689a..fd7e5f08d 100644 --- a/src/client.h +++ b/src/client.h @@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef CLIENT_HEADER #define CLIENT_HEADER -#include "network/connection.h" +#include "connection.h" #include "environment.h" #include "irrlichttypes_extrabloated.h" #include "jthread/jmutex.h" @@ -34,7 +34,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "localplayer.h" #include "hud.h" #include "particles.h" -#include "network/networkpacket.h" struct MeshMakeData; class MapBlockMesh; @@ -48,6 +47,7 @@ struct MapDrawControl; class MtEventManager; struct PointedThing; class Database; +class Server; struct QueuedMeshUpdate { @@ -341,61 +341,11 @@ public: */ void step(float dtime); - /* - * Command Handlers - */ - - void handleCommand(NetworkPacket* pkt); - - void handleCommand_Null(NetworkPacket* pkt) {}; - void handleCommand_Deprecated(NetworkPacket* pkt); - void handleCommand_Init(NetworkPacket* pkt); - void handleCommand_AccessDenied(NetworkPacket* pkt); - void handleCommand_RemoveNode(NetworkPacket* pkt); - void handleCommand_AddNode(NetworkPacket* pkt); - void handleCommand_BlockData(NetworkPacket* pkt); - void handleCommand_Inventory(NetworkPacket* pkt); - void handleCommand_TimeOfDay(NetworkPacket* pkt); - void handleCommand_ChatMessage(NetworkPacket* pkt); - void handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt); - void handleCommand_ActiveObjectMessages(NetworkPacket* pkt); - void handleCommand_Movement(NetworkPacket* pkt); - void handleCommand_HP(NetworkPacket* pkt); - void handleCommand_Breath(NetworkPacket* pkt); - void handleCommand_MovePlayer(NetworkPacket* pkt); - void handleCommand_PlayerItem(NetworkPacket* pkt); - void handleCommand_DeathScreen(NetworkPacket* pkt); - void handleCommand_AnnounceMedia(NetworkPacket* pkt); - void handleCommand_Media(NetworkPacket* pkt); - void handleCommand_ToolDef(NetworkPacket* pkt); - void handleCommand_NodeDef(NetworkPacket* pkt); - void handleCommand_CraftItemDef(NetworkPacket* pkt); - void handleCommand_ItemDef(NetworkPacket* pkt); - void handleCommand_PlaySound(NetworkPacket* pkt); - void handleCommand_StopSound(NetworkPacket* pkt); - void handleCommand_Privileges(NetworkPacket* pkt); - void handleCommand_InventoryFormSpec(NetworkPacket* pkt); - void handleCommand_DetachedInventory(NetworkPacket* pkt); - void handleCommand_ShowFormSpec(NetworkPacket* pkt); - void handleCommand_SpawnParticle(NetworkPacket* pkt); - void handleCommand_AddParticleSpawner(NetworkPacket* pkt); - void handleCommand_DeleteParticleSpawner(NetworkPacket* pkt); - void handleCommand_HudAdd(NetworkPacket* pkt); - void handleCommand_HudRemove(NetworkPacket* pkt); - void handleCommand_HudChange(NetworkPacket* pkt); - void handleCommand_HudSetFlags(NetworkPacket* pkt); - void handleCommand_HudSetParam(NetworkPacket* pkt); - void handleCommand_HudSetSky(NetworkPacket* pkt); - void handleCommand_OverrideDayNightRatio(NetworkPacket* pkt); - void handleCommand_LocalPlayerAnimations(NetworkPacket* pkt); - void handleCommand_EyeOffset(NetworkPacket* pkt); - void ProcessData(u8 *data, u32 datasize, u16 sender_peer_id); - // Returns true if something was received bool AsyncProcessPacket(); bool AsyncProcessData(); - void Send(NetworkPacket* pkt); + void Send(u16 channelnum, SharedBuffer data, bool reliable); void interact(u8 action, const PointedThing& pointed); @@ -515,7 +465,7 @@ public: // Insert a media file appropriately into the appropriate manager bool loadMedia(const std::string &data, const std::string &filename); // Send a request for conventional media transfer - void request_media(const std::vector &file_requests); + void request_media(const std::list &file_requests); // Send a notification that no conventional media transfer is needed void received_media(); @@ -577,13 +527,13 @@ private: // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT //s32 m_daynight_i; //u32 m_daynight_ratio; - std::queue m_chat_queue; + Queue m_chat_queue; // The seed returned by the server in TOCLIENT_INIT is stored here u64 m_map_seed; std::string m_password; bool m_access_denied; std::wstring m_access_denied_reason; - std::queue m_client_event_queue; + Queue m_client_event_queue; bool m_itemdef_received; bool m_nodedef_received; ClientMediaDownloader *m_media_downloader; @@ -619,13 +569,12 @@ private: LocalClientState m_state; // Used for saving server map to disk client-side - Database *m_localdb; - IntervalLimiter m_localdb_save_interval; - u16 m_cache_save_interval; + Database *localdb; + Server *localserver; - // TODO: Add callback to update these when g_settings changes + // TODO: Add callback to update this when g_settings changes bool m_cache_smooth_lighting; - bool m_cache_enable_shaders; }; #endif // !CLIENT_HEADER + diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt deleted file mode 100644 index 288acf14c..000000000 --- a/src/client/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(client_SRCS - ${CMAKE_CURRENT_SOURCE_DIR}/clientlauncher.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/tile.cpp - PARENT_SCOPE -) diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp deleted file mode 100644 index 0f60dcd63..000000000 --- a/src/client/clientlauncher.cpp +++ /dev/null @@ -1,709 +0,0 @@ -/* -Minetest -Copyright (C) 2010-2013 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 -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 "main.h" -#include "mainmenumanager.h" -#include "debug.h" -#include "clouds.h" -#include "server.h" -#include "filesys.h" -#include "guiMainMenu.h" -#include "game.h" -#include "chat.h" -#include "gettext.h" -#include "profiler.h" -#include "log.h" -#include "serverlist.h" -#include "guiEngine.h" -#include "player.h" -#include "fontengine.h" -#include "clientlauncher.h" - -// A pointer to a global instance of the time getter -// TODO: why? -TimeGetter *g_timegetter = NULL; - -u32 getTimeMs() -{ - if (g_timegetter == NULL) - return 0; - return g_timegetter->getTime(PRECISION_MILLI); -} - -u32 getTime(TimePrecision prec) { - if (g_timegetter == NULL) - return 0; - return g_timegetter->getTime(prec); -} - -ClientLauncher::~ClientLauncher() -{ - if (receiver) - delete receiver; - - if (input) - delete input; - - if (g_fontengine) - delete g_fontengine; - - if (device) - device->drop(); -} - - -bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args) -{ - init_args(game_params, cmd_args); - - // List video modes if requested - if (list_video_modes) - return print_video_modes(); - - if (!init_engine(game_params.log_level)) { - errorstream << "Could not initialize game engine." << std::endl; - return false; - } - - // Speed tests (done after irrlicht is loaded to get timer) - if (cmd_args.getFlag("speedtests")) { - dstream << "Running speed tests" << std::endl; - speed_tests(); - return true; - } - - video::IVideoDriver *video_driver = device->getVideoDriver(); - if (video_driver == NULL) { - errorstream << "Could not initialize video driver." << std::endl; - return false; - } - - porting::setXorgClassHint(video_driver->getExposedVideoData(), "Minetest"); - - /* - This changes the minimum allowed number of vertices in a VBO. - Default is 500. - */ - //driver->setMinHardwareBufferVertexCount(50); - - // Create time getter - g_timegetter = new IrrlichtTimeGetter(device); - - // Create game callback for menus - g_gamecallback = new MainGameCallback(device); - - device->setResizable(true); - - if (random_input) - input = new RandomInputHandler(); - else - input = new RealInputHandler(device, receiver); - - smgr = device->getSceneManager(); - smgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); - - guienv = device->getGUIEnvironment(); - skin = guienv->getSkin(); - skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255, 255, 255, 255)); - skin->setColor(gui::EGDC_3D_LIGHT, video::SColor(0, 0, 0, 0)); - skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255, 30, 30, 30)); - skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255, 0, 0, 0)); - skin->setColor(gui::EGDC_HIGH_LIGHT, video::SColor(255, 70, 120, 50)); - skin->setColor(gui::EGDC_HIGH_LIGHT_TEXT, video::SColor(255, 255, 255, 255)); - - g_fontengine = new FontEngine(g_settings, guienv); - assert(g_fontengine != NULL); - -#if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2 - // Irrlicht 1.8 input colours - skin->setColor(gui::EGDC_EDITABLE, video::SColor(255, 128, 128, 128)); - skin->setColor(gui::EGDC_FOCUSED_EDITABLE, video::SColor(255, 96, 134, 49)); -#endif - - // Create the menu clouds - if (!g_menucloudsmgr) - g_menucloudsmgr = smgr->createNewSceneManager(); - if (!g_menuclouds) - g_menuclouds = new Clouds(g_menucloudsmgr->getRootSceneNode(), - g_menucloudsmgr, -1, rand(), 100); - g_menuclouds->update(v2f(0, 0), video::SColor(255, 200, 200, 255)); - scene::ICameraSceneNode* camera; - camera = g_menucloudsmgr->addCameraSceneNode(0, - v3f(0, 0, 0), v3f(0, 60, 100)); - camera->setFarValue(10000); - - /* - GUI stuff - */ - - ChatBackend chat_backend; - - // If an error occurs, this is set to something by menu(). - // It is then displayed before the menu shows on the next call to menu() - std::wstring error_message = L""; - - bool first_loop = true; - - /* - Menu-game loop - */ - bool retval = true; - bool *kill = porting::signal_handler_killstatus(); - - while (device->run() && !*kill && !g_gamecallback->shutdown_requested) - { - // Set the window caption - const wchar_t *text = wgettext("Main Menu"); - device->setWindowCaption((std::wstring(L"Minetest [") + text + L"]").c_str()); - delete[] text; - - try { // This is used for catching disconnects - - guienv->clear(); - - /* - We need some kind of a root node to be able to add - custom gui elements directly on the screen. - Otherwise they won't be automatically drawn. - */ - guiroot = guienv->addStaticText(L"", core::rect(0, 0, 10000, 10000)); - - bool game_has_run = launch_game(&error_message, game_params, cmd_args); - - // If skip_main_menu, we only want to startup once - if (skip_main_menu && !first_loop) - break; - - first_loop = false; - - if (!game_has_run) { - if (skip_main_menu) - break; - else - continue; - } - - // Break out of menu-game loop to shut down cleanly - if (!device->run() || *kill) { - if (g_settings_path != "") - g_settings->updateConfigFile(g_settings_path.c_str()); - break; - } - - if (current_playername.length() > PLAYERNAME_SIZE-1) { - error_message = wgettext("Player name too long."); - playername = current_playername.substr(0, PLAYERNAME_SIZE-1); - g_settings->set("name", playername); - continue; - } - - device->getVideoDriver()->setTextureCreationFlag( - video::ETCF_CREATE_MIP_MAPS, g_settings->getBool("mip_map")); - -#ifdef HAVE_TOUCHSCREENGUI - receiver->m_touchscreengui = new TouchScreenGUI(device, receiver); - g_touchscreengui = receiver->m_touchscreengui; -#endif - the_game( - kill, - random_input, - input, - device, - worldspec.path, - current_playername, - current_password, - current_address, - current_port, - error_message, - chat_backend, - gamespec, - simple_singleplayer_mode - ); - smgr->clear(); - -#ifdef HAVE_TOUCHSCREENGUI - delete g_touchscreengui; - g_touchscreengui = NULL; - receiver->m_touchscreengui = NULL; -#endif - - } //try - catch (con::PeerNotFoundException &e) { - error_message = wgettext("Connection error (timed out?)"); - errorstream << wide_to_narrow(error_message) << std::endl; - } - -#ifdef NDEBUG - catch (std::exception &e) { - std::string narrow_message = "Some exception: \""; - narrow_message += e.what(); - narrow_message += "\""; - errorstream << narrow_message << std::endl; - error_message = narrow_to_wide(narrow_message); - } -#endif - - // If no main menu, show error and exit - if (skip_main_menu) { - if (error_message != L"") { - verbosestream << "error_message = " - << wide_to_narrow(error_message) << std::endl; - retval = false; - } - break; - } - } // Menu-game loop - - g_menuclouds->drop(); - g_menucloudsmgr->drop(); - - return retval; -} - -void ClientLauncher::init_args(GameParams &game_params, const Settings &cmd_args) -{ - - skip_main_menu = cmd_args.getFlag("go"); - - // FIXME: This is confusing (but correct) - - /* If world_path is set then override it unless skipping the main menu using - * the --go command line param. Else, give preference to the address - * supplied on the command line - */ - address = g_settings->get("address"); - if (game_params.world_path != "" && !skip_main_menu) - address = ""; - else if (cmd_args.exists("address")) - address = cmd_args.get("address"); - - playername = g_settings->get("name"); - if (cmd_args.exists("name")) - playername = cmd_args.get("name"); - - list_video_modes = cmd_args.getFlag("videomodes"); - - use_freetype = g_settings->getBool("freetype"); - - random_input = g_settings->getBool("random_input") - || cmd_args.getFlag("random-input"); -} - -bool ClientLauncher::init_engine(int log_level) -{ - receiver = new MyEventReceiver(); - create_engine_device(log_level); - return device != NULL; -} - -bool ClientLauncher::launch_game(std::wstring *error_message, - GameParams &game_params, const Settings &cmd_args) -{ - // Initialize menu data - MainMenuData menudata; - menudata.address = address; - menudata.name = playername; - menudata.port = itos(game_params.socket_port); - menudata.errormessage = wide_to_narrow(*error_message); - - *error_message = L""; - - if (cmd_args.exists("password")) - menudata.password = cmd_args.get("password"); - - menudata.enable_public = g_settings->getBool("server_announce"); - - // If a world was commanded, append and select it - if (game_params.world_path != "") { - worldspec.gameid = getWorldGameId(game_params.world_path, true); - worldspec.name = _("[--world parameter]"); - - if (worldspec.gameid == "") { // Create new - worldspec.gameid = g_settings->get("default_game"); - worldspec.name += " [new]"; - } - worldspec.path = game_params.world_path; - } - - /* Show the GUI menu - */ - if (!skip_main_menu) { - main_menu(&menudata); - - // Skip further loading if there was an exit signal. - if (*porting::signal_handler_killstatus()) - return false; - - address = menudata.address; - int newport = stoi(menudata.port); - if (newport != 0) - game_params.socket_port = newport; - - simple_singleplayer_mode = menudata.simple_singleplayer_mode; - - std::vector worldspecs = getAvailableWorlds(); - - if (menudata.selected_world >= 0 - && menudata.selected_world < (int)worldspecs.size()) { - g_settings->set("selected_world_path", - worldspecs[menudata.selected_world].path); - worldspec = worldspecs[menudata.selected_world]; - } - } - - if (menudata.errormessage != "") { - /* The calling function will pass this back into this function upon the - * next iteration (if any) causing it to be displayed by the GUI - */ - *error_message = narrow_to_wide(menudata.errormessage); - return false; - } - - if (menudata.name == "") - menudata.name = std::string("Guest") + itos(myrand_range(1000, 9999)); - else - playername = menudata.name; - - password = translatePassword(playername, narrow_to_wide(menudata.password)); - - g_settings->set("name", playername); - - current_playername = playername; - current_password = password; - current_address = address; - current_port = game_params.socket_port; - - // If using simple singleplayer mode, override - if (simple_singleplayer_mode) { - assert(skip_main_menu == false); - current_playername = "singleplayer"; - current_password = ""; - current_address = ""; - current_port = myrand_range(49152, 65535); - } else if (address != "") { - ServerListSpec server; - server["name"] = menudata.servername; - server["address"] = menudata.address; - server["port"] = menudata.port; - server["description"] = menudata.serverdescription; - ServerList::insert(server); - } - - infostream << "Selected world: " << worldspec.name - << " [" << worldspec.path << "]" << std::endl; - - if (current_address == "") { // If local game - if (worldspec.path == "") { - *error_message = wgettext("No world selected and no address " - "provided. Nothing to do."); - errorstream << wide_to_narrow(*error_message) << std::endl; - return false; - } - - if (!fs::PathExists(worldspec.path)) { - *error_message = wgettext("Provided world path doesn't exist: ") - + narrow_to_wide(worldspec.path); - errorstream << wide_to_narrow(*error_message) << std::endl; - return false; - } - - // Load gamespec for required game - gamespec = findWorldSubgame(worldspec.path); - if (!gamespec.isValid() && !game_params.game_spec.isValid()) { - *error_message = wgettext("Could not find or load game \"") - + narrow_to_wide(worldspec.gameid) + L"\""; - errorstream << wide_to_narrow(*error_message) << std::endl; - return false; - } - - if (porting::signal_handler_killstatus()) - return true; - - if (game_params.game_spec.isValid() && - game_params.game_spec.id != worldspec.gameid) { - errorstream << "WARNING: Overriding gamespec from \"" - << worldspec.gameid << "\" to \"" - << game_params.game_spec.id << "\"" << std::endl; - gamespec = game_params.game_spec; - } - - if (!gamespec.isValid()) { - *error_message = wgettext("Invalid gamespec."); - *error_message += L" (world_gameid=" - + narrow_to_wide(worldspec.gameid) + L")"; - errorstream << wide_to_narrow(*error_message) << std::endl; - return false; - } - } - - return true; -} - -void ClientLauncher::main_menu(MainMenuData *menudata) -{ - bool *kill = porting::signal_handler_killstatus(); - video::IVideoDriver *driver = device->getVideoDriver(); - - infostream << "Waiting for other menus" << std::endl; - while (device->run() && *kill == false) { - if (noMenuActive()) - break; - driver->beginScene(true, true, video::SColor(255, 128, 128, 128)); - guienv->drawAll(); - driver->endScene(); - // On some computers framerate doesn't seem to be automatically limited - sleep_ms(25); - } - infostream << "Waited for other menus" << std::endl; - - // Cursor can be non-visible when coming from the game -#ifndef ANDROID - device->getCursorControl()->setVisible(true); -#endif - - /* show main menu */ - GUIEngine mymenu(device, guiroot, &g_menumgr, smgr, menudata, *kill); - - smgr->clear(); /* leave scene manager in a clean state */ -} - -bool ClientLauncher::create_engine_device(int log_level) -{ - static const irr::ELOG_LEVEL irr_log_level[5] = { - ELL_NONE, - ELL_ERROR, - ELL_WARNING, - ELL_INFORMATION, -#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) - ELL_INFORMATION -#else - ELL_DEBUG -#endif - }; - - // Resolution selection - bool fullscreen = g_settings->getBool("fullscreen"); - u16 screenW = g_settings->getU16("screenW"); - u16 screenH = g_settings->getU16("screenH"); - - // bpp, fsaa, vsync - bool vsync = g_settings->getBool("vsync"); - u16 bits = g_settings->getU16("fullscreen_bpp"); - u16 fsaa = g_settings->getU16("fsaa"); - - // Determine driver - video::E_DRIVER_TYPE driverType = video::EDT_OPENGL; - std::string driverstring = g_settings->get("video_driver"); - std::vector drivers - = porting::getSupportedVideoDrivers(); - u32 i; - for (i = 0; i != drivers.size(); i++) { - if (!strcasecmp(driverstring.c_str(), - porting::getVideoDriverName(drivers[i]))) { - driverType = drivers[i]; - break; - } - } - if (i == drivers.size()) { - errorstream << "Invalid video_driver specified; " - "defaulting to opengl" << std::endl; - } - - SIrrlichtCreationParameters params = SIrrlichtCreationParameters(); - params.DriverType = driverType; - params.WindowSize = core::dimension2d(screenW, screenH); - params.Bits = bits; - params.AntiAlias = fsaa; - params.Fullscreen = fullscreen; - params.Stencilbuffer = false; - params.Vsync = vsync; - params.EventReceiver = receiver; - params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu"); -#ifdef __ANDROID__ - params.PrivateData = porting::app_global; - params.OGLES2ShaderPath = std::string(porting::path_user + DIR_DELIM + - "media" + DIR_DELIM + "Shaders" + DIR_DELIM).c_str(); -#endif - - device = createDeviceEx(params); - - if (device) { - // Map our log level to irrlicht engine one. - ILogger* irr_logger = device->getLogger(); - irr_logger->setLogLevel(irr_log_level[log_level]); - - porting::initIrrlicht(device); - } - - return device != NULL; -} - -void ClientLauncher::speed_tests() -{ - // volatile to avoid some potential compiler optimisations - volatile static s16 temp16; - volatile static f32 tempf; - static v3f tempv3f1; - static v3f tempv3f2; - static std::string tempstring; - static std::string tempstring2; - - tempv3f1 = v3f(); - tempv3f2 = v3f(); - tempstring = std::string(); - tempstring2 = std::string(); - - { - infostream << "The following test should take around 20ms." << std::endl; - TimeTaker timer("Testing std::string speed"); - const u32 jj = 10000; - for (u32 j = 0; j < jj; j++) { - tempstring = ""; - tempstring2 = ""; - const u32 ii = 10; - for (u32 i = 0; i < ii; i++) { - tempstring2 += "asd"; - } - for (u32 i = 0; i < ii+1; i++) { - tempstring += "asd"; - if (tempstring == tempstring2) - break; - } - } - } - - infostream << "All of the following tests should take around 100ms each." - << std::endl; - - { - TimeTaker timer("Testing floating-point conversion speed"); - tempf = 0.001; - for (u32 i = 0; i < 4000000; i++) { - temp16 += tempf; - tempf += 0.001; - } - } - - { - TimeTaker timer("Testing floating-point vector speed"); - - tempv3f1 = v3f(1, 2, 3); - tempv3f2 = v3f(4, 5, 6); - for (u32 i = 0; i < 10000000; i++) { - tempf += tempv3f1.dotProduct(tempv3f2); - tempv3f2 += v3f(7, 8, 9); - } - } - - { - TimeTaker timer("Testing std::map speed"); - - std::map map1; - tempf = -324; - const s16 ii = 300; - for (s16 y = 0; y < ii; y++) { - for (s16 x = 0; x < ii; x++) { - map1[v2s16(x, y)] = tempf; - tempf += 1; - } - } - for (s16 y = ii - 1; y >= 0; y--) { - for (s16 x = 0; x < ii; x++) { - tempf = map1[v2s16(x, y)]; - } - } - } - - { - infostream << "Around 5000/ms should do well here." << std::endl; - TimeTaker timer("Testing mutex speed"); - - JMutex m; - u32 n = 0; - u32 i = 0; - do { - n += 10000; - for (; i < n; i++) { - m.Lock(); - m.Unlock(); - } - } - // Do at least 10ms - while(timer.getTimerTime() < 10); - - u32 dtime = timer.stop(); - u32 per_ms = n / dtime; - infostream << "Done. " << dtime << "ms, " << per_ms << "/ms" << std::endl; - } -} - -bool ClientLauncher::print_video_modes() -{ - IrrlichtDevice *nulldevice; - - bool vsync = g_settings->getBool("vsync"); - u16 fsaa = g_settings->getU16("fsaa"); - MyEventReceiver* receiver = new MyEventReceiver(); - - SIrrlichtCreationParameters params = SIrrlichtCreationParameters(); - params.DriverType = video::EDT_NULL; - params.WindowSize = core::dimension2d(640, 480); - params.Bits = 24; - params.AntiAlias = fsaa; - params.Fullscreen = false; - params.Stencilbuffer = false; - params.Vsync = vsync; - params.EventReceiver = receiver; - params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu"); - - nulldevice = createDeviceEx(params); - - if (nulldevice == NULL) { - delete receiver; - return false; - } - - dstream << _("Available video modes (WxHxD):") << std::endl; - - video::IVideoModeList *videomode_list = nulldevice->getVideoModeList(); - - if (videomode_list != NULL) { - s32 videomode_count = videomode_list->getVideoModeCount(); - core::dimension2d videomode_res; - s32 videomode_depth; - for (s32 i = 0; i < videomode_count; ++i) { - videomode_res = videomode_list->getVideoModeResolution(i); - videomode_depth = videomode_list->getVideoModeDepth(i); - dstream << videomode_res.Width << "x" << videomode_res.Height - << "x" << videomode_depth << std::endl; - } - - dstream << _("Active video mode (WxHxD):") << std::endl; - videomode_res = videomode_list->getDesktopResolution(); - videomode_depth = videomode_list->getDesktopDepth(); - dstream << videomode_res.Width << "x" << videomode_res.Height - << "x" << videomode_depth << std::endl; - - } - - nulldevice->drop(); - delete receiver; - - return videomode_list != NULL; -} diff --git a/src/client/clientlauncher.h b/src/client/clientlauncher.h deleted file mode 100644 index c3e0ae866..000000000 --- a/src/client/clientlauncher.h +++ /dev/null @@ -1,129 +0,0 @@ -/* -Minetest -Copyright (C) 2010-2013 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 -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. -*/ - -#ifndef __CLIENT_LAUNCHER_H__ -#define __CLIENT_LAUNCHER_H__ - -#include "irrlichttypes_extrabloated.h" -#include "client/inputhandler.h" -#include "gameparams.h" - -// A small helper class -class TimeGetter -{ -public: - virtual u32 getTime(TimePrecision prec) = 0; -}; - -// A precise irrlicht one -class IrrlichtTimeGetter: public TimeGetter -{ -public: - IrrlichtTimeGetter(IrrlichtDevice *device): - m_device(device) - {} - u32 getTime(TimePrecision prec) - { - if (prec == PRECISION_MILLI) { - if (m_device == NULL) - return 0; - return m_device->getTimer()->getRealTime(); - } else { - return porting::getTime(prec); - } - } -private: - IrrlichtDevice *m_device; -}; -// Not so precise one which works without irrlicht -class SimpleTimeGetter: public TimeGetter -{ -public: - u32 getTime(TimePrecision prec) - { - return porting::getTime(prec); - } -}; - -class ClientLauncher -{ -public: - ClientLauncher() : - list_video_modes(false), - skip_main_menu(false), - use_freetype(false), - random_input(false), - address(""), - playername(""), - password(""), - device(NULL), - input(NULL), - receiver(NULL), - skin(NULL), - font(NULL), - simple_singleplayer_mode(false), - current_playername("inv£lid"), - current_password(""), - current_address("does-not-exist"), - current_port(0) - {} - - ~ClientLauncher(); - - bool run(GameParams &game_params, const Settings &cmd_args); - -protected: - void init_args(GameParams &game_params, const Settings &cmd_args); - bool init_engine(int log_level); - - bool launch_game(std::wstring *error_message, GameParams &game_params, - const Settings &cmd_args); - - void main_menu(MainMenuData *menudata); - bool create_engine_device(int log_level); - - void speed_tests(); - bool print_video_modes(); - - bool list_video_modes; - bool skip_main_menu; - bool use_freetype; - bool random_input; - std::string address; - std::string playername; - std::string password; - IrrlichtDevice *device; - InputHandler *input; - MyEventReceiver *receiver; - gui::IGUISkin *skin; - gui::IGUIFont *font; - scene::ISceneManager *smgr; - SubgameSpec gamespec; - WorldSpec worldspec; - bool simple_singleplayer_mode; - - // These are set up based on the menu and other things - // TODO: Are these required since there's already playername, password, etc - std::string current_playername; - std::string current_password; - std::string current_address; - int current_port; -}; - -#endif diff --git a/src/client/inputhandler.h b/src/client/inputhandler.h deleted file mode 100644 index 7cd3ddc71..000000000 --- a/src/client/inputhandler.h +++ /dev/null @@ -1,428 +0,0 @@ -/* -Minetest -Copyright (C) 2010-2013 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 -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. -*/ - -#ifndef __INPUT_HANDLER_H__ -#define __INPUT_HANDLER_H__ - -#include "irrlichttypes_extrabloated.h" - -class MyEventReceiver : public IEventReceiver -{ -public: - // This is the one method that we have to implement - virtual bool OnEvent(const SEvent& event) - { - /* - React to nothing here if a menu is active - */ - if (noMenuActive() == false) { -#ifdef HAVE_TOUCHSCREENGUI - if (m_touchscreengui != 0) { - m_touchscreengui->Toggle(false); - } -#endif - return g_menumgr.preprocessEvent(event); - } - - // Remember whether each key is down or up - if (event.EventType == irr::EET_KEY_INPUT_EVENT) { - if (event.KeyInput.PressedDown) { - keyIsDown.set(event.KeyInput); - keyWasDown.set(event.KeyInput); - } else { - keyIsDown.unset(event.KeyInput); - } - } - -#ifdef HAVE_TOUCHSCREENGUI - // case of touchscreengui we have to handle different events - if ((m_touchscreengui != 0) && - (event.EventType == irr::EET_TOUCH_INPUT_EVENT)) { - m_touchscreengui->translateEvent(event); - return true; - } -#endif - // handle mouse events - if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) { - if (noMenuActive() == false) { - left_active = false; - middle_active = false; - right_active = false; - } else { - left_active = event.MouseInput.isLeftPressed(); - middle_active = event.MouseInput.isMiddlePressed(); - right_active = event.MouseInput.isRightPressed(); - - if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { - leftclicked = true; - } - if (event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN) { - rightclicked = true; - } - if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) { - leftreleased = true; - } - if (event.MouseInput.Event == EMIE_RMOUSE_LEFT_UP) { - rightreleased = true; - } - if (event.MouseInput.Event == EMIE_MOUSE_WHEEL) { - mouse_wheel += event.MouseInput.Wheel; - } - } - } - if (event.EventType == irr::EET_LOG_TEXT_EVENT) { - dstream << std::string("Irrlicht log: ") + std::string(event.LogEvent.Text) - << std::endl; - return true; - } - /* always return false in order to continue processing events */ - return false; - } - - bool IsKeyDown(const KeyPress &keyCode) const - { - return keyIsDown[keyCode]; - } - - // Checks whether a key was down and resets the state - bool WasKeyDown(const KeyPress &keyCode) - { - bool b = keyWasDown[keyCode]; - if (b) - keyWasDown.unset(keyCode); - return b; - } - - s32 getMouseWheel() - { - s32 a = mouse_wheel; - mouse_wheel = 0; - return a; - } - - void clearInput() - { - keyIsDown.clear(); - keyWasDown.clear(); - - leftclicked = false; - rightclicked = false; - leftreleased = false; - rightreleased = false; - - left_active = false; - middle_active = false; - right_active = false; - - mouse_wheel = 0; - } - - MyEventReceiver() - { - clearInput(); -#ifdef HAVE_TOUCHSCREENGUI - m_touchscreengui = NULL; -#endif - } - - bool leftclicked; - bool rightclicked; - bool leftreleased; - bool rightreleased; - - bool left_active; - bool middle_active; - bool right_active; - - s32 mouse_wheel; - -#ifdef HAVE_TOUCHSCREENGUI - TouchScreenGUI* m_touchscreengui; -#endif - -private: - // The current state of keys - KeyList keyIsDown; - // Whether a key has been pressed or not - KeyList keyWasDown; -}; - - -/* - Separated input handler -*/ - -class RealInputHandler : public InputHandler -{ -public: - RealInputHandler(IrrlichtDevice *device, MyEventReceiver *receiver): - m_device(device), - m_receiver(receiver), - m_mousepos(0,0) - { - } - virtual bool isKeyDown(const KeyPress &keyCode) - { - return m_receiver->IsKeyDown(keyCode); - } - virtual bool wasKeyDown(const KeyPress &keyCode) - { - return m_receiver->WasKeyDown(keyCode); - } - virtual v2s32 getMousePos() - { - if (m_device->getCursorControl()) { - return m_device->getCursorControl()->getPosition(); - } - else { - return m_mousepos; - } - } - virtual void setMousePos(s32 x, s32 y) - { - if (m_device->getCursorControl()) { - m_device->getCursorControl()->setPosition(x, y); - } - else { - m_mousepos = v2s32(x,y); - } - } - - virtual bool getLeftState() - { - return m_receiver->left_active; - } - virtual bool getRightState() - { - return m_receiver->right_active; - } - - virtual bool getLeftClicked() - { - return m_receiver->leftclicked; - } - virtual bool getRightClicked() - { - return m_receiver->rightclicked; - } - virtual void resetLeftClicked() - { - m_receiver->leftclicked = false; - } - virtual void resetRightClicked() - { - m_receiver->rightclicked = false; - } - - virtual bool getLeftReleased() - { - return m_receiver->leftreleased; - } - virtual bool getRightReleased() - { - return m_receiver->rightreleased; - } - virtual void resetLeftReleased() - { - m_receiver->leftreleased = false; - } - virtual void resetRightReleased() - { - m_receiver->rightreleased = false; - } - - virtual s32 getMouseWheel() - { - return m_receiver->getMouseWheel(); - } - - void clear() - { - m_receiver->clearInput(); - } -private: - IrrlichtDevice *m_device; - MyEventReceiver *m_receiver; - v2s32 m_mousepos; -}; - -class RandomInputHandler : public InputHandler -{ -public: - RandomInputHandler() - { - leftdown = false; - rightdown = false; - leftclicked = false; - rightclicked = false; - leftreleased = false; - rightreleased = false; - keydown.clear(); - } - virtual bool isKeyDown(const KeyPress &keyCode) - { - return keydown[keyCode]; - } - virtual bool wasKeyDown(const KeyPress &keyCode) - { - return false; - } - virtual v2s32 getMousePos() - { - return mousepos; - } - virtual void setMousePos(s32 x, s32 y) - { - mousepos = v2s32(x, y); - } - - virtual bool getLeftState() - { - return leftdown; - } - virtual bool getRightState() - { - return rightdown; - } - - virtual bool getLeftClicked() - { - return leftclicked; - } - virtual bool getRightClicked() - { - return rightclicked; - } - virtual void resetLeftClicked() - { - leftclicked = false; - } - virtual void resetRightClicked() - { - rightclicked = false; - } - - virtual bool getLeftReleased() - { - return leftreleased; - } - virtual bool getRightReleased() - { - return rightreleased; - } - virtual void resetLeftReleased() - { - leftreleased = false; - } - virtual void resetRightReleased() - { - rightreleased = false; - } - - virtual s32 getMouseWheel() - { - return 0; - } - - virtual void step(float dtime) - { - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 40); - keydown.toggle(getKeySetting("keymap_jump")); - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 40); - keydown.toggle(getKeySetting("keymap_special1")); - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 40); - keydown.toggle(getKeySetting("keymap_forward")); - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 40); - keydown.toggle(getKeySetting("keymap_left")); - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 20); - mousespeed = v2s32(Rand(-20, 20), Rand(-15, 20)); - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 30); - leftdown = !leftdown; - if (leftdown) - leftclicked = true; - if (!leftdown) - leftreleased = true; - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 15); - rightdown = !rightdown; - if (rightdown) - rightclicked = true; - if (!rightdown) - rightreleased = true; - } - } - mousepos += mousespeed; - } - - s32 Rand(s32 min, s32 max) - { - return (myrand()%(max-min+1))+min; - } -private: - KeyList keydown; - v2s32 mousepos; - v2s32 mousespeed; - bool leftdown; - bool rightdown; - bool leftclicked; - bool rightclicked; - bool leftreleased; - bool rightreleased; -}; - -#endif diff --git a/src/clientiface.cpp b/src/clientiface.cpp index 126979897..40d1ef811 100644 --- a/src/clientiface.cpp +++ b/src/clientiface.cpp @@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "player.h" #include "settings.h" #include "mapblock.h" -#include "network/connection.h" +#include "connection.h" #include "environment.h" #include "map.h" #include "emerge.h" @@ -59,7 +59,7 @@ void RemoteClient::ResendBlockIfOnWire(v3s16 p) } } -void RemoteClient::GetNextBlocks ( +void RemoteClient::GetNextBlocks( ServerEnvironment *env, EmergeManager * emerge, float dtime, @@ -182,15 +182,18 @@ void RemoteClient::GetNextBlocks ( //bool queue_is_full = false; s16 d; - for(d = d_start; d <= d_max; d++) { + for(d = d_start; d <= d_max; d++) + { /* Get the border/face dot coordinates of a "d-radiused" box */ - std::vector list = FacePositionCache::getFacePositions(d); + std::list list; + getFacePositions(list, d); - std::vector::iterator li; - for(li = list.begin(); li != list.end(); ++li) { + std::list::iterator li; + for(li=list.begin(); li!=list.end(); ++li) + { v3s16 p = *li + center; /* @@ -560,9 +563,9 @@ ClientInterface::~ClientInterface() } } -std::vector ClientInterface::getClientIDs(ClientState min_state) +std::list ClientInterface::getClientIDs(ClientState min_state) { - std::vector reply; + std::list reply; JMutexAutoLock clientslock(m_clients_mutex); for(std::map::iterator @@ -596,22 +599,20 @@ void ClientInterface::UpdatePlayerList() { if (m_env != NULL) { - std::vector clients = getClientIDs(); + std::list clients = getClientIDs(); m_clients_names.clear(); if(!clients.empty()) infostream<<"Players:"<::iterator + for(std::list::iterator i = clients.begin(); - i != clients.end(); ++i) { + i != clients.end(); ++i) + { Player *player = m_env->getPlayer(*i); - - if (player == NULL) + if(player==NULL) continue; - - infostream << "* " << player->getName() << "\t"; + infostream<<"* "<getName()<<"\t"; { JMutexAutoLock clientslock(m_clients_mutex); @@ -619,36 +620,32 @@ void ClientInterface::UpdatePlayerList() if(client != NULL) client->PrintInfo(infostream); } - m_clients_names.push_back(player->getName()); } } } -void ClientInterface::send(u16 peer_id, u8 channelnum, - NetworkPacket* pkt, bool reliable, bool deletepkt) +void ClientInterface::send(u16 peer_id,u8 channelnum, + SharedBuffer data, bool reliable) { - m_con->Send(peer_id, channelnum, pkt, reliable); - - if (deletepkt) - delete pkt; + m_con->Send(peer_id, channelnum, data, reliable); } void ClientInterface::sendToAll(u16 channelnum, - NetworkPacket* pkt, bool reliable) + SharedBuffer data, bool reliable) { JMutexAutoLock clientslock(m_clients_mutex); for(std::map::iterator i = m_clients.begin(); - i != m_clients.end(); ++i) { + i != m_clients.end(); ++i) + { RemoteClient *client = i->second; - if (client->net_proto_version != 0) { - m_con->Send(client->peer_id, channelnum, pkt, reliable); + if (client->net_proto_version != 0) + { + m_con->Send(client->peer_id, channelnum, data, reliable); } } - - delete pkt; } RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min) diff --git a/src/clientiface.h b/src/clientiface.h index 2f265b128..cb3dae04b 100644 --- a/src/clientiface.h +++ b/src/clientiface.h @@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "constants.h" #include "serialization.h" // for SER_FMT_VER_INVALID #include "jthread/jmutex.h" -#include "network/networkpacket.h" #include #include @@ -388,16 +387,16 @@ public: void step(float dtime); /* get list of active client id's */ - std::vector getClientIDs(ClientState min_state=CS_Active); + std::list getClientIDs(ClientState min_state=CS_Active); /* get list of client player names */ std::vector getPlayerNames(); /* send message to client */ - void send(u16 peer_id, u8 channelnum, NetworkPacket* pkt, bool reliable, bool deletepkt=true); + void send(u16 peer_id, u8 channelnum, SharedBuffer data, bool reliable); /* send to all clients */ - void sendToAll(u16 channelnum, NetworkPacket* pkt, bool reliable); + void sendToAll(u16 channelnum, SharedBuffer data, bool reliable); /* delete a client */ void DeleteClient(u16 peer_id); @@ -458,7 +457,7 @@ private: JMutex m_env_mutex; float m_print_info_timer; - + static const char *statenames[]; }; diff --git a/src/clientmap.cpp b/src/clientmap.cpp index 1c420b5f9..2db901f22 100644 --- a/src/clientmap.cpp +++ b/src/clientmap.cpp @@ -161,9 +161,9 @@ static bool isOccluded(Map *map, v3s16 p0, v3s16 p1, float step, float stepfac, else is_transparent = (f.solidness != 2); if(!is_transparent){ - if(count == needed_count) - return true; count++; + if(count >= needed_count) + return true; } step *= stepfac; } @@ -247,7 +247,7 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver) continue; } - MapBlockVect sectorblocks; + std::list< MapBlock * > sectorblocks; sector->getBlocks(sectorblocks); /* @@ -256,8 +256,8 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver) u32 sector_blocks_drawn = 0; - for(MapBlockVect::iterator i = sectorblocks.begin(); - i != sectorblocks.end(); i++) + std::list< MapBlock * >::iterator i; + for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++) { MapBlock *block = *i; @@ -391,12 +391,12 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver) struct MeshBufList { video::SMaterial m; - std::vector bufs; + std::list bufs; }; struct MeshBufListList { - std::vector lists; + std::list lists; void clear() { @@ -405,7 +405,7 @@ struct MeshBufListList void add(scene::IMeshBuffer *buf) { - for(std::vector::iterator i = lists.begin(); + for(std::list::iterator i = lists.begin(); i != lists.end(); ++i){ MeshBufList &l = *i; video::SMaterial &m = buf->getMaterial(); @@ -595,20 +595,25 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) } } - std::vector &lists = drawbufs.lists; + std::list &lists = drawbufs.lists; int timecheck_counter = 0; - for(std::vector::iterator i = lists.begin(); - i != lists.end(); ++i) { - timecheck_counter++; - if(timecheck_counter > 50) { - timecheck_counter = 0; - int time2 = time(0); - if(time2 > time1 + 4) { - infostream << "ClientMap::renderMap(): " - "Rendering takes ages, returning." - << std::endl; - return; + for(std::list::iterator i = lists.begin(); + i != lists.end(); ++i) + { + { + timecheck_counter++; + if(timecheck_counter > 50) + { + timecheck_counter = 0; + int time2 = time(0); + if(time2 > time1 + 4) + { + infostream<<"ClientMap::renderMap(): " + "Rendering takes ages, returning." + <setMaterial(list.m); - for(std::vector::iterator j = list.bufs.begin(); - j != list.bufs.end(); ++j) { + for(std::list::iterator j = list.bufs.begin(); + j != list.bufs.end(); ++j) + { scene::IMeshBuffer *buf = *j; driver->drawMeshBuffer(buf); vertex_count += buf->getVertexCount(); meshbuffer_count++; } +#if 0 + /* + Draw the faces of the block + */ + { + //JMutexAutoLock lock(block->mesh_mutex); + MapBlockMesh *mapBlockMesh = block->mesh; + assert(mapBlockMesh); + + scene::SMesh *mesh = mapBlockMesh->getMesh(); + assert(mesh); + + u32 c = mesh->getMeshBufferCount(); + bool stuff_actually_drawn = false; + for(u32 i=0; igetMeshBuffer(i); + const video::SMaterial& material = buf->getMaterial(); + video::IMaterialRenderer* rnd = + driver->getMaterialRenderer(material.MaterialType); + bool transparent = (rnd && rnd->isTransparent()); + // Render transparent on transparent pass and likewise. + if(transparent == is_transparent_pass) + { + if(buf->getVertexCount() == 0) + errorstream<<"Block ["<setMaterial(buf->getMaterial()); + driver->drawMeshBuffer(buf); + vertex_count += buf->getVertexCount(); + meshbuffer_count++; + stuff_actually_drawn = true; + } + } + if(stuff_actually_drawn) + blocks_had_pass_meshbuf++; + else + blocks_without_stuff++; + } +#endif } } // ScopeProfiler diff --git a/src/clientmedia.cpp b/src/clientmedia.cpp index 1d825c143..434eeb248 100644 --- a/src/clientmedia.cpp +++ b/src/clientmedia.cpp @@ -18,20 +18,20 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "clientmedia.h" +#include "util/serialize.h" +#include "util/string.h" #include "httpfetch.h" #include "client.h" +#include "clientserver.h" #include "filecache.h" #include "filesys.h" +#include "hex.h" +#include "sha1.h" #include "debug.h" #include "log.h" #include "porting.h" #include "settings.h" #include "main.h" -#include "network/networkprotocol.h" -#include "util/hex.h" -#include "util/serialize.h" -#include "util/sha1.h" -#include "util/string.h" static std::string getMediaCacheDir() { @@ -488,7 +488,7 @@ void ClientMediaDownloader::startConventionalTransfers(Client *client) if (m_uncached_received_count != m_uncached_count) { // Some media files have not been received yet, use the // conventional slow method (minetest protocol) to get them - std::vector file_requests; + std::list file_requests; for (std::map::iterator it = m_files.begin(); it != m_files.end(); ++it) { diff --git a/src/clientobject.cpp b/src/clientobject.cpp index ae1be092f..37f693c5e 100644 --- a/src/clientobject.cpp +++ b/src/clientobject.cpp @@ -39,13 +39,14 @@ ClientActiveObject::~ClientActiveObject() removeFromScene(true); } -ClientActiveObject* ClientActiveObject::create(ActiveObjectType type, - IGameDef *gamedef, ClientEnvironment *env) +ClientActiveObject* ClientActiveObject::create(u8 type, IGameDef *gamedef, + ClientEnvironment *env) { // Find factory function std::map::iterator n; n = m_types.find(type); - if(n == m_types.end()) { + if(n == m_types.end()) + { // If factory is not found, just return. dstream<<"WARNING: ClientActiveObject: No factory for type=" <<(int)type< objects; + std::list objects; #ifndef SERVER ClientEnvironment *c_env = dynamic_cast(env); - if (c_env != 0) { + if (c_env != 0) + { f32 distance = speed_f.getLength(); std::vector clientobjects; c_env->getActiveObjects(pos_f,distance * 1.5,clientobjects); - for (size_t i=0; i < clientobjects.size(); i++) { + for (size_t i=0; i < clientobjects.size(); i++) + { if ((self == 0) || (self != clientobjects[i].obj)) { objects.push_back((ActiveObject*)clientobjects[i].obj); } @@ -317,10 +319,12 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, #endif { ServerEnvironment *s_env = dynamic_cast(env); - if (s_env != 0) { + if (s_env != 0) + { f32 distance = speed_f.getLength(); std::set s_objects = s_env->getObjectsInsideRadius(pos_f,distance * 1.5); - for (std::set::iterator iter = s_objects.begin(); iter != s_objects.end(); iter++) { + for (std::set::iterator iter = s_objects.begin(); iter != s_objects.end(); iter++) + { ServerActiveObject *current = s_env->getActiveObject(*iter); if ((self == 0) || (self != current)) { objects.push_back((ActiveObject*)current); @@ -329,14 +333,16 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, } } - for (std::vector::const_iterator iter = objects.begin(); - iter != objects.end(); ++iter) { + for (std::list::const_iterator iter = objects.begin();iter != objects.end(); ++iter) + { ActiveObject *object = *iter; - if (object != NULL) { + if (object != NULL) + { aabb3f object_collisionbox; if (object->getCollisionBox(&object_collisionbox) && - object->collideWithObjects()) { + object->collideWithObjects()) + { cboxes.push_back(object_collisionbox); is_unloaded.push_back(false); is_step_up.push_back(false); diff --git a/src/network/connection.cpp b/src/connection.cpp similarity index 90% rename from src/network/connection.cpp rename to src/connection.cpp index b73981ccc..2ee6d2c6e 100644 --- a/src/network/connection.cpp +++ b/src/connection.cpp @@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/string.h" #include "settings.h" #include "profiler.h" +#include "main.h" // for profiling namespace con { @@ -133,7 +134,7 @@ std::list > makeSplitPacket( u16 chunk_count = 0; do{ end = start + maximum_data_size - 1; - if (end > data.getSize() - 1) + if(end > data.getSize() - 1) end = data.getSize() - 1; u32 payload_size = end - start + 1; @@ -172,7 +173,7 @@ std::list > makeAutoSplitPacket( { u32 original_header_size = 1; std::list > list; - if (data.getSize() + original_header_size > chunksize_max) + if(data.getSize() + original_header_size > chunksize_max) { list = makeSplitPacket(data, chunksize_max, split_seqnum); split_seqnum++; @@ -245,7 +246,7 @@ RPBSearchResult ReliablePacketBuffer::findPacket(u16 seqnum) u16 s = readU16(&(i->data[BASE_HEADER_SIZE+1])); /*dout_con<<"findPacket(): finding seqnum="< ReliablePacketBuffer::getTimedOuts(float timeout, for(std::list::iterator i = m_list.begin(); i != m_list.end(); ++i) { - if (i->time >= timeout) { + if(i->time >= timeout) { timed_outs.push_back(*i); //this packet will be sent right afterwards reset timeout here @@ -457,7 +458,7 @@ SharedBuffer IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable) u16 chunk_num = readU16(&p.data[BASE_HEADER_SIZE+5]); // Add if doesn't exist - if (m_buf.find(seqnum) == m_buf.end()) + if(m_buf.find(seqnum) == m_buf.end()) { IncomingSplitPacket *sp = new IncomingSplitPacket(); sp->chunk_count = chunk_count; @@ -468,11 +469,11 @@ SharedBuffer IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable) IncomingSplitPacket *sp = m_buf[seqnum]; // TODO: These errors should be thrown or something? Dunno. - if (chunk_count != sp->chunk_count) + if(chunk_count != sp->chunk_count) LOG(derr_con<<"Connection: WARNING: chunk_count="<chunk_count="<chunk_count <reliable) + if(reliable != sp->reliable) LOG(derr_con<<"Connection: WARNING: reliable="<reliable="<reliable < IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable) // If chunk already exists, ignore it. // Sometimes two identical packets may arrive when there is network // lag and the server re-sends stuff. - if (sp->chunks.find(chunk_num) != sp->chunks.end()) + if(sp->chunks.find(chunk_num) != sp->chunks.end()) return SharedBuffer(); // Cut chunk data out of packet @@ -492,7 +493,7 @@ SharedBuffer IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable) sp->chunks[chunk_num] = chunkdata; // If not all chunks are received, return empty buffer - if (sp->allReceived() == false) + if(sp->allReceived() == false) return SharedBuffer(); // Calculate total size @@ -532,10 +533,10 @@ void IncomingSplitBuffer::removeUnreliableTimedOuts(float dtime, float timeout) { IncomingSplitPacket *p = i->second; // Reliable ones are not removed by timeout - if (p->reliable == true) + if(p->reliable == true) continue; p->time += dtime; - if (p->time >= timeout) + if(p->time >= timeout) remove_queue.push_back(i->first); } } @@ -918,7 +919,7 @@ void Peer::RTTStatistics(float rtt, std::string profiler_id, m_rtt.max_rtt = rtt; /* do average calculation */ - if (m_rtt.avg_rtt < 0.0) + if(m_rtt.avg_rtt < 0.0) m_rtt.avg_rtt = rtt; else m_rtt.avg_rtt = m_rtt.avg_rtt * (num_samples/(num_samples-1)) + @@ -940,7 +941,7 @@ void Peer::RTTStatistics(float rtt, std::string profiler_id, if (jitter >= m_rtt.jitter_max) m_rtt.jitter_max = jitter; - if (m_rtt.jitter_avg < 0.0) + if(m_rtt.jitter_avg < 0.0) m_rtt.jitter_avg = jitter; else m_rtt.jitter_avg = m_rtt.jitter_avg * (num_samples/(num_samples-1)) + @@ -1026,9 +1027,9 @@ void UDPPeer::reportRTT(float rtt) RTTStatistics(rtt,"rudp",MAX_RELIABLE_WINDOW_SIZE*10); float timeout = getStat(AVG_RTT) * RESEND_TIMEOUT_FACTOR; - if (timeout < RESEND_TIMEOUT_MIN) + if(timeout < RESEND_TIMEOUT_MIN) timeout = RESEND_TIMEOUT_MIN; - if (timeout > RESEND_TIMEOUT_MAX) + if(timeout > RESEND_TIMEOUT_MAX) timeout = RESEND_TIMEOUT_MAX; JMutexAutoLock usage_lock(m_exclusive_access_mutex); @@ -1038,7 +1039,7 @@ void UDPPeer::reportRTT(float rtt) bool UDPPeer::Ping(float dtime,SharedBuffer& data) { m_ping_timer += dtime; - if (m_ping_timer >= PING_TIMEOUT) + if(m_ping_timer >= PING_TIMEOUT) { // Create and send PING packet writeU8(&data[0], TYPE_CONTROL); @@ -1058,19 +1059,22 @@ void UDPPeer::PutReliableSendCommand(ConnectionCommand &c, if ( channels[c.channelnum].queued_commands.empty() && /* don't queue more packets then window size */ (channels[c.channelnum].queued_reliables.size() - < (channels[c.channelnum].getWindowSize()/2))) { + < (channels[c.channelnum].getWindowSize()/2))) + { LOG(dout_con<getDesc() <<" processing reliable command for peer id: " << c.peer_id <<" data size: " << c.data.getSize() << std::endl); - if (!processReliableSendCommand(c,max_packet_size)) { - channels[c.channelnum].queued_commands.push(c); + if (!processReliableSendCommand(c,max_packet_size)) + { + channels[c.channelnum].queued_commands.push_back(c); } } - else { + else + { LOG(dout_con<getDesc() <<" Queueing reliable command for peer id: " << c.peer_id <<" data size: " << c.data.getSize() < toadd; + Queue toadd; volatile u16 initial_sequence_number = 0; for(std::list >::iterator i = originals.begin(); @@ -1126,20 +1130,19 @@ bool UDPPeer::processReliableSendCommand( m_connection->GetProtocolID(), m_connection->GetPeerID(), c.channelnum); - toadd.push(p); + toadd.push_back(p); } if (have_sequence_number) { volatile u16 pcount = 0; while(toadd.size() > 0) { - BufferedPacket p = toadd.front(); - toadd.pop(); + BufferedPacket p = toadd.pop_front(); // LOG(dout_con<getDesc() // << " queuing reliable packet for peer_id: " << c.peer_id // << " channel: " << (c.channelnum&0xFF) // << " seqnum: " << readU16(&p.data[BASE_HEADER_SIZE+1]) // << std::endl) - channels[c.channelnum].queued_reliables.push(p); + channels[c.channelnum].queued_reliables.push_back(p); pcount++; } assert(channels[c.channelnum].queued_reliables.size() < 0xFFFF); @@ -1154,7 +1157,7 @@ bool UDPPeer::processReliableSendCommand( } while(toadd.size() > 0) { /* remove packet */ - toadd.pop(); + toadd.pop_front(); bool successfully_put_back_sequence_number = channels[c.channelnum].putBackSequenceNumber( @@ -1191,8 +1194,7 @@ void UDPPeer::RunCommandQueues( (commands_processed < maxcommands)) { try { - ConnectionCommand c = channels[i].queued_commands.front(); - channels[i].queued_commands.pop(); + ConnectionCommand c = channels[i].queued_commands.pop_front(); LOG(dout_con<getDesc() <<" processing queued reliable command "<(&peer) == 0) + if(dynamic_cast(&peer) == 0) continue; PROFILE(std::stringstream peerIdentifier); @@ -1369,7 +1371,7 @@ void ConnectionSendThread::runTimeouts(float dtime) /* Check peer timeout */ - if (peer->isTimedOut(m_timeout)) + if(peer->isTimedOut(m_timeout)) { infostream<getDesc() <<"RunTimeouts(): Peer "<id @@ -1475,7 +1477,7 @@ void ConnectionSendThread::rawSend(const BufferedPacket &packet) LOG(dout_con <getDesc() << " rawSend: " << packet.data.getSize() << " bytes sent" << std::endl); - } catch(SendFailedException &e) { + } catch(SendFailedException &e){ LOG(derr_con<getDesc() <<"Connection::rawSend(): SendFailedException: " < data, bool reliable) { PeerHelper peer = m_connection->getPeerNoEx(peer_id); - if (!peer) { + if(!peer) { LOG(dout_con<getDesc() <<" INFO: dropped packet for non existent peer_id: " << peer_id << std::endl); @@ -1516,7 +1518,7 @@ bool ConnectionSendThread::rawSendAsPacket(u16 peer_id, u8 channelnum, } Channel *channel = &(dynamic_cast(&peer)->channels[channelnum]); - if (reliable) + if(reliable) { bool have_sequence_number_for_raw_packet = true; u16 seqnum = @@ -1549,7 +1551,7 @@ bool ConnectionSendThread::rawSendAsPacket(u16 peer_id, u8 channelnum, <<" INFO: queueing reliable packet for peer_id: " << peer_id <<" channel: " << channelnum <<" seqnum: " << seqnum << std::endl); - channel->queued_reliables.push(p); + channel->queued_reliables.push_back(p); return false; } } @@ -1584,7 +1586,7 @@ void ConnectionSendThread::processReliableCommand(ConnectionCommand &c) { assert(c.reliable); - switch(c.type) { + switch(c.type){ case CONNCMD_NONE: LOG(dout_con<getDesc() <<"UDP processing reliable CONNCMD_NONE"<getDesc() <<" UDP processing CONNCMD_NONE"<m_udpSocket.Bind(bind_address); m_connection->SetPeerID(PEER_ID_SERVER); } - catch(SocketException &e) { + catch(SocketException &e){ // Create event ConnectionEvent ce; ce.bindFailed(); @@ -1726,9 +1728,8 @@ void ConnectionSendThread::connect(Address address) // Send a dummy packet to server with peer_id = PEER_ID_INEXISTENT m_connection->SetPeerID(PEER_ID_INEXISTENT); - NetworkPacket* pkt = new NetworkPacket(0,0); - m_connection->Send(PEER_ID_SERVER, 0, pkt, true); - delete pkt; + SharedBuffer data(0); + m_connection->Send(PEER_ID_SERVER, 0, data, true); } void ConnectionSendThread::disconnect() @@ -1781,7 +1782,7 @@ void ConnectionSendThread::send(u16 peer_id, u8 channelnum, assert(channelnum < CHANNEL_COUNT); PeerHelper peer = m_connection->getPeerNoEx(peer_id); - if (!peer) + if(!peer) { LOG(dout_con<getDesc()<<" peer: peer_id="<>>NOT<<< found on sending packet" @@ -1918,8 +1919,7 @@ void ConnectionSendThread::sendPackets(float dtime) < dynamic_cast(&peer)->channels[i].getWindowSize())&& (peer->m_increment_packets_remaining > 0)) { - BufferedPacket p = dynamic_cast(&peer)->channels[i].queued_reliables.front(); - dynamic_cast(&peer)->channels[i].queued_reliables.pop(); + BufferedPacket p = dynamic_cast(&peer)->channels[i].queued_reliables.pop_front(); Channel* channel = &(dynamic_cast(&peer)->channels[i]); LOG(dout_con<getDesc() <<" INFO: sending a queued reliable packet " @@ -1942,14 +1942,13 @@ void ConnectionSendThread::sendPackets(float dtime) unsigned int initial_queuesize = m_outgoing_queue.size(); /* send non reliable packets*/ for(unsigned int i=0;i < initial_queuesize;i++) { - OutgoingPacket packet = m_outgoing_queue.front(); - m_outgoing_queue.pop(); + OutgoingPacket packet = m_outgoing_queue.pop_front(); - if (packet.reliable) - continue; + assert(!packet.reliable && + "reliable packets are not allowed in outgoing queue!"); PeerHelper peer = m_connection->getPeerNoEx(packet.peer_id); - if (!peer) { + if(!peer) { LOG(dout_con<getDesc() <<" Outgoing queue: peer_id="<>>NOT<<< found on sending packet" @@ -1967,13 +1966,13 @@ void ConnectionSendThread::sendPackets(float dtime) } else if ( ( peer->m_increment_packets_remaining > 0) || - (StopRequested())) { + (StopRequested())){ rawSendAsPacket(packet.peer_id, packet.channelnum, packet.data, packet.reliable); peer->m_increment_packets_remaining--; } else { - m_outgoing_queue.push(packet); + m_outgoing_queue.push_back(packet); pending_unreliable[packet.peer_id] = true; } } @@ -1993,7 +1992,7 @@ void ConnectionSendThread::sendAsPacket(u16 peer_id, u8 channelnum, SharedBuffer data, bool ack) { OutgoingPacket packet(peer_id, channelnum, data, false, ack); - m_outgoing_queue.push(packet); + m_outgoing_queue.push_back(packet); } ConnectionReceiveThread::ConnectionReceiveThread(unsigned int max_packet_size) : @@ -2108,149 +2107,152 @@ void ConnectionReceiveThread::receive() /* first of all read packets from socket */ /* check for incoming data available */ while( (loop_count < 10) && - (m_connection->m_udpSocket.WaitData(50))) { + (m_connection->m_udpSocket.WaitData(50))) + { loop_count++; - try { - if (packet_queued) { - bool data_left = true; - u16 peer_id; - SharedBuffer resultdata; - while(data_left) { - try { - data_left = getFromBuffers(peer_id, resultdata); - if (data_left) { - ConnectionEvent e; - e.dataReceived(peer_id, resultdata); - m_connection->putEvent(e); - } - } - catch(ProcessedSilentlyException &e) { - /* try reading again */ + try{ + if (packet_queued) + { + bool no_data_left = false; + u16 peer_id; + SharedBuffer resultdata; + while(!no_data_left) + { + try { + no_data_left = !getFromBuffers(peer_id, resultdata); + if (!no_data_left) { + ConnectionEvent e; + e.dataReceived(peer_id, resultdata); + m_connection->putEvent(e); } } - packet_queued = false; - } - - Address sender; - s32 received_size = m_connection->m_udpSocket.Receive(sender, *packetdata, packet_maxsize); - - if ((received_size < BASE_HEADER_SIZE) || - (readU32(&packetdata[0]) != m_connection->GetProtocolID())) - { - LOG(derr_con<getDesc() - <<"Receive(): Invalid incoming packet, " - <<"size: " << received_size - <<", protocol: " - << ((received_size >= 4) ? readU32(&packetdata[0]) : -1) - << std::endl); - continue; - } - - u16 peer_id = readPeerId(*packetdata); - u8 channelnum = readChannel(*packetdata); - - if (channelnum > CHANNEL_COUNT-1) { - LOG(derr_con<getDesc() - <<"Receive(): Invalid channel "<lookupPeer(sender); - } - - /* The peer was not found in our lists. Add it. */ - if (peer_id == PEER_ID_INEXISTENT) { - peer_id = m_connection->createPeer(sender, MTP_MINETEST_RELIABLE_UDP, 0); - } - - PeerHelper peer = m_connection->getPeerNoEx(peer_id); - - if (!peer) { - LOG(dout_con<getDesc() - <<" got packet from unknown peer_id: " - <getAddress(MTP_UDP, peer_address)) { - if (peer_address != sender) { - LOG(derr_con<getDesc() - <getDesc() - <<" Peer "<getDesc() - <getDesc() - <<" Peer "<m_udpSocket.Receive(sender, *packetdata, packet_maxsize); + if ((received_size < 0) || + (received_size < BASE_HEADER_SIZE) || + (readU32(&packetdata[0]) != m_connection->GetProtocolID())) + { + LOG(derr_con<getDesc() + <<"Receive(): Invalid incoming packet, " + <<"size: " << received_size + <<", protocol: " + << ((received_size >= 4) ? readU32(&packetdata[0]) : -1) + << std::endl); + continue; + } - /* mark peer as seen with id */ - if (!(packet_peer_id == PEER_ID_INEXISTENT)) - peer->setSentWithID(); + u16 peer_id = readPeerId(*packetdata); + u8 channelnum = readChannel(*packetdata); - peer->ResetTimeout(); + if(channelnum > CHANNEL_COUNT-1){ + LOG(derr_con<getDesc() + <<"Receive(): Invalid channel "<(&peer) != 0) - { - channel = &(dynamic_cast(&peer)->channels[channelnum]); - } + /* Try to identify peer by sender address (may happen on join) */ + if(peer_id == PEER_ID_INEXISTENT) + { + peer_id = m_connection->lookupPeer(sender); + } - if (channel != 0) { - channel->UpdateBytesReceived(received_size); - } + /* The peer was not found in our lists. Add it. */ + if(peer_id == PEER_ID_INEXISTENT) + { + peer_id = m_connection->createPeer(sender, MTP_MINETEST_RELIABLE_UDP, 0); + } - // Throw the received packet to channel->processPacket() + PeerHelper peer = m_connection->getPeerNoEx(peer_id); - // Make a new SharedBuffer from the data without the base headers - SharedBuffer strippeddata(received_size - BASE_HEADER_SIZE); - memcpy(*strippeddata, &packetdata[BASE_HEADER_SIZE], - strippeddata.getSize()); + if (!peer) { + LOG(dout_con<getDesc() + <<" got packet from unknown peer_id: " + < resultdata = processPacket - (channel, strippeddata, peer_id, channelnum, false); + // Validate peer address - LOG(dout_con<getDesc() - <<" ProcessPacket from peer_id: " << peer_id - << ",channel: " << (channelnum & 0xFF) << ", returned " - << resultdata.getSize() << " bytes" <putEvent(e); - } - catch(ProcessedSilentlyException &e) { - } - catch(ProcessedQueued &e) { - packet_queued = true; + if (peer->getAddress(MTP_UDP, peer_address)) { + if (peer_address != sender) { + LOG(derr_con<getDesc() + <getDesc() + <<" Peer "<getDesc() + <getDesc() + <<" Peer "<setSentWithID(); + + peer->ResetTimeout(); + + Channel *channel = 0; + + if (dynamic_cast(&peer) != 0) + { + channel = &(dynamic_cast(&peer)->channels[channelnum]); } + + if (channel != 0) { + channel->UpdateBytesReceived(received_size); + } + + // Throw the received packet to channel->processPacket() + + // Make a new SharedBuffer from the data without the base headers + SharedBuffer strippeddata(received_size - BASE_HEADER_SIZE); + memcpy(*strippeddata, &packetdata[BASE_HEADER_SIZE], + strippeddata.getSize()); + + try{ + // Process it (the result is some data with no headers made by us) + SharedBuffer resultdata = processPacket + (channel, strippeddata, peer_id, channelnum, false); + + LOG(dout_con<getDesc() + <<" ProcessPacket from peer_id: " << peer_id + << ",channel: " << (channelnum & 0xFF) << ", returned " + << resultdata.getSize() << " bytes" <putEvent(e); + }catch(ProcessedSilentlyException &e){ + }catch(ProcessedQueued &e){ + packet_queued = true; + } + }catch(InvalidIncomingDataException &e){ + } + catch(ProcessedSilentlyException &e){ + } } } @@ -2265,14 +2267,17 @@ bool ConnectionReceiveThread::getFromBuffers(u16 &peer_id, SharedBuffer &dst if (!peer) continue; - if (dynamic_cast(&peer) == 0) + if(dynamic_cast(&peer) == 0) continue; for(u16 i=0; i(&peer))->channels[i]; - if (checkIncomingBuffers(channel, peer_id, dst)) { + SharedBuffer resultdata; + bool got = checkIncomingBuffers(channel, peer_id, resultdata); + if(got){ + dst = resultdata; return true; } } @@ -2286,7 +2291,7 @@ bool ConnectionReceiveThread::checkIncomingBuffers(Channel *channel, u16 firstseqnum = 0; if (channel->incoming_reliables.getFirstSeqnum(firstseqnum)) { - if (firstseqnum == channel->readNextIncomingSeqNum()) + if(firstseqnum == channel->readNextIncomingSeqNum()) { BufferedPacket p = channel->incoming_reliables.popFirst(); peer_id = readPeerId(*p.data); @@ -2324,7 +2329,7 @@ SharedBuffer ConnectionReceiveThread::processPacket(Channel *channel, throw ProcessedSilentlyException("Peer not found (possible timeout)"); } - if (packetdata.getSize() < 1) + if(packetdata.getSize() < 1) throw InvalidIncomingDataException("packetdata.getSize() < 1"); u8 type = readU8(&(packetdata[0])); @@ -2334,17 +2339,17 @@ SharedBuffer ConnectionReceiveThread::processPacket(Channel *channel, assert(0); } - if (type == TYPE_CONTROL) + if(type == TYPE_CONTROL) { - if (packetdata.getSize() < 2) + if(packetdata.getSize() < 2) throw InvalidIncomingDataException("packetdata.getSize() < 2"); u8 controltype = readU8(&(packetdata[1])); - if (controltype == CONTROLTYPE_ACK) + if(controltype == CONTROLTYPE_ACK) { assert(channel != 0); - if (packetdata.getSize() < 4) + if(packetdata.getSize() < 4) throw InvalidIncomingDataException ("packetdata.getSize() < 4 (ACK header size)"); @@ -2389,7 +2394,7 @@ SharedBuffer ConnectionReceiveThread::processPacket(Channel *channel, m_connection->TriggerSend(); } } - catch(NotFoundException &e) { + catch(NotFoundException &e){ LOG(derr_con<getDesc() <<"WARNING: ACKed packet not " "in outgoing queue" @@ -2398,16 +2403,17 @@ SharedBuffer ConnectionReceiveThread::processPacket(Channel *channel, } throw ProcessedSilentlyException("Got an ACK"); } - else if (controltype == CONTROLTYPE_SET_PEER_ID) { + else if(controltype == CONTROLTYPE_SET_PEER_ID) + { // Got a packet to set our peer id - if (packetdata.getSize() < 4) + if(packetdata.getSize() < 4) throw InvalidIncomingDataException ("packetdata.getSize() < 4 (SET_PEER_ID header size)"); u16 peer_id_new = readU16(&packetdata[2]); LOG(dout_con<getDesc() <<"Got new peer id: "<GetPeerID() != PEER_ID_INEXISTENT) + if(m_connection->GetPeerID() != PEER_ID_INEXISTENT) { LOG(derr_con<getDesc() <<"WARNING: Not changing" @@ -2429,21 +2435,21 @@ SharedBuffer ConnectionReceiveThread::processPacket(Channel *channel, throw ProcessedSilentlyException("Got a SET_PEER_ID"); } - else if (controltype == CONTROLTYPE_PING) + else if(controltype == CONTROLTYPE_PING) { // Just ignore it, the incoming data already reset // the timeout counter LOG(dout_con<getDesc()<<"PING"<getDesc() <<"DISCO: Removing peer "<<(peer_id)<deletePeer(peer_id, false) == false) + if(m_connection->deletePeer(peer_id, false) == false) { derr_con<getDesc() <<"DISCO: Peer not found"< ConnectionReceiveThread::processPacket(Channel *channel, throw ProcessedSilentlyException("Got a DISCO"); } - else if (controltype == CONTROLTYPE_ENABLE_BIG_SEND_WINDOW) + else if(controltype == CONTROLTYPE_ENABLE_BIG_SEND_WINDOW) { dynamic_cast(&peer)->setNonLegacyPeer(); throw ProcessedSilentlyException("Got non legacy control"); @@ -2463,9 +2469,9 @@ SharedBuffer ConnectionReceiveThread::processPacket(Channel *channel, throw InvalidIncomingDataException("Invalid control type"); } } - else if (type == TYPE_ORIGINAL) + else if(type == TYPE_ORIGINAL) { - if (packetdata.getSize() <= ORIGINAL_HEADER_SIZE) + if(packetdata.getSize() <= ORIGINAL_HEADER_SIZE) throw InvalidIncomingDataException ("packetdata.getSize() <= ORIGINAL_HEADER_SIZE"); LOG(dout_con<getDesc() @@ -2476,7 +2482,7 @@ SharedBuffer ConnectionReceiveThread::processPacket(Channel *channel, memcpy(*payload, &(packetdata[ORIGINAL_HEADER_SIZE]), payload.getSize()); return payload; } - else if (type == TYPE_SPLIT) + else if(type == TYPE_SPLIT) { Address peer_address; @@ -2495,7 +2501,7 @@ SharedBuffer ConnectionReceiveThread::processPacket(Channel *channel, SharedBuffer data = peer->addSpiltPacket(channelnum,packet,reliable); - if (data.getSize() != 0) + if(data.getSize() != 0) { LOG(dout_con<getDesc() <<"RETURNING TYPE_SPLIT: Constructed full data, " @@ -2509,14 +2515,14 @@ SharedBuffer ConnectionReceiveThread::processPacket(Channel *channel, //TODO throw some error } } - else if (type == TYPE_RELIABLE) + else if(type == TYPE_RELIABLE) { assert(channel != 0); // Recursive reliable packets not allowed - if (reliable) + if(reliable) throw InvalidIncomingDataException("Found nested reliable packets"); - if (packetdata.getSize() < RELIABLE_HEADER_SIZE) + if(packetdata.getSize() < RELIABLE_HEADER_SIZE) throw InvalidIncomingDataException ("packetdata.getSize() < RELIABLE_HEADER_SIZE"); @@ -2733,7 +2739,7 @@ PeerHelper Connection::getPeer(u16 peer_id) JMutexAutoLock peerlock(m_peers_mutex); std::map::iterator node = m_peers.find(peer_id); - if (node == m_peers.end()) { + if(node == m_peers.end()){ throw PeerNotFoundException("GetPeer: Peer not found (possible timeout)"); } @@ -2748,7 +2754,7 @@ PeerHelper Connection::getPeerNoEx(u16 peer_id) JMutexAutoLock peerlock(m_peers_mutex); std::map::iterator node = m_peers.find(peer_id); - if (node == m_peers.end()) { + if(node == m_peers.end()){ return PeerHelper(NULL); } @@ -2767,7 +2773,7 @@ u16 Connection::lookupPeer(Address& sender) for(; j != m_peers.end(); ++j) { Peer *peer = j->second; - if (peer->isActive()) + if(peer->isActive()) continue; Address tocheck; @@ -2801,11 +2807,10 @@ bool Connection::deletePeer(u16 peer_id, bool timeout) /* lock list as short as possible */ { JMutexAutoLock peerlock(m_peers_mutex); - if (m_peers.find(peer_id) == m_peers.end()) + if(m_peers.find(peer_id) == m_peers.end()) return false; peer = m_peers[peer_id]; m_peers.erase(peer_id); - m_peer_ids.remove(peer_id); } Address peer_address; @@ -2825,7 +2830,7 @@ bool Connection::deletePeer(u16 peer_id, bool timeout) ConnectionEvent Connection::getEvent() { - if (m_event_queue.empty()) { + if(m_event_queue.empty()){ ConnectionEvent e; e.type = CONNEVENT_NONE; return e; @@ -2835,9 +2840,9 @@ ConnectionEvent Connection::getEvent() ConnectionEvent Connection::waitEvent(u32 timeout_ms) { - try { + try{ return m_event_queue.pop_front(timeout_ms); - } catch(ItemNotFoundException &ex) { + } catch(ItemNotFoundException &ex){ ConnectionEvent e; e.type = CONNEVENT_NONE; return e; @@ -2846,7 +2851,8 @@ ConnectionEvent Connection::waitEvent(u32 timeout_ms) void Connection::putCommand(ConnectionCommand &c) { - if (!m_shutting_down) { + if (!m_shutting_down) + { m_command_queue.push_back(c); m_sendThread.Trigger(); } @@ -2870,14 +2876,14 @@ bool Connection::Connected() { JMutexAutoLock peerlock(m_peers_mutex); - if (m_peers.size() != 1) + if(m_peers.size() != 1) return false; std::map::iterator node = m_peers.find(PEER_ID_SERVER); - if (node == m_peers.end()) + if(node == m_peers.end()) return false; - if (m_peer_id == PEER_ID_INEXISTENT) + if(m_peer_id == PEER_ID_INEXISTENT) return false; return true; @@ -2892,12 +2898,12 @@ void Connection::Disconnect() u32 Connection::Receive(u16 &peer_id, SharedBuffer &data) { - for(;;) { + for(;;){ ConnectionEvent e = waitEvent(m_bc_receive_timeout); - if (e.type != CONNEVENT_NONE) + if(e.type != CONNEVENT_NONE) LOG(dout_con< &data) return e.data.getSize(); case CONNEVENT_PEER_ADDED: { UDPPeer tmp(e.peer_id, e.address, this); - if (m_bc_peerhandler) + if(m_bc_peerhandler) m_bc_peerhandler->peerAdded(&tmp); continue; } case CONNEVENT_PEER_REMOVED: { UDPPeer tmp(e.peer_id, e.address, this); - if (m_bc_peerhandler) + if(m_bc_peerhandler) m_bc_peerhandler->deletingPeer(&tmp, e.timeout); continue; } case CONNEVENT_BIND_FAILED: @@ -2922,14 +2928,22 @@ u32 Connection::Receive(u16 &peer_id, SharedBuffer &data) throw NoIncomingDataException("No incoming data"); } -void Connection::Send(u16 peer_id, u8 channelnum, - NetworkPacket* pkt, bool reliable) +void Connection::SendToAll(u8 channelnum, SharedBuffer data, bool reliable) { assert(channelnum < CHANNEL_COUNT); ConnectionCommand c; + c.sendToAll(channelnum, data, reliable); + putCommand(c); +} - c.send(peer_id, channelnum, pkt->oldForgePacket(), reliable); +void Connection::Send(u16 peer_id, u8 channelnum, + SharedBuffer data, bool reliable) +{ + assert(channelnum < CHANNEL_COUNT); + + ConnectionCommand c; + c.send(peer_id, channelnum, data, reliable); putCommand(c); } @@ -2999,37 +3013,37 @@ u16 Connection::createPeer(Address& sender, MTProtocols protocol, int fd) /* Find an unused peer id */ + { JMutexAutoLock lock(m_peers_mutex); - bool out_of_ids = false; - for(;;) { - // Check if exists - if (m_peers.find(peer_id_new) == m_peers.end()) - - break; - // Check for overflow - if (peer_id_new == overflow) { - out_of_ids = true; - break; + bool out_of_ids = false; + for(;;) + { + // Check if exists + if(m_peers.find(peer_id_new) == m_peers.end()) + break; + // Check for overflow + if(peer_id_new == overflow){ + out_of_ids = true; + break; + } + peer_id_new++; } - peer_id_new++; + if(out_of_ids){ + errorstream<id] = peer; } - if (out_of_ids) { - errorstream << getDesc() << " ran out of peer ids" << std::endl; - return PEER_ID_INEXISTENT; - } + m_next_remote_peer_id = (peer_id_new +1) % MAX_UDP_PEERS; - // Create a peer - Peer *peer = 0; - peer = new UDPPeer(peer_id_new, sender, this); - - m_peers[peer->id] = peer; - m_peer_ids.push_back(peer->id); - - m_next_remote_peer_id = (peer_id_new +1 ) % MAX_UDP_PEERS; - - LOG(dout_con << getDesc() - << "createPeer(): giving peer_id=" << peer_id_new << std::endl); + LOG(dout_con< base) { - if ((totest - base) > (SEQNUM_MAX/2)) + if((totest - base) > (SEQNUM_MAX/2)) return false; else return true; } else { - if ((base - totest) > (SEQNUM_MAX/2)) + if((base - totest) > (SEQNUM_MAX/2)) return true; else return false; @@ -363,9 +362,9 @@ public: packet is constructed. If not, returns one of length 0. */ SharedBuffer insert(BufferedPacket &p, bool reliable); - + void removeUnreliableTimedOuts(float dtime, float timeout); - + private: // Key is seqnum std::map m_buf; @@ -496,7 +495,7 @@ public: u16 readNextSplitSeqNum(); void setNextSplitSeqNum(u16 seqnum); - + // This is for buffering the incoming packets that are coming in // the wrong order ReliablePacketBuffer incoming_reliables; @@ -505,10 +504,10 @@ public: ReliablePacketBuffer outgoing_reliables_sent; //queued reliable packets - std::queue queued_reliables; + Queue queued_reliables; //queue commands prior splitting to packets - std::queue queued_commands; + Queue queued_commands; IncomingSplitBuffer incoming_splits; @@ -874,7 +873,7 @@ struct ConnectionEvent std::string describe() { - switch(type) { + switch(type){ case CONNEVENT_NONE: return "CONNEVENT_NONE"; case CONNEVENT_DATA_RECEIVED: @@ -888,7 +887,7 @@ struct ConnectionEvent } return "Invalid ConnectionEvent"; } - + void dataReceived(u16 peer_id_, SharedBuffer data_) { type = CONNEVENT_DATA_RECEIVED; @@ -964,7 +963,7 @@ private: Connection* m_connection; unsigned int m_max_packet_size; float m_timeout; - std::queue m_outgoing_queue; + Queue m_outgoing_queue; JSemaphore m_send_sleep_semaphore; unsigned int m_iteration_packets_avaialble; @@ -1026,15 +1025,16 @@ public: ConnectionEvent getEvent(); ConnectionEvent waitEvent(u32 timeout_ms); void putCommand(ConnectionCommand &c); - - void SetTimeoutMs(int timeout) { m_bc_receive_timeout = timeout; } + + void SetTimeoutMs(int timeout){ m_bc_receive_timeout = timeout; } void Serve(Address bind_addr); void Connect(Address address); bool Connected(); void Disconnect(); u32 Receive(u16 &peer_id, SharedBuffer &data); - void Send(u16 peer_id, u8 channelnum, NetworkPacket* pkt, bool reliable); - u16 GetPeerID() { return m_peer_id; } + void SendToAll(u8 channelnum, SharedBuffer data, bool reliable); + void Send(u16 peer_id, u8 channelnum, SharedBuffer data, bool reliable); + u16 GetPeerID(){ return m_peer_id; } Address GetPeerAddress(u16 peer_id); float getPeerStat(u16 peer_id, rtt_stat_type type); float getLocalStat(rate_stat_type type); @@ -1051,14 +1051,14 @@ protected: UDPPeer* createServerPeer(Address& sender); bool deletePeer(u16 peer_id, bool timeout); - void SetPeerID(u16 id) { m_peer_id = id; } + void SetPeerID(u16 id){ m_peer_id = id; } void sendAck(u16 peer_id, u8 channelnum, u16 seqnum); void PrintInfo(std::ostream &out); void PrintInfo(); - std::list getPeerIDs() { return m_peer_ids; } + std::list getPeerIDs(); UDPSocket m_udpSocket; MutexedQueue m_command_queue; @@ -1074,9 +1074,8 @@ private: u16 m_peer_id; u32 m_protocol_id; - + std::map m_peers; - std::list m_peer_ids; JMutex m_peers_mutex; ConnectionSendThread m_sendThread; @@ -1096,3 +1095,4 @@ private: } // namespace #endif + diff --git a/src/constants.h b/src/constants.h index d7163bf68..9a7bb9d86 100644 --- a/src/constants.h +++ b/src/constants.h @@ -100,13 +100,7 @@ with this program; if not, write to the Free Software Foundation, Inc., /* GUI related things */ - -// TODO: implement dpi-based scaling for windows and remove this hack -#if defined(_WIN32) - #define TTF_DEFAULT_FONT_SIZE (18) -#else - #define TTF_DEFAULT_FONT_SIZE (15) -#endif +#define TTF_DEFAULT_FONT_SIZE (14) #define DEFAULT_FONT_SIZE (10) #endif diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 5c3c7b54c..6d41b2749 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -27,13 +27,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/numeric.h" // For IntervalLimiter #include "util/serialize.h" #include "util/mathconstants.h" -#include "client/tile.h" +#include "tile.h" #include "environment.h" #include "collision.h" #include "settings.h" #include "serialization.h" // For decompressZlib #include "gamedef.h" #include "clientobject.h" +#include "content_object.h" #include "mesh.h" #include "itemdef.h" #include "tool.h" @@ -144,7 +145,7 @@ public: TestCAO(IGameDef *gamedef, ClientEnvironment *env); virtual ~TestCAO(); - ActiveObjectType getType() const + u8 getType() const { return ACTIVEOBJECT_TYPE_TEST; } @@ -288,7 +289,7 @@ public: ItemCAO(IGameDef *gamedef, ClientEnvironment *env); virtual ~ItemCAO(); - ActiveObjectType getType() const + u8 getType() const { return ACTIVEOBJECT_TYPE_ITEM; } @@ -962,7 +963,7 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, // Add a text node for showing the name gui::IGUIEnvironment* gui = irr->getGUIEnvironment(); std::wstring wname = narrow_to_wide(m_name); - m_textnode = smgr->addTextSceneNode(gui->getSkin()->getFont(), + m_textnode = smgr->addTextSceneNode(gui->getBuiltInFont(), wname.c_str(), video::SColor(255,255,255,255), node); m_textnode->grab(); m_textnode->setPosition(v3f(0, BS*1.1, 0)); diff --git a/src/content_cao.h b/src/content_cao.h index 31ccd04d4..69e2e54a2 100644 --- a/src/content_cao.h +++ b/src/content_cao.h @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "irrlichttypes_extrabloated.h" +#include "content_object.h" #include "clientobject.h" #include "object_properties.h" #include "itemgroup.h" @@ -114,7 +115,7 @@ public: return new GenericCAO(gamedef, env); } - inline ActiveObjectType getType() const + inline u8 getType() const { return ACTIVEOBJECT_TYPE_GENERIC; } diff --git a/src/content_cso.cpp b/src/content_cso.cpp index c337472ff..4779b20d1 100644 --- a/src/content_cso.cpp +++ b/src/content_cso.cpp @@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_cso.h" #include -#include "client/tile.h" +#include "tile.h" #include "environment.h" #include "gamedef.h" #include "log.h" diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index 3428f85f9..9af3be789 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapblock_mesh.h" // For MapBlock_LightColor() and MeshCollector #include "settings.h" #include "nodedef.h" -#include "client/tile.h" +#include "tile.h" #include "mesh.h" #include #include "gamedef.h" @@ -45,7 +45,8 @@ with this program; if not, write to the Free Software Foundation, Inc., // (compatible with ContentFeatures). If you specified 0,0,1,1 // for each face, that would be the same as passing NULL. void makeCuboid(MeshCollector *collector, const aabb3f &box, - TileSpec *tiles, int tilecount, video::SColor &c, const f32* txc) + TileSpec *tiles, int tilecount, + video::SColor &c, const f32* txc) { assert(tilecount >= 1 && tilecount <= 6); @@ -54,7 +55,8 @@ void makeCuboid(MeshCollector *collector, const aabb3f &box, - if(txc == NULL) { + if(txc == NULL) + { static const f32 txc_default[24] = { 0,0,1,1, 0,0,1,1, @@ -158,16 +160,14 @@ void makeCuboid(MeshCollector *collector, const aabb3f &box, } u16 indices[] = {0,1,2,2,3,0}; // Add to mesh collector - for (s32 j = 0; j < 24; j += 4) { - int tileindex = MYMIN(j / 4, tilecount - 1); - collector->append(tiles[tileindex], vertices + j, 4, indices, 6); + for(s32 j=0; j<24; j+=4) + { + int tileindex = MYMIN(j/4, tilecount-1); + collector->append(tiles[tileindex], + vertices+j, 4, indices, 6); } } -/* - TODO: Fix alpha blending for special nodes - Currently only the last element rendered is blended correct -*/ void mapblock_mesh_generate_special(MeshMakeData *data, MeshCollector &collector) { @@ -191,6 +191,54 @@ void mapblock_mesh_generate_special(MeshMakeData *data, v3s16 blockpos_nodes = data->m_blockpos*MAP_BLOCKSIZE; + // Create selection mesh + v3s16 p = data->m_highlighted_pos_relative; + if (data->m_show_hud && + (p.X >= 0) && (p.X < MAP_BLOCKSIZE) && + (p.Y >= 0) && (p.Y < MAP_BLOCKSIZE) && + (p.Z >= 0) && (p.Z < MAP_BLOCKSIZE)) { + + MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + p); + if(n.getContent() != CONTENT_AIR) { + // Get selection mesh light level + static const v3s16 dirs[7] = { + v3s16( 0, 0, 0), + v3s16( 0, 1, 0), + v3s16( 0,-1, 0), + v3s16( 1, 0, 0), + v3s16(-1, 0, 0), + v3s16( 0, 0, 1), + v3s16( 0, 0,-1) + }; + + u16 l = 0; + u16 l1 = 0; + for (u8 i = 0; i < 7; i++) { + MapNode n1 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p + dirs[i]); + l1 = getInteriorLight(n1, -4, nodedef); + if (l1 > l) + l = l1; + } + video::SColor c = MapBlock_LightColor(255, l, 0); + data->m_highlight_mesh_color = c; + std::vector boxes = n.getSelectionBoxes(nodedef); + TileSpec h_tile; + h_tile.material_flags |= MATERIAL_FLAG_HIGHLIGHTED; + h_tile.texture = tsrc->getTexture("halo.png",&h_tile.texture_id); + v3f pos = intToFloat(p, BS); + f32 d = 0.05 * BS; + for(std::vector::iterator + i = boxes.begin(); + i != boxes.end(); i++) + { + aabb3f box = *i; + box.MinEdge += v3f(-d, -d, -d) + pos; + box.MaxEdge += v3f(d, d, d) + pos; + makeCuboid(&collector, box, &h_tile, 1, c, NULL); + } + } + } + for(s16 z = 0; z < MAP_BLOCKSIZE; z++) for(s16 y = 0; y < MAP_BLOCKSIZE; y++) for(s16 x = 0; x < MAP_BLOCKSIZE; x++) @@ -1421,65 +1469,77 @@ void mapblock_mesh_generate_special(MeshMakeData *data, content_t thiscontent = n.getContent(); std::string groupname = "connect_to_raillike"; // name of the group that enables connecting to raillike nodes of different kind - int self_group = ((ItemGroupList) nodedef->get(n).groups)[groupname]; + bool self_connect_to_raillike = ((ItemGroupList) nodedef->get(n).groups)[groupname] != 0; if ((nodedef->get(n_minus_x).drawtype == NDT_RAILLIKE - && ((ItemGroupList) nodedef->get(n_minus_x).groups)[groupname] != self_group) + && ((ItemGroupList) nodedef->get(n_minus_x).groups)[groupname] != 0 + && self_connect_to_raillike) || n_minus_x.getContent() == thiscontent) is_rail_x[0] = true; if ((nodedef->get(n_minus_x_minus_y).drawtype == NDT_RAILLIKE - && ((ItemGroupList) nodedef->get(n_minus_x_minus_y).groups)[groupname] != self_group) + && ((ItemGroupList) nodedef->get(n_minus_x_minus_y).groups)[groupname] != 0 + && self_connect_to_raillike) || n_minus_x_minus_y.getContent() == thiscontent) is_rail_x_minus_y[0] = true; if ((nodedef->get(n_minus_x_plus_y).drawtype == NDT_RAILLIKE - && ((ItemGroupList) nodedef->get(n_minus_x_plus_y).groups)[groupname] != self_group) + && ((ItemGroupList) nodedef->get(n_minus_x_plus_y).groups)[groupname] != 0 + && self_connect_to_raillike) || n_minus_x_plus_y.getContent() == thiscontent) is_rail_x_plus_y[0] = true; if ((nodedef->get(n_plus_x).drawtype == NDT_RAILLIKE - && ((ItemGroupList) nodedef->get(n_plus_x).groups)[groupname] != self_group) + && ((ItemGroupList) nodedef->get(n_plus_x).groups)[groupname] != 0 + && self_connect_to_raillike) || n_plus_x.getContent() == thiscontent) is_rail_x[1] = true; if ((nodedef->get(n_plus_x_minus_y).drawtype == NDT_RAILLIKE - && ((ItemGroupList) nodedef->get(n_plus_x_minus_y).groups)[groupname] != self_group) + && ((ItemGroupList) nodedef->get(n_plus_x_minus_y).groups)[groupname] != 0 + && self_connect_to_raillike) || n_plus_x_minus_y.getContent() == thiscontent) is_rail_x_minus_y[1] = true; if ((nodedef->get(n_plus_x_plus_y).drawtype == NDT_RAILLIKE - && ((ItemGroupList) nodedef->get(n_plus_x_plus_y).groups)[groupname] != self_group) + && ((ItemGroupList) nodedef->get(n_plus_x_plus_y).groups)[groupname] != 0 + && self_connect_to_raillike) || n_plus_x_plus_y.getContent() == thiscontent) is_rail_x_plus_y[1] = true; if ((nodedef->get(n_minus_z).drawtype == NDT_RAILLIKE - && ((ItemGroupList) nodedef->get(n_minus_z).groups)[groupname] != self_group) + && ((ItemGroupList) nodedef->get(n_minus_z).groups)[groupname] != 0 + && self_connect_to_raillike) || n_minus_z.getContent() == thiscontent) is_rail_z[0] = true; if ((nodedef->get(n_minus_z_minus_y).drawtype == NDT_RAILLIKE - && ((ItemGroupList) nodedef->get(n_minus_z_minus_y).groups)[groupname] != self_group) + && ((ItemGroupList) nodedef->get(n_minus_z_minus_y).groups)[groupname] != 0 + && self_connect_to_raillike) || n_minus_z_minus_y.getContent() == thiscontent) is_rail_z_minus_y[0] = true; if ((nodedef->get(n_minus_z_plus_y).drawtype == NDT_RAILLIKE - && ((ItemGroupList) nodedef->get(n_minus_z_plus_y).groups)[groupname] != self_group) + && ((ItemGroupList) nodedef->get(n_minus_z_plus_y).groups)[groupname] != 0 + && self_connect_to_raillike) || n_minus_z_plus_y.getContent() == thiscontent) is_rail_z_plus_y[0] = true; if ((nodedef->get(n_plus_z).drawtype == NDT_RAILLIKE - && ((ItemGroupList) nodedef->get(n_plus_z).groups)[groupname] != self_group) + && ((ItemGroupList) nodedef->get(n_plus_z).groups)[groupname] != 0 + && self_connect_to_raillike) || n_plus_z.getContent() == thiscontent) is_rail_z[1] = true; if ((nodedef->get(n_plus_z_minus_y).drawtype == NDT_RAILLIKE - && ((ItemGroupList) nodedef->get(n_plus_z_minus_y).groups)[groupname] != self_group) + && ((ItemGroupList) nodedef->get(n_plus_z_minus_y).groups)[groupname] != 0 + && self_connect_to_raillike) || n_plus_z_minus_y.getContent() == thiscontent) is_rail_z_minus_y[1] = true; if ((nodedef->get(n_plus_z_plus_y).drawtype == NDT_RAILLIKE - && ((ItemGroupList) nodedef->get(n_plus_z_plus_y).groups)[groupname] != self_group) + && ((ItemGroupList) nodedef->get(n_plus_z_plus_y).groups)[groupname] != 0 + && self_connect_to_raillike) || n_plus_z_plus_y.getContent() == thiscontent) is_rail_z_plus_y[1] = true; @@ -1706,55 +1766,5 @@ void mapblock_mesh_generate_special(MeshMakeData *data, break;} } } - - /* - Caused by incorrect alpha blending, selection mesh needs to be created as - last element to ensure it gets blended correct over nodes with alpha channel - */ - // Create selection mesh - v3s16 p = data->m_highlighted_pos_relative; - if (data->m_show_hud && - (p.X >= 0) && (p.X < MAP_BLOCKSIZE) && - (p.Y >= 0) && (p.Y < MAP_BLOCKSIZE) && - (p.Z >= 0) && (p.Z < MAP_BLOCKSIZE)) { - - MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + p); - if(n.getContent() != CONTENT_AIR) { - // Get selection mesh light level - static const v3s16 dirs[7] = { - v3s16( 0, 0, 0), - v3s16( 0, 1, 0), - v3s16( 0,-1, 0), - v3s16( 1, 0, 0), - v3s16(-1, 0, 0), - v3s16( 0, 0, 1), - v3s16( 0, 0,-1) - }; - - u16 l = 0; - u16 l1 = 0; - for (u8 i = 0; i < 7; i++) { - MapNode n1 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p + dirs[i]); - l1 = getInteriorLight(n1, -4, nodedef); - if (l1 > l) - l = l1; - } - video::SColor c = MapBlock_LightColor(255, l, 0); - data->m_highlight_mesh_color = c; - std::vector boxes = n.getSelectionBoxes(nodedef); - TileSpec h_tile; - h_tile.material_flags |= MATERIAL_FLAG_HIGHLIGHTED; - h_tile.texture = tsrc->getTexture("halo.png",&h_tile.texture_id); - v3f pos = intToFloat(p, BS); - f32 d = 0.05 * BS; - for (std::vector::iterator i = boxes.begin(); - i != boxes.end(); i++) { - aabb3f box = *i; - box.MinEdge += v3f(-d, -d, -d) + pos; - box.MaxEdge += v3f(d, d, d) + pos; - makeCuboid(&collector, box, &h_tile, 1, c, NULL); - } - } - } } diff --git a/src/gameparams.h b/src/content_object.h similarity index 63% rename from src/gameparams.h rename to src/content_object.h index b50e943d2..65a829773 100644 --- a/src/gameparams.h +++ b/src/content_object.h @@ -17,17 +17,23 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __GAME_PARAMS_H__ -#define __GAME_PARAMS_H__ +#ifndef CONTENT_OBJECT_HEADER +#define CONTENT_OBJECT_HEADER -#include "irrlichttypes_extrabloated.h" +#define ACTIVEOBJECT_TYPE_TEST 1 +#define ACTIVEOBJECT_TYPE_ITEM 2 +#define ACTIVEOBJECT_TYPE_RAT 3 +#define ACTIVEOBJECT_TYPE_OERKKI1 4 +#define ACTIVEOBJECT_TYPE_FIREFLY 5 +#define ACTIVEOBJECT_TYPE_MOBV2 6 -struct GameParams { - u16 socket_port; - std::string world_path; - SubgameSpec game_spec; - bool is_dedicated_server; - int log_level; -}; +#define ACTIVEOBJECT_TYPE_LUAENTITY 7 + +// Special type, not stored as a static object +#define ACTIVEOBJECT_TYPE_PLAYER 100 + +// Special type, only exists as CAO +#define ACTIVEOBJECT_TYPE_GENERIC 101 #endif + diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 9b2e41677..d4b3079ec 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -29,13 +29,60 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "tool.h" // For ToolCapabilities #include "gamedef.h" #include "player.h" -#include "server.h" #include "scripting_game.h" #include "genericobject.h" #include "log.h" std::map ServerActiveObject::m_types; +/* + DummyLoadSAO +*/ + +class DummyLoadSAO : public ServerActiveObject +{ +public: + DummyLoadSAO(ServerEnvironment *env, v3f pos, u8 type): + ServerActiveObject(env, pos) + { + ServerActiveObject::registerType(type, create); + } + // Pretend to be the test object (to fool the client) + u8 getType() const + { return ACTIVEOBJECT_TYPE_TEST; } + // And never save to disk + bool isStaticAllowed() const + { return false; } + + static ServerActiveObject* create(ServerEnvironment *env, v3f pos, + const std::string &data) + { + return new DummyLoadSAO(env, pos, 0); + } + + void step(float dtime, bool send_recommended) + { + m_removed = true; + infostream<<"DummyLoadSAO step"< box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.); + collisionMoveResult moveresult; + // Apply gravity + m_speed_f += v3f(0, -dtime*9.81*BS, 0); + // Maximum movement without glitches + f32 pos_max_d = BS*0.25; + // Limit speed + if(m_speed_f.getLength()*dtime > pos_max_d) + m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime); + v3f pos_f = getBasePosition(); + v3f accel_f = v3f(0,0,0); + f32 stepheight = 0; + moveresult = collisionMoveSimple(m_env,m_env->getGameDef(), + pos_max_d, box, stepheight, dtime, + pos_f, m_speed_f, accel_f); + + if(send_recommended == false) + return; + + if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS) + { + setBasePosition(pos_f); + m_last_sent_position = pos_f; + + std::ostringstream os(std::ios::binary); + // command (0 = update position) + writeU8(os, 0); + // pos + writeV3F1000(os, m_base_position); + // create message and add to list + ActiveObjectMessage aom(getId(), false, os.str()); + m_messages_out.push_back(aom); + } + if(m_itemstring_changed) + { + m_itemstring_changed = false; + + std::ostringstream os(std::ios::binary); + // command (1 = update itemstring) + writeU8(os, 1); + // itemstring + os<getGameDef()->idef(); + ItemStack item; + item.deSerialize(m_itemstring, idef); + infostream<<__FUNCTION_NAME<<": m_itemstring=\""< item=\""<getInventory(); + if(inv != NULL) + { + std::string wieldlist = puncher->getWieldList(); + ItemStack leftover = inv->addItem(wieldlist, item); + puncher->setInventoryModified(); + if(leftover.empty()) + { + m_removed = true; + } + else + { + m_itemstring = leftover.getItemString(); + m_itemstring_changed = true; + } + } + + return 0; + } + + bool getCollisionBox(aabb3f *toset) { + return false; + } + + bool collideWithObjects() { + return false; + } + +private: + std::string m_itemstring; + bool m_itemstring_changed; + v3f m_speed_f; + v3f m_last_sent_position; + IntervalLimiter m_move_interval; +}; + +// Prototype (registers item for deserialization) +ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), ""); + +ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos, + const std::string &itemstring) +{ + return new ItemSAO(env, pos, itemstring); +} + /* LuaEntitySAO */ @@ -233,7 +477,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) std::string str = getPropertyPacket(); // create message and add to list ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.push_back(aom); } // If attached, check that our parent is still there. If it isn't, detach. @@ -320,7 +564,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) m_armor_groups); // create message and add to list ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.push_back(aom); } if(m_animation_sent == false){ @@ -328,7 +572,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) std::string str = gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend); // create message and add to list ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.push_back(aom); } if(m_bone_position_sent == false){ @@ -337,7 +581,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y); // create message and add to list ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.push_back(aom); } } @@ -346,7 +590,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation); // create message and add to list ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.push_back(aom); } } @@ -461,7 +705,7 @@ int LuaEntitySAO::punch(v3f dir, std::string str = gob_cmd_punched(result.damage, getHP()); // create message and add to list ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.push_back(aom); } if(getHP() == 0) @@ -610,7 +854,7 @@ void LuaEntitySAO::setTextureMod(const std::string &mod) std::string str = gob_cmd_set_texture_mod(mod); // create message and add to list ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.push_back(aom); } void LuaEntitySAO::setSprite(v2s16 p, int num_frames, float framelength, @@ -624,7 +868,7 @@ void LuaEntitySAO::setSprite(v2s16 p, int num_frames, float framelength, ); // create message and add to list ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.push_back(aom); } std::string LuaEntitySAO::getName() @@ -664,7 +908,7 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end) ); // create message and add to list ActiveObjectMessage aom(getId(), false, str); - m_messages_out.push(aom); + m_messages_out.push_back(aom); } bool LuaEntitySAO::getCollisionBox(aabb3f *toset) { @@ -717,6 +961,11 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_, m_attachment_parent_id(0), m_attachment_sent(false), // public + m_moved(false), + m_inventory_not_sent(false), + m_hp_not_sent(false), + m_breath_not_sent(false), + m_wielded_item_not_sent(false), m_physics_override_speed(1), m_physics_override_jump(1), m_physics_override_gravity(1), @@ -856,7 +1105,7 @@ void PlayerSAO::step(float dtime, bool send_recommended) std::string str = getPropertyPacket(); // create message and add to list ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.push_back(aom); } // If attached, check that our parent is still there. If it isn't, detach. @@ -867,7 +1116,7 @@ void PlayerSAO::step(float dtime, bool send_recommended) m_attachment_position = v3f(0,0,0); m_attachment_rotation = v3f(0,0,0); m_player->setPosition(m_last_good_position); - ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id); + m_moved = true; } //dstream<<"PlayerSAO::step: dtime: "<setPosition(pos); // Movement caused by this command is always valid m_last_good_position = pos; - ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id); + // Force position change on client + m_moved = true; } void PlayerSAO::moveTo(v3f pos, bool continuous) @@ -992,19 +1248,22 @@ void PlayerSAO::moveTo(v3f pos, bool continuous) m_player->setPosition(pos); // Movement caused by this command is always valid m_last_good_position = pos; - ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id); + // Force position change on client + m_moved = true; } void PlayerSAO::setYaw(float yaw) { m_player->setYaw(yaw); - ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id); + // Force change on client + m_moved = true; } void PlayerSAO::setPitch(float pitch) { m_player->setPitch(pitch); - ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id); + // Force change on client + m_moved = true; } int PlayerSAO::punch(v3f dir, @@ -1025,7 +1284,7 @@ int PlayerSAO::punch(v3f dir, std::string str = gob_cmd_punched(0, getHP()); // create message and add to list ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.push_back(aom); return 0; } } @@ -1067,18 +1326,27 @@ void PlayerSAO::setHP(s16 hp) { s16 oldhp = m_player->hp; - if (hp < 0) + if(hp < 0) hp = 0; - else if (hp > PLAYER_MAX_HP) + else if(hp > PLAYER_MAX_HP) hp = PLAYER_MAX_HP; + if(hp < oldhp && g_settings->getBool("enable_damage") == false) + { + m_hp_not_sent = true; // fix wrong prediction on client + return; + } + m_player->hp = hp; - if (oldhp > hp) - m_damage += (oldhp - hp); + if(hp != oldhp) { + m_hp_not_sent = true; + if(oldhp > hp) + m_damage += oldhp - hp; + } // Update properties on death - if ((hp == 0) != (oldhp == 0)) + if((hp == 0) != (oldhp == 0)) m_properties_sent = false; } @@ -1157,6 +1425,11 @@ InventoryLocation PlayerSAO::getInventoryLocation() const return loc; } +void PlayerSAO::setInventoryModified() +{ + m_inventory_not_sent = true; +} + std::string PlayerSAO::getWieldList() const { return "main"; @@ -1169,8 +1442,10 @@ int PlayerSAO::getWieldIndex() const void PlayerSAO::setWieldIndex(int i) { - if(i != m_wield_index) { + if(i != m_wield_index) + { m_wield_index = i; + m_wielded_item_not_sent = true; } } @@ -1237,6 +1512,7 @@ bool PlayerSAO::checkMovementCheat() <<" moved too fast; resetting position" <setPosition(m_last_good_position); + m_moved = true; cheated = true; } } diff --git a/src/content_sao.h b/src/content_sao.h index cc372ff55..38baeab3a 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -21,10 +21,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #define CONTENT_SAO_HEADER #include "serverobject.h" +#include "content_object.h" #include "itemgroup.h" #include "player.h" #include "object_properties.h" +ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos, + const std::string &itemstring); + /* LuaEntitySAO needs some internals exposed. */ @@ -35,9 +39,9 @@ public: LuaEntitySAO(ServerEnvironment *env, v3f pos, const std::string &name, const std::string &state); ~LuaEntitySAO(); - ActiveObjectType getType() const + u8 getType() const { return ACTIVEOBJECT_TYPE_LUAENTITY; } - ActiveObjectType getSendType() const + u8 getSendType() const { return ACTIVEOBJECT_TYPE_GENERIC; } virtual void addedToEnvironment(u32 dtime_s); static ServerActiveObject* create(ServerEnvironment *env, v3f pos, @@ -154,9 +158,9 @@ public: PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_, const std::set &privs, bool is_singleplayer); ~PlayerSAO(); - ActiveObjectType getType() const + u8 getType() const { return ACTIVEOBJECT_TYPE_PLAYER; } - ActiveObjectType getSendType() const + u8 getSendType() const { return ACTIVEOBJECT_TYPE_GENERIC; } std::string getDescription(); @@ -205,6 +209,7 @@ public: Inventory* getInventory(); const Inventory* getInventory() const; InventoryLocation getInventoryLocation() const; + void setInventoryModified(); std::string getWieldList() const; int getWieldIndex() const; void setWieldIndex(int i); @@ -314,6 +319,13 @@ private: bool m_attachment_sent; public: + // Some flags used by Server + bool m_moved; + bool m_inventory_not_sent; + bool m_hp_not_sent; + bool m_breath_not_sent; + bool m_wielded_item_not_sent; + float m_physics_override_speed; float m_physics_override_jump; float m_physics_override_gravity; diff --git a/src/craftdef.cpp b/src/craftdef.cpp index 80937ccb7..afc41303f 100644 --- a/src/craftdef.cpp +++ b/src/craftdef.cpp @@ -418,28 +418,27 @@ bool CraftDefinitionShaped::check(const CraftInput &input, IGameDef *gamedef) co return false; // it was empty // Different sizes? - if(inp_max_x - inp_min_x != rec_max_x - rec_min_x || - inp_max_y - inp_min_y != rec_max_y - rec_min_y) + if(inp_max_x - inp_min_x != rec_max_x - rec_min_x) + return false; + if(inp_max_y - inp_min_y != rec_max_y - rec_min_y) return false; // Verify that all item names in the bounding box are equal unsigned int w = inp_max_x - inp_min_x + 1; unsigned int h = inp_max_y - inp_min_y + 1; + for(unsigned int y=0; yidef()) - ) { - return false; - } + if(!inputItemMatchesRecipe( + inp_names[inp_y * inp_width + inp_x], + rec_names[rec_y * rec_width + rec_x], gamedef->idef()) + ){ + return false; } } diff --git a/src/database-dummy.cpp b/src/database-dummy.cpp index 71f60d81c..271d9c975 100644 --- a/src/database-dummy.cpp +++ b/src/database-dummy.cpp @@ -18,38 +18,64 @@ with this program; if not, write to the Free Software Foundation, Inc., */ /* -Dummy database class +Dummy "database" class */ + #include "database-dummy.h" +#include "map.h" +#include "mapsector.h" +#include "mapblock.h" +#include "serialization.h" +#include "main.h" +#include "settings.h" +#include "log.h" -bool Database_Dummy::saveBlock(const v3s16 &pos, const std::string &data) +Database_Dummy::Database_Dummy(ServerMap *map) { - m_database[getBlockAsInteger(pos)] = data; + srvmap = map; +} + +int Database_Dummy::Initialized(void) +{ + return 1; +} + +void Database_Dummy::beginSave() {} +void Database_Dummy::endSave() {} + +bool Database_Dummy::saveBlock(v3s16 blockpos, std::string &data) +{ + m_database[getBlockAsInteger(blockpos)] = data; return true; } -std::string Database_Dummy::loadBlock(const v3s16 &pos) +std::string Database_Dummy::loadBlock(v3s16 blockpos) { - s64 i = getBlockAsInteger(pos); - if (m_database.count(i)) - return m_database[i]; + if (m_database.count(getBlockAsInteger(blockpos))) + return m_database[getBlockAsInteger(blockpos)]; else return ""; } -bool Database_Dummy::deleteBlock(const v3s16 &pos) +bool Database_Dummy::deleteBlock(v3s16 blockpos) { - m_database.erase(getBlockAsInteger(pos)); + m_database.erase(getBlockAsInteger(blockpos)); return true; } -void Database_Dummy::listAllLoadableBlocks(std::vector &dst) +void Database_Dummy::listAllLoadableBlocks(std::list &dst) { - for (std::map::const_iterator x = m_database.begin(); - x != m_database.end(); ++x) { - dst.push_back(getIntegerAsBlock(x->first)); + for(std::map::iterator x = m_database.begin(); x != m_database.end(); ++x) + { + v3s16 p = getIntegerAsBlock(x->first); + //dstream<<"block_i="< &dst); - + Database_Dummy(ServerMap *map); + virtual void beginSave(); + virtual void endSave(); + virtual bool saveBlock(v3s16 blockpos, std::string &data); + virtual std::string loadBlock(v3s16 blockpos); + virtual bool deleteBlock(v3s16 blockpos); + virtual void listAllLoadableBlocks(std::list &dst); + virtual int Initialized(void); + ~Database_Dummy(); private: - std::map m_database; + ServerMap *srvmap; + std::map m_database; }; - #endif - diff --git a/src/database-leveldb.cpp b/src/database-leveldb.cpp index e895354a4..de510e533 100644 --- a/src/database-leveldb.cpp +++ b/src/database-leveldb.cpp @@ -22,54 +22,57 @@ with this program; if not, write to the Free Software Foundation, Inc., #if USE_LEVELDB #include "database-leveldb.h" - -#include "log.h" -#include "filesys.h" -#include "exceptions.h" -#include "util/string.h" - #include "leveldb/db.h" +#include "map.h" +#include "mapsector.h" +#include "mapblock.h" +#include "serialization.h" +#include "main.h" +#include "settings.h" +#include "log.h" +#include "filesys.h" #define ENSURE_STATUS_OK(s) \ if (!(s).ok()) { \ - throw FileNotGoodException(std::string("LevelDB error: ") + \ - (s).ToString()); \ + throw FileNotGoodException(std::string("LevelDB error: ") + (s).ToString()); \ } - -Database_LevelDB::Database_LevelDB(const std::string &savedir) +Database_LevelDB::Database_LevelDB(ServerMap *map, std::string savedir) { leveldb::Options options; options.create_if_missing = true; - leveldb::Status status = leveldb::DB::Open(options, - savedir + DIR_DELIM + "map.db", &m_database); + leveldb::Status status = leveldb::DB::Open(options, savedir + DIR_DELIM + "map.db", &m_database); ENSURE_STATUS_OK(status); + srvmap = map; } -Database_LevelDB::~Database_LevelDB() +int Database_LevelDB::Initialized(void) { - delete m_database; + return 1; } -bool Database_LevelDB::saveBlock(const v3s16 &pos, const std::string &data) +void Database_LevelDB::beginSave() {} +void Database_LevelDB::endSave() {} + +bool Database_LevelDB::saveBlock(v3s16 blockpos, std::string &data) { leveldb::Status status = m_database->Put(leveldb::WriteOptions(), - i64tos(getBlockAsInteger(pos)), data); + i64tos(getBlockAsInteger(blockpos)), data); if (!status.ok()) { errorstream << "WARNING: saveBlock: LevelDB error saving block " - << PP(pos) << ": " << status.ToString() << std::endl; + << PP(blockpos) << ": " << status.ToString() << std::endl; return false; } return true; } -std::string Database_LevelDB::loadBlock(const v3s16 &pos) +std::string Database_LevelDB::loadBlock(v3s16 blockpos) { std::string datastr; leveldb::Status status = m_database->Get(leveldb::ReadOptions(), - i64tos(getBlockAsInteger(pos)), &datastr); + i64tos(getBlockAsInteger(blockpos)), &datastr); if(status.ok()) return datastr; @@ -77,20 +80,20 @@ std::string Database_LevelDB::loadBlock(const v3s16 &pos) return ""; } -bool Database_LevelDB::deleteBlock(const v3s16 &pos) +bool Database_LevelDB::deleteBlock(v3s16 blockpos) { leveldb::Status status = m_database->Delete(leveldb::WriteOptions(), - i64tos(getBlockAsInteger(pos))); + i64tos(getBlockAsInteger(blockpos))); if (!status.ok()) { errorstream << "WARNING: deleteBlock: LevelDB error deleting block " - << PP(pos) << ": " << status.ToString() << std::endl; + << PP(blockpos) << ": " << status.ToString() << std::endl; return false; } return true; } -void Database_LevelDB::listAllLoadableBlocks(std::vector &dst) +void Database_LevelDB::listAllLoadableBlocks(std::list &dst) { leveldb::Iterator* it = m_database->NewIterator(leveldb::ReadOptions()); for (it->SeekToFirst(); it->Valid(); it->Next()) { @@ -100,5 +103,8 @@ void Database_LevelDB::listAllLoadableBlocks(std::vector &dst) delete it; } -#endif // USE_LEVELDB - +Database_LevelDB::~Database_LevelDB() +{ + delete m_database; +} +#endif diff --git a/src/database-leveldb.h b/src/database-leveldb.h index 4afe2fdc7..c195260da 100644 --- a/src/database-leveldb.h +++ b/src/database-leveldb.h @@ -28,22 +28,23 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "leveldb/db.h" #include +class ServerMap; + class Database_LevelDB : public Database { public: - Database_LevelDB(const std::string &savedir); + Database_LevelDB(ServerMap *map, std::string savedir); + virtual void beginSave(); + virtual void endSave(); + virtual bool saveBlock(v3s16 blockpos, std::string &data); + virtual std::string loadBlock(v3s16 blockpos); + virtual bool deleteBlock(v3s16 blockpos); + virtual void listAllLoadableBlocks(std::list &dst); + virtual int Initialized(void); ~Database_LevelDB(); - - virtual bool saveBlock(const v3s16 &pos, const std::string &data); - virtual std::string loadBlock(const v3s16 &pos); - virtual bool deleteBlock(const v3s16 &pos); - virtual void listAllLoadableBlocks(std::vector &dst); - private: - leveldb::DB *m_database; + ServerMap *srvmap; + leveldb::DB* m_database; }; - -#endif // USE_LEVELDB - #endif - +#endif diff --git a/src/database-redis.cpp b/src/database-redis.cpp index 7b42274b9..b086f899d 100644 --- a/src/database-redis.cpp +++ b/src/database-redis.cpp @@ -20,78 +20,84 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "config.h" #if USE_REDIS +/* + Redis databases +*/ + #include "database-redis.h" +#include +#include "map.h" +#include "mapsector.h" +#include "mapblock.h" +#include "serialization.h" +#include "main.h" #include "settings.h" #include "log.h" -#include "exceptions.h" -#include "util/string.h" - -#include -#include +#include "filesys.h" -Database_Redis::Database_Redis(Settings &conf) +Database_Redis::Database_Redis(ServerMap *map, std::string savedir) { + Settings conf; + conf.readConfigFile((std::string(savedir) + DIR_DELIM + "world.mt").c_str()); std::string tmp; try { - tmp = conf.get("redis_address"); - hash = conf.get("redis_hash"); - } catch (SettingNotFoundException) { - throw SettingNotFoundException("Set redis_address and " - "redis_hash in world.mt to use the redis backend"); + tmp = conf.get("redis_address"); + hash = conf.get("redis_hash"); + } catch(SettingNotFoundException e) { + throw SettingNotFoundException("Set redis_address and redis_hash in world.mt to use the redis backend"); } const char *addr = tmp.c_str(); int port = conf.exists("redis_port") ? conf.getU16("redis_port") : 6379; ctx = redisConnect(addr, port); - if (!ctx) { + if(!ctx) throw FileNotGoodException("Cannot allocate redis context"); - } else if(ctx->err) { + else if(ctx->err) { std::string err = std::string("Connection error: ") + ctx->errstr; redisFree(ctx); throw FileNotGoodException(err); } + srvmap = map; } -Database_Redis::~Database_Redis() +int Database_Redis::Initialized(void) { - redisFree(ctx); + return 1; } void Database_Redis::beginSave() { - redisReply *reply = static_cast(redisCommand(ctx, "MULTI")); - if (!reply) { - throw FileNotGoodException(std::string( - "Redis command 'MULTI' failed: ") + ctx->errstr); - } + redisReply *reply; + reply = (redisReply*) redisCommand(ctx, "MULTI"); + if(!reply) + throw FileNotGoodException(std::string("redis command 'MULTI' failed: ") + ctx->errstr); freeReplyObject(reply); } void Database_Redis::endSave() { - redisReply *reply = static_cast(redisCommand(ctx, "EXEC")); - if (!reply) { - throw FileNotGoodException(std::string( - "Redis command 'EXEC' failed: ") + ctx->errstr); - } + redisReply *reply; + reply = (redisReply*) redisCommand(ctx, "EXEC"); + if(!reply) + throw FileNotGoodException(std::string("redis command 'EXEC' failed: ") + ctx->errstr); freeReplyObject(reply); } -bool Database_Redis::saveBlock(const v3s16 &pos, const std::string &data) +bool Database_Redis::saveBlock(v3s16 blockpos, std::string &data) { - std::string tmp = i64tos(getBlockAsInteger(pos)); + std::string tmp = i64tos(getBlockAsInteger(blockpos)); - redisReply *reply = static_cast(redisCommand(ctx, "HSET %s %s %b", - hash.c_str(), tmp.c_str(), data.c_str(), data.size())); + redisReply *reply = (redisReply *)redisCommand(ctx, "HSET %s %s %b", + hash.c_str(), tmp.c_str(), data.c_str(), data.size()); if (!reply) { errorstream << "WARNING: saveBlock: redis command 'HSET' failed on " - "block " << PP(pos) << ": " << ctx->errstr << std::endl; + "block " << PP(blockpos) << ": " << ctx->errstr << std::endl; freeReplyObject(reply); return false; } if (reply->type == REDIS_REPLY_ERROR) { - errorstream << "WARNING: saveBlock: saving block " << PP(pos) + errorstream << "WARNING: saveBlock: saving block " << PP(blockpos) << "failed" << std::endl; freeReplyObject(reply); return false; @@ -101,36 +107,38 @@ bool Database_Redis::saveBlock(const v3s16 &pos, const std::string &data) return true; } -std::string Database_Redis::loadBlock(const v3s16 &pos) +std::string Database_Redis::loadBlock(v3s16 blockpos) { - std::string tmp = i64tos(getBlockAsInteger(pos)); - redisReply *reply = static_cast(redisCommand(ctx, - "HGET %s %s", hash.c_str(), tmp.c_str())); + std::string tmp = i64tos(getBlockAsInteger(blockpos)); + redisReply *reply; + reply = (redisReply*) redisCommand(ctx, "HGET %s %s", hash.c_str(), tmp.c_str()); - if (!reply) { - throw FileNotGoodException(std::string( - "Redis command 'HGET %s %s' failed: ") + ctx->errstr); - } else if (reply->type != REDIS_REPLY_STRING) { + if(!reply) + throw FileNotGoodException(std::string("redis command 'HGET %s %s' failed: ") + ctx->errstr); + if(reply->type != REDIS_REPLY_STRING) return ""; - } std::string str(reply->str, reply->len); freeReplyObject(reply); // std::string copies the memory so this won't cause any problems return str; } -bool Database_Redis::deleteBlock(const v3s16 &pos) +bool Database_Redis::deleteBlock(v3s16 blockpos) { - std::string tmp = i64tos(getBlockAsInteger(pos)); + std::string tmp = i64tos(getBlockAsInteger(blockpos)); - redisReply *reply = static_cast(redisCommand(ctx, - "HDEL %s %s", hash.c_str(), tmp.c_str())); + redisReply *reply = (redisReply *)redisCommand(ctx, "HDEL %s %s", + hash.c_str(), tmp.c_str()); if (!reply) { - throw FileNotGoodException(std::string( - "Redis command 'HDEL %s %s' failed: ") + ctx->errstr); - } else if (reply->type == REDIS_REPLY_ERROR) { - errorstream << "WARNING: deleteBlock: deleting block " << PP(pos) - << " failed" << std::endl; + errorstream << "WARNING: deleteBlock: redis command 'HDEL' failed on " + "block " << PP(blockpos) << ": " << ctx->errstr << std::endl; + freeReplyObject(reply); + return false; + } + + if (reply->type == REDIS_REPLY_ERROR) { + errorstream << "WARNING: deleteBlock: deleting block " << PP(blockpos) + << "failed" << std::endl; freeReplyObject(reply); return false; } @@ -139,21 +147,24 @@ bool Database_Redis::deleteBlock(const v3s16 &pos) return true; } -void Database_Redis::listAllLoadableBlocks(std::vector &dst) +void Database_Redis::listAllLoadableBlocks(std::list &dst) { - redisReply *reply = static_cast(redisCommand(ctx, "HKEYS %s", hash.c_str())); - if (!reply) { - throw FileNotGoodException(std::string( - "Redis command 'HKEYS %s' failed: ") + ctx->errstr); - } else if (reply->type != REDIS_REPLY_ARRAY) { + redisReply *reply; + reply = (redisReply*) redisCommand(ctx, "HKEYS %s", hash.c_str()); + if(!reply) + throw FileNotGoodException(std::string("redis command 'HKEYS %s' failed: ") + ctx->errstr); + if(reply->type != REDIS_REPLY_ARRAY) throw FileNotGoodException("Failed to get keys from database"); - } - for (size_t i = 0; i < reply->elements; i++) { + for(size_t i = 0; i < reply->elements; i++) + { assert(reply->element[i]->type == REDIS_REPLY_STRING); dst.push_back(getIntegerAsBlock(stoi64(reply->element[i]->str))); } freeReplyObject(reply); } -#endif // USE_REDIS - +Database_Redis::~Database_Redis() +{ + redisFree(ctx); +} +#endif diff --git a/src/database-redis.h b/src/database-redis.h index 45e702c83..34b90fa59 100644 --- a/src/database-redis.h +++ b/src/database-redis.h @@ -28,28 +28,24 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include -class Settings; +class ServerMap; class Database_Redis : public Database { public: - Database_Redis(Settings &conf); - ~Database_Redis(); - + Database_Redis(ServerMap *map, std::string savedir); virtual void beginSave(); virtual void endSave(); - - virtual bool saveBlock(const v3s16 &pos, const std::string &data); - virtual std::string loadBlock(const v3s16 &pos); - virtual bool deleteBlock(const v3s16 &pos); - virtual void listAllLoadableBlocks(std::vector &dst); - + virtual bool saveBlock(v3s16 blockpos, std::string &data); + virtual std::string loadBlock(v3s16 blockpos); + virtual bool deleteBlock(v3s16 blockpos); + virtual void listAllLoadableBlocks(std::list &dst); + virtual int Initialized(void); + ~Database_Redis(); private: + ServerMap *srvmap; redisContext *ctx; std::string hash; }; - -#endif // USE_REDIS - #endif - +#endif diff --git a/src/database-sqlite3.cpp b/src/database-sqlite3.cpp index 3480894c9..0679da97d 100644 --- a/src/database-sqlite3.cpp +++ b/src/database-sqlite3.cpp @@ -18,231 +18,297 @@ with this program; if not, write to the Free Software Foundation, Inc., */ /* -SQLite format specification: - blocks: - (PK) INT id - BLOB data + SQLite format specification: + - Initially only replaces sectors/ and sectors2/ + + If map.sqlite does not exist in the save dir + or the block was not found in the database + the map will try to load from sectors folder. + In either case, map.sqlite will be created + and all future saves will save there. + + Structure of map.sqlite: + Tables: + blocks + (PK) INT pos + BLOB data */ #include "database-sqlite3.h" -#include "log.h" -#include "filesys.h" -#include "exceptions.h" +#include "map.h" +#include "mapsector.h" +#include "mapblock.h" +#include "serialization.h" #include "main.h" #include "settings.h" -#include "util/string.h" +#include "log.h" +#include "filesys.h" -#include - - -#define SQLRES(s, r) \ - if ((s) != (r)) { \ - throw FileNotGoodException(std::string(\ - "SQLite3 database error (" \ - __FILE__ ":" TOSTRING(__LINE__) \ - "): ") +\ - sqlite3_errmsg(m_database)); \ - } -#define SQLOK(s) SQLRES(s, SQLITE_OK) - -#define PREPARE_STATEMENT(name, query) \ - SQLOK(sqlite3_prepare_v2(m_database, query, -1, &m_stmt_##name, NULL)) - -#define FINALIZE_STATEMENT(statement) \ - if (sqlite3_finalize(statement) != SQLITE_OK) { \ - throw FileNotGoodException(std::string( \ - "SQLite3: Failed to finalize " #statement ": ") + \ - sqlite3_errmsg(m_database)); \ - } - - -Database_SQLite3::Database_SQLite3(const std::string &savedir) : - m_initialized(false), - m_savedir(savedir), - m_database(NULL), - m_stmt_read(NULL), - m_stmt_write(NULL), - m_stmt_list(NULL), - m_stmt_delete(NULL) +Database_SQLite3::Database_SQLite3(ServerMap *map, std::string savedir) { + m_database = NULL; + m_database_read = NULL; + m_database_write = NULL; + m_database_list = NULL; + m_database_delete = NULL; + m_savedir = savedir; + srvmap = map; +} + +int Database_SQLite3::Initialized(void) +{ + return m_database ? 1 : 0; } void Database_SQLite3::beginSave() { verifyDatabase(); - SQLRES(sqlite3_step(m_stmt_begin), SQLITE_DONE); - sqlite3_reset(m_stmt_begin); + if(sqlite3_exec(m_database, "BEGIN;", NULL, NULL, NULL) != SQLITE_OK) + errorstream<<"WARNING: beginSave() failed, saving might be slow."; } void Database_SQLite3::endSave() { verifyDatabase(); - SQLRES(sqlite3_step(m_stmt_end), SQLITE_DONE); - sqlite3_reset(m_stmt_end); + if(sqlite3_exec(m_database, "COMMIT;", NULL, NULL, NULL) != SQLITE_OK) + errorstream<<"WARNING: endSave() failed, map might not have saved."; } -void Database_SQLite3::openDatabase() +void Database_SQLite3::createDirs(std::string path) { - if (m_database) return; + if(fs::CreateAllDirs(path) == false) + { + infostream< &dst) +void Database_SQLite3::listAllLoadableBlocks(std::list &dst) { verifyDatabase(); - while (sqlite3_step(m_stmt_list) == SQLITE_ROW) { - dst.push_back(getIntegerAsBlock(sqlite3_column_int64(m_stmt_list, 0))); + while(sqlite3_step(m_database_list) == SQLITE_ROW) + { + sqlite3_int64 block_i = sqlite3_column_int64(m_database_list, 0); + v3s16 p = getIntegerAsBlock(block_i); + //dstream<<"block_i="< &dst); - virtual bool initialized() const { return m_initialized; } + virtual bool saveBlock(v3s16 blockpos, std::string &data); + virtual std::string loadBlock(v3s16 blockpos); + virtual bool deleteBlock(v3s16 blockpos); + virtual void listAllLoadableBlocks(std::list &dst); + virtual int Initialized(void); ~Database_SQLite3(); - private: - // Open the database - void openDatabase(); + ServerMap *srvmap; + std::string m_savedir; + sqlite3 *m_database; + sqlite3_stmt *m_database_read; + sqlite3_stmt *m_database_write; + sqlite3_stmt *m_database_delete; + sqlite3_stmt *m_database_list; + // Create the database structure void createDatabase(); - // Open and initialize the database if needed + // Verify we can read/write to the database void verifyDatabase(); - - void bindPos(sqlite3_stmt *stmt, const v3s16 &pos, int index=1); - - bool m_initialized; - - std::string m_savedir; - - sqlite3 *m_database; - sqlite3_stmt *m_stmt_read; - sqlite3_stmt *m_stmt_write; - sqlite3_stmt *m_stmt_list; - sqlite3_stmt *m_stmt_delete; - sqlite3_stmt *m_stmt_begin; - sqlite3_stmt *m_stmt_end; + void createDirs(std::string path); }; #endif - diff --git a/src/database.cpp b/src/database.cpp index 262d475ec..26f6992fc 100644 --- a/src/database.cpp +++ b/src/database.cpp @@ -48,7 +48,7 @@ static inline s64 pythonmodulo(s64 i, s16 mod) } -s64 Database::getBlockAsInteger(const v3s16 &pos) +s64 Database::getBlockAsInteger(const v3s16 pos) const { return (u64) pos.Z * 0x1000000 + (u64) pos.Y * 0x1000 + @@ -56,7 +56,7 @@ s64 Database::getBlockAsInteger(const v3s16 &pos) } -v3s16 Database::getIntegerAsBlock(s64 i) +v3s16 Database::getIntegerAsBlock(s64 i) const { v3s16 pos; pos.X = unsigned_to_signed(pythonmodulo(i, 4096), 2048); diff --git a/src/database.h b/src/database.h index cee7b6fd9..f04c4aa50 100644 --- a/src/database.h +++ b/src/database.h @@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef DATABASE_HEADER #define DATABASE_HEADER -#include +#include #include #include "irr_v3d.h" #include "irrlichttypes.h" @@ -32,22 +32,16 @@ with this program; if not, write to the Free Software Foundation, Inc., class Database { public: - virtual ~Database() {} + virtual void beginSave() = 0; + virtual void endSave() = 0; - virtual void beginSave() {} - virtual void endSave() {} - - virtual bool saveBlock(const v3s16 &pos, const std::string &data) = 0; - virtual std::string loadBlock(const v3s16 &pos) = 0; - virtual bool deleteBlock(const v3s16 &pos) = 0; - - static s64 getBlockAsInteger(const v3s16 &pos); - static v3s16 getIntegerAsBlock(s64 i); - - virtual void listAllLoadableBlocks(std::vector &dst) = 0; - - virtual bool initialized() const { return true; } + virtual bool saveBlock(v3s16 blockpos, std::string &data) = 0; + virtual std::string loadBlock(v3s16 blockpos) = 0; + virtual bool deleteBlock(v3s16 blockpos) = 0; + s64 getBlockAsInteger(const v3s16 pos) const; + v3s16 getIntegerAsBlock(s64 i) const; + virtual void listAllLoadableBlocks(std::list &dst) = 0; + virtual int Initialized(void)=0; + virtual ~Database() {}; }; - #endif - diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index f49fbb008..6504c5155 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -48,7 +48,6 @@ void set_default_settings(Settings *settings) settings->setDefault("keymap_freemove", "KEY_KEY_K"); settings->setDefault("keymap_fastmove", "KEY_KEY_J"); settings->setDefault("keymap_noclip", "KEY_KEY_H"); - settings->setDefault("keymap_cinematic", "KEY_F8"); settings->setDefault("keymap_screenshot", "KEY_F12"); settings->setDefault("keymap_toggle_hud", "KEY_F1"); settings->setDefault("keymap_toggle_chat", "KEY_F2"); @@ -116,9 +115,6 @@ void set_default_settings(Settings *settings) settings->setDefault("free_move", "false"); settings->setDefault("noclip", "false"); settings->setDefault("continuous_forward", "false"); - settings->setDefault("cinematic", "false"); - settings->setDefault("camera_smoothing", "0"); - settings->setDefault("cinematic_camera_smoothing", "0.7"); settings->setDefault("fast_move", "false"); settings->setDefault("invert_mouse", "false"); settings->setDefault("enable_clouds", "true"); @@ -292,7 +288,6 @@ void set_default_settings(Settings *settings) settings->setDefault("water_level", "1"); settings->setDefault("chunksize", "5"); settings->setDefault("mg_flags", ""); - settings->setDefault("enable_floating_dungeons", "true"); // IPv6 settings->setDefault("enable_ipv6", "true"); diff --git a/src/dungeongen.cpp b/src/dungeongen.cpp index 3b7e755b3..eb452a196 100644 --- a/src/dungeongen.cpp +++ b/src/dungeongen.cpp @@ -79,17 +79,14 @@ void DungeonGen::generate(u32 bseed, v3s16 nmin, v3s16 nmax) { // Dungeon generator doesn't modify places which have this set vm->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE); - bool no_float = !g_settings->getBool("enable_floating_dungeons"); - - // Set all air and water (and optionally ignore) to be untouchable - // to make dungeons open to caves and open air + // Set all air and water to be untouchable to make dungeons open + // to caves and open air for (s16 z = nmin.Z; z <= nmax.Z; z++) { for (s16 y = nmin.Y; y <= nmax.Y; y++) { u32 i = vm->m_area.index(nmin.X, y, z); for (s16 x = nmin.X; x <= nmax.X; x++) { content_t c = vm->m_data[i].getContent(); - if (c == CONTENT_AIR || c == dp.c_water - || (no_float && c == CONTENT_IGNORE)) + if (c == CONTENT_AIR || c == dp.c_water) vm->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE; i++; } diff --git a/src/emerge.cpp b/src/emerge.cpp index a697bcb07..c485caffa 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -361,10 +361,7 @@ void EmergeManager::loadParamsFromSettings(Settings *settings) std::string seed_str; const char *setname = (settings == g_settings) ? "fixed_map_seed" : "seed"; - if (!settings->getNoEx("seed", seed_str)) { - g_settings->getNoEx(setname, seed_str); - } - if (!seed_str.empty()) { + if (settings->getNoEx(setname, seed_str) && !seed_str.empty()) { params.seed = read_seed(seed_str.c_str()); } else { params.seed = diff --git a/src/environment.cpp b/src/environment.cpp index 60a26e65f..e1f79803b 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -61,8 +61,9 @@ Environment::Environment(): Environment::~Environment() { // Deallocate players - for(std::vector::iterator i = m_players.begin(); - i != m_players.end(); ++i) { + for(std::list::iterator i = m_players.begin(); + i != m_players.end(); ++i) + { delete (*i); } } @@ -88,7 +89,7 @@ void Environment::removePlayer(u16 peer_id) { DSTACK(__FUNCTION_NAME); - for(std::vector::iterator i = m_players.begin(); + for(std::list::iterator i = m_players.begin(); i != m_players.end();) { Player *player = *i; @@ -103,7 +104,7 @@ void Environment::removePlayer(u16 peer_id) void Environment::removePlayer(const char *name) { - for (std::vector::iterator it = m_players.begin(); + for (std::list::iterator it = m_players.begin(); it != m_players.end(); ++it) { if (strcmp((*it)->getName(), name) == 0) { delete *it; @@ -115,8 +116,9 @@ void Environment::removePlayer(const char *name) Player * Environment::getPlayer(u16 peer_id) { - for(std::vector::iterator i = m_players.begin(); - i != m_players.end(); ++i) { + for(std::list::iterator i = m_players.begin(); + i != m_players.end(); ++i) + { Player *player = *i; if(player->peer_id == peer_id) return player; @@ -126,8 +128,9 @@ Player * Environment::getPlayer(u16 peer_id) Player * Environment::getPlayer(const char *name) { - for(std::vector::iterator i = m_players.begin(); - i != m_players.end(); ++i) { + for(std::list::iterator i = m_players.begin(); + i != m_players.end(); ++i) + { Player *player = *i; if(strcmp(player->getName(), name) == 0) return player; @@ -137,13 +140,15 @@ Player * Environment::getPlayer(const char *name) Player * Environment::getRandomConnectedPlayer() { - std::vector connected_players = getPlayers(true); + std::list connected_players = getPlayers(true); u32 chosen_one = myrand() % connected_players.size(); u32 j = 0; - for(std::vector::iterator + for(std::list::iterator i = connected_players.begin(); - i != connected_players.end(); ++i) { - if(j == chosen_one) { + i != connected_players.end(); ++i) + { + if(j == chosen_one) + { Player *player = *i; return player; } @@ -154,15 +159,17 @@ Player * Environment::getRandomConnectedPlayer() Player * Environment::getNearestConnectedPlayer(v3f pos) { - std::vector connected_players = getPlayers(true); + std::list connected_players = getPlayers(true); f32 nearest_d = 0; Player *nearest_player = NULL; - for(std::vector::iterator + for(std::list::iterator i = connected_players.begin(); - i != connected_players.end(); ++i) { + i != connected_players.end(); ++i) + { Player *player = *i; f32 d = player->getPosition().getDistanceFrom(pos); - if(d < nearest_d || nearest_player == NULL) { + if(d < nearest_d || nearest_player == NULL) + { nearest_d = d; nearest_player = player; } @@ -170,20 +177,22 @@ Player * Environment::getNearestConnectedPlayer(v3f pos) return nearest_player; } -std::vector Environment::getPlayers() +std::list Environment::getPlayers() { return m_players; } -std::vector Environment::getPlayers(bool ignore_disconnected) +std::list Environment::getPlayers(bool ignore_disconnected) { - std::vector newlist; - for(std::vector::iterator + std::list newlist; + for(std::list::iterator i = m_players.begin(); - i != m_players.end(); ++i) { + i != m_players.end(); ++i) + { Player *player = *i; - if(ignore_disconnected) { + if(ignore_disconnected) + { // Ignore disconnected players if(player->peer_id == 0) continue; @@ -203,42 +212,24 @@ u32 Environment::getDayNightRatio() void Environment::setTimeOfDaySpeed(float speed) { - JMutexAutoLock(this->m_timeofday_lock); + JMutexAutoLock(this->m_lock); m_time_of_day_speed = speed; } float Environment::getTimeOfDaySpeed() { - JMutexAutoLock(this->m_timeofday_lock); + JMutexAutoLock(this->m_lock); float retval = m_time_of_day_speed; return retval; } -void Environment::setTimeOfDay(u32 time) -{ - JMutexAutoLock(this->m_time_lock); - m_time_of_day = time; - m_time_of_day_f = (float)time / 24000.0; -} - -u32 Environment::getTimeOfDay() -{ - JMutexAutoLock(this->m_time_lock); - u32 retval = m_time_of_day; - return retval; -} - -float Environment::getTimeOfDayF() -{ - JMutexAutoLock(this->m_time_lock); - float retval = m_time_of_day_f; - return retval; -} - void Environment::stepTimeOfDay(float dtime) { - // getTimeOfDaySpeed lock the value we need to prevent MT problems - float day_speed = getTimeOfDaySpeed(); + float day_speed = 0; + { + JMutexAutoLock(this->m_lock); + day_speed = m_time_of_day_speed; + } m_time_counter += dtime; f32 speed = day_speed * 24000./(24.*3600); @@ -296,7 +287,7 @@ void fillRadiusBlock(v3s16 p0, s16 r, std::set &list) } } -void ActiveBlockList::update(std::vector &active_positions, +void ActiveBlockList::update(std::list &active_positions, s16 radius, std::set &blocks_removed, std::set &blocks_added) @@ -305,7 +296,7 @@ void ActiveBlockList::update(std::vector &active_positions, Create the new list */ std::set newlist = m_forceloaded_list; - for(std::vector::iterator i = active_positions.begin(); + for(std::list::iterator i = active_positions.begin(); i != active_positions.end(); ++i) { fillRadiusBlock(*i, radius, newlist); @@ -382,7 +373,7 @@ ServerEnvironment::~ServerEnvironment() m_map->drop(); // Delete ActiveBlockModifiers - for(std::vector::iterator + for(std::list::iterator i = m_abms.begin(); i != m_abms.end(); ++i){ delete i->abm; } @@ -404,8 +395,8 @@ bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize, v3s16 //calculate normalized direction vector v3f normalized_vector = v3f((pos2.X - pos1.X)/distance, - (pos2.Y - pos1.Y)/distance, - (pos2.Z - pos1.Z)/distance); + (pos2.Y - pos1.Y)/distance, + (pos2.Z - pos1.Z)/distance); //find out if there's a node on path between pos1 and pos2 for (float i = 1; i < distance; i += stepsize) { @@ -430,7 +421,7 @@ void ServerEnvironment::saveLoadedPlayers() std::string players_path = m_path_world + DIR_DELIM "players"; fs::CreateDir(players_path); - for (std::vector::iterator it = m_players.begin(); + for (std::list::iterator it = m_players.begin(); it != m_players.end(); ++it) { RemotePlayer *player = static_cast(*it); @@ -558,9 +549,9 @@ class ABMHandler { private: ServerEnvironment *m_env; - std::map > m_aabms; + std::map > m_aabms; public: - ABMHandler(std::vector &abms, + ABMHandler(std::list &abms, float dtime_s, ServerEnvironment *env, bool use_timers): m_env(env) @@ -568,8 +559,8 @@ public: if(dtime_s < 0.001) return; INodeDefManager *ndef = env->getGameDef()->ndef(); - for(std::vector::iterator - i = abms.begin(); i != abms.end(); ++i) { + for(std::list::iterator + i = abms.begin(); i != abms.end(); ++i){ ActiveBlockModifier *abm = i->abm; float trigger_interval = abm->getTriggerInterval(); if(trigger_interval < 0.001) @@ -613,10 +604,10 @@ public: k != ids.end(); k++) { content_t c = *k; - std::map >::iterator j; + std::map >::iterator j; j = m_aabms.find(c); if(j == m_aabms.end()){ - std::vector aabmlist; + std::list aabmlist; m_aabms[c] = aabmlist; j = m_aabms.find(c); } @@ -673,13 +664,14 @@ public: content_t c = n.getContent(); v3s16 p = p0 + block->getPosRelative(); - std::map >::iterator j; + std::map >::iterator j; j = m_aabms.find(c); if(j == m_aabms.end()) continue; - for(std::vector::iterator - i = j->second.begin(); i != j->second.end(); i++) { + for(std::list::iterator + i = j->second.begin(); i != j->second.end(); i++) + { if(myrand() % i->chance != 0) continue; @@ -859,10 +851,11 @@ void ServerEnvironment::clearAllObjects() { infostream<<"ServerEnvironment::clearAllObjects(): " <<"Removing all active objects"< objects_to_remove; + std::list objects_to_remove; for(std::map::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) { + i != m_active_objects.end(); ++i) + { ServerActiveObject* obj = i->second; if(obj->getType() == ACTIVEOBJECT_TYPE_PLAYER) continue; @@ -895,15 +888,15 @@ void ServerEnvironment::clearAllObjects() // Id to be removed from m_active_objects objects_to_remove.push_back(id); } - // Remove references from m_active_objects - for(std::vector::iterator i = objects_to_remove.begin(); - i != objects_to_remove.end(); ++i) { + for(std::list::iterator i = objects_to_remove.begin(); + i != objects_to_remove.end(); ++i) + { m_active_objects.erase(*i); } // Get list of loaded blocks - std::vector loaded_blocks; + std::list loaded_blocks; infostream<<"ServerEnvironment::clearAllObjects(): " <<"Listing all loaded blocks"<listAllLoadedBlocks(loaded_blocks); @@ -912,7 +905,7 @@ void ServerEnvironment::clearAllObjects() < loadable_blocks; + std::list loadable_blocks; infostream<<"ServerEnvironment::clearAllObjects(): " <<"Listing all loadable blocks"<listAllLoadableBlocks(loadable_blocks); @@ -922,8 +915,9 @@ void ServerEnvironment::clearAllObjects() <<", now clearing"<::iterator i = loaded_blocks.begin(); - i != loaded_blocks.end(); ++i) { + for(std::list::iterator i = loaded_blocks.begin(); + i != loaded_blocks.end(); ++i) + { v3s16 p = *i; MapBlock *block = m_map->getBlockNoCreateNoEx(p); assert(block); @@ -937,8 +931,9 @@ void ServerEnvironment::clearAllObjects() u32 num_blocks_checked = 0; u32 num_blocks_cleared = 0; u32 num_objs_cleared = 0; - for(std::vector::iterator i = loadable_blocks.begin(); - i != loadable_blocks.end(); ++i) { + for(std::list::iterator i = loadable_blocks.begin(); + i != loadable_blocks.end(); ++i) + { v3s16 p = *i; MapBlock *block = m_map->emergeBlock(p, false); if(!block){ @@ -974,8 +969,9 @@ void ServerEnvironment::clearAllObjects() m_map->unloadUnreferencedBlocks(); // Drop references that were added above - for(std::vector::iterator i = loaded_blocks.begin(); - i != loaded_blocks.end(); ++i) { + for(std::list::iterator i = loaded_blocks.begin(); + i != loaded_blocks.end(); ++i) + { v3s16 p = *i; MapBlock *block = m_map->getBlockNoCreateNoEx(p); assert(block); @@ -1016,7 +1012,7 @@ void ServerEnvironment::step(float dtime) */ { ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG); - for(std::vector::iterator i = m_players.begin(); + for(std::list::iterator i = m_players.begin(); i != m_players.end(); ++i) { Player *player = *i; @@ -1039,15 +1035,15 @@ void ServerEnvironment::step(float dtime) /* Get player block positions */ - std::vector players_blockpos; - for(std::vector::iterator + std::list players_blockpos; + for(std::list::iterator i = m_players.begin(); - i != m_players.end(); ++i) { + i != m_players.end(); ++i) + { Player *player = *i; // Ignore disconnected players if(player->peer_id == 0) continue; - v3s16 blockpos = getNodeBlockPos( floatToInt(player->getPosition(), BS)); players_blockpos.push_back(blockpos); @@ -1182,7 +1178,7 @@ void ServerEnvironment::step(float dtime) <<") being handled"<getBlockNoCreateNoEx(p); - if(block == NULL) + if(block==NULL) continue; // Set current time as timestamp @@ -1239,8 +1235,7 @@ void ServerEnvironment::step(float dtime) while(!obj->m_messages_out.empty()) { m_active_object_messages.push_back( - obj->m_messages_out.front()); - obj->m_messages_out.pop(); + obj->m_messages_out.pop_front()); } } } @@ -1547,10 +1542,11 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, */ void ServerEnvironment::removeRemovedObjects() { - std::vector objects_to_remove; + std::list objects_to_remove; for(std::map::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) { + i != m_active_objects.end(); ++i) + { u16 id = i->first; ServerActiveObject* obj = i->second; // This shouldn't happen but check it @@ -1620,13 +1616,13 @@ void ServerEnvironment::removeRemovedObjects() // Delete if(obj->environmentDeletes()) delete obj; - // Id to be removed from m_active_objects objects_to_remove.push_back(id); } // Remove references from m_active_objects - for(std::vector::iterator i = objects_to_remove.begin(); - i != objects_to_remove.end(); ++i) { + for(std::list::iterator i = objects_to_remove.begin(); + i != objects_to_remove.end(); ++i) + { m_active_objects.erase(*i); } } @@ -1670,19 +1666,17 @@ static void print_hexdump(std::ostream &o, const std::string &data) */ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s) { - if(block == NULL) + if(block==NULL) return; - // Ignore if no stored objects (to not set changed flag) if(block->m_static_objects.m_stored.empty()) return; - verbosestream<<"ServerEnvironment::activateObjects(): " <<"activating objects of block "<getPos()) <<" ("<m_static_objects.m_stored.size() <<" objects)"<m_static_objects.m_stored.size() > g_settings->getU16("max_objects_per_block")); - if (large_amount) { + if(large_amount){ errorstream<<"suspiciously large amount of objects detected: " <m_static_objects.m_stored.size()<<" in " <getPos()) @@ -1696,17 +1690,20 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s) } // Activate stored objects - std::vector new_stored; - for (std::vector::iterator + std::list new_stored; + for(std::list::iterator i = block->m_static_objects.m_stored.begin(); - i != block->m_static_objects.m_stored.end(); ++i) { + i != block->m_static_objects.m_stored.end(); ++i) + { + /*infostream<<"Server: Creating an active object from " + <<"static data"<m_static_objects.m_stored.clear(); // Add leftover failed stuff to stored list - for(std::vector::iterator + for(std::list::iterator i = new_stored.begin(); - i != new_stored.end(); ++i) { + i != new_stored.end(); ++i) + { StaticObject &s_obj = *i; block->m_static_objects.m_stored.push_back(s_obj); } @@ -1767,10 +1765,11 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s) */ void ServerEnvironment::deactivateFarObjects(bool force_delete) { - std::vector objects_to_remove; + std::list objects_to_remove; for(std::map::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) { + i != m_active_objects.end(); ++i) + { ServerActiveObject* obj = i->second; assert(obj); @@ -1987,8 +1986,9 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) } // Remove references from m_active_objects - for(std::vector::iterator i = objects_to_remove.begin(); - i != objects_to_remove.end(); ++i) { + for(std::list::iterator i = objects_to_remove.begin(); + i != objects_to_remove.end(); ++i) + { m_active_objects.erase(*i); } } @@ -2025,8 +2025,9 @@ ClientEnvironment::~ClientEnvironment() delete i->second; } - for(std::vector::iterator - i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i) { + for(std::list::iterator + i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i) + { delete *i; } @@ -2058,8 +2059,9 @@ void ClientEnvironment::addPlayer(Player *player) LocalPlayer * ClientEnvironment::getLocalPlayer() { - for(std::vector::iterator i = m_players.begin(); - i != m_players.end(); ++i) { + for(std::list::iterator i = m_players.begin(); + i != m_players.end(); ++i) + { Player *player = *i; if(player->isLocal()) return (LocalPlayer*)player; @@ -2082,7 +2084,7 @@ void ClientEnvironment::step(float dtime) LocalPlayer *lplayer = getLocalPlayer(); assert(lplayer); // collision info queue - std::vector player_collisions; + std::list player_collisions; /* Get the speed the player is going @@ -2197,8 +2199,10 @@ void ClientEnvironment::step(float dtime) //std::cout<<"Looped "<::iterator i = player_collisions.begin(); - i != player_collisions.end(); ++i) { + for(std::list::iterator + i = player_collisions.begin(); + i != player_collisions.end(); ++i) + { CollisionInfo &info = *i; v3f speed_diff = info.new_speed - info.old_speed;; // Handle only fall damage @@ -2313,14 +2317,16 @@ void ClientEnvironment::step(float dtime) /* Stuff that can be done in an arbitarily large dtime */ - for(std::vector::iterator i = m_players.begin(); - i != m_players.end(); ++i) { + for(std::list::iterator i = m_players.begin(); + i != m_players.end(); ++i) + { Player *player = *i; /* Handle non-local players */ - if(player->isLocal() == false) { + if(player->isLocal() == false) + { // Move player->move(dtime, this, 100*BS); @@ -2381,18 +2387,16 @@ void ClientEnvironment::step(float dtime) Step and handle simple objects */ g_profiler->avg("CEnv: num of simple objects", m_simple_objects.size()); - for(std::vector::iterator - i = m_simple_objects.begin(); i != m_simple_objects.end();) { - std::vector::iterator cur = i; - ClientSimpleObject *simple = *cur; - + for(std::list::iterator + i = m_simple_objects.begin(); i != m_simple_objects.end();) + { + ClientSimpleObject *simple = *i; + std::list::iterator cur = i; + ++i; simple->step(dtime); - if(simple->m_to_be_removed) { + if(simple->m_to_be_removed){ delete simple; - i = m_simple_objects.erase(cur); - } - else { - ++i; + m_simple_objects.erase(cur); } } } @@ -2484,7 +2488,7 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type, const std::string &init_data) { ClientActiveObject* obj = - ClientActiveObject::create((ActiveObjectType) type, m_gamedef, this); + ClientActiveObject::create(type, m_gamedef, this); if(obj == NULL) { infostream<<"ClientEnvironment::addActiveObject(): " diff --git a/src/environment.h b/src/environment.h index c9c374413..13c0c0efe 100644 --- a/src/environment.h +++ b/src/environment.h @@ -75,19 +75,28 @@ public: Player * getPlayer(const char *name); Player * getRandomConnectedPlayer(); Player * getNearestConnectedPlayer(v3f pos); - std::vector getPlayers(); - std::vector getPlayers(bool ignore_disconnected); + std::list getPlayers(); + std::list getPlayers(bool ignore_disconnected); u32 getDayNightRatio(); // 0-23999 - virtual void setTimeOfDay(u32 time); - u32 getTimeOfDay(); - float getTimeOfDayF(); + virtual void setTimeOfDay(u32 time) + { + m_time_of_day = time; + m_time_of_day_f = (float)time / 24000.0; + } + + u32 getTimeOfDay() + { return m_time_of_day; } + + float getTimeOfDayF() + { return m_time_of_day_f; } void stepTimeOfDay(float dtime); void setTimeOfDaySpeed(float speed); + float getTimeOfDaySpeed(); void setDayNightRatioOverride(bool enable, u32 value) @@ -101,7 +110,7 @@ public: protected: // peer_ids in here should be unique, except that there may be many 0s - std::vector m_players; + std::list m_players; // Time of day in milli-hours (0-23999); determines day and night u32 m_time_of_day; // Time of day in 0...1 @@ -125,8 +134,7 @@ protected: bool m_cache_enable_shaders; private: - JMutex m_timeofday_lock; - JMutex m_time_lock; + JMutex m_lock; }; @@ -174,7 +182,7 @@ struct ABMWithState class ActiveBlockList { public: - void update(std::vector &active_positions, + void update(std::list &active_positions, s16 radius, std::set &blocks_removed, std::set &blocks_added); @@ -393,7 +401,7 @@ private: u32 m_game_time; // A helper variable for incrementing the latter float m_game_time_fraction_counter; - std::vector m_abms; + std::list m_abms; // An interval for generally sending object positions and stuff float m_recommended_send_interval; // Estimate for general maximum lag as determined by server. @@ -521,7 +529,7 @@ private: IGameDef *m_gamedef; IrrlichtDevice *m_irr; std::map m_active_objects; - std::vector m_simple_objects; + std::list m_simple_objects; std::list m_client_event_queue; IntervalLimiter m_active_object_light_update_interval; IntervalLimiter m_lava_hurt_interval; diff --git a/src/filecache.cpp b/src/filecache.cpp index f1694d8d5..33677cc83 100644 --- a/src/filecache.cpp +++ b/src/filecache.cpp @@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filecache.h" -#include "network/networkprotocol.h" +#include "clientserver.h" #include "log.h" #include "filesys.h" #include diff --git a/src/game.cpp b/src/game.cpp index 87ee081be..fe3e838b2 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -51,7 +51,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "nodemetadata.h" #include "main.h" // For g_settings #include "itemdef.h" -#include "client/tile.h" // For TextureSource +#include "tile.h" // For TextureSource #include "shader.h" // For ShaderSource #include "logoutputbuffer.h" #include "subgame.h" @@ -492,7 +492,7 @@ private: color(color) {} }; - std::vector m_log; + std::list m_log; public: u32 m_log_max_size; @@ -515,7 +515,7 @@ public: { std::map m_meta; - for (std::vector::const_iterator k = m_log.begin(); + for (std::list::const_iterator k = m_log.begin(); k != m_log.end(); k++) { const Piece &piece = *k; @@ -613,7 +613,7 @@ public: float lastscaledvalue = 0.0; bool lastscaledvalue_exists = false; - for (std::vector::const_iterator j = m_log.begin(); + for (std::list::const_iterator j = m_log.begin(); j != m_log.end(); j++) { const Piece &piece = *j; float value = 0; @@ -1043,11 +1043,7 @@ static inline void create_formspec_menu(GUIFormSpecMenu **cur_formspec, } } -#ifdef __ANDROID__ #define SIZE_TAG "size[11,5.5]" -#else -#define SIZE_TAG "size[11,5.5,true]" // Fixed size on desktop -#endif static void show_chat_menu(GUIFormSpecMenu **cur_formspec, InventoryManager *invmgr, IGameDef *gamedef, @@ -1078,7 +1074,7 @@ static void show_deathscreen(GUIFormSpecMenu **cur_formspec, std::string(FORMSPEC_VERSION_STRING) + SIZE_TAG "bgcolor[#320000b4;true]" - "label[4.85,1.35;" + gettext("You died.") + "]" + "label[4.85,1.35;You died.]" "button_exit[4,3;3,0.5;btn_respawn;" + gettext("Respawn") + "]" ; @@ -1137,7 +1133,7 @@ static void show_pause_menu(GUIFormSpecMenu **cur_formspec, os << "button_exit[4," << (ypos++) << ";3,0.5;btn_change_password;" << wide_to_narrow(wstrgettext("Change Password")) << "]"; } - + #ifndef __ANDROID__ os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;" << wide_to_narrow(wstrgettext("Sound Volume")) << "]"; @@ -1161,7 +1157,7 @@ static void show_pause_menu(GUIFormSpecMenu **cur_formspec, LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU"); create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst, NULL); - (*cur_formspec)->setFocus(L"btn_continue"); + (*cur_formspec)->doPause = true; } @@ -1253,7 +1249,6 @@ struct KeyCache { KEYMAP_ID_FREEMOVE, KEYMAP_ID_FASTMOVE, KEYMAP_ID_NOCLIP, - KEYMAP_ID_CINEMATIC, KEYMAP_ID_SCREENSHOT, KEYMAP_ID_TOGGLE_HUD, KEYMAP_ID_TOGGLE_CHAT, @@ -1302,7 +1297,6 @@ void KeyCache::populate() key[KEYMAP_ID_FREEMOVE] = getKeySetting("keymap_freemove"); key[KEYMAP_ID_FASTMOVE] = getKeySetting("keymap_fastmove"); key[KEYMAP_ID_NOCLIP] = getKeySetting("keymap_noclip"); - key[KEYMAP_ID_CINEMATIC] = getKeySetting("keymap_cinematic"); key[KEYMAP_ID_SCREENSHOT] = getKeySetting("keymap_screenshot"); key[KEYMAP_ID_TOGGLE_HUD] = getKeySetting("keymap_toggle_hud"); key[KEYMAP_ID_TOGGLE_CHAT] = getKeySetting("keymap_toggle_chat"); @@ -1499,7 +1493,6 @@ protected: void toggleFreeMoveAlt(float *statustext_time, float *jump_timer); void toggleFast(float *statustext_time); void toggleNoClip(float *statustext_time); - void toggleCinematic(float *statustext_time); void toggleChat(float *statustext_time, bool *flag); void toggleHud(float *statustext_time, bool *flag); @@ -1740,7 +1733,6 @@ void Game::run() { ProfilerGraph graph; RunStats stats = { 0 }; - CameraOrientation cam_view_target = { 0 }; CameraOrientation cam_view = { 0 }; GameRunData runData = { 0 }; FpsControl draw_times = { 0 }; @@ -1796,17 +1788,7 @@ void Game::run() updateProfilers(runData, stats, draw_times, dtime); processUserInput(&flags, &runData, dtime); // Update camera before player movement to avoid camera lag of one frame - updateCameraDirection(&cam_view_target, &flags); - float cam_smoothing = 0; - if (g_settings->getBool("cinematic")) - cam_smoothing = 1 - g_settings->getFloat("cinematic_camera_smoothing"); - else - cam_smoothing = 1 - g_settings->getFloat("camera_smoothing"); - cam_smoothing = rangelim(cam_smoothing, 0.01f, 1.0f); - cam_view.camera_yaw += (cam_view_target.camera_yaw - - cam_view.camera_yaw) * cam_smoothing; - cam_view.camera_pitch += (cam_view_target.camera_pitch - - cam_view.camera_pitch) * cam_smoothing; + updateCameraDirection(&cam_view, &flags); updatePlayerControl(cam_view); step(&dtime); processClientEvents(&cam_view, &runData.damage_flash); @@ -2582,8 +2564,6 @@ void Game::processKeyboardInput(VolatileRunFlags *flags, toggleFast(statustext_time); } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_NOCLIP])) { toggleNoClip(statustext_time); - } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CINEMATIC])) { - toggleCinematic(statustext_time); } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_SCREENSHOT])) { client->makeScreenshot(device); } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_HUD])) { @@ -2689,15 +2669,6 @@ void Game::dropSelectedItem() void Game::openInventory() { - /* - * Don't permit to open inventory is CAO or player doesn't exists. - * This prevent showing an empty inventory at player load - */ - - LocalPlayer *player = client->getEnv().getLocalPlayer(); - if (player == NULL || player->getCAO() == NULL) - return; - infostream << "the_game: " << "Launching inventory" << std::endl; PlayerInventoryFormSource *fs_src = new PlayerInventoryFormSource(client); @@ -2770,16 +2741,6 @@ void Game::toggleNoClip(float *statustext_time) statustext += L" (note: no 'noclip' privilege)"; } -void Game::toggleCinematic(float *statustext_time) -{ - static const wchar_t *msg[] = { L"cinematic disabled", L"cinematic enabled" }; - bool cinematic = !g_settings->getBool("cinematic"); - g_settings->set("cinematic", bool_to_cstr(cinematic)); - - *statustext_time = 0; - statustext = msg[cinematic]; -} - void Game::toggleChat(float *statustext_time, bool *flag) { @@ -3257,13 +3218,10 @@ void Game::updateCamera(VolatileRunFlags *flags, u32 busy_time, v3s16 old_camera_offset = camera->getOffset(); if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CAMERA_MODE])) { + camera->toggleCameraMode(); GenericCAO *playercao = player->getCAO(); - // If playercao not loaded, don't change camera - if (playercao == NULL) - return; - - camera->toggleCameraMode(); + assert(playercao != NULL); playercao->setVisible(camera->getCameraMode() > CAMERA_MODE_FIRST); } @@ -3968,28 +3926,6 @@ void Game::updateFrame(std::vector &highlight_boxes, } -inline static const char *yawToDirectionString(int yaw) -{ - // NOTE: TODO: This can be done mathematically without the else/else-if - // cascade. - - const char *player_direction; - - yaw = wrapDegrees_0_360(yaw); - - if (yaw >= 45 && yaw < 135) - player_direction = "West [-X]"; - else if (yaw >= 135 && yaw < 225) - player_direction = "South [-Z]"; - else if (yaw >= 225 && yaw < 315) - player_direction = "East [+X]"; - else - player_direction = "North [+Z]"; - - return player_direction; -} - - void Game::updateGui(float *statustext_time, const RunStats &stats, const GameRunData& runData, f32 dtime, const VolatileRunFlags &flags, const CameraOrientation &cam) @@ -4045,7 +3981,6 @@ void Game::updateGui(float *statustext_time, const RunStats &stats, << ", " << (player_position.Y / BS) << ", " << (player_position.Z / BS) << ") (yaw=" << (wrapDegrees_0_360(cam.camera_yaw)) - << " " << yawToDirectionString(cam.camera_yaw) << ") (seed = " << ((u64)client->getMapSeed()) << ")"; @@ -4263,3 +4198,4 @@ void the_game(bool *kill, error_message = narrow_to_wide(e.what()) + wstrgettext("\nCheck debug.txt for details."); } } + diff --git a/src/gettext.cpp b/src/gettext.cpp index fc7569418..688a22570 100644 --- a/src/gettext.cpp +++ b/src/gettext.cpp @@ -26,24 +26,24 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #if USE_GETTEXT && defined(_MSC_VER) -#include +#include #include #include #include "filesys.h" -#define setlocale(category, localename) \ - setlocale(category, MSVC_LocaleLookup(localename)) +#define setlocale(category,localename) \ + setlocale(category,MSVC_LocaleLookup(localename)) -static std::map glb_supported_locales; +static std::map glb_supported_locales; /******************************************************************************/ BOOL CALLBACK UpdateLocaleCallback(LPTSTR pStr) { char* endptr = 0; - int LOCALEID = strtol(pStr, &endptr,16); + int LOCALEID = strtol(pStr,&endptr,16); wchar_t buffer[LOCALE_NAME_MAX_LENGTH]; - memset(buffer, 0, sizeof(buffer)); + memset(buffer,0,sizeof(buffer)); if (GetLocaleInfoW( LOCALEID, LOCALE_SISO639LANGNAME, @@ -52,7 +52,7 @@ BOOL CALLBACK UpdateLocaleCallback(LPTSTR pStr) std::wstring name = buffer; - memset(buffer, 0, sizeof(buffer)); + memset(buffer,0,sizeof(buffer)); GetLocaleInfoW( LOCALEID, LOCALE_SISO3166CTRYNAME, @@ -61,7 +61,7 @@ BOOL CALLBACK UpdateLocaleCallback(LPTSTR pStr) std::wstring country = buffer; - memset(buffer, 0, sizeof(buffer)); + memset(buffer,0,sizeof(buffer)); GetLocaleInfoW( LOCALEID, LOCALE_SENGLISHLANGUAGENAME, @@ -96,7 +96,7 @@ const char* MSVC_LocaleLookup(const char* raw_shortname) { } if (first_use) { - EnumSystemLocalesA(UpdateLocaleCallback, LCID_SUPPORTED | LCID_ALTERNATE_SORTS); + EnumSystemLocalesA(UpdateLocaleCallback,LCID_SUPPORTED | LCID_ALTERNATE_SORTS); first_use = false; } @@ -148,8 +148,8 @@ void init_gettext(const char *path, const std::string &configured_language) { if (current_language_var != configured_language) { STARTUPINFO startupinfo; PROCESS_INFORMATION processinfo; - memset(&startupinfo, 0, sizeof(startupinfo)); - memset(&processinfo, 0, sizeof(processinfo)); + memset(&startupinfo,0,sizeof(startupinfo)); + memset(&processinfo,0,sizeof(processinfo)); errorstream << "MSVC localization workaround active restating minetest in new environment!" << std::endl; std::string parameters = ""; @@ -169,7 +169,7 @@ void init_gettext(const char *path, const std::string &configured_language) { /** users may start by short name in commandline without extention **/ std::string appname = argv[0]; - if (appname.substr(appname.length() - 4) != ".exe") { + if (appname.substr(appname.length() -4) != ".exe") { appname += ".exe"; } @@ -260,7 +260,7 @@ void init_gettext(const char *path, const std::string &configured_language) { /* no matter what locale is used we need number format to be "C" */ /* to ensure formspec parameters are evaluated correct! */ - setlocale(LC_NUMERIC, "C"); + setlocale(LC_NUMERIC,"C"); infostream << "Message locale is now set to: " << setlocale(LC_ALL, 0) << std::endl; } diff --git a/src/gettext.h b/src/gettext.h index dce45fa3a..8e6282887 100644 --- a/src/gettext.h +++ b/src/gettext.h @@ -41,19 +41,16 @@ void init_gettext(const char *path, const std::string &configured_language); extern const wchar_t *narrow_to_wide_c(const char *mbs); extern std::wstring narrow_to_wide(const std::string &mbs); + // You must free the returned string! inline const wchar_t *wgettext(const char *str) { return narrow_to_wide_c(gettext(str)); } -// Gettext under MSVC needs this strange way. Just don't ask... inline std::wstring wstrgettext(const std::string &text) { - const wchar_t *tmp = wgettext(text.c_str()); - std::wstring retval = (std::wstring)tmp; - delete[] tmp; - return retval; + return narrow_to_wide(gettext(text.c_str())); } inline std::string strgettext(const std::string &text) diff --git a/src/guiChatConsole.cpp b/src/guiChatConsole.cpp index b52589044..bdce7c872 100644 --- a/src/guiChatConsole.cpp +++ b/src/guiChatConsole.cpp @@ -26,7 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "main.h" // for g_settings #include "porting.h" -#include "client/tile.h" +#include "tile.h" #include "fontengine.h" #include "log.h" #include "gettext.h" @@ -99,7 +99,7 @@ GUIChatConsole::GUIChatConsole( { core::dimension2d dim = m_font->getDimension(L"M"); m_fontsize = v2u32(dim.Width, dim.Height); - m_font->grab(); + dstream << "Font size: " << m_fontsize.X << " " << m_fontsize.Y << std::endl; } m_fontsize.X = MYMAX(m_fontsize.X, 1); m_fontsize.Y = MYMAX(m_fontsize.Y, 1); @@ -109,10 +109,7 @@ GUIChatConsole::GUIChatConsole( } GUIChatConsole::~GUIChatConsole() -{ - if (m_font) - m_font->drop(); -} +{} void GUIChatConsole::openConsole(f32 height) { diff --git a/src/guiChatConsole.h b/src/guiChatConsole.h index 652b265a4..2bf45fdf4 100644 --- a/src/guiChatConsole.h +++ b/src/guiChatConsole.h @@ -122,6 +122,9 @@ private: // font gui::IGUIFont* m_font; v2u32 m_fontsize; +#if USE_FREETYPE + bool m_use_freetype; +#endif }; diff --git a/src/guiEngine.cpp b/src/guiEngine.cpp index b45011c2c..de6f44134 100644 --- a/src/guiEngine.cpp +++ b/src/guiEngine.cpp @@ -38,7 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "fontengine.h" #ifdef __ANDROID__ -#include "client/tile.h" +#include "tile.h" #include #endif diff --git a/src/guiEngine.h b/src/guiEngine.h index e57573220..0be8634dd 100644 --- a/src/guiEngine.h +++ b/src/guiEngine.h @@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "modalMenu.h" #include "guiFormSpecMenu.h" #include "sound.h" -#include "client/tile.h" +#include "tile.h" /******************************************************************************/ /* Typedefs and macros */ diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 581da894b..20c9ecde7 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -37,8 +37,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include "log.h" -#include "client/tile.h" // ITextureSource +#include "tile.h" // ITextureSource #include "hud.h" // drawItemStack +#include "hex.h" +#include "util/string.h" +#include "util/numeric.h" #include "filesys.h" #include "gettime.h" #include "gettext.h" @@ -47,10 +50,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "main.h" #include "settings.h" #include "client.h" -#include "fontengine.h" -#include "util/hex.h" -#include "util/numeric.h" #include "util/string.h" // for parseColorString() +#include "fontengine.h" #define MY_CHECKPOS(a,b) \ if (v_pos.size() != 2) { \ @@ -96,7 +97,6 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, m_form_src(fsrc), m_text_dst(tdst), m_formspec_version(0), - m_focused_element(L""), m_font(NULL) #ifdef __ANDROID__ ,m_JavaDialogFieldName(L"") @@ -1757,6 +1757,8 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element) <getDynamicData(); } - //set focus - if (!m_focused_element.empty()) - mydata.focused_fieldname = m_focused_element; - //preserve focus gui::IGUIElement *focused_element = Environment->getFocus(); if (focused_element && focused_element->getParent() == this) { diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 2074fb780..6d6c07453 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "inventorymanager.h" #include "modalMenu.h" #include "guiTable.h" -#include "network/networkprotocol.h" +#include "clientserver.h" class IGameDef; class InventoryManager; @@ -246,20 +246,13 @@ public: m_allowclose = value; } - void lockSize(bool lock,v2u32 basescreensize=v2u32(0,0)) - { + void lockSize(bool lock,v2u32 basescreensize=v2u32(0,0)) { m_lock = lock; m_lockscreensize = basescreensize; } void removeChildren(); void setInitialFocus(); - - void setFocus(std::wstring elementname) - { - m_focused_element = elementname; - } - /* Remove and re-add (or reposition) stuff */ @@ -355,7 +348,6 @@ private: IFormSource *m_form_src; TextDest *m_text_dst; unsigned int m_formspec_version; - std::wstring m_focused_element; typedef struct { bool explicit_size; diff --git a/src/guiKeyChangeMenu.cpp b/src/guiKeyChangeMenu.cpp index 9b5a31d26..9bc8118a1 100644 --- a/src/guiKeyChangeMenu.cpp +++ b/src/guiKeyChangeMenu.cpp @@ -51,7 +51,6 @@ enum GUI_ID_KEY_FAST_BUTTON, GUI_ID_KEY_JUMP_BUTTON, GUI_ID_KEY_NOCLIP_BUTTON, - GUI_ID_KEY_CINEMATIC_BUTTON, GUI_ID_KEY_CHAT_BUTTON, GUI_ID_KEY_CMD_BUTTON, GUI_ID_KEY_CONSOLE_BUTTON, @@ -138,27 +137,27 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) { key_setting *k = key_settings.at(i); { - core::rect < s32 > rect(0, 0, 110, 20); + core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); Environment->addStaticText(k->button_name, rect, false, true, this, -1); } { core::rect < s32 > rect(0, 0, 100, 30); - rect += topleft + v2s32(offset.X + 115, offset.Y - 5); + rect += topleft + v2s32(offset.X + 105, offset.Y - 5); const wchar_t *text = wgettext(k->key.name()); k->button = Environment->addButton(rect, this, k->id, text); delete[] text; } if(i + 1 == KMaxButtonPerColumns) - offset = v2s32(260, 60); + offset = v2s32(250, 60); else offset += v2s32(0, 25); } { - s32 option_x = offset.X; - s32 option_y = offset.Y + 5; + s32 option_x = offset.X + 10; + s32 option_y = offset.Y; u32 option_w = 180; { core::rect rect(0, 0, option_w, 30); @@ -172,9 +171,9 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) } { - s32 option_x = offset.X; - s32 option_y = offset.Y + 5; - u32 option_w = 280; + s32 option_x = offset.X + 10; + s32 option_y = offset.Y; + u32 option_w = 220; { core::rect rect(0, 0, option_w, 30); rect += topleft + v2s32(option_x, option_y); @@ -395,23 +394,22 @@ void GUIKeyChangeMenu::add_key(int id, const wchar_t *button_name, const std::st void GUIKeyChangeMenu::init_keys() { - this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward"); - this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward"); - this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left"); - this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right"); - this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Use"), "keymap_special1"); - this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump"); - this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak"); - this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop"); - this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory"); - this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat"); - this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd"); - this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console"); - this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove"); - this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove"); - this->add_key(GUI_ID_KEY_CINEMATIC_BUTTON, wgettext("Toggle Cinematic"), "keymap_cinematic"); - this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip"); - this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect"); - this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks"); + this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward"); + this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward"); + this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left"); + this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right"); + this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Use"), "keymap_special1"); + this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump"); + this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak"); + this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop"); + this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory"); + this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat"); + this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd"); + this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console"); + this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove"); + this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove"); + this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip"); + this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect"); + this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks"); } diff --git a/src/guiPasswordChange.cpp b/src/guiPasswordChange.cpp index 0e19f571d..d9a5cc48b 100644 --- a/src/guiPasswordChange.cpp +++ b/src/guiPasswordChange.cpp @@ -103,8 +103,8 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) */ s32 ypos = 50; { - core::rect rect(0, 0, 150, 20); - rect += topleft_client + v2s32(25, ypos+6); + core::rect rect(0, 0, 110, 20); + rect += topleft_client + v2s32(35, ypos+6); text = wgettext("Old Password"); Environment->addStaticText(text, rect, false, true, this, -1); delete[] text; @@ -119,8 +119,8 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) } ypos += 50; { - core::rect rect(0, 0, 150, 20); - rect += topleft_client + v2s32(25, ypos+6); + core::rect rect(0, 0, 110, 20); + rect += topleft_client + v2s32(35, ypos+6); text = wgettext("New Password"); Environment->addStaticText(text, rect, false, true, this, -1); delete[] text; @@ -134,8 +134,8 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) } ypos += 50; { - core::rect rect(0, 0, 150, 20); - rect += topleft_client + v2s32(25, ypos+6); + core::rect rect(0, 0, 110, 20); + rect += topleft_client + v2s32(35, ypos+6); text = wgettext("Confirm Password"); Environment->addStaticText(text, rect, false, true, this, -1); delete[] text; diff --git a/src/guiTable.cpp b/src/guiTable.cpp index a7a53f581..05db228da 100644 --- a/src/guiTable.cpp +++ b/src/guiTable.cpp @@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "debug.h" #include "log.h" -#include "client/tile.h" +#include "tile.h" #include "gettime.h" #include "util/string.h" #include "util/numeric.h" diff --git a/src/util/hex.h b/src/hex.h similarity index 100% rename from src/util/hex.h rename to src/hex.h diff --git a/src/httpfetch.cpp b/src/httpfetch.cpp index e6886f652..47e33480b 100644 --- a/src/httpfetch.cpp +++ b/src/httpfetch.cpp @@ -37,7 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" JMutex g_httpfetch_mutex; -std::map > g_httpfetch_results; +std::map > g_httpfetch_results; HTTPFetchRequest::HTTPFetchRequest() { @@ -57,7 +57,7 @@ static void httpfetch_deliver_result(const HTTPFetchResult &fetch_result) unsigned long caller = fetch_result.caller; if (caller != HTTPFETCH_DISCARD) { JMutexAutoLock lock(g_httpfetch_mutex); - g_httpfetch_results[caller].push(fetch_result); + g_httpfetch_results[caller].push_back(fetch_result); } } @@ -70,11 +70,11 @@ unsigned long httpfetch_caller_alloc() // Check each caller ID except HTTPFETCH_DISCARD const unsigned long discard = HTTPFETCH_DISCARD; for (unsigned long caller = discard + 1; caller != discard; ++caller) { - std::map >::iterator + std::map >::iterator it = g_httpfetch_results.find(caller); if (it == g_httpfetch_results.end()) { - verbosestream << "httpfetch_caller_alloc: allocating " - << caller << std::endl; + verbosestream<<"httpfetch_caller_alloc: allocating " + < >::iterator + std::map >::iterator it = g_httpfetch_results.find(caller); if (it == g_httpfetch_results.end()) return false; // Check that result queue is nonempty - std::queue &caller_results = it->second; + std::list &caller_results = it->second; if (caller_results.empty()) return false; // Pop first result fetch_result = caller_results.front(); - caller_results.pop(); + caller_results.pop_front(); return true; } @@ -194,6 +194,7 @@ private: HTTPFetchRequest request; HTTPFetchResult result; std::ostringstream oss; + char *post_fields; struct curl_slist *http_header; curl_httppost *post; }; diff --git a/src/hud.cpp b/src/hud.cpp index aabaa066c..29ebb8103 100644 --- a/src/hud.cpp +++ b/src/hud.cpp @@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gamedef.h" #include "itemdef.h" #include "inventory.h" -#include "client/tile.h" +#include "tile.h" #include "localplayer.h" #include "camera.h" #include "porting.h" diff --git a/src/itemdef.cpp b/src/itemdef.cpp index 381773bb4..ac67c5b27 100644 --- a/src/itemdef.cpp +++ b/src/itemdef.cpp @@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapblock_mesh.h" #include "mesh.h" #include "wieldmesh.h" -#include "client/tile.h" +#include "tile.h" #endif #include "log.h" #include "main.h" // g_settings @@ -249,8 +249,8 @@ public: virtual ~CItemDefManager() { #ifndef SERVER - const std::vector &values = m_clientcached.getValues(); - for(std::vector::const_iterator + const std::list &values = m_clientcached.getValues(); + for(std::list::const_iterator i = values.begin(); i != values.end(); ++i) { ClientCached *cc = *i; @@ -362,6 +362,8 @@ public: scene::IMesh *node_mesh = NULL; + bool reenable_shaders = false; + if (need_rtt_mesh || need_wield_mesh) { u8 param1 = 0; if (f.param_type == CPT_LIGHT) @@ -370,7 +372,11 @@ public: /* Make a mesh from the node */ - MeshMakeData mesh_make_data(gamedef, false); + if (g_settings->getBool("enable_shaders")) { + reenable_shaders = true; + g_settings->setBool("enable_shaders", false); + } + MeshMakeData mesh_make_data(gamedef); u8 param2 = 0; if (f.param_type_2 == CPT2_WALLMOUNTED) param2 = 1; @@ -437,6 +443,9 @@ public: if (node_mesh) node_mesh->drop(); + + if (reenable_shaders) + g_settings->setBool("enable_shaders",true); } // Put in cache diff --git a/src/jthread/jevent.h b/src/jthread/jevent.h index 9ea7ebde8..f97e09ca0 100644 --- a/src/jthread/jevent.h +++ b/src/jthread/jevent.h @@ -30,7 +30,7 @@ #ifdef _WIN32 #include -#elif defined(__MACH__) && defined(__APPLE__) +#elif __MACH__ #include #include #include @@ -43,7 +43,7 @@ class Event { #ifdef _WIN32 HANDLE hEvent; -#elif defined(__MACH__) && defined(__APPLE__) +#elif __MACH__ semaphore_t sem; #else sem_t sem; diff --git a/src/jthread/jsemaphore.h b/src/jthread/jsemaphore.h index 32e9bc2f2..4ab006aea 100644 --- a/src/jthread/jsemaphore.h +++ b/src/jthread/jsemaphore.h @@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #define MAX_SEMAPHORE_COUNT 1024 -#elif defined(__MACH__) && defined(__APPLE__) +#elif __MACH__ #include #include #include @@ -52,7 +52,7 @@ public: private: #if defined(WIN32) HANDLE m_hSemaphore; -#elif defined(__MACH__) && defined(__APPLE__) +#elif __MACH__ semaphore_t m_semaphore; int semcount; #else diff --git a/src/jthread/pthread/jevent.cpp b/src/jthread/pthread/jevent.cpp index e1d40f4c1..6a45a37d2 100644 --- a/src/jthread/pthread/jevent.cpp +++ b/src/jthread/pthread/jevent.cpp @@ -29,7 +29,7 @@ #define UNUSED(expr) do { (void)(expr); } while (0) -#if defined(__MACH__) && defined(__APPLE__) +#ifdef __MACH__ #undef sem_t #define sem_t semaphore_t #undef sem_init diff --git a/src/jthread/pthread/jsemaphore.cpp b/src/jthread/pthread/jsemaphore.cpp index 15281ba64..16e001e92 100644 --- a/src/jthread/pthread/jsemaphore.cpp +++ b/src/jthread/pthread/jsemaphore.cpp @@ -20,13 +20,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include "jthread/jsemaphore.h" -#if defined(__MACH__) && defined(__APPLE__) +#ifdef __MACH__ #include #endif #define UNUSED(expr) do { (void)(expr); } while (0) -#if defined(__MACH__) && defined(__APPLE__) +#ifdef __MACH__ #undef sem_t #undef sem_init #undef sem_wait @@ -44,7 +44,7 @@ JSemaphore::JSemaphore() { int sem_init_retval = sem_init(&m_semaphore,0,0); assert(sem_init_retval == 0); UNUSED(sem_init_retval); -#if defined(__MACH__) && defined(__APPLE__) +#ifdef __MACH__ semcount = 0; #endif } @@ -73,7 +73,7 @@ void JSemaphore::Post() { int sem_post_retval = sem_post(&m_semaphore); assert(sem_post_retval == 0); UNUSED(sem_post_retval); -#if defined(__MACH__) && defined(__APPLE__) +#ifdef __MACH__ pthread_mutex_lock(&semcount_mutex); semcount++; pthread_mutex_unlock(&semcount_mutex); @@ -84,7 +84,7 @@ void JSemaphore::Wait() { int sem_wait_retval = sem_wait(&m_semaphore); assert(sem_wait_retval == 0); UNUSED(sem_wait_retval); -#if defined(__MACH__) && defined(__APPLE__) +#ifdef __MACH__ pthread_mutex_lock(&semcount_mutex); semcount--; pthread_mutex_unlock(&semcount_mutex); @@ -92,7 +92,7 @@ void JSemaphore::Wait() { } bool JSemaphore::Wait(unsigned int time_ms) { -#if defined(__MACH__) && defined(__APPLE__) +#ifdef __MACH__ mach_timespec_t waittime; waittime.tv_sec = time_ms / 1000; waittime.tv_nsec = 1000000 * (time_ms % 1000); @@ -106,14 +106,14 @@ bool JSemaphore::Wait(unsigned int time_ms) { return false; } -#if !(defined(__MACH__) && defined(__APPLE__)) +#ifndef __MACH__ waittime.tv_nsec = ((time_ms % 1000) * 1000 * 1000) + (now.tv_usec * 1000); waittime.tv_sec = (time_ms / 1000) + (waittime.tv_nsec / (1000*1000*1000)) + now.tv_sec; waittime.tv_nsec %= 1000*1000*1000; #endif errno = 0; -#if defined(__MACH__) && defined(__APPLE__) +#ifdef __MACH__ int sem_wait_retval = semaphore_timedwait(m_semaphore, waittime); if (sem_wait_retval == KERN_OPERATION_TIMED_OUT) { errno = ETIMEDOUT; @@ -128,7 +128,7 @@ bool JSemaphore::Wait(unsigned int time_ms) { if (sem_wait_retval == 0) { -#if defined(__MACH__) && defined(__APPLE__) +#ifdef __MACH__ pthread_mutex_lock(&semcount_mutex); semcount--; pthread_mutex_unlock(&semcount_mutex); @@ -144,7 +144,7 @@ bool JSemaphore::Wait(unsigned int time_ms) { int JSemaphore::GetValue() { int retval = 0; -#if defined(__MACH__) && defined(__APPLE__) +#ifdef __MACH__ pthread_mutex_lock(&semcount_mutex); retval = semcount; pthread_mutex_unlock(&semcount_mutex); diff --git a/src/keycode.cpp b/src/keycode.cpp index 27d0b6d50..c5f102b44 100644 --- a/src/keycode.cpp +++ b/src/keycode.cpp @@ -22,8 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "exceptions.h" #include "settings.h" #include "log.h" +#include "hex.h" #include "debug.h" -#include "util/hex.h" class UnknownKeycode : public BaseException { diff --git a/src/localplayer.cpp b/src/localplayer.cpp index cb183947a..69d4ec7ef 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -67,7 +67,7 @@ LocalPlayer::~LocalPlayer() } void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, - std::vector *collision_info) + std::list *collision_info) { Map *map = &env->getMap(); INodeDefManager *nodemgr = m_gamedef->ndef(); @@ -323,8 +323,9 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, */ bool bouncy_jump = false; // Dont report if flying - if(collision_info && !(g_settings->getBool("free_move") && fly_allowed)) { - for(size_t i=0; igetBool("free_move") && fly_allowed)) + { + for(size_t i=0; ipush_back(info); if(info.new_speed.Y - info.old_speed.Y > 0.1*BS && diff --git a/src/localplayer.h b/src/localplayer.h index 2a4a9dfc7..16b66716d 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -48,7 +48,7 @@ public: void move(f32 dtime, Environment *env, f32 pos_max_d); void move(f32 dtime, Environment *env, f32 pos_max_d, - std::vector *collision_info); + std::list *collision_info); void applyControl(float dtime); diff --git a/src/log.cpp b/src/log.cpp index 398c89eb0..b3b3f3f1b 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -24,14 +24,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include "threads.h" -#include "jthread/jmutexautolock.h" #include "debug.h" #include "gettime.h" #include "porting.h" #include "config.h" #ifdef __ANDROID__ -unsigned int android_log_level_mapping[] = { +unsigned int android_log_level_mapping[] { /* LMT_ERROR */ ANDROID_LOG_ERROR, /* LMT_ACTION */ ANDROID_LOG_WARN, /* LMT_INFO */ ANDROID_LOG_INFO, @@ -39,7 +38,7 @@ unsigned int android_log_level_mapping[] = { }; #endif -std::vector log_outputs[LMT_NUM_VALUES]; +std::list log_outputs[LMT_NUM_VALUES]; std::map log_threadnames; JMutex log_threadnamemutex; @@ -63,7 +62,7 @@ void log_add_output_all_levs(ILogOutput *out) void log_remove_output(ILogOutput *out) { for(int i=0; i::iterator it = + std::list::iterator it = std::find(log_outputs[i].begin(), log_outputs[i].end(), out); if(it != log_outputs[i].end()) log_outputs[i].erase(it); @@ -72,29 +71,33 @@ void log_remove_output(ILogOutput *out) void log_set_lev_silence(enum LogMessageLevel lev, bool silence) { - JMutexAutoLock lock(log_threadnamemutex); + log_threadnamemutex.Lock(); - for (std::vector::iterator it = log_outputs[lev].begin(); - it != log_outputs[lev].end(); ++it) { + for (std::list::iterator + it = log_outputs[lev].begin(); + it != log_outputs[lev].end(); + ++it) { ILogOutput *out = *it; out->silence = silence; } + + log_threadnamemutex.Unlock(); } void log_register_thread(const std::string &name) { threadid_t id = get_current_thread_id(); - JMutexAutoLock lock(log_threadnamemutex); - + log_threadnamemutex.Lock(); log_threadnames[id] = name; + log_threadnamemutex.Unlock(); } void log_deregister_thread() { threadid_t id = get_current_thread_id(); - JMutexAutoLock lock(log_threadnamemutex); - + log_threadnamemutex.Lock(); log_threadnames.erase(id); + log_threadnamemutex.Unlock(); } static std::string get_lev_string(enum LogMessageLevel lev) @@ -116,7 +119,7 @@ static std::string get_lev_string(enum LogMessageLevel lev) void log_printline(enum LogMessageLevel lev, const std::string &text) { - JMutexAutoLock lock(log_threadnamemutex); + log_threadnamemutex.Lock(); std::string threadname = "(unknown thread)"; std::map::const_iterator i; i = log_threadnames.find(get_current_thread_id()); @@ -124,10 +127,9 @@ void log_printline(enum LogMessageLevel lev, const std::string &text) threadname = i->second; std::string levelname = get_lev_string(lev); std::ostringstream os(std::ios_base::binary); - os << getTimestamp() << ": " << levelname << "["<::iterator i = log_outputs[lev].begin(); - i != log_outputs[lev].end(); i++) { + os<::iterator i = log_outputs[lev].begin(); + i != log_outputs[lev].end(); i++){ ILogOutput *out = *i; if (out->silence) continue; @@ -136,6 +138,7 @@ void log_printline(enum LogMessageLevel lev, const std::string &text) out->printLog(os.str(), lev); out->printLog(lev, text); } + log_threadnamemutex.Unlock(); } class Logbuf : public std::streambuf diff --git a/src/lua/CMakeLists.txt b/src/lua/CMakeLists.txt index 4bfe318ee..36e271889 100644 --- a/src/lua/CMakeLists.txt +++ b/src/lua/CMakeLists.txt @@ -47,6 +47,10 @@ else() endif() mark_as_advanced(LUA_USE_DLOPEN) +if(DEFAULT_POSIX) +else() +endif() + if(DEFAULT_ANSI) option(LUA_ANSI "Disable non-ansi features." ON) else() @@ -83,10 +87,6 @@ if(LUA_USE_DLOPEN) endif(NOT APPLE) endif(LUA_USE_DLOPEN) -if(DEFAULT_POSIX) - set(COMMON_CFLAGS "${COMMON_CFLAGS} -DLUA_USE_POSIX") -endif(DEFAULT_POSIX) - if(LUA_ANSI) set(COMMON_CFLAGS "${COMMON_CFLAGS} -DLUA_ANSI") endif(LUA_ANSI) diff --git a/src/lua/src/lauxlib.c b/src/lua/src/lauxlib.c index be41ebcd3..10f14e2c0 100644 --- a/src/lua/src/lauxlib.c +++ b/src/lua/src/lauxlib.c @@ -574,8 +574,7 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ if (lf.f == NULL) return errfile(L, "reopen", fnameindex); /* skip eventual `#!...' */ - while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) - {} + while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; lf.extraline = 0; } ungetc(c, lf.f); diff --git a/src/main.cpp b/src/main.cpp index a01ddec93..bbf88e80d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,6 +17,19 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef NDEBUG + /*#ifdef _WIN32 + #pragma message ("Disabling unit tests") + #else + #warning "Disabling unit tests" + #endif*/ + // Disable unit tests + #define ENABLE_TESTS 0 +#else + // Enable unit tests + #define ENABLE_TESTS 1 +#endif + #ifdef _MSC_VER #ifndef SERVER // Dedicated server isn't linked with Irrlicht #pragma comment(lib, "Irrlicht.lib") @@ -31,28 +44,48 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "main.h" #include "mainmenumanager.h" +#include +#include +#include #include "irrlichttypes_extrabloated.h" #include "debug.h" #include "test.h" +#include "clouds.h" #include "server.h" +#include "constants.h" +#include "porting.h" +#include "gettime.h" #include "filesys.h" +#include "config.h" #include "version.h" #include "guiMainMenu.h" #include "game.h" +#include "keycode.h" +#include "tile.h" +#include "chat.h" #include "defaultsettings.h" #include "gettext.h" +#include "settings.h" #include "profiler.h" #include "log.h" +#include "mods.h" +#include "util/string.h" +#include "subgame.h" #include "quicktune.h" +#include "serverlist.h" #include "httpfetch.h" #include "guiEngine.h" -#include "map.h" #include "mapsector.h" +#include "player.h" #include "fontengine.h" -#include "gameparams.h" -#include "database.h" -#ifndef SERVER -#include "client/clientlauncher.h" + +#include "database-sqlite3.h" +#ifdef USE_LEVELDB +#include "database-leveldb.h" +#endif + +#if USE_REDIS +#include "database-redis.h" #endif #ifdef HAVE_TOUCHSCREENGUI @@ -96,6 +129,14 @@ std::ostream *derr_client_ptr = &errorstream; typedef std::map OptionList; +struct GameParams { + u16 socket_port; + std::string world_path; + SubgameSpec game_spec; + bool is_dedicated_server; + int log_level; +}; + /********************************************************************** * Private functions **********************************************************************/ @@ -133,7 +174,13 @@ static bool get_game_from_cmdline(GameParams *game_params, const Settings &cmd_a static bool determine_subgame(GameParams *game_params); static bool run_dedicated_server(const GameParams &game_params, const Settings &cmd_args); -static bool migrate_database(const GameParams &game_params, const Settings &cmd_args); +static bool migrate_database(const GameParams &game_params, const Settings &cmd_args, + Server *server); + +#ifndef SERVER +static bool print_video_modes(); +static void speed_tests(); +#endif /**********************************************************************/ @@ -174,6 +221,61 @@ u32 getTime(TimePrecision prec) return porting::getTime(prec); } +#else + +// A small helper class +class TimeGetter +{ +public: + virtual u32 getTime(TimePrecision prec) = 0; +}; + +// A precise irrlicht one +class IrrlichtTimeGetter: public TimeGetter +{ +public: + IrrlichtTimeGetter(IrrlichtDevice *device): + m_device(device) + {} + u32 getTime(TimePrecision prec) + { + if (prec == PRECISION_MILLI) { + if (m_device == NULL) + return 0; + return m_device->getTimer()->getRealTime(); + } else { + return porting::getTime(prec); + } + } +private: + IrrlichtDevice *m_device; +}; +// Not so precise one which works without irrlicht +class SimpleTimeGetter: public TimeGetter +{ +public: + u32 getTime(TimePrecision prec) + { + return porting::getTime(prec); + } +}; + +// A pointer to a global instance of the time getter +// TODO: why? +TimeGetter *g_timegetter = NULL; + +u32 getTimeMs() +{ + if (g_timegetter == NULL) + return 0; + return g_timegetter->getTime(PRECISION_MILLI); +} + +u32 getTime(TimePrecision prec) { + if (g_timegetter == NULL) + return 0; + return g_timegetter->getTime(prec); +} #endif class StderrLogOutput: public ILogOutput @@ -196,6 +298,482 @@ public: } } main_dstream_no_stderr_log_out; +#ifndef SERVER + +/* + Event handler for Irrlicht + + NOTE: Everything possible should be moved out from here, + probably to InputHandler and the_game +*/ + +class MyEventReceiver : public IEventReceiver +{ +public: + // This is the one method that we have to implement + virtual bool OnEvent(const SEvent& event) + { + /* + React to nothing here if a menu is active + */ + if (noMenuActive() == false) { +#ifdef HAVE_TOUCHSCREENGUI + if (m_touchscreengui != 0) { + m_touchscreengui->Toggle(false); + } +#endif + return g_menumgr.preprocessEvent(event); + } + + // Remember whether each key is down or up + if (event.EventType == irr::EET_KEY_INPUT_EVENT) { + if (event.KeyInput.PressedDown) { + keyIsDown.set(event.KeyInput); + keyWasDown.set(event.KeyInput); + } else { + keyIsDown.unset(event.KeyInput); + } + } + +#ifdef HAVE_TOUCHSCREENGUI + // case of touchscreengui we have to handle different events + if ((m_touchscreengui != 0) && + (event.EventType == irr::EET_TOUCH_INPUT_EVENT)) { + m_touchscreengui->translateEvent(event); + return true; + } +#endif + // handle mouse events + if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) { + if (noMenuActive() == false) { + left_active = false; + middle_active = false; + right_active = false; + } else { + left_active = event.MouseInput.isLeftPressed(); + middle_active = event.MouseInput.isMiddlePressed(); + right_active = event.MouseInput.isRightPressed(); + + if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { + leftclicked = true; + } + if (event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN) { + rightclicked = true; + } + if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) { + leftreleased = true; + } + if (event.MouseInput.Event == EMIE_RMOUSE_LEFT_UP) { + rightreleased = true; + } + if (event.MouseInput.Event == EMIE_MOUSE_WHEEL) { + mouse_wheel += event.MouseInput.Wheel; + } + } + } + if (event.EventType == irr::EET_LOG_TEXT_EVENT) { + dstream << std::string("Irrlicht log: ") + std::string(event.LogEvent.Text) + << std::endl; + return true; + } + /* always return false in order to continue processing events */ + return false; + } + + bool IsKeyDown(const KeyPress &keyCode) const + { + return keyIsDown[keyCode]; + } + + // Checks whether a key was down and resets the state + bool WasKeyDown(const KeyPress &keyCode) + { + bool b = keyWasDown[keyCode]; + if (b) + keyWasDown.unset(keyCode); + return b; + } + + s32 getMouseWheel() + { + s32 a = mouse_wheel; + mouse_wheel = 0; + return a; + } + + void clearInput() + { + keyIsDown.clear(); + keyWasDown.clear(); + + leftclicked = false; + rightclicked = false; + leftreleased = false; + rightreleased = false; + + left_active = false; + middle_active = false; + right_active = false; + + mouse_wheel = 0; + } + + MyEventReceiver() + { + clearInput(); +#ifdef HAVE_TOUCHSCREENGUI + m_touchscreengui = NULL; +#endif + } + + bool leftclicked; + bool rightclicked; + bool leftreleased; + bool rightreleased; + + bool left_active; + bool middle_active; + bool right_active; + + s32 mouse_wheel; + +#ifdef HAVE_TOUCHSCREENGUI + TouchScreenGUI* m_touchscreengui; +#endif + +private: + // The current state of keys + KeyList keyIsDown; + // Whether a key has been pressed or not + KeyList keyWasDown; +}; + +/* + Separated input handler +*/ + +class RealInputHandler : public InputHandler +{ +public: + RealInputHandler(IrrlichtDevice *device, MyEventReceiver *receiver): + m_device(device), + m_receiver(receiver), + m_mousepos(0,0) + { + } + virtual bool isKeyDown(const KeyPress &keyCode) + { + return m_receiver->IsKeyDown(keyCode); + } + virtual bool wasKeyDown(const KeyPress &keyCode) + { + return m_receiver->WasKeyDown(keyCode); + } + virtual v2s32 getMousePos() + { + if (m_device->getCursorControl()) { + return m_device->getCursorControl()->getPosition(); + } + else { + return m_mousepos; + } + } + virtual void setMousePos(s32 x, s32 y) + { + if (m_device->getCursorControl()) { + m_device->getCursorControl()->setPosition(x, y); + } + else { + m_mousepos = v2s32(x,y); + } + } + + virtual bool getLeftState() + { + return m_receiver->left_active; + } + virtual bool getRightState() + { + return m_receiver->right_active; + } + + virtual bool getLeftClicked() + { + return m_receiver->leftclicked; + } + virtual bool getRightClicked() + { + return m_receiver->rightclicked; + } + virtual void resetLeftClicked() + { + m_receiver->leftclicked = false; + } + virtual void resetRightClicked() + { + m_receiver->rightclicked = false; + } + + virtual bool getLeftReleased() + { + return m_receiver->leftreleased; + } + virtual bool getRightReleased() + { + return m_receiver->rightreleased; + } + virtual void resetLeftReleased() + { + m_receiver->leftreleased = false; + } + virtual void resetRightReleased() + { + m_receiver->rightreleased = false; + } + + virtual s32 getMouseWheel() + { + return m_receiver->getMouseWheel(); + } + + void clear() + { + m_receiver->clearInput(); + } +private: + IrrlichtDevice *m_device; + MyEventReceiver *m_receiver; + v2s32 m_mousepos; +}; + +class RandomInputHandler : public InputHandler +{ +public: + RandomInputHandler() + { + leftdown = false; + rightdown = false; + leftclicked = false; + rightclicked = false; + leftreleased = false; + rightreleased = false; + keydown.clear(); + } + virtual bool isKeyDown(const KeyPress &keyCode) + { + return keydown[keyCode]; + } + virtual bool wasKeyDown(const KeyPress &keyCode) + { + return false; + } + virtual v2s32 getMousePos() + { + return mousepos; + } + virtual void setMousePos(s32 x, s32 y) + { + mousepos = v2s32(x, y); + } + + virtual bool getLeftState() + { + return leftdown; + } + virtual bool getRightState() + { + return rightdown; + } + + virtual bool getLeftClicked() + { + return leftclicked; + } + virtual bool getRightClicked() + { + return rightclicked; + } + virtual void resetLeftClicked() + { + leftclicked = false; + } + virtual void resetRightClicked() + { + rightclicked = false; + } + + virtual bool getLeftReleased() + { + return leftreleased; + } + virtual bool getRightReleased() + { + return rightreleased; + } + virtual void resetLeftReleased() + { + leftreleased = false; + } + virtual void resetRightReleased() + { + rightreleased = false; + } + + virtual s32 getMouseWheel() + { + return 0; + } + + virtual void step(float dtime) + { + { + static float counter1 = 0; + counter1 -= dtime; + if (counter1 < 0.0) { + counter1 = 0.1 * Rand(1, 40); + keydown.toggle(getKeySetting("keymap_jump")); + } + } + { + static float counter1 = 0; + counter1 -= dtime; + if (counter1 < 0.0) { + counter1 = 0.1 * Rand(1, 40); + keydown.toggle(getKeySetting("keymap_special1")); + } + } + { + static float counter1 = 0; + counter1 -= dtime; + if (counter1 < 0.0) { + counter1 = 0.1 * Rand(1, 40); + keydown.toggle(getKeySetting("keymap_forward")); + } + } + { + static float counter1 = 0; + counter1 -= dtime; + if (counter1 < 0.0) { + counter1 = 0.1 * Rand(1, 40); + keydown.toggle(getKeySetting("keymap_left")); + } + } + { + static float counter1 = 0; + counter1 -= dtime; + if (counter1 < 0.0) { + counter1 = 0.1 * Rand(1, 20); + mousespeed = v2s32(Rand(-20, 20), Rand(-15, 20)); + } + } + { + static float counter1 = 0; + counter1 -= dtime; + if (counter1 < 0.0) { + counter1 = 0.1 * Rand(1, 30); + leftdown = !leftdown; + if (leftdown) + leftclicked = true; + if (!leftdown) + leftreleased = true; + } + } + { + static float counter1 = 0; + counter1 -= dtime; + if (counter1 < 0.0) { + counter1 = 0.1 * Rand(1, 15); + rightdown = !rightdown; + if (rightdown) + rightclicked = true; + if (!rightdown) + rightreleased = true; + } + } + mousepos += mousespeed; + } + + s32 Rand(s32 min, s32 max) + { + return (myrand()%(max-min+1))+min; + } +private: + KeyList keydown; + v2s32 mousepos; + v2s32 mousespeed; + bool leftdown; + bool rightdown; + bool leftclicked; + bool rightclicked; + bool leftreleased; + bool rightreleased; +}; + + +class ClientLauncher +{ +public: + ClientLauncher() : + list_video_modes(false), + skip_main_menu(false), + use_freetype(false), + random_input(false), + address(""), + playername(""), + password(""), + device(NULL), + input(NULL), + receiver(NULL), + skin(NULL), + font(NULL), + simple_singleplayer_mode(false), + current_playername("inv£lid"), + current_password(""), + current_address("does-not-exist"), + current_port(0) + {} + + ~ClientLauncher(); + + bool run(GameParams &game_params, const Settings &cmd_args); + +protected: + void init_args(GameParams &game_params, const Settings &cmd_args); + bool init_engine(int log_level); + + bool launch_game(std::wstring *error_message, GameParams &game_params, + const Settings &cmd_args); + + void main_menu(MainMenuData *menudata); + bool create_engine_device(int log_level); + + bool list_video_modes; + bool skip_main_menu; + bool use_freetype; + bool random_input; + std::string address; + std::string playername; + std::string password; + IrrlichtDevice *device; + InputHandler *input; + MyEventReceiver *receiver; + gui::IGUISkin *skin; + gui::IGUIFont *font; + scene::ISceneManager *smgr; + SubgameSpec gamespec; + WorldSpec worldspec; + bool simple_singleplayer_mode; + + // These are set up based on the menu and other things + // TODO: Are these required since there's already playername, password, etc + std::string current_playername; + std::string current_password; + std::string current_address; + int current_port; +}; + +#endif // !SERVER + static OptionList allowed_options; int main(int argc, char *argv[]) @@ -258,9 +836,9 @@ int main(int argc, char *argv[]) #ifndef __ANDROID__ // Run unit tests - if (cmd_args.getFlag("run-unittests")) { + if ((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false) + || cmd_args.getFlag("enable-unittests") == true) { run_tests(); - return 0; } #endif @@ -331,8 +909,10 @@ static void set_allowed_options(OptionList *allowed_options) _("Load configuration from specified file")))); allowed_options->insert(std::make_pair("port", ValueSpec(VALUETYPE_STRING, _("Set network port (UDP)")))); - allowed_options->insert(std::make_pair("run-unittests", ValueSpec(VALUETYPE_FLAG, - _("Run the unit tests and exit")))); + allowed_options->insert(std::make_pair("disable-unittests", ValueSpec(VALUETYPE_FLAG, + _("Disable unit tests")))); + allowed_options->insert(std::make_pair("enable-unittests", ValueSpec(VALUETYPE_FLAG, + _("Enable unit tests")))); allowed_options->insert(std::make_pair("map-dir", ValueSpec(VALUETYPE_STRING, _("Same as --world (deprecated)")))); allowed_options->insert(std::make_pair("world", ValueSpec(VALUETYPE_STRING, @@ -886,14 +1466,14 @@ static bool run_dedicated_server(const GameParams &game_params, const Settings & return false; } - // Database migration - if (cmd_args.exists("migrate")) - return migrate_database(game_params, cmd_args); - // Create server Server server(game_params.world_path, game_params.game_spec, false, bind_addr.isIPv6()); + // Database migration + if (cmd_args.exists("migrate")) + return migrate_database(game_params, cmd_args, &server); + server.start(bind_addr); // Run server @@ -903,63 +1483,79 @@ static bool run_dedicated_server(const GameParams &game_params, const Settings & return true; } -static bool migrate_database(const GameParams &game_params, const Settings &cmd_args) +static bool migrate_database(const GameParams &game_params, const Settings &cmd_args, + Server *server) { - std::string migrate_to = cmd_args.get("migrate"); Settings world_mt; - std::string world_mt_path = game_params.world_path + DIR_DELIM + "world.mt"; - if (!world_mt.readConfigFile(world_mt_path.c_str())) { - errorstream << "Cannot read world.mt!" << std::endl; + bool success = world_mt.readConfigFile((game_params.world_path + + DIR_DELIM + "world.mt").c_str()); + if (!success) { + errorstream << "Cannot read world.mt" << std::endl; return false; } + if (!world_mt.exists("backend")) { - errorstream << "Please specify your current backend in world.mt:" - << std::endl - << " backend = {sqlite3|leveldb|redis|dummy}" - << std::endl; + errorstream << "Please specify your current backend in world.mt file:" + << std::endl << " backend = {sqlite3|leveldb|redis|dummy}" + << std::endl; return false; } + std::string backend = world_mt.get("backend"); + Database *new_db; + std::string migrate_to = cmd_args.get("migrate"); + if (backend == migrate_to) { - errorstream << "Cannot migrate: new backend is same" - << " as the old one" << std::endl; + errorstream << "Cannot migrate: new backend is same as the old one" + << std::endl; return false; } - Database *old_db = ServerMap::createDatabase(backend, game_params.world_path, world_mt), - *new_db = ServerMap::createDatabase(migrate_to, game_params.world_path, world_mt); - u32 count = 0; - time_t last_update_time = 0; - bool &kill = *porting::signal_handler_killstatus(); - - std::vector blocks; - old_db->listAllLoadableBlocks(blocks); - new_db->beginSave(); - for (std::vector::const_iterator it = blocks.begin(); it != blocks.end(); ++it) { - if (kill) return false; - - const std::string &data = old_db->loadBlock(*it); - if (!data.empty()) { - new_db->saveBlock(*it, data); - } else { - errorstream << "Failed to load block " << PP(*it) << ", skipping it." << std::endl; - } - if (++count % 0xFF == 0 && time(NULL) - last_update_time >= 1) { - std::cerr << " Migrated " << count << " blocks, " - << (100.0 * count / blocks.size()) << "% completed.\r"; - new_db->endSave(); - new_db->beginSave(); - last_update_time = time(NULL); - } + if (migrate_to == "sqlite3") + new_db = new Database_SQLite3(&(ServerMap&)server->getMap(), + game_params.world_path); +#if USE_LEVELDB + else if (migrate_to == "leveldb") + new_db = new Database_LevelDB(&(ServerMap&)server->getMap(), + game_params.world_path); +#endif +#if USE_REDIS + else if (migrate_to == "redis") + new_db = new Database_Redis(&(ServerMap&)server->getMap(), + game_params.world_path); +#endif + else { + errorstream << "Migration to " << migrate_to << " is not supported" + << std::endl; + return false; + } + + std::list blocks; + ServerMap &old_map = ((ServerMap&)server->getMap()); + old_map.listAllLoadableBlocks(blocks); + int count = 0; + new_db->beginSave(); + for (std::list::iterator i = blocks.begin(); i != blocks.end(); i++) { + MapBlock *block = old_map.loadBlock(*i); + if (!block) { + errorstream << "Failed to load block " << PP(*i) << ", skipping it."; + } else { + old_map.saveBlock(block, new_db); + MapSector *sector = old_map.getSectorNoGenerate(v2s16(i->X, i->Z)); + sector->deleteBlock(block); + } + ++count; + if (count % 500 == 0) + actionstream << "Migrated " << count << " blocks " + << (100.0 * count / blocks.size()) << "% completed" << std::endl; } - std::cerr << std::endl; new_db->endSave(); - delete old_db; delete new_db; actionstream << "Successfully migrated " << count << " blocks" << std::endl; world_mt.set("backend", migrate_to); - if (!world_mt.updateConfigFile(world_mt_path.c_str())) + if (!world_mt.updateConfigFile( + (game_params.world_path+ DIR_DELIM + "world.mt").c_str())) errorstream << "Failed to update world.mt!" << std::endl; else actionstream << "world.mt updated" << std::endl; @@ -967,3 +1563,671 @@ static bool migrate_database(const GameParams &game_params, const Settings &cmd_ return true; } + +/***************************************************************************** + * Client + *****************************************************************************/ +#ifndef SERVER + +ClientLauncher::~ClientLauncher() +{ + if (receiver) + delete receiver; + + if (input) + delete input; + + if (g_fontengine) + delete g_fontengine; + + if (device) + device->drop(); +} + + +bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args) +{ + init_args(game_params, cmd_args); + + // List video modes if requested + if (list_video_modes) + return print_video_modes(); + + if (!init_engine(game_params.log_level)) { + errorstream << "Could not initialize game engine." << std::endl; + return false; + } + + // Speed tests (done after irrlicht is loaded to get timer) + if (cmd_args.getFlag("speedtests")) { + dstream << "Running speed tests" << std::endl; + speed_tests(); + return true; + } + + video::IVideoDriver *video_driver = device->getVideoDriver(); + if (video_driver == NULL) { + errorstream << "Could not initialize video driver." << std::endl; + return false; + } + + porting::setXorgClassHint(video_driver->getExposedVideoData(), "Minetest"); + + /* + This changes the minimum allowed number of vertices in a VBO. + Default is 500. + */ + //driver->setMinHardwareBufferVertexCount(50); + + // Create time getter + g_timegetter = new IrrlichtTimeGetter(device); + + // Create game callback for menus + g_gamecallback = new MainGameCallback(device); + + device->setResizable(true); + + if (random_input) + input = new RandomInputHandler(); + else + input = new RealInputHandler(device, receiver); + + smgr = device->getSceneManager(); + + guienv = device->getGUIEnvironment(); + skin = guienv->getSkin(); + skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255, 255, 255, 255)); + skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255, 0, 0, 0)); + skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255, 0, 0, 0)); + skin->setColor(gui::EGDC_HIGH_LIGHT, video::SColor(255, 70, 100, 50)); + skin->setColor(gui::EGDC_HIGH_LIGHT_TEXT, video::SColor(255, 255, 255, 255)); + + g_fontengine = new FontEngine(g_settings, guienv); + assert(g_fontengine != NULL); + +#if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2 + // Irrlicht 1.8 input colours + skin->setColor(gui::EGDC_EDITABLE, video::SColor(255, 128, 128, 128)); + skin->setColor(gui::EGDC_FOCUSED_EDITABLE, video::SColor(255, 96, 134, 49)); +#endif + + // Create the menu clouds + if (!g_menucloudsmgr) + g_menucloudsmgr = smgr->createNewSceneManager(); + if (!g_menuclouds) + g_menuclouds = new Clouds(g_menucloudsmgr->getRootSceneNode(), + g_menucloudsmgr, -1, rand(), 100); + g_menuclouds->update(v2f(0, 0), video::SColor(255, 200, 200, 255)); + scene::ICameraSceneNode* camera; + camera = g_menucloudsmgr->addCameraSceneNode(0, + v3f(0, 0, 0), v3f(0, 60, 100)); + camera->setFarValue(10000); + + /* + GUI stuff + */ + + ChatBackend chat_backend; + + // If an error occurs, this is set to something by menu(). + // It is then displayed before the menu shows on the next call to menu() + std::wstring error_message = L""; + + bool first_loop = true; + + /* + Menu-game loop + */ + bool retval = true; + bool *kill = porting::signal_handler_killstatus(); + + while (device->run() && !*kill && !g_gamecallback->shutdown_requested) + { + // Set the window caption + const wchar_t *text = wgettext("Main Menu"); + device->setWindowCaption((std::wstring(L"Minetest [") + text + L"]").c_str()); + delete[] text; + + try { // This is used for catching disconnects + + guienv->clear(); + + /* + We need some kind of a root node to be able to add + custom gui elements directly on the screen. + Otherwise they won't be automatically drawn. + */ + guiroot = guienv->addStaticText(L"", core::rect(0, 0, 10000, 10000)); + + bool game_has_run = launch_game(&error_message, game_params, cmd_args); + + // If skip_main_menu, we only want to startup once + if (skip_main_menu && !first_loop) + break; + + first_loop = false; + + if (!game_has_run) { + if (skip_main_menu) + break; + else + continue; + } + + // Break out of menu-game loop to shut down cleanly + if (!device->run() || *kill) { + if (g_settings_path != "") + g_settings->updateConfigFile(g_settings_path.c_str()); + break; + } + + if (current_playername.length() > PLAYERNAME_SIZE-1) { + error_message = wgettext("Player name too long."); + playername = current_playername.substr(0, PLAYERNAME_SIZE-1); + g_settings->set("name", playername); + continue; + } + + device->getVideoDriver()->setTextureCreationFlag( + video::ETCF_CREATE_MIP_MAPS, g_settings->getBool("mip_map")); + +#ifdef HAVE_TOUCHSCREENGUI + receiver->m_touchscreengui = new TouchScreenGUI(device, receiver); + g_touchscreengui = receiver->m_touchscreengui; +#endif + the_game( + kill, + random_input, + input, + device, + worldspec.path, + current_playername, + current_password, + current_address, + current_port, + error_message, + chat_backend, + gamespec, + simple_singleplayer_mode + ); + smgr->clear(); + +#ifdef HAVE_TOUCHSCREENGUI + delete g_touchscreengui; + g_touchscreengui = NULL; + receiver->m_touchscreengui = NULL; +#endif + + } //try + catch (con::PeerNotFoundException &e) { + error_message = wgettext("Connection error (timed out?)"); + errorstream << wide_to_narrow(error_message) << std::endl; + } + +#ifdef NDEBUG + catch (std::exception &e) { + std::string narrow_message = "Some exception: \""; + narrow_message += e.what(); + narrow_message += "\""; + errorstream << narrow_message << std::endl; + error_message = narrow_to_wide(narrow_message); + } +#endif + + // If no main menu, show error and exit + if (skip_main_menu) { + if (error_message != L"") { + verbosestream << "error_message = " + << wide_to_narrow(error_message) << std::endl; + retval = false; + } + break; + } + } // Menu-game loop + + g_menuclouds->drop(); + g_menucloudsmgr->drop(); + + return retval; +} + +void ClientLauncher::init_args(GameParams &game_params, const Settings &cmd_args) +{ + + skip_main_menu = cmd_args.getFlag("go"); + + // FIXME: This is confusing (but correct) + + /* If world_path is set then override it unless skipping the main menu using + * the --go command line param. Else, give preference to the address + * supplied on the command line + */ + address = g_settings->get("address"); + if (game_params.world_path != "" && !skip_main_menu) + address = ""; + else if (cmd_args.exists("address")) + address = cmd_args.get("address"); + + playername = g_settings->get("name"); + if (cmd_args.exists("name")) + playername = cmd_args.get("name"); + + list_video_modes = cmd_args.getFlag("videomodes"); + + use_freetype = g_settings->getBool("freetype"); + + random_input = g_settings->getBool("random_input") + || cmd_args.getFlag("random-input"); +} + +bool ClientLauncher::init_engine(int log_level) +{ + receiver = new MyEventReceiver(); + create_engine_device(log_level); + return device != NULL; +} + +bool ClientLauncher::launch_game(std::wstring *error_message, + GameParams &game_params, const Settings &cmd_args) +{ + // Initialize menu data + MainMenuData menudata; + menudata.address = address; + menudata.name = playername; + menudata.port = itos(game_params.socket_port); + menudata.errormessage = wide_to_narrow(*error_message); + + *error_message = L""; + + if (cmd_args.exists("password")) + menudata.password = cmd_args.get("password"); + + menudata.enable_public = g_settings->getBool("server_announce"); + + // If a world was commanded, append and select it + if (game_params.world_path != "") { + worldspec.gameid = getWorldGameId(game_params.world_path, true); + worldspec.name = _("[--world parameter]"); + + if (worldspec.gameid == "") { // Create new + worldspec.gameid = g_settings->get("default_game"); + worldspec.name += " [new]"; + } + worldspec.path = game_params.world_path; + } + + /* Show the GUI menu + */ + if (!skip_main_menu) { + main_menu(&menudata); + + // Skip further loading if there was an exit signal. + if (*porting::signal_handler_killstatus()) + return false; + + address = menudata.address; + int newport = stoi(menudata.port); + if (newport != 0) + game_params.socket_port = newport; + + simple_singleplayer_mode = menudata.simple_singleplayer_mode; + + std::vector worldspecs = getAvailableWorlds(); + + if (menudata.selected_world >= 0 + && menudata.selected_world < (int)worldspecs.size()) { + g_settings->set("selected_world_path", + worldspecs[menudata.selected_world].path); + worldspec = worldspecs[menudata.selected_world]; + } + } + + if (menudata.errormessage != "") { + /* The calling function will pass this back into this function upon the + * next iteration (if any) causing it to be displayed by the GUI + */ + *error_message = narrow_to_wide(menudata.errormessage); + return false; + } + + if (menudata.name == "") + menudata.name = std::string("Guest") + itos(myrand_range(1000, 9999)); + else + playername = menudata.name; + + password = translatePassword(playername, narrow_to_wide(menudata.password)); + + g_settings->set("name", playername); + + current_playername = playername; + current_password = password; + current_address = address; + current_port = game_params.socket_port; + + // If using simple singleplayer mode, override + if (simple_singleplayer_mode) { + assert(skip_main_menu == false); + current_playername = "singleplayer"; + current_password = ""; + current_address = ""; + current_port = myrand_range(49152, 65535); + } else if (address != "") { + ServerListSpec server; + server["name"] = menudata.servername; + server["address"] = menudata.address; + server["port"] = menudata.port; + server["description"] = menudata.serverdescription; + ServerList::insert(server); + } + + infostream << "Selected world: " << worldspec.name + << " [" << worldspec.path << "]" << std::endl; + + if (current_address == "") { // If local game + if (worldspec.path == "") { + *error_message = wgettext("No world selected and no address " + "provided. Nothing to do."); + errorstream << wide_to_narrow(*error_message) << std::endl; + return false; + } + + if (!fs::PathExists(worldspec.path)) { + *error_message = wgettext("Provided world path doesn't exist: ") + + narrow_to_wide(worldspec.path); + errorstream << wide_to_narrow(*error_message) << std::endl; + return false; + } + + // Load gamespec for required game + gamespec = findWorldSubgame(worldspec.path); + if (!gamespec.isValid() && !game_params.game_spec.isValid()) { + *error_message = wgettext("Could not find or load game \"") + + narrow_to_wide(worldspec.gameid) + L"\""; + errorstream << wide_to_narrow(*error_message) << std::endl; + return false; + } + + if (porting::signal_handler_killstatus()) + return true; + + if (game_params.game_spec.isValid() && + game_params.game_spec.id != worldspec.gameid) { + errorstream << "WARNING: Overriding gamespec from \"" + << worldspec.gameid << "\" to \"" + << game_params.game_spec.id << "\"" << std::endl; + gamespec = game_params.game_spec; + } + + if (!gamespec.isValid()) { + *error_message = wgettext("Invalid gamespec."); + *error_message += L" (world_gameid=" + + narrow_to_wide(worldspec.gameid) + L")"; + errorstream << wide_to_narrow(*error_message) << std::endl; + return false; + } + } + + return true; +} + +void ClientLauncher::main_menu(MainMenuData *menudata) +{ + bool *kill = porting::signal_handler_killstatus(); + video::IVideoDriver *driver = device->getVideoDriver(); + + infostream << "Waiting for other menus" << std::endl; + while (device->run() && *kill == false) { + if (noMenuActive()) + break; + driver->beginScene(true, true, video::SColor(255, 128, 128, 128)); + guienv->drawAll(); + driver->endScene(); + // On some computers framerate doesn't seem to be automatically limited + sleep_ms(25); + } + infostream << "Waited for other menus" << std::endl; + + // Cursor can be non-visible when coming from the game +#ifndef ANDROID + device->getCursorControl()->setVisible(true); +#endif + + /* show main menu */ + GUIEngine mymenu(device, guiroot, &g_menumgr, smgr, menudata, *kill); + + smgr->clear(); /* leave scene manager in a clean state */ +} + +bool ClientLauncher::create_engine_device(int log_level) +{ + static const irr::ELOG_LEVEL irr_log_level[5] = { + ELL_NONE, + ELL_ERROR, + ELL_WARNING, + ELL_INFORMATION, +#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) + ELL_INFORMATION +#else + ELL_DEBUG +#endif + }; + + // Resolution selection + bool fullscreen = g_settings->getBool("fullscreen"); + u16 screenW = g_settings->getU16("screenW"); + u16 screenH = g_settings->getU16("screenH"); + + // bpp, fsaa, vsync + bool vsync = g_settings->getBool("vsync"); + u16 bits = g_settings->getU16("fullscreen_bpp"); + u16 fsaa = g_settings->getU16("fsaa"); + + // Determine driver + video::E_DRIVER_TYPE driverType = video::EDT_OPENGL; + std::string driverstring = g_settings->get("video_driver"); + std::vector drivers + = porting::getSupportedVideoDrivers(); + u32 i; + for (i = 0; i != drivers.size(); i++) { + if (!strcasecmp(driverstring.c_str(), + porting::getVideoDriverName(drivers[i]))) { + driverType = drivers[i]; + break; + } + } + if (i == drivers.size()) { + errorstream << "Invalid video_driver specified; " + "defaulting to opengl" << std::endl; + } + + SIrrlichtCreationParameters params = SIrrlichtCreationParameters(); + params.DriverType = driverType; + params.WindowSize = core::dimension2d(screenW, screenH); + params.Bits = bits; + params.AntiAlias = fsaa; + params.Fullscreen = fullscreen; + params.Stencilbuffer = false; + params.Vsync = vsync; + params.EventReceiver = receiver; + params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu"); +#ifdef __ANDROID__ + params.PrivateData = porting::app_global; + params.OGLES2ShaderPath = std::string(porting::path_user + DIR_DELIM + + "media" + DIR_DELIM + "Shaders" + DIR_DELIM).c_str(); +#endif + + device = createDeviceEx(params); + + if (device) { + // Map our log level to irrlicht engine one. + ILogger* irr_logger = device->getLogger(); + irr_logger->setLogLevel(irr_log_level[log_level]); + + porting::initIrrlicht(device); + } + + return device != NULL; +} + +// Misc functions + +static bool print_video_modes() +{ + IrrlichtDevice *nulldevice; + + bool vsync = g_settings->getBool("vsync"); + u16 fsaa = g_settings->getU16("fsaa"); + MyEventReceiver* receiver = new MyEventReceiver(); + + SIrrlichtCreationParameters params = SIrrlichtCreationParameters(); + params.DriverType = video::EDT_NULL; + params.WindowSize = core::dimension2d(640, 480); + params.Bits = 24; + params.AntiAlias = fsaa; + params.Fullscreen = false; + params.Stencilbuffer = false; + params.Vsync = vsync; + params.EventReceiver = receiver; + params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu"); + + nulldevice = createDeviceEx(params); + + if (nulldevice == NULL) { + delete receiver; + return false; + } + + dstream << _("Available video modes (WxHxD):") << std::endl; + + video::IVideoModeList *videomode_list = nulldevice->getVideoModeList(); + + if (videomode_list != NULL) { + s32 videomode_count = videomode_list->getVideoModeCount(); + core::dimension2d videomode_res; + s32 videomode_depth; + for (s32 i = 0; i < videomode_count; ++i) { + videomode_res = videomode_list->getVideoModeResolution(i); + videomode_depth = videomode_list->getVideoModeDepth(i); + dstream << videomode_res.Width << "x" << videomode_res.Height + << "x" << videomode_depth << std::endl; + } + + dstream << _("Active video mode (WxHxD):") << std::endl; + videomode_res = videomode_list->getDesktopResolution(); + videomode_depth = videomode_list->getDesktopDepth(); + dstream << videomode_res.Width << "x" << videomode_res.Height + << "x" << videomode_depth << std::endl; + + } + + nulldevice->drop(); + delete receiver; + + return videomode_list != NULL; +} + +#endif // !SERVER + +/***************************************************************************** + * Performance tests + *****************************************************************************/ +#ifndef SERVER +static void speed_tests() +{ + // volatile to avoid some potential compiler optimisations + volatile static s16 temp16; + volatile static f32 tempf; + static v3f tempv3f1; + static v3f tempv3f2; + static std::string tempstring; + static std::string tempstring2; + + tempv3f1 = v3f(); + tempv3f2 = v3f(); + tempstring = std::string(); + tempstring2 = std::string(); + + { + infostream << "The following test should take around 20ms." << std::endl; + TimeTaker timer("Testing std::string speed"); + const u32 jj = 10000; + for (u32 j = 0; j < jj; j++) { + tempstring = ""; + tempstring2 = ""; + const u32 ii = 10; + for (u32 i = 0; i < ii; i++) { + tempstring2 += "asd"; + } + for (u32 i = 0; i < ii+1; i++) { + tempstring += "asd"; + if (tempstring == tempstring2) + break; + } + } + } + + infostream << "All of the following tests should take around 100ms each." + << std::endl; + + { + TimeTaker timer("Testing floating-point conversion speed"); + tempf = 0.001; + for (u32 i = 0; i < 4000000; i++) { + temp16 += tempf; + tempf += 0.001; + } + } + + { + TimeTaker timer("Testing floating-point vector speed"); + + tempv3f1 = v3f(1, 2, 3); + tempv3f2 = v3f(4, 5, 6); + for (u32 i = 0; i < 10000000; i++) { + tempf += tempv3f1.dotProduct(tempv3f2); + tempv3f2 += v3f(7, 8, 9); + } + } + + { + TimeTaker timer("Testing std::map speed"); + + std::map map1; + tempf = -324; + const s16 ii = 300; + for (s16 y = 0; y < ii; y++) { + for (s16 x = 0; x < ii; x++) { + map1[v2s16(x, y)] = tempf; + tempf += 1; + } + } + for (s16 y = ii - 1; y >= 0; y--) { + for (s16 x = 0; x < ii; x++) { + tempf = map1[v2s16(x, y)]; + } + } + } + + { + infostream << "Around 5000/ms should do well here." << std::endl; + TimeTaker timer("Testing mutex speed"); + + JMutex m; + u32 n = 0; + u32 i = 0; + do { + n += 10000; + for (; i < n; i++) { + m.Lock(); + m.Unlock(); + } + } + // Do at least 10ms + while(timer.getTimerTime() < 10); + + u32 dtime = timer.stop(); + u32 per_ms = n / dtime; + infostream << "Done. " << dtime << "ms, " << per_ms << "/ms" << std::endl; + } +} +#endif diff --git a/src/map.cpp b/src/map.cpp index e80c82522..d8f018742 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -53,6 +53,22 @@ with this program; if not, write to the Free Software Foundation, Inc., #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" +/* + SQLite format specification: + - Initially only replaces sectors/ and sectors2/ + + If map.sqlite does not exist in the save dir + or the block was not found in the database + the map will try to load from sectors folder. + In either case, map.sqlite will be created + and all future saves will save there. + + Structure of map.sqlite: + Tables: + blocks + (PK) INT pos + BLOB data +*/ /* Map @@ -1405,39 +1421,43 @@ bool Map::getDayNightDiff(v3s16 blockpos) Updates usage timers */ void Map::timerUpdate(float dtime, float unload_timeout, - std::vector *unloaded_blocks) + std::list *unloaded_blocks) { bool save_before_unloading = (mapType() == MAPTYPE_SERVER); // Profile modified reasons Profiler modprofiler; - std::vector sector_deletion_queue; + std::list sector_deletion_queue; u32 deleted_blocks_count = 0; u32 saved_blocks_count = 0; u32 block_count_all = 0; beginSave(); for(std::map::iterator si = m_sectors.begin(); - si != m_sectors.end(); ++si) { + si != m_sectors.end(); ++si) + { MapSector *sector = si->second; bool all_blocks_deleted = true; - MapBlockVect blocks; + std::list blocks; sector->getBlocks(blocks); - for(MapBlockVect::iterator i = blocks.begin(); - i != blocks.end(); ++i) { + for(std::list::iterator i = blocks.begin(); + i != blocks.end(); ++i) + { MapBlock *block = (*i); block->incrementUsageTimer(dtime); - if(block->refGet() == 0 && block->getUsageTimer() > unload_timeout) { + if(block->refGet() == 0 && block->getUsageTimer() > unload_timeout) + { v3s16 p = block->getPos(); // Save if modified - if (block->getModified() != MOD_STATE_CLEAN && save_before_unloading) { + if (block->getModified() != MOD_STATE_CLEAN && save_before_unloading) + { modprofiler.add(block->getModifiedReason(), 1); if (!saveBlock(block)) continue; @@ -1452,13 +1472,15 @@ void Map::timerUpdate(float dtime, float unload_timeout, deleted_blocks_count++; } - else { + else + { all_blocks_deleted = false; block_count_all++; } } - if(all_blocks_deleted) { + if(all_blocks_deleted) + { sector_deletion_queue.push_back(si->first); } } @@ -1484,15 +1506,16 @@ void Map::timerUpdate(float dtime, float unload_timeout, } } -void Map::unloadUnreferencedBlocks(std::vector *unloaded_blocks) +void Map::unloadUnreferencedBlocks(std::list *unloaded_blocks) { timerUpdate(0.0, -1.0, unloaded_blocks); } -void Map::deleteSectors(std::vector §orList) +void Map::deleteSectors(std::list &list) { - for(std::vector::iterator j = sectorList.begin(); - j != sectorList.end(); ++j) { + for(std::list::iterator j = list.begin(); + j != list.end(); ++j) + { MapSector *sector = m_sectors[*j]; // If sector is in sector cache, remove it from there if(m_sector_cache == sector) @@ -1503,6 +1526,63 @@ void Map::deleteSectors(std::vector §orList) } } +#if 0 +void Map::unloadUnusedData(float timeout, + core::list *deleted_blocks) +{ + core::list sector_deletion_queue; + u32 deleted_blocks_count = 0; + u32 saved_blocks_count = 0; + + core::map::Iterator si = m_sectors.getIterator(); + for(; si.atEnd() == false; si++) + { + MapSector *sector = si.getNode()->getValue(); + + bool all_blocks_deleted = true; + + core::list blocks; + sector->getBlocks(blocks); + for(core::list::Iterator i = blocks.begin(); + i != blocks.end(); i++) + { + MapBlock *block = (*i); + + if(block->getUsageTimer() > timeout) + { + // Save if modified + if(block->getModified() != MOD_STATE_CLEAN) + { + saveBlock(block); + saved_blocks_count++; + } + // Delete from memory + sector->deleteBlock(block); + deleted_blocks_count++; + } + else + { + all_blocks_deleted = false; + } + } + + if(all_blocks_deleted) + { + sector_deletion_queue.push_back(si.getNode()->getKey()); + } + } + + deleteSectors(sector_deletion_queue); + + infostream<<"Map: Unloaded "< & modified_blocks) // Find out whether there is a suspect for this action std::string suspect; - if(m_gamedef->rollback()) { + if(m_gamedef->rollback()){ suspect = m_gamedef->rollback()->getSuspect(p0, 83, 1); } - if(m_gamedef->rollback() && !suspect.empty()){ + if(!suspect.empty()){ // Blame suspect RollbackScopeActor rollback_scope(m_gamedef->rollback(), suspect, true); // Get old node for rollback @@ -2015,13 +2095,25 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emer bool succeeded = conf.readConfigFile(conf_path.c_str()); if (!succeeded || !conf.exists("backend")) { // fall back to sqlite3 + dbase = new Database_SQLite3(this, savedir); conf.set("backend", "sqlite3"); + } else { + std::string backend = conf.get("backend"); + if (backend == "dummy") + dbase = new Database_Dummy(this); + else if (backend == "sqlite3") + dbase = new Database_SQLite3(this, savedir); + #if USE_LEVELDB + else if (backend == "leveldb") + dbase = new Database_LevelDB(this, savedir); + #endif + #if USE_REDIS + else if (backend == "redis") + dbase = new Database_Redis(this, savedir); + #endif + else + throw BaseException("Unknown map backend"); } - std::string backend = conf.get("backend"); - dbase = createDatabase(backend, savedir, conf); - - if (!conf.updateConfigFile(conf_path.c_str())) - errorstream << "ServerMap::ServerMap(): Failed to update world.mt!" << std::endl; m_savedir = savedir; m_map_saving_enabled = false; @@ -2800,8 +2892,7 @@ plan_b: } bool ServerMap::loadFromFolders() { - if (!dbase->initialized() && - !fs::PathExists(m_savedir + DIR_DELIM + "map.sqlite")) + if(!dbase->Initialized() && !fs::PathExists(m_savedir + DIR_DELIM + "map.sqlite")) // ? return true; return false; } @@ -2823,14 +2914,14 @@ std::string ServerMap::getSectorDir(v2s16 pos, int layout) { case 1: snprintf(cc, 9, "%.4x%.4x", - (unsigned int) pos.X & 0xffff, - (unsigned int) pos.Y & 0xffff); + (unsigned int)pos.X&0xffff, + (unsigned int)pos.Y&0xffff); return m_savedir + DIR_DELIM + "sectors" + DIR_DELIM + cc; case 2: - snprintf(cc, 9, (std::string("%.3x") + DIR_DELIM + "%.3x").c_str(), - (unsigned int) pos.X & 0xfff, - (unsigned int) pos.Y & 0xfff); + snprintf(cc, 9, "%.3x" DIR_DELIM "%.3x", + (unsigned int)pos.X&0xfff, + (unsigned int)pos.Y&0xfff); return m_savedir + DIR_DELIM + "sectors2" + DIR_DELIM + cc; default: @@ -2854,10 +2945,10 @@ v2s16 ServerMap::getSectorPos(std::string dirname) { // New layout fs::RemoveLastPathComponent(dirname, &component, 2); - r = sscanf(component.c_str(), (std::string("%3x") + DIR_DELIM + "%3x").c_str(), &x, &y); + r = sscanf(component.c_str(), "%3x" DIR_DELIM "%3x", &x, &y); // Sign-extend the 12 bit values up to 16 bits... - if(x & 0x800) x |= 0xF000; - if(y & 0x800) y |= 0xF000; + if(x&0x800) x|=0xF000; + if(y&0x800) y|=0xF000; } else { @@ -2892,7 +2983,8 @@ std::string ServerMap::getBlockFilename(v3s16 p) void ServerMap::save(ModifiedState save_level) { DSTACK(__FUNCTION_NAME); - if(m_map_saving_enabled == false) { + if(m_map_saving_enabled == false) + { infostream<<"WARNING: Not saving map, saving disabled."<::iterator i = m_sectors.begin(); - i != m_sectors.end(); ++i) { + i != m_sectors.end(); ++i) + { ServerMapSector *sector = (ServerMapSector*)i->second; assert(sector->getId() == MAPSECTOR_SERVER); - if(sector->differs_from_disk || save_level == MOD_STATE_CLEAN) { + if(sector->differs_from_disk || save_level == MOD_STATE_CLEAN) + { saveSectorMeta(sector); sector_meta_count++; } - - MapBlockVect blocks; + std::list blocks; sector->getBlocks(blocks); - for(MapBlockVect::iterator j = blocks.begin(); - j != blocks.end(); ++j) { + for(std::list::iterator j = blocks.begin(); + j != blocks.end(); ++j) + { MapBlock *block = *j; block_count_all++; - if(block->getModified() >= (u32)save_level) { + if(block->getModified() >= (u32)save_level) + { // Lazy beginSave() - if(!save_started) { + if(!save_started){ beginSave(); save_started = true; } @@ -2954,7 +3050,6 @@ void ServerMap::save(ModifiedState save_level) } } } - if(save_started) endSave(); @@ -2962,7 +3057,8 @@ void ServerMap::save(ModifiedState save_level) Only print if something happened or saved whole map */ if(save_level == MOD_STATE_CLEAN || sector_meta_count != 0 - || block_count != 0) { + || block_count != 0) + { infostream<<"ServerMap: Written: " < &dst) +void ServerMap::listAllLoadableBlocks(std::list &dst) { - if (loadFromFolders()) { - errorstream << "Map::listAllLoadableBlocks(): Result will be missing " - << "all blocks that are stored in flat files." << std::endl; + if(loadFromFolders()){ + errorstream<<"Map::listAllLoadableBlocks(): Result will be missing " + <<"all blocks that are stored in flat files"<listAllLoadableBlocks(dst); } -void ServerMap::listAllLoadedBlocks(std::vector &dst) +void ServerMap::listAllLoadedBlocks(std::list &dst) { for(std::map::iterator si = m_sectors.begin(); si != m_sectors.end(); ++si) { MapSector *sector = si->second; - MapBlockVect blocks; + std::list blocks; sector->getBlocks(blocks); - for(MapBlockVect::iterator i = blocks.begin(); - i != blocks.end(); ++i) { - v3s16 p = (*i)->getPos(); + for(std::list::iterator i = blocks.begin(); + i != blocks.end(); ++i) + { + MapBlock *block = (*i); + v3s16 p = block->getPos(); dst.push_back(p); } } @@ -3233,24 +3331,6 @@ bool ServerMap::loadSectorFull(v2s16 p2d) } #endif -Database *ServerMap::createDatabase(const std::string &name, const std::string &savedir, Settings &conf) -{ - if (name == "sqlite3") - return new Database_SQLite3(savedir); - if (name == "dummy") - return new Database_Dummy(); - #if USE_LEVELDB - else if (name == "leveldb") - return new Database_LevelDB(savedir); - #endif - #if USE_REDIS - else if (name == "redis") - return new Database_Redis(conf); - #endif - else - throw BaseException(std::string("Database backend ") + name + " not supported."); -} - void ServerMap::beginSave() { dbase->beginSave(); @@ -3290,7 +3370,7 @@ bool ServerMap::saveBlock(MapBlock *block, Database *db) std::string data = o.str(); bool ret = db->saveBlock(p3d, data); - if (ret) { + if(ret) { // We just wrote it to the disk so clear modified flag block->resetModified(); } @@ -3302,7 +3382,7 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, { DSTACK(__FUNCTION_NAME); - std::string fullpath = sectordir + DIR_DELIM + blockfile; + std::string fullpath = sectordir+DIR_DELIM+blockfile; try { std::ifstream is(fullpath.c_str(), std::ios_base::binary); @@ -3504,7 +3584,7 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos) */ std::string blockfilename = getBlockFilename(blockpos); - if(fs::PathExists(sectordir + DIR_DELIM + blockfilename) == false) + if(fs::PathExists(sectordir+DIR_DELIM+blockfilename) == false) return NULL; /* diff --git a/src/map.h b/src/map.h index a4fd8406b..1089e6d34 100644 --- a/src/map.h +++ b/src/map.h @@ -34,7 +34,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/container.h" #include "nodetimer.h" -class Settings; class Database; class ClientMap; class MapSector; @@ -278,18 +277,28 @@ public: Saves modified blocks before unloading on MAPTYPE_SERVER. */ void timerUpdate(float dtime, float unload_timeout, - std::vector *unloaded_blocks=NULL); + std::list *unloaded_blocks=NULL); /* Unloads all blocks with a zero refCount(). Saves modified blocks before unloading on MAPTYPE_SERVER. */ - void unloadUnreferencedBlocks(std::vector *unloaded_blocks=NULL); + void unloadUnreferencedBlocks(std::list *unloaded_blocks=NULL); // Deletes sectors and their blocks from memory // Takes cache into account // If deleted sector is in sector cache, clears cache - void deleteSectors(std::vector &list); + void deleteSectors(std::list &list); + +#if 0 + /* + Unload unused data + = flush changed to disk and delete from memory, if usage timer of + block is more than timeout + */ + void unloadUnusedData(float timeout, + core::list *deleted_blocks=NULL); +#endif // For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: " virtual void PrintInfo(std::ostream &out); @@ -446,7 +455,6 @@ public: /* Database functions */ - static Database *createDatabase(const std::string &name, const std::string &savedir, Settings &conf); // Verify we can read/write to the database void verifyDatabase(); @@ -458,8 +466,8 @@ public: void endSave(); void save(ModifiedState save_level); - void listAllLoadableBlocks(std::vector &dst); - void listAllLoadedBlocks(std::vector &dst); + void listAllLoadableBlocks(std::list &dst); + void listAllLoadedBlocks(std::list &dst); // Saves map seed and possibly other stuff void saveMapMeta(); void loadMapMeta(); @@ -483,8 +491,8 @@ public: // Returns true if sector now resides in memory //bool deFlushSector(v2s16 p2d); + bool saveBlock(MapBlock *block, Database *db); bool saveBlock(MapBlock *block); - static bool saveBlock(MapBlock *block, Database *db); // This will generate a sector with getSector if not found. void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false); MapBlock* loadBlock(v3s16 p); diff --git a/src/mapblock.cpp b/src/mapblock.cpp index a05b7a4da..ecd9a016b 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -330,42 +330,47 @@ void MapBlock::copyFrom(VoxelManipulator &dst) void MapBlock::actuallyUpdateDayNightDiff() { INodeDefManager *nodemgr = m_gamedef->ndef(); - // Running this function un-expires m_day_night_differs m_day_night_differs_expired = false; - if (data == NULL) { + if(data == NULL) + { m_day_night_differs = false; return; } - bool differs; + bool differs = false; /* Check if any lighting value differs */ - for (u32 i = 0; i < MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++) { + for(u32 i=0; i MapBlockVect; - inline bool blockpos_over_limit(v3s16 p) { return diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp index d95b8d286..cf311acba 100644 --- a/src/mapblock_mesh.cpp +++ b/src/mapblock_mesh.cpp @@ -42,7 +42,7 @@ static void applyFacesShading(video::SColor& color, float factor) MeshMakeData */ -MeshMakeData::MeshMakeData(IGameDef *gamedef, bool use_shaders): +MeshMakeData::MeshMakeData(IGameDef *gamedef): m_vmanip(), m_blockpos(-1337,-1337,-1337), m_crack_pos_relative(-1337, -1337, -1337), @@ -50,8 +50,7 @@ MeshMakeData::MeshMakeData(IGameDef *gamedef, bool use_shaders): m_smooth_lighting(false), m_show_hud(false), m_highlight_mesh_color(255, 255, 255, 255), - m_gamedef(gamedef), - m_use_shaders(use_shaders) + m_gamedef(gamedef) {} void MeshMakeData::fill(MapBlock *block) @@ -248,7 +247,7 @@ static u16 getSmoothLightCombined(v3s16 p, MeshMakeData *data) for (u32 i = 0; i < 8; i++) { - const MapNode &n = data->m_vmanip.getNodeRefUnsafeCheckFlags(p - dirs8[i]); + MapNode n = data->m_vmanip.getNodeNoEx(p - dirs8[i]); // if it's CONTENT_IGNORE we can't do any light calculations if (n.getContent() == CONTENT_IGNORE) { @@ -438,6 +437,8 @@ struct FastFace static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3, v3f p, v3s16 dir, v3f scale, u8 light_source, std::vector &dest) { + FastFace face; + // Position is at the center of the cube. v3f pos = p * BS; @@ -588,10 +589,6 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3, u8 alpha = tile.alpha; - dest.push_back(FastFace()); - - FastFace& face = *dest.rbegin(); - face.vertices[0] = video::S3DVertex(vertex_pos[0], normal, MapBlock_LightColor(alpha, li0, light_source), core::vector2d(x0+w*abs_scale, y0+h)); @@ -606,6 +603,7 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3, core::vector2d(x0+w*abs_scale, y0)); face.tile = tile; + dest.push_back(face); } /* @@ -746,8 +744,8 @@ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 dir, MeshMakeData *data) static void getTileInfo( // Input: MeshMakeData *data, - const v3s16 &p, - const v3s16 &face_dir, + v3s16 p, + v3s16 face_dir, // Output: bool &makes_face, v3s16 &p_corrected, @@ -761,20 +759,14 @@ static void getTileInfo( INodeDefManager *ndef = data->m_gamedef->ndef(); v3s16 blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE; - MapNode &n0 = vmanip.getNodeRefUnsafe(blockpos_nodes + p); + MapNode n0 = vmanip.getNodeNoEx(blockpos_nodes + p); // Don't even try to get n1 if n0 is already CONTENT_IGNORE - if (n0.getContent() == CONTENT_IGNORE) { - makes_face = false; - return; - } - - const MapNode &n1 = vmanip.getNodeRefUnsafeCheckFlags(blockpos_nodes + p + face_dir); - - if (n1.getContent() == CONTENT_IGNORE) { + if (n0.getContent() == CONTENT_IGNORE ) { makes_face = false; return; } + MapNode n1 = vmanip.getNodeNoEx(blockpos_nodes + p + face_dir); // This is hackish bool equivalent = false; @@ -1036,7 +1028,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): m_last_daynight_ratio((u32) -1), m_daynight_diffs() { - m_enable_shaders = data->m_use_shaders; + m_enable_shaders = g_settings->getBool("enable_shaders"); m_enable_highlighting = g_settings->getBool("enable_node_highlighting"); // 4-21ms for MAP_BLOCKSIZE=16 (NOTE: probably outdated) @@ -1044,7 +1036,6 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): //TimeTaker timer1("MapBlockMesh()"); std::vector fastfaces_new; - fastfaces_new.reserve(512); /* We are including the faces of the trailing edges of the block. diff --git a/src/mapblock_mesh.h b/src/mapblock_mesh.h index b334ce469..be56d4c58 100644 --- a/src/mapblock_mesh.h +++ b/src/mapblock_mesh.h @@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MAPBLOCK_MESH_HEADER #include "irrlichttypes_extrabloated.h" -#include "client/tile.h" +#include "tile.h" #include "voxel.h" #include @@ -45,9 +45,8 @@ struct MeshMakeData video::SColor m_highlight_mesh_color; IGameDef *m_gamedef; - bool m_use_shaders; - MeshMakeData(IGameDef *gamedef, bool use_shaders); + MeshMakeData(IGameDef *gamedef); /* Copy central data directly from block, and other data from diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 17aa1dd92..ba1b16d6a 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -41,8 +41,6 @@ with this program; if not, write to the Free Software Foundation, Inc., const char *GenElementManager::ELEMENT_TITLE = "element"; -static const s16 INVALID_HEIGHT = MAP_GENERATION_LIMIT + 1; - FlagDesc flagdesc_mapgen[] = { {"trees", MG_TREES}, {"caves", MG_CAVES}, @@ -157,12 +155,6 @@ s16 Mapgen::findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax) } -void Mapgen::initHeightMap(s16 *dest, size_t len) -{ - for (size_t i = 0; i < len; i++) - dest[i] = INVALID_HEIGHT; -} - void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax) { if (!heightmap) @@ -174,13 +166,11 @@ void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax) for (s16 x = nmin.X; x <= nmax.X; x++, index++) { s16 y = findGroundLevel(v2s16(x, z), nmin.Y, nmax.Y); - if (heightmap[index] != INVALID_HEIGHT) { - // if the values found are out of range, trust the old heightmap - if (y == nmax.Y && heightmap[index] > nmax.Y) - continue; - if (y == nmin.Y - 1 && heightmap[index] < nmin.Y) - continue; - } + // if the values found are out of range, trust the old heightmap + if (y == nmax.Y && heightmap[index] > nmax.Y) + continue; + if (y == nmin.Y - 1 && heightmap[index] < nmin.Y) + continue; heightmap[index] = y; } @@ -427,8 +417,9 @@ void GenerateNotifier::getEvents( std::map > &event_map, bool peek_events) { - for (std::vector::iterator it = m_notify_events.begin(); - it != m_notify_events.end(); ++it) { + std::list::iterator it; + + for (it = m_notify_events.begin(); it != m_notify_events.end(); ++it) { GenNotifyEvent &gn = *it; std::string name = (gn.type == GENNOTIFY_DECORATION) ? "decoration#"+ itos(gn.id) : diff --git a/src/mapgen.h b/src/mapgen.h index 01710786b..5bbdd724d 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -91,7 +91,7 @@ public: private: u32 m_notify_on; std::set *m_notify_on_deco_ids; - std::vector m_notify_events; + std::list m_notify_events; }; struct MapgenSpecificParams { @@ -151,7 +151,6 @@ public: static u32 getBlockSeed2(v3s16 p, int seed); s16 findGroundLevelFull(v2s16 p2d); s16 findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax); - void initHeightMap(s16 *dest, size_t len); void updateHeightmap(v3s16 nmin, v3s16 nmax); void updateLiquid(UniqueQueue *trans_liquid, v3s16 nmin, v3s16 nmax); diff --git a/src/mapgen_v5.cpp b/src/mapgen_v5.cpp index 34484c7e5..f7efc4e18 100644 --- a/src/mapgen_v5.cpp +++ b/src/mapgen_v5.cpp @@ -42,6 +42,7 @@ with this program; if not, write to the Free Software Foundation, Inc., FlagDesc flagdesc_mapgen_v5[] = { + {"blobs", MGV5_BLOBS}, {NULL, 0} }; @@ -60,8 +61,6 @@ MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge) this->biomemap = new u8[csize.X * csize.Z]; this->heightmap = new s16[csize.X * csize.Z]; - initHeightMap(this->heightmap, csize.X * csize.Z); - MapgenV5Params *sp = (MapgenV5Params *)params->sparams; this->spflags = sp->spflags; @@ -74,6 +73,8 @@ MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge) noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 2, csize.Z); noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 2, csize.Z); noise_ground = new Noise(&sp->np_ground, seed, csize.X, csize.Y + 2, csize.Z); + noise_crumble = new Noise(&sp->np_crumble, seed, csize.X, csize.Y + 2, csize.Z); + noise_wetness = new Noise(&sp->np_wetness, seed, csize.X, csize.Y + 2, csize.Z); // Biome noise noise_heat = new Noise(¶ms->np_biome_heat, seed, csize.X, csize.Z); @@ -116,6 +117,8 @@ MapgenV5::~MapgenV5() delete noise_cave1; delete noise_cave2; delete noise_ground; + delete noise_crumble; + delete noise_wetness; delete noise_heat; delete noise_humidity; @@ -127,7 +130,7 @@ MapgenV5::~MapgenV5() MapgenV5Params::MapgenV5Params() { - spflags = 0; + spflags = MGV5_BLOBS; np_filler_depth = NoiseParams(0, 1, v3f(150, 150, 150), 261, 4, 0.7, 2.0); np_factor = NoiseParams(0, 1, v3f(250, 250, 250), 920381, 3, 0.45, 2.0); @@ -135,11 +138,18 @@ MapgenV5Params::MapgenV5Params() np_cave1 = NoiseParams(0, 12, v3f(50, 50, 50), 52534, 4, 0.5, 2.0); np_cave2 = NoiseParams(0, 12, v3f(50, 50, 50), 10325, 4, 0.5, 2.0); np_ground = NoiseParams(0, 40, v3f(80, 80, 80), 983240, 4, 0.55, 2.0, NOISE_FLAG_EASED); + np_crumble = NoiseParams(0, 1, v3f(20, 20, 20), 34413, 3, 1.3, 2.0, NOISE_FLAG_EASED); + np_wetness = NoiseParams(0, 1, v3f(40, 40, 40), 32474, 4, 1.1, 2.0); } +// Scaling the output of the noise function affects the overdrive of the +// contour function, which affects the shape of the output considerably. + +// Two original MT 0.3 parameters for non-eased noise: + //#define CAVE_NOISE_SCALE 12.0 -//#define CAVE_NOISE_THRESHOLD (1.5/CAVE_NOISE_SCALE) = 0.125 +//#define CAVE_NOISE_THRESHOLD (1.5/CAVE_NOISE_SCALE) void MapgenV5Params::readParams(Settings *settings) @@ -152,6 +162,8 @@ void MapgenV5Params::readParams(Settings *settings) settings->getNoiseParams("mgv5_np_cave1", np_cave1); settings->getNoiseParams("mgv5_np_cave2", np_cave2); settings->getNoiseParams("mgv5_np_ground", np_ground); + settings->getNoiseParams("mgv5_np_crumble", np_crumble); + settings->getNoiseParams("mgv5_np_wetness", np_wetness); } @@ -165,6 +177,8 @@ void MapgenV5Params::writeParams(Settings *settings) settings->setNoiseParams("mgv5_np_cave1", np_cave1); settings->setNoiseParams("mgv5_np_cave2", np_cave2); settings->setNoiseParams("mgv5_np_ground", np_ground); + settings->setNoiseParams("mgv5_np_crumble", np_crumble); + settings->setNoiseParams("mgv5_np_wetness", np_wetness); } @@ -173,20 +187,23 @@ int MapgenV5::getGroundLevelAtPoint(v2s16 p) //TimeTaker t("getGroundLevelAtPoint", NULL, PRECISION_MICRO); float f = 0.55 + NoisePerlin2D(&noise_factor->np, p.X, p.Y, seed); - if (f < 0.01) + if(f < 0.01) f = 0.01; - else if (f >= 1.0) + else if(f >= 1.0) f *= 1.6; float h = water_level + NoisePerlin2D(&noise_height->np, p.X, p.Y, seed); s16 search_top = water_level + 15; s16 search_base = water_level; + // Use these 2 lines instead for a slower search returning highest ground level: + //s16 search_top = h + f * noise_ground->np->octaves * noise_ground->np->scale; + //s16 search_base = h - f * noise_ground->np->octaves * noise_ground->np->scale; s16 level = -31000; for (s16 y = search_top; y >= search_base; y--) { float n_ground = NoisePerlin3D(&noise_ground->np, p.X, y, p.Y, seed); - if (n_ground * f > y - h) { - if (y >= search_top - 7) + if(n_ground * f > y - h) { + if(y >= search_top - 7) break; else level = y; @@ -230,20 +247,18 @@ void MapgenV5::makeChunk(BlockMakeData *data) // Generate base terrain s16 stone_surface_max_y = generateBaseTerrain(); - - // Create heightmap updateHeightmap(node_min, node_max); - // Create biomemap at heightmap surface + // Calculate biomes bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result, noise_humidity->result, heightmap, biomemap); // Actually place the biome-specific nodes - generateBiomes(noise_heat->result, noise_humidity->result); + generateBiomes(); // Generate caves if ((flags & MG_CAVES) && (stone_surface_max_y >= node_min.Y)) - generateCaves(stone_surface_max_y); + generateCaves(); // Generate dungeons and desert temples if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) { @@ -254,6 +269,11 @@ void MapgenV5::makeChunk(BlockMakeData *data) // Generate the registered decorations m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); + // Generate underground dirt, sand, gravel and lava blobs + if (spflags & MGV5_BLOBS) { + generateBlobs(); + } + // Generate the registered ores m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); @@ -291,6 +311,11 @@ void MapgenV5::calculateNoise() noise_cave2->perlinMap3D(x, y, z); } + if (spflags & MGV5_BLOBS) { + noise_crumble->perlinMap3D(x, y, z); + noise_wetness->perlinMap3D(x, y, z); + } + if (node_max.Y >= water_level) { noise_filler_depth->perlinMap2D(x, z); noise_heat->perlinMap2D(x, z); @@ -301,6 +326,8 @@ void MapgenV5::calculateNoise() } +// Two original MT 0.3 functions: + //bool is_cave(u32 index) { // double d1 = contour(noise_cave1->result[index]); // double d2 = contour(noise_cave2->result[index]); @@ -324,22 +351,22 @@ int MapgenV5::generateBaseTerrain() u32 index2d = 0; int stone_surface_max_y = -MAP_GENERATION_LIMIT; - for (s16 z=node_min.Z; z<=node_max.Z; z++) { - for (s16 y=node_min.Y - 1; y<=node_max.Y + 1; y++) { + for(s16 z=node_min.Z; z<=node_max.Z; z++) { + for(s16 y=node_min.Y - 1; y<=node_max.Y + 1; y++) { u32 i = vm->m_area.index(node_min.X, y, z); - for (s16 x=node_min.X; x<=node_max.X; x++, i++, index++, index2d++) { - if (vm->m_data[i].getContent() != CONTENT_IGNORE) + for(s16 x=node_min.X; x<=node_max.X; x++, i++, index++, index2d++) { + if(vm->m_data[i].getContent() != CONTENT_IGNORE) continue; float f = 0.55 + noise_factor->result[index2d]; - if (f < 0.01) + if(f < 0.01) f = 0.01; - else if (f >= 1.0) + else if(f >= 1.0) f *= 1.6; - float h = noise_height->result[index2d]; + float h = water_level + noise_height->result[index2d]; - if (noise_ground->result[index] * f < y - h) { - if (y <= water_level) + if(noise_ground->result[index] * f < y - h) { + if(y <= water_level) vm->m_data[i] = MapNode(c_water_source); else vm->m_data[i] = MapNode(CONTENT_AIR); @@ -358,7 +385,7 @@ int MapgenV5::generateBaseTerrain() } -void MapgenV5::generateBiomes(float *heat_map, float *humidity_map) +void MapgenV5::generateBiomes() { if (node_max.Y < water_level) return; @@ -372,11 +399,12 @@ void MapgenV5::generateBiomes(float *heat_map, float *humidity_map) for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { - Biome *biome = NULL; - s16 dfiller = 0; - s16 y0_top = 0; - s16 y0_filler = 0; - s16 depth_water_top = 0; + Biome *biome = (Biome *)bmgr->get(biomemap[index]); + s16 dfiller = biome->depth_filler + noise_filler_depth->result[index]; + s16 y0_top = biome->depth_top; + s16 y0_filler = biome->depth_top + dfiller; + s16 shore_max = water_level + biome->height_shore; + s16 depth_water_top = biome->depth_water_top; s16 nplaced = 0; u32 i = vm->m_area.index(x, node_max.Y, z); @@ -387,23 +415,25 @@ void MapgenV5::generateBiomes(float *heat_map, float *humidity_map) for (s16 y = node_max.Y; y >= node_min.Y; y--) { content_t c = vm->m_data[i].getContent(); - if (c != CONTENT_IGNORE && c != CONTENT_AIR && (y == node_max.Y || have_air)) { - biome = bmgr->getBiome(heat_map[index], humidity_map[index], y); - dfiller = biome->depth_filler + noise_filler_depth->result[index]; - y0_top = biome->depth_top; - y0_filler = biome->depth_top + dfiller; - depth_water_top = biome->depth_water_top; - } - if (c == c_stone && have_air) { content_t c_below = vm->m_data[i - em.X].getContent(); if (c_below != CONTENT_AIR) { if (nplaced < y0_top) { - vm->m_data[i] = MapNode(biome->c_top); + if(y < water_level) + vm->m_data[i] = MapNode(biome->c_underwater); + else if(y <= shore_max) + vm->m_data[i] = MapNode(biome->c_shore_top); + else + vm->m_data[i] = MapNode(biome->c_top); nplaced++; } else if (nplaced < y0_filler && nplaced >= y0_top) { - vm->m_data[i] = MapNode(biome->c_filler); + if(y < water_level) + vm->m_data[i] = MapNode(biome->c_underwater); + else if(y <= shore_max) + vm->m_data[i] = MapNode(biome->c_shore_filler); + else + vm->m_data[i] = MapNode(biome->c_filler); nplaced++; } else if (c == c_stone) { have_air = false; @@ -440,18 +470,18 @@ void MapgenV5::generateBiomes(float *heat_map, float *humidity_map) } -void MapgenV5::generateCaves(int max_stone_y) +void MapgenV5::generateCaves() { u32 index = 0; u32 index2d = 0; - for (s16 z=node_min.Z; z<=node_max.Z; z++) { - for (s16 y=node_min.Y - 1; y<=node_max.Y + 1; y++) { + for(s16 z=node_min.Z; z<=node_max.Z; z++) { + for(s16 y=node_min.Y - 1; y<=node_max.Y + 1; y++) { u32 i = vm->m_area.index(node_min.X, y, z); - for (s16 x=node_min.X; x<=node_max.X; x++, i++, index++, index2d++) { + for(s16 x=node_min.X; x<=node_max.X; x++, i++, index++, index2d++) { Biome *biome = (Biome *)bmgr->get(biomemap[index2d]); content_t c = vm->m_data[i].getContent(); - if (c == CONTENT_AIR + if(c == CONTENT_AIR || (y <= water_level && c != biome->c_stone && c != c_stone)) @@ -459,22 +489,43 @@ void MapgenV5::generateCaves(int max_stone_y) float d1 = contour(noise_cave1->result[index]); float d2 = contour(noise_cave2->result[index]); - if (d1*d2 > 0.125) + if(d1*d2 > 0.125) vm->m_data[i] = MapNode(CONTENT_AIR); } index2d = index2d - ystride; } index2d = index2d + ystride; } +} - if (node_max.Y > -256) - return; - PseudoRandom ps(blockseed + 21343); - u32 bruises_count = (ps.range(1, 5) == 1) ? ps.range(1, 2) : 0; - for (u32 i = 0; i < bruises_count; i++) { - CaveV5 cave(this, &ps); - cave.makeCave(node_min, node_max, max_stone_y); +void MapgenV5::generateBlobs() +{ + u32 index = 0; + + for(s16 z=node_min.Z; z<=node_max.Z; z++) { + for(s16 y=node_min.Y - 1; y<=node_max.Y + 1; y++) { + u32 i = vm->m_area.index(node_min.X, y, z); + for(s16 x=node_min.X; x<=node_max.X; x++, i++, index++) { + content_t c = vm->m_data[i].getContent(); + if(c != c_stone) + continue; + + if(noise_crumble->result[index] > 1.3) { + if(noise_wetness->result[index] > 0.0) + vm->m_data[i] = MapNode(c_dirt); + else + vm->m_data[i] = MapNode(c_sand); + } else if(noise_crumble->result[index] > 0.7) { + if(noise_wetness->result[index] < -0.6) + vm->m_data[i] = MapNode(c_gravel); + } else if(noise_crumble->result[index] < -3.5 + + MYMIN(0.1 * + sqrt((float)MYMAX(0, -y)), 1.5)) { + vm->m_data[i] = MapNode(c_lava_source); + } + } + } } } diff --git a/src/mapgen_v5.h b/src/mapgen_v5.h index e95874e84..1949bf5db 100644 --- a/src/mapgen_v5.h +++ b/src/mapgen_v5.h @@ -23,9 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapgen.h" /////////////////// Mapgen V5 flags -//#define MGV5_ 0x01 - -class BiomeManager; +#define MGV5_BLOBS 0x01 extern FlagDesc flagdesc_mapgen_v5[]; @@ -38,6 +36,8 @@ struct MapgenV5Params : public MapgenSpecificParams { NoiseParams np_cave1; NoiseParams np_cave2; NoiseParams np_ground; + NoiseParams np_crumble; + NoiseParams np_wetness; MapgenV5Params(); ~MapgenV5Params() {} @@ -67,6 +67,8 @@ public: Noise *noise_cave1; Noise *noise_cave2; Noise *noise_ground; + Noise *noise_crumble; + Noise *noise_wetness; Noise *noise_heat; Noise *noise_humidity; @@ -93,8 +95,9 @@ public: int getGroundLevelAtPoint(v2s16 p); void calculateNoise(); int generateBaseTerrain(); - void generateBiomes(float *heat_map, float *humidity_map); - void generateCaves(int max_stone_y); + void generateBiomes(); + void generateCaves(); + void generateBlobs(); void dustTopNodes(); }; diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index 8ea4cd21d..95cdbd279 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -55,10 +55,6 @@ MapgenV6::MapgenV6(int mapgenid, MapgenParams *params, EmergeManager *emerge) this->m_emerge = emerge; this->ystride = csize.X; //////fix this - this->heightmap = new s16[csize.X * csize.Z]; - - initHeightMap(this->heightmap, csize.X * csize.Z); - MapgenV6Params *sp = (MapgenV6Params *)params->sparams; this->spflags = sp->spflags; this->freq_desert = sp->freq_desert; @@ -119,8 +115,6 @@ MapgenV6::~MapgenV6() delete noise_mud; delete noise_beach; delete noise_biome; - - delete[] heightmap; } @@ -504,9 +498,6 @@ void MapgenV6::makeChunk(BlockMakeData *data) } - // Create heightmap after mudflow - updateHeightmap(node_min, node_max); - // Add dungeons if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) { DungeonParams dp; diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index 21ee967c6..a7b9076b3 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -64,8 +64,6 @@ MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge) this->heightmap = new s16[csize.X * csize.Z]; this->ridge_heightmap = new s16[csize.X * csize.Z]; - initHeightMap(this->heightmap, csize.X * csize.Z); - MapgenV7Params *sp = (MapgenV7Params *)params->sparams; this->spflags = sp->spflags; @@ -241,15 +239,14 @@ void MapgenV7::makeChunk(BlockMakeData *data) // Generate base terrain, mountains, and ridges with initial heightmaps s16 stone_surface_max_y = generateTerrain(); - // Create heightmap updateHeightmap(node_min, node_max); - // Create biomemap at heightmap surface + // Calculate biomes bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result, noise_humidity->result, heightmap, biomemap); - // Actually place the biome-specific nodes - generateBiomes(noise_heat->result, noise_humidity->result); + // Actually place the biome-specific nodes and what not + generateBiomes(); if (flags & MG_CAVES) generateCaves(stone_surface_max_y); @@ -537,7 +534,7 @@ void MapgenV7::generateRidgeTerrain() } -void MapgenV7::generateBiomes(float *heat_map, float *humidity_map) +void MapgenV7::generateBiomes() { if (node_max.Y < water_level) return; @@ -551,11 +548,12 @@ void MapgenV7::generateBiomes(float *heat_map, float *humidity_map) for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { - Biome *biome = NULL; - s16 dfiller = 0; - s16 y0_top = 0; - s16 y0_filler = 0; - s16 depth_water_top = 0; + Biome *biome = (Biome *)bmgr->get(biomemap[index]); + s16 dfiller = biome->depth_filler + noise_filler_depth->result[index]; + s16 y0_top = biome->depth_top; + s16 y0_filler = biome->depth_top + dfiller; + s16 shore_max = water_level + biome->height_shore; + s16 depth_water_top = biome->depth_water_top; s16 nplaced = 0; u32 i = vm->m_area.index(x, node_max.Y, z); @@ -576,23 +574,25 @@ void MapgenV7::generateBiomes(float *heat_map, float *humidity_map) have_air = !getMountainTerrainFromMap(j, index, y); } - if (c != CONTENT_IGNORE && c != CONTENT_AIR && (y == node_max.Y || have_air)) { - biome = bmgr->getBiome(heat_map[index], humidity_map[index], y); - dfiller = biome->depth_filler + noise_filler_depth->result[index]; - y0_top = biome->depth_top; - y0_filler = biome->depth_top + dfiller; - depth_water_top = biome->depth_water_top; - } - if (c == c_stone && have_air) { content_t c_below = vm->m_data[i - em.X].getContent(); if (c_below != CONTENT_AIR) { if (nplaced < y0_top) { - vm->m_data[i] = MapNode(biome->c_top); + if(y < water_level) + vm->m_data[i] = MapNode(biome->c_underwater); + else if(y <= shore_max) + vm->m_data[i] = MapNode(biome->c_shore_top); + else + vm->m_data[i] = MapNode(biome->c_top); nplaced++; } else if (nplaced < y0_filler && nplaced >= y0_top) { - vm->m_data[i] = MapNode(biome->c_filler); + if(y < water_level) + vm->m_data[i] = MapNode(biome->c_underwater); + else if(y <= shore_max) + vm->m_data[i] = MapNode(biome->c_shore_filler); + else + vm->m_data[i] = MapNode(biome->c_filler); nplaced++; } else if (c == c_stone) { have_air = false; @@ -792,7 +792,7 @@ void MapgenV7::generateCaves(int max_stone_y) PseudoRandom ps(blockseed + 21343); u32 bruises_count = (ps.range(1, 5) == 1) ? ps.range(1, 2) : 0; for (u32 i = 0; i < bruises_count; i++) { - CaveV7 cave(this, &ps); + CaveV7 cave(this, &ps, true); cave.makeCave(node_min, node_max, max_stone_y); } } diff --git a/src/mapgen_v7.h b/src/mapgen_v7.h index 8a02bf564..bcf362ac9 100644 --- a/src/mapgen_v7.h +++ b/src/mapgen_v7.h @@ -114,7 +114,7 @@ public: int generateMountainTerrain(int ymax); void generateRidgeTerrain(); - void generateBiomes(float *heat_map, float *humidity_map); + void generateBiomes(); void dustTopNodes(); //void addTopNodes(); diff --git a/src/mapnode.cpp b/src/mapnode.cpp index 44525b644..056b94054 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -74,22 +74,6 @@ void MapNode::setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr assert(0); } -bool MapNode::isLightDayNightEq(INodeDefManager *nodemgr) const -{ - const ContentFeatures &f = nodemgr->get(*this); - bool isEqual; - - if (f.param_type == CPT_LIGHT) { - u8 day = MYMAX(f.light_source, param1 & 0x0f); - u8 night = MYMAX(f.light_source, (param1 >> 4) & 0x0f); - isEqual = day == night; - } else { - isEqual = true; - } - - return isEqual; -} - u8 MapNode::getLight(enum LightBank bank, INodeDefManager *nodemgr) const { // Select the brightest of [light source, propagated light] @@ -104,7 +88,7 @@ u8 MapNode::getLight(enum LightBank bank, INodeDefManager *nodemgr) const return MYMAX(f.light_source, light); } -u8 MapNode::getLightNoChecks(enum LightBank bank, const ContentFeatures *f) const +u8 MapNode::getLightNoChecks(enum LightBank bank, const ContentFeatures *f) { return MYMAX(f->light_source, bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f); diff --git a/src/mapnode.h b/src/mapnode.h index 7cc25c60c..82c53e7d4 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -192,14 +192,6 @@ struct MapNode } void setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr); - - /** - * Check if the light value for night differs from the light value for day. - * - * @return If the light values are equal, returns true; otherwise false - */ - bool isLightDayNightEq(INodeDefManager *nodemgr) const; - u8 getLight(enum LightBank bank, INodeDefManager *nodemgr) const; /** @@ -217,7 +209,7 @@ struct MapNode * @pre f != NULL * @pre f->param_type == CPT_LIGHT */ - u8 getLightNoChecks(LightBank bank, const ContentFeatures *f) const; + u8 getLightNoChecks(LightBank bank, const ContentFeatures *f); bool getLightBanks(u8 &lightday, u8 &lightnight, INodeDefManager *nodemgr) const; diff --git a/src/mapsector.cpp b/src/mapsector.cpp index 7bc4bd3a3..0d40a659d 100644 --- a/src/mapsector.cpp +++ b/src/mapsector.cpp @@ -133,7 +133,7 @@ void MapSector::deleteBlock(MapBlock *block) delete block; } -void MapSector::getBlocks(MapBlockVect &dest) +void MapSector::getBlocks(std::list &dest) { for(std::map::iterator bi = m_blocks.begin(); bi != m_blocks.end(); ++bi) diff --git a/src/mapsector.h b/src/mapsector.h index e89247a92..dac4ee8d6 100644 --- a/src/mapsector.h +++ b/src/mapsector.h @@ -22,11 +22,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes.h" #include "irr_v2d.h" -#include "mapblock.h" #include #include -#include +#include +class MapBlock; class Map; class IGameDef; @@ -61,7 +61,7 @@ public: void deleteBlock(MapBlock *block); - void getBlocks(MapBlockVect &dest); + void getBlocks(std::list &dest); // Always false at the moment, because sector contains no metadata. bool differs_from_disk; diff --git a/src/mg_biome.cpp b/src/mg_biome.cpp index e076d3092..0d17ae5ed 100644 --- a/src/mg_biome.cpp +++ b/src/mg_biome.cpp @@ -43,6 +43,7 @@ BiomeManager::BiomeManager(IGameDef *gamedef) : b->flags = 0; b->depth_top = 0; b->depth_filler = 0; + b->height_shore = 0; b->depth_water_top = 0; b->y_min = -MAP_GENERATION_LIMIT; b->y_max = MAP_GENERATION_LIMIT; @@ -52,6 +53,9 @@ BiomeManager::BiomeManager(IGameDef *gamedef) : NodeResolveInfo *nri = new NodeResolveInfo(b); nri->nodenames.push_back("air"); nri->nodenames.push_back("air"); + nri->nodenames.push_back("air"); + nri->nodenames.push_back("air"); + nri->nodenames.push_back("air"); nri->nodenames.push_back("mapgen_stone"); nri->nodenames.push_back("mapgen_water_source"); nri->nodenames.push_back("mapgen_water_source"); @@ -122,6 +126,9 @@ void Biome::resolveNodeNames(NodeResolveInfo *nri) { m_ndef->getIdFromResolveInfo(nri, "mapgen_dirt_with_grass", CONTENT_AIR, c_top); m_ndef->getIdFromResolveInfo(nri, "mapgen_dirt", CONTENT_AIR, c_filler); + m_ndef->getIdFromResolveInfo(nri, "mapgen_sand", CONTENT_AIR, c_shore_top); + m_ndef->getIdFromResolveInfo(nri, "mapgen_sand", CONTENT_AIR, c_shore_filler); + m_ndef->getIdFromResolveInfo(nri, "mapgen_sand", CONTENT_AIR, c_underwater); m_ndef->getIdFromResolveInfo(nri, "mapgen_stone", CONTENT_AIR, c_stone); m_ndef->getIdFromResolveInfo(nri, "mapgen_water_source", CONTENT_AIR, c_water_top); m_ndef->getIdFromResolveInfo(nri, "mapgen_water_source", CONTENT_AIR, c_water); diff --git a/src/mg_biome.h b/src/mg_biome.h index 3648c085d..3577960a9 100644 --- a/src/mg_biome.h +++ b/src/mg_biome.h @@ -39,6 +39,9 @@ public: content_t c_top; content_t c_filler; + content_t c_shore_top; + content_t c_shore_filler; + content_t c_underwater; content_t c_stone; content_t c_water_top; content_t c_water; @@ -46,6 +49,7 @@ public: s16 depth_top; s16 depth_filler; + s16 height_shore; s16 depth_water_top; s16 y_min; diff --git a/src/mg_decoration.cpp b/src/mg_decoration.cpp index ab9401e28..a67c3cd8c 100644 --- a/src/mg_decoration.cpp +++ b/src/mg_decoration.cpp @@ -31,7 +31,6 @@ FlagDesc flagdesc_deco[] = { {"place_center_x", DECO_PLACE_CENTER_X}, {"place_center_y", DECO_PLACE_CENTER_Y}, {"place_center_z", DECO_PLACE_CENTER_Z}, - {"force_placement", DECO_FORCE_PLACEMENT}, {NULL, 0} }; @@ -141,7 +140,6 @@ size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) s16 y = mg->heightmap ? mg->heightmap[mapindex] : mg->findGroundLevel(v2s16(x, z), nmin.Y, nmax.Y); - y = MYMAX(y, mg->water_level); if (y < nmin.Y || y > nmax.Y || y < y_min || y > y_max) @@ -335,8 +333,6 @@ size_t DecoSchematic::generate(MMVManip *vm, PseudoRandom *pr, s16 max_y, v3s16 if (flags & DECO_PLACE_CENTER_Z) p.Z -= (schematic->size.Z + 1) / 2; - bool force_placement = (flags & DECO_FORCE_PLACEMENT); - if (!vm->m_area.contains(p)) return 0; @@ -348,7 +344,7 @@ size_t DecoSchematic::generate(MMVManip *vm, PseudoRandom *pr, s16 max_y, v3s16 Rotation rot = (rotation == ROTATE_RAND) ? (Rotation)pr->range(ROTATE_0, ROTATE_270) : rotation; - schematic->blitToVManip(p, vm, rot, force_placement, m_ndef); + schematic->blitToVManip(p, vm, rot, false, m_ndef); return 1; } diff --git a/src/mg_decoration.h b/src/mg_decoration.h index fd7739b92..ab4a9377b 100644 --- a/src/mg_decoration.h +++ b/src/mg_decoration.h @@ -35,11 +35,10 @@ enum DecorationType { DECO_LSYSTEM }; -#define DECO_PLACE_CENTER_X 0x01 -#define DECO_PLACE_CENTER_Y 0x02 -#define DECO_PLACE_CENTER_Z 0x04 -#define DECO_USE_NOISE 0x08 -#define DECO_FORCE_PLACEMENT 0x10 +#define DECO_PLACE_CENTER_X 0x01 +#define DECO_PLACE_CENTER_Y 0x02 +#define DECO_PLACE_CENTER_Z 0x04 +#define DECO_USE_NOISE 0x08 extern FlagDesc flagdesc_deco[]; diff --git a/src/mods.cpp b/src/mods.cpp index cb5a6b9fd..6126de7a1 100644 --- a/src/mods.cpp +++ b/src/mods.cpp @@ -47,11 +47,6 @@ static bool parseDependsLine(std::istream &is, void parseModContents(ModSpec &spec) { // NOTE: this function works in mutual recursion with getModsInPath - Settings info; - info.readConfigFile((spec.path+DIR_DELIM+"mod.conf").c_str()); - - if (info.exists("name")) - spec.name = info.get("name"); spec.depends.clear(); spec.optdepends.clear(); diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt deleted file mode 100644 index 3162469c8..000000000 --- a/src/network/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -set(common_network_SRCS - ${CMAKE_CURRENT_SOURCE_DIR}/connection.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/networkpacket.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/packethandlers/server.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/serveropcodes.cpp - PARENT_SCOPE -) - -if (BUILD_CLIENT) - set(client_network_SRCS - ${CMAKE_CURRENT_SOURCE_DIR}/clientopcodes.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/packethandlers/client.cpp - PARENT_SCOPE - ) -endif(BUILD_CLIENT) \ No newline at end of file diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp deleted file mode 100644 index 88eef0ad6..000000000 --- a/src/network/clientopcodes.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* -Minetest -Copyright (C) 2013 celeron55, Perttu Ahola -Copyright (C) 2015 nerzhul, Loic Blot - -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 "clientopcodes.h" - -const static ToClientCommandHandler null_command_handler = {"TOCLIENT_NULL", TOCLIENT_STATE_ALL, &Client::handleCommand_Null}; - -const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] = -{ - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - { "TOCLIENT_INIT", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_Init }, // 0x10 - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - { "TOCLIENT_BLOCKDATA", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_BlockData }, // 0x20 - { "TOCLIENT_ADDNODE", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_AddNode }, // 0x21 - { "TOCLIENT_REMOVENODE", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_RemoveNode }, // 0x22 - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - { "TOCLIENT_INVENTORY", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Inventory }, // 0x27 - null_command_handler, - { "TOCLIENT_TIME_OF_DAY", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_TimeOfDay }, // 0x29 - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - null_command_handler, - { "TOCLIENT_CHAT_MESSAGE", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ChatMessage }, // 0x30 - { "TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ActiveObjectRemoveAdd }, // 0x31 - { "TOCLIENT_ACTIVE_OBJECT_MESSAGES", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ActiveObjectMessages }, // 0x32 - { "TOCLIENT_HP", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HP }, // 0x33 - { "TOCLIENT_MOVE_PLAYER", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_MovePlayer }, // 0x34 - { "TOCLIENT_ACCESS_DENIED", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_AccessDenied }, // 0x35 - { "TOCLIENT_PLAYERITEM", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_PlayerItem }, // 0x36 - { "TOCLIENT_DEATHSCREEN", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_DeathScreen }, // 0x37 - { "TOCLIENT_MEDIA", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Media }, // 0x38 - { "TOCLIENT_TOOLDEF", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ToolDef }, // 0x39 - { "TOCLIENT_NODEDEF", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_NodeDef }, // 0x3a - { "TOCLIENT_CRAFTITEMDEF", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_CraftItemDef }, // 0x3b - { "TOCLIENT_ANNOUNCE_MEDIA", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_AnnounceMedia }, // 0x3c - { "TOCLIENT_ITEMDEF", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ItemDef }, // 0x3d - null_command_handler, - { "TOCLIENT_PLAY_SOUND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_PlaySound }, // 0x3f - { "TOCLIENT_STOP_SOUND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_StopSound }, // 0x40 - { "TOCLIENT_PRIVILEGES", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Privileges }, // 0x41 - { "TOCLIENT_INVENTORY_FORMSPEC", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_InventoryFormSpec }, // 0x42 - { "TOCLIENT_DETACHED_INVENTORY", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_DetachedInventory }, // 0x43 - { "TOCLIENT_SHOW_FORMSPEC", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ShowFormSpec }, // 0x44 - { "TOCLIENT_MOVEMENT", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Movement }, // 0x45 - { "TOCLIENT_SPAWN_PARTICLE", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_SpawnParticle }, // 0x46 - { "TOCLIENT_ADD_PARTICLESPAWNER", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_AddParticleSpawner }, // 0x47 - { "TOCLIENT_DELETE_PARTICLESPAWNER", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_DeleteParticleSpawner }, // 0x48 - { "TOCLIENT_HUDADD", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HudAdd }, // 0x49 - { "TOCLIENT_HUDRM", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HudRemove }, // 0x4a - { "TOCLIENT_HUDCHANGE", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HudChange }, // 0x4b - { "TOCLIENT_HUD_SET_FLAGS", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HudSetFlags }, // 0x4c - { "TOCLIENT_HUD_SET_PARAM", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HudSetParam }, // 0x4d - { "TOCLIENT_BREATH", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Breath }, // 0x4e - { "TOCLIENT_SET_SKY", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HudSetSky }, // 0x4f - { "TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_OverrideDayNightRatio }, // 0x50 - { "TOCLIENT_LOCAL_PLAYER_ANIMATIONS", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_LocalPlayerAnimations }, // 0x51 - { "TOCLIENT_EYE_OFFSET", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_EyeOffset }, // 0x52 -}; - -const static ServerCommandFactory null_command_factory = { "TOSERVER_NULL", 0, false }; - -const ServerCommandFactory serverCommandFactoryTable[TOSERVER_NUM_MSG_TYPES] = -{ - null_command_factory, // 0x00 - null_command_factory, // 0x01 - null_command_factory, // 0x02 - null_command_factory, // 0x03 - null_command_factory, // 0x04 - null_command_factory, // 0x05 - null_command_factory, // 0x06 - null_command_factory, // 0x07 - null_command_factory, // 0x08 - null_command_factory, // 0x09 - null_command_factory, // 0x0a - null_command_factory, // 0x0b - null_command_factory, // 0x0c - null_command_factory, // 0x0d - null_command_factory, // 0x0e - null_command_factory, // 0x0f - { "TOSERVER_INIT", 1, false }, // 0x10 - { "TOSERVER_INIT2", 1, true }, // 0x11 - null_command_factory, // 0x12 - null_command_factory, // 0x13 - null_command_factory, // 0x14 - null_command_factory, // 0x15 - null_command_factory, // 0x16 - null_command_factory, // 0x17 - null_command_factory, // 0x18 - null_command_factory, // 0x19 - null_command_factory, // 0x1a - null_command_factory, // 0x1b - null_command_factory, // 0x1c - null_command_factory, // 0x1d - null_command_factory, // 0x1e - null_command_factory, // 0x1f - null_command_factory, // 0x20 - null_command_factory, // 0x21 - null_command_factory, // 0x22 - { "TOSERVER_PLAYERPOS", 0, false }, // 0x23 - { "TOSERVER_GOTBLOCKS", 2, true }, // 0x24 - { "TOSERVER_DELETEDBLOCKS", 2, true }, // 0x25 - null_command_factory, // 0x26 - { "TOSERVER_CLICK_OBJECT", 0, false }, // 0x27 - { "TOSERVER_GROUND_ACTION", 0, false }, // 0x28 - { "TOSERVER_RELEASE", 0, false }, // 0x29 - null_command_factory, // 0x2a - null_command_factory, // 0x2b - null_command_factory, // 0x2c - null_command_factory, // 0x2d - null_command_factory, // 0x2e - null_command_factory, // 0x2f - { "TOSERVER_SIGNTEXT", 0, false }, // 0x30 - { "TOSERVER_INVENTORY_ACTION", 0, true }, // 0x31 - { "TOSERVER_CHAT_MESSAGE", 0, true }, // 0x32 - { "TOSERVER_SIGNNODETEXT", 0, false }, // 0x33 - { "TOSERVER_CLICK_ACTIVEOBJECT", 0, false }, // 0x34 - { "TOSERVER_DAMAGE", 0, true }, // 0x35 - { "TOSERVER_PASSWORD", 0, true }, // 0x36 - { "TOSERVER_PLAYERITEM", 0, true }, // 0x37 - { "TOSERVER_RESPAWN", 0, true }, // 0x38 - { "TOSERVER_INTERACT", 0, true }, // 0x39 - { "TOSERVER_REMOVED_SOUNDS", 1, true }, // 0x3a - { "TOSERVER_NODEMETA_FIELDS", 0, true }, // 0x3b - { "TOSERVER_INVENTORY_FIELDS", 0, true }, // 0x3c - null_command_factory, // 0x3d - null_command_factory, // 0x3e - null_command_factory, // 0x3f - { "TOSERVER_REQUEST_MEDIA", 1, true }, // 0x40 - { "TOSERVER_RECEIVED_MEDIA", 1, true }, // 0x41 - { "TOSERVER_BREATH", 0, true }, // 0x42 - { "TOSERVER_CLIENT_READY", 0, true }, // 0x43 -}; diff --git a/src/network/clientopcodes.h b/src/network/clientopcodes.h deleted file mode 100644 index 9143865b8..000000000 --- a/src/network/clientopcodes.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -Minetest -Copyright (C) 2013 celeron55, Perttu Ahola -Copyright (C) 2015 nerzhul, Loic Blot - -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. -*/ - -#ifndef CLIENTOPCODES_HEADER -#define CLIENTOPCODES_HEADER - -#include "client.h" -#include "networkprotocol.h" -#include "networkpacket.h" - -enum ToClientConnectionState { - TOCLIENT_STATE_NOT_CONNECTED, - TOCLIENT_STATE_CONNECTED, - TOCLIENT_STATE_ALL, -}; - -struct ToClientCommandHandler -{ - const char* name; - ToClientConnectionState state; - void (Client::*handler)(NetworkPacket* pkt); -}; - -struct ServerCommandFactory -{ - const char* name; - u16 channel; - bool reliable; -}; - -extern const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES]; - -extern const ServerCommandFactory serverCommandFactoryTable[TOSERVER_NUM_MSG_TYPES]; - -#endif diff --git a/src/network/networkpacket.cpp b/src/network/networkpacket.cpp deleted file mode 100644 index b2b1974d7..000000000 --- a/src/network/networkpacket.cpp +++ /dev/null @@ -1,523 +0,0 @@ -/* -Minetest -Copyright (C) 2015 nerzhul, Loic Blot - -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 "networkpacket.h" -#include "debug.h" -#include "exceptions.h" -#include "util/serialize.h" - -NetworkPacket::NetworkPacket(u8 *data, u32 datasize, u16 peer_id): -m_read_offset(0), m_peer_id(peer_id) -{ - m_read_offset = 0; - m_datasize = datasize - 2; - - // split command and datas - m_command = readU16(&data[0]); - m_data = std::vector(&data[2], &data[2 + m_datasize]); -} - -NetworkPacket::NetworkPacket(u16 command, u32 datasize, u16 peer_id): -m_datasize(datasize), m_read_offset(0), m_command(command), m_peer_id(peer_id) -{ - m_data.resize(m_datasize); -} - -NetworkPacket::NetworkPacket(u16 command, u32 datasize): -m_datasize(datasize), m_read_offset(0), m_command(command), m_peer_id(0) -{ - m_data.resize(m_datasize); -} - -NetworkPacket::~NetworkPacket() -{ - m_data.clear(); -} - -char* NetworkPacket::getString(u32 from_offset) -{ - if (from_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - return (char*)&m_data[from_offset]; -} - -void NetworkPacket::putRawString(const char* src, u32 len) -{ - if (m_read_offset + len * sizeof(char) >= m_datasize) { - m_datasize += len * sizeof(char); - m_data.resize(m_datasize); - } - - memcpy(&m_data[m_read_offset], src, len); - m_read_offset += len; -} - -NetworkPacket& NetworkPacket::operator>>(std::string& dst) -{ - u16 strLen = readU16(&m_data[m_read_offset]); - m_read_offset += sizeof(u16); - - dst.clear(); - - if (strLen == 0) { - return *this; - } - - dst.reserve(strLen); - dst.append((char*)&m_data[m_read_offset], strLen); - - m_read_offset += strLen * sizeof(char); - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(std::string src) -{ - u16 msgsize = src.size(); - if (msgsize > 0xFFFF) { - msgsize = 0xFFFF; - } - - *this << msgsize; - - if (m_read_offset + msgsize * sizeof(char) >= m_datasize) { - m_datasize += msgsize * sizeof(char); - m_data.resize(m_datasize); - } - - memcpy(&m_data[m_read_offset], src.c_str(), msgsize); - m_read_offset += msgsize; - - return *this; -} - -void NetworkPacket::putLongString(std::string src) -{ - u32 msgsize = src.size(); - if (msgsize > 0xFFFFFFFF) { - msgsize = 0xFFFFFFFF; - } - - *this << msgsize; - - if (m_read_offset + msgsize * sizeof(char) >= m_datasize) { - m_datasize += msgsize * sizeof(char); - m_data.resize(m_datasize); - } - - memcpy(&m_data[m_read_offset], src.c_str(), msgsize); - m_read_offset += msgsize; -} - -NetworkPacket& NetworkPacket::operator>>(std::wstring& dst) -{ - u16 strLen = readU16(&m_data[m_read_offset]); - m_read_offset += sizeof(u16); - - dst.clear(); - - if (strLen == 0) { - return *this; - } - - dst.reserve(strLen); - for(u16 i=0; i 0xFFFF) { - msgsize = 0xFFFF; - } - - *this << msgsize; - - // Write string - for (u16 i=0; i>(char& dst) -{ - if (m_read_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - dst = readU8(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -char NetworkPacket::getChar(u32 offset) -{ - if (offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - return readU8(&m_data[offset]); -} - -NetworkPacket& NetworkPacket::operator<<(char src) -{ - checkDataSize(); - - writeU8(&m_data[m_read_offset], src); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(u8 src) -{ - checkDataSize(); - - writeU8(&m_data[m_read_offset], src); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(bool src) -{ - checkDataSize(); - - writeU8(&m_data[m_read_offset], src); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(u16 src) -{ - checkDataSize(); - - writeU16(&m_data[m_read_offset], src); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(u32 src) -{ - checkDataSize(); - - writeU32(&m_data[m_read_offset], src); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(u64 src) -{ - checkDataSize(); - - writeU64(&m_data[m_read_offset], src); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(float src) -{ - checkDataSize(); - - writeF1000(&m_data[m_read_offset], src); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator>>(bool& dst) -{ - if (m_read_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - dst = readU8(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator>>(u8& dst) -{ - if (m_read_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - dst = readU8(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -u8 NetworkPacket::getU8(u32 offset) -{ - if (offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - return readU8(&m_data[offset]); -} - -u8* NetworkPacket::getU8Ptr(u32 from_offset) -{ - if (m_datasize == 0) { - return NULL; - } - - if (from_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - return (u8*)&m_data[from_offset]; -} - -NetworkPacket& NetworkPacket::operator>>(u16& dst) -{ - if (m_read_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - dst = readU16(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -u16 NetworkPacket::getU16(u32 from_offset) -{ - if (from_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - return readU16(&m_data[from_offset]); -} - -NetworkPacket& NetworkPacket::operator>>(u32& dst) -{ - if (m_read_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - dst = readU32(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator>>(u64& dst) -{ - if (m_read_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - dst = readU64(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator>>(float& dst) -{ - if (m_read_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - dst = readF1000(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator>>(v2f& dst) -{ - if (m_read_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - dst = readV2F1000(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator>>(v3f& dst) -{ - if (m_read_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - dst = readV3F1000(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator>>(s16& dst) -{ - if (m_read_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - dst = readS16(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(s16 src) -{ - *this << (u16) src; - return *this; -} - -NetworkPacket& NetworkPacket::operator>>(s32& dst) -{ - if (m_read_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - dst = readS32(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(s32 src) -{ - *this << (u32) src; - return *this; -} - -NetworkPacket& NetworkPacket::operator>>(v3s16& dst) -{ - if (m_read_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - dst = readV3S16(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator>>(v2s32& dst) -{ - dst = readV2S32(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator>>(v3s32& dst) -{ - if (m_read_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - dst = readV3S32(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(v2f src) -{ - *this << (float) src.X; - *this << (float) src.Y; - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(v3f src) -{ - *this << (float) src.X; - *this << (float) src.Y; - *this << (float) src.Z; - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(v3s16 src) -{ - *this << (s16) src.X; - *this << (s16) src.Y; - *this << (s16) src.Z; - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(v2s32 src) -{ - *this << (s32) src.X; - *this << (s32) src.Y; - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(v3s32 src) -{ - *this << (s32) src.X; - *this << (s32) src.Y; - *this << (s32) src.Z; - return *this; -} - -NetworkPacket& NetworkPacket::operator>>(video::SColor& dst) -{ - if (m_read_offset >= m_datasize) - throw SerializationError("Malformed packet read"); - - dst = readARGB8(&m_data[m_read_offset]); - - incrOffset(); - return *this; -} - -NetworkPacket& NetworkPacket::operator<<(video::SColor src) -{ - checkDataSize(); - - writeU32(&m_data[m_read_offset], src.color); - - incrOffset(); - return *this; -} - -SharedBuffer NetworkPacket::oldForgePacket() -{ - SharedBuffer sb(m_datasize + 2); - writeU16(&sb[0], m_command); - - u8* datas = getU8Ptr(0); - - if (datas != NULL) - memcpy(&sb[2], datas, m_datasize); - return sb; -} diff --git a/src/network/networkpacket.h b/src/network/networkpacket.h deleted file mode 100644 index e8c8565b0..000000000 --- a/src/network/networkpacket.h +++ /dev/null @@ -1,129 +0,0 @@ -/* -Minetest -Copyright (C) 2015 nerzhul, Loic Blot - -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. -*/ - -#ifndef NETWORKPACKET_HEADER -#define NETWORKPACKET_HEADER - -#include "util/pointer.h" -#include "util/numeric.h" -#include "networkprotocol.h" - -class NetworkPacket -{ - -public: - NetworkPacket(u8 *data, u32 datasize, u16 peer_id); - NetworkPacket(u16 command, u32 datasize, u16 peer_id); - NetworkPacket(u16 command, u32 datasize); - ~NetworkPacket(); - - // Getters - u32 getSize() { return m_datasize; } - u16 getPeerId() { return m_peer_id; } - u16 getCommand() { return m_command; } - - // Data extractors - char* getString(u32 from_offset); - void putRawString(const char* src, u32 len); - - NetworkPacket& operator>>(std::string& dst); - NetworkPacket& operator<<(std::string src); - - void putLongString(std::string src); - - NetworkPacket& operator>>(std::wstring& dst); - NetworkPacket& operator<<(std::wstring src); - - std::string readLongString(); - - char getChar(u32 offset); - NetworkPacket& operator>>(char& dst); - NetworkPacket& operator<<(char src); - - NetworkPacket& operator>>(bool& dst); - NetworkPacket& operator<<(bool src); - - u8 getU8(u32 offset); - - NetworkPacket& operator>>(u8& dst); - NetworkPacket& operator<<(u8 src); - - u8* getU8Ptr(u32 offset); - - u16 getU16(u32 from_offset); - NetworkPacket& operator>>(u16& dst); - NetworkPacket& operator<<(u16 src); - - NetworkPacket& operator>>(u32& dst); - NetworkPacket& operator<<(u32 src); - - NetworkPacket& operator>>(u64& dst); - NetworkPacket& operator<<(u64 src); - - NetworkPacket& operator>>(float& dst); - NetworkPacket& operator<<(float src); - - NetworkPacket& operator>>(v2f& dst); - NetworkPacket& operator<<(v2f src); - - NetworkPacket& operator>>(v3f& dst); - NetworkPacket& operator<<(v3f src); - - NetworkPacket& operator>>(s16& dst); - NetworkPacket& operator<<(s16 src); - - NetworkPacket& operator>>(s32& dst); - NetworkPacket& operator<<(s32 src); - - NetworkPacket& operator>>(v2s32& dst); - NetworkPacket& operator<<(v2s32 src); - - NetworkPacket& operator>>(v3s16& dst); - NetworkPacket& operator<<(v3s16 src); - - NetworkPacket& operator>>(v3s32& dst); - NetworkPacket& operator<<(v3s32 src); - - NetworkPacket& operator>>(video::SColor& dst); - NetworkPacket& operator<<(video::SColor src); - - // Temp, we remove SharedBuffer when migration finished - SharedBuffer oldForgePacket(); -private: - template void checkDataSize() - { - if (m_read_offset + sizeof(T) > m_datasize) { - m_datasize += sizeof(T); - m_data.resize(m_datasize); - } - } - - template void incrOffset() - { - m_read_offset += sizeof(T); - } - - std::vector m_data; - u32 m_datasize; - u32 m_read_offset; - u16 m_command; - u16 m_peer_id; -}; - -#endif diff --git a/src/network/packethandlers/client.cpp b/src/network/packethandlers/client.cpp deleted file mode 100644 index 82f8b61b7..000000000 --- a/src/network/packethandlers/client.cpp +++ /dev/null @@ -1,1024 +0,0 @@ -/* -Minetest -Copyright (C) 2015 nerzhul, Loic Blot - -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 "client.h" - -#include "util/base64.h" -#include "clientmedia.h" -#include "log.h" -#include "map.h" -#include "mapsector.h" -#include "nodedef.h" -#include "serialization.h" -#include "server.h" -#include "strfnd.h" -#include "network/clientopcodes.h" -#include "util/serialize.h" - -void Client::handleCommand_Deprecated(NetworkPacket* pkt) -{ - infostream << "Got deprecated command " - << toClientCommandTable[pkt->getCommand()].name << " from peer " - << pkt->getPeerId() << "!" << std::endl; -} - -void Client::handleCommand_Init(NetworkPacket* pkt) -{ - if (pkt->getSize() < 1) - return; - - u8 deployed; - *pkt >> deployed; - - infostream << "Client: TOCLIENT_INIT received with " - "deployed=" << ((int)deployed & 0xff) << std::endl; - - if (!ser_ver_supported(deployed)) { - infostream << "Client: TOCLIENT_INIT: Server sent " - << "unsupported ser_fmt_ver"<< std::endl; - return; - } - - m_server_ser_ver = deployed; - - // Get player position - v3s16 playerpos_s16(0, BS * 2 + BS * 20, 0); - if (pkt->getSize() >= 1 + 6) { - *pkt >> playerpos_s16; - } - v3f playerpos_f = intToFloat(playerpos_s16, BS) - v3f(0, BS / 2, 0); - - - // Set player position - Player *player = m_env.getLocalPlayer(); - assert(player != NULL); - player->setPosition(playerpos_f); - - if (pkt->getSize() >= 1 + 6 + 8) { - // Get map seed - *pkt >> m_map_seed; - infostream << "Client: received map seed: " << m_map_seed << std::endl; - } - - if (pkt->getSize() >= 1 + 6 + 8 + 4) { - *pkt >> m_recommended_send_interval; - infostream << "Client: received recommended send interval " - << m_recommended_send_interval<getSize() >= 2) { - *pkt >> m_access_denied_reason; - } -} - -void Client::handleCommand_RemoveNode(NetworkPacket* pkt) -{ - if (pkt->getSize() < 6) - return; - - v3s16 p; - *pkt >> p; - removeNode(p); -} - -void Client::handleCommand_AddNode(NetworkPacket* pkt) -{ - if (pkt->getSize() < 6 + MapNode::serializedLength(m_server_ser_ver)) - return; - - v3s16 p; - *pkt >> p; - - MapNode n; - n.deSerialize(pkt->getU8Ptr(6), m_server_ser_ver); - - bool remove_metadata = true; - u32 index = 6 + MapNode::serializedLength(m_server_ser_ver); - if ((pkt->getSize() >= index + 1) && pkt->getU8(index)) { - remove_metadata = false; - } - - addNode(p, n, remove_metadata); -} -void Client::handleCommand_BlockData(NetworkPacket* pkt) -{ - // Ignore too small packet - if (pkt->getSize() < 6) - return; - - v3s16 p; - *pkt >> p; - - std::string datastring(pkt->getString(6), pkt->getSize() - 6); - std::istringstream istr(datastring, std::ios_base::binary); - - MapSector *sector; - MapBlock *block; - - v2s16 p2d(p.X, p.Z); - sector = m_env.getMap().emergeSector(p2d); - - assert(sector->getPos() == p2d); - - block = sector->getBlockNoCreateNoEx(p.Y); - if (block) { - /* - Update an existing block - */ - block->deSerialize(istr, m_server_ser_ver, false); - block->deSerializeNetworkSpecific(istr); - } - else { - /* - Create a new block - */ - block = new MapBlock(&m_env.getMap(), p, this); - block->deSerialize(istr, m_server_ser_ver, false); - block->deSerializeNetworkSpecific(istr); - sector->insertBlock(block); - } - - if (m_localdb) { - ServerMap::saveBlock(block, m_localdb); - } - - /* - Add it to mesh update queue and set it to be acknowledged after update. - */ - addUpdateMeshTaskWithEdge(p, true); -} - -void Client::handleCommand_Inventory(NetworkPacket* pkt) -{ - if (pkt->getSize() < 1) - return; - - std::string datastring(pkt->getString(0), pkt->getSize()); - std::istringstream is(datastring, std::ios_base::binary); - - Player *player = m_env.getLocalPlayer(); - assert(player != NULL); - - player->inventory.deSerialize(is); - - m_inventory_updated = true; - - delete m_inventory_from_server; - m_inventory_from_server = new Inventory(player->inventory); - m_inventory_from_server_age = 0.0; -} - -void Client::handleCommand_TimeOfDay(NetworkPacket* pkt) -{ - if (pkt->getSize() < 2) - return; - - u16 time_of_day; - - *pkt >> time_of_day; - - time_of_day = time_of_day % 24000; - float time_speed = 0; - - if (pkt->getSize() >= 2 + 4) { - *pkt >> time_speed; - } - else { - // Old message; try to approximate speed of time by ourselves - float time_of_day_f = (float)time_of_day / 24000.0; - float tod_diff_f = 0; - - if (time_of_day_f < 0.2 && m_last_time_of_day_f > 0.8) - tod_diff_f = time_of_day_f - m_last_time_of_day_f + 1.0; - else - tod_diff_f = time_of_day_f - m_last_time_of_day_f; - - m_last_time_of_day_f = time_of_day_f; - float time_diff = m_time_of_day_update_timer; - m_time_of_day_update_timer = 0; - - if (m_time_of_day_set) { - time_speed = (3600.0 * 24.0) * tod_diff_f / time_diff; - infostream << "Client: Measured time_of_day speed (old format): " - << time_speed << " tod_diff_f=" << tod_diff_f - << " time_diff=" << time_diff << std::endl; - } - } - - // Update environment - m_env.setTimeOfDay(time_of_day); - m_env.setTimeOfDaySpeed(time_speed); - m_time_of_day_set = true; - - u32 dr = m_env.getDayNightRatio(); - infostream << "Client: time_of_day=" << time_of_day - << " time_speed=" << time_speed - << " dr=" << dr << std::endl; -} - -void Client::handleCommand_ChatMessage(NetworkPacket* pkt) -{ - /* - u16 command - u16 length - wstring message - */ - u16 len, read_wchar; - - *pkt >> len; - - std::wstring message; - for (u32 i = 0; i < len; i++) { - *pkt >> read_wchar; - message += (wchar_t)read_wchar; - } - - m_chat_queue.push(message); -} - -void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt) -{ - /* - u16 command - u16 count of removed objects - for all removed objects { - u16 id - } - u16 count of added objects - for all added objects { - u16 id - u8 type - u32 initialization data length - string initialization data - } - */ - - // Read removed objects - u8 type; - u16 removed_count, added_count, id; - - *pkt >> removed_count; - - for (u16 i = 0; i < removed_count; i++) { - *pkt >> id; - m_env.removeActiveObject(id); - } - - // Read added objects - *pkt >> added_count; - - for (u16 i = 0; i < added_count; i++) { - *pkt >> id >> type; - m_env.addActiveObject(id, type, pkt->readLongString()); - } -} - -void Client::handleCommand_ActiveObjectMessages(NetworkPacket* pkt) -{ - /* - u16 command - for all objects - { - u16 id - u16 message length - string message - } - */ - char buf[6]; - // Get all data except the command number - std::string datastring(pkt->getString(0), pkt->getSize()); - // Throw them in an istringstream - std::istringstream is(datastring, std::ios_base::binary); - - while(is.eof() == false) { - is.read(buf, 2); - u16 id = readU16((u8*)buf); - if (is.eof()) - break; - is.read(buf, 2); - size_t message_size = readU16((u8*)buf); - std::string message; - message.reserve(message_size); - for (u32 i = 0; i < message_size; i++) { - is.read(buf, 1); - message.append(buf, 1); - } - // Pass on to the environment - m_env.processActiveObjectMessage(id, message); - } -} - -void Client::handleCommand_Movement(NetworkPacket* pkt) -{ - Player *player = m_env.getLocalPlayer(); - assert(player != NULL); - - float mad, maa, maf, msw, mscr, msf, mscl, msj, lf, lfs, ls, g; - - *pkt >> mad >> maa >> maf >> msw >> mscr >> msf >> mscl >> msj - >> lf >> lfs >> ls >> g; - - player->movement_acceleration_default = mad * BS; - player->movement_acceleration_air = maa * BS; - player->movement_acceleration_fast = maf * BS; - player->movement_speed_walk = msw * BS; - player->movement_speed_crouch = mscr * BS; - player->movement_speed_fast = msf * BS; - player->movement_speed_climb = mscl * BS; - player->movement_speed_jump = msj * BS; - player->movement_liquid_fluidity = lf * BS; - player->movement_liquid_fluidity_smooth = lfs * BS; - player->movement_liquid_sink = ls * BS; - player->movement_gravity = g * BS; -} - -void Client::handleCommand_HP(NetworkPacket* pkt) -{ - - Player *player = m_env.getLocalPlayer(); - assert(player != NULL); - - u8 oldhp = player->hp; - - u8 hp; - *pkt >> hp; - - player->hp = hp; - - if (hp < oldhp) { - // Add to ClientEvent queue - ClientEvent event; - event.type = CE_PLAYER_DAMAGE; - event.player_damage.amount = oldhp - hp; - m_client_event_queue.push(event); - } -} - -void Client::handleCommand_Breath(NetworkPacket* pkt) -{ - Player *player = m_env.getLocalPlayer(); - assert(player != NULL); - - u16 breath; - - *pkt >> breath; - - player->setBreath(breath); -} - -void Client::handleCommand_MovePlayer(NetworkPacket* pkt) -{ - Player *player = m_env.getLocalPlayer(); - assert(player != NULL); - - v3f pos; - f32 pitch, yaw; - - *pkt >> pos >> pitch >> yaw; - - player->setPosition(pos); - - infostream << "Client got TOCLIENT_MOVE_PLAYER" - << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")" - << " pitch=" << pitch - << " yaw=" << yaw - << std::endl; - - /* - Add to ClientEvent queue. - This has to be sent to the main program because otherwise - it would just force the pitch and yaw values to whatever - the camera points to. - */ - ClientEvent event; - event.type = CE_PLAYER_FORCE_MOVE; - event.player_force_move.pitch = pitch; - event.player_force_move.yaw = yaw; - m_client_event_queue.push(event); - - // Ignore damage for a few seconds, so that the player doesn't - // get damage from falling on ground - m_ignore_damage_timer = 3.0; -} - -void Client::handleCommand_PlayerItem(NetworkPacket* pkt) -{ - infostream << "Client: WARNING: Ignoring TOCLIENT_PLAYERITEM" << std::endl; -} - -void Client::handleCommand_DeathScreen(NetworkPacket* pkt) -{ - bool set_camera_point_target; - v3f camera_point_target; - - *pkt >> set_camera_point_target; - *pkt >> camera_point_target; - - ClientEvent event; - event.type = CE_DEATHSCREEN; - event.deathscreen.set_camera_point_target = set_camera_point_target; - event.deathscreen.camera_point_target_x = camera_point_target.X; - event.deathscreen.camera_point_target_y = camera_point_target.Y; - event.deathscreen.camera_point_target_z = camera_point_target.Z; - m_client_event_queue.push(event); -} - -void Client::handleCommand_AnnounceMedia(NetworkPacket* pkt) -{ - u16 num_files; - - *pkt >> num_files; - - infostream << "Client: Received media announcement: packet size: " - << pkt->getSize() << std::endl; - - if (m_media_downloader == NULL || - m_media_downloader->isStarted()) { - const char *problem = m_media_downloader ? - "we already saw another announcement" : - "all media has been received already"; - errorstream << "Client: Received media announcement but " - << problem << "! " - << " files=" << num_files - << " size=" << pkt->getSize() << std::endl; - return; - } - - // Mesh update thread must be stopped while - // updating content definitions - assert(!m_mesh_update_thread.IsRunning()); - - for (u16 i = 0; i < num_files; i++) { - std::string name, sha1_base64; - - *pkt >> name >> sha1_base64; - - std::string sha1_raw = base64_decode(sha1_base64); - m_media_downloader->addFile(name, sha1_raw); - } - - std::vector remote_media; - try { - std::string str; - - *pkt >> str; - - Strfnd sf(str); - while(!sf.atend()) { - std::string baseurl = trim(sf.next(",")); - if (baseurl != "") - m_media_downloader->addRemoteServer(baseurl); - } - } - catch(SerializationError& e) { - // not supported by server or turned off - } - - m_media_downloader->step(this); -} - -void Client::handleCommand_Media(NetworkPacket* pkt) -{ - /* - u16 command - u16 total number of file bunches - u16 index of this bunch - u32 number of files in this bunch - for each file { - u16 length of name - string name - u32 length of data - data - } - */ - u16 num_bunches; - u16 bunch_i; - u32 num_files; - - *pkt >> num_bunches >> bunch_i >> num_files; - - infostream << "Client: Received files: bunch " << bunch_i << "/" - << num_bunches << " files=" << num_files - << " size=" << pkt->getSize() << std::endl; - - if (num_files == 0) - return; - - if (m_media_downloader == NULL || - !m_media_downloader->isStarted()) { - const char *problem = m_media_downloader ? - "media has not been requested" : - "all media has been received already"; - errorstream << "Client: Received media but " - << problem << "! " - << " bunch " << bunch_i << "/" << num_bunches - << " files=" << num_files - << " size=" << pkt->getSize() << std::endl; - return; - } - - // Mesh update thread must be stopped while - // updating content definitions - assert(!m_mesh_update_thread.IsRunning()); - - for (u32 i=0; i < num_files; i++) { - std::string name; - - *pkt >> name; - - std::string data = pkt->readLongString(); - - m_media_downloader->conventionalTransferDone( - name, data, this); - } -} - -void Client::handleCommand_ToolDef(NetworkPacket* pkt) -{ - infostream << "Client: WARNING: Ignoring TOCLIENT_TOOLDEF" << std::endl; -} - -void Client::handleCommand_NodeDef(NetworkPacket* pkt) -{ - infostream << "Client: Received node definitions: packet size: " - << pkt->getSize() << std::endl; - - // Mesh update thread must be stopped while - // updating content definitions - assert(!m_mesh_update_thread.IsRunning()); - - // Decompress node definitions - std::string datastring(pkt->getString(0), pkt->getSize()); - std::istringstream is(datastring, std::ios_base::binary); - std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary); - std::ostringstream tmp_os; - decompressZlib(tmp_is, tmp_os); - - // Deserialize node definitions - std::istringstream tmp_is2(tmp_os.str()); - m_nodedef->deSerialize(tmp_is2); - m_nodedef_received = true; -} - -void Client::handleCommand_CraftItemDef(NetworkPacket* pkt) -{ - infostream << "Client: WARNING: Ignoring TOCLIENT_CRAFTITEMDEF" << std::endl; -} - -void Client::handleCommand_ItemDef(NetworkPacket* pkt) -{ - infostream << "Client: Received item definitions: packet size: " - << pkt->getSize() << std::endl; - - // Mesh update thread must be stopped while - // updating content definitions - assert(!m_mesh_update_thread.IsRunning()); - - // Decompress item definitions - std::string datastring(pkt->getString(0), pkt->getSize()); - std::istringstream is(datastring, std::ios_base::binary); - std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary); - std::ostringstream tmp_os; - decompressZlib(tmp_is, tmp_os); - - // Deserialize node definitions - std::istringstream tmp_is2(tmp_os.str()); - m_itemdef->deSerialize(tmp_is2); - m_itemdef_received = true; -} - -void Client::handleCommand_PlaySound(NetworkPacket* pkt) -{ - s32 server_id; - std::string name; - float gain; - u8 type; // 0=local, 1=positional, 2=object - v3f pos; - u16 object_id; - bool loop; - - *pkt >> server_id >> name >> gain >> type >> pos >> object_id >> loop; - - // Start playing - int client_id = -1; - switch(type) { - case 0: // local - client_id = m_sound->playSound(name, loop, gain); - break; - case 1: // positional - client_id = m_sound->playSoundAt(name, loop, gain, pos); - break; - case 2: - { // object - ClientActiveObject *cao = m_env.getActiveObject(object_id); - if (cao) - pos = cao->getPosition(); - client_id = m_sound->playSoundAt(name, loop, gain, pos); - // TODO: Set up sound to move with object - break; - } - default: - break; - } - - if (client_id != -1) { - m_sounds_server_to_client[server_id] = client_id; - m_sounds_client_to_server[client_id] = server_id; - if (object_id != 0) - m_sounds_to_objects[client_id] = object_id; - } -} - -void Client::handleCommand_StopSound(NetworkPacket* pkt) -{ - s32 server_id; - - *pkt >> server_id; - - std::map::iterator i = - m_sounds_server_to_client.find(server_id); - - if (i != m_sounds_server_to_client.end()) { - int client_id = i->second; - m_sound->stopSound(client_id); - } -} - -void Client::handleCommand_Privileges(NetworkPacket* pkt) -{ - m_privileges.clear(); - infostream << "Client: Privileges updated: "; - u16 num_privileges; - - *pkt >> num_privileges; - - for (u16 i = 0; i < num_privileges; i++) { - std::string priv; - - *pkt >> priv; - - m_privileges.insert(priv); - infostream << priv << " "; - } - infostream << std::endl; -} - -void Client::handleCommand_InventoryFormSpec(NetworkPacket* pkt) -{ - Player *player = m_env.getLocalPlayer(); - assert(player != NULL); - - // Store formspec in LocalPlayer - player->inventory_formspec = pkt->readLongString(); -} - -void Client::handleCommand_DetachedInventory(NetworkPacket* pkt) -{ - std::string datastring(pkt->getString(0), pkt->getSize()); - std::istringstream is(datastring, std::ios_base::binary); - - std::string name = deSerializeString(is); - - infostream << "Client: Detached inventory update: \"" << name - << "\"" << std::endl; - - Inventory *inv = NULL; - if (m_detached_inventories.count(name) > 0) - inv = m_detached_inventories[name]; - else { - inv = new Inventory(m_itemdef); - m_detached_inventories[name] = inv; - } - inv->deSerialize(is); -} - -void Client::handleCommand_ShowFormSpec(NetworkPacket* pkt) -{ - std::string formspec = pkt->readLongString(); - std::string formname; - - *pkt >> formname; - - ClientEvent event; - event.type = CE_SHOW_FORMSPEC; - // pointer is required as event is a struct only! - // adding a std:string to a struct isn't possible - event.show_formspec.formspec = new std::string(formspec); - event.show_formspec.formname = new std::string(formname); - m_client_event_queue.push(event); -} - -void Client::handleCommand_SpawnParticle(NetworkPacket* pkt) -{ - std::string datastring(pkt->getString(0), pkt->getSize()); - std::istringstream is(datastring, std::ios_base::binary); - - v3f pos = readV3F1000(is); - v3f vel = readV3F1000(is); - v3f acc = readV3F1000(is); - float expirationtime = readF1000(is); - float size = readF1000(is); - bool collisiondetection = readU8(is); - std::string texture = deSerializeLongString(is); - bool vertical = false; - try { - vertical = readU8(is); - } catch (...) {} - - ClientEvent event; - event.type = CE_SPAWN_PARTICLE; - event.spawn_particle.pos = new v3f (pos); - event.spawn_particle.vel = new v3f (vel); - event.spawn_particle.acc = new v3f (acc); - event.spawn_particle.expirationtime = expirationtime; - event.spawn_particle.size = size; - event.spawn_particle.collisiondetection = collisiondetection; - event.spawn_particle.vertical = vertical; - event.spawn_particle.texture = new std::string(texture); - - m_client_event_queue.push(event); -} - -void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt) -{ - u16 amount; - float spawntime; - v3f minpos; - v3f maxpos; - v3f minvel; - v3f maxvel; - v3f minacc; - v3f maxacc; - float minexptime; - float maxexptime; - float minsize; - float maxsize; - bool collisiondetection; - u32 id; - - *pkt >> amount >> spawntime >> minpos >> maxpos >> minvel >> maxvel - >> minacc >> maxacc >> minexptime >> maxexptime >> minsize - >> maxsize >> collisiondetection; - - std::string texture = pkt->readLongString(); - - *pkt >> id; - - bool vertical = false; - try { - *pkt >> vertical; - } catch (...) {} - - ClientEvent event; - event.type = CE_ADD_PARTICLESPAWNER; - event.add_particlespawner.amount = amount; - event.add_particlespawner.spawntime = spawntime; - event.add_particlespawner.minpos = new v3f (minpos); - event.add_particlespawner.maxpos = new v3f (maxpos); - event.add_particlespawner.minvel = new v3f (minvel); - event.add_particlespawner.maxvel = new v3f (maxvel); - event.add_particlespawner.minacc = new v3f (minacc); - event.add_particlespawner.maxacc = new v3f (maxacc); - event.add_particlespawner.minexptime = minexptime; - event.add_particlespawner.maxexptime = maxexptime; - event.add_particlespawner.minsize = minsize; - event.add_particlespawner.maxsize = maxsize; - event.add_particlespawner.collisiondetection = collisiondetection; - event.add_particlespawner.vertical = vertical; - event.add_particlespawner.texture = new std::string(texture); - event.add_particlespawner.id = id; - - m_client_event_queue.push(event); -} - - -void Client::handleCommand_DeleteParticleSpawner(NetworkPacket* pkt) -{ - u16 id; - - *pkt >> id; - - ClientEvent event; - event.type = CE_DELETE_PARTICLESPAWNER; - event.delete_particlespawner.id = (u32) id; - - m_client_event_queue.push(event); -} - -void Client::handleCommand_HudAdd(NetworkPacket* pkt) -{ - std::string datastring(pkt->getString(0), pkt->getSize()); - std::istringstream is(datastring, std::ios_base::binary); - - u32 id; - u8 type; - v2f pos; - std::string name; - v2f scale; - std::string text; - u32 number; - u32 item; - u32 dir; - v2f align; - v2f offset; - v3f world_pos; - v2s32 size; - - *pkt >> id >> type >> pos >> name >> scale >> text >> number >> item - >> dir >> align >> offset; - try { - *pkt >> world_pos; - } - catch(SerializationError &e) {}; - - try { - *pkt >> size; - } catch(SerializationError &e) {}; - - ClientEvent event; - event.type = CE_HUDADD; - event.hudadd.id = id; - event.hudadd.type = type; - event.hudadd.pos = new v2f(pos); - event.hudadd.name = new std::string(name); - event.hudadd.scale = new v2f(scale); - event.hudadd.text = new std::string(text); - event.hudadd.number = number; - event.hudadd.item = item; - event.hudadd.dir = dir; - event.hudadd.align = new v2f(align); - event.hudadd.offset = new v2f(offset); - event.hudadd.world_pos = new v3f(world_pos); - event.hudadd.size = new v2s32(size); - m_client_event_queue.push(event); -} - -void Client::handleCommand_HudRemove(NetworkPacket* pkt) -{ - u32 id; - - *pkt >> id; - - ClientEvent event; - event.type = CE_HUDRM; - event.hudrm.id = id; - m_client_event_queue.push(event); -} - -void Client::handleCommand_HudChange(NetworkPacket* pkt) -{ - std::string sdata; - v2f v2fdata; - v3f v3fdata; - u32 intdata = 0; - v2s32 v2s32data; - u32 id; - u8 stat; - - *pkt >> id >> stat; - - if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE || - stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET) - *pkt >> v2fdata; - else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT) - *pkt >> sdata; - else if (stat == HUD_STAT_WORLD_POS) - *pkt >> v3fdata; - else if (stat == HUD_STAT_SIZE ) - *pkt >> v2s32data; - else - *pkt >> intdata; - - ClientEvent event; - event.type = CE_HUDCHANGE; - event.hudchange.id = id; - event.hudchange.stat = (HudElementStat)stat; - event.hudchange.v2fdata = new v2f(v2fdata); - event.hudchange.v3fdata = new v3f(v3fdata); - event.hudchange.sdata = new std::string(sdata); - event.hudchange.data = intdata; - event.hudchange.v2s32data = new v2s32(v2s32data); - m_client_event_queue.push(event); -} - -void Client::handleCommand_HudSetFlags(NetworkPacket* pkt) -{ - u32 flags, mask; - - *pkt >> flags >> mask; - - Player *player = m_env.getLocalPlayer(); - assert(player != NULL); - - player->hud_flags &= ~mask; - player->hud_flags |= flags; -} - -void Client::handleCommand_HudSetParam(NetworkPacket* pkt) -{ - u16 param; std::string value; - - *pkt >> param >> value; - - Player *player = m_env.getLocalPlayer(); - assert(player != NULL); - - if (param == HUD_PARAM_HOTBAR_ITEMCOUNT && value.size() == 4) { - s32 hotbar_itemcount = readS32((u8*) value.c_str()); - if (hotbar_itemcount > 0 && hotbar_itemcount <= HUD_HOTBAR_ITEMCOUNT_MAX) - player->hud_hotbar_itemcount = hotbar_itemcount; - } - else if (param == HUD_PARAM_HOTBAR_IMAGE) { - ((LocalPlayer *) player)->hotbar_image = value; - } - else if (param == HUD_PARAM_HOTBAR_SELECTED_IMAGE) { - ((LocalPlayer *) player)->hotbar_selected_image = value; - } -} - -void Client::handleCommand_HudSetSky(NetworkPacket* pkt) -{ - std::string datastring(pkt->getString(0), pkt->getSize()); - std::istringstream is(datastring, std::ios_base::binary); - - video::SColor *bgcolor = new video::SColor(readARGB8(is)); - std::string *type = new std::string(deSerializeString(is)); - u16 count = readU16(is); - std::vector *params = new std::vector; - - for (size_t i = 0; i < count; i++) - params->push_back(deSerializeString(is)); - - ClientEvent event; - event.type = CE_SET_SKY; - event.set_sky.bgcolor = bgcolor; - event.set_sky.type = type; - event.set_sky.params = params; - m_client_event_queue.push(event); -} - -void Client::handleCommand_OverrideDayNightRatio(NetworkPacket* pkt) -{ - bool do_override; - u16 day_night_ratio_u; - - *pkt >> do_override >> day_night_ratio_u; - - float day_night_ratio_f = (float)day_night_ratio_u / 65536; - - ClientEvent event; - event.type = CE_OVERRIDE_DAY_NIGHT_RATIO; - event.override_day_night_ratio.do_override = do_override; - event.override_day_night_ratio.ratio_f = day_night_ratio_f; - m_client_event_queue.push(event); -} - -void Client::handleCommand_LocalPlayerAnimations(NetworkPacket* pkt) -{ - LocalPlayer *player = m_env.getLocalPlayer(); - assert(player != NULL); - - *pkt >> player->local_animations[0]; - *pkt >> player->local_animations[1]; - *pkt >> player->local_animations[2]; - *pkt >> player->local_animations[3]; - *pkt >> player->local_animation_speed; -} - -void Client::handleCommand_EyeOffset(NetworkPacket* pkt) -{ - LocalPlayer *player = m_env.getLocalPlayer(); - assert(player != NULL); - - *pkt >> player->eye_offset_first >> player->eye_offset_third; -} diff --git a/src/network/packethandlers/server.cpp b/src/network/packethandlers/server.cpp deleted file mode 100644 index a11e8dc2f..000000000 --- a/src/network/packethandlers/server.cpp +++ /dev/null @@ -1,1549 +0,0 @@ -/* -Minetest -Copyright (C) 2015 nerzhul, Loic Blot - -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 "server.h" -#include "log.h" - -#include "content_abm.h" -#include "content_sao.h" -#include "emerge.h" -#include "main.h" -#include "nodedef.h" -#include "player.h" -#include "rollback_interface.h" -#include "scripting_game.h" -#include "settings.h" -#include "tool.h" -#include "version.h" -#include "network/networkprotocol.h" -#include "network/serveropcodes.h" -#include "util/base64.h" -#include "util/pointedthing.h" -#include "util/serialize.h" - -void Server::handleCommand_Deprecated(NetworkPacket* pkt) -{ - infostream << "Server: " << toServerCommandTable[pkt->getCommand()].name - << " not supported anymore" << std::endl; -} - -void Server::handleCommand_Init(NetworkPacket* pkt) -{ - // [0] u8 SER_FMT_VER_HIGHEST_READ - // [1] u8[20] player_name - // [21] u8[28] password <--- can be sent without this, from old versions - - if (pkt->getSize() < 1+PLAYERNAME_SIZE) - return; - - RemoteClient* client = getClient(pkt->getPeerId(), CS_Created); - - std::string addr_s; - try { - Address address = getPeerAddress(pkt->getPeerId()); - addr_s = address.serializeString(); - } - catch (con::PeerNotFoundException &e) { - /* - * no peer for this packet found - * most common reason is peer timeout, e.g. peer didn't - * respond for some time, your server was overloaded or - * things like that. - */ - infostream << "Server::ProcessData(): Cancelling: peer " - << pkt->getPeerId() << " not found" << std::endl; - return; - } - - // If net_proto_version is set, this client has already been handled - if (client->getState() > CS_Created) { - verbosestream << "Server: Ignoring multiple TOSERVER_INITs from " - << addr_s << " (peer_id=" << pkt->getPeerId() << ")" << std::endl; - return; - } - - verbosestream << "Server: Got TOSERVER_INIT from " << addr_s << " (peer_id=" - << pkt->getPeerId() << ")" << std::endl; - - // Do not allow multiple players in simple singleplayer mode. - // This isn't a perfect way to do it, but will suffice for now - if (m_simple_singleplayer_mode && m_clients.getClientIDs().size() > 1) { - infostream << "Server: Not allowing another client (" << addr_s - << ") to connect in simple singleplayer mode" << std::endl; - DenyAccess(pkt->getPeerId(), L"Running in simple singleplayer mode."); - return; - } - - // First byte after command is maximum supported - // serialization version - u8 client_max; - - *pkt >> client_max; - - u8 our_max = SER_FMT_VER_HIGHEST_READ; - // Use the highest version supported by both - int deployed = std::min(client_max, our_max); - // If it's lower than the lowest supported, give up. - if (deployed < SER_FMT_VER_LOWEST) - deployed = SER_FMT_VER_INVALID; - - if (deployed == SER_FMT_VER_INVALID) { - actionstream << "Server: A mismatched client tried to connect from " - << addr_s << std::endl; - infostream<<"Server: Cannot negotiate serialization version with " - << addr_s << std::endl; - DenyAccess(pkt->getPeerId(), std::wstring( - L"Your client's version is not supported.\n" - L"Server version is ") - + narrow_to_wide(minetest_version_simple) + L"." - ); - return; - } - - client->setPendingSerializationVersion(deployed); - - /* - Read and check network protocol version - */ - - u16 min_net_proto_version = 0; - if (pkt->getSize() >= 1 + PLAYERNAME_SIZE + PASSWORD_SIZE + 2) - min_net_proto_version = pkt->getU16(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 (pkt->getSize() >= 1 + PLAYERNAME_SIZE + PASSWORD_SIZE + 2 + 2) - max_net_proto_version = pkt->getU16(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) { - // 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: " << addr_s << ": Protocol version: min: " - << min_net_proto_version << ", max: " << max_net_proto_version - << ", chosen: " << net_proto_version << std::endl; - - client->net_proto_version = net_proto_version; - - if (net_proto_version < SERVER_PROTOCOL_VERSION_MIN || - net_proto_version > SERVER_PROTOCOL_VERSION_MAX) { - actionstream << "Server: A mismatched client tried to connect from " - << addr_s << std::endl; - DenyAccess(pkt->getPeerId(), std::wstring( - L"Your client's version is not supported.\n" - L"Server version is ") - + narrow_to_wide(minetest_version_simple) + L",\n" - + L"server's PROTOCOL_VERSION is " - + narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MIN)) - + L"..." - + narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MAX)) - + L", client's PROTOCOL_VERSION is " - + narrow_to_wide(itos(min_net_proto_version)) - + L"..." - + narrow_to_wide(itos(max_net_proto_version)) - ); - return; - } - - if (g_settings->getBool("strict_protocol_version_checking")) { - if (net_proto_version != LATEST_PROTOCOL_VERSION) { - actionstream << "Server: A mismatched (strict) client tried to " - << "connect from " << addr_s << std::endl; - DenyAccess(pkt->getPeerId(), std::wstring( - L"Your client's version is not supported.\n" - L"Server version is ") - + narrow_to_wide(minetest_version_simple) + L",\n" - + L"server's PROTOCOL_VERSION (strict) is " - + narrow_to_wide(itos(LATEST_PROTOCOL_VERSION)) - + L", client's PROTOCOL_VERSION is " - + narrow_to_wide(itos(min_net_proto_version)) - + L"..." - + narrow_to_wide(itos(max_net_proto_version)) - ); - return; - } - } - - /* - Set up player - */ - char playername[PLAYERNAME_SIZE]; - unsigned int playername_length = 0; - for (; playername_length < PLAYERNAME_SIZE; playername_length++ ) { - playername[playername_length] = pkt->getChar(1+playername_length); - if (pkt->getChar(1+playername_length) == 0) - break; - } - - if (playername_length == PLAYERNAME_SIZE) { - actionstream << "Server: Player with name exceeding max length " - << "tried to connect from " << addr_s << std::endl; - DenyAccess(pkt->getPeerId(), L"Name too long"); - return; - } - - - if (playername[0]=='\0') { - actionstream << "Server: Player with an empty name " - << "tried to connect from " << addr_s << std::endl; - DenyAccess(pkt->getPeerId(), L"Empty name"); - return; - } - - if (string_allowed(playername, PLAYERNAME_ALLOWED_CHARS) == false) { - actionstream << "Server: Player with an invalid name " - << "tried to connect from " << addr_s << std::endl; - DenyAccess(pkt->getPeerId(), L"Name contains unallowed characters"); - return; - } - - if (!isSingleplayer() && strcasecmp(playername, "singleplayer") == 0) { - actionstream << "Server: Player with the name \"singleplayer\" " - << "tried to connect from " << addr_s << std::endl; - DenyAccess(pkt->getPeerId(), L"Name is not allowed"); - return; - } - - { - std::string reason; - if (m_script->on_prejoinplayer(playername, addr_s, reason)) { - actionstream << "Server: Player with the name \"" << playername << "\" " - << "tried to connect from " << addr_s << " " - << "but it was disallowed for the following reason: " - << reason << std::endl; - DenyAccess(pkt->getPeerId(), narrow_to_wide(reason.c_str())); - return; - } - } - - infostream<<"Server: New connection: \""<getSize() < 1 + PLAYERNAME_SIZE + PASSWORD_SIZE) { - // old version - assume blank password - given_password[0] = 0; - } - else { - for (u16 i = 0; i < PASSWORD_SIZE - 1; i++) { - given_password[i] = pkt->getChar(21 + i); - } - given_password[PASSWORD_SIZE - 1] = 0; - } - - if (!base64_is_valid(given_password)) { - actionstream << "Server: " << playername - << " supplied invalid password hash" << std::endl; - DenyAccess(pkt->getPeerId(), L"Invalid password hash"); - return; - } - - // Enforce user limit. - // Don't enforce for users that have some admin right - if (m_clients.getClientIDs(CS_Created).size() >= g_settings->getU16("max_users") && - !checkPriv(playername, "server") && - !checkPriv(playername, "ban") && - !checkPriv(playername, "privs") && - !checkPriv(playername, "password") && - playername != g_settings->get("name")) { - actionstream << "Server: " << playername << " tried to join, but there" - << " are already max_users=" - << g_settings->getU16("max_users") << " players." << std::endl; - DenyAccess(pkt->getPeerId(), L"Too many users."); - return; - } - - std::string checkpwd; // Password hash to check against - bool has_auth = m_script->getAuth(playername, &checkpwd, NULL); - - // If no authentication info exists for user, create it - if (!has_auth) { - if (!isSingleplayer() && - g_settings->getBool("disallow_empty_password") && - std::string(given_password) == "") { - actionstream << "Server: " << playername - << " supplied empty password" << std::endl; - DenyAccess(pkt->getPeerId(), L"Empty passwords are " - L"disallowed. Set a password and try again."); - return; - } - std::wstring raw_default_password = - narrow_to_wide(g_settings->get("default_password")); - std::string initial_password = - translatePassword(playername, raw_default_password); - - // If default_password is empty, allow any initial password - if (raw_default_password.length() == 0) - initial_password = given_password; - - m_script->createAuth(playername, initial_password); - } - - has_auth = m_script->getAuth(playername, &checkpwd, NULL); - - if (!has_auth) { - actionstream << "Server: " << playername << " cannot be authenticated" - << " (auth handler does not work?)" << std::endl; - DenyAccess(pkt->getPeerId(), L"Not allowed to login"); - return; - } - - if (given_password != checkpwd) { - actionstream << "Server: " << playername << " supplied wrong password" - << std::endl; - DenyAccess(pkt->getPeerId(), L"Wrong password"); - return; - } - - RemotePlayer *player = - static_cast(m_env->getPlayer(playername)); - - if (player && player->peer_id != 0) { - errorstream << "Server: " << playername << ": Failed to emerge player" - << " (player allocated to an another client)" << std::endl; - DenyAccess(pkt->getPeerId(), L"Another client is connected with this " - L"name. If your client closed unexpectedly, try again in " - L"a minute."); - } - - m_clients.setPlayerName(pkt->getPeerId(), playername); - - /* - Answer with a TOCLIENT_INIT - */ - - NetworkPacket* resp_pkt = new NetworkPacket(TOCLIENT_INIT, 1 + 6 + 8 + 4, - pkt->getPeerId()); - - *resp_pkt << (u8) deployed << (v3s16) floatToInt(v3f(0,0,0), BS) - << (u64) m_env->getServerMap().getSeed() - << g_settings->getFloat("dedicated_server_step"); - - Send(resp_pkt); - m_clients.event(pkt->getPeerId(), CSE_Init); -} - -void Server::handleCommand_Init2(NetworkPacket* pkt) -{ - verbosestream << "Server: Got TOSERVER_INIT2 from " - << pkt->getPeerId() << std::endl; - - m_clients.event(pkt->getPeerId(), CSE_GotInit2); - u16 protocol_version = m_clients.getProtocolVersion(pkt->getPeerId()); - - - ///// begin compatibility code - PlayerSAO* playersao = NULL; - if (protocol_version <= 22) { - playersao = StageTwoClientInit(pkt->getPeerId()); - - if (playersao == NULL) { - errorstream - << "TOSERVER_INIT2 stage 2 client init failed for peer " - << pkt->getPeerId() << std::endl; - return; - } - } - ///// end compatibility code - - /* - Send some initialization data - */ - - infostream << "Server: Sending content to " - << getPlayerName(pkt->getPeerId()) << std::endl; - - // Send player movement settings - SendMovement(pkt->getPeerId()); - - // Send item definitions - SendItemDef(pkt->getPeerId(), m_itemdef, protocol_version); - - // Send node definitions - SendNodeDef(pkt->getPeerId(), m_nodedef, protocol_version); - - m_clients.event(pkt->getPeerId(), CSE_SetDefinitionsSent); - - // Send media announcement - sendMediaAnnouncement(pkt->getPeerId()); - - // Send detached inventories - sendDetachedInventories(pkt->getPeerId()); - - // Send time of day - u16 time = m_env->getTimeOfDay(); - float time_speed = g_settings->getFloat("time_speed"); - SendTimeOfDay(pkt->getPeerId(), time, time_speed); - - ///// begin compatibility code - if (protocol_version <= 22) { - m_clients.event(pkt->getPeerId(), CSE_SetClientReady); - m_script->on_joinplayer(playersao); - } - ///// end compatibility code - - // Warnings about protocol version can be issued here - if (getClient(pkt->getPeerId())->net_proto_version < LATEST_PROTOCOL_VERSION) { - SendChatMessage(pkt->getPeerId(), L"# Server: WARNING: YOUR CLIENT'S " - L"VERSION MAY NOT BE FULLY COMPATIBLE WITH THIS SERVER!"); - } -} - -void Server::handleCommand_RequestMedia(NetworkPacket* pkt) -{ - std::vector tosend; - u16 numfiles; - - *pkt >> numfiles; - - infostream << "Sending " << numfiles << " files to " - << getPlayerName(pkt->getPeerId()) << std::endl; - verbosestream << "TOSERVER_REQUEST_MEDIA: " << std::endl; - - for (u16 i = 0; i < numfiles; i++) { - std::string name; - - *pkt >> name; - - tosend.push_back(name); - verbosestream << "TOSERVER_REQUEST_MEDIA: requested file " - << name << std::endl; - } - - sendRequestedMedia(pkt->getPeerId(), tosend); -} - -void Server::handleCommand_ReceivedMedia(NetworkPacket* pkt) -{ -} - -void Server::handleCommand_ClientReady(NetworkPacket* pkt) -{ - u16 peer_id = pkt->getPeerId(); - u16 peer_proto_ver = getClient(peer_id, CS_InitDone)->net_proto_version; - - // clients <= protocol version 22 did not send ready message, - // they're already initialized - if (peer_proto_ver <= 22) { - infostream << "Client sent message not expected by a " - << "client using protocol version <= 22," - << "disconnecing peer_id: " << peer_id << std::endl; - m_con.DisconnectPeer(peer_id); - return; - } - - PlayerSAO* playersao = StageTwoClientInit(peer_id); - - if (playersao == NULL) { - errorstream - << "TOSERVER_CLIENT_READY stage 2 client init failed for peer_id: " - << peer_id << std::endl; - m_con.DisconnectPeer(peer_id); - return; - } - - - if (pkt->getSize() < 8) { - errorstream - << "TOSERVER_CLIENT_READY client sent inconsistent data, disconnecting peer_id: " - << peer_id << std::endl; - m_con.DisconnectPeer(peer_id); - return; - } - - u8 major_ver, minor_ver, patch_ver; - *pkt >> major_ver >> minor_ver >> patch_ver; - - m_clients.setClientVersion( - peer_id, major_ver, minor_ver, patch_ver, - std::string(pkt->getString(6),(u16) pkt->getU8(4))); - - m_clients.event(peer_id, CSE_SetClientReady); - m_script->on_joinplayer(playersao); -} - -void Server::handleCommand_GotBlocks(NetworkPacket* pkt) -{ - if (pkt->getSize() < 1) - return; - - /* - [0] u16 command - [2] u8 count - [3] v3s16 pos_0 - [3+6] v3s16 pos_1 - ... - */ - - u8 count; - *pkt >> count; - - RemoteClient *client = getClient(pkt->getPeerId()); - - for (u16 i = 0; i < count; i++) { - if ((s16)pkt->getSize() < 1 + (i + 1) * 6) - throw con::InvalidIncomingDataException - ("GOTBLOCKS length is too short"); - v3s16 p; - - *pkt >> p; - - client->GotBlock(p); - } -} - -void Server::handleCommand_PlayerPos(NetworkPacket* pkt) -{ - if (pkt->getSize() < 12 + 12 + 4 + 4) - return; - - v3s32 ps, ss; - s32 f32pitch, f32yaw; - - *pkt >> ps; - *pkt >> ss; - *pkt >> f32pitch; - *pkt >> f32yaw; - - f32 pitch = (f32)f32pitch / 100.0; - f32 yaw = (f32)f32yaw / 100.0; - u32 keyPressed = 0; - - if (pkt->getSize() >= 12 + 12 + 4 + 4 + 4) - *pkt >> keyPressed; - - v3f position((f32)ps.X / 100.0, (f32)ps.Y / 100.0, (f32)ps.Z / 100.0); - v3f speed((f32)ss.X / 100.0, (f32)ss.Y / 100.0, (f32)ss.Z / 100.0); - - pitch = modulo360f(pitch); - yaw = modulo360f(yaw); - - Player *player = m_env->getPlayer(pkt->getPeerId()); - if (player == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - PlayerSAO *playersao = player->getPlayerSAO(); - if (playersao == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player object for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - player->setPosition(position); - player->setSpeed(speed); - player->setPitch(pitch); - player->setYaw(yaw); - player->keyPressed = keyPressed; - player->control.up = (keyPressed & 1); - player->control.down = (keyPressed & 2); - player->control.left = (keyPressed & 4); - player->control.right = (keyPressed & 8); - player->control.jump = (keyPressed & 16); - player->control.aux1 = (keyPressed & 32); - player->control.sneak = (keyPressed & 64); - player->control.LMB = (keyPressed & 128); - player->control.RMB = (keyPressed & 256); - - if (playersao->checkMovementCheat()) { - // Call callbacks - m_script->on_cheat(playersao, "moved_too_fast"); - SendMovePlayer(pkt->getPeerId()); - } -} - -void Server::handleCommand_DeletedBlocks(NetworkPacket* pkt) -{ - if (pkt->getSize() < 1) - return; - - /* - [0] u16 command - [2] u8 count - [3] v3s16 pos_0 - [3+6] v3s16 pos_1 - ... - */ - - u8 count; - *pkt >> count; - - RemoteClient *client = getClient(pkt->getPeerId()); - - for (u16 i = 0; i < count; i++) { - if ((s16)pkt->getSize() < 1 + (i + 1) * 6) - throw con::InvalidIncomingDataException - ("DELETEDBLOCKS length is too short"); - v3s16 p; - *pkt >> p; - - client->SetBlockNotSent(p); - } -} - -void Server::handleCommand_InventoryAction(NetworkPacket* pkt) -{ - Player *player = m_env->getPlayer(pkt->getPeerId()); - if (player == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - PlayerSAO *playersao = player->getPlayerSAO(); - if (playersao == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player object for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - // Strip command and create a stream - std::string datastring(pkt->getString(0), pkt->getSize()); - verbosestream << "TOSERVER_INVENTORY_ACTION: data=" << datastring - << std::endl; - std::istringstream is(datastring, std::ios_base::binary); - // Create an action - InventoryAction *a = InventoryAction::deSerialize(is); - if (a == NULL) { - infostream << "TOSERVER_INVENTORY_ACTION: " - << "InventoryAction::deSerialize() returned NULL" - << std::endl; - return; - } - - // If something goes wrong, this player is to blame - RollbackScopeActor rollback_scope(m_rollback, - std::string("player:")+player->getName()); - - /* - Note: Always set inventory not sent, to repair cases - where the client made a bad prediction. - */ - - /* - Handle restrictions and special cases of the move action - */ - if (a->getType() == IACTION_MOVE) { - IMoveAction *ma = (IMoveAction*)a; - - ma->from_inv.applyCurrentPlayer(player->getName()); - ma->to_inv.applyCurrentPlayer(player->getName()); - - setInventoryModified(ma->from_inv); - setInventoryModified(ma->to_inv); - - bool from_inv_is_current_player = - (ma->from_inv.type == InventoryLocation::PLAYER) && - (ma->from_inv.name == player->getName()); - - bool to_inv_is_current_player = - (ma->to_inv.type == InventoryLocation::PLAYER) && - (ma->to_inv.name == player->getName()); - - /* - Disable moving items out of craftpreview - */ - if (ma->from_list == "craftpreview") { - infostream << "Ignoring IMoveAction from " - << (ma->from_inv.dump()) << ":" << ma->from_list - << " to " << (ma->to_inv.dump()) << ":" << ma->to_list - << " because src is " << ma->from_list << std::endl; - delete a; - return; - } - - /* - Disable moving items into craftresult and craftpreview - */ - if (ma->to_list == "craftpreview" || ma->to_list == "craftresult") { - infostream << "Ignoring IMoveAction from " - << (ma->from_inv.dump()) << ":" << ma->from_list - << " to " << (ma->to_inv.dump()) << ":" << ma->to_list - << " because dst is " << ma->to_list << std::endl; - delete a; - return; - } - - // Disallow moving items in elsewhere than player's inventory - // if not allowed to interact - if (!checkPriv(player->getName(), "interact") && - (!from_inv_is_current_player || - !to_inv_is_current_player)) { - infostream << "Cannot move outside of player's inventory: " - << "No interact privilege" << std::endl; - delete a; - return; - } - } - /* - Handle restrictions and special cases of the drop action - */ - else if (a->getType() == IACTION_DROP) { - IDropAction *da = (IDropAction*)a; - - da->from_inv.applyCurrentPlayer(player->getName()); - - setInventoryModified(da->from_inv); - - /* - Disable dropping items out of craftpreview - */ - if (da->from_list == "craftpreview") { - infostream << "Ignoring IDropAction from " - << (da->from_inv.dump()) << ":" << da->from_list - << " because src is " << da->from_list << std::endl; - delete a; - return; - } - - // Disallow dropping items if not allowed to interact - if (!checkPriv(player->getName(), "interact")) { - delete a; - return; - } - } - /* - Handle restrictions and special cases of the craft action - */ - else if (a->getType() == IACTION_CRAFT) { - ICraftAction *ca = (ICraftAction*)a; - - ca->craft_inv.applyCurrentPlayer(player->getName()); - - setInventoryModified(ca->craft_inv); - - //bool craft_inv_is_current_player = - // (ca->craft_inv.type == InventoryLocation::PLAYER) && - // (ca->craft_inv.name == player->getName()); - - // Disallow crafting if not allowed to interact - if (!checkPriv(player->getName(), "interact")) { - infostream << "Cannot craft: " - << "No interact privilege" << std::endl; - delete a; - return; - } - } - - // Do the action - a->apply(this, playersao, this); - // Eat the action - delete a; -} - -void Server::handleCommand_ChatMessage(NetworkPacket* pkt) -{ - /* - u16 command - u16 length - wstring message - */ - u16 len; - *pkt >> len; - - std::wstring message; - for (u16 i = 0; i < len; i++) { - u16 tmp_wchar; - *pkt >> tmp_wchar; - - message += (wchar_t)tmp_wchar; - } - - Player *player = m_env->getPlayer(pkt->getPeerId()); - if (player == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - // If something goes wrong, this player is to blame - RollbackScopeActor rollback_scope(m_rollback, - std::string("player:")+player->getName()); - - // Get player name of this client - std::wstring name = narrow_to_wide(player->getName()); - - // Run script hook - bool ate = m_script->on_chat_message(player->getName(), - wide_to_narrow(message)); - // If script ate the message, don't proceed - if (ate) - return; - - // Line to send to players - std::wstring line; - // Whether to send to the player that sent the line - bool send_to_sender_only = false; - - // Commands are implemented in Lua, so only catch invalid - // commands that were not "eaten" and send an error back - if (message[0] == L'/') { - message = message.substr(1); - send_to_sender_only = true; - if (message.length() == 0) - line += L"-!- Empty command"; - else - line += L"-!- Invalid command: " + str_split(message, L' ')[0]; - } - else { - if (checkPriv(player->getName(), "shout")) { - line += L"<"; - line += name; - line += L"> "; - line += message; - } else { - line += L"-!- You don't have permission to shout."; - send_to_sender_only = true; - } - } - - if (line != L"") - { - /* - Send the message to sender - */ - if (send_to_sender_only) { - SendChatMessage(pkt->getPeerId(), line); - } - /* - Send the message to others - */ - else { - actionstream << "CHAT: " << wide_to_narrow(line)< clients = m_clients.getClientIDs(); - - for (std::vector::iterator i = clients.begin(); - i != clients.end(); ++i) { - if (*i != pkt->getPeerId()) - SendChatMessage(*i, line); - } - } - } -} - -void Server::handleCommand_Damage(NetworkPacket* pkt) -{ - u8 damage; - - *pkt >> damage; - - Player *player = m_env->getPlayer(pkt->getPeerId()); - if (player == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - PlayerSAO *playersao = player->getPlayerSAO(); - if (playersao == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player object for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - if (g_settings->getBool("enable_damage")) { - actionstream << player->getName() << " damaged by " - << (int)damage << " hp at " << PP(player->getPosition() / BS) - << std::endl; - - playersao->setHP(playersao->getHP() - damage); - SendPlayerHPOrDie(playersao->getPeerID(), playersao->getHP() == 0); - } -} - -void Server::handleCommand_Breath(NetworkPacket* pkt) -{ - u16 breath; - - *pkt >> breath; - - Player *player = m_env->getPlayer(pkt->getPeerId()); - if (player == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - PlayerSAO *playersao = player->getPlayerSAO(); - if (playersao == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player object for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - playersao->setBreath(breath); - SendPlayerBreath(pkt->getPeerId()); -} - -void Server::handleCommand_Password(NetworkPacket* pkt) -{ - /* - [0] u16 TOSERVER_PASSWORD - [2] u8[28] old password - [30] u8[28] new password - */ - - errorstream << "PAssword packet size: " << pkt->getSize() << " size required: " << PASSWORD_SIZE * 2 << std::endl; - if (pkt->getSize() != PASSWORD_SIZE * 2) - return; - - std::string oldpwd; - std::string newpwd; - - for (u16 i = 0; i < PASSWORD_SIZE - 1; i++) { - char c = pkt->getChar(i); - if (c == 0) - break; - oldpwd += c; - } - - for (u16 i = 0; i < PASSWORD_SIZE - 1; i++) { - char c = pkt->getChar(PASSWORD_SIZE + i); - if (c == 0) - break; - newpwd += c; - } - - Player *player = m_env->getPlayer(pkt->getPeerId()); - if (player == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - if (!base64_is_valid(newpwd)) { - infostream<<"Server: " << player->getName() << - " supplied invalid password hash" << std::endl; - // Wrong old password supplied!! - SendChatMessage(pkt->getPeerId(), L"Invalid new password hash supplied. Password NOT changed."); - return; - } - - infostream << "Server: Client requests a password change from " - << "'" << oldpwd << "' to '" << newpwd << "'" << std::endl; - - std::string playername = player->getName(); - - std::string checkpwd; - m_script->getAuth(playername, &checkpwd, NULL); - - if (oldpwd != checkpwd) { - infostream << "Server: invalid old password" << std::endl; - // Wrong old password supplied!! - SendChatMessage(pkt->getPeerId(), L"Invalid old password supplied. Password NOT changed."); - return; - } - - bool success = m_script->setPassword(playername, newpwd); - if (success) { - actionstream << player->getName() << " changes password" << std::endl; - SendChatMessage(pkt->getPeerId(), L"Password change successful."); - } else { - actionstream << player->getName() << " tries to change password but " - << "it fails" << std::endl; - SendChatMessage(pkt->getPeerId(), L"Password change failed or inavailable."); - } -} - -void Server::handleCommand_PlayerItem(NetworkPacket* pkt) -{ - if (pkt->getSize() < 2) - return; - - Player *player = m_env->getPlayer(pkt->getPeerId()); - if (player == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - PlayerSAO *playersao = player->getPlayerSAO(); - if (playersao == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player object for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - u16 item; - - *pkt >> item; - - playersao->setWieldIndex(item); -} - -void Server::handleCommand_Respawn(NetworkPacket* pkt) -{ - Player *player = m_env->getPlayer(pkt->getPeerId()); - if (player == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - if (player->hp != 0 || !g_settings->getBool("enable_damage")) - return; - - RespawnPlayer(pkt->getPeerId()); - - actionstream << player->getName() << " respawns at " - << PP(player->getPosition()/BS) << std::endl; - - // ActiveObject is added to environment in AsyncRunStep after - // the previous addition has been succesfully removed -} - -void Server::handleCommand_Interact(NetworkPacket* pkt) -{ - std::string datastring(pkt->getString(0), pkt->getSize()); - std::istringstream is(datastring, std::ios_base::binary); - - /* - [0] u16 command - [2] u8 action - [3] u16 item - [5] u32 length of the next item - [9] serialized PointedThing - actions: - 0: start digging (from undersurface) or use - 1: stop digging (all parameters ignored) - 2: digging completed - 3: place block or item (to abovesurface) - 4: use item - */ - u8 action = readU8(is); - u16 item_i = readU16(is); - std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary); - PointedThing pointed; - pointed.deSerialize(tmp_is); - - verbosestream << "TOSERVER_INTERACT: action=" << (int)action << ", item=" - << item_i << ", pointed=" << pointed.dump() << std::endl; - - Player *player = m_env->getPlayer(pkt->getPeerId()); - if (player == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - PlayerSAO *playersao = player->getPlayerSAO(); - if (playersao == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player object for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - if (player->hp == 0) { - verbosestream << "TOSERVER_INTERACT: " << player->getName() - << " tried to interact, but is dead!" << std::endl; - return; - } - - v3f player_pos = playersao->getLastGoodPosition(); - - // Update wielded item - playersao->setWieldIndex(item_i); - - // Get pointed to node (undefined if not POINTEDTYPE_NODE) - v3s16 p_under = pointed.node_undersurface; - v3s16 p_above = pointed.node_abovesurface; - - // Get pointed to object (NULL if not POINTEDTYPE_OBJECT) - ServerActiveObject *pointed_object = NULL; - if (pointed.type == POINTEDTHING_OBJECT) { - pointed_object = m_env->getActiveObject(pointed.object_id); - if (pointed_object == NULL) { - verbosestream << "TOSERVER_INTERACT: " - "pointed object is NULL" << std::endl; - return; - } - - } - - v3f pointed_pos_under = player_pos; - v3f pointed_pos_above = player_pos; - if (pointed.type == POINTEDTHING_NODE) { - pointed_pos_under = intToFloat(p_under, BS); - pointed_pos_above = intToFloat(p_above, BS); - } - else if (pointed.type == POINTEDTHING_OBJECT) { - pointed_pos_under = pointed_object->getBasePosition(); - pointed_pos_above = pointed_pos_under; - } - - /* - Check that target is reasonably close - (only when digging or placing things) - */ - if (action == 0 || action == 2 || action == 3) { - float d = player_pos.getDistanceFrom(pointed_pos_under); - float max_d = BS * 14; // Just some large enough value - if (d > max_d) { - actionstream << "Player " << player->getName() - << " tried to access " << pointed.dump() - << " from too far: " - << "d=" << d <<", max_d=" << max_d - << ". ignoring." << std::endl; - // Re-send block to revert change on client-side - RemoteClient *client = getClient(pkt->getPeerId()); - v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS)); - client->SetBlockNotSent(blockpos); - // Call callbacks - m_script->on_cheat(playersao, "interacted_too_far"); - // Do nothing else - return; - } - } - - /* - Make sure the player is allowed to do it - */ - if (!checkPriv(player->getName(), "interact")) { - actionstream<getName()<<" attempted to interact with " - <getPeerId()); - // Digging completed -> under - if (action == 2) { - v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS)); - client->SetBlockNotSent(blockpos); - } - // Placement -> above - if (action == 3) { - v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS)); - client->SetBlockNotSent(blockpos); - } - return; - } - - /* - If something goes wrong, this player is to blame - */ - RollbackScopeActor rollback_scope(m_rollback, - std::string("player:")+player->getName()); - - /* - 0: start digging or punch object - */ - if (action == 0) { - if (pointed.type == POINTEDTHING_NODE) { - /* - NOTE: This can be used in the future to check if - somebody is cheating, by checking the timing. - */ - MapNode n(CONTENT_IGNORE); - bool pos_ok; - n = m_env->getMap().getNodeNoEx(p_under, &pos_ok); - if (pos_ok) - n = m_env->getMap().getNodeNoEx(p_under, &pos_ok); - - if (!pos_ok) { - infostream << "Server: Not punching: Node not found." - << " Adding block to emerge queue." - << std::endl; - m_emerge->enqueueBlockEmerge(pkt->getPeerId(), getNodeBlockPos(p_above), false); - } - - if (n.getContent() != CONTENT_IGNORE) - m_script->node_on_punch(p_under, n, playersao, pointed); - // Cheat prevention - playersao->noCheatDigStart(p_under); - } - else if (pointed.type == POINTEDTHING_OBJECT) { - // Skip if object has been removed - if (pointed_object->m_removed) - return; - - actionstream<getName()<<" punches object " - <getDescription()<getWieldedItem(); - ToolCapabilities toolcap = - punchitem.getToolCapabilities(m_itemdef); - v3f dir = (pointed_object->getBasePosition() - - (player->getPosition() + player->getEyeOffset()) - ).normalize(); - float time_from_last_punch = - playersao->resetTimeFromLastPunch(); - - s16 src_original_hp = pointed_object->getHP(); - s16 dst_origin_hp = playersao->getHP(); - - pointed_object->punch(dir, &toolcap, playersao, - time_from_last_punch); - - // If the object is a player and its HP changed - if (src_original_hp != pointed_object->getHP() && - pointed_object->getType() == ACTIVEOBJECT_TYPE_PLAYER) { - SendPlayerHPOrDie(((PlayerSAO*)pointed_object)->getPeerID(), - pointed_object->getHP() == 0); - } - - // If the puncher is a player and its HP changed - if (dst_origin_hp != playersao->getHP()) { - SendPlayerHPOrDie(playersao->getPeerID(), playersao->getHP() == 0); - } - } - - } // action == 0 - - /* - 1: stop digging - */ - else if (action == 1) { - } // action == 1 - - /* - 2: Digging completed - */ - else if (action == 2) { - // Only digging of nodes - if (pointed.type == POINTEDTHING_NODE) { - bool pos_ok; - MapNode n = m_env->getMap().getNodeNoEx(p_under, &pos_ok); - if (!pos_ok) { - infostream << "Server: Not finishing digging: Node not found." - << " Adding block to emerge queue." - << std::endl; - m_emerge->enqueueBlockEmerge(pkt->getPeerId(), getNodeBlockPos(p_above), false); - } - - /* Cheat prevention */ - bool is_valid_dig = true; - if (!isSingleplayer() && !g_settings->getBool("disable_anticheat")) { - v3s16 nocheat_p = playersao->getNoCheatDigPos(); - float nocheat_t = playersao->getNoCheatDigTime(); - playersao->noCheatDigEnd(); - // If player didn't start digging this, ignore dig - if (nocheat_p != p_under) { - infostream << "Server: NoCheat: " << player->getName() - << " started digging " - << PP(nocheat_p) << " and completed digging " - << PP(p_under) << "; not digging." << std::endl; - is_valid_dig = false; - // Call callbacks - m_script->on_cheat(playersao, "finished_unknown_dig"); - } - // Get player's wielded item - ItemStack playeritem; - InventoryList *mlist = playersao->getInventory()->getList("main"); - if (mlist != NULL) - playeritem = mlist->getItem(playersao->getWieldIndex()); - ToolCapabilities playeritem_toolcap = - playeritem.getToolCapabilities(m_itemdef); - // Get diggability and expected digging time - DigParams params = getDigParams(m_nodedef->get(n).groups, - &playeritem_toolcap); - // If can't dig, try hand - if (!params.diggable) { - const ItemDefinition &hand = m_itemdef->get(""); - const ToolCapabilities *tp = hand.tool_capabilities; - if (tp) - params = getDigParams(m_nodedef->get(n).groups, tp); - } - // If can't dig, ignore dig - if (!params.diggable) { - infostream << "Server: NoCheat: " << player->getName() - << " completed digging " << PP(p_under) - << ", which is not diggable with tool. not digging." - << std::endl; - is_valid_dig = false; - // Call callbacks - m_script->on_cheat(playersao, "dug_unbreakable"); - } - // Check digging time - // If already invalidated, we don't have to - if (!is_valid_dig) { - // Well not our problem then - } - // Clean and long dig - else if (params.time > 2.0 && nocheat_t * 1.2 > params.time) { - // All is good, but grab time from pool; don't care if - // it's actually available - playersao->getDigPool().grab(params.time); - } - // Short or laggy dig - // Try getting the time from pool - else if (playersao->getDigPool().grab(params.time)) { - // All is good - } - // Dig not possible - else { - infostream << "Server: NoCheat: " << player->getName() - << " completed digging " << PP(p_under) - << "too fast; not digging." << std::endl; - is_valid_dig = false; - // Call callbacks - m_script->on_cheat(playersao, "dug_too_fast"); - } - } - - /* Actually dig node */ - - if (is_valid_dig && n.getContent() != CONTENT_IGNORE) - m_script->node_on_dig(p_under, n, playersao); - - v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS)); - RemoteClient *client = getClient(pkt->getPeerId()); - // Send unusual result (that is, node not being removed) - if (m_env->getMap().getNodeNoEx(p_under).getContent() != CONTENT_AIR) { - // Re-send block to revert change on client-side - client->SetBlockNotSent(blockpos); - } - else { - client->ResendBlockIfOnWire(blockpos); - } - } - } // action == 2 - - /* - 3: place block or right-click object - */ - else if (action == 3) { - ItemStack item = playersao->getWieldedItem(); - - // Reset build time counter - if (pointed.type == POINTEDTHING_NODE && - item.getDefinition(m_itemdef).type == ITEM_NODE) - getClient(pkt->getPeerId())->m_time_from_building = 0.0; - - if (pointed.type == POINTEDTHING_OBJECT) { - // Right click object - - // Skip if object has been removed - if (pointed_object->m_removed) - return; - - actionstream << player->getName() << " right-clicks object " - << pointed.object_id << ": " - << pointed_object->getDescription() << std::endl; - - // Do stuff - pointed_object->rightClick(playersao); - } - else if (m_script->item_OnPlace( - item, playersao, pointed)) { - // Placement was handled in lua - - // Apply returned ItemStack - if (playersao->setWieldedItem(item)) { - SendInventory(playersao); - } - } - - // If item has node placement prediction, always send the - // blocks to make sure the client knows what exactly happened - RemoteClient *client = getClient(pkt->getPeerId()); - v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS)); - v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS)); - if (item.getDefinition(m_itemdef).node_placement_prediction != "") { - client->SetBlockNotSent(blockpos); - if (blockpos2 != blockpos) { - client->SetBlockNotSent(blockpos2); - } - } - else { - client->ResendBlockIfOnWire(blockpos); - if (blockpos2 != blockpos) { - client->ResendBlockIfOnWire(blockpos2); - } - } - } // action == 3 - - /* - 4: use - */ - else if (action == 4) { - ItemStack item = playersao->getWieldedItem(); - - actionstream << player->getName() << " uses " << item.name - << ", pointing at " << pointed.dump() << std::endl; - - if (m_script->item_OnUse( - item, playersao, pointed)) { - // Apply returned ItemStack - playersao->setWieldedItem(item); - } - - } // action == 4 - - - /* - Catch invalid actions - */ - else { - infostream << "WARNING: Server: Invalid action " - << action << std::endl; - } -} - -void Server::handleCommand_RemovedSounds(NetworkPacket* pkt) -{ - u16 num; - *pkt >> num; - for (u16 k = 0; k < num; k++) { - s32 id; - - *pkt >> id; - - std::map::iterator i = - m_playing_sounds.find(id); - - if (i == m_playing_sounds.end()) - continue; - - ServerPlayingSound &psound = i->second; - psound.clients.erase(pkt->getPeerId()); - if (psound.clients.empty()) - m_playing_sounds.erase(i++); - } -} - -void Server::handleCommand_NodeMetaFields(NetworkPacket* pkt) -{ - v3s16 p; - std::string formname; - u16 num; - - *pkt >> p >> formname >> num; - - std::map fields; - for (u16 k = 0; k < num; k++) { - std::string fieldname; - *pkt >> fieldname; - fields[fieldname] = pkt->readLongString(); - } - - Player *player = m_env->getPlayer(pkt->getPeerId()); - if (player == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - PlayerSAO *playersao = player->getPlayerSAO(); - if (playersao == NULL) { - errorstream << "Server::ProcessData(): Cancelling: " - "No player object for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - // If something goes wrong, this player is to blame - RollbackScopeActor rollback_scope(m_rollback, - std::string("player:")+player->getName()); - - // Check the target node for rollback data; leave others unnoticed - RollbackNode rn_old(&m_env->getMap(), p, this); - - m_script->node_on_receive_fields(p, formname, fields, playersao); - - // Report rollback data - RollbackNode rn_new(&m_env->getMap(), p, this); - if (rollback() && rn_new != rn_old) { - RollbackAction action; - action.setSetNode(p, rn_old, rn_new); - rollback()->reportAction(action); - } -} - -void Server::handleCommand_InventoryFields(NetworkPacket* pkt) -{ - std::string formname; - u16 num; - - *pkt >> formname >> num; - - std::map fields; - for (u16 k = 0; k < num; k++) { - std::string fieldname; - *pkt >> fieldname; - fields[fieldname] = pkt->readLongString(); - } - - Player *player = m_env->getPlayer(pkt->getPeerId()); - if (player == NULL) { - errorstream << "Server::ProcessData(): Canceling: " - "No player for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - PlayerSAO *playersao = player->getPlayerSAO(); - if (playersao == NULL) { - errorstream << "Server::ProcessData(): Canceling: " - "No player object for peer_id=" << pkt->getPeerId() - << " disconnecting peer!" << std::endl; - m_con.DisconnectPeer(pkt->getPeerId()); - return; - } - - m_script->on_playerReceiveFields(playersao, formname, fields); -} diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp deleted file mode 100644 index bd36b427f..000000000 --- a/src/network/serveropcodes.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* -Minetest -Copyright (C) 2013 celeron55, Perttu Ahola -Copyright (C) 2015 nerzhul, Loic Blot - -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 "serveropcodes.h" - -const static ToServerCommandHandler null_command_handler = { "TOSERVER_NULL", TOSERVER_STATE_ALL, &Server::handleCommand_Null }; - -const ToServerCommandHandler toServerCommandTable[TOSERVER_NUM_MSG_TYPES] = -{ - null_command_handler, // 0x00 - null_command_handler, // 0x01 - null_command_handler, // 0x02 - null_command_handler, // 0x03 - null_command_handler, // 0x04 - null_command_handler, // 0x05 - null_command_handler, // 0x06 - null_command_handler, // 0x07 - null_command_handler, // 0x08 - null_command_handler, // 0x09 - null_command_handler, // 0x0a - null_command_handler, // 0x0b - null_command_handler, // 0x0c - null_command_handler, // 0x0d - null_command_handler, // 0x0e - null_command_handler, // 0x0f - { "TOSERVER_INIT", TOSERVER_STATE_NOT_CONNECTED, &Server::handleCommand_Init }, // 0x10 - { "TOSERVER_INIT2", TOSERVER_STATE_NOT_CONNECTED, &Server::handleCommand_Init2 }, // 0x11 - null_command_handler, // 0x12 - null_command_handler, // 0x13 - null_command_handler, // 0x14 - null_command_handler, // 0x15 - null_command_handler, // 0x16 - null_command_handler, // 0x17 - null_command_handler, // 0x18 - null_command_handler, // 0x19 - null_command_handler, // 0x1a - null_command_handler, // 0x1b - null_command_handler, // 0x1c - null_command_handler, // 0x1d - null_command_handler, // 0x1e - null_command_handler, // 0x1f - null_command_handler, // 0x20 - null_command_handler, // 0x21 - null_command_handler, // 0x22 - { "TOSERVER_PLAYERPOS", TOSERVER_STATE_INGAME, &Server::handleCommand_PlayerPos }, // 0x23 - { "TOSERVER_GOTBLOCKS", TOSERVER_STATE_STARTUP, &Server::handleCommand_GotBlocks }, // 0x24 - { "TOSERVER_DELETEDBLOCKS", TOSERVER_STATE_INGAME, &Server::handleCommand_DeletedBlocks }, // 0x25 - null_command_handler, // 0x26 - { "TOSERVER_CLICK_OBJECT", TOSERVER_STATE_INGAME, &Server::handleCommand_Deprecated }, // 0x27 - { "TOSERVER_GROUND_ACTION", TOSERVER_STATE_INGAME, &Server::handleCommand_Deprecated }, // 0x28 - { "TOSERVER_RELEASE", TOSERVER_STATE_INGAME, &Server::handleCommand_Deprecated }, // 0x29 - null_command_handler, // 0x2a - null_command_handler, // 0x2b - null_command_handler, // 0x2c - null_command_handler, // 0x2d - null_command_handler, // 0x2e - null_command_handler, // 0x2f - { "TOSERVER_SIGNTEXT", TOSERVER_STATE_INGAME, &Server::handleCommand_Deprecated }, // 0x30 - { "TOSERVER_INVENTORY_ACTION", TOSERVER_STATE_INGAME, &Server::handleCommand_InventoryAction }, // 0x31 - { "TOSERVER_CHAT_MESSAGE", TOSERVER_STATE_INGAME, &Server::handleCommand_ChatMessage }, // 0x32 - { "TOSERVER_SIGNNODETEXT", TOSERVER_STATE_INGAME, &Server::handleCommand_Deprecated }, // 0x33 - { "TOSERVER_CLICK_ACTIVEOBJECT", TOSERVER_STATE_INGAME, &Server::handleCommand_Deprecated }, // 0x34 - { "TOSERVER_DAMAGE", TOSERVER_STATE_INGAME, &Server::handleCommand_Damage }, // 0x35 - { "TOSERVER_PASSWORD", TOSERVER_STATE_INGAME, &Server::handleCommand_Password }, // 0x36 - { "TOSERVER_PLAYERITEM", TOSERVER_STATE_INGAME, &Server::handleCommand_PlayerItem }, // 0x37 - { "TOSERVER_RESPAWN", TOSERVER_STATE_INGAME, &Server::handleCommand_Respawn }, // 0x38 - { "TOSERVER_INTERACT", TOSERVER_STATE_INGAME, &Server::handleCommand_Interact }, // 0x39 - { "TOSERVER_REMOVED_SOUNDS", TOSERVER_STATE_INGAME, &Server::handleCommand_RemovedSounds }, // 0x3a - { "TOSERVER_NODEMETA_FIELDS", TOSERVER_STATE_INGAME, &Server::handleCommand_NodeMetaFields }, // 0x3b - { "TOSERVER_INVENTORY_FIELDS", TOSERVER_STATE_INGAME, &Server::handleCommand_InventoryFields }, // 0x3c - null_command_handler, // 0x3d - null_command_handler, // 0x3e - null_command_handler, // 0x3f - { "TOSERVER_REQUEST_MEDIA", TOSERVER_STATE_STARTUP, &Server::handleCommand_RequestMedia }, // 0x40 - { "TOSERVER_RECEIVED_MEDIA", TOSERVER_STATE_STARTUP, &Server::handleCommand_ReceivedMedia }, // 0x41 - { "TOSERVER_BREATH", TOSERVER_STATE_INGAME, &Server::handleCommand_Breath }, // 0x42 - { "TOSERVER_CLIENT_READY", TOSERVER_STATE_STARTUP, &Server::handleCommand_ClientReady }, // 0x43 -}; - -const static ClientCommandFactory null_command_factory = { "TOCLIENT_NULL", 0, false }; - -const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] = -{ - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - { "TOCLIENT_INIT", 0, true }, // 0x10 - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - { "TOCLIENT_BLOCKDATA", 2, true }, // 0x20 - { "TOCLIENT_ADDNODE", 0, true }, // 0x21 - { "TOCLIENT_REMOVENODE", 0, true }, // 0x22 - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - { "TOCLIENT_INVENTORY", 0, true }, // 0x27 - null_command_factory, - { "TOCLIENT_TIME_OF_DAY", 0, true }, // 0x29 - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - null_command_factory, - { "TOCLIENT_CHAT_MESSAGE", 0, true }, // 0x30 - { "TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD", 0, true }, // 0x31 - { "TOCLIENT_ACTIVE_OBJECT_MESSAGES", 0, true }, // 0x32 Special packet, sent by 0 (rel) and 1 (unrel) channel - { "TOCLIENT_HP", 0, true }, // 0x33 - { "TOCLIENT_MOVE_PLAYER", 0, true }, // 0x34 - { "TOCLIENT_ACCESS_DENIED", 0, true }, // 0x35 - { "TOCLIENT_PLAYERITEM", 0, false }, // 0x36 obsolete - { "TOCLIENT_DEATHSCREEN", 0, true }, // 0x37 - { "TOCLIENT_MEDIA", 2, true }, // 0x38 - { "TOCLIENT_TOOLDEF", 0, false }, // 0x39 obsolete - { "TOCLIENT_NODEDEF", 0, true }, // 0x3a - { "TOCLIENT_CRAFTITEMDEF", 0, false }, // 0x3b obsolete - { "TOCLIENT_ANNOUNCE_MEDIA", 0, true }, // 0x3c - { "TOCLIENT_ITEMDEF", 0, true }, // 0x3d - null_command_factory, - { "TOCLIENT_PLAY_SOUND", 0, true }, // 0x3f - { "TOCLIENT_STOP_SOUND", 0, true }, // 0x40 - { "TOCLIENT_PRIVILEGES", 0, true }, // 0x41 - { "TOCLIENT_INVENTORY_FORMSPEC", 0, true }, // 0x42 - { "TOCLIENT_DETACHED_INVENTORY", 0, true }, // 0x43 - { "TOCLIENT_SHOW_FORMSPEC", 0, true }, // 0x44 - { "TOCLIENT_MOVEMENT", 0, true }, // 0x45 - { "TOCLIENT_SPAWN_PARTICLE", 0, true }, // 0x46 - { "TOCLIENT_ADD_PARTICLESPAWNER", 0, true }, // 0x47 - { "TOCLIENT_DELETE_PARTICLESPAWNER", 0, true }, // 0x48 - { "TOCLIENT_HUDADD", 1, true }, // 0x49 - { "TOCLIENT_HUDRM", 1, true }, // 0x4a - { "TOCLIENT_HUDCHANGE", 0, true }, // 0x4b - { "TOCLIENT_HUD_SET_FLAGS", 0, true }, // 0x4c - { "TOCLIENT_HUD_SET_PARAM", 0, true }, // 0x4d - { "TOCLIENT_BREATH", 0, true }, // 0x4e - { "TOCLIENT_SET_SKY", 0, true }, // 0x4f - { "TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO", 0, true }, // 0x50 - { "TOCLIENT_LOCAL_PLAYER_ANIMATIONS", 0, true }, // 0x51 - { "TOCLIENT_EYE_OFFSET", 0, true }, // 0x52 -}; diff --git a/src/network/serveropcodes.h b/src/network/serveropcodes.h deleted file mode 100644 index aa3301069..000000000 --- a/src/network/serveropcodes.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -Minetest -Copyright (C) 2013 celeron55, Perttu Ahola -Copyright (C) 2015 nerzhul, Loic Blot - -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. -*/ - -#ifndef SERVEROPCODES_HEADER -#define SERVEROPCODES_HEADER - -#include "server.h" -#include "networkprotocol.h" -#include "networkpacket.h" - -enum ToServerConnectionState { - TOSERVER_STATE_NOT_CONNECTED, - TOSERVER_STATE_STARTUP, - TOSERVER_STATE_INGAME, - TOSERVER_STATE_ALL, -}; -struct ToServerCommandHandler -{ - const std::string name; - ToServerConnectionState state; - void (Server::*handler)(NetworkPacket* pkt); -}; - -struct ClientCommandFactory -{ - const char* name; - u16 channel; - bool reliable; -}; - -extern const ToServerCommandHandler toServerCommandTable[TOSERVER_NUM_MSG_TYPES]; - -extern const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES]; - -#endif diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 6cf456e4d..bcf51a072 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "main.h" // For g_settings #include "itemdef.h" #ifndef SERVER -#include "client/tile.h" +#include "tile.h" #include "mesh.h" #include #endif @@ -443,7 +443,7 @@ private: content_t m_next_id; // List of node strings and node resolver callbacks to perform - std::vector m_pending_node_lookups; + std::list m_pending_node_lookups; // True when all nodes have been registered bool m_node_registration_complete; @@ -479,7 +479,7 @@ void CNodeDefManager::clear() m_next_id = 0; m_node_registration_complete = false; - for (std::vector::iterator + for (std::list::iterator it = m_pending_node_lookups.begin(); it != m_pending_node_lookups.end(); ++it) @@ -1309,7 +1309,7 @@ void CNodeDefManager::pendNodeResolve(NodeResolveInfo *nri) void CNodeDefManager::cancelNodeResolve(NodeResolver *resolver) { - for (std::vector::iterator + for (std::list::iterator it = m_pending_node_lookups.begin(); it != m_pending_node_lookups.end(); ++it) { @@ -1326,7 +1326,7 @@ void CNodeDefManager::runNodeResolverCallbacks() { while (!m_pending_node_lookups.empty()) { NodeResolveInfo *nri = m_pending_node_lookups.front(); - m_pending_node_lookups.erase(m_pending_node_lookups.begin()); + m_pending_node_lookups.pop_front(); nri->resolver->resolveNodeNames(nri); nri->resolver->m_lookup_done = true; delete nri; @@ -1345,7 +1345,7 @@ bool CNodeDefManager::getIdFromResolveInfo(NodeResolveInfo *nri, content_t c; std::string name = nri->nodenames.front(); - nri->nodenames.erase(nri->nodenames.begin()); + nri->nodenames.pop_front(); bool success = getId(name, c); if (!success && node_alt != "") { @@ -1385,7 +1385,7 @@ bool CNodeDefManager::getIdsFromResolveInfo(NodeResolveInfo *nri, content_t c; std::string name = nri->nodenames.front(); - nri->nodenames.erase(nri->nodenames.begin()); + nri->nodenames.pop_front(); if (name.substr(0,6) != "group:") { if (getId(name, c)) { diff --git a/src/nodedef.h b/src/nodedef.h index a1c2e1b53..7280bb8ea 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "mapnode.h" #ifndef SERVER -#include "client/tile.h" +#include "tile.h" #include "shader.h" #endif #include "itemgroup.h" @@ -309,7 +309,7 @@ struct NodeResolveInfo { resolver = nr; } - std::vector nodenames; + std::list nodenames; std::list nodelistinfo; NodeResolver *resolver; }; diff --git a/src/particles.cpp b/src/particles.cpp index a137aaaba..603e38cdd 100644 --- a/src/particles.cpp +++ b/src/particles.cpp @@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "debug.h" #include "main.h" // For g_profiler and g_settings #include "settings.h" -#include "client/tile.h" +#include "tile.h" #include "gamedef.h" #include "collision.h" #include @@ -107,13 +107,20 @@ Particle::~Particle() void Particle::OnRegisterSceneNode() { if (IsVisible) - SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT_EFFECT); + { + SceneManager->registerNodeForRendering + (this, scene::ESNRP_TRANSPARENT); + SceneManager->registerNodeForRendering + (this, scene::ESNRP_SOLID); + } ISceneNode::OnRegisterSceneNode(); } void Particle::render() { + // TODO: Render particles in front of water and the selectionbox + video::IVideoDriver* driver = SceneManager->getVideoDriver(); driver->setMaterial(m_material); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); diff --git a/src/particles.h b/src/particles.h index 2bc2e7bfa..d7f1147f1 100644 --- a/src/particles.h +++ b/src/particles.h @@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "irrlichttypes_extrabloated.h" -#include "client/tile.h" +#include "tile.h" #include "localplayer.h" #include "environment.h" diff --git a/src/porting.h b/src/porting.h index 3d2677564..8387453e8 100644 --- a/src/porting.h +++ b/src/porting.h @@ -60,7 +60,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include //for uintptr_t -#if (defined(linux) || defined(__linux) || defined(__GNU__)) && !defined(_GNU_SOURCE) + #if (defined(linux) || defined(__linux)) && !defined(_GNU_SOURCE) #define _GNU_SOURCE #endif @@ -228,7 +228,7 @@ void initIrrlicht(irr::IrrlichtDevice * ); #else // Posix #include #include -#if defined(__MACH__) && defined(__APPLE__) +#ifdef __MACH__ #include #include #endif @@ -258,7 +258,7 @@ void initIrrlicht(irr::IrrlichtDevice * ); { struct timespec ts; // from http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x -#if defined(__MACH__) && defined(__APPLE__) // OS X does not have clock_gettime, use clock_get_time +#ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time clock_serv_t cclock; mach_timespec_t mts; host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); @@ -358,7 +358,7 @@ inline u32 getDeltaMs(u32 old_time_ms, u32 new_time_ms) inline void setThreadName(const char *name) { pthread_setname_np(name); } -#elif defined(_WIN32) || defined(__GNU__) +#elif defined(_WIN32) inline void setThreadName(const char* name) {} #else #warning "Unrecognized platform, thread names will not be available." diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 1f1d8bffa..cd5d253ac 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -406,6 +406,19 @@ int ModApiEnvMod::l_add_item(lua_State *L) script_error(L); lua_remove(L, errorhandler); // Remove error handler return 1; + /*lua_pushvalue(L, 1); + lua_pushstring(L, "__builtin:item"); + lua_pushstring(L, item.getItemString().c_str()); + return l_add_entity(L);*/ + /*// Do it + ServerActiveObject *obj = createItemSAO(env, pos, item.getItemString()); + int objectid = env->addActiveObject(obj); + // If failed to add, return nothing (reads as nil) + if(objectid == 0) + return 0; + // Return ObjectRef + objectrefGetOrCreate(L, obj); + return 1;*/ } // get_player_by_name(name) @@ -517,8 +530,9 @@ int ModApiEnvMod::l_find_node_near(lua_State *L) } for(int d=1; d<=radius; d++){ - std::vector list = FacePositionCache::getFacePositions(d); - for(std::vector::iterator i = list.begin(); + std::list list; + getFacePositions(list, d); + for(std::list::iterator i = list.begin(); i != list.end(); ++i){ v3s16 p = pos + (*i); content_t c = env->getMap().getNodeNoEx(p).getContent(); @@ -541,17 +555,17 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) v3s16 minp = read_v3s16(L, 1); v3s16 maxp = read_v3s16(L, 2); std::set filter; - if(lua_istable(L, 3)) { + if(lua_istable(L, 3)){ int table = 3; lua_pushnil(L); - while(lua_next(L, table) != 0) { + while(lua_next(L, table) != 0){ // key at index -2 and value at index -1 luaL_checktype(L, -1, LUA_TSTRING); ndef->getIds(lua_tostring(L, -1), filter); // removes value, keeps key for next iteration lua_pop(L, 1); } - } else if(lua_isstring(L, 3)) { + } else if(lua_isstring(L, 3)){ ndef->getIds(lua_tostring(L, 3), filter); } @@ -570,59 +584,6 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) return 1; } -// find_nodes_in_area_under_air(minp, maxp, nodenames) -> list of positions -// nodenames: e.g. {"ignore", "group:tree"} or "default:dirt" -int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L) -{ - /* Note: A similar but generalized (and therefore slower) version of this - * function could be created -- e.g. find_nodes_in_area_under -- which - * would accept a node name (or ID?) or list of names that the "above node" - * should be. - * TODO - */ - - GET_ENV_PTR; - - INodeDefManager *ndef = getServer(L)->ndef(); - v3s16 minp = read_v3s16(L, 1); - v3s16 maxp = read_v3s16(L, 2); - std::set filter; - - if (lua_istable(L, 3)) { - int table = 3; - lua_pushnil(L); - while(lua_next(L, table) != 0) { - // key at index -2 and value at index -1 - luaL_checktype(L, -1, LUA_TSTRING); - ndef->getIds(lua_tostring(L, -1), filter); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } else if (lua_isstring(L, 3)) { - ndef->getIds(lua_tostring(L, 3), filter); - } - - lua_newtable(L); - u64 i = 0; - for (s16 x = minp.X; x <= maxp.X; x++) - for (s16 z = minp.Z; z <= maxp.Z; z++) { - s16 y = minp.Y; - v3s16 p(x, y, z); - content_t c = env->getMap().getNodeNoEx(p).getContent(); - for (; y <= maxp.Y; y++) { - v3s16 psurf(x, y + 1, z); - content_t csurf = env->getMap().getNodeNoEx(psurf).getContent(); - if(c != CONTENT_AIR && csurf == CONTENT_AIR && - filter.count(c) != 0) { - push_v3s16(L, v3s16(x, y, z)); - lua_rawseti(L, -2, ++i); - } - c = csurf; - } - } - return 1; -} - // get_perlin(seeddiff, octaves, persistence, scale) // returns world-specific PerlinNoise int ModApiEnvMod::l_get_perlin(lua_State *L) @@ -920,7 +881,6 @@ void ModApiEnvMod::Initialize(lua_State *L, int top) API_FCT(get_gametime); API_FCT(find_node_near); API_FCT(find_nodes_in_area); - API_FCT(find_nodes_in_area_under_air); API_FCT(delete_area); API_FCT(get_perlin); API_FCT(get_perlin_map); diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h index 5c9afd2f1..bfaea1c4d 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -119,10 +119,6 @@ private: // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" static int l_find_nodes_in_area(lua_State *L); - // find_surface_nodes_in_area(minp, maxp, nodenames) -> list of positions - // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" - static int l_find_nodes_in_area_under_air(lua_State *L); - // delete_area(p1, p2) -> true/false static int l_delete_area(lua_State *L); diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 2bed2a255..28c3d193d 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -472,7 +472,6 @@ int ModApiMainMenu::l_get_favorites(lua_State *L) for (unsigned int i = 0; i < servers.size(); i++) { - lua_pushnumber(L,index); lua_newtable(L); @@ -510,18 +509,6 @@ int ModApiMainMenu::l_get_favorites(lua_State *L) lua_settable(L, top_lvl2); } - if (servers[i]["proto_min"].asString().size()) { - lua_pushstring(L,"proto_min"); - lua_pushinteger(L,servers[i]["proto_min"].asInt()); - lua_settable(L, top_lvl2); - } - - if (servers[i]["proto_max"].asString().size()) { - lua_pushstring(L,"proto_max"); - lua_pushinteger(L,servers[i]["proto_max"].asInt()); - lua_settable(L, top_lvl2); - } - if (servers[i]["password"].asString().size()) { lua_pushstring(L,"password"); lua_pushboolean(L,servers[i]["password"].asBool()); @@ -872,19 +859,19 @@ int ModApiMainMenu::l_extract_zip(lua_State *L) unsigned int number_of_files = files_in_zip->getFileCount(); - for (unsigned int i=0; i < number_of_files; i++) { + for (unsigned int i=0; i < number_of_files; i++) { std::string fullpath = destination; fullpath += DIR_DELIM; fullpath += files_in_zip->getFullFileName(i).c_str(); - std::string fullpath_dir = fs::RemoveLastPathComponent(fullpath); - if (!files_in_zip->isDirectory(i)) { - if (!fs::PathExists(fullpath_dir) && !fs::CreateAllDirs(fullpath_dir)) { + if (files_in_zip->isDirectory(i)) { + if (! fs::CreateAllDirs(fullpath) ) { fs->removeFileArchive(fs->getFileArchiveCount()-1); lua_pushboolean(L,false); return 1; } - + } + else { io::IReadFile* toread = opened_zip->createAndOpenFile(i); FILE *targetfile = fopen(fullpath.c_str(),"wb"); @@ -896,7 +883,7 @@ int ModApiMainMenu::l_extract_zip(lua_State *L) } char read_buffer[1024]; - long total_read = 0; + unsigned int total_read = 0; while (total_read < toread->getSize()) { @@ -1095,19 +1082,6 @@ int ModApiMainMenu::l_get_screen_info(lua_State *L) return 1; } -/******************************************************************************/ -int ModApiMainMenu::l_get_min_supp_proto(lua_State *L) -{ - lua_pushinteger(L, CLIENT_PROTOCOL_VERSION_MIN); - return 1; -} - -int ModApiMainMenu::l_get_max_supp_proto(lua_State *L) -{ - lua_pushinteger(L, CLIENT_PROTOCOL_VERSION_MAX); - return 1; -} - /******************************************************************************/ int ModApiMainMenu::l_do_async_callback(lua_State *L) { @@ -1168,8 +1142,6 @@ void ModApiMainMenu::Initialize(lua_State *L, int top) API_FCT(gettext); API_FCT(get_video_drivers); API_FCT(get_screen_info); - API_FCT(get_min_supp_proto); - API_FCT(get_max_supp_proto); API_FCT(do_async_callback); } diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h index 8b21a93aa..ff61dd97a 100644 --- a/src/script/lua_api/l_mainmenu.h +++ b/src/script/lua_api/l_mainmenu.h @@ -137,12 +137,6 @@ private: static int l_get_video_drivers(lua_State *L); - //version compatibility - static int l_get_min_supp_proto(lua_State *L); - - static int l_get_max_supp_proto(lua_State *L); - - // async static int l_do_async_callback(lua_State *L); diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index 54ec69010..d470cef88 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -444,7 +444,8 @@ int ModApiMapgen::l_register_biome(lua_State *L) b->name = getstringfield_default(L, index, "name", ""); b->depth_top = getintfield_default(L, index, "depth_top", 1); - b->depth_filler = getintfield_default(L, index, "depth_filler", 2); + b->depth_filler = getintfield_default(L, index, "depth_filler", 3); + b->height_shore = getintfield_default(L, index, "height_shore", 3); b->depth_water_top = getintfield_default(L, index, "depth_water_top", 0); b->y_min = getintfield_default(L, index, "y_min", -31000); b->y_max = getintfield_default(L, index, "y_max", 31000); @@ -459,9 +460,12 @@ int ModApiMapgen::l_register_biome(lua_State *L) } NodeResolveInfo *nri = new NodeResolveInfo(b); - std::vector &nnames = nri->nodenames; + std::list &nnames = nri->nodenames; nnames.push_back(getstringfield_default(L, index, "node_top", "")); nnames.push_back(getstringfield_default(L, index, "node_filler", "")); + nnames.push_back(getstringfield_default(L, index, "node_shore_top", "")); + nnames.push_back(getstringfield_default(L, index, "node_shore_filler", "")); + nnames.push_back(getstringfield_default(L, index, "node_underwater", "")); nnames.push_back(getstringfield_default(L, index, "node_stone", "")); nnames.push_back(getstringfield_default(L, index, "node_water_top", "")); nnames.push_back(getstringfield_default(L, index, "node_water", "")); diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index d8cfaf82b..4286840fe 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "tool.h" #include "serverobject.h" +#include "content_object.h" #include "content_sao.h" #include "server.h" #include "hud.h" @@ -131,7 +132,6 @@ int ObjectRef::l_remove(lua_State *L) ObjectRef *ref = checkobject(L, 1); ServerActiveObject *co = getobject(ref); if(co == NULL) return 0; - if(co->getType() == ACTIVEOBJECT_TYPE_PLAYER) return 0; verbosestream<<"ObjectRef::l_remove(): id="<getId()<m_removed = true; return 0; @@ -208,26 +208,8 @@ int ObjectRef::l_punch(lua_State *L) time_from_last_punch = lua_tonumber(L, 3); ToolCapabilities toolcap = read_tool_capabilities(L, 4); dir.normalize(); - - s16 src_original_hp = co->getHP(); - s16 dst_origin_hp = puncher->getHP(); - // Do it co->punch(dir, &toolcap, puncher, time_from_last_punch); - - // If the punched is a player, and its HP changed - if (src_original_hp != co->getHP() && - co->getType() == ACTIVEOBJECT_TYPE_PLAYER) { - getServer(L)->SendPlayerHPOrDie(((PlayerSAO*)co)->getPeerID(), - co->getHP() == 0); - } - - // If the puncher is a player, and its HP changed - if (dst_origin_hp != puncher->getHP() && - puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) { - getServer(L)->SendPlayerHPOrDie(((PlayerSAO*)puncher)->getPeerID(), - puncher->getHP() == 0); - } return 0; } @@ -261,9 +243,6 @@ int ObjectRef::l_set_hp(lua_State *L) <<" hp="<setHP(hp); - if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER) { - getServer(L)->SendPlayerHPOrDie(((PlayerSAO*)co)->getPeerID(), co->getHP() == 0); - } // Return return 0; } @@ -355,9 +334,6 @@ int ObjectRef::l_set_wielded_item(lua_State *L) // Do it ItemStack item = read_item(L, 2, getServer(L)); bool success = co->setWieldedItem(item); - if (success && co->getType() == ACTIVEOBJECT_TYPE_PLAYER) { - getServer(L)->SendInventory(((PlayerSAO*)co)); - } lua_pushboolean(L, success); return 1; } @@ -815,11 +791,7 @@ int ObjectRef::l_set_breath(lua_State *L) u16 breath = luaL_checknumber(L, 2); // Do it co->setBreath(breath); - - // If the object is a player sent the breath to client - if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER) - getServer(L)->SendPlayerBreath(((PlayerSAO*)co)->getPeerID()); - + co->m_breath_not_sent = true; return 0; } diff --git a/src/script/lua_api/l_rollback.cpp b/src/script/lua_api/l_rollback.cpp index 5744e6813..f55a72d1b 100644 --- a/src/script/lua_api/l_rollback.cpp +++ b/src/script/lua_api/l_rollback.cpp @@ -44,9 +44,6 @@ int ModApiRollback::l_rollback_get_node_actions(lua_State *L) int limit = luaL_checknumber(L, 4); Server *server = getServer(L); IRollbackManager *rollback = server->getRollbackManager(); - if (rollback == NULL) { - return 0; - } std::list actions = rollback->getNodeActors(pos, range, seconds, limit); std::list::iterator iter = actions.begin(); @@ -83,13 +80,6 @@ int ModApiRollback::l_rollback_revert_actions_by(lua_State *L) int seconds = luaL_checknumber(L, 2); Server *server = getServer(L); IRollbackManager *rollback = server->getRollbackManager(); - - // If rollback is disabled, tell it's not a success. - if (rollback == NULL) { - lua_pushboolean(L, false); - lua_newtable(L); - return 2; - } std::list actions = rollback->getRevertActions(actor, seconds); std::list log; bool success = server->rollbackRevertActions(actions, &log); diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index fcdd8c2ff..8d7f6512e 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -367,18 +367,33 @@ int ModApiServer::l_get_modnames(lua_State *L) NO_MAP_LOCK_REQUIRED; // Get a list of mods - std::vector modlist; - getServer(L)->getModNames(modlist); + std::list mods_unsorted, mods_sorted; + getServer(L)->getModNames(mods_unsorted); // Take unsorted items from mods_unsorted and sort them into // mods_sorted; not great performance but the number of mods on a // server will likely be small. - std::sort(modlist.begin(), modlist.end()); + for(std::list::iterator i = mods_unsorted.begin(); + i != mods_unsorted.end(); ++i) { + bool added = false; + for(std::list::iterator x = mods_sorted.begin(); + x != mods_sorted.end(); ++x) { + // I doubt anybody using Minetest will be using + // anything not ASCII based :) + if(i->compare(*x) <= 0) { + mods_sorted.insert(x, *i); + added = true; + break; + } + } + if(!added) + mods_sorted.push_back(*i); + } // Package them up for Lua - lua_createtable(L, modlist.size(), 0); - std::vector::iterator iter = modlist.begin(); - for (u16 i = 0; iter != modlist.end(); iter++) { + lua_createtable(L, mods_sorted.size(), 0); + std::list::iterator iter = mods_sorted.begin(); + for (u16 i = 0; iter != mods_sorted.end(); iter++) { lua_pushstring(L, iter->c_str()); lua_rawseti(L, -2, ++i); } diff --git a/src/server.cpp b/src/server.cpp index 09884f1bc..399c41b70 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -21,8 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include -#include "network/networkprotocol.h" -#include "network/serveropcodes.h" +#include "clientserver.h" #include "ban.h" #include "environment.h" #include "map.h" @@ -51,18 +50,20 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_abm.h" #include "content_sao.h" #include "mods.h" +#include "sha1.h" +#include "base64.h" +#include "tool.h" #include "sound.h" // dummySoundManager #include "event_manager.h" +#include "hex.h" #include "serverlist.h" #include "util/string.h" +#include "util/pointedthing.h" #include "util/mathconstants.h" #include "rollback.h" #include "util/serialize.h" #include "util/thread.h" #include "defaultsettings.h" -#include "util/base64.h" -#include "util/sha1.h" -#include "util/hex.h" class ClientNotFoundException : public BaseException { @@ -243,6 +244,9 @@ Server::Server( std::string ban_path = m_path_world + DIR_DELIM "ipban.txt"; m_banmanager = new BanManager(ban_path); + // Create rollback manager + m_rollback = new RollbackManager(m_path_world, this); + ModConfiguration modconf(m_path_world); m_mods = modconf.getMods(); std::vector unsatisfied_mods = modconf.getUnsatisfiedMods(); @@ -350,12 +354,6 @@ Server::Server( // Initialize mapgens m_emerge->initMapgens(); - m_enable_rollback_recording = g_settings->getBool("enable_rollback_recording"); - if (m_enable_rollback_recording) { - // Create rollback manager - m_rollback = new RollbackManager(m_path_world, this); - } - // Give environment reference to scripting api m_script->initializeEnvironment(m_env); @@ -535,18 +533,23 @@ void Server::AsyncRunStep(bool initial_step) /* Update time of day and overall game time */ - m_env->setTimeOfDaySpeed(g_settings->getFloat("time_speed")); + { + JMutexAutoLock envlock(m_env_mutex); - /* - Send to clients at constant intervals - */ + m_env->setTimeOfDaySpeed(g_settings->getFloat("time_speed")); - m_time_of_day_send_timer -= dtime; - if(m_time_of_day_send_timer < 0.0) { - m_time_of_day_send_timer = g_settings->getFloat("time_send_interval"); - u16 time = m_env->getTimeOfDay(); - float time_speed = g_settings->getFloat("time_speed"); - SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed); + /* + Send to clients at constant intervals + */ + + m_time_of_day_send_timer -= dtime; + if(m_time_of_day_send_timer < 0.0) + { + m_time_of_day_send_timer = g_settings->getFloat("time_send_interval"); + u16 time = m_env->getTimeOfDay(); + float time_speed = g_settings->getFloat("time_speed"); + SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed); + } } { @@ -581,6 +584,56 @@ void Server::AsyncRunStep(bool initial_step) Do background stuff */ + /* + Handle players + */ + { + JMutexAutoLock lock(m_env_mutex); + + std::list clientids = m_clients.getClientIDs(); + + ScopeProfiler sp(g_profiler, "Server: handle players"); + + for(std::list::iterator + i = clientids.begin(); + i != clientids.end(); ++i) + { + PlayerSAO *playersao = getPlayerSAO(*i); + if(playersao == NULL) + continue; + + /* + Handle player HPs (die if hp=0) + */ + if(playersao->m_hp_not_sent && g_settings->getBool("enable_damage")) + { + if(playersao->getHP() == 0) + DiePlayer(*i); + else + SendPlayerHP(*i); + } + + /* + Send player breath if changed + */ + if(playersao->m_breath_not_sent) { + SendPlayerBreath(*i); + } + + /* + Send player inventories if necessary + */ + if(playersao->m_moved){ + SendMovePlayer(*i); + playersao->m_moved = false; + } + if(playersao->m_inventory_not_sent){ + UpdateCrafting(*i); + SendInventory(*i); + } + } + } + /* Transform liquids */ m_liquid_transform_timer += dtime; if(m_liquid_transform_timer >= m_liquid_transform_every) @@ -765,18 +818,46 @@ void Server::AsyncRunStep(bool initial_step) obj->m_known_by_count++; } - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, 0, client->peer_id); - pkt->putRawString(data_buffer.c_str(), data_buffer.size()); + // Send packet + SharedBuffer reply(2 + data_buffer.size()); + writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD); + memcpy((char*)&reply[2], data_buffer.c_str(), + data_buffer.size()); + // Send as reliable + m_clients.send(client->peer_id, 0, reply, true); - - verbosestream << "Server: Sent object remove/add: " - << removed_objects.size() << " removed, " - << added_objects.size() << " added, " - << "packet size is " << pkt->getSize() << std::endl; - - Send(pkt); + verbosestream<<"Server: Sent object remove/add: " + < all_known_objects; + + for(core::map::Iterator + i = m_clients.getIterator(); + i.atEnd() == false; i++) + { + RemoteClient *client = i.getNode()->getValue(); + // Go through all known objects of client + for(core::map::Iterator + i = client->m_known_objects.getIterator(); + i.atEnd()==false; i++) + { + u16 id = i.getNode()->getKey(); + all_known_objects[id] = true; + } + } + + m_env->setKnownActiveObjects(whatever); +#endif + } /* @@ -788,22 +869,25 @@ void Server::AsyncRunStep(bool initial_step) // Key = object id // Value = data sent by object - std::map* > buffered_messages; + std::map* > buffered_messages; // Get active object messages from environment - for(;;) { + for(;;) + { ActiveObjectMessage aom = m_env->getActiveObjectMessage(); - if (aom.id == 0) + if(aom.id == 0) break; - std::vector* message_list = NULL; - std::map* >::iterator n; + std::list* message_list = NULL; + std::map* >::iterator n; n = buffered_messages.find(aom.id); - if (n == buffered_messages.end()) { - message_list = new std::vector; + if(n == buffered_messages.end()) + { + message_list = new std::list; buffered_messages[aom.id] = message_list; } - else { + else + { message_list = n->second; } message_list->push_back(aom); @@ -812,26 +896,28 @@ void Server::AsyncRunStep(bool initial_step) m_clients.Lock(); std::map clients = m_clients.getClientList(); // Route data to every client - for (std::map::iterator + for(std::map::iterator i = clients.begin(); - i != clients.end(); ++i) { + i != clients.end(); ++i) + { RemoteClient *client = i->second; std::string reliable_data; std::string unreliable_data; // Go through all objects in message buffer - for (std::map* >::iterator + for(std::map* >::iterator j = buffered_messages.begin(); - j != buffered_messages.end(); ++j) { + j != buffered_messages.end(); ++j) + { // If object is not known by client, skip it u16 id = j->first; - if (client->m_known_objects.find(id) == client->m_known_objects.end()) + if(client->m_known_objects.find(id) == client->m_known_objects.end()) continue; - // Get message list of object - std::vector* list = j->second; + std::list* list = j->second; // Go through every message - for (std::vector::iterator - k = list->begin(); k != list->end(); ++k) { + for(std::list::iterator + k = list->begin(); k != list->end(); ++k) + { // Compose the full new data with header ActiveObjectMessage aom = *k; std::string new_data; @@ -852,28 +938,40 @@ void Server::AsyncRunStep(bool initial_step) reliable_data and unreliable_data are now ready. Send them. */ - if(reliable_data.size() > 0) { - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ACTIVE_OBJECT_MESSAGES, - 0, client->peer_id); - - pkt->putRawString(reliable_data.c_str(), reliable_data.size()); - Send(pkt); + if(reliable_data.size() > 0) + { + SharedBuffer reply(2 + reliable_data.size()); + writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_MESSAGES); + memcpy((char*)&reply[2], reliable_data.c_str(), + reliable_data.size()); + // Send as reliable + m_clients.send(client->peer_id, 0, reply, true); + } + if(unreliable_data.size() > 0) + { + SharedBuffer reply(2 + unreliable_data.size()); + writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_MESSAGES); + memcpy((char*)&reply[2], unreliable_data.c_str(), + unreliable_data.size()); + // Send as unreliable + m_clients.send(client->peer_id, 1, reply, false); } - if(unreliable_data.size() > 0) { - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ACTIVE_OBJECT_MESSAGES, - 0, client->peer_id); - - pkt->putRawString(unreliable_data.c_str(), unreliable_data.size()); - Send(pkt); - } + /*if(reliable_data.size() > 0 || unreliable_data.size() > 0) + { + infostream<<"Server: Size of object message data: " + <<"reliable: "<* >::iterator + for(std::map* >::iterator i = buffered_messages.begin(); - i != buffered_messages.end(); ++i) { + i != buffered_messages.end(); ++i) + { delete i->second; } } @@ -900,67 +998,83 @@ void Server::AsyncRunStep(bool initial_step) while(m_unsent_map_edit_queue.size() != 0) { - MapEditEvent* event = m_unsent_map_edit_queue.front(); - m_unsent_map_edit_queue.pop(); + MapEditEvent* event = m_unsent_map_edit_queue.pop_front(); // Players far away from the change are stored here. // Instead of sending the changes, MapBlocks are set not sent // for them. - std::vector far_players; + std::list far_players; - switch (event->type) { - case MEET_ADDNODE: - case MEET_SWAPNODE: + if(event->type == MEET_ADDNODE || event->type == MEET_SWAPNODE) + { + //infostream<<"Server: MEET_ADDNODE"<p, event->n, event->already_known_by_peer, - &far_players, disable_single_change_sending ? 5 : 30, - event->type == MEET_ADDNODE); - break; - case MEET_REMOVENODE: + if(disable_single_change_sending) + sendAddNode(event->p, event->n, event->already_known_by_peer, + &far_players, 5, event->type == MEET_ADDNODE); + else + sendAddNode(event->p, event->n, event->already_known_by_peer, + &far_players, 30, event->type == MEET_ADDNODE); + } + else if(event->type == MEET_REMOVENODE) + { + //infostream<<"Server: MEET_REMOVENODE"<p, event->already_known_by_peer, - &far_players, disable_single_change_sending ? 5 : 30); - break; - case MEET_BLOCK_NODE_METADATA_CHANGED: - infostream << "Server: MEET_BLOCK_NODE_METADATA_CHANGED" << std::endl; - prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1); - setBlockNotSent(event->p); - break; - case MEET_OTHER: - infostream << "Server: MEET_OTHER" << std::endl; + if(disable_single_change_sending) + sendRemoveNode(event->p, event->already_known_by_peer, + &far_players, 5); + else + sendRemoveNode(event->p, event->already_known_by_peer, + &far_players, 30); + } + else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED) + { + infostream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<p); + } + else if(event->type == MEET_OTHER) + { + infostream<<"Server: MEET_OTHER"<::iterator i = event->modified_blocks.begin(); - i != event->modified_blocks.end(); ++i) { + i != event->modified_blocks.end(); ++i) + { setBlockNotSent(*i); } - break; - default: + } + else + { prof.add("unknown", 1); - infostream << "WARNING: Server: Unknown MapEditEvent " - << ((u32)event->type) << std::endl; - break; + infostream<<"WARNING: Server: Unknown MapEditEvent " + <<((u32)event->type)< modified_blocks2; for(std::set::iterator i = event->modified_blocks.begin(); - i != event->modified_blocks.end(); ++i) { + i != event->modified_blocks.end(); ++i) + { modified_blocks2[*i] = m_env->getMap().getBlockNoCreateNoEx(*i); } - // Set blocks not sent - for(std::vector::iterator + for(std::list::iterator i = far_players.begin(); - i != far_players.end(); ++i) { - if(RemoteClient *client = getClient(*i)) - client->SetBlocksNotSent(modified_blocks2); + i != far_players.end(); ++i) + { + u16 peer_id = *i; + RemoteClient *client = getClient(peer_id); + if(client==NULL) + continue; + client->SetBlocksNotSent(modified_blocks2); } } @@ -994,6 +1108,10 @@ void Server::AsyncRunStep(bool initial_step) counter = 0.0; m_emerge->startThreads(); + + // Update m_enable_rollback_recording here too + m_enable_rollback_recording = + g_settings->getBool("enable_rollback_recording"); } } @@ -1031,11 +1149,12 @@ void Server::Receive() SharedBuffer data; u16 peer_id; u32 datasize; - try { + try{ datasize = m_con.Receive(peer_id,data); ProcessData(*data, datasize, peer_id); } - catch(con::InvalidIncomingDataException &e) { + catch(con::InvalidIncomingDataException &e) + { infostream<<"Server::Receive(): " "InvalidIncomingDataException: what()=" <(m_env->getPlayer(playername.c_str())); // If failed, cancel - if((playersao == NULL) || (player == NULL)) { - if(player && player->peer_id != 0) { + if((playersao == NULL) || (player == NULL)) + { + if(player && player->peer_id != 0){ errorstream<<"Server: "<getBool("enable_damage")) @@ -1117,7 +1240,8 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id) SendDeathscreen(peer_id, false, v3f(0,0,0)); // Note things in chat if not in simple singleplayer mode - if(!m_simple_singleplayer_mode) { + if(!m_simple_singleplayer_mode) + { // Send information about server to player in chat SendChatMessage(peer_id, getStatusString()); @@ -1147,7 +1271,8 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id) actionstream<getName() <<" joins game. List of players: "; for (std::vector::iterator i = names.begin(); - i != names.end(); i++) { + i != names.end(); i++) + { actionstream << *i << " "; } @@ -1156,12 +1281,6 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id) return playersao; } -inline void Server::handleCommand(NetworkPacket* pkt) -{ - const ToServerCommandHandler& opHandle = toServerCommandTable[pkt->getCommand()]; - (this->*opHandle.handler)(pkt); -} - void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) { DSTACK(__FUNCTION_NAME); @@ -1170,90 +1289,1459 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) ScopeProfiler sp(g_profiler, "Server::ProcessData"); - try { + std::string addr_s; + try{ Address address = getPeerAddress(peer_id); - std::string addr_s = address.serializeString(); + addr_s = address.serializeString(); - if(m_banmanager->isIpBanned(addr_s)) { + // drop player if is ip is banned + if(m_banmanager->isIpBanned(addr_s)){ std::string ban_name = m_banmanager->getBanName(addr_s); - infostream << "Server: A banned client tried to connect from " - << addr_s << "; banned name was " - << ban_name << std::endl; + infostream<<"Server: A banned client tried to connect from " + <getCommand(); - - // Command must be handled into ToServerCommandHandler - if (command >= TOSERVER_NUM_MSG_TYPES) { - infostream << "Server: Ignoring unknown command " - << command << std::endl; - } - - if (toServerCommandTable[command].state == TOSERVER_STATE_NOT_CONNECTED) { - handleCommand(pkt); - delete pkt; + // If net_proto_version is set, this client has already been handled + if(client->getState() > CS_Created) + { + verbosestream<<"Server: Ignoring multiple TOSERVER_INITs from " + <serialization_version; + verbosestream<<"Server: Got TOSERVER_INIT from "<setPendingSerializationVersion(deployed); - errorstream << "Got packet command: " << command << " for peer id " - << peer_id << " but client isn't active yet. Dropping packet " - << std::endl; + /* + Read and check network protocol version + */ - delete pkt; + 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) + { + // 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 < SERVER_PROTOCOL_VERSION_MIN || + net_proto_version > SERVER_PROTOCOL_VERSION_MAX) + { + actionstream<<"Server: A mismatched client tried to connect from " + <getBool("strict_protocol_version_checking")) + { + if(net_proto_version != LATEST_PROTOCOL_VERSION) + { + actionstream<<"Server: A mismatched (strict) client tried to " + <<"connect from "<on_prejoinplayer(playername, addr_s, reason)) + { + actionstream<<"Server: Player with the name \""<= g_settings->getU16("max_users") && + !checkPriv(playername, "server") && + !checkPriv(playername, "ban") && + !checkPriv(playername, "privs") && + !checkPriv(playername, "password") && + playername != g_settings->get("name")) + { + actionstream<<"Server: "<getAuth(playername, &checkpwd, NULL); + + // If no authentication info exists for user, create it + if(!has_auth){ + if(!isSingleplayer() && + g_settings->getBool("disallow_empty_password") && + std::string(given_password) == ""){ + actionstream<<"Server: "<get("default_password")); + std::string initial_password = + translatePassword(playername, raw_default_password); + + // If default_password is empty, allow any initial password + if (raw_default_password.length() == 0) + initial_password = given_password; + + m_script->createAuth(playername, initial_password); + } + + has_auth = m_script->getAuth(playername, &checkpwd, NULL); + + if(!has_auth){ + actionstream<<"Server: "<(m_env->getPlayer(playername)); + + if(player && player->peer_id != 0){ + errorstream<<"Server: "< reply(2+1+6+8+4); + writeU16(&reply[0], TOCLIENT_INIT); + writeU8(&reply[2], deployed); + //send dummy pos for legacy reasons only + writeV3S16(&reply[2+1], floatToInt(v3f(0,0,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_clients.send(peer_id, 0, reply, true); + m_clients.event(peer_id, CSE_Init); + } + + return; + } + + if(command == TOSERVER_INIT2) + { + + verbosestream<<"Server: Got TOSERVER_INIT2 from " + <getTimeOfDay(); + float time_speed = g_settings->getFloat("time_speed"); + SendTimeOfDay(peer_id, time, time_speed); + + ///// begin compatibility code + if (protocol_version <= 22) { + m_clients.event(peer_id, CSE_SetClientReady); + m_script->on_joinplayer(playersao); + } + ///// end compatibility code + + // Warnings about protocol version can be issued here + if(getClient(peer_id)->net_proto_version < LATEST_PROTOCOL_VERSION) + { + SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT'S " + L"VERSION MAY NOT BE FULLY COMPATIBLE WITH THIS SERVER!"); + } + + return; + } + + u8 peer_ser_ver = getClient(peer_id, CS_InitDone)->serialization_version; + u16 peer_proto_ver = getClient(peer_id, CS_InitDone)->net_proto_version; + + if(peer_ser_ver == SER_FMT_VER_INVALID) + { + errorstream<<"Server::ProcessData(): Cancelling: Peer" + " serialization format invalid or not initialized." + " Skipping incoming command="< tosend; + u16 numfiles = readU16(is); + + infostream<<"Sending "<on_joinplayer(playersao); } - catch(SendFailedException &e) { - errorstream << "Server::ProcessData(): SendFailedException: " - << "what=" << e.what() - << std::endl; + else if(command == TOSERVER_GOTBLOCKS) + { + if(datasize < 2+1) + return; + + /* + [0] u16 command + [2] u8 count + [3] v3s16 pos_0 + [3+6] v3s16 pos_1 + ... + */ + + u16 count = data[2]; + for(u16 i=0; iGotBlock(p); + } + return; + } + + if (m_clients.getClientState(peer_id) < CS_Active) + { + if (command == TOSERVER_PLAYERPOS) return; + + errorstream<<"Got packet command: " << command << " for peer id " + << peer_id << " but client isn't active yet. Dropping packet " + <getPlayer(peer_id); + if(player == NULL) { + errorstream<<"Server::ProcessData(): Cancelling: " + "No player for peer_id="<getPlayerSAO(); + if(playersao == NULL) { + errorstream<<"Server::ProcessData(): Cancelling: " + "No player object for peer_id="<= 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); + yaw = wrapDegrees(yaw); + + player->setPosition(position); + player->setSpeed(speed); + player->setPitch(pitch); + player->setYaw(yaw); + player->keyPressed=keyPressed; + player->control.up = (bool)(keyPressed&1); + player->control.down = (bool)(keyPressed&2); + player->control.left = (bool)(keyPressed&4); + player->control.right = (bool)(keyPressed&8); + player->control.jump = (bool)(keyPressed&16); + player->control.aux1 = (bool)(keyPressed&32); + player->control.sneak = (bool)(keyPressed&64); + player->control.LMB = (bool)(keyPressed&128); + player->control.RMB = (bool)(keyPressed&256); + + bool cheated = playersao->checkMovementCheat(); + if(cheated){ + // Call callbacks + m_script->on_cheat(playersao, "moved_too_fast"); + } + + /*infostream<<"Server::ProcessData(): Moved player "<SetBlockNotSent(p); + } + } + else if(command == TOSERVER_CLICK_OBJECT) + { + infostream<<"Server: CLICK_OBJECT not supported anymore"<getName()); + + /* + Note: Always set inventory not sent, to repair cases + where the client made a bad prediction. + */ + + /* + Handle restrictions and special cases of the move action + */ + if(a->getType() == IACTION_MOVE) + { + IMoveAction *ma = (IMoveAction*)a; + + ma->from_inv.applyCurrentPlayer(player->getName()); + ma->to_inv.applyCurrentPlayer(player->getName()); + + setInventoryModified(ma->from_inv); + setInventoryModified(ma->to_inv); + + bool from_inv_is_current_player = + (ma->from_inv.type == InventoryLocation::PLAYER) && + (ma->from_inv.name == player->getName()); + + bool to_inv_is_current_player = + (ma->to_inv.type == InventoryLocation::PLAYER) && + (ma->to_inv.name == player->getName()); + + /* + Disable moving items out of craftpreview + */ + if(ma->from_list == "craftpreview") + { + infostream<<"Ignoring IMoveAction from " + <<(ma->from_inv.dump())<<":"<from_list + <<" to "<<(ma->to_inv.dump())<<":"<to_list + <<" because src is "<from_list<to_list == "craftpreview" || ma->to_list == "craftresult") + { + infostream<<"Ignoring IMoveAction from " + <<(ma->from_inv.dump())<<":"<from_list + <<" to "<<(ma->to_inv.dump())<<":"<to_list + <<" because dst is "<to_list<getName(), "interact") && + (!from_inv_is_current_player || + !to_inv_is_current_player)) + { + infostream<<"Cannot move outside of player's inventory: " + <<"No interact privilege"<getType() == IACTION_DROP) + { + IDropAction *da = (IDropAction*)a; + + da->from_inv.applyCurrentPlayer(player->getName()); + + setInventoryModified(da->from_inv); + + /* + Disable dropping items out of craftpreview + */ + if(da->from_list == "craftpreview") + { + infostream<<"Ignoring IDropAction from " + <<(da->from_inv.dump())<<":"<from_list + <<" because src is "<from_list<getName(), "interact")) + { + delete a; + return; + } + } + /* + Handle restrictions and special cases of the craft action + */ + else if(a->getType() == IACTION_CRAFT) + { + ICraftAction *ca = (ICraftAction*)a; + + ca->craft_inv.applyCurrentPlayer(player->getName()); + + setInventoryModified(ca->craft_inv); + + //bool craft_inv_is_current_player = + // (ca->craft_inv.type == InventoryLocation::PLAYER) && + // (ca->craft_inv.name == player->getName()); + + // Disallow crafting if not allowed to interact + if(!checkPriv(player->getName(), "interact")) + { + infostream<<"Cannot craft: " + <<"No interact privilege"<apply(this, playersao, this); + // Eat the action + delete a; + } + else if(command == TOSERVER_CHAT_MESSAGE) + { + /* + u16 command + u16 length + wstring message + */ + u8 buf[6]; + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + // Read stuff + is.read((char*)buf, 2); + u16 len = readU16(buf); + + std::wstring message; + for(u16 i=0; igetName()); + + // Get player name of this client + std::wstring name = narrow_to_wide(player->getName()); + + // Run script hook + bool ate = m_script->on_chat_message(player->getName(), + wide_to_narrow(message)); + // If script ate the message, don't proceed + if(ate) + return; + + // Line to send to players + std::wstring line; + // Whether to send to the player that sent the line + bool send_to_sender_only = false; + + // Commands are implemented in Lua, so only catch invalid + // commands that were not "eaten" and send an error back + if(message[0] == L'/') + { + message = message.substr(1); + send_to_sender_only = true; + if(message.length() == 0) + line += L"-!- Empty command"; + else + line += L"-!- Invalid command: " + str_split(message, L' ')[0]; + } + else + { + if(checkPriv(player->getName(), "shout")){ + line += L"<"; + line += name; + line += L"> "; + line += message; + } else { + line += L"-!- You don't have permission to shout."; + send_to_sender_only = true; + } + } + + if(line != L"") + { + /* + Send the message to sender + */ + if (send_to_sender_only) + { + SendChatMessage(peer_id, line); + } + /* + Send the message to others + */ + else + { + actionstream<<"CHAT: "< clients = m_clients.getClientIDs(); + + for(std::list::iterator + i = clients.begin(); + i != clients.end(); ++i) + { + if (*i != peer_id) + SendChatMessage(*i, line); + } + } + } + } + else if(command == TOSERVER_DAMAGE) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + u8 damage = readU8(is); + + if(g_settings->getBool("enable_damage")) + { + actionstream<getName()<<" damaged by " + <<(int)damage<<" hp at "<getPosition()/BS) + <setHP(playersao->getHP() - damage); + + if(playersao->getHP() == 0 && playersao->m_hp_not_sent) + DiePlayer(peer_id); + + if(playersao->m_hp_not_sent) + SendPlayerHP(peer_id); + } + } + else if(command == TOSERVER_BREATH) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + u16 breath = readU16(is); + playersao->setBreath(breath); + m_script->player_event(playersao,"breath_changed"); + } + else if(command == TOSERVER_PASSWORD) + { + /* + [0] u16 TOSERVER_PASSWORD + [2] u8[28] old password + [30] u8[28] new password + */ + + if(datasize != 2+PASSWORD_SIZE*2) + return; + /*char password[PASSWORD_SIZE]; + for(u32 i=0; igetName()<<" supplied invalid password hash"<getName(); + + std::string checkpwd; + m_script->getAuth(playername, &checkpwd, NULL); + + if(oldpwd != checkpwd) + { + infostream<<"Server: invalid old password"<setPassword(playername, newpwd); + if(success){ + actionstream<getName()<<" changes password"<getName()<<" tries to change password but " + <<"it fails"<setWieldIndex(item); + } + else if(command == TOSERVER_RESPAWN) + { + if(player->hp != 0 || !g_settings->getBool("enable_damage")) + return; + + RespawnPlayer(peer_id); + + actionstream<getName()<<" respawns at " + <getPosition()/BS)<getName() + <<" tried to interact, but is dead!"<getLastGoodPosition(); + + // Update wielded item + playersao->setWieldIndex(item_i); + + // Get pointed to node (undefined if not POINTEDTYPE_NODE) + v3s16 p_under = pointed.node_undersurface; + v3s16 p_above = pointed.node_abovesurface; + + // Get pointed to object (NULL if not POINTEDTYPE_OBJECT) + ServerActiveObject *pointed_object = NULL; + if(pointed.type == POINTEDTHING_OBJECT) + { + pointed_object = m_env->getActiveObject(pointed.object_id); + if(pointed_object == NULL) + { + verbosestream<<"TOSERVER_INTERACT: " + "pointed object is NULL"<getBasePosition(); + pointed_pos_above = pointed_pos_under; + } + + /* + Check that target is reasonably close + (only when digging or placing things) + */ + if(action == 0 || action == 2 || action == 3) + { + float d = player_pos.getDistanceFrom(pointed_pos_under); + float max_d = BS * 14; // Just some large enough value + if(d > max_d){ + actionstream<<"Player "<getName() + <<" tried to access "<SetBlockNotSent(blockpos); + // Call callbacks + m_script->on_cheat(playersao, "interacted_too_far"); + // Do nothing else + return; + } + } + + /* + Make sure the player is allowed to do it + */ + if(!checkPriv(player->getName(), "interact")) + { + actionstream<getName()<<" attempted to interact with " + < under + if(action == 2){ + v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS)); + client->SetBlockNotSent(blockpos); + } + // Placement -> above + if(action == 3){ + v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS)); + client->SetBlockNotSent(blockpos); + } + return; + } + + /* + If something goes wrong, this player is to blame + */ + RollbackScopeActor rollback_scope(m_rollback, + std::string("player:")+player->getName()); + + /* + 0: start digging or punch object + */ + if(action == 0) + { + if(pointed.type == POINTEDTHING_NODE) + { + /* + NOTE: This can be used in the future to check if + somebody is cheating, by checking the timing. + */ + MapNode n(CONTENT_IGNORE); + bool pos_ok; + n = m_env->getMap().getNodeNoEx(p_under, &pos_ok); + if (pos_ok) + n = m_env->getMap().getNodeNoEx(p_under, &pos_ok); + + if (!pos_ok) { + infostream<<"Server: Not punching: Node not found." + <<" Adding block to emerge queue." + <enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false); + } + + if(n.getContent() != CONTENT_IGNORE) + m_script->node_on_punch(p_under, n, playersao, pointed); + // Cheat prevention + playersao->noCheatDigStart(p_under); + } + else if(pointed.type == POINTEDTHING_OBJECT) + { + // Skip if object has been removed + if(pointed_object->m_removed) + return; + + actionstream<getName()<<" punches object " + <getDescription()<getWieldedItem(); + ToolCapabilities toolcap = + punchitem.getToolCapabilities(m_itemdef); + v3f dir = (pointed_object->getBasePosition() - + (player->getPosition() + player->getEyeOffset()) + ).normalize(); + float time_from_last_punch = + playersao->resetTimeFromLastPunch(); + pointed_object->punch(dir, &toolcap, playersao, + time_from_last_punch); + } + + } // action == 0 + + /* + 1: stop digging + */ + else if(action == 1) + { + } // action == 1 + + /* + 2: Digging completed + */ + else if(action == 2) + { + // Only digging of nodes + if(pointed.type == POINTEDTHING_NODE) + { + bool pos_ok; + MapNode n = m_env->getMap().getNodeNoEx(p_under, &pos_ok); + if (!pos_ok) { + infostream << "Server: Not finishing digging: Node not found." + << " Adding block to emerge queue." + << std::endl; + m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false); + } + + /* Cheat prevention */ + bool is_valid_dig = true; + if(!isSingleplayer() && !g_settings->getBool("disable_anticheat")) + { + v3s16 nocheat_p = playersao->getNoCheatDigPos(); + float nocheat_t = playersao->getNoCheatDigTime(); + playersao->noCheatDigEnd(); + // If player didn't start digging this, ignore dig + if(nocheat_p != p_under){ + infostream<<"Server: NoCheat: "<getName() + <<" started digging " + <on_cheat(playersao, "finished_unknown_dig"); + } + // Get player's wielded item + ItemStack playeritem; + InventoryList *mlist = playersao->getInventory()->getList("main"); + if(mlist != NULL) + playeritem = mlist->getItem(playersao->getWieldIndex()); + ToolCapabilities playeritem_toolcap = + playeritem.getToolCapabilities(m_itemdef); + // Get diggability and expected digging time + DigParams params = getDigParams(m_nodedef->get(n).groups, + &playeritem_toolcap); + // If can't dig, try hand + if(!params.diggable){ + const ItemDefinition &hand = m_itemdef->get(""); + const ToolCapabilities *tp = hand.tool_capabilities; + if(tp) + params = getDigParams(m_nodedef->get(n).groups, tp); + } + // If can't dig, ignore dig + if(!params.diggable){ + infostream<<"Server: NoCheat: "<getName() + <<" completed digging "<on_cheat(playersao, "dug_unbreakable"); + } + // Check digging time + // If already invalidated, we don't have to + if(!is_valid_dig){ + // Well not our problem then + } + // Clean and long dig + else if(params.time > 2.0 && nocheat_t * 1.2 > params.time){ + // All is good, but grab time from pool; don't care if + // it's actually available + playersao->getDigPool().grab(params.time); + } + // Short or laggy dig + // Try getting the time from pool + else if(playersao->getDigPool().grab(params.time)){ + // All is good + } + // Dig not possible + else{ + infostream<<"Server: NoCheat: "<getName() + <<" completed digging "<on_cheat(playersao, "dug_too_fast"); + } + } + + /* Actually dig node */ + + if(is_valid_dig && n.getContent() != CONTENT_IGNORE) + m_script->node_on_dig(p_under, n, playersao); + + v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS)); + RemoteClient *client = getClient(peer_id); + // Send unusual result (that is, node not being removed) + if(m_env->getMap().getNodeNoEx(p_under).getContent() != CONTENT_AIR) + { + // Re-send block to revert change on client-side + client->SetBlockNotSent(blockpos); + } + else { + client->ResendBlockIfOnWire(blockpos); + } + } + } // action == 2 + + /* + 3: place block or right-click object + */ + else if(action == 3) + { + ItemStack item = playersao->getWieldedItem(); + + // Reset build time counter + if(pointed.type == POINTEDTHING_NODE && + item.getDefinition(m_itemdef).type == ITEM_NODE) + getClient(peer_id)->m_time_from_building = 0.0; + + if(pointed.type == POINTEDTHING_OBJECT) + { + // Right click object + + // Skip if object has been removed + if(pointed_object->m_removed) + return; + + actionstream<getName()<<" right-clicks object " + <getDescription()<rightClick(playersao); + } + else if(m_script->item_OnPlace( + item, playersao, pointed)) + { + // Placement was handled in lua + + // Apply returned ItemStack + playersao->setWieldedItem(item); + } + + // If item has node placement prediction, always send the + // blocks to make sure the client knows what exactly happened + RemoteClient *client = getClient(peer_id); + v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS)); + v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS)); + if(item.getDefinition(m_itemdef).node_placement_prediction != "") { + client->SetBlockNotSent(blockpos); + if(blockpos2 != blockpos) { + client->SetBlockNotSent(blockpos2); + } + } + else { + client->ResendBlockIfOnWire(blockpos); + if(blockpos2 != blockpos) { + client->ResendBlockIfOnWire(blockpos2); + } + } + } // action == 3 + + /* + 4: use + */ + else if(action == 4) + { + ItemStack item = playersao->getWieldedItem(); + + actionstream<getName()<<" uses "<item_OnUse( + item, playersao, pointed)) + { + // Apply returned ItemStack + playersao->setWieldedItem(item); + } + + } // action == 4 + + + /* + Catch invalid actions + */ + else + { + infostream<<"WARNING: Server: Invalid action " + <::iterator i = + m_playing_sounds.find(id); + if(i == m_playing_sounds.end()) + continue; + ServerPlayingSound &psound = i->second; + psound.clients.erase(peer_id); + if(psound.clients.empty()) + m_playing_sounds.erase(i++); + } + } + else if(command == TOSERVER_NODEMETA_FIELDS) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + v3s16 p = readV3S16(is); + std::string formname = deSerializeString(is); + int num = readU16(is); + std::map fields; + for(int k=0; kgetName()); + + // Check the target node for rollback data; leave others unnoticed + RollbackNode rn_old(&m_env->getMap(), p, this); + + m_script->node_on_receive_fields(p, formname, fields,playersao); + + // Report rollback data + RollbackNode rn_new(&m_env->getMap(), p, this); + if(rollback() && rn_new != rn_old){ + RollbackAction action; + action.setSetNode(p, rn_old, rn_new); + rollback()->reportAction(action); + } + } + else if(command == TOSERVER_INVENTORY_FIELDS) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + std::string formname = deSerializeString(is); + int num = readU16(is); + std::map fields; + for(int k=0; kon_playerReceiveFields(playersao, formname, fields); + } + else + { + infostream<<"Server::ProcessData(): Ignoring " + "unknown command "<getArea())) return; MapEditEvent *e = event->clone(); - m_unsent_map_edit_queue.push(e); + m_unsent_map_edit_queue.push_back(e); } Inventory* Server::getInventory(const InventoryLocation &loc) { - switch (loc.type) { + switch(loc.type){ case InventoryLocation::UNDEFINED: + {} + break; case InventoryLocation::CURRENT_PLAYER: - break; + {} + break; case InventoryLocation::PLAYER: { Player *player = m_env->getPlayer(loc.name.c_str()); @@ -1289,7 +2781,7 @@ Inventory* Server::getInventory(const InventoryLocation &loc) return NULL; return playersao->getInventory(); } - break; + break; case InventoryLocation::NODEMETA: { NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p); @@ -1297,17 +2789,16 @@ Inventory* Server::getInventory(const InventoryLocation &loc) return NULL; return meta->getInventory(); } - break; + break; case InventoryLocation::DETACHED: { if(m_detached_inventories.count(loc.name) == 0) return NULL; return m_detached_inventories[loc.name]; } - break; + break; default: assert(0); - break; } return NULL; } @@ -1315,7 +2806,8 @@ void Server::setInventoryModified(const InventoryLocation &loc) { switch(loc.type){ case InventoryLocation::UNDEFINED: - break; + {} + break; case InventoryLocation::PLAYER: { Player *player = m_env->getPlayer(loc.name.c_str()); @@ -1324,10 +2816,10 @@ void Server::setInventoryModified(const InventoryLocation &loc) PlayerSAO *playersao = player->getPlayerSAO(); if(!playersao) return; - - SendInventory(playersao); + playersao->m_inventory_not_sent = true; + playersao->m_wielded_item_not_sent = true; } - break; + break; case InventoryLocation::NODEMETA: { v3s16 blockpos = getNodeBlockPos(loc.p); @@ -1338,28 +2830,29 @@ void Server::setInventoryModified(const InventoryLocation &loc) setBlockNotSent(blockpos); } - break; + break; case InventoryLocation::DETACHED: { sendDetachedInventory(loc.name,PEER_ID_INEXISTENT); } - break; + break; default: assert(0); - break; } } void Server::SetBlocksNotSent(std::map& block) { - std::vector clients = m_clients.getClientIDs(); + std::list clients = m_clients.getClientIDs(); m_clients.Lock(); // Set the modified blocks unsent for all the clients - for (std::vector::iterator i = clients.begin(); + for (std::list::iterator + i = clients.begin(); i != clients.end(); ++i) { - if (RemoteClient *client = m_clients.lockedGetClientNoEx(*i)) + RemoteClient *client = m_clients.lockedGetClientNoEx(*i); + if (client != NULL) client->SetBlocksNotSent(block); - } + } m_clients.Unlock(); } @@ -1373,7 +2866,7 @@ void Server::peerAdded(con::Peer *peer) c.type = con::PEER_ADDED; c.peer_id = peer->id; c.timeout = false; - m_peer_change_queue.push(c); + m_peer_change_queue.push_back(c); } void Server::deletingPeer(con::Peer *peer, bool timeout) @@ -1387,7 +2880,7 @@ void Server::deletingPeer(con::Peer *peer, bool timeout) c.type = con::PEER_REMOVED; c.peer_id = peer->id; c.timeout = timeout; - m_peer_change_queue.push(c); + m_peer_change_queue.push_back(c); } bool Server::getClientConInfo(u16 peer_id, con::rtt_stat_type type, float* retval) @@ -1436,8 +2929,7 @@ void Server::handlePeerChanges() { while(m_peer_change_queue.size() > 0) { - con::PeerChange c = m_peer_change_queue.front(); - m_peer_change_queue.pop(); + con::PeerChange c = m_peer_change_queue.pop_front(); verbosestream<<"Server: Handling peer change: " <<"id="<getFloat("movement_acceleration_air")); + writeF1000(os, g_settings->getFloat("movement_acceleration_fast")); + writeF1000(os, g_settings->getFloat("movement_speed_walk")); + writeF1000(os, g_settings->getFloat("movement_speed_crouch")); + writeF1000(os, g_settings->getFloat("movement_speed_fast")); + writeF1000(os, g_settings->getFloat("movement_speed_climb")); + writeF1000(os, g_settings->getFloat("movement_speed_jump")); + writeF1000(os, g_settings->getFloat("movement_liquid_fluidity")); + writeF1000(os, g_settings->getFloat("movement_liquid_fluidity_smooth")); + writeF1000(os, g_settings->getFloat("movement_liquid_sink")); + writeF1000(os, g_settings->getFloat("movement_gravity")); - *pkt << g_settings->getFloat("movement_acceleration_default"); - *pkt << g_settings->getFloat("movement_acceleration_air"); - *pkt << g_settings->getFloat("movement_acceleration_fast"); - *pkt << g_settings->getFloat("movement_speed_walk"); - *pkt << g_settings->getFloat("movement_speed_crouch"); - *pkt << g_settings->getFloat("movement_speed_fast"); - *pkt << g_settings->getFloat("movement_speed_climb"); - *pkt << g_settings->getFloat("movement_speed_jump"); - *pkt << g_settings->getFloat("movement_liquid_fluidity"); - *pkt << g_settings->getFloat("movement_liquid_fluidity_smooth"); - *pkt << g_settings->getFloat("movement_liquid_sink"); - *pkt << g_settings->getFloat("movement_gravity"); - - Send(pkt); + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + m_clients.send(peer_id, 0, data, true); } void Server::SendHP(u16 peer_id, u8 hp) { DSTACK(__FUNCTION_NAME); + std::ostringstream os(std::ios_base::binary); - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_HP, 1, peer_id); - *pkt << hp; - Send(pkt); + writeU16(os, TOCLIENT_HP); + writeU8(os, hp); + + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + m_clients.send(peer_id, 0, data, true); } void Server::SendBreath(u16 peer_id, u16 breath) { DSTACK(__FUNCTION_NAME); + std::ostringstream os(std::ios_base::binary); - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_BREATH, 2, peer_id); - *pkt << (u16) breath; - Send(pkt); + writeU16(os, TOCLIENT_BREATH); + writeU16(os, breath); + + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + m_clients.send(peer_id, 0, data, true); } void Server::SendAccessDenied(u16 peer_id,const std::wstring &reason) { DSTACK(__FUNCTION_NAME); + std::ostringstream os(std::ios_base::binary); - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ACCESS_DENIED, 0, peer_id); - *pkt << reason; - Send(pkt); + writeU16(os, TOCLIENT_ACCESS_DENIED); + os< data((u8*)s.c_str(), s.size()); + // Send as reliable + m_clients.send(peer_id, 0, data, true); } void Server::SendDeathscreen(u16 peer_id,bool set_camera_point_target, v3f camera_point_target) { DSTACK(__FUNCTION_NAME); + std::ostringstream os(std::ios_base::binary); - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_DEATHSCREEN, 1 + sizeof(v3f), peer_id); - *pkt << set_camera_point_target << camera_point_target; - Send(pkt); + writeU16(os, TOCLIENT_DEATHSCREEN); + writeU8(os, set_camera_point_target); + writeV3F1000(os, camera_point_target); + + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + m_clients.send(peer_id, 0, data, true); } void Server::SendItemDef(u16 peer_id, IItemDefManager *itemdef, u16 protocol_version) { DSTACK(__FUNCTION_NAME); - - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ITEMDEF, 0, peer_id); + std::ostringstream os(std::ios_base::binary); /* u16 command u32 length of the next item zlib-compressed serialized ItemDefManager */ + writeU16(os, TOCLIENT_ITEMDEF); std::ostringstream tmp_os(std::ios::binary); itemdef->serialize(tmp_os, protocol_version); std::ostringstream tmp_os2(std::ios::binary); compressZlib(tmp_os.str(), tmp_os2); - pkt->putLongString(tmp_os2.str()); + os<readDamage(), playersao->getHP()); ActiveObjectMessage aom(playersao->getId(), true, str); - playersao->m_messages_out.push(aom); + playersao->m_messages_out.push_back(aom); } void Server::SendPlayerBreath(u16 peer_id) @@ -1824,8 +3476,8 @@ void Server::SendPlayerBreath(u16 peer_id) DSTACK(__FUNCTION_NAME); PlayerSAO *playersao = getPlayerSAO(peer_id); assert(playersao); - - m_script->player_event(playersao, "breath_changed"); + playersao->m_breath_not_sent = false; + m_script->player_event(playersao,"breath_changed"); SendBreath(peer_id, playersao->getBreath()); } @@ -1835,8 +3487,11 @@ void Server::SendMovePlayer(u16 peer_id) Player *player = m_env->getPlayer(peer_id); assert(player); - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_MOVE_PLAYER, 0, peer_id); - *pkt << player->getPosition() << player->getPitch() << player->getYaw(); + std::ostringstream os(std::ios_base::binary); + writeU16(os, TOCLIENT_MOVE_PLAYER); + writeV3F1000(os, player->getPosition()); + writeF1000(os, player->getPitch()); + writeF1000(os, player->getYaw()); { v3f pos = player->getPosition(); @@ -1849,25 +3504,44 @@ void Server::SendMovePlayer(u16 peer_id) < data((u8*)s.c_str(), s.size()); + // Send as reliable + m_clients.send(peer_id, 0, data, true); } void Server::SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed) { - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0, - peer_id); + std::ostringstream os(std::ios_base::binary); - *pkt << animation_frames[0] << animation_frames[1] << animation_frames[2] - << animation_frames[3] << animation_speed; + writeU16(os, TOCLIENT_LOCAL_PLAYER_ANIMATIONS); + writeV2S32(os, animation_frames[0]); + writeV2S32(os, animation_frames[1]); + writeV2S32(os, animation_frames[2]); + writeV2S32(os, animation_frames[3]); + writeF1000(os, animation_speed); - Send(pkt); + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8 *)s.c_str(), s.size()); + // Send as reliable + m_clients.send(peer_id, 0, data, true); } void Server::SendEyeOffset(u16 peer_id, v3f first, v3f third) { - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_EYE_OFFSET, 0, peer_id); - *pkt << first << third; - Send(pkt); + std::ostringstream os(std::ios_base::binary); + + writeU16(os, TOCLIENT_EYE_OFFSET); + writeV3F1000(os, first); + writeV3F1000(os, third); + + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8 *)s.c_str(), s.size()); + // Send as reliable + m_clients.send(peer_id, 0, data, true); } void Server::SendPlayerPrivileges(u16 peer_id) { @@ -1879,15 +3553,19 @@ void Server::SendPlayerPrivileges(u16 peer_id) std::set privs; m_script->getAuth(player->getName(), NULL, &privs); - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_PRIVILEGES, 0, peer_id); - *pkt << (u16) privs.size(); - + std::ostringstream os(std::ios_base::binary); + writeU16(os, TOCLIENT_PRIVILEGES); + writeU16(os, privs.size()); for(std::set::const_iterator i = privs.begin(); - i != privs.end(); i++) { - *pkt << (*i); + i != privs.end(); i++){ + os< data((u8*)s.c_str(), s.size()); + // Send as reliable + m_clients.send(peer_id, 0, data, true); } void Server::SendPlayerInventoryFormspec(u16 peer_id) @@ -1897,9 +3575,15 @@ void Server::SendPlayerInventoryFormspec(u16 peer_id) if(player->peer_id == PEER_ID_INEXISTENT) return; - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id); - pkt->putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec); - Send(pkt); + std::ostringstream os(std::ios_base::binary); + writeU16(os, TOCLIENT_INVENTORY_FORMSPEC); + os<inventory_formspec); + + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + m_clients.send(peer_id, 0, data, true); } s32 Server::playSound(const SimpleSoundSpec &spec, @@ -1913,7 +3597,7 @@ s32 Server::playSound(const SimpleSoundSpec &spec, return -1; // Filter destination clients - std::vector dst_clients; + std::list dst_clients; if(params.to_player != "") { Player *player = m_env->getPlayer(params.to_player.c_str()); @@ -1929,16 +3613,17 @@ s32 Server::playSound(const SimpleSoundSpec &spec, } dst_clients.push_back(player->peer_id); } - else { - std::vector clients = m_clients.getClientIDs(); + else + { + std::list clients = m_clients.getClientIDs(); - for(std::vector::iterator - i = clients.begin(); i != clients.end(); ++i) { + for(std::list::iterator + i = clients.begin(); i != clients.end(); ++i) + { Player *player = m_env->getPlayer(*i); if(!player) continue; - - if(pos_exists) { + if(pos_exists){ if(player->getPosition().getDistanceFrom(pos) > params.max_hear_distance) continue; @@ -1946,7 +3631,6 @@ s32 Server::playSound(const SimpleSoundSpec &spec, dst_clients.push_back(*i); } } - if(dst_clients.empty()) return -1; @@ -1956,17 +3640,28 @@ s32 Server::playSound(const SimpleSoundSpec &spec, m_playing_sounds[id] = ServerPlayingSound(); ServerPlayingSound &psound = m_playing_sounds[id]; psound.params = params; - - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_PLAY_SOUND, 0); - *pkt << id << spec.name << (float) (spec.gain * params.gain) - << (u8) params.type << pos << params.object << params.loop; - - for(std::vector::iterator i = dst_clients.begin(); - i != dst_clients.end(); i++) { + for(std::list::iterator i = dst_clients.begin(); + i != dst_clients.end(); i++) psound.clients.insert(*i); - m_clients.send(*i, 0, pkt, true, false); + // Create packet + std::ostringstream os(std::ios_base::binary); + writeU16(os, TOCLIENT_PLAY_SOUND); + writeS32(os, id); + os< data((u8*)s.c_str(), s.size()); + // Send + for(std::list::iterator i = dst_clients.begin(); + i != dst_clients.end(); i++){ + // Send as reliable + m_clients.send(*i, 0, data, true); } - delete pkt; return id; } void Server::stopSound(s32 handle) @@ -1977,38 +3672,52 @@ void Server::stopSound(s32 handle) if(i == m_playing_sounds.end()) return; ServerPlayingSound &psound = i->second; - - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_STOP_SOUND, 4); - *pkt << handle; - + // Create packet + std::ostringstream os(std::ios_base::binary); + writeU16(os, TOCLIENT_STOP_SOUND); + writeS32(os, handle); + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send for(std::set::iterator i = psound.clients.begin(); - i != psound.clients.end(); i++) { + i != psound.clients.end(); i++){ // Send as reliable - m_clients.send(*i, 0, pkt, true, false); + m_clients.send(*i, 0, data, true); } - delete pkt; // Remove sound reference m_playing_sounds.erase(i); } void Server::sendRemoveNode(v3s16 p, u16 ignore_id, - std::vector *far_players, float far_d_nodes) + std::list *far_players, float far_d_nodes) { float maxd = far_d_nodes*BS; v3f p_f = intToFloat(p, BS); - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_REMOVENODE, 6); - *pkt << p; + // Create packet + u32 replysize = 8; + SharedBuffer reply(replysize); + writeU16(&reply[0], TOCLIENT_REMOVENODE); + writeS16(&reply[2], p.X); + writeS16(&reply[4], p.Y); + writeS16(&reply[6], p.Z); - std::vector clients = m_clients.getClientIDs(); - for(std::vector::iterator i = clients.begin(); - i != clients.end(); ++i) { - if (far_players) { + std::list clients = m_clients.getClientIDs(); + for(std::list::iterator + i = clients.begin(); + i != clients.end(); ++i) + { + if(far_players) + { // Get player - if(Player *player = m_env->getPlayer(*i)) { + Player *player = m_env->getPlayer(*i); + if(player) + { // If player is far away, only set modified blocks not sent v3f player_pos = player->getPosition(); - if(player_pos.getDistanceFrom(p_f) > maxd) { + if(player_pos.getDistanceFrom(p_f) > maxd) + { far_players->push_back(*i); continue; } @@ -2016,41 +3725,53 @@ void Server::sendRemoveNode(v3s16 p, u16 ignore_id, } // Send as reliable - m_clients.send(*i, 0, pkt, true, false); + m_clients.send(*i, 0, reply, true); } - // This loop needs the deletion of the packet here - delete pkt; } void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id, - std::vector *far_players, float far_d_nodes, + std::list *far_players, float far_d_nodes, bool remove_metadata) { float maxd = far_d_nodes*BS; v3f p_f = intToFloat(p, BS); - std::vector clients = m_clients.getClientIDs(); - for(std::vector::iterator i = clients.begin(); - i != clients.end(); ++i) { + std::list clients = m_clients.getClientIDs(); + for(std::list::iterator + i = clients.begin(); + i != clients.end(); ++i) + { - if(far_players) { + if(far_players) + { // Get player - if(Player *player = m_env->getPlayer(*i)) { + Player *player = m_env->getPlayer(*i); + if(player) + { // If player is far away, only set modified blocks not sent v3f player_pos = player->getPosition(); - if(player_pos.getDistanceFrom(p_f) > maxd) { + if(player_pos.getDistanceFrom(p_f) > maxd) + { far_players->push_back(*i); continue; } } } - - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1); + SharedBuffer reply(0); m_clients.Lock(); RemoteClient* client = m_clients.lockedGetClientNoEx(*i); - if (client != 0) { - *pkt << p << n.param0 << n.param1 << n.param2 - << (u8) (remove_metadata ? 0 : 1); + if (client != 0) + { + // Create packet + u32 replysize = 9 + MapNode::serializedLength(client->serialization_version); + reply = SharedBuffer(replysize); + writeU16(&reply[0], TOCLIENT_ADDNODE); + writeS16(&reply[2], p.X); + writeS16(&reply[4], p.Y); + writeS16(&reply[6], p.Z); + n.serialize(&reply[8], client->serialization_version); + u32 index = 8 + MapNode::serializedLength(client->serialization_version); + writeU8(&reply[index], remove_metadata ? 0 : 1); if (!remove_metadata) { if (client->net_proto_version <= 21) { @@ -2063,17 +3784,19 @@ void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id, m_clients.Unlock(); // Send as reliable - if (pkt->getSize() > 0) - m_clients.send(*i, 0, pkt, true); + if (reply.getSize() > 0) + m_clients.send(*i, 0, reply, true); } } void Server::setBlockNotSent(v3s16 p) { - std::vector clients = m_clients.getClientIDs(); + std::list clients = m_clients.getClientIDs(); m_clients.Lock(); - for(std::vector::iterator i = clients.begin(); - i != clients.end(); ++i) { + for(std::list::iterator + i = clients.begin(); + i != clients.end(); ++i) + { RemoteClient *client = m_clients.lockedGetClientNoEx(*i); client->SetBlockNotSent(p); } @@ -2086,6 +3809,27 @@ void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto v3s16 p = block->getPos(); +#if 0 + // Analyze it a bit + bool completely_air = true; + for(s16 z0=0; z0getNodeNoEx(v3s16(x0,y0,z0)).d != CONTENT_AIR) + { + completely_air = false; + x0 = y0 = z0 = MAP_BLOCKSIZE; // Break out + } + } + + // Print result + infostream<<"Server: Sending block ("<serialize(os, ver, false); block->serializeNetworkSpecific(os, net_proto_version); std::string s = os.str(); + SharedBuffer blockdata((u8*)s.c_str(), s.size()); - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_BLOCKDATA, - 2 + 2 + 2 + 2 + s.size(), peer_id); + u32 replysize = 8 + blockdata.getSize(); + SharedBuffer reply(replysize); + writeU16(&reply[0], TOCLIENT_BLOCKDATA); + writeS16(&reply[2], p.X); + writeS16(&reply[4], p.Y); + writeS16(&reply[6], p.Z); + memcpy(&reply[8], *blockdata, blockdata.getSize()); - *pkt << p; - pkt->putRawString(s.c_str(), s.size()); - Send(pkt); + /*infostream<<"Server: Sending block ("< clients = m_clients.getClientIDs(); + std::list clients = m_clients.getClientIDs(); m_clients.Lock(); - for(std::vector::iterator i = clients.begin(); - i != clients.end(); ++i) { + for(std::list::iterator + i = clients.begin(); + i != clients.end(); ++i) + { RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active); if (client == NULL) @@ -2180,9 +3936,9 @@ void Server::fillMediaCache() infostream<<"Server: Calculating media file checksums"< paths; + std::list paths; for(std::vector::iterator i = m_mods.begin(); - i != m_mods.end(); i++) { + i != m_mods.end(); i++){ const ModSpec &mod = *i; paths.push_back(mod.path + DIR_DELIM + "textures"); paths.push_back(mod.path + DIR_DELIM + "sounds"); @@ -2192,18 +3948,19 @@ void Server::fillMediaCache() paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server"); // Collect media file information from paths into cache - for(std::vector::iterator i = paths.begin(); - i != paths.end(); i++) { + for(std::list::iterator i = paths.begin(); + i != paths.end(); i++) + { std::string mediapath = *i; std::vector dirlist = fs::GetDirListing(mediapath); - for (u32 j = 0; j < dirlist.size(); j++) { - if (dirlist[j].dir) // Ignode dirs + for(u32 j=0; jm_media[filename] = MediaInfo(filepath, sha1_base64); + verbosestream<<"Server: "< file_announcements; + std::list file_announcements; - for (std::map::iterator i = m_media.begin(); + for(std::map::iterator i = m_media.begin(); i != m_media.end(); i++){ // Put in list file_announcements.push_back( @@ -2301,6 +4057,7 @@ void Server::sendMediaAnnouncement(u16 peer_id) std::ostringstream os(std::ios_base::binary); /* + u16 command u32 number of files for each texture { u16 length of name @@ -2310,17 +4067,23 @@ void Server::sendMediaAnnouncement(u16 peer_id) } */ - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id); - *pkt << (u16) file_announcements.size(); + writeU16(os, TOCLIENT_ANNOUNCE_MEDIA); + writeU16(os, file_announcements.size()); - for (std::vector::iterator + for(std::list::iterator j = file_announcements.begin(); - j != file_announcements.end(); ++j) { - *pkt << j->name << j->sha1_digest; + j != file_announcements.end(); ++j){ + os<name); + os<sha1_digest); } + os<get("remote_media")); - *pkt << g_settings->get("remote_media"); - Send(pkt); + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + + // Send as reliable + m_clients.send(peer_id, 0, data, true); } struct SendableMedia @@ -2338,7 +4101,7 @@ struct SendableMedia }; void Server::sendRequestedMedia(u16 peer_id, - const std::vector &tosend) + const std::list &tosend) { DSTACK(__FUNCTION_NAME); @@ -2350,16 +4113,17 @@ void Server::sendRequestedMedia(u16 peer_id, // Put 5kB in one bunch (this is not accurate) u32 bytes_per_bunch = 5000; - std::vector< std::vector > file_bunches; - file_bunches.push_back(std::vector()); + std::vector< std::list > file_bunches; + file_bunches.push_back(std::list()); u32 file_size_bunch_total = 0; - for(std::vector::const_iterator i = tosend.begin(); - i != tosend.end(); ++i) { + for(std::list::const_iterator i = tosend.begin(); + i != tosend.end(); ++i) + { const std::string &name = *i; - if(m_media.find(name) == m_media.end()) { + if(m_media.find(name) == m_media.end()){ errorstream<<"Server::sendRequestedMedia(): Client asked for " <<"unknown file \""<<(name)<<"\""<= bytes_per_bunch) { - file_bunches.push_back(std::vector()); + if(file_size_bunch_total >= bytes_per_bunch){ + file_bunches.push_back(std::list()); file_size_bunch_total = 0; } @@ -2411,8 +4175,11 @@ void Server::sendRequestedMedia(u16 peer_id, /* Create and send packets */ - u16 num_bunches = file_bunches.size(); - for(u16 i = 0; i < num_bunches; i++) { + u32 num_bunches = file_bunches.size(); + for(u32 i=0; i::iterator + for(std::list::iterator j = file_bunches[i].begin(); - j != file_bunches[i].end(); ++j) { - *pkt << j->name; - pkt->putLongString(j->data); + j != file_bunches[i].end(); ++j){ + os<name); + os<data); } - verbosestream << "Server::sendRequestedMedia(): bunch " - << i << "/" << num_bunches - << " files=" << file_bunches[i].size() - << " size=" << pkt->getSize() << std::endl; - Send(pkt); + // Make data buffer + std::string s = os.str(); + verbosestream<<"Server::sendRequestedMedia(): bunch " + <serialize(os); // Make data buffer std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); - NetworkPacket* pkt = new NetworkPacket(TOCLIENT_DETACHED_INVENTORY, 0, peer_id); - pkt->putRawString(s.c_str(), s.size()); - - if (peer_id != PEER_ID_INEXISTENT) { - Send(pkt); + if (peer_id != PEER_ID_INEXISTENT) + { + // Send as reliable + m_clients.send(peer_id, 0, data, true); } - else { - m_clients.sendToAll(0, pkt, true); + else + { + m_clients.sendToAll(0,data,true); } } @@ -2476,7 +4251,7 @@ void Server::sendDetachedInventories(u16 peer_id) for(std::map::iterator i = m_detached_inventories.begin(); - i != m_detached_inventories.end(); i++) { + i != m_detached_inventories.end(); i++){ const std::string &name = i->first; //Inventory *inv = i->second; sendDetachedInventory(name, peer_id); @@ -2494,9 +4269,9 @@ void Server::DiePlayer(u16 peer_id) PlayerSAO *playersao = getPlayerSAO(peer_id); assert(playersao); - infostream << "Server::DiePlayer(): Player " - << playersao->getPlayer()->getName() - << " dies" << std::endl; + infostream<<"Server::DiePlayer(): Player " + <getPlayer()->getName() + <<" dies"<setHP(0); @@ -2514,20 +4289,16 @@ void Server::RespawnPlayer(u16 peer_id) PlayerSAO *playersao = getPlayerSAO(peer_id); assert(playersao); - infostream << "Server::RespawnPlayer(): Player " - << playersao->getPlayer()->getName() - << " respawns" << std::endl; + infostream<<"Server::RespawnPlayer(): Player " + <getPlayer()->getName() + <<" respawns"<setHP(PLAYER_MAX_HP); playersao->setBreath(PLAYER_MAX_BREATH); - SendPlayerHP(peer_id); - SendPlayerBreath(peer_id); - bool repositioned = m_script->on_respawnplayer(playersao); if(!repositioned){ v3f pos = findSpawnPos(m_env->getServerMap()); - // setPos will send the new position to client playersao->setPos(pos); } } @@ -2593,24 +4364,26 @@ void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason) Print out action */ { - if(player != NULL && reason != CDR_DENY) { + if(player != NULL && reason != CDR_DENY) + { std::ostringstream os(std::ios_base::binary); - std::vector clients = m_clients.getClientIDs(); + std::list clients = m_clients.getClientIDs(); - for(std::vector::iterator i = clients.begin(); - i != clients.end(); ++i) { + for(std::list::iterator + i = clients.begin(); + i != clients.end(); ++i) + { // Get player Player *player = m_env->getPlayer(*i); if(!player) continue; - // Get name of player - os << player->getName() << " "; + os<getName()<<" "; } - actionstream << player->getName() << " " - << (reason == CDR_TIMEOUT ? "times out." : "leaves game.") - << " List of players: " << os.str() << std::endl; + actionstream<getName()<<" " + <<(reason==CDR_TIMEOUT?"times out.":"leaves game.") + <<" List of players: "<getPlayer(peer_id); + assert(player); + // Get a preview for crafting ItemStack preview; InventoryLocation loc; @@ -2684,9 +4460,10 @@ std::wstring Server::getStatusString() // Information about clients bool first = true; os< clients = m_clients.getClientIDs(); - for(std::vector::iterator i = clients.begin(); - i != clients.end(); ++i) { + std::list clients = m_clients.getClientIDs(); + for(std::list::iterator i = clients.begin(); + i != clients.end(); ++i) + { // Get player Player *player = m_env->getPlayer(*i); // Get name of player @@ -2695,12 +4472,12 @@ std::wstring Server::getStatusString() name = narrow_to_wide(player->getName()); // Add name to information string if(!first) - os << L", "; + os<getMap()))->isSavingEnabled() == false) os<get("motd") != "") @@ -2723,10 +4500,11 @@ bool Server::checkPriv(const std::string &name, const std::string &priv) void Server::reportPrivsModified(const std::string &name) { - if(name == "") { - std::vector clients = m_clients.getClientIDs(); - for(std::vector::iterator i = clients.begin(); - i != clients.end(); ++i) { + if(name == ""){ + std::list clients = m_clients.getClientIDs(); + for(std::list::iterator + i = clients.begin(); + i != clients.end(); ++i){ Player *player = m_env->getPlayer(*i); reportPrivsModified(player->getName()); } @@ -3161,9 +4939,10 @@ const ModSpec* Server::getModSpec(const std::string &modname) } return NULL; } -void Server::getModNames(std::vector &modlist) +void Server::getModNames(std::list &modlist) { - for(std::vector::iterator i = m_mods.begin(); i != m_mods.end(); i++) { + for(std::vector::iterator i = m_mods.begin(); i != m_mods.end(); i++) + { modlist.push_back(i->name); } } @@ -3231,12 +5010,13 @@ v3f findSpawnPos(ServerMap &map) PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id) { + RemotePlayer *player = NULL; bool newplayer = false; /* Try to get an existing player */ - RemotePlayer *player = static_cast(m_env->getPlayer(name)); + player = static_cast(m_env->getPlayer(name)); // If player is already connected, cancel if(player != NULL && player->peer_id != 0) diff --git a/src/server.h b/src/server.h index ba6c37faa..3d6b00d99 100644 --- a/src/server.h +++ b/src/server.h @@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef SERVER_HEADER #define SERVER_HEADER -#include "network/connection.h" +#include "connection.h" #include "irr_v3d.h" #include "map.h" #include "hud.h" @@ -33,7 +33,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/thread.h" #include "environment.h" #include "clientiface.h" -#include "network/networkpacket.h" #include #include #include @@ -188,39 +187,8 @@ public: void AsyncRunStep(bool initial_step=false); void Receive(); PlayerSAO* StageTwoClientInit(u16 peer_id); - - /* - * Command Handlers - */ - - void handleCommand(NetworkPacket* pkt); - - void handleCommand_Null(NetworkPacket* pkt) {}; - void handleCommand_Deprecated(NetworkPacket* pkt); - void handleCommand_Init(NetworkPacket* pkt); - void handleCommand_Init2(NetworkPacket* pkt); - void handleCommand_RequestMedia(NetworkPacket* pkt); - void handleCommand_ReceivedMedia(NetworkPacket* pkt); - void handleCommand_ClientReady(NetworkPacket* pkt); - void handleCommand_GotBlocks(NetworkPacket* pkt); - void handleCommand_PlayerPos(NetworkPacket* pkt); - void handleCommand_DeletedBlocks(NetworkPacket* pkt); - void handleCommand_InventoryAction(NetworkPacket* pkt); - void handleCommand_ChatMessage(NetworkPacket* pkt); - void handleCommand_Damage(NetworkPacket* pkt); - void handleCommand_Breath(NetworkPacket* pkt); - void handleCommand_Password(NetworkPacket* pkt); - void handleCommand_PlayerItem(NetworkPacket* pkt); - void handleCommand_Respawn(NetworkPacket* pkt); - void handleCommand_Interact(NetworkPacket* pkt); - void handleCommand_RemovedSounds(NetworkPacket* pkt); - void handleCommand_NodeMetaFields(NetworkPacket* pkt); - void handleCommand_InventoryFields(NetworkPacket* pkt); - void ProcessData(u8 *data, u32 datasize, u16 peer_id); - void Send(NetworkPacket* pkt); - // Environment must be locked when called void setTimeOfDay(u32 time); @@ -327,7 +295,7 @@ public: IWritableCraftDefManager* getWritableCraftDefManager(); const ModSpec* getModSpec(const std::string &modname); - void getModNames(std::vector &modlist); + void getModNames(std::list &modlist); std::string getBuiltinLuaPath(); inline std::string getWorldPath() { return m_path_world; } @@ -341,7 +309,7 @@ public: bool showFormspec(const char *name, const std::string &formspec, const std::string &formname); Map & getMap() { return m_env->getMap(); } ServerEnvironment & getEnv() { return *m_env; } - + u32 hudAdd(Player *player, HudElement *element); bool hudRemove(Player *player, u32 id); bool hudChange(Player *player, u32 id, HudElementStat stat, void *value); @@ -352,13 +320,13 @@ public: inline Address getPeerAddress(u16 peer_id) { return m_con.GetPeerAddress(peer_id); } - + bool setLocalPlayerAnimations(Player *player, v2s32 animation_frames[4], f32 frame_speed); bool setPlayerEyeOffset(Player *player, v3f first, v3f third); bool setSky(Player *player, const video::SColor &bgcolor, const std::string &type, const std::vector ¶ms); - + bool overrideDayNightRatio(Player *player, bool do_override, float brightness); @@ -372,11 +340,6 @@ public: u8* ser_vers, u16* prot_vers, u8* major, u8* minor, u8* patch, std::string* vers_string); - void SendPlayerHPOrDie(u16 peer_id, bool die) { die ? DiePlayer(peer_id) : SendPlayerHP(peer_id); } - void SendPlayerBreath(u16 peer_id); - void SendInventory(PlayerSAO* playerSAO); - void SendMovePlayer(u16 peer_id); - // Bind address Address m_bind_addr; @@ -396,11 +359,13 @@ private: /* mark blocks not sent for all clients */ void SetBlocksNotSent(std::map& block); - + // Envlock and conlock should be locked when calling these + void SendInventory(u16 peer_id); void SendChatMessage(u16 peer_id, const std::wstring &message); void SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed); void SendPlayerHP(u16 peer_id); - + void SendPlayerBreath(u16 peer_id); + void SendMovePlayer(u16 peer_id); void SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed); void SendEyeOffset(u16 peer_id, v3f first, v3f third); void SendPlayerPrivileges(u16 peer_id); @@ -414,7 +379,7 @@ private: void SendSetSky(u16 peer_id, const video::SColor &bgcolor, const std::string &type, const std::vector ¶ms); void SendOverrideDayNightRatio(u16 peer_id, bool do_override, float ratio); - + /* Send a node removal/addition event to all clients except ignore_id. Additionally, if far_players!=NULL, players further away than @@ -422,9 +387,9 @@ private: */ // Envlock and conlock should be locked when calling these void sendRemoveNode(v3s16 p, u16 ignore_id=0, - std::vector *far_players=NULL, float far_d_nodes=100); + std::list *far_players=NULL, float far_d_nodes=100); void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0, - std::vector *far_players=NULL, float far_d_nodes=100, + std::list *far_players=NULL, float far_d_nodes=100, bool remove_metadata=true); void setBlockNotSent(v3s16 p); @@ -437,7 +402,7 @@ private: void fillMediaCache(); void sendMediaAnnouncement(u16 peer_id); void sendRequestedMedia(u16 peer_id, - const std::vector &tosend); + const std::list &tosend); void sendDetachedInventory(const std::string &name, u16 peer_id); void sendDetachedInventories(u16 peer_id); @@ -466,7 +431,7 @@ private: void DiePlayer(u16 peer_id); void RespawnPlayer(u16 peer_id); void DeleteClient(u16 peer_id, ClientDeletionReason reason); - void UpdateCrafting(Player *player); + void UpdateCrafting(u16 peer_id); // When called, connection mutex should be locked RemoteClient* getClient(u16 peer_id,ClientState state_min=CS_Active); @@ -582,12 +547,15 @@ private: Queues stuff from peerAdded() and deletingPeer() to handlePeerChanges() */ - std::queue m_peer_change_queue; + Queue m_peer_change_queue; /* Random stuff */ + // Mod parent directory paths + std::list m_modspaths; + bool m_shutdown_requested; /* @@ -603,7 +571,7 @@ private: Queue of map edits from the environment for sending to the clients This is behind m_env_mutex */ - std::queue m_unsent_map_edit_queue; + Queue m_unsent_map_edit_queue; /* Set to true when the server itself is modifying the map and does all sending of information by itself. diff --git a/src/serverlist.cpp b/src/serverlist.cpp index a3353340e..472a6b85c 100644 --- a/src/serverlist.cpp +++ b/src/serverlist.cpp @@ -28,7 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include "porting.h" #include "log.h" -#include "network/networkprotocol.h" #include "json/json.h" #include "convert_json.h" #include "httpfetch.h" @@ -68,11 +67,8 @@ std::vector getLocal() std::vector getOnline() { - std::ostringstream geturl; - geturl << g_settings->get("serverlist_url") << - "/list?proto_version_min=" << CLIENT_PROTOCOL_VERSION_MIN << - "&proto_version_max=" << CLIENT_PROTOCOL_VERSION_MAX; - Json::Value root = fetchJsonValue(geturl.str(), NULL); + Json::Value root = fetchJsonValue( + (g_settings->get("serverlist_url") + "/list").c_str(), NULL); std::vector server_list; @@ -209,12 +205,9 @@ void sendAnnounce(const std::string &action, server["address"] = g_settings->get("server_address"); } if (action != "delete") { - bool strict_checking = g_settings->getBool("strict_protocol_version_checking"); server["name"] = g_settings->get("server_name"); server["description"] = g_settings->get("server_description"); server["version"] = minetest_version_simple; - server["proto_min"] = strict_checking ? LATEST_PROTOCOL_VERSION : SERVER_PROTOCOL_VERSION_MIN; - server["proto_max"] = strict_checking ? LATEST_PROTOCOL_VERSION : SERVER_PROTOCOL_VERSION_MAX; server["url"] = g_settings->get("server_url"); server["creative"] = g_settings->getBool("creative_mode"); server["damage"] = g_settings->getBool("enable_damage"); diff --git a/src/serverobject.cpp b/src/serverobject.cpp index 699040bf2..81307bc34 100644 --- a/src/serverobject.cpp +++ b/src/serverobject.cpp @@ -38,19 +38,15 @@ ServerActiveObject::~ServerActiveObject() { } -ServerActiveObject* ServerActiveObject::create(ActiveObjectType type, +ServerActiveObject* ServerActiveObject::create(u8 type, ServerEnvironment *env, u16 id, v3f pos, const std::string &data) { // Find factory function std::map::iterator n; n = m_types.find(type); - if(n == m_types.end()) { - // These are 0.3 entity types, return without error. - if (ACTIVEOBJECT_TYPE_ITEM <= type && type <= ACTIVEOBJECT_TYPE_MOBV2) { - return NULL; - } - + if(n == m_types.end()) + { // If factory is not found, just return. dstream<<"WARNING: ServerActiveObject: No factory for type=" <getList(getWieldList())) { + Inventory *inv = getInventory(); + if(inv) + { + InventoryList *list = inv->getList(getWieldList()); + if (list) + { list->changeItem(getWieldIndex(), item); + setInventoryModified(); return true; } } diff --git a/src/serverobject.h b/src/serverobject.h index 5c4d13e3b..8e80225e4 100644 --- a/src/serverobject.h +++ b/src/serverobject.h @@ -58,7 +58,7 @@ public: ServerActiveObject(ServerEnvironment *env, v3f pos); virtual ~ServerActiveObject(); - virtual ActiveObjectType getSendType() const + virtual u8 getSendType() const { return getType(); } // Called after id has been set and has been inserted in environment @@ -71,7 +71,7 @@ public: { return true; } // Create a certain type of ServerActiveObject - static ServerActiveObject* create(ActiveObjectType type, + static ServerActiveObject* create(u8 type, ServerEnvironment *env, u16 id, v3f pos, const std::string &data); @@ -218,7 +218,7 @@ public: /* Queue of messages to be sent to the client */ - std::queue m_messages_out; + Queue m_messages_out; protected: // Used for creating objects based on type diff --git a/src/util/sha1.cpp b/src/sha1.cpp similarity index 100% rename from src/util/sha1.cpp rename to src/sha1.cpp diff --git a/src/util/sha1.h b/src/sha1.h similarity index 100% rename from src/util/sha1.h rename to src/sha1.h diff --git a/src/shader.cpp b/src/shader.cpp index 8c572ed49..167045804 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -36,7 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "gamedef.h" #include "strfnd.h" // trim() -#include "client/tile.h" +#include "tile.h" /* A cache from shader name to shader path diff --git a/src/sky.cpp b/src/sky.cpp index ac8e2cbf6..664ed694b 100644 --- a/src/sky.cpp +++ b/src/sky.cpp @@ -3,7 +3,7 @@ #include "ISceneManager.h" #include "ICameraSceneNode.h" #include "S3DVertex.h" -#include "client/tile.h" +#include "tile.h" #include "noise.h" // easeCurve #include "main.h" // g_profiler #include "profiler.h" diff --git a/src/staticobject.cpp b/src/staticobject.cpp index 2e7d45a47..16d98605b 100644 --- a/src/staticobject.cpp +++ b/src/staticobject.cpp @@ -47,9 +47,10 @@ void StaticObjectList::serialize(std::ostream &os) // count u16 count = m_stored.size() + m_active.size(); writeU16(os, count); - for(std::vector::iterator + for(std::list::iterator i = m_stored.begin(); - i != m_stored.end(); ++i) { + i != m_stored.end(); ++i) + { StaticObject &s_obj = *i; s_obj.serialize(os); } @@ -67,7 +68,8 @@ void StaticObjectList::deSerialize(std::istream &is) u8 version = readU8(is); // count u16 count = readU16(is); - for(u16 i = 0; i < count; i++) { + for(u16 i=0; i #include -#include +#include #include #include "debug.h" @@ -95,7 +95,7 @@ public: from m_stored and inserted to m_active. The caller directly manipulates these containers. */ - std::vector m_stored; + std::list m_stored; std::map m_active; private: diff --git a/src/subgame.cpp b/src/subgame.cpp index ccf477e8f..fd2679eae 100644 --- a/src/subgame.cpp +++ b/src/subgame.cpp @@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "strfnd.h" #ifndef SERVER -#include "client/tile.h" // getImagePath +#include "tile.h" // getImagePath #endif #include "util/string.h" diff --git a/src/test.cpp b/src/test.cpp index 350cab127..80494e07a 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "player.h" #include "main.h" #include "socket.h" -#include "network/connection.h" +#include "connection.h" #include "serialization.h" #include "voxel.h" #include "collision.h" @@ -42,7 +42,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/numeric.h" #include "util/serialize.h" #include "noise.h" // PseudoRandom used for random data for compression -#include "network/networkprotocol.h" // LATEST_PROTOCOL_VERSION +#include "clientserver.h" // LATEST_PROTOCOL_VERSION #include /* @@ -147,45 +147,15 @@ struct TestBase struct TestUtilities: public TestBase { - inline float ref_WrapDegrees180(float f) - { - // This is a slower alternative to the wrapDegrees_180() function; - // used as a reference for testing - float value = fmodf(f + 180, 360); - if (value < 0) - value += 360; - return value - 180; - } - - inline float ref_WrapDegrees_0_360(float f) - { - // This is a slower alternative to the wrapDegrees_0_360() function; - // used as a reference for testing - float value = fmodf(f, 360); - if (value < 0) - value += 360; - return value < 0 ? value + 360 : value; - } - - void Run() { - UASSERT(fabs(modulo360f(100.0) - 100.0) < 0.001); - UASSERT(fabs(modulo360f(720.5) - 0.5) < 0.001); - UASSERT(fabs(modulo360f(-0.5) - (-0.5)) < 0.001); - UASSERT(fabs(modulo360f(-365.5) - (-5.5)) < 0.001); - - for (float f = -720; f <= -360; f += 0.25) { - UASSERT(fabs(modulo360f(f) - modulo360f(f + 360)) < 0.001); - } - - for (float f = -1440; f <= 1440; f += 0.25) { - UASSERT(fabs(modulo360f(f) - fmodf(f, 360)) < 0.001); - UASSERT(fabs(wrapDegrees_180(f) - ref_WrapDegrees180(f)) < 0.001); - UASSERT(fabs(wrapDegrees_0_360(f) - ref_WrapDegrees_0_360(f)) < 0.001); - UASSERT(wrapDegrees_0_360(fabs(wrapDegrees_180(f) - wrapDegrees_0_360(f))) < 0.001); - } - + /*infostream<<"wrapDegrees(100.0) = "<get("bind_address"); - try { - bind_addr.Resolve(bind_str.c_str()); - - if (!bind_addr.isIPv6()) { - address = bind_addr; - } - } catch (ResolveError &e) { - } - // IPv6 socket test - if (g_settings->getBool("enable_ipv6")) { + { UDPSocket socket6; if (!socket6.init(true, true)) { @@ -1754,7 +1709,7 @@ struct TestSocket: public TestBase UASSERT(memcmp(sender.getAddress6().sin6_addr.s6_addr, Address(&bytes, 0).getAddress6().sin6_addr.s6_addr, 16) == 0); } - catch (SendFailedException &e) { + catch (SendFailedException e) { errorstream << "IPv6 support enabled but not available!" << std::endl; } @@ -1767,15 +1722,7 @@ struct TestSocket: public TestBase socket.Bind(address); const char sendbuffer[] = "hello world!"; - /* - * If there is a bind address, use it. - * It's useful in container environments - */ - if (address != Address(0, 0, 0, 0, port)) { - socket.Send(address, sendbuffer, sizeof(sendbuffer)); - } - else - socket.Send(Address(127, 0, 0 ,1, port), sendbuffer, sizeof(sendbuffer)); + socket.Send(Address(127, 0, 0 ,1, port), sendbuffer, sizeof(sendbuffer)); sleep_ms(50); @@ -1787,15 +1734,8 @@ struct TestSocket: public TestBase } //FIXME: This fails on some systems UASSERT(strncmp(sendbuffer, rcvbuffer, sizeof(sendbuffer)) == 0); - - if (address != Address(0, 0, 0, 0, port)) { - UASSERT(sender.getAddress().sin_addr.s_addr == - address.getAddress().sin_addr.s_addr); - } - else { - UASSERT(sender.getAddress().sin_addr.s_addr == - Address(127, 0, 0, 1, 0).getAddress().sin_addr.s_addr); - } + UASSERT(sender.getAddress().sin_addr.s_addr == + Address(127, 0, 0, 1, 0).getAddress().sin_addr.s_addr); } } }; @@ -1895,24 +1835,9 @@ struct TestConnection: public TestBase Handler hand_server("server"); Handler hand_client("client"); - Address address(0, 0, 0, 0, 30001); - Address bind_addr(0, 0, 0, 0, 30001); - /* - * Try to use the bind_address for servers with no localhost address - * For example: FreeBSD jails - */ - std::string bind_str = g_settings->get("bind_address"); - try { - bind_addr.Resolve(bind_str.c_str()); - - if (!bind_addr.isIPv6()) { - address = bind_addr; - } - } catch (ResolveError &e) { - } - infostream<<"** Creating server Connection"< sentdata = pkt->oldForgePacket(); + /*u8 data[] = "Hello World!"; + u32 datasize = sizeof(data);*/ + SharedBuffer data = SharedBufferFromString("Hello World!"); infostream<<"** running client.Send()"< recvdata; - infostream << "** running server.Receive()" << std::endl; + infostream<<"** running server.Receive()"< data1 = SharedBufferFromString("hello1"); + SharedBuffer data2 = SharedBufferFromString("Hello2"); + + Address client_address = + server.GetPeerAddress(peer_id_client); + + infostream<<"*** Sending packets in wrong order (2,1,2)" + <channels[chn]; + u16 sn = ch->next_outgoing_seqnum; + ch->next_outgoing_seqnum = sn+1; + server.Send(peer_id_client, chn, data2, true); + ch->next_outgoing_seqnum = sn; + server.Send(peer_id_client, chn, data1, true); + ch->next_outgoing_seqnum = sn+1; + server.Send(peer_id_client, chn, data2, true); + + sleep_ms(50); + + infostream<<"*** Receiving the packets"< recvdata; + u32 size; + + infostream<<"** running client.Receive()"<getU8Ptr(0))[i])&0xff); + snprintf(buf, 10, "%.2X", ((int)((const char*)*data1)[i])&0xff); infostream<20) infostream<<"..."; infostream< sentdata = pkt->oldForgePacket(); - - server.Send(peer_id_client, 0, pkt, true); + server.Send(peer_id_client, 0, data1, true); //sleep_ms(3000); @@ -2104,10 +2134,8 @@ struct TestConnection: public TestBase infostream<<"..."; infostream< m_texture_trash; + std::list m_texture_trash; // Cached settings needed for making textures from meshes bool m_setting_trilinear_filter; @@ -455,9 +455,10 @@ TextureSource::~TextureSource() } m_textureinfo_cache.clear(); - for (std::vector::iterator iter = + for (std::list::iterator iter = m_texture_trash.begin(); iter != m_texture_trash.end(); - iter++) { + iter++) + { video::ITexture *t = *iter; //cleanup trashed texture diff --git a/src/client/tile.h b/src/tile.h similarity index 100% rename from src/client/tile.h rename to src/tile.h diff --git a/src/touchscreengui.h b/src/touchscreengui.h index a00df5c47..4fe731513 100644 --- a/src/touchscreengui.h +++ b/src/touchscreengui.h @@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "game.h" -#include "client/tile.h" +#include "tile.h" using namespace irr; using namespace irr::core; diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 56bf8a25a..9cb8a19b6 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -1,10 +1,8 @@ set(UTIL_SRCS - ${CMAKE_CURRENT_SOURCE_DIR}/base64.cpp ${CMAKE_CURRENT_SOURCE_DIR}/directiontables.cpp ${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp ${CMAKE_CURRENT_SOURCE_DIR}/serialize.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/sha1.cpp ${CMAKE_CURRENT_SOURCE_DIR}/string.cpp ${CMAKE_CURRENT_SOURCE_DIR}/timetaker.cpp PARENT_SCOPE) diff --git a/src/util/container.h b/src/util/container.h index 7945df54b..5e9f13d88 100644 --- a/src/util/container.h +++ b/src/util/container.h @@ -77,6 +77,7 @@ private: std::queue m_queue; }; +#if 1 template class MutexedMap { @@ -108,9 +109,9 @@ public: return true; } - std::vector getValues() + std::list getValues() { - std::vector result; + std::list result; for(typename std::map::iterator i = m_values.begin(); i != m_values.end(); ++i){ @@ -128,6 +129,7 @@ private: std::map m_values; JMutex m_mutex; }; +#endif /* Generates ids for comparable values. @@ -183,6 +185,67 @@ private: std::map m_value_to_id; }; +/* +FIFO queue (well, actually a FILO also) +*/ +template +class Queue +{ +public: + Queue(): + m_list_size(0) + {} + + void push_back(T t) + { + m_list.push_back(t); + ++m_list_size; + } + + void push_front(T t) + { + m_list.push_front(t); + ++m_list_size; + } + + T pop_front() + { + if(m_list.empty()) + throw ItemNotFoundException("Queue: queue is empty"); + + typename std::list::iterator begin = m_list.begin(); + T t = *begin; + m_list.erase(begin); + --m_list_size; + return t; + } + T pop_back() + { + if(m_list.empty()) + throw ItemNotFoundException("Queue: queue is empty"); + + typename std::list::iterator last = m_list.back(); + T t = *last; + m_list.erase(last); + --m_list_size; + return t; + } + + u32 size() + { + return m_list_size; + } + + bool empty() + { + return m_list.empty(); + } + +protected: + std::list m_list; + u32 m_list_size; +}; + /* Thread-safe FIFO queue (well, actually a FILO also) */ diff --git a/src/util/numeric.cpp b/src/util/numeric.cpp index 19f927134..6173515ee 100644 --- a/src/util/numeric.cpp +++ b/src/util/numeric.cpp @@ -20,84 +20,79 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "numeric.h" #include "mathconstants.h" -#include "log.h" +#include "../log.h" #include "../constants.h" // BS, MAP_BLOCKSIZE #include #include -std::map > FacePositionCache::m_cache; // Calculate the borders of a "d-radius" cube -std::vector FacePositionCache::getFacePositions(u16 d) +void getFacePositions(std::list &list, u16 d) { - if (m_cache.find(d) != m_cache.end()) - return m_cache[d]; - - generateFacePosition(d); - return m_cache[d]; - -} - -void FacePositionCache::generateFacePosition(u16 d) -{ - m_cache[d] = std::vector(); - if(d == 0) { - m_cache[d].push_back(v3s16(0,0,0)); + if(d == 0) + { + list.push_back(v3s16(0,0,0)); return; } - if(d == 1) { + if(d == 1) + { /* This is an optimized sequence of coordinates. */ - m_cache[d].push_back(v3s16( 0, 1, 0)); // top - m_cache[d].push_back(v3s16( 0, 0, 1)); // back - m_cache[d].push_back(v3s16(-1, 0, 0)); // left - m_cache[d].push_back(v3s16( 1, 0, 0)); // right - m_cache[d].push_back(v3s16( 0, 0,-1)); // front - m_cache[d].push_back(v3s16( 0,-1, 0)); // bottom + list.push_back(v3s16( 0, 1, 0)); // top + list.push_back(v3s16( 0, 0, 1)); // back + list.push_back(v3s16(-1, 0, 0)); // left + list.push_back(v3s16( 1, 0, 0)); // right + list.push_back(v3s16( 0, 0,-1)); // front + list.push_back(v3s16( 0,-1, 0)); // bottom // 6 - m_cache[d].push_back(v3s16(-1, 0, 1)); // back left - m_cache[d].push_back(v3s16( 1, 0, 1)); // back right - m_cache[d].push_back(v3s16(-1, 0,-1)); // front left - m_cache[d].push_back(v3s16( 1, 0,-1)); // front right - m_cache[d].push_back(v3s16(-1,-1, 0)); // bottom left - m_cache[d].push_back(v3s16( 1,-1, 0)); // bottom right - m_cache[d].push_back(v3s16( 0,-1, 1)); // bottom back - m_cache[d].push_back(v3s16( 0,-1,-1)); // bottom front - m_cache[d].push_back(v3s16(-1, 1, 0)); // top left - m_cache[d].push_back(v3s16( 1, 1, 0)); // top right - m_cache[d].push_back(v3s16( 0, 1, 1)); // top back - m_cache[d].push_back(v3s16( 0, 1,-1)); // top front + list.push_back(v3s16(-1, 0, 1)); // back left + list.push_back(v3s16( 1, 0, 1)); // back right + list.push_back(v3s16(-1, 0,-1)); // front left + list.push_back(v3s16( 1, 0,-1)); // front right + list.push_back(v3s16(-1,-1, 0)); // bottom left + list.push_back(v3s16( 1,-1, 0)); // bottom right + list.push_back(v3s16( 0,-1, 1)); // bottom back + list.push_back(v3s16( 0,-1,-1)); // bottom front + list.push_back(v3s16(-1, 1, 0)); // top left + list.push_back(v3s16( 1, 1, 0)); // top right + list.push_back(v3s16( 0, 1, 1)); // top back + list.push_back(v3s16( 0, 1,-1)); // top front // 18 - m_cache[d].push_back(v3s16(-1, 1, 1)); // top back-left - m_cache[d].push_back(v3s16( 1, 1, 1)); // top back-right - m_cache[d].push_back(v3s16(-1, 1,-1)); // top front-left - m_cache[d].push_back(v3s16( 1, 1,-1)); // top front-right - m_cache[d].push_back(v3s16(-1,-1, 1)); // bottom back-left - m_cache[d].push_back(v3s16( 1,-1, 1)); // bottom back-right - m_cache[d].push_back(v3s16(-1,-1,-1)); // bottom front-left - m_cache[d].push_back(v3s16( 1,-1,-1)); // bottom front-right + list.push_back(v3s16(-1, 1, 1)); // top back-left + list.push_back(v3s16( 1, 1, 1)); // top back-right + list.push_back(v3s16(-1, 1,-1)); // top front-left + list.push_back(v3s16( 1, 1,-1)); // top front-right + list.push_back(v3s16(-1,-1, 1)); // bottom back-left + list.push_back(v3s16( 1,-1, 1)); // bottom back-right + list.push_back(v3s16(-1,-1,-1)); // bottom front-left + list.push_back(v3s16( 1,-1,-1)); // bottom front-right // 26 return; } // Take blocks in all sides, starting from y=0 and going +-y - for(s16 y=0; y<=d-1; y++) { + for(s16 y=0; y<=d-1; y++) + { // Left and right side, including borders - for(s16 z=-d; z<=d; z++) { - m_cache[d].push_back(v3s16(d,y,z)); - m_cache[d].push_back(v3s16(-d,y,z)); - if(y != 0) { - m_cache[d].push_back(v3s16(d,-y,z)); - m_cache[d].push_back(v3s16(-d,-y,z)); + for(s16 z=-d; z<=d; z++) + { + list.push_back(v3s16(d,y,z)); + list.push_back(v3s16(-d,y,z)); + if(y != 0) + { + list.push_back(v3s16(d,-y,z)); + list.push_back(v3s16(-d,-y,z)); } } // Back and front side, excluding borders - for(s16 x=-d+1; x<=d-1; x++) { - m_cache[d].push_back(v3s16(x,y,d)); - m_cache[d].push_back(v3s16(x,y,-d)); - if(y != 0) { - m_cache[d].push_back(v3s16(x,-y,d)); - m_cache[d].push_back(v3s16(x,-y,-d)); + for(s16 x=-d+1; x<=d-1; x++) + { + list.push_back(v3s16(x,y,d)); + list.push_back(v3s16(x,y,-d)); + if(y != 0) + { + list.push_back(v3s16(x,-y,d)); + list.push_back(v3s16(x,-y,-d)); } } } @@ -105,9 +100,10 @@ void FacePositionCache::generateFacePosition(u16 d) // Take the bottom and top face with borders // -d -#include -#include #include - -/* - * This class permits to cache getFacePosition call results - * This reduces CPU usage and vector calls - */ -class FacePositionCache -{ -public: - static std::vector getFacePositions(u16 d); -private: - static void generateFacePosition(u16 d); - static std::map > m_cache; -}; +// Calculate the borders of a "d-radius" cube +void getFacePositions(std::list &list, u16 d); class IndentationRaiser { @@ -184,56 +171,57 @@ inline void sortBoxVerticies(v3s16 &p1, v3s16 &p2) { } -/** Returns \p f wrapped to the range [-360, 360] - * - * See test.cpp for example cases. - * - * \note This is also used in cases where degrees wrapped to the range [0, 360] - * is innapropriate (e.g. pitch needs negative values) - * - * \internal functionally equivalent -- although precision may vary slightly -- - * to fmodf((f), 360.0f) however empirical tests indicate that this approach is - * faster. - */ -inline float modulo360f(float f) +/* + See test.cpp for example cases. + wraps degrees to the range of -360...360 + NOTE: Wrapping to 0...360 is not used because pitch needs negative values. +*/ +inline float wrapDegrees(float f) { - int sign; - int whole; - float fraction; - - if (f < 0) { - f = -f; - sign = -1; - } else { - sign = 1; - } - - whole = f; - - fraction = f - whole; - whole %= 360; - - return sign * (whole + fraction); + // Take examples of f=10, f=720.5, f=-0.5, f=-360.5 + // This results in + // 10, 720, -1, -361 + int i = floor(f); + // 0, 2, 0, -1 + int l = i / 360; + // NOTE: This would be used for wrapping to 0...360 + // 0, 2, -1, -2 + /*if(i < 0) + l -= 1;*/ + // 0, 720, 0, -360 + int k = l * 360; + // 10, 0.5, -0.5, -0.5 + f -= float(k); + return f; } - -/** Returns \p f wrapped to the range [0, 360] - */ +/* Wrap to 0...360 */ inline float wrapDegrees_0_360(float f) { - float value = modulo360f(f); - return value < 0 ? value + 360 : value; + // Take examples of f=10, f=720.5, f=-0.5, f=-360.5 + // This results in + // 10, 720, -1, -361 + int i = floor(f); + // 0, 2, 0, -1 + int l = i / 360; + // Wrap to 0...360 + // 0, 2, -1, -2 + if(i < 0) + l -= 1; + // 0, 720, 0, -360 + int k = l * 360; + // 10, 0.5, -0.5, -0.5 + f -= float(k); + return f; } - -/** Returns \p f wrapped to the range [-180, 180] - */ +/* Wrap to -180...180 */ inline float wrapDegrees_180(float f) { - float value = modulo360f(f + 180); - if (value < 0) - value += 360; - return value - 180; + f += 180; + f = wrapDegrees_0_360(f); + f -= 180; + return f; } /* diff --git a/src/util/string.cpp b/src/util/string.cpp index c48abe835..b4908d62d 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -22,9 +22,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "numeric.h" #include "log.h" -#include "base64.h" -#include "hex.h" -#include "sha1.h" +#include "../sha1.h" +#include "../base64.h" +#include "../hex.h" #include "../porting.h" #include @@ -40,7 +40,6 @@ static bool parseHexColorString(const std::string &value, video::SColor &color); static bool parseNamedColorString(const std::string &value, video::SColor &color); #ifdef __ANDROID__ - const wchar_t* wide_chars = L" !\"#$%&'()*+,-./0123456789:;<=>?@" L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" @@ -63,38 +62,31 @@ int wctomb(char *s, wchar_t wc) int mbtowc(wchar_t *pwc, const char *s, size_t n) { - if (s == NULL || *s == '\0') + wchar_t *intermediate = narrow_to_wide(s); + + if (intermediate.length() > 0) { + *pwc = intermediate[0]; + return 1; + } else { return -1; - - const wchar_t *tmp = narrow_to_wide_c(s); - bool success = tmp[0] != '\0'; - - if (success) - *pwc = tmp[0]; - - delete tmp; - - return success ? 1 : -1; + } } - // You must free the returned string! const wchar_t *narrow_to_wide_c(const char *mbs) { size_t mbl = strlen(mbs); - wchar_t *wcs = new wchar_t[mbl + 1]; + wchar_t wcs = new wchar_t[mbl + 1]; - size_t i, dest_i = 0; - for (i = 0; i < mbl; i++) { + for (size_t i = 0; i < mbl; i++) { if (((unsigned char) mbs[i] > 31) && ((unsigned char) mbs[i] < 127)) { - wcs[dest_i++] = wide_chars[(unsigned char) mbs[i] - 32]; + wcs[i] = wide_chars[(unsigned char) mbs[i] - 32]; } //handle newline else if (mbs[i] == '\n') { - wcs[dest_i++] = L'\n'; + wcs[i] = L'\n'; } } - wcs[dest_i] = '\0'; return wcs; } @@ -106,13 +98,11 @@ const wchar_t *narrow_to_wide_c(const char *mbs) { wchar_t *wcs = NULL; #if defined(_WIN32) - int nResult = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) mbs, -1, 0, 0); - if (nResult == 0) { - errorstream << "gettext: MultiByteToWideChar returned null" << std::endl; - } else { - wcs = new wchar_t[nResult]; - MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) mbs, -1, (WCHAR *) wcs, nResult); - } + int wcl = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) mbs, -1, NULL, 0); + if (!wcl) + return NULL; + wcs = new wchar_t[wcl]; + MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) mbs, -1, (WCHAR *) wcs, wcl); #else size_t wcl = mbstowcs(NULL, mbs, 0); if (wcl == (size_t) -1) @@ -130,13 +120,12 @@ const wchar_t *narrow_to_wide_c(const char *mbs) std::wstring narrow_to_wide(const std::string& mbs) { - size_t wcl = mbs.size(); - Buffer wcs(wcl + 1); - size_t l = mbstowcs(*wcs, mbs.c_str(), wcl); - if (l == (size_t)(-1)) + const wchar_t *wcs = narrow_to_wide_c(mbs.c_str()); + if (!wcs) return L""; - wcs[l] = 0; - return *wcs; + std::wstring wstr(wcs); + delete [] wcs; + return wstr; } #ifdef __ANDROID__ diff --git a/src/voxel.cpp b/src/voxel.cpp index a5e0b09fe..8ac786aab 100644 --- a/src/voxel.cpp +++ b/src/voxel.cpp @@ -621,8 +621,6 @@ void VoxelManipulator::spreadLight(enum LightBank bank, } #endif -const MapNode VoxelManipulator::ContentIgnoreNode = MapNode(CONTENT_IGNORE); - #if 1 /* Lights neighbors of from_nodes, collects all them and then diff --git a/src/voxel.h b/src/voxel.h index 054644889..52274ac19 100644 --- a/src/voxel.h +++ b/src/voxel.h @@ -413,21 +413,10 @@ public: } // Stuff explodes if non-emerged area is touched with this. // Emerge first, and check VOXELFLAG_NO_DATA if appropriate. - MapNode & getNodeRefUnsafe(const v3s16 &p) + MapNode & getNodeRefUnsafe(v3s16 p) { return m_data[m_area.index(p)]; } - - const MapNode & getNodeRefUnsafeCheckFlags(const v3s16 &p) - { - s32 index = m_area.index(p); - - if (m_flags[index] & VOXELFLAG_NO_DATA) - return ContentIgnoreNode; - - return m_data[index]; - } - u8 & getFlagsRefUnsafe(v3s16 p) { return m_flags[m_area.index(p)]; @@ -580,8 +569,6 @@ public: */ u8 *m_flags; - static const MapNode ContentIgnoreNode; - //TODO: Use these or remove them //TODO: Would these make any speed improvement? //bool m_pressure_route_valid; diff --git a/src/wieldmesh.cpp b/src/wieldmesh.cpp index a2be55544..4ddae36d4 100644 --- a/src/wieldmesh.cpp +++ b/src/wieldmesh.cpp @@ -26,7 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "nodedef.h" #include "mesh.h" #include "mapblock_mesh.h" -#include "client/tile.h" +#include "tile.h" #include "log.h" #include "util/numeric.h" #include @@ -340,9 +340,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, IGameDef *gamedef) } else if (f.drawtype == NDT_NORMAL || f.drawtype == NDT_ALLFACES) { setCube(f.tiles, def.wield_scale, tsrc); } else { - //// TODO: Change false in the following constructor args to - //// appropriate value when shader is added for wield items (if applicable) - MeshMakeData mesh_make_data(gamedef, false); + MeshMakeData mesh_make_data(gamedef); MapNode mesh_make_node(id, 255, 0); mesh_make_data.fillSingleNode(&mesh_make_node); MapBlockMesh mapblock_mesh(&mesh_make_data, v3s16(0, 0, 0)); diff --git a/util/travis/before_install.sh b/util/travis/before_install.sh index a50d5f370..0b1332308 100755 --- a/util/travis/before_install.sh +++ b/util/travis/before_install.sh @@ -8,15 +8,12 @@ if [ $CC = "clang" ]; then sudo apt-get install llvm-3.1 sudo apt-get install clang fi -sudo apt-get install p7zip-full if [ $WINDOWS = "no" ]; then sudo apt-get install libirrlicht-dev cmake libbz2-dev libpng12-dev \ - libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libhiredis-dev \ - libogg-dev libvorbis-dev libopenal-dev gettext - # Linking to LevelDB is broken, use a custom build - wget http://sfan5.pf-control.de/libleveldb-1.18-ubuntu12.04.7z - sudo 7z x -o/usr libleveldb-1.18-ubuntu12.04.7z + libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev \ + libvorbis-dev libopenal-dev gettext else + sudo apt-get install p7zip-full if [ $WINDOWS = "32" ]; then wget http://sfan5.pf-control.de/mingw_w64_i686_ubuntu12.04_4.9.1.7z -O mingw.7z sed -e "s|%PREFIX%|i686-w64-mingw32|" \ diff --git a/util/travis/script.sh b/util/travis/script.sh index 35a62f16e..a8e2634e9 100755 --- a/util/travis/script.sh +++ b/util/travis/script.sh @@ -3,12 +3,8 @@ if [ $WINDOWS = "no" ]; then mkdir -p travisbuild cd travisbuild - cmake -DENABLE_GETTEXT=1 -DENABLE_LEVELDB=1 -DENABLE_REDIS=1 -DCMAKE_BUILD_TYPE=Debug .. + cmake -DENABLE_GETTEXT=1 .. make -j2 - echo "Running unit tests for minetest" - ../bin/minetest --run-unittests - echo "Running unit tests for minetestserver" - ../bin/minetestserver --run-unittests else [ $CC = "clang" ] && exit 1 # Not supposed to happen # We need to have our build directory outside of the minetest directory because