diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c64b2e76..3065710ab 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 11) +set(VERSION_PATCH 12) set(VERSION_PATCH_ORIG ${VERSION_PATCH}) if(VERSION_EXTRA) diff --git a/README.txt b/README.txt index 0999bd165..a3aa9e6b3 100644 --- a/README.txt +++ b/README.txt @@ -103,18 +103,30 @@ Compiling on GNU/Linux: ----------------------- Install dependencies. Here's an example for Debian/Ubuntu: -$ 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 +$ 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 -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 +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 $ tar xf master.tar.gz -$ cd minetest-minetest-286edd4 (or similar) +$ cd minetest-master -Download minetest_game (otherwise only the "Minimal development test" game is available) +Download minetest_game, without using git: $ cd games/ -$ 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 +$ wget https://github.com/minetest/minetest_game/archive/master.tar.gz +$ tar xf master.tar.gz +$ mv minetest_game-master minetest_game $ cd .. Build a version that runs directly from the source directory: @@ -122,8 +134,7 @@ $ cmake . -DRUN_IN_PLACE=1 $ make -j2 Run it: -$ cd bin -$ ./minetest +$ ./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 68625b6a7..6027982ed 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 = 5 +ANDROID_VERSION_CODE = 6 ################################################################################ # toolchain config for arm old processors diff --git a/build/android/jni/Android.mk b/build/android/jni/Android.mk index 7546626b2..5739d3b07 100644 --- a/build/android/jni/Android.mk +++ b/build/android/jni/Android.mk @@ -102,7 +102,6 @@ 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 \ @@ -190,7 +189,6 @@ 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 \ @@ -205,10 +203,12 @@ LOCAL_SRC_FILES := \ 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 \ diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index deeba788e..39fca7d1e 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -545,12 +545,11 @@ function table.copy(t, seen) seen = seen or {} seen[t] = n for k, v in pairs(t) do - 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) + 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 end return n end - -------------------------------------------------------------------------------- -- mainmenu only functions -------------------------------------------------------------------------------- @@ -565,7 +564,7 @@ if INIT == "mainmenu" then return nil end - function fgettext(text, ...) + function fgettext_ne(text, ...) text = core.gettext(text) local arg = {n=select('#', ...), ...} if arg.n >= 1 then @@ -587,7 +586,11 @@ if INIT == "mainmenu" then end text = result end - return core.formspec_escape(text) + return text + end + + function fgettext(text, ...) + return core.formspec_escape(fgettext_ne(text, ...)) end end diff --git a/builtin/common/serialize.lua b/builtin/common/serialize.lua index 24b2a12ee..90b8b2ad6 100644 --- a/builtin/common/serialize.lua +++ b/builtin/common/serialize.lua @@ -115,11 +115,20 @@ 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 2d94817e8..210117884 100644 --- a/builtin/game/chatcommands.lua +++ b/builtin/game/chatcommands.lua @@ -229,21 +229,28 @@ core.register_chatcommand("setpassword", { if not toname then return false, "Name field required" end - local actstr = "?" + local act_str_past = "?" + local act_str_pres = "?" if not raw_password then core.set_player_password(toname, "") - actstr = "cleared" + act_str_past = "cleared" + act_str_pres = "clears" else core.set_player_password(toname, core.get_password_hash(toname, raw_password)) - actstr = "set" + act_str_past = "set" + act_str_pres = "sets" end if toname ~= name then core.chat_send_player(toname, "Your password was " - .. actstr .. " by " .. name) + .. act_str_past .. " by " .. name) end - return true, "Password of player \"" .. toname .. "\" " .. actstr + + core.log("action", name .. " " .. act_str_pres + .. " password of " .. toname .. ".") + + return true, "Password of player \"" .. toname .. "\" " .. act_str_past end, }) @@ -257,6 +264,9 @@ 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, }) @@ -404,13 +414,14 @@ core.register_chatcommand("set", { }) core.register_chatcommand("deleteblocks", { - params = "[here] [ ]", + params = "(here [radius]) | ( )", description = "delete map blocks contained in area pos1 to pos2", privs = {server=true}, func = function(name, param) local p1 = {} local p2 = {} - if param == "here" then + local args = param:split(" ") + if args[1] == "here" then local player = core.get_player_by_name(name) if player == nil then core.log("error", "player is nil") @@ -418,6 +429,12 @@ 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 @@ -570,6 +587,9 @@ 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 @@ -583,6 +603,10 @@ 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" @@ -614,6 +638,9 @@ 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 e136d4f4c..d25f4eff0 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,19 +357,37 @@ function core.item_drop(itemstack, dropper, pos) return itemstack end -function core.item_eat(hp_change, replace_with_item) - return function(itemstack, user, pointed_thing) -- closure - 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 +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 - 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 + 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) end end @@ -425,7 +443,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) @@ -438,7 +456,7 @@ function core.node_dig(pos, node, digger) end end digger:set_wielded_item(wielded) - + -- Handle drops core.handle_node_drops(pos, drops, digger) @@ -449,7 +467,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 @@ -507,7 +525,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 549c0967b..f32d77f2a 100644 --- a/builtin/mainmenu/common.lua +++ b/builtin/mainmenu/common.lua @@ -16,9 +16,15 @@ --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 -------------------------------------------------------------------------------- @@ -42,6 +48,25 @@ 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 = "" @@ -68,6 +93,7 @@ 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 = '' @@ -87,11 +113,17 @@ 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 @@ -114,7 +146,7 @@ function render_favorite(spec,render_details) details = details .. "0," end - return details .. text + return details .. (grey_out and '#aaaaaa,' or ',') .. text end -------------------------------------------------------------------------------- @@ -195,7 +227,7 @@ function asyncOnlineFavourites() nil, function(result) if core.setting_getbool("public_serverlist") then - menudata.favorites = result + menudata.favorites = order_favorite_list(result) core.event_handler("Refresh") end end @@ -225,3 +257,21 @@ 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 a15e4c11f..4d13faea8 100644 --- a/builtin/mainmenu/dlg_config_world.lua +++ b/builtin/mainmenu/dlg_config_world.lua @@ -16,6 +16,9 @@ --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) @@ -195,10 +198,12 @@ 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 mod.enabled then - worldfile:set("load_mod_"..mod.name, "true") + if modname_valid(mod.name) then + worldfile:set("load_mod_"..mod.name, tostring(mod.enabled)) else - worldfile:set("load_mod_"..mod.name, "false") + 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 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 32e1fbf83..b42d119e0 100644 --- a/builtin/mainmenu/dlg_create_world.lua +++ b/builtin/mainmenu/dlg_create_world.lua @@ -90,6 +90,8 @@ 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) @@ -97,8 +99,6 @@ 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 dfaa04d3c..d008ec8b0 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -139,7 +139,11 @@ local function init_globals() tv_main:add(tab_credits) tv_main:set_global_event_handler(main_event_handler) - tv_main:set_fixed_size(false) + if PLATFORM ~= "Android" then + tv_main:set_fixed_size(true) + else + tv_main:set_fixed_size(false) + end 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 f0ddfce8f..ad861082d 100644 --- a/builtin/mainmenu/store.lua +++ b/builtin/mainmenu/store.lua @@ -122,35 +122,36 @@ 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") .. - " " .. data.title .. " " .. - fgettext("please wait...") .. "]" + return "size[6,2]label[0.25,0.75;" .. + fgettext("Downloading $1, please wait...", data.title) .. "]" 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() + modstore.successfulldialog(this) else + this.parent:show() + this:delete() modstore.lastmodtitle = "" end - this:delete() return true end return false end, - nil, - modstore.tv_store) + nil) + 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() +function modstore.successfulldialog(downloading_dlg) local new_dlg = dialog_create("store_downloading", function(data) local retval = "" @@ -158,18 +159,16 @@ function modstore.successfulldialog() 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.5,1.5;1,0.5;btn_confirm_mod_successfull;" .. fgettext("ok") .. "]" + retval = retval .. "button[2.2,1.5;1.5,0.5;btn_confirm_mod_successfull;" .. fgettext("Ok") .. "]" + return retval end, function(this,fields) if fields["btn_confirm_mod_successfull"] ~= nil then this.parent:show() - this:hide() + downloading_dlg:delete() this:delete() return true @@ -177,10 +176,10 @@ function modstore.successfulldialog() return false end, - nil, - modstore.tv_store) + nil) - new_dlg.data.title = title + new_dlg:set_parent(modstore.tv_store) + modstore.tv_store:hide() new_dlg:show() end @@ -217,7 +216,9 @@ 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 @@ -228,12 +229,7 @@ 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 - - if modstore.lastmodtitle ~= "" then - modstore.lastmodtitle = modstore.lastmodtitle .. ", " - end - - modstore.lastmodtitle = modstore.lastmodtitle .. moddetails.title + modstore.lastmodtitle = moddetails.title if not core.handle_async( function(param) @@ -281,7 +277,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) @@ -299,7 +295,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 @@ -391,7 +387,7 @@ function modstore.getscreenshot(ypos,listentry) listentry.details.screenshot_url == "") then if listentry.texturename == nil then - listentry.texturename = modstore.basetexturedir .. "no_screenshot.png" + listentry.texturename = defaulttexturedir .. "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 d16ecca8c..901f14553 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 = modstore.basetexturedir .. "no_screenshot.png" + modscreenshot = defaulttexturedir .. "no_screenshot.png" end retval = retval @@ -96,7 +96,7 @@ local function get_formspec(tabview, name, tabdata) else --show dependencies - retval = retval .. ",Depends:," + retval = retval .. "," .. fgettext("Depends:") .. "," local toadd = modmgr.get_dependencies(selected_mod.path) diff --git a/builtin/mainmenu/tab_multiplayer.lua b/builtin/mainmenu/tab_multiplayer.lua index c44fd0144..570259718 100644 --- a/builtin/mainmenu/tab_multiplayer.lua +++ b/builtin/mainmenu/tab_multiplayer.lua @@ -59,9 +59,10 @@ 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("Creative mode", "creative") .. ",padding=1;" .. - image_column("Damage enabled", "damage") .. ",padding=0.25;" .. - image_column("PvP enabled", "pvp") .. ",padding=0.25;" .. + 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;" .. "text,padding=1]" -- name else retval = retval .. "tablecolumns[text]" @@ -88,7 +89,6 @@ 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,6 +98,10 @@ 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"] @@ -189,7 +193,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 = core.get_favorites() + menudata.favorites = order_favorite_list(core.get_favorites()) tabdata.fav_selected = nil core.setting_set("address","") @@ -198,8 +202,9 @@ local function main_button_handler(tabview, fields, name, tabdata) return true end - if fields["btn_mp_connect"] ~= nil or - fields["key_enter"] ~= nil then + if (fields["btn_mp_connect"] ~= nil or + fields["key_enter"] ~= nil) and fields["te_address"] ~= nil and + fields["te_port"] ~= nil then gamedata.playername = fields["te_name"] gamedata.password = fields["te_pwd"] @@ -214,6 +219,11 @@ 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 cab1702cf..b9a6b650f 100644 --- a/builtin/mainmenu/tab_simple_main.lua +++ b/builtin/mainmenu/tab_simple_main.lua @@ -42,9 +42,10 @@ 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("Creative mode", "creative") .. ",padding=1;" .. - image_column("Damage enabled", "damage") .. ",padding=0.25;" .. - image_column("PvP enabled", "pvp") .. ",padding=0.25;" .. + 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;" .. "text,padding=1]" -- name else retval = retval .. "tablecolumns[text]" @@ -87,7 +88,6 @@ local function get_formspec(tabview, name, tabdata) end -------------------------------------------------------------------------------- - local function main_button_handler(tabview, fields, name, tabdata) if fields["btn_start_singleplayer"] then @@ -159,6 +159,11 @@ 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 dce78fbaa..a84765d4e 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.a Irrlicht + FIND_LIBRARY(IRRLICHT_LIBRARY NAMES libIrrlicht.so libIrrlicht.a Irrlicht PATHS /usr/local/lib /usr/lib diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 586c520fc..5fa164e6b 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1,4 +1,4 @@ -Minetest Lua Modding API Reference 0.4.11 +Minetest Lua Modding API Reference 0.4.12 ========================================= * More information at * Developer Wiki: @@ -20,7 +20,8 @@ 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 ------- @@ -593,13 +594,14 @@ 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. @@ -679,24 +681,26 @@ 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 @@ -741,64 +745,75 @@ 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`. +Currently supported flags: `place_center_x`, `place_center_y`, + `place_center_z`, `force_placement`. * `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. @@ -812,7 +827,8 @@ 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. @@ -876,15 +892,18 @@ 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 @@ -1036,8 +1055,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 connect to - other group members with same drawtype +* `connect_to_raillike`: makes nodes of raillike drawtype with same group value + connect to each other ### Known damage and digging time defining groups * `crumbly`: dirt, sand @@ -1177,7 +1196,8 @@ 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 @@ -1185,7 +1205,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. @@ -1198,8 +1218,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. @@ -1244,12 +1264,14 @@ 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;]", @@ -1849,6 +1871,9 @@ 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`) @@ -1866,8 +1891,10 @@ 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. @@ -1926,6 +1953,9 @@ 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)` @@ -2037,7 +2067,11 @@ 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` can be `nil`. + * 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` ### Defaults for the `on_punch` and `on_dig` node definition callbacks * `minetest.node_punch(pos, node, puncher, pointed_thing)` @@ -2094,12 +2128,15 @@ 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. @@ -2244,7 +2281,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 @@ -2260,7 +2297,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 @@ -2288,6 +2325,7 @@ 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 @@ -2360,7 +2398,8 @@ 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` @@ -2392,13 +2431,16 @@ 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({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_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_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}`) @@ -2485,7 +2527,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)`. @@ -2519,36 +2561,43 @@ 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` @@ -2557,10 +2606,12 @@ 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` @@ -2587,37 +2638,39 @@ 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: @@ -2629,7 +2682,8 @@ 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 ------------------- @@ -2676,7 +2730,8 @@ 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 @@ -3138,8 +3193,10 @@ Definition tables schematic = { size = {x=4, y=6, z=4}, data = { - {name="cobble", param1=255, param2=0}, - {name="dirt_with_grass", param1=255, param2=0}, + {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}, ... }, yslice_prob = { @@ -3150,7 +3207,7 @@ Definition tables }, -- ^ See 'Schematic specifier' for details. replacements = {["oldname"] = "convert_to", ...}, - flags = "place_center_x, place_center_z", + flags = "place_center_x, place_center_y, place_center_z, force_placement", -- ^ 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 5c0f90df6..e5ba46d4c 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -1,4 +1,4 @@ -Minetest Lua Mainmenu API Reference 0.4.11 +Minetest Lua Mainmenu API Reference 0.4.12 ======================================== Introduction @@ -197,9 +197,11 @@ core.delete_world(index) Helpers: core.gettext(string) -> string ^ look up the translation of a string in the gettext message catalog -fgettext(string, ...) -> string +fgettext_ne(string, ...) ^ call core.gettext(string), replace "$1"..."$9" with the given -^ extra arguments, call core.formspec_escape and return the result +^ extra arguments and return the result +fgettext(string, ...) -> string +^ same as fgettext_ne(), but calls core.formspec_escape before returning result core.parse_json(string[, nullvalue]) -> something (possible in async calls) ^ see core.parse_json (lua_api.txt) dump(obj, dumped={}) @@ -211,6 +213,12 @@ 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 eb883fa8e..5e8637897 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -48,6 +48,7 @@ #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 @@ -127,6 +128,13 @@ #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 @@ -252,16 +260,16 @@ #freetype = true # Path to TrueTypeFont or bitmap #font_path = fonts/liberationsans.ttf -#font_size = 13 +#font_size = 15 # 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 = 13 +#mono_font_size = 15 # This font will be used for certain languages #fallback_font_path = fonts/DroidSansFallbackFull.ttf -#fallback_font_size = 13 +#fallback_font_size = 15 #fallback_font_shadow = 1 #fallback_font_shadow_alpha = 128 # Override language. When no value is provided (default) system language is used. @@ -337,6 +345,7 @@ # 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). @@ -460,6 +469,8 @@ # 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: @@ -477,33 +488,14 @@ # flags = "defaults" #} # Only the group format supports noise flags which are needed for eased noise. -# 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 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_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 = { -# 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_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_ground = { # offset = 0 # scale = 40 @@ -514,17 +506,6 @@ # 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 36decb43f..896404789 100644 --- a/misc/minetest.desktop +++ b/misc/minetest.desktop @@ -2,6 +2,8 @@ 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 ce24e54ae..563275b01 100644 --- a/po/cs/minetest.po +++ b/po/cs/minetest.po @@ -1,24 +1,23 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. +# Czech translations for minetest. +# Copyright (C) 2011 celeron +# This file is distributed under the same license as the minetest. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: minetest\n" "Report-Msgid-Bugs-To: \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" +"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" "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/fstk/ui.lua:67 builtin/mainmenu/store.lua:165 msgid "Ok" msgstr "OK" @@ -29,18 +28,18 @@ msgstr "Svět:" #: builtin/mainmenu/dlg_config_world.lua:30 #: builtin/mainmenu/dlg_config_world.lua:32 msgid "Hide Game" -msgstr "Skrýt interní" +msgstr "Skrýt vnitřní" #: builtin/mainmenu/dlg_config_world.lua:36 #: builtin/mainmenu/dlg_config_world.lua:38 msgid "Hide mp content" -msgstr "Skrýt obsah balíčku" +msgstr "Skrýt obsahy balíčků" #: builtin/mainmenu/dlg_config_world.lua:46 msgid "Mod:" -msgstr "Mody:" +msgstr "Mod:" -#: builtin/mainmenu/dlg_config_world.lua:48 +#: builtin/mainmenu/dlg_config_world.lua:48 builtin/mainmenu/tab_mods.lua:99 msgid "Depends:" msgstr "Závislosti:" @@ -82,7 +81,7 @@ msgstr "Seedové číslo" #: builtin/mainmenu/dlg_create_world.lua:56 msgid "Mapgen" -msgstr "Generátor světa" +msgstr "Generátor mapy" #: builtin/mainmenu/dlg_create_world.lua:59 msgid "Game" @@ -94,19 +93,19 @@ msgstr "Vytvořit" #: builtin/mainmenu/dlg_create_world.lua:68 msgid "You have no subgames installed." -msgstr "" +msgstr "Nemáte nainstalované žádné podhry." #: builtin/mainmenu/dlg_create_world.lua:69 msgid "Download one from minetest.net" -msgstr "" +msgstr "Stáhněte si jednu z minetest.net" #: builtin/mainmenu/dlg_create_world.lua:72 msgid "Warning: The minimal development test is meant for developers." -msgstr "" +msgstr "Varování: \"Minimal development test\" je zamýšlen pouze pro vývojáře." #: builtin/mainmenu/dlg_create_world.lua:73 msgid "Download a subgame, such as minetest_game, from minetest.net" -msgstr "" +msgstr "Stáhněte si z minetest.net podhru, například minetest_game." #: builtin/mainmenu/dlg_create_world.lua:97 msgid "A world named \"$1\" already exists" @@ -114,7 +113,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 žádná hra" +msgstr "Nebyla vybrána podhra nebo název" #: builtin/mainmenu/dlg_delete_mod.lua:26 msgid "Are you sure you want to delete \"$1\"?" @@ -122,7 +121,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:25 +#: builtin/mainmenu/tab_settings.lua:79 msgid "Yes" msgstr "Ano" @@ -156,16 +155,15 @@ 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: nepodporovaný typ souboru \"$1\"" +"Instalace modu: špatný archiv nebo nepodporovaný typ souboru \"$1\"" #: builtin/mainmenu/modmgr.lua:363 msgid "Failed to install $1 to $2" @@ -173,60 +171,49 @@ msgstr "Selhala instalace $1 do $2" #: builtin/mainmenu/modmgr.lua:366 msgid "Install Mod: unable to find suitable foldername for modpack $1" -msgstr "" -"Install Mod: nenalezen vhodný adresář s příslušným názvem pro balíček modů $1" +msgstr "Instalace modu: nenalezen vhodný adresář s příslušným názvem pro balíček $1" #: builtin/mainmenu/modmgr.lua:386 msgid "Install Mod: unable to find real modname for: $1" -msgstr "Install Mod: Nenašel jsem skutečné jméno modu: $1" +msgstr "Instalace modu: nenašel jsem skutečné jméno modu: $1" #: builtin/mainmenu/store.lua:88 msgid "Unsorted" -msgstr "" +msgstr "Neřazené" -#: builtin/mainmenu/store.lua:99 builtin/mainmenu/store.lua:584 +#: builtin/mainmenu/store.lua:99 builtin/mainmenu/store.lua:580 msgid "Search" -msgstr "" +msgstr "Hledání" -#: builtin/mainmenu/store.lua:125 -#, fuzzy -msgid "Downloading" -msgstr "Stáhnout" +#: builtin/mainmenu/store.lua:126 +msgid "Downloading $1, please wait..." +msgstr "Stahuji $1, prosím čekejte..." -#: builtin/mainmenu/store.lua:127 -msgid "please wait..." -msgstr "" - -#: builtin/mainmenu/store.lua:159 +#: builtin/mainmenu/store.lua:160 msgid "Successfully installed:" -msgstr "" +msgstr "Úspěšně nainstalováno:" -#: builtin/mainmenu/store.lua:163 -#, fuzzy +#: builtin/mainmenu/store.lua:162 msgid "Shortname:" -msgstr "Název světa" +msgstr "Zkratka:" -#: builtin/mainmenu/store.lua:167 src/guiFormSpecMenu.cpp:2866 -msgid "ok" -msgstr "" - -#: builtin/mainmenu/store.lua:476 +#: builtin/mainmenu/store.lua:472 msgid "Rating" msgstr "Hodnocení" -#: builtin/mainmenu/store.lua:501 +#: builtin/mainmenu/store.lua:497 msgid "re-Install" -msgstr "přeinstalovat" +msgstr "Přeinstalovat" -#: builtin/mainmenu/store.lua:503 +#: builtin/mainmenu/store.lua:499 msgid "Install" msgstr "Instalovat" -#: builtin/mainmenu/store.lua:522 +#: builtin/mainmenu/store.lua:518 msgid "Close store" -msgstr "" +msgstr "Zavřít obchod" -#: builtin/mainmenu/store.lua:530 +#: builtin/mainmenu/store.lua:526 msgid "Page $1 of $2" msgstr "Strana $1 z $2" @@ -248,7 +235,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" @@ -268,7 +255,7 @@ msgstr "Přejmenovat" #: builtin/mainmenu/tab_mods.lua:95 msgid "Uninstall selected modpack" -msgstr "Odinstalovat označený balíček modů" +msgstr "Odinstalovat označený balíček" #: builtin/mainmenu/tab_mods.lua:106 msgid "Uninstall selected mod" @@ -276,39 +263,53 @@ 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 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:24 +msgid "Name / Password :" +msgstr "Jméno / Heslo :" #: builtin/mainmenu/tab_multiplayer.lua:29 #: builtin/mainmenu/tab_simple_main.lua:30 msgid "Public Serverlist" -msgstr "Veřejný seznam serverů" +msgstr "Seznam veřejných 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 "Vymazat" +msgstr "Smazat" #: builtin/mainmenu/tab_multiplayer.lua:38 #: builtin/mainmenu/tab_simple_main.lua:34 msgid "Connect" msgstr "Připojit" -#: builtin/mainmenu/tab_multiplayer.lua:252 +#: 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 msgid "Client" -msgstr "Hra více hráčů" +msgstr "Klient" #: builtin/mainmenu/tab_server.lua:27 builtin/mainmenu/tab_singleplayer.lua:86 msgid "New" @@ -320,18 +321,18 @@ msgstr "Nastavit" #: builtin/mainmenu/tab_server.lua:29 msgid "Start Game" -msgstr "Začít hru" +msgstr "Spustit 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:63 +#: builtin/mainmenu/tab_server.lua:31 builtin/mainmenu/tab_simple_main.lua:75 #: 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:65 +#: builtin/mainmenu/tab_server.lua:33 builtin/mainmenu/tab_simple_main.lua:77 #: builtin/mainmenu/tab_singleplayer.lua:92 msgid "Enable Damage" msgstr "Povolit poškození" @@ -340,13 +341,17 @@ 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 "" +msgstr "Svázat adresu" #: builtin/mainmenu/tab_server.lua:47 msgid "Port" -msgstr "" +msgstr "Port" #: builtin/mainmenu/tab_server.lua:51 msgid "Server Port" @@ -354,140 +359,153 @@ msgstr "Port serveru" #: builtin/mainmenu/tab_server.lua:174 msgid "Server" -msgstr "Místní 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" #: 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 "" +msgstr "Jste si jisti, že chcete resetovat místní svět?" -#: builtin/mainmenu/tab_settings.lua:27 +#: builtin/mainmenu/tab_settings.lua:81 msgid "No!!!" -msgstr "" +msgstr "Ne!!!" -#: builtin/mainmenu/tab_settings.lua:134 +#: builtin/mainmenu/tab_settings.lua:181 msgid "Smooth Lighting" -msgstr "Hladké osvětlení" +msgstr "Plynulé osvětlení" -#: builtin/mainmenu/tab_settings.lua:136 +#: builtin/mainmenu/tab_settings.lua:183 msgid "Enable Particles" -msgstr "Povolit Částice" +msgstr "Povolit částice" -#: builtin/mainmenu/tab_settings.lua:138 +#: builtin/mainmenu/tab_settings.lua:185 msgid "3D Clouds" -msgstr "3D Mraky" +msgstr "3D mraky" -#: builtin/mainmenu/tab_settings.lua:140 -#, fuzzy +#: builtin/mainmenu/tab_settings.lua:187 msgid "Fancy Trees" -msgstr "Pěkné stromy" +msgstr "Ozdobné stromy" -#: builtin/mainmenu/tab_settings.lua:142 +#: builtin/mainmenu/tab_settings.lua:189 msgid "Opaque Water" msgstr "Neprůhledná voda" -#: builtin/mainmenu/tab_settings.lua:144 -#, fuzzy +#: builtin/mainmenu/tab_settings.lua:191 msgid "Connected Glass" -msgstr "Připojit" +msgstr "Propojené sklo" -#: builtin/mainmenu/tab_settings.lua:149 +#: 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 msgid "Restart minetest for driver change to take effect" -msgstr "" +msgstr "Aby se změna ovladače projevila, restartujte Minetest." -#: 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 +#: builtin/mainmenu/tab_settings.lua:207 msgid "Shaders" msgstr "Shadery" -#: builtin/mainmenu/tab_settings.lua:164 +#: builtin/mainmenu/tab_settings.lua:212 msgid "Change keys" msgstr "Změnit nastavení kláves" -#: builtin/mainmenu/tab_settings.lua:167 -#, fuzzy +#: builtin/mainmenu/tab_settings.lua:215 msgid "Reset singleplayer world" -msgstr "Hra jednoho hráče" +msgstr "Reset místního světa" -#: builtin/mainmenu/tab_settings.lua:171 +#: builtin/mainmenu/tab_settings.lua:219 msgid "GUI scale factor" -msgstr "" +msgstr "Měřítko GUI" -#: builtin/mainmenu/tab_settings.lua:175 +#: builtin/mainmenu/tab_settings.lua:223 msgid "Scaling factor applied to menu elements: " -msgstr "" +msgstr "Měřítko aplikované na prvky menu: " -#: builtin/mainmenu/tab_settings.lua:181 +#: builtin/mainmenu/tab_settings.lua:229 msgid "Touch free target" -msgstr "" +msgstr "Středový kurzor" -#: builtin/mainmenu/tab_settings.lua:187 +#: builtin/mainmenu/tab_settings.lua:235 msgid "Touchthreshold (px)" -msgstr "" +msgstr "Dosah dotyku (px)" -#: builtin/mainmenu/tab_settings.lua:194 builtin/mainmenu/tab_settings.lua:208 -#, fuzzy +#: builtin/mainmenu/tab_settings.lua:242 builtin/mainmenu/tab_settings.lua:256 msgid "Bumpmapping" -msgstr "Mip-Mapování" +msgstr "Bump mapování" -#: builtin/mainmenu/tab_settings.lua:196 builtin/mainmenu/tab_settings.lua:209 +#: builtin/mainmenu/tab_settings.lua:244 builtin/mainmenu/tab_settings.lua:257 msgid "Generate Normalmaps" -msgstr "" +msgstr "Generovat normálové mapy" -#: builtin/mainmenu/tab_settings.lua:198 builtin/mainmenu/tab_settings.lua:210 +#: builtin/mainmenu/tab_settings.lua:246 builtin/mainmenu/tab_settings.lua:258 msgid "Parallax Occlusion" -msgstr "" +msgstr "Parallax Occlusion" -#: builtin/mainmenu/tab_settings.lua:200 builtin/mainmenu/tab_settings.lua:211 +#: builtin/mainmenu/tab_settings.lua:248 builtin/mainmenu/tab_settings.lua:259 msgid "Waving Water" -msgstr "" +msgstr "Vlnění vody" -#: builtin/mainmenu/tab_settings.lua:202 builtin/mainmenu/tab_settings.lua:212 +#: builtin/mainmenu/tab_settings.lua:250 builtin/mainmenu/tab_settings.lua:260 msgid "Waving Leaves" -msgstr "" +msgstr "Vlnění listů" -#: builtin/mainmenu/tab_settings.lua:204 builtin/mainmenu/tab_settings.lua:213 +#: builtin/mainmenu/tab_settings.lua:252 builtin/mainmenu/tab_settings.lua:261 msgid "Waving Plants" -msgstr "" +msgstr "Vlnění rostlin" -#: builtin/mainmenu/tab_settings.lua:255 +#: builtin/mainmenu/tab_settings.lua:287 msgid "To enable shaders the OpenGL driver needs to be used." -msgstr "Pro povolení shaderů je nutné používat OpenGL ovladač." +msgstr "Pro povolení shaderů musíte používat OpenGL ovladač." -#: builtin/mainmenu/tab_settings.lua:330 +#: builtin/mainmenu/tab_settings.lua:398 msgid "Settings" msgstr "Nastavení" -#: builtin/mainmenu/tab_simple_main.lua:67 +#: builtin/mainmenu/tab_simple_main.lua:79 msgid "Fly mode" -msgstr "" +msgstr "Létací režim" -#: builtin/mainmenu/tab_simple_main.lua:71 -#, fuzzy +#: builtin/mainmenu/tab_simple_main.lua:83 msgid "Start Singleplayer" -msgstr "Hra jednoho hráče" +msgstr "Start místní hry" -#: builtin/mainmenu/tab_simple_main.lua:72 -#, fuzzy +#: builtin/mainmenu/tab_simple_main.lua:84 msgid "Config mods" -msgstr "Nastavit" +msgstr "Nastavení modů" -#: builtin/mainmenu/tab_simple_main.lua:191 -#, fuzzy +#: builtin/mainmenu/tab_simple_main.lua:203 msgid "Main" msgstr "Hlavní nabídka" @@ -497,7 +515,7 @@ msgstr "Hrát" #: builtin/mainmenu/tab_singleplayer.lua:224 msgid "Singleplayer" -msgstr "Hra jednoho hráče" +msgstr "Místní hra" #: builtin/mainmenu/tab_texturepacks.lua:49 msgid "Select texture pack:" @@ -508,43 +526,168 @@ msgid "No information available" msgstr "Informace nejsou dostupné" #: builtin/mainmenu/tab_texturepacks.lua:114 -#, fuzzy msgid "Texturepacks" msgstr "Balíčky textur" -#: src/client.cpp:2726 +#: 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 msgid "Item textures..." -msgstr "Textury předmětů..." +msgstr "Textury věcí..." + +#: src/client.cpp:2845 +msgid "Done!" +msgstr "Hotovo!" #: src/fontengine.cpp:70 src/fontengine.cpp:226 msgid "needs_fallback_font" msgstr "no" -#: src/game.cpp:1063 +#: 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 msgid "Respawn" -msgstr "Oživení" +msgstr "Znovu stvořit" -#: src/game.cpp:2250 +#: 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 msgid "Item definitions..." -msgstr "Definice předmětů..." +msgstr "Definice věcí..." -#: src/game.cpp:2255 +#: src/game.cpp:2279 msgid "Node definitions..." msgstr "Definice bloků..." -#: src/game.cpp:2262 +#: src/game.cpp:2286 msgid "Media..." msgstr "Média..." -#: src/game.cpp:2267 +#: src/game.cpp:2291 msgid " KB/s" -msgstr "" +msgstr " KB/s" -#: src/game.cpp:2271 +#: src/game.cpp:2295 msgid " MB/s" -msgstr "" +msgstr " MB/s" -#: src/game.cpp:4220 +#: src/game.cpp:4210 msgid "" "\n" "Check debug.txt for details." @@ -552,18 +695,17 @@ msgstr "" "\n" "Pro detaily se podívejte do debug.txt." -#: src/guiFormSpecMenu.cpp:2055 -msgid "Proceed" -msgstr "Pokračovat" - -#: src/guiFormSpecMenu.cpp:2846 +#: src/guiFormSpecMenu.cpp:2797 msgid "Enter " -msgstr "" +msgstr "Zadejte " + +#: src/guiFormSpecMenu.cpp:2817 +msgid "ok" +msgstr "OK" #: 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 @@ -572,7 +714,7 @@ msgstr "\"Použít\" = slézt dolů" #: src/guiKeyChangeMenu.cpp:180 msgid "Double tap \"jump\" to toggle fly" -msgstr "Dvě zmáčknutí klávesy \"skok\" zapnou létání" +msgstr "Dvojstisk klávesy \"skok\" zapne létání" #: src/guiKeyChangeMenu.cpp:296 msgid "Key already in use" @@ -592,11 +734,11 @@ msgstr "Vzad" #: src/guiKeyChangeMenu.cpp:399 src/keycode.cpp:229 msgid "Left" -msgstr "Vlevo" +msgstr "Doleva" #: src/guiKeyChangeMenu.cpp:400 src/keycode.cpp:229 msgid "Right" -msgstr "Vpravo" +msgstr "Doprava" #: src/guiKeyChangeMenu.cpp:401 msgid "Use" @@ -608,7 +750,7 @@ msgstr "Skok" #: src/guiKeyChangeMenu.cpp:403 msgid "Sneak" -msgstr "Plížení" +msgstr "Plížit se" #: src/guiKeyChangeMenu.cpp:404 msgid "Drop" @@ -636,11 +778,11 @@ msgstr "Létání" #: src/guiKeyChangeMenu.cpp:410 msgid "Toggle fast" -msgstr "Rychlý pohyb" +msgstr "Turbo" #: src/guiKeyChangeMenu.cpp:411 msgid "Toggle noclip" -msgstr "Noclip" +msgstr "Duch" #: src/guiKeyChangeMenu.cpp:412 msgid "Range select" @@ -650,25 +792,25 @@ msgstr "Změna dohledu" msgid "Print stacks" msgstr "Vypsat hromádky" -#: src/guiPasswordChange.cpp:106 +#: src/guiPasswordChange.cpp:108 msgid "Old Password" msgstr "Staré heslo" -#: src/guiPasswordChange.cpp:122 +#: src/guiPasswordChange.cpp:124 msgid "New Password" msgstr "Nové heslo" -#: src/guiPasswordChange.cpp:137 +#: src/guiPasswordChange.cpp:139 msgid "Confirm Password" msgstr "Potvrdit heslo" -#: src/guiPasswordChange.cpp:153 +#: src/guiPasswordChange.cpp:155 msgid "Change" msgstr "Změnit" -#: src/guiPasswordChange.cpp:162 +#: src/guiPasswordChange.cpp:164 msgid "Passwords do not match!" -msgstr "Hesla si neodpovídají!" +msgstr "Hesla se neshodují!" #: src/guiVolumeChange.cpp:106 msgid "Sound Volume: " @@ -740,7 +882,7 @@ msgstr "Shift" #: src/keycode.cpp:227 msgid "Convert" -msgstr "Převádět" +msgstr "Convert" #: src/keycode.cpp:227 msgid "Escape" @@ -748,7 +890,7 @@ msgstr "Esc" #: src/keycode.cpp:227 msgid "Final" -msgstr "Konečný" +msgstr "Final" #: src/keycode.cpp:227 msgid "Junja" @@ -760,7 +902,7 @@ msgstr "Kanji" #: src/keycode.cpp:227 msgid "Nonconvert" -msgstr "Nepřevádět" +msgstr "Nonconvert" #: src/keycode.cpp:228 msgid "End" @@ -812,7 +954,7 @@ msgstr "Pomoc" #: src/keycode.cpp:230 msgid "Insert" -msgstr "Vložit" +msgstr "Insert" #: src/keycode.cpp:230 msgid "Snapshot" @@ -966,165 +1108,111 @@ msgstr "PA1" msgid "Zoom" msgstr "Přiblížení" -#: src/main.cpp:1681 +#: src/main.cpp:1688 msgid "Main Menu" msgstr "Hlavní nabídka" -#: src/main.cpp:1719 +#: src/main.cpp:1726 msgid "Player name too long." -msgstr "" +msgstr "Jméno hráče je příliš dlouhé." -#: src/main.cpp:1757 +#: src/main.cpp:1764 msgid "Connection error (timed out?)" msgstr "Chyba spojení (vypršel čas?)" -#: src/main.cpp:1919 +#: src/main.cpp:1929 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:1926 +#: src/main.cpp:1936 msgid "Provided world path doesn't exist: " -msgstr "" +msgstr "Uvedená cesta ke světu neexistuje: " -#: src/main.cpp:1935 +#: src/main.cpp:1945 msgid "Could not find or load game \"" msgstr "Hru nebylo možné nahrát nebo najít \"" -#: src/main.cpp:1953 +#: src/main.cpp:1963 msgid "Invalid gamespec." msgstr "Neplatná specifikace hry." -#~ 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 "Downloading" +msgstr "Stahuji" -#~ 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 "Exit to OS" -#~ msgstr "Ukončit hru" - -#~ msgid "Exit to Menu" -#~ msgstr "Odejít do Nabídky" - -#~ msgid "Sound Volume" -#~ msgstr "Hlasitost" - -#~ msgid "Change Password" -#~ msgstr "Změnit heslo" - -#~ msgid "Continue" -#~ msgstr "Pokračovat" - -#~ msgid "You died." -#~ msgstr "Zemřel jsi." - -#~ msgid "Shutting down stuff..." -#~ msgstr "Vypínám to..." - -#~ msgid "Connecting to server..." -#~ msgstr "Připojuji se k serveru..." - -#~ msgid "Resolving address..." -#~ msgstr "Překládám adresu..." - -#~ msgid "Creating client..." -#~ msgstr "Vytvářím klienta..." - -#~ msgid "Creating server...." -#~ msgstr "Vytvářím server..." - -#~ msgid "Loading..." -#~ msgstr "Nahrávám..." - -#~ msgid "Local install" -#~ msgstr "Místní instalace" - -#~ msgid "Add mod:" -#~ msgstr "Přidat mod:" - -#~ msgid "MODS" -#~ msgstr "MODY" - -#~ 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 "Game Name" +#~ msgstr "Název 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" +#~ msgid "GAMES" +#~ msgstr "HRY" + +#~ msgid "Games" +#~ msgstr "Hry" + +#~ msgid "Mods:" +#~ msgstr "Mody:" + +#~ msgid "edit game" +#~ msgstr "upravit hru" + +#~ msgid "new game" +#~ msgstr "nová hra" + +#~ msgid "EDIT GAME" +#~ msgstr "UPRAVIT HRU" + +#~ msgid "Remove selected mod" +#~ msgstr "Odstranit vybraný mod" + +#~ msgid "<<-- Add mod" +#~ msgstr "<<-- Přidat mod" + +#~ msgid "CLIENT" +#~ msgstr "KLIENT" + +#~ msgid "Favorites:" +#~ msgstr "Oblíbené:" + +#~ 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 "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 "Anisotropic Filtering" +#~ msgstr "Anizotropní filtrování" + +#~ msgid "Mip-Mapping" +#~ msgstr "Mip-Mapování" diff --git a/po/es/minetest.po b/po/es/minetest.po index a5380d597..5f60213f2 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: 2014-12-13 15:24+0100\n" -"PO-Revision-Date: 2015-01-19 09:56+0100\n" +"POT-Creation-Date: 2015-02-14 13:50+0100\n" +"PO-Revision-Date: 2015-02-14 13:35+0100\n" "Last-Translator: Diego de las Heras \n" -"Language-Team: LANGUAGE \n" +"Language-Team: \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.3\n" +"X-Generator: Poedit 1.7.4\n" -#: builtin/fstk/ui.lua:67 +#: builtin/fstk/ui.lua:67 builtin/mainmenu/store.lua:165 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/dlg_config_world.lua:48 builtin/mainmenu/tab_mods.lua:99 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:25 +#: builtin/mainmenu/tab_settings.lua:79 msgid "Yes" msgstr "Sí" @@ -186,48 +186,40 @@ 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:584 +#: builtin/mainmenu/store.lua:99 builtin/mainmenu/store.lua:580 msgid "Search" msgstr "Buscar" -#: builtin/mainmenu/store.lua:125 -msgid "Downloading" -msgstr "Descargando" +#: builtin/mainmenu/store.lua:126 +msgid "Downloading $1, please wait..." +msgstr "Descargando $1, por favor espere..." -#: builtin/mainmenu/store.lua:127 -msgid "please wait..." -msgstr "por favor espere..." - -#: builtin/mainmenu/store.lua:159 +#: builtin/mainmenu/store.lua:160 msgid "Successfully installed:" msgstr "Instalado con éxito:" -#: builtin/mainmenu/store.lua:163 +#: builtin/mainmenu/store.lua:162 msgid "Shortname:" msgstr "Nombre corto:" -#: builtin/mainmenu/store.lua:167 src/guiFormSpecMenu.cpp:2866 -msgid "ok" -msgstr "aceptar" - -#: builtin/mainmenu/store.lua:476 +#: builtin/mainmenu/store.lua:472 msgid "Rating" msgstr "Clasificación" -#: builtin/mainmenu/store.lua:501 +#: builtin/mainmenu/store.lua:497 msgid "re-Install" msgstr "Reinstalar" -#: builtin/mainmenu/store.lua:503 +#: builtin/mainmenu/store.lua:499 msgid "Install" msgstr "Instalar" # En el menú principal de mods pone repositorio no tienda. -#: builtin/mainmenu/store.lua:522 +#: builtin/mainmenu/store.lua:518 msgid "Close store" msgstr "Cerrar repositorio" -#: builtin/mainmenu/store.lua:530 +#: builtin/mainmenu/store.lua:526 msgid "Page $1 of $2" msgstr "Página $1 de $2" @@ -288,8 +280,7 @@ msgstr "Mods" msgid "Address / Port :" msgstr "Dirección / puerto:" -#: builtin/mainmenu/tab_multiplayer.lua:24 builtin/mainmenu/tab_server.lua:37 -#: builtin/mainmenu/tab_simple_main.lua:25 +#: builtin/mainmenu/tab_multiplayer.lua:24 msgid "Name / Password :" msgstr "Nombre / contraseña:" @@ -308,7 +299,22 @@ msgstr "Borrar" msgid "Connect" msgstr "Conectar" -#: builtin/mainmenu/tab_multiplayer.lua:252 +#: 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 msgid "Client" msgstr "Cliente" @@ -328,12 +334,12 @@ msgstr "Iniciar juego" msgid "Select World:" msgstr "Selecciona un mundo:" -#: builtin/mainmenu/tab_server.lua:31 builtin/mainmenu/tab_simple_main.lua:63 +#: builtin/mainmenu/tab_server.lua:31 builtin/mainmenu/tab_simple_main.lua:75 #: builtin/mainmenu/tab_singleplayer.lua:90 msgid "Creative Mode" msgstr "Modo creativo" -#: builtin/mainmenu/tab_server.lua:33 builtin/mainmenu/tab_simple_main.lua:65 +#: builtin/mainmenu/tab_server.lua:33 builtin/mainmenu/tab_simple_main.lua:77 #: builtin/mainmenu/tab_singleplayer.lua:92 msgid "Enable Damage" msgstr "Permitir daños" @@ -342,6 +348,11 @@ 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" @@ -358,133 +369,151 @@ 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:27 +#: builtin/mainmenu/tab_settings.lua:81 msgid "No!!!" msgstr "¡¡¡No!!!" -#: builtin/mainmenu/tab_settings.lua:134 +#: builtin/mainmenu/tab_settings.lua:181 msgid "Smooth Lighting" msgstr "Iluminación suave" -#: builtin/mainmenu/tab_settings.lua:136 +#: builtin/mainmenu/tab_settings.lua:183 msgid "Enable Particles" msgstr "Habilitar partículas" -#: builtin/mainmenu/tab_settings.lua:138 +#: builtin/mainmenu/tab_settings.lua:185 msgid "3D Clouds" msgstr "Nubes 3D" -#: builtin/mainmenu/tab_settings.lua:141 +#: builtin/mainmenu/tab_settings.lua:187 msgid "Fancy Trees" msgstr "Árboles detallados" -#: builtin/mainmenu/tab_settings.lua:142 +#: builtin/mainmenu/tab_settings.lua:189 msgid "Opaque Water" msgstr "Agua opaca" -#: builtin/mainmenu/tab_settings.lua:145 +#: builtin/mainmenu/tab_settings.lua:191 msgid "Connected Glass" msgstr "Vidrios conectados" -#: builtin/mainmenu/tab_settings.lua:149 +#: 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 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: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 +#: builtin/mainmenu/tab_settings.lua:207 msgid "Shaders" msgstr "Sombreadores" -#: builtin/mainmenu/tab_settings.lua:164 +#: builtin/mainmenu/tab_settings.lua:212 msgid "Change keys" msgstr "Configurar teclas" -#: builtin/mainmenu/tab_settings.lua:167 +#: builtin/mainmenu/tab_settings.lua:215 msgid "Reset singleplayer world" msgstr "Reiniciar mundo de un jugador" -#: builtin/mainmenu/tab_settings.lua:171 +#: builtin/mainmenu/tab_settings.lua:219 msgid "GUI scale factor" msgstr "Factor de escala (GUI)" -#: builtin/mainmenu/tab_settings.lua:175 +#: builtin/mainmenu/tab_settings.lua:223 msgid "Scaling factor applied to menu elements: " msgstr "Factor de escala aplicado a los elementos del menú: " -#: builtin/mainmenu/tab_settings.lua:182 -#, fuzzy +#: builtin/mainmenu/tab_settings.lua:229 msgid "Touch free target" msgstr "Tocar para interactuar" -#: builtin/mainmenu/tab_settings.lua:187 +#: builtin/mainmenu/tab_settings.lua:235 msgid "Touchthreshold (px)" msgstr "Umbral táctil (px)" -#: builtin/mainmenu/tab_settings.lua:194 builtin/mainmenu/tab_settings.lua:208 -#, fuzzy +#: builtin/mainmenu/tab_settings.lua:242 builtin/mainmenu/tab_settings.lua:256 msgid "Bumpmapping" msgstr "Mapeado de relieve" -#: builtin/mainmenu/tab_settings.lua:196 builtin/mainmenu/tab_settings.lua:209 +#: builtin/mainmenu/tab_settings.lua:244 builtin/mainmenu/tab_settings.lua:257 msgid "Generate Normalmaps" msgstr "Generar mapas normales" -#: builtin/mainmenu/tab_settings.lua:198 builtin/mainmenu/tab_settings.lua:210 +#: builtin/mainmenu/tab_settings.lua:246 builtin/mainmenu/tab_settings.lua:258 msgid "Parallax Occlusion" msgstr "Oclusión de paralaje" -#: builtin/mainmenu/tab_settings.lua:200 builtin/mainmenu/tab_settings.lua:211 +#: builtin/mainmenu/tab_settings.lua:248 builtin/mainmenu/tab_settings.lua:259 msgid "Waving Water" msgstr "Oleaje en el agua" -#: builtin/mainmenu/tab_settings.lua:202 builtin/mainmenu/tab_settings.lua:212 +#: builtin/mainmenu/tab_settings.lua:250 builtin/mainmenu/tab_settings.lua:260 msgid "Waving Leaves" msgstr "Movimiento de hojas" -#: builtin/mainmenu/tab_settings.lua:204 builtin/mainmenu/tab_settings.lua:213 +#: builtin/mainmenu/tab_settings.lua:252 builtin/mainmenu/tab_settings.lua:261 msgid "Waving Plants" msgstr "Movimiento de plantas" -#: builtin/mainmenu/tab_settings.lua:255 +#: builtin/mainmenu/tab_settings.lua:287 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:330 +#: builtin/mainmenu/tab_settings.lua:398 msgid "Settings" msgstr "Configuración" -#: builtin/mainmenu/tab_simple_main.lua:67 +#: builtin/mainmenu/tab_simple_main.lua:79 msgid "Fly mode" msgstr "Modo vuelo" -#: builtin/mainmenu/tab_simple_main.lua:71 +#: builtin/mainmenu/tab_simple_main.lua:83 msgid "Start Singleplayer" msgstr "Comenzar un jugador" -#: builtin/mainmenu/tab_simple_main.lua:72 +#: builtin/mainmenu/tab_simple_main.lua:84 msgid "Config mods" msgstr "Configurar mods" -#: builtin/mainmenu/tab_simple_main.lua:191 +#: builtin/mainmenu/tab_simple_main.lua:203 msgid "Main" msgstr "Principal" @@ -509,39 +538,195 @@ msgstr "Sin información disponible" msgid "Texturepacks" msgstr "Texturas" -#: src/client.cpp:2726 +#: 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 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:1063 +#: 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 msgid "Respawn" msgstr "Revivir" -#: src/game.cpp:2250 +#: 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 msgid "Item definitions..." msgstr "Definiciones de objetos..." -#: src/game.cpp:2255 +#: src/game.cpp:2279 msgid "Node definitions..." msgstr "Definiciones de nodos..." -#: src/game.cpp:2262 +#: src/game.cpp:2286 msgid "Media..." msgstr "Media..." -#: src/game.cpp:2267 +#: src/game.cpp:2291 msgid " KB/s" msgstr " KB/s" -#: src/game.cpp:2271 +#: src/game.cpp:2295 msgid " MB/s" msgstr " MB/s" -#: src/game.cpp:4220 +#: src/game.cpp:4210 msgid "" "\n" "Check debug.txt for details." @@ -549,14 +734,14 @@ msgstr "" "\n" "Consulta debug.txt para obtener más detalles." -#: src/guiFormSpecMenu.cpp:2055 -msgid "Proceed" -msgstr "Continuar" - -#: src/guiFormSpecMenu.cpp:2846 +#: src/guiFormSpecMenu.cpp:2797 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 "" @@ -647,23 +832,23 @@ msgstr "Seleccionar distancia" msgid "Print stacks" msgstr "Imprimir pilas" -#: src/guiPasswordChange.cpp:106 +#: src/guiPasswordChange.cpp:108 msgid "Old Password" msgstr "Contraseña anterior" -#: src/guiPasswordChange.cpp:122 +#: src/guiPasswordChange.cpp:124 msgid "New Password" msgstr "Contraseña nueva" -#: src/guiPasswordChange.cpp:137 +#: src/guiPasswordChange.cpp:139 msgid "Confirm Password" msgstr "Confirmar contraseña" -#: src/guiPasswordChange.cpp:153 +#: src/guiPasswordChange.cpp:155 msgid "Change" msgstr "Cambiar" -#: src/guiPasswordChange.cpp:162 +#: src/guiPasswordChange.cpp:164 msgid "Passwords do not match!" msgstr "¡Las contraseñas no coinciden!" @@ -963,210 +1148,3 @@ 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 910be7826..8dba0dc91 100644 --- a/po/ja/minetest.po +++ b/po/ja/minetest.po @@ -1,239 +1,26 @@ -# 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: 2013-11-23 17:37+0100\n" -"PO-Revision-Date: 2014-12-28 15:48+0900\n" +"POT-Creation-Date: 2015-02-14 23:12+0900\n" +"PO-Revision-Date: 2015-02-22 10:57+0900\n" "Last-Translator: Rui Takeda \n" -"Language-Team: Japanese\n" +"Language-Team: Japanese \n" +"Language: ja\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 "Game Name" -msgstr "ゲーム名" - -msgid "Create" -msgstr "作成" - -msgid "Cancel" -msgstr "キャンセル" - -msgid "Gamemgr: Unable to copy mod \"$1\" to game \"$2\"" -msgstr "Gamemgr: \"$1\"のModを \"$2\" にコピーできません" - -msgid "Games" -msgstr "ゲーム" - -msgid "Mods:" -msgstr "Mod:" - -msgid "edit game" -msgstr "ゲーム編集" - -msgid "new game" -msgstr "新規ゲーム" - -msgid "Remove selected mod" -msgstr "選択したModを削除" msgid "Ok" msgstr "決定" -msgid "World name" -msgstr "ワールド名" - -msgid "Seed" -msgstr "シード値" - -msgid "Mapgen" -msgstr "マップ生成" - -msgid "Game" -msgstr "ゲーム" - -msgid "Delete World \"$1\"?" -msgstr "\"$1\"のワールドを削除しますか?" - -msgid "Yes" -msgstr "はい" - -msgid "No" -msgstr "いいえ" - -msgid "A world named \"$1\" already exists" -msgstr "\"$1\"という名前のワールドを作成できません。同名のワールドが存在しています" - -msgid "No worldname given or no game selected" -msgstr "ワールド名が入力されていないか、ゲームが選択されていません" - -msgid "To enable shaders the OpenGL driver needs to be used." -msgstr "シェーダーを有効にするには、OpenGLのドライバが必要です" - -msgid "Address/Port" -msgstr "アドレス/ポート" - -msgid "Name/Password" -msgstr "名前/パスワード" - -msgid "Public Serverlist" -msgstr "公開されているサーバーリスト" - -msgid "Delete" -msgstr "削除" - -msgid "Connect" -msgstr "接続" - -msgid "New" -msgstr "作成" - -msgid "Configure" -msgstr "設定" - -msgid "Start Game" -msgstr "ゲームスタート" - -msgid "Select World:" -msgstr "ワールド選択:" - -msgid "Creative Mode" -msgstr "クリエイティブモード" - -msgid "Enable Damage" -msgstr "ダメージ有効" - -msgid "Public" -msgstr "公開する" - -msgid "Name" -msgstr "名前" - -msgid "Password" -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 "貢献者" - -msgid "Previous Contributors" -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 "オンラインで検索" - -msgid "No mod description available" -msgstr "Modの説明がありません" - -msgid "Mod information:" -msgstr "Modの情報:" - -msgid "Rename" -msgstr "名前を変更" - -msgid "Uninstall selected modpack" -msgstr "選択したModパックを削除" - -msgid "Uninstall selected mod" -msgstr "選択したModを削除" - -msgid "Rename Modpack:" -msgstr "Modパックの名前を変更" - -msgid "Accept" -msgstr "了承" - msgid "World:" msgstr "ワールド:" msgid "Hide Game" -msgstr "内部Mod" +msgstr "ゲームを隠す" msgid "Hide mp content" msgstr "Modパックの簡略化" @@ -247,6 +34,9 @@ msgstr "依存Mod:" msgid "Save" msgstr "保存" +msgid "Cancel" +msgstr "キャンセル" + msgid "Enable MP" msgstr "有効化" @@ -257,22 +47,103 @@ msgid "enabled" msgstr "有効化" msgid "Enable all" -msgstr "全て有効化" +msgstr "すべて有効化" -msgid "Modmgr: failed to delete \"$1\"" -msgstr "Modmgr: \"$1\"の削除に失敗しました" +msgid "World name" +msgstr "ワールド名" -msgid "Modmgr: invalid modpath \"$1\"" -msgstr "Modmgr: \"$1\"は無効なModパスです" +msgid "Seed" +msgstr "Seed値" + +msgid "Mapgen" +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\"を削除してよろしいですか?" +msgstr "本当に\"$1\"を削除してよろしいですか?" + +msgid "Yes" +msgstr "はい" msgid "No of course not!" -msgstr "違います!" +msgstr "いいえ" -msgid "Page $1 of $2" -msgstr "ページ $1/$2" +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 "Accept" +msgstr "決定" + +msgid "Install Mod: file: \"$1\"" +msgstr "Modインストール:ファイル\"$1\"からModをインストールします。" + +msgid "" +"\n" +"Install Mod: unsupported filetype \"$1\" or broken archive" +msgstr "" +"\n" +"Modインストール:ファイル\"$1\"は非対応の形式か、壊れています。" + +msgid "Failed to install $1 to $2" +msgstr "$2へ$1をインストールできませんでした。" + +msgid "Install Mod: unable to find suitable foldername for modpack $1" +msgstr "" +"Modインストール:Modパック$1に適したフォルダ名を見つけることができませんでし" +"た。" + +msgid "Install Mod: unable to find real modname for: $1" +msgstr "Modインストール:$1の本来のMod名が不明です。" + +msgid "Unsorted" +msgstr "未分類" + +msgid "Search" +msgstr "検索" + +msgid "Downloading $1, please wait..." +msgstr "$1をダウンロードしています。しばらくお待ちください..." + +msgid "Successfully installed:" +msgstr "インストールが完了しました。:" + +msgid "Shortname:" +msgstr "省略名" msgid "Rating" msgstr "評価" @@ -283,63 +154,415 @@ msgstr "再インストール" msgid "Install" msgstr "インストール" +msgid "Close store" +msgstr "閉じる" + +msgid "Page $1 of $2" +msgstr "ページ $1/$2" + +msgid "Credits" +msgstr "クレジット" + +msgid "Core Developers" +msgstr "開発者" + +msgid "Active Contributors" +msgstr "開発協力者" + +msgid "Previous Contributors" +msgstr "以前の開発協力者" + +msgid "Installed Mods:" +msgstr "インストール済みのMod:" + +msgid "Online mod repository" +msgstr "オンラインでModを検索" + +msgid "No mod description available" +msgstr "Modの説明がありません。" + +msgid "Mod information:" +msgstr "Modの情報:" + +msgid "Rename" +msgstr "名前を変更" + +msgid "Uninstall selected modpack" +msgstr "選択したModパックを削除" + +msgid "Uninstall selected mod" +msgstr "選択したModを削除" + +msgid "Select Mod File:" +msgstr "Modファイルを選択" + +msgid "Mods" +msgstr "Mod" + +msgid "Address / Port :" +msgstr "アドレスとポート:" + +msgid "Name / Password :" +msgstr "名前とパスワード:" + +msgid "Public Serverlist" +msgstr "公開済みのサーバーの一覧" + +msgid "Delete" +msgstr "削除" + +msgid "Connect" +msgstr "接続" + +msgid "Creative mode" +msgstr "クリエイティブモード" + +msgid "Damage enabled" +msgstr "HPあり" + +msgid "PvP enabled" +msgstr "PvPあり" + +msgid "Client" +msgstr "クライアント" + +msgid "New" +msgstr "作成" + +msgid "Configure" +msgstr "設定" + +msgid "Start Game" +msgstr "ゲームスタート" + +msgid "Select World:" +msgstr "ワールドを選択:" + +msgid "Creative Mode" +msgstr "クリエイティブモード" + +msgid "Enable Damage" +msgstr "ダメージあり" + +msgid "Public" +msgstr "サーバーを公開する" + +msgid "Name/Password" +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 "Item textures..." -msgstr "アイテムのテクスチャ設定中..." +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 "終了中..." 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 "Shutting down..." -msgstr "終了中..." +msgid " KB/s" +msgstr " KB/秒" + +msgid " MB/s" +msgstr " MB/秒" msgid "" "\n" "Check debug.txt for details." msgstr "" "\n" -"詳細はdebug.txtを御覧ください。" +"詳細はdebug.txtをご覧ください。" -msgid "You died." -msgstr "You died!" +msgid "Enter " +msgstr "Enter" -msgid "Respawn" -msgstr "Respawn" - -msgid "Proceed" +msgid "ok" 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 "キー入力待ち" @@ -351,19 +574,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 "落とす" @@ -381,16 +604,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 "スタックの表示" @@ -408,53 +631,13 @@ msgid "Change" msgstr "変更" msgid "Passwords do not match!" -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" +msgstr "パスワードが一致しません!" msgid "Sound Volume: " -msgstr "音量" +msgstr "音量:" msgid "Exit" -msgstr "戻る" +msgstr "閉じる" msgid "Left Button" msgstr "左ボタン" @@ -671,56 +854,3 @@ 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 new file mode 100644 index 000000000..385ae5bcd --- /dev/null +++ b/po/tr/minetest.po @@ -0,0 +1,1248 @@ +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 93083f369..fc053b104 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -355,9 +355,12 @@ add_subdirectory(jthread) add_subdirectory(script) add_subdirectory(util) +set (unittests_SRCS + test.cpp +) + set(common_SRCS ban.cpp - base64.cpp cavegen.cpp clientiface.cpp collision.cpp @@ -418,12 +421,10 @@ 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 @@ -432,6 +433,7 @@ set(common_SRCS ${JTHREAD_SRCS} ${common_SCRIPT_SRCS} ${UTIL_SRCS} + ${unittests_SRCS} ) # This gives us the icon and file version information diff --git a/src/activeobject.h b/src/activeobject.h index 46880fc7f..48f078d3f 100644 --- a/src/activeobject.h +++ b/src/activeobject.h @@ -23,7 +23,22 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irr_aabb3d.h" #include -#define ACTIVEOBJECT_TYPE_INVALID 0 +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, +}; // Other types are defined in content_object.h struct ActiveObjectMessage @@ -60,7 +75,7 @@ public: m_id = id; } - virtual u8 getType() const = 0; + virtual ActiveObjectType getType() const = 0; virtual bool getCollisionBox(aabb3f *toset) = 0; virtual bool collideWithObjects() = 0; protected: diff --git a/src/cavegen.cpp b/src/cavegen.cpp index 22bf03d17..8fb1a7293 100644 --- a/src/cavegen.cpp +++ b/src/cavegen.cpp @@ -20,6 +20,7 @@ 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" @@ -27,7 +28,263 @@ 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) { @@ -141,37 +398,68 @@ 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 * 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 + (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 ); // Jump downward sometimes if (!large_cave && ps->range(0, 12) == 0) { vec = v3f( - (float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2, + (float)(ps->next() % maxlen.X) - (float)maxlen.X / 2, (float)(ps->next() % (maxlen.Y * 2)) - (float)maxlen.Y, - (float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2 + (float)(ps->next() % maxlen.Z) - (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; @@ -279,12 +567,12 @@ void CaveV6::carveRoute(v3f vec, float f, bool randomize_xz) { ///////////////////////////////////////// Caves V7 -CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps, bool is_large_cave) { + +CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps) { 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; @@ -294,17 +582,10 @@ CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps, bool is_large_cave) { dswitchint = ps->range(1, 14); flooded = ps->range(1, 2) == 2; - 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); - } + 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); } @@ -335,15 +616,13 @@ 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); - 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); + 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; @@ -360,8 +639,7 @@ 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 = large_cave ? - GENNOTIFY_LARGECAVE_BEGIN : GENNOTIFY_CAVE_BEGIN; + GenNotifyType notifytype = GENNOTIFY_LARGECAVE_BEGIN; mg->gennotify.addEvent(notifytype, abs_pos); // Generate some tunnel starting from orp @@ -370,86 +648,60 @@ 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 = large_cave ? - GENNOTIFY_LARGECAVE_END : GENNOTIFY_CAVE_END; + notifytype = GENNOTIFY_LARGECAVE_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; - 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 - ); - } + maxlen = v3s16( + rs_part_max_length_rs, + rs_part_max_length_rs / 2, + rs_part_max_length_rs + ); v3f vec; // Jump downward sometimes - 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 - ); - } + 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. - if (large_cave) { - v3s16 orpi(orp.X, orp.Y, orp.Z); - v3s16 veci(vec.X, vec.Y, vec.Z); - v3s16 p; + 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 - } - - 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) - return; - } else if (p.Y > water_level) { + 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.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; } vec += main_direction; @@ -502,7 +754,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 ? lavanode : waternode; + MapNode liquidnode = (nval < 0.40 && node_max.Y < -256) ? lavanode : waternode; v3f fp = orp + vec * f; fp.X += 0.1 * ps->range(-10, 10); @@ -516,7 +768,6 @@ 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++) { @@ -528,10 +779,6 @@ 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) @@ -560,24 +807,17 @@ 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; - 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; + 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; - vm->m_flags[i] |= VMANIP_FLAG_CAVE; - } } } } } + diff --git a/src/cavegen.h b/src/cavegen.h index 7371df6fa..27626753a 100644 --- a/src/cavegen.h +++ b/src/cavegen.h @@ -22,9 +22,55 @@ 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; @@ -83,7 +129,6 @@ public: int dswitchint; int part_max_length_rs; - bool large_cave; bool large_cave_is_flat; bool flooded; @@ -109,7 +154,7 @@ public: int water_level; CaveV7() {} - CaveV7(MapgenV7 *mg, PseudoRandom *ps, bool large_cave); + CaveV7(MapgenV7 *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); diff --git a/src/cguittfont/CGUITTFont.cpp b/src/cguittfont/CGUITTFont.cpp index f6606996e..2342eb748 100644 --- a/src/cguittfont/CGUITTFont.cpp +++ b/src/cguittfont/CGUITTFont.cpp @@ -29,6 +29,7 @@ */ #include +#include #include "CGUITTFont.h" namespace irr @@ -64,8 +65,24 @@ 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); @@ -87,10 +104,11 @@ 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 (int y = 0; y < bits.rows; ++y) + + for (s32 y = 0; y < (s32)bits.rows; ++y) { u16* row = image_data; - for (int x = 0; x < bits.width; ++x) + for (s32 x = 0; x < (s32)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. @@ -116,10 +134,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 (int y = 0; y < bits.rows; ++y) + for (s32 y = 0; y < (s32)bits.rows; ++y) { u8* row = glyph_data; - for (int x = 0; x < bits.width; ++x) + for (s32 x = 0; x < (s32)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 c175c792a..eb7abe5a1 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 __MACH__ +#elif defined(__MACH__) && defined(__APPLE__) #include #elif defined(__FreeBSD__) #include diff --git a/src/client.cpp b/src/client.cpp index 2f70d624c..a21899fde 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -43,7 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "nodedef.h" #include "itemdef.h" #include "shader.h" -#include "base64.h" +#include "util/base64.h" #include "clientmap.h" #include "clientmedia.h" #include "sound.h" @@ -52,10 +52,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #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; @@ -271,28 +269,26 @@ 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_state(LC_Created), + m_localdb(NULL) { - /* - Add local player - */ - { - Player *player = new LocalPlayer(this, playername); + // Add local player + m_env.addPlayer(new LocalPlayer(this, playername)); - m_env.addPlayer(player); - } + m_cache_save_interval = g_settings->getU16("server_map_save_interval"); 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(); - if (localdb != NULL) { - actionstream << "Local map saving ended" << std::endl; - localdb->endSave(); - delete localserver; + // Save local server map + if (m_localdb) { + infostream << "Local map saving ended." << std::endl; + m_localdb->endSave(); } } @@ -535,7 +531,7 @@ void Client::step(float 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::list deleted_blocks; + std::vector deleted_blocks; m_env.getMap().timerUpdate(map_timer_and_unload_dtime, g_settings->getFloat("client_unload_unused_data_timeout"), &deleted_blocks); @@ -549,8 +545,8 @@ void Client::step(float dtime) NOTE: This loop is intentionally iterated the way it is. */ - std::list::iterator i = deleted_blocks.begin(); - std::list sendlist; + std::vector::iterator i = deleted_blocks.begin(); + std::vector sendlist; for(;;) { if(sendlist.size() == 255 || i == deleted_blocks.end()) @@ -569,7 +565,7 @@ void Client::step(float dtime) writeU16(&reply[0], TOSERVER_DELETEDBLOCKS); reply[2] = sendlist.size(); u32 k = 0; - for(std::list::iterator + for(std::vector::iterator j = sendlist.begin(); j != sendlist.end(); ++j) { @@ -807,6 +803,13 @@ void Client::step(float dtime) 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) @@ -906,7 +909,7 @@ void Client::deletingPeer(con::Peer *peer, bool timeout) string name } */ -void Client::request_media(const std::list &file_requests) +void Client::request_media(const std::vector &file_requests) { std::ostringstream os(std::ios_base::binary); writeU16(os, TOSERVER_REQUEST_MEDIA); @@ -914,7 +917,7 @@ void Client::request_media(const std::list &file_requests) assert(file_requests_size <= 0xFFFF); writeU16(os, (u16) (file_requests_size & 0xFFFF)); - for(std::list::const_iterator i = file_requests.begin(); + for(std::vector::const_iterator i = file_requests.begin(); i != file_requests.end(); ++i) { os<getBool("enable_local_map_saving") || is_local_server) + 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()); - SubgameSpec gamespec; + fs::CreateAllDirs(world_path); - 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(); + m_localdb = new Database_SQLite3(world_path); + m_localdb->beginSave(); actionstream << "Local map saving started, map will be saved at '" << world_path << "'" << std::endl; } @@ -1209,8 +1197,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) sector->insertBlock(block); } - if (localdb != NULL) { - ((ServerMap&) localserver->getMap()).saveBlock(block, localdb); + if (m_localdb) { + ServerMap::saveBlock(block, m_localdb); } /* @@ -2613,7 +2601,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); + MeshMakeData *data = new MeshMakeData(this, m_cache_enable_shaders); { //TimeTaker timer("data fill"); @@ -2807,7 +2795,8 @@ void Client::makeScreenshot(IrrlichtDevice *device) if (image) { raw_image->copyTo(image); irr::c8 filename[256]; - snprintf(filename, sizeof(filename), "%s" DIR_DELIM "screenshot_%u.png", + snprintf(filename, sizeof(filename), + (std::string("%s") + DIR_DELIM + "screenshot_%u.png").c_str(), g_settings->get("screenshot_path").c_str(), device->getTimer()->getRealTime()); std::ostringstream sstr; diff --git a/src/client.h b/src/client.h index fd7e5f08d..db7e0fc45 100644 --- a/src/client.h +++ b/src/client.h @@ -47,7 +47,6 @@ struct MapDrawControl; class MtEventManager; struct PointedThing; class Database; -class Server; struct QueuedMeshUpdate { @@ -465,7 +464,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::list &file_requests); + void request_media(const std::vector &file_requests); // Send a notification that no conventional media transfer is needed void received_media(); @@ -569,11 +568,13 @@ private: LocalClientState m_state; // Used for saving server map to disk client-side - Database *localdb; - Server *localserver; + Database *m_localdb; + IntervalLimiter m_localdb_save_interval; + u16 m_cache_save_interval; - // TODO: Add callback to update this when g_settings changes + // TODO: Add callback to update these when g_settings changes bool m_cache_smooth_lighting; + bool m_cache_enable_shaders; }; #endif // !CLIENT_HEADER diff --git a/src/clientiface.cpp b/src/clientiface.cpp index 40d1ef811..6b1666fd9 100644 --- a/src/clientiface.cpp +++ b/src/clientiface.cpp @@ -59,7 +59,7 @@ void RemoteClient::ResendBlockIfOnWire(v3s16 p) } } -void RemoteClient::GetNextBlocks( +void RemoteClient::GetNextBlocks ( ServerEnvironment *env, EmergeManager * emerge, float dtime, @@ -182,18 +182,15 @@ 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::list list; - getFacePositions(list, d); + std::vector list = FacePositionCache::getFacePositions(d); - std::list::iterator li; - for(li=list.begin(); li!=list.end(); ++li) - { + std::vector::iterator li; + for(li = list.begin(); li != list.end(); ++li) { v3s16 p = *li + center; /* diff --git a/src/clientmap.cpp b/src/clientmap.cpp index 2db901f22..1c420b5f9 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){ - count++; - if(count >= needed_count) + if(count == needed_count) return true; + count++; } step *= stepfac; } @@ -247,7 +247,7 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver) continue; } - std::list< MapBlock * > sectorblocks; + MapBlockVect sectorblocks; sector->getBlocks(sectorblocks); /* @@ -256,8 +256,8 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver) u32 sector_blocks_drawn = 0; - std::list< MapBlock * >::iterator i; - for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++) + for(MapBlockVect::iterator 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::list bufs; + std::vector bufs; }; struct MeshBufListList { - std::list lists; + std::vector lists; void clear() { @@ -405,7 +405,7 @@ struct MeshBufListList void add(scene::IMeshBuffer *buf) { - for(std::list::iterator i = lists.begin(); + for(std::vector::iterator i = lists.begin(); i != lists.end(); ++i){ MeshBufList &l = *i; video::SMaterial &m = buf->getMaterial(); @@ -595,25 +595,20 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) } } - std::list &lists = drawbufs.lists; + std::vector &lists = drawbufs.lists; int timecheck_counter = 0; - 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." - <::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; } } @@ -621,60 +616,14 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) driver->setMaterial(list.m); - for(std::list::iterator j = list.bufs.begin(); - j != list.bufs.end(); ++j) - { + for(std::vector::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 434eeb248..0b63b14b1 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 "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::list file_requests; + std::vector 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 37f693c5e..ae1be092f 100644 --- a/src/clientobject.cpp +++ b/src/clientobject.cpp @@ -39,14 +39,13 @@ ClientActiveObject::~ClientActiveObject() removeFromScene(true); } -ClientActiveObject* ClientActiveObject::create(u8 type, IGameDef *gamedef, - ClientEnvironment *env) +ClientActiveObject* ClientActiveObject::create(ActiveObjectType 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::vector 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); } @@ -319,12 +317,10 @@ 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); @@ -333,16 +329,14 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, } } - for (std::list::const_iterator iter = objects.begin();iter != objects.end(); ++iter) - { + for (std::vector::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/constants.h b/src/constants.h index 9a7bb9d86..d7163bf68 100644 --- a/src/constants.h +++ b/src/constants.h @@ -100,7 +100,13 @@ with this program; if not, write to the Free Software Foundation, Inc., /* GUI related things */ -#define TTF_DEFAULT_FONT_SIZE (14) + +// 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 DEFAULT_FONT_SIZE (10) #endif diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 6d41b2749..ddfa3b032 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -34,7 +34,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serialization.h" // For decompressZlib #include "gamedef.h" #include "clientobject.h" -#include "content_object.h" #include "mesh.h" #include "itemdef.h" #include "tool.h" @@ -145,7 +144,7 @@ public: TestCAO(IGameDef *gamedef, ClientEnvironment *env); virtual ~TestCAO(); - u8 getType() const + ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_TEST; } @@ -289,7 +288,7 @@ public: ItemCAO(IGameDef *gamedef, ClientEnvironment *env); virtual ~ItemCAO(); - u8 getType() const + ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_ITEM; } @@ -963,7 +962,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->getBuiltInFont(), + m_textnode = smgr->addTextSceneNode(gui->getSkin()->getFont(), 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 69e2e54a2..31ccd04d4 100644 --- a/src/content_cao.h +++ b/src/content_cao.h @@ -22,7 +22,6 @@ 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" @@ -115,7 +114,7 @@ public: return new GenericCAO(gamedef, env); } - inline u8 getType() const + inline ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_GENERIC; } diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index 9af3be789..82a134ada 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -45,8 +45,7 @@ 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); @@ -55,8 +54,7 @@ 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, @@ -160,14 +158,16 @@ 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,54 +191,6 @@ 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++) @@ -1469,77 +1421,65 @@ 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 - bool self_connect_to_raillike = ((ItemGroupList) nodedef->get(n).groups)[groupname] != 0; + int self_group = ((ItemGroupList) nodedef->get(n).groups)[groupname]; if ((nodedef->get(n_minus_x).drawtype == NDT_RAILLIKE - && ((ItemGroupList) nodedef->get(n_minus_x).groups)[groupname] != 0 - && self_connect_to_raillike) + && ((ItemGroupList) nodedef->get(n_minus_x).groups)[groupname] != self_group) || 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] != 0 - && self_connect_to_raillike) + && ((ItemGroupList) nodedef->get(n_minus_x_minus_y).groups)[groupname] != self_group) || 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] != 0 - && self_connect_to_raillike) + && ((ItemGroupList) nodedef->get(n_minus_x_plus_y).groups)[groupname] != self_group) || 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] != 0 - && self_connect_to_raillike) + && ((ItemGroupList) nodedef->get(n_plus_x).groups)[groupname] != self_group) || 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] != 0 - && self_connect_to_raillike) + && ((ItemGroupList) nodedef->get(n_plus_x_minus_y).groups)[groupname] != self_group) || 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] != 0 - && self_connect_to_raillike) + && ((ItemGroupList) nodedef->get(n_plus_x_plus_y).groups)[groupname] != self_group) || 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] != 0 - && self_connect_to_raillike) + && ((ItemGroupList) nodedef->get(n_minus_z).groups)[groupname] != self_group) || 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] != 0 - && self_connect_to_raillike) + && ((ItemGroupList) nodedef->get(n_minus_z_minus_y).groups)[groupname] != self_group) || 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] != 0 - && self_connect_to_raillike) + && ((ItemGroupList) nodedef->get(n_minus_z_plus_y).groups)[groupname] != self_group) || 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] != 0 - && self_connect_to_raillike) + && ((ItemGroupList) nodedef->get(n_plus_z).groups)[groupname] != self_group) || 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] != 0 - && self_connect_to_raillike) + && ((ItemGroupList) nodedef->get(n_plus_z_minus_y).groups)[groupname] != self_group) || 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] != 0 - && self_connect_to_raillike) + && ((ItemGroupList) nodedef->get(n_plus_z_plus_y).groups)[groupname] != self_group) || n_plus_z_plus_y.getContent() == thiscontent) is_rail_z_plus_y[1] = true; @@ -1766,5 +1706,55 @@ 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/content_object.h b/src/content_object.h deleted file mode 100644 index 65a829773..000000000 --- a/src/content_object.h +++ /dev/null @@ -1,39 +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 CONTENT_OBJECT_HEADER -#define CONTENT_OBJECT_HEADER - -#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 - -#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 d4b3079ec..78f5275d1 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -35,54 +35,6 @@ with this program; if not, write to the Free Software Foundation, Inc., 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 */ @@ -965,7 +720,6 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_, 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), @@ -1171,13 +925,7 @@ void PlayerSAO::step(float dtime, bool send_recommended) m_messages_out.push_back(aom); } - if(m_wielded_item_not_sent) - { - m_wielded_item_not_sent = false; - // GenericCAO has no special way to show this - } - - if(m_armor_groups_sent == false){ + if(m_armor_groups_sent == false) { m_armor_groups_sent = true; std::string str = gob_cmd_update_armor_groups( m_armor_groups); @@ -1442,10 +1190,8 @@ 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; } } diff --git a/src/content_sao.h b/src/content_sao.h index 38baeab3a..b5550903b 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -21,14 +21,10 @@ 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. */ @@ -39,9 +35,9 @@ public: LuaEntitySAO(ServerEnvironment *env, v3f pos, const std::string &name, const std::string &state); ~LuaEntitySAO(); - u8 getType() const + ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_LUAENTITY; } - u8 getSendType() const + ActiveObjectType getSendType() const { return ACTIVEOBJECT_TYPE_GENERIC; } virtual void addedToEnvironment(u32 dtime_s); static ServerActiveObject* create(ServerEnvironment *env, v3f pos, @@ -158,9 +154,9 @@ public: PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_, const std::set &privs, bool is_singleplayer); ~PlayerSAO(); - u8 getType() const + ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_PLAYER; } - u8 getSendType() const + ActiveObjectType getSendType() const { return ACTIVEOBJECT_TYPE_GENERIC; } std::string getDescription(); @@ -324,7 +320,6 @@ public: 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; diff --git a/src/database-dummy.cpp b/src/database-dummy.cpp index 271d9c975..71f60d81c 100644 --- a/src/database-dummy.cpp +++ b/src/database-dummy.cpp @@ -18,64 +18,38 @@ 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" -Database_Dummy::Database_Dummy(ServerMap *map) +bool Database_Dummy::saveBlock(const v3s16 &pos, const std::string &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; + m_database[getBlockAsInteger(pos)] = data; return true; } -std::string Database_Dummy::loadBlock(v3s16 blockpos) +std::string Database_Dummy::loadBlock(const v3s16 &pos) { - if (m_database.count(getBlockAsInteger(blockpos))) - return m_database[getBlockAsInteger(blockpos)]; + s64 i = getBlockAsInteger(pos); + if (m_database.count(i)) + return m_database[i]; else return ""; } -bool Database_Dummy::deleteBlock(v3s16 blockpos) +bool Database_Dummy::deleteBlock(const v3s16 &pos) { - m_database.erase(getBlockAsInteger(blockpos)); + m_database.erase(getBlockAsInteger(pos)); return true; } -void Database_Dummy::listAllLoadableBlocks(std::list &dst) +void Database_Dummy::listAllLoadableBlocks(std::vector &dst) { - for(std::map::iterator x = m_database.begin(); x != m_database.end(); ++x) - { - v3s16 p = getIntegerAsBlock(x->first); - //dstream<<"block_i="< &dst); - virtual int Initialized(void); - ~Database_Dummy(); + 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: - ServerMap *srvmap; - std::map m_database; + std::map m_database; }; + #endif + diff --git a/src/database-leveldb.cpp b/src/database-leveldb.cpp index de510e533..e895354a4 100644 --- a/src/database-leveldb.cpp +++ b/src/database-leveldb.cpp @@ -22,57 +22,54 @@ with this program; if not, write to the Free Software Foundation, Inc., #if USE_LEVELDB #include "database-leveldb.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" +#include "exceptions.h" +#include "util/string.h" + +#include "leveldb/db.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(ServerMap *map, std::string savedir) + +Database_LevelDB::Database_LevelDB(const 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; } -int Database_LevelDB::Initialized(void) +Database_LevelDB::~Database_LevelDB() { - return 1; + delete m_database; } -void Database_LevelDB::beginSave() {} -void Database_LevelDB::endSave() {} - -bool Database_LevelDB::saveBlock(v3s16 blockpos, std::string &data) +bool Database_LevelDB::saveBlock(const v3s16 &pos, const std::string &data) { leveldb::Status status = m_database->Put(leveldb::WriteOptions(), - i64tos(getBlockAsInteger(blockpos)), data); + i64tos(getBlockAsInteger(pos)), data); if (!status.ok()) { errorstream << "WARNING: saveBlock: LevelDB error saving block " - << PP(blockpos) << ": " << status.ToString() << std::endl; + << PP(pos) << ": " << status.ToString() << std::endl; return false; } return true; } -std::string Database_LevelDB::loadBlock(v3s16 blockpos) +std::string Database_LevelDB::loadBlock(const v3s16 &pos) { std::string datastr; leveldb::Status status = m_database->Get(leveldb::ReadOptions(), - i64tos(getBlockAsInteger(blockpos)), &datastr); + i64tos(getBlockAsInteger(pos)), &datastr); if(status.ok()) return datastr; @@ -80,20 +77,20 @@ std::string Database_LevelDB::loadBlock(v3s16 blockpos) return ""; } -bool Database_LevelDB::deleteBlock(v3s16 blockpos) +bool Database_LevelDB::deleteBlock(const v3s16 &pos) { leveldb::Status status = m_database->Delete(leveldb::WriteOptions(), - i64tos(getBlockAsInteger(blockpos))); + i64tos(getBlockAsInteger(pos))); if (!status.ok()) { errorstream << "WARNING: deleteBlock: LevelDB error deleting block " - << PP(blockpos) << ": " << status.ToString() << std::endl; + << PP(pos) << ": " << status.ToString() << std::endl; return false; } return true; } -void Database_LevelDB::listAllLoadableBlocks(std::list &dst) +void Database_LevelDB::listAllLoadableBlocks(std::vector &dst) { leveldb::Iterator* it = m_database->NewIterator(leveldb::ReadOptions()); for (it->SeekToFirst(); it->Valid(); it->Next()) { @@ -103,8 +100,5 @@ void Database_LevelDB::listAllLoadableBlocks(std::list &dst) delete it; } -Database_LevelDB::~Database_LevelDB() -{ - delete m_database; -} -#endif +#endif // USE_LEVELDB + diff --git a/src/database-leveldb.h b/src/database-leveldb.h index c195260da..4afe2fdc7 100644 --- a/src/database-leveldb.h +++ b/src/database-leveldb.h @@ -28,23 +28,22 @@ 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(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(const std::string &savedir); ~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: - ServerMap *srvmap; - leveldb::DB* m_database; + leveldb::DB *m_database; }; + +#endif // USE_LEVELDB + #endif -#endif + diff --git a/src/database-redis.cpp b/src/database-redis.cpp index b086f899d..7b42274b9 100644 --- a/src/database-redis.cpp +++ b/src/database-redis.cpp @@ -20,151 +20,140 @@ 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 "filesys.h" +#include "exceptions.h" +#include "util/string.h" + +#include +#include -Database_Redis::Database_Redis(ServerMap *map, std::string savedir) +Database_Redis::Database_Redis(Settings &conf) { - 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 e) { - 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) { + 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; -} - -int Database_Redis::Initialized(void) -{ - return 1; -} - -void Database_Redis::beginSave() { - 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; - reply = (redisReply*) redisCommand(ctx, "EXEC"); - if(!reply) - throw FileNotGoodException(std::string("redis command 'EXEC' failed: ") + ctx->errstr); - freeReplyObject(reply); -} - -bool Database_Redis::saveBlock(v3s16 blockpos, std::string &data) -{ - std::string tmp = i64tos(getBlockAsInteger(blockpos)); - - 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(blockpos) << ": " << ctx->errstr << std::endl; - freeReplyObject(reply); - return false; - } - - if (reply->type == REDIS_REPLY_ERROR) { - errorstream << "WARNING: saveBlock: saving block " << PP(blockpos) - << "failed" << std::endl; - freeReplyObject(reply); - return false; - } - - freeReplyObject(reply); - return true; -} - -std::string Database_Redis::loadBlock(v3s16 blockpos) -{ - 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); - 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(v3s16 blockpos) -{ - std::string tmp = i64tos(getBlockAsInteger(blockpos)); - - redisReply *reply = (redisReply *)redisCommand(ctx, "HDEL %s %s", - hash.c_str(), tmp.c_str()); - if (!reply) { - 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; - } - - freeReplyObject(reply); - return true; -} - -void Database_Redis::listAllLoadableBlocks(std::list &dst) -{ - 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++) - { - assert(reply->element[i]->type == REDIS_REPLY_STRING); - dst.push_back(getIntegerAsBlock(stoi64(reply->element[i]->str))); - } - freeReplyObject(reply); } Database_Redis::~Database_Redis() { redisFree(ctx); } -#endif + +void Database_Redis::beginSave() { + redisReply *reply = static_cast(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); + } + freeReplyObject(reply); +} + +bool Database_Redis::saveBlock(const v3s16 &pos, const std::string &data) +{ + std::string tmp = i64tos(getBlockAsInteger(pos)); + + redisReply *reply = static_cast(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; + freeReplyObject(reply); + return false; + } + + if (reply->type == REDIS_REPLY_ERROR) { + errorstream << "WARNING: saveBlock: saving block " << PP(pos) + << "failed" << std::endl; + freeReplyObject(reply); + return false; + } + + freeReplyObject(reply); + return true; +} + +std::string Database_Redis::loadBlock(const v3s16 &pos) +{ + std::string tmp = i64tos(getBlockAsInteger(pos)); + redisReply *reply = static_cast(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) { + 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) +{ + std::string tmp = i64tos(getBlockAsInteger(pos)); + + redisReply *reply = static_cast(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; + freeReplyObject(reply); + return false; + } + + freeReplyObject(reply); + return true; +} + +void Database_Redis::listAllLoadableBlocks(std::vector &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) { + throw FileNotGoodException("Failed to get keys from database"); + } + 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 + diff --git a/src/database-redis.h b/src/database-redis.h index 34b90fa59..45e702c83 100644 --- a/src/database-redis.h +++ b/src/database-redis.h @@ -28,24 +28,28 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include -class ServerMap; +class Settings; class Database_Redis : public Database { public: - Database_Redis(ServerMap *map, std::string savedir); + Database_Redis(Settings &conf); + ~Database_Redis(); + 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_Redis(); + + 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: - 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 0679da97d..3480894c9 100644 --- a/src/database-sqlite3.cpp +++ b/src/database-sqlite3.cpp @@ -18,297 +18,231 @@ with this program; if not, write to the Free Software Foundation, Inc., */ /* - 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 +SQLite format specification: + blocks: + (PK) INT id + BLOB data */ #include "database-sqlite3.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" +#include "exceptions.h" +#include "main.h" +#include "settings.h" +#include "util/string.h" -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; -} +#include -int Database_SQLite3::Initialized(void) + +#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) { - return m_database ? 1 : 0; } void Database_SQLite3::beginSave() { verifyDatabase(); - if(sqlite3_exec(m_database, "BEGIN;", NULL, NULL, NULL) != SQLITE_OK) - errorstream<<"WARNING: beginSave() failed, saving might be slow."; + SQLRES(sqlite3_step(m_stmt_begin), SQLITE_DONE); + sqlite3_reset(m_stmt_begin); } void Database_SQLite3::endSave() { verifyDatabase(); - if(sqlite3_exec(m_database, "COMMIT;", NULL, NULL, NULL) != SQLITE_OK) - errorstream<<"WARNING: endSave() failed, map might not have saved."; + SQLRES(sqlite3_step(m_stmt_end), SQLITE_DONE); + sqlite3_reset(m_stmt_end); } -void Database_SQLite3::createDirs(std::string path) +void Database_SQLite3::openDatabase() { - if(fs::CreateAllDirs(path) == false) - { - infostream< &dst) +void Database_SQLite3::listAllLoadableBlocks(std::vector &dst) { verifyDatabase(); - 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 int Initialized(void); + 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 initialized() const { return m_initialized; } ~Database_SQLite3(); -private: - 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; +private: + // Open the database + void openDatabase(); // Create the database structure void createDatabase(); - // Verify we can read/write to the database + // Open and initialize the database if needed void verifyDatabase(); - void createDirs(std::string path); + + 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; }; #endif + diff --git a/src/database.cpp b/src/database.cpp index 26f6992fc..262d475ec 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) const +s64 Database::getBlockAsInteger(const v3s16 &pos) { return (u64) pos.Z * 0x1000000 + (u64) pos.Y * 0x1000 + @@ -56,7 +56,7 @@ s64 Database::getBlockAsInteger(const v3s16 pos) const } -v3s16 Database::getIntegerAsBlock(s64 i) const +v3s16 Database::getIntegerAsBlock(s64 i) { v3s16 pos; pos.X = unsigned_to_signed(pythonmodulo(i, 4096), 2048); diff --git a/src/database.h b/src/database.h index f04c4aa50..cee7b6fd9 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,16 +32,22 @@ with this program; if not, write to the Free Software Foundation, Inc., class Database { public: - virtual void beginSave() = 0; - virtual void endSave() = 0; + virtual ~Database() {} - 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() {}; + 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; } }; + #endif + diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 6504c5155..f49fbb008 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -48,6 +48,7 @@ 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"); @@ -115,6 +116,9 @@ 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"); @@ -288,6 +292,7 @@ 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 eb452a196..3b7e755b3 100644 --- a/src/dungeongen.cpp +++ b/src/dungeongen.cpp @@ -79,14 +79,17 @@ 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); - // Set all air and water to be untouchable to make dungeons open - // to caves and open air + 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 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) + if (c == CONTENT_AIR || c == dp.c_water + || (no_float && c == CONTENT_IGNORE)) vm->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE; i++; } diff --git a/src/emerge.cpp b/src/emerge.cpp index c485caffa..a697bcb07 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -361,7 +361,10 @@ void EmergeManager::loadParamsFromSettings(Settings *settings) std::string seed_str; const char *setname = (settings == g_settings) ? "fixed_map_seed" : "seed"; - if (settings->getNoEx(setname, seed_str) && !seed_str.empty()) { + if (!settings->getNoEx("seed", seed_str)) { + g_settings->getNoEx(setname, seed_str); + } + if (!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 e1f79803b..85fa9cff0 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -61,9 +61,8 @@ Environment::Environment(): Environment::~Environment() { // Deallocate players - for(std::list::iterator i = m_players.begin(); - i != m_players.end(); ++i) - { + for(std::vector::iterator i = m_players.begin(); + i != m_players.end(); ++i) { delete (*i); } } @@ -89,7 +88,7 @@ void Environment::removePlayer(u16 peer_id) { DSTACK(__FUNCTION_NAME); - for(std::list::iterator i = m_players.begin(); + for(std::vector::iterator i = m_players.begin(); i != m_players.end();) { Player *player = *i; @@ -104,7 +103,7 @@ void Environment::removePlayer(u16 peer_id) void Environment::removePlayer(const char *name) { - for (std::list::iterator it = m_players.begin(); + for (std::vector::iterator it = m_players.begin(); it != m_players.end(); ++it) { if (strcmp((*it)->getName(), name) == 0) { delete *it; @@ -116,9 +115,8 @@ void Environment::removePlayer(const char *name) Player * Environment::getPlayer(u16 peer_id) { - for(std::list::iterator i = m_players.begin(); - i != m_players.end(); ++i) - { + for(std::vector::iterator i = m_players.begin(); + i != m_players.end(); ++i) { Player *player = *i; if(player->peer_id == peer_id) return player; @@ -128,9 +126,8 @@ Player * Environment::getPlayer(u16 peer_id) Player * Environment::getPlayer(const char *name) { - for(std::list::iterator i = m_players.begin(); - i != m_players.end(); ++i) - { + for(std::vector::iterator i = m_players.begin(); + i != m_players.end(); ++i) { Player *player = *i; if(strcmp(player->getName(), name) == 0) return player; @@ -140,15 +137,13 @@ Player * Environment::getPlayer(const char *name) Player * Environment::getRandomConnectedPlayer() { - std::list connected_players = getPlayers(true); + std::vector connected_players = getPlayers(true); u32 chosen_one = myrand() % connected_players.size(); u32 j = 0; - for(std::list::iterator + for(std::vector::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; } @@ -159,17 +154,15 @@ Player * Environment::getRandomConnectedPlayer() Player * Environment::getNearestConnectedPlayer(v3f pos) { - std::list connected_players = getPlayers(true); + std::vector connected_players = getPlayers(true); f32 nearest_d = 0; Player *nearest_player = NULL; - for(std::list::iterator + for(std::vector::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; } @@ -177,22 +170,20 @@ Player * Environment::getNearestConnectedPlayer(v3f pos) return nearest_player; } -std::list Environment::getPlayers() +std::vector Environment::getPlayers() { return m_players; } -std::list Environment::getPlayers(bool ignore_disconnected) +std::vector Environment::getPlayers(bool ignore_disconnected) { - std::list newlist; - for(std::list::iterator + std::vector newlist; + for(std::vector::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; @@ -212,24 +203,42 @@ u32 Environment::getDayNightRatio() void Environment::setTimeOfDaySpeed(float speed) { - JMutexAutoLock(this->m_lock); + JMutexAutoLock(this->m_timeofday_lock); m_time_of_day_speed = speed; } float Environment::getTimeOfDaySpeed() { - JMutexAutoLock(this->m_lock); + JMutexAutoLock(this->m_timeofday_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) { - float day_speed = 0; - { - JMutexAutoLock(this->m_lock); - day_speed = m_time_of_day_speed; - } + // getTimeOfDaySpeed lock the value we need to prevent MT problems + float day_speed = getTimeOfDaySpeed(); m_time_counter += dtime; f32 speed = day_speed * 24000./(24.*3600); @@ -287,7 +296,7 @@ void fillRadiusBlock(v3s16 p0, s16 r, std::set &list) } } -void ActiveBlockList::update(std::list &active_positions, +void ActiveBlockList::update(std::vector &active_positions, s16 radius, std::set &blocks_removed, std::set &blocks_added) @@ -296,7 +305,7 @@ void ActiveBlockList::update(std::list &active_positions, Create the new list */ std::set newlist = m_forceloaded_list; - for(std::list::iterator i = active_positions.begin(); + for(std::vector::iterator i = active_positions.begin(); i != active_positions.end(); ++i) { fillRadiusBlock(*i, radius, newlist); @@ -373,7 +382,7 @@ ServerEnvironment::~ServerEnvironment() m_map->drop(); // Delete ActiveBlockModifiers - for(std::list::iterator + for(std::vector::iterator i = m_abms.begin(); i != m_abms.end(); ++i){ delete i->abm; } @@ -395,8 +404,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) { @@ -421,7 +430,7 @@ void ServerEnvironment::saveLoadedPlayers() std::string players_path = m_path_world + DIR_DELIM "players"; fs::CreateDir(players_path); - for (std::list::iterator it = m_players.begin(); + for (std::vector::iterator it = m_players.begin(); it != m_players.end(); ++it) { RemotePlayer *player = static_cast(*it); @@ -549,9 +558,9 @@ class ABMHandler { private: ServerEnvironment *m_env; - std::map > m_aabms; + std::map > m_aabms; public: - ABMHandler(std::list &abms, + ABMHandler(std::vector &abms, float dtime_s, ServerEnvironment *env, bool use_timers): m_env(env) @@ -559,8 +568,8 @@ public: if(dtime_s < 0.001) return; INodeDefManager *ndef = env->getGameDef()->ndef(); - for(std::list::iterator - i = abms.begin(); i != abms.end(); ++i){ + for(std::vector::iterator + i = abms.begin(); i != abms.end(); ++i) { ActiveBlockModifier *abm = i->abm; float trigger_interval = abm->getTriggerInterval(); if(trigger_interval < 0.001) @@ -604,10 +613,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::list aabmlist; + std::vector aabmlist; m_aabms[c] = aabmlist; j = m_aabms.find(c); } @@ -664,14 +673,13 @@ 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::list::iterator - i = j->second.begin(); i != j->second.end(); i++) - { + for(std::vector::iterator + i = j->second.begin(); i != j->second.end(); i++) { if(myrand() % i->chance != 0) continue; @@ -851,11 +859,10 @@ void ServerEnvironment::clearAllObjects() { infostream<<"ServerEnvironment::clearAllObjects(): " <<"Removing all active objects"< objects_to_remove; + std::vector 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; @@ -888,15 +895,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::list::iterator i = objects_to_remove.begin(); - i != objects_to_remove.end(); ++i) - { + for(std::vector::iterator i = objects_to_remove.begin(); + i != objects_to_remove.end(); ++i) { m_active_objects.erase(*i); } // Get list of loaded blocks - std::list loaded_blocks; + std::vector loaded_blocks; infostream<<"ServerEnvironment::clearAllObjects(): " <<"Listing all loaded blocks"<listAllLoadedBlocks(loaded_blocks); @@ -905,7 +912,7 @@ void ServerEnvironment::clearAllObjects() < loadable_blocks; + std::vector loadable_blocks; infostream<<"ServerEnvironment::clearAllObjects(): " <<"Listing all loadable blocks"<listAllLoadableBlocks(loadable_blocks); @@ -915,9 +922,8 @@ void ServerEnvironment::clearAllObjects() <<", now clearing"<::iterator i = loaded_blocks.begin(); - i != loaded_blocks.end(); ++i) - { + for(std::vector::iterator i = loaded_blocks.begin(); + i != loaded_blocks.end(); ++i) { v3s16 p = *i; MapBlock *block = m_map->getBlockNoCreateNoEx(p); assert(block); @@ -931,9 +937,8 @@ void ServerEnvironment::clearAllObjects() u32 num_blocks_checked = 0; u32 num_blocks_cleared = 0; u32 num_objs_cleared = 0; - for(std::list::iterator i = loadable_blocks.begin(); - i != loadable_blocks.end(); ++i) - { + for(std::vector::iterator i = loadable_blocks.begin(); + i != loadable_blocks.end(); ++i) { v3s16 p = *i; MapBlock *block = m_map->emergeBlock(p, false); if(!block){ @@ -969,9 +974,8 @@ void ServerEnvironment::clearAllObjects() m_map->unloadUnreferencedBlocks(); // Drop references that were added above - for(std::list::iterator i = loaded_blocks.begin(); - i != loaded_blocks.end(); ++i) - { + for(std::vector::iterator i = loaded_blocks.begin(); + i != loaded_blocks.end(); ++i) { v3s16 p = *i; MapBlock *block = m_map->getBlockNoCreateNoEx(p); assert(block); @@ -1012,7 +1016,7 @@ void ServerEnvironment::step(float dtime) */ { ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG); - for(std::list::iterator i = m_players.begin(); + for(std::vector::iterator i = m_players.begin(); i != m_players.end(); ++i) { Player *player = *i; @@ -1035,15 +1039,15 @@ void ServerEnvironment::step(float dtime) /* Get player block positions */ - std::list players_blockpos; - for(std::list::iterator + std::vector players_blockpos; + for(std::vector::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); @@ -1178,7 +1182,7 @@ void ServerEnvironment::step(float dtime) <<") being handled"<getBlockNoCreateNoEx(p); - if(block==NULL) + if(block == NULL) continue; // Set current time as timestamp @@ -1542,11 +1546,10 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, */ void ServerEnvironment::removeRemovedObjects() { - std::list objects_to_remove; + std::vector 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 @@ -1616,13 +1619,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::list::iterator i = objects_to_remove.begin(); - i != objects_to_remove.end(); ++i) - { + for(std::vector::iterator i = objects_to_remove.begin(); + i != objects_to_remove.end(); ++i) { m_active_objects.erase(*i); } } @@ -1666,17 +1669,19 @@ 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()) @@ -1690,20 +1695,17 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s) } // Activate stored objects - std::list new_stored; - for(std::list::iterator + std::vector new_stored; + for (std::vector::iterator i = block->m_static_objects.m_stored.begin(); - i != block->m_static_objects.m_stored.end(); ++i) - { - /*infostream<<"Server: Creating an active object from " - <<"static data"<m_static_objects.m_stored.end(); ++i) { StaticObject &s_obj = *i; + // Create an active object from the data ServerActiveObject *obj = ServerActiveObject::create - (s_obj.type, this, 0, s_obj.pos, s_obj.data); + ((ActiveObjectType) s_obj.type, this, 0, s_obj.pos, s_obj.data); // If couldn't create object, store static data back. - if(obj==NULL) - { + if(obj == NULL) { errorstream<<"ServerEnvironment::activateObjects(): " <<"failed to create active object from static object " <<"in block "<m_static_objects.m_stored.clear(); // Add leftover failed stuff to stored list - for(std::list::iterator + for(std::vector::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); } @@ -1765,11 +1766,10 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s) */ void ServerEnvironment::deactivateFarObjects(bool force_delete) { - std::list objects_to_remove; + std::vector 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); @@ -1986,9 +1986,8 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) } // Remove references from m_active_objects - for(std::list::iterator i = objects_to_remove.begin(); - i != objects_to_remove.end(); ++i) - { + for(std::vector::iterator i = objects_to_remove.begin(); + i != objects_to_remove.end(); ++i) { m_active_objects.erase(*i); } } @@ -2025,9 +2024,8 @@ ClientEnvironment::~ClientEnvironment() delete i->second; } - for(std::list::iterator - i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i) - { + for(std::vector::iterator + i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i) { delete *i; } @@ -2059,9 +2057,8 @@ void ClientEnvironment::addPlayer(Player *player) LocalPlayer * ClientEnvironment::getLocalPlayer() { - for(std::list::iterator i = m_players.begin(); - i != m_players.end(); ++i) - { + for(std::vector::iterator i = m_players.begin(); + i != m_players.end(); ++i) { Player *player = *i; if(player->isLocal()) return (LocalPlayer*)player; @@ -2084,7 +2081,7 @@ void ClientEnvironment::step(float dtime) LocalPlayer *lplayer = getLocalPlayer(); assert(lplayer); // collision info queue - std::list player_collisions; + std::vector player_collisions; /* Get the speed the player is going @@ -2199,10 +2196,8 @@ void ClientEnvironment::step(float dtime) //std::cout<<"Looped "<::iterator - i = player_collisions.begin(); - i != player_collisions.end(); ++i) - { + for(std::vector::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 @@ -2317,16 +2312,14 @@ void ClientEnvironment::step(float dtime) /* Stuff that can be done in an arbitarily large dtime */ - for(std::list::iterator i = m_players.begin(); - i != m_players.end(); ++i) - { + for(std::vector::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); @@ -2387,16 +2380,18 @@ void ClientEnvironment::step(float dtime) Step and handle simple objects */ g_profiler->avg("CEnv: num of simple objects", m_simple_objects.size()); - for(std::list::iterator - i = m_simple_objects.begin(); i != m_simple_objects.end();) - { - ClientSimpleObject *simple = *i; - std::list::iterator cur = i; - ++i; + for(std::vector::iterator + i = m_simple_objects.begin(); i != m_simple_objects.end();) { + std::vector::iterator cur = i; + ClientSimpleObject *simple = *cur; + simple->step(dtime); - if(simple->m_to_be_removed){ + if(simple->m_to_be_removed) { delete simple; - m_simple_objects.erase(cur); + i = m_simple_objects.erase(cur); + } + else { + ++i; } } } @@ -2488,7 +2483,7 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type, const std::string &init_data) { ClientActiveObject* obj = - ClientActiveObject::create(type, m_gamedef, this); + ClientActiveObject::create((ActiveObjectType) type, m_gamedef, this); if(obj == NULL) { infostream<<"ClientEnvironment::addActiveObject(): " diff --git a/src/environment.h b/src/environment.h index 13c0c0efe..c9c374413 100644 --- a/src/environment.h +++ b/src/environment.h @@ -75,28 +75,19 @@ public: Player * getPlayer(const char *name); Player * getRandomConnectedPlayer(); Player * getNearestConnectedPlayer(v3f pos); - std::list getPlayers(); - std::list getPlayers(bool ignore_disconnected); + std::vector getPlayers(); + std::vector getPlayers(bool ignore_disconnected); u32 getDayNightRatio(); // 0-23999 - 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; } + virtual void setTimeOfDay(u32 time); + u32 getTimeOfDay(); + float getTimeOfDayF(); void stepTimeOfDay(float dtime); void setTimeOfDaySpeed(float speed); - float getTimeOfDaySpeed(); void setDayNightRatioOverride(bool enable, u32 value) @@ -110,7 +101,7 @@ public: protected: // peer_ids in here should be unique, except that there may be many 0s - std::list m_players; + std::vector 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 @@ -134,7 +125,8 @@ protected: bool m_cache_enable_shaders; private: - JMutex m_lock; + JMutex m_timeofday_lock; + JMutex m_time_lock; }; @@ -182,7 +174,7 @@ struct ABMWithState class ActiveBlockList { public: - void update(std::list &active_positions, + void update(std::vector &active_positions, s16 radius, std::set &blocks_removed, std::set &blocks_added); @@ -401,7 +393,7 @@ private: u32 m_game_time; // A helper variable for incrementing the latter float m_game_time_fraction_counter; - std::list m_abms; + std::vector 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. @@ -529,7 +521,7 @@ private: IGameDef *m_gamedef; IrrlichtDevice *m_irr; std::map m_active_objects; - std::list m_simple_objects; + std::vector 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/game.cpp b/src/game.cpp index fe3e838b2..96e028599 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -492,7 +492,7 @@ private: color(color) {} }; - std::list m_log; + std::vector m_log; public: u32 m_log_max_size; @@ -515,7 +515,7 @@ public: { std::map m_meta; - for (std::list::const_iterator k = m_log.begin(); + for (std::vector::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::list::const_iterator j = m_log.begin(); + for (std::vector::const_iterator j = m_log.begin(); j != m_log.end(); j++) { const Piece &piece = *j; float value = 0; @@ -1043,7 +1043,11 @@ 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, @@ -1074,7 +1078,7 @@ static void show_deathscreen(GUIFormSpecMenu **cur_formspec, std::string(FORMSPEC_VERSION_STRING) + SIZE_TAG "bgcolor[#320000b4;true]" - "label[4.85,1.35;You died.]" + "label[4.85,1.35;" + gettext("You died.") + "]" "button_exit[4,3;3,0.5;btn_respawn;" + gettext("Respawn") + "]" ; @@ -1133,7 +1137,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")) << "]"; @@ -1157,7 +1161,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; } @@ -1249,6 +1253,7 @@ 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, @@ -1297,6 +1302,7 @@ 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"); @@ -1493,6 +1499,7 @@ 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); @@ -1733,6 +1740,7 @@ void Game::run() { ProfilerGraph graph; RunStats stats = { 0 }; + CameraOrientation cam_view_target = { 0 }; CameraOrientation cam_view = { 0 }; GameRunData runData = { 0 }; FpsControl draw_times = { 0 }; @@ -1788,7 +1796,17 @@ 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, &flags); + 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; updatePlayerControl(cam_view); step(&dtime); processClientEvents(&cam_view, &runData.damage_flash); @@ -2564,6 +2582,8 @@ 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])) { @@ -2669,6 +2689,15 @@ 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); @@ -2741,6 +2770,16 @@ 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) { @@ -3218,10 +3257,13 @@ 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(); - assert(playercao != NULL); + // If playercao not loaded, don't change camera + if (playercao == NULL) + return; + + camera->toggleCameraMode(); playercao->setVisible(camera->getCameraMode() > CAMERA_MODE_FIRST); } @@ -3926,6 +3968,28 @@ 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) @@ -3981,6 +4045,7 @@ 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()) << ")"; @@ -4198,4 +4263,3 @@ 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 688a22570..fc7569418 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 8e6282887..dce45fa3a 100644 --- a/src/gettext.h +++ b/src/gettext.h @@ -41,16 +41,19 @@ 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) { - return narrow_to_wide(gettext(text.c_str())); + const wchar_t *tmp = wgettext(text.c_str()); + std::wstring retval = (std::wstring)tmp; + delete[] tmp; + return retval; } inline std::string strgettext(const std::string &text) diff --git a/src/guiChatConsole.cpp b/src/guiChatConsole.cpp index bdce7c872..8210e0bf4 100644 --- a/src/guiChatConsole.cpp +++ b/src/guiChatConsole.cpp @@ -99,7 +99,7 @@ GUIChatConsole::GUIChatConsole( { core::dimension2d dim = m_font->getDimension(L"M"); m_fontsize = v2u32(dim.Width, dim.Height); - dstream << "Font size: " << m_fontsize.X << " " << m_fontsize.Y << std::endl; + m_font->grab(); } m_fontsize.X = MYMAX(m_fontsize.X, 1); m_fontsize.Y = MYMAX(m_fontsize.Y, 1); @@ -109,7 +109,10 @@ 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 2bf45fdf4..652b265a4 100644 --- a/src/guiChatConsole.h +++ b/src/guiChatConsole.h @@ -122,9 +122,6 @@ private: // font gui::IGUIFont* m_font; v2u32 m_fontsize; -#if USE_FREETYPE - bool m_use_freetype; -#endif }; diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 20c9ecde7..a3cc03131 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -39,9 +39,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #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" @@ -50,8 +47,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "main.h" #include "settings.h" #include "client.h" -#include "util/string.h" // for parseColorString() #include "fontengine.h" +#include "util/hex.h" +#include "util/numeric.h" +#include "util/string.h" // for parseColorString() #define MY_CHECKPOS(a,b) \ if (v_pos.size() != 2) { \ @@ -97,6 +96,7 @@ 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,8 +1757,6 @@ 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 6d6c07453..48cb5c553 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -246,13 +246,20 @@ 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 */ @@ -348,6 +355,7 @@ 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 9bc8118a1..9b5a31d26 100644 --- a/src/guiKeyChangeMenu.cpp +++ b/src/guiKeyChangeMenu.cpp @@ -51,6 +51,7 @@ 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, @@ -137,27 +138,27 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) { key_setting *k = key_settings.at(i); { - core::rect < s32 > rect(0, 0, 100, 20); + core::rect < s32 > rect(0, 0, 110, 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 + 105, offset.Y - 5); + rect += topleft + v2s32(offset.X + 115, 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(250, 60); + offset = v2s32(260, 60); else offset += v2s32(0, 25); } { - s32 option_x = offset.X + 10; - s32 option_y = offset.Y; + s32 option_x = offset.X; + s32 option_y = offset.Y + 5; u32 option_w = 180; { core::rect rect(0, 0, option_w, 30); @@ -171,9 +172,9 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) } { - s32 option_x = offset.X + 10; - s32 option_y = offset.Y; - u32 option_w = 220; + s32 option_x = offset.X; + s32 option_y = offset.Y + 5; + u32 option_w = 280; { core::rect rect(0, 0, option_w, 30); rect += topleft + v2s32(option_x, option_y); @@ -394,22 +395,23 @@ 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_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_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"); } diff --git a/src/guiPasswordChange.cpp b/src/guiPasswordChange.cpp index d9a5cc48b..0e19f571d 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, 110, 20); - rect += topleft_client + v2s32(35, ypos+6); + core::rect rect(0, 0, 150, 20); + rect += topleft_client + v2s32(25, 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, 110, 20); - rect += topleft_client + v2s32(35, ypos+6); + core::rect rect(0, 0, 150, 20); + rect += topleft_client + v2s32(25, 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, 110, 20); - rect += topleft_client + v2s32(35, ypos+6); + core::rect rect(0, 0, 150, 20); + rect += topleft_client + v2s32(25, ypos+6); text = wgettext("Confirm Password"); Environment->addStaticText(text, rect, false, true, this, -1); delete[] text; diff --git a/src/httpfetch.cpp b/src/httpfetch.cpp index 47e33480b..e6886f652 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_back(fetch_result); + g_httpfetch_results[caller].push(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 " - < >::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::list &caller_results = it->second; + std::queue &caller_results = it->second; if (caller_results.empty()) return false; // Pop first result fetch_result = caller_results.front(); - caller_results.pop_front(); + caller_results.pop(); return true; } @@ -194,7 +194,6 @@ private: HTTPFetchRequest request; HTTPFetchResult result; std::ostringstream oss; - char *post_fields; struct curl_slist *http_header; curl_httppost *post; }; diff --git a/src/itemdef.cpp b/src/itemdef.cpp index ac67c5b27..3b4d2596a 100644 --- a/src/itemdef.cpp +++ b/src/itemdef.cpp @@ -249,8 +249,8 @@ public: virtual ~CItemDefManager() { #ifndef SERVER - const std::list &values = m_clientcached.getValues(); - for(std::list::const_iterator + const std::vector &values = m_clientcached.getValues(); + for(std::vector::const_iterator i = values.begin(); i != values.end(); ++i) { ClientCached *cc = *i; @@ -362,8 +362,6 @@ 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) @@ -372,11 +370,7 @@ public: /* Make a mesh from the node */ - if (g_settings->getBool("enable_shaders")) { - reenable_shaders = true; - g_settings->setBool("enable_shaders", false); - } - MeshMakeData mesh_make_data(gamedef); + MeshMakeData mesh_make_data(gamedef, false); u8 param2 = 0; if (f.param_type_2 == CPT2_WALLMOUNTED) param2 = 1; @@ -443,9 +437,6 @@ 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 f97e09ca0..9ea7ebde8 100644 --- a/src/jthread/jevent.h +++ b/src/jthread/jevent.h @@ -30,7 +30,7 @@ #ifdef _WIN32 #include -#elif __MACH__ +#elif defined(__MACH__) && defined(__APPLE__) #include #include #include @@ -43,7 +43,7 @@ class Event { #ifdef _WIN32 HANDLE hEvent; -#elif __MACH__ +#elif defined(__MACH__) && defined(__APPLE__) semaphore_t sem; #else sem_t sem; diff --git a/src/jthread/jsemaphore.h b/src/jthread/jsemaphore.h index 4ab006aea..32e9bc2f2 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 __MACH__ +#elif defined(__MACH__) && defined(__APPLE__) #include #include #include @@ -52,7 +52,7 @@ public: private: #if defined(WIN32) HANDLE m_hSemaphore; -#elif __MACH__ +#elif defined(__MACH__) && defined(__APPLE__) semaphore_t m_semaphore; int semcount; #else diff --git a/src/jthread/pthread/jevent.cpp b/src/jthread/pthread/jevent.cpp index 6a45a37d2..e1d40f4c1 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) -#ifdef __MACH__ +#if defined(__MACH__) && defined(__APPLE__) #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 16e001e92..15281ba64 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" -#ifdef __MACH__ +#if defined(__MACH__) && defined(__APPLE__) #include #endif #define UNUSED(expr) do { (void)(expr); } while (0) -#ifdef __MACH__ +#if defined(__MACH__) && defined(__APPLE__) #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); -#ifdef __MACH__ +#if defined(__MACH__) && defined(__APPLE__) 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); -#ifdef __MACH__ +#if defined(__MACH__) && defined(__APPLE__) 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); -#ifdef __MACH__ +#if defined(__MACH__) && defined(__APPLE__) 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) { -#ifdef __MACH__ +#if defined(__MACH__) && defined(__APPLE__) 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; } -#ifndef __MACH__ +#if !(defined(__MACH__) && defined(__APPLE__)) 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; -#ifdef __MACH__ +#if defined(__MACH__) && defined(__APPLE__) 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) { -#ifdef __MACH__ +#if defined(__MACH__) && defined(__APPLE__) 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; -#ifdef __MACH__ +#if defined(__MACH__) && defined(__APPLE__) pthread_mutex_lock(&semcount_mutex); retval = semcount; pthread_mutex_unlock(&semcount_mutex); diff --git a/src/keycode.cpp b/src/keycode.cpp index c5f102b44..27d0b6d50 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 69d4ec7ef..cb183947a 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::list *collision_info) + std::vector *collision_info) { Map *map = &env->getMap(); INodeDefManager *nodemgr = m_gamedef->ndef(); @@ -323,9 +323,8 @@ 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 16b66716d..2a4a9dfc7 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::list *collision_info); + std::vector *collision_info); void applyControl(float dtime); diff --git a/src/log.cpp b/src/log.cpp index b3b3f3f1b..398c89eb0 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -24,13 +24,14 @@ 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, @@ -38,7 +39,7 @@ unsigned int android_log_level_mapping[] { }; #endif -std::list log_outputs[LMT_NUM_VALUES]; +std::vector log_outputs[LMT_NUM_VALUES]; std::map log_threadnames; JMutex log_threadnamemutex; @@ -62,7 +63,7 @@ void log_add_output_all_levs(ILogOutput *out) void log_remove_output(ILogOutput *out) { for(int i=0; i::iterator it = + std::vector::iterator it = std::find(log_outputs[i].begin(), log_outputs[i].end(), out); if(it != log_outputs[i].end()) log_outputs[i].erase(it); @@ -71,33 +72,29 @@ void log_remove_output(ILogOutput *out) void log_set_lev_silence(enum LogMessageLevel lev, bool silence) { - log_threadnamemutex.Lock(); + JMutexAutoLock lock(log_threadnamemutex); - for (std::list::iterator - it = log_outputs[lev].begin(); - it != log_outputs[lev].end(); - ++it) { + for (std::vector::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(); - log_threadnamemutex.Lock(); + JMutexAutoLock lock(log_threadnamemutex); + log_threadnames[id] = name; - log_threadnamemutex.Unlock(); } void log_deregister_thread() { threadid_t id = get_current_thread_id(); - log_threadnamemutex.Lock(); + JMutexAutoLock lock(log_threadnamemutex); + log_threadnames.erase(id); - log_threadnamemutex.Unlock(); } static std::string get_lev_string(enum LogMessageLevel lev) @@ -119,7 +116,7 @@ static std::string get_lev_string(enum LogMessageLevel lev) void log_printline(enum LogMessageLevel lev, const std::string &text) { - log_threadnamemutex.Lock(); + JMutexAutoLock lock(log_threadnamemutex); std::string threadname = "(unknown thread)"; std::map::const_iterator i; i = log_threadnames.find(get_current_thread_id()); @@ -127,9 +124,10 @@ 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<::iterator i = log_outputs[lev].begin(); - i != log_outputs[lev].end(); i++){ + os << getTimestamp() << ": " << levelname << "["<::iterator i = log_outputs[lev].begin(); + i != log_outputs[lev].end(); i++) { ILogOutput *out = *i; if (out->silence) continue; @@ -138,7 +136,6 @@ 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 36e271889..4bfe318ee 100644 --- a/src/lua/CMakeLists.txt +++ b/src/lua/CMakeLists.txt @@ -47,10 +47,6 @@ 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() @@ -87,6 +83,10 @@ 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/main.cpp b/src/main.cpp index bbf88e80d..bf861eb69 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,19 +17,6 @@ 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") @@ -75,18 +62,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serverlist.h" #include "httpfetch.h" #include "guiEngine.h" +#include "map.h" #include "mapsector.h" #include "player.h" #include "fontengine.h" - -#include "database-sqlite3.h" -#ifdef USE_LEVELDB -#include "database-leveldb.h" -#endif - -#if USE_REDIS -#include "database-redis.h" -#endif +#include "database.h" #ifdef HAVE_TOUCHSCREENGUI #include "touchscreengui.h" @@ -174,8 +154,7 @@ 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, - Server *server); +static bool migrate_database(const GameParams &game_params, const Settings &cmd_args); #ifndef SERVER static bool print_video_modes(); @@ -836,9 +815,9 @@ int main(int argc, char *argv[]) #ifndef __ANDROID__ // Run unit tests - if ((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false) - || cmd_args.getFlag("enable-unittests") == true) { + if (cmd_args.getFlag("run-unittests")) { run_tests(); + return 0; } #endif @@ -909,10 +888,8 @@ 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("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("run-unittests", ValueSpec(VALUETYPE_FLAG, + _("Run the unit tests and exit")))); 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, @@ -1466,14 +1443,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 @@ -1483,79 +1460,63 @@ 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, - Server *server) +static bool migrate_database(const GameParams &game_params, const Settings &cmd_args) { - Settings world_mt; - 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 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"); - + 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; + 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; + return false; + } + std::string backend = world_mt.get("backend"); 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); - 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; - } + u32 count = 0; + time_t last_update_time = 0; + bool &kill = *porting::signal_handler_killstatus(); - std::list blocks; - ServerMap &old_map = ((ServerMap&)server->getMap()); - old_map.listAllLoadableBlocks(blocks); - int count = 0; + std::vector blocks; + old_db->listAllLoadableBlocks(blocks); 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."; + 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 { - old_map.saveBlock(block, new_db); - MapSector *sector = old_map.getSectorNoGenerate(v2s16(i->X, i->Z)); - sector->deleteBlock(block); + 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); } - ++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( - (game_params.world_path+ DIR_DELIM + "world.mt").c_str())) + if (!world_mt.updateConfigFile(world_mt_path.c_str())) errorstream << "Failed to update world.mt!" << std::endl; else actionstream << "world.mt updated" << std::endl; @@ -1633,13 +1594,15 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args) 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_HIGH_LIGHT, video::SColor(255, 0, 0, 0)); + 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, 100, 50)); + 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); diff --git a/src/map.cpp b/src/map.cpp index d8f018742..e80c82522 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -53,22 +53,6 @@ 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 @@ -1421,43 +1405,39 @@ bool Map::getDayNightDiff(v3s16 blockpos) Updates usage timers */ void Map::timerUpdate(float dtime, float unload_timeout, - std::list *unloaded_blocks) + std::vector *unloaded_blocks) { bool save_before_unloading = (mapType() == MAPTYPE_SERVER); // Profile modified reasons Profiler modprofiler; - std::list sector_deletion_queue; + std::vector 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; - std::list blocks; + MapBlockVect blocks; sector->getBlocks(blocks); - for(std::list::iterator i = blocks.begin(); - i != blocks.end(); ++i) - { + for(MapBlockVect::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; @@ -1472,15 +1452,13 @@ 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); } } @@ -1506,16 +1484,15 @@ void Map::timerUpdate(float dtime, float unload_timeout, } } -void Map::unloadUnreferencedBlocks(std::list *unloaded_blocks) +void Map::unloadUnreferencedBlocks(std::vector *unloaded_blocks) { timerUpdate(0.0, -1.0, unloaded_blocks); } -void Map::deleteSectors(std::list &list) +void Map::deleteSectors(std::vector §orList) { - for(std::list::iterator j = list.begin(); - j != list.end(); ++j) - { + for(std::vector::iterator j = sectorList.begin(); + j != sectorList.end(); ++j) { MapSector *sector = m_sectors[*j]; // If sector is in sector cache, remove it from there if(m_sector_cache == sector) @@ -1526,63 +1503,6 @@ void Map::deleteSectors(std::list &list) } } -#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(!suspect.empty()){ + if(m_gamedef->rollback() && !suspect.empty()){ // Blame suspect RollbackScopeActor rollback_scope(m_gamedef->rollback(), suspect, true); // Get old node for rollback @@ -2095,25 +2015,13 @@ 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; @@ -2892,7 +2800,8 @@ 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; } @@ -2914,14 +2823,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, "%.3x" DIR_DELIM "%.3x", - (unsigned int)pos.X&0xfff, - (unsigned int)pos.Y&0xfff); + snprintf(cc, 9, (std::string("%.3x") + DIR_DELIM + "%.3x").c_str(), + (unsigned int) pos.X & 0xfff, + (unsigned int) pos.Y & 0xfff); return m_savedir + DIR_DELIM + "sectors2" + DIR_DELIM + cc; default: @@ -2945,10 +2854,10 @@ v2s16 ServerMap::getSectorPos(std::string dirname) { // New layout fs::RemoveLastPathComponent(dirname, &component, 2); - r = sscanf(component.c_str(), "%3x" DIR_DELIM "%3x", &x, &y); + r = sscanf(component.c_str(), (std::string("%3x") + DIR_DELIM + "%3x").c_str(), &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 { @@ -2983,8 +2892,7 @@ 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++; } - std::list blocks; + + MapBlockVect blocks; sector->getBlocks(blocks); - for(std::list::iterator j = blocks.begin(); - j != blocks.end(); ++j) - { + for(MapBlockVect::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; } @@ -3050,6 +2954,7 @@ void ServerMap::save(ModifiedState save_level) } } } + if(save_started) endSave(); @@ -3057,8 +2962,7 @@ 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::vector &dst) { - if(loadFromFolders()){ - errorstream<<"Map::listAllLoadableBlocks(): Result will be missing " - <<"all blocks that are stored in flat files"<listAllLoadableBlocks(dst); } -void ServerMap::listAllLoadedBlocks(std::list &dst) +void ServerMap::listAllLoadedBlocks(std::vector &dst) { for(std::map::iterator si = m_sectors.begin(); si != m_sectors.end(); ++si) { MapSector *sector = si->second; - std::list blocks; + MapBlockVect blocks; sector->getBlocks(blocks); - for(std::list::iterator i = blocks.begin(); - i != blocks.end(); ++i) - { - MapBlock *block = (*i); - v3s16 p = block->getPos(); + for(MapBlockVect::iterator i = blocks.begin(); + i != blocks.end(); ++i) { + v3s16 p = (*i)->getPos(); dst.push_back(p); } } @@ -3331,6 +3233,24 @@ 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(); @@ -3370,7 +3290,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(); } @@ -3382,7 +3302,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); @@ -3584,7 +3504,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 1089e6d34..a4fd8406b 100644 --- a/src/map.h +++ b/src/map.h @@ -34,6 +34,7 @@ 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; @@ -277,28 +278,18 @@ public: Saves modified blocks before unloading on MAPTYPE_SERVER. */ void timerUpdate(float dtime, float unload_timeout, - std::list *unloaded_blocks=NULL); + std::vector *unloaded_blocks=NULL); /* Unloads all blocks with a zero refCount(). Saves modified blocks before unloading on MAPTYPE_SERVER. */ - void unloadUnreferencedBlocks(std::list *unloaded_blocks=NULL); + void unloadUnreferencedBlocks(std::vector *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::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 + void deleteSectors(std::vector &list); // For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: " virtual void PrintInfo(std::ostream &out); @@ -455,6 +446,7 @@ 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(); @@ -466,8 +458,8 @@ public: void endSave(); void save(ModifiedState save_level); - void listAllLoadableBlocks(std::list &dst); - void listAllLoadedBlocks(std::list &dst); + void listAllLoadableBlocks(std::vector &dst); + void listAllLoadedBlocks(std::vector &dst); // Saves map seed and possibly other stuff void saveMapMeta(); void loadMapMeta(); @@ -491,8 +483,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 ecd9a016b..a05b7a4da 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -330,47 +330,42 @@ 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 = false; + bool differs; /* Check if any lighting value differs */ - 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 cf311acba..d95b8d286 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): +MeshMakeData::MeshMakeData(IGameDef *gamedef, bool use_shaders): m_vmanip(), m_blockpos(-1337,-1337,-1337), m_crack_pos_relative(-1337, -1337, -1337), @@ -50,7 +50,8 @@ MeshMakeData::MeshMakeData(IGameDef *gamedef): m_smooth_lighting(false), m_show_hud(false), m_highlight_mesh_color(255, 255, 255, 255), - m_gamedef(gamedef) + m_gamedef(gamedef), + m_use_shaders(use_shaders) {} void MeshMakeData::fill(MapBlock *block) @@ -247,7 +248,7 @@ static u16 getSmoothLightCombined(v3s16 p, MeshMakeData *data) for (u32 i = 0; i < 8; i++) { - MapNode n = data->m_vmanip.getNodeNoEx(p - dirs8[i]); + const MapNode &n = data->m_vmanip.getNodeRefUnsafeCheckFlags(p - dirs8[i]); // if it's CONTENT_IGNORE we can't do any light calculations if (n.getContent() == CONTENT_IGNORE) { @@ -437,8 +438,6 @@ 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; @@ -589,6 +588,10 @@ 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)); @@ -603,7 +606,6 @@ 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); } /* @@ -744,8 +746,8 @@ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 dir, MeshMakeData *data) static void getTileInfo( // Input: MeshMakeData *data, - v3s16 p, - v3s16 face_dir, + const v3s16 &p, + const v3s16 &face_dir, // Output: bool &makes_face, v3s16 &p_corrected, @@ -759,14 +761,20 @@ static void getTileInfo( INodeDefManager *ndef = data->m_gamedef->ndef(); v3s16 blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE; - MapNode n0 = vmanip.getNodeNoEx(blockpos_nodes + p); + MapNode &n0 = vmanip.getNodeRefUnsafe(blockpos_nodes + p); // Don't even try to get n1 if n0 is already CONTENT_IGNORE - if (n0.getContent() == 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) { makes_face = false; return; } - MapNode n1 = vmanip.getNodeNoEx(blockpos_nodes + p + face_dir); // This is hackish bool equivalent = false; @@ -1028,7 +1036,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): m_last_daynight_ratio((u32) -1), m_daynight_diffs() { - m_enable_shaders = g_settings->getBool("enable_shaders"); + m_enable_shaders = data->m_use_shaders; m_enable_highlighting = g_settings->getBool("enable_node_highlighting"); // 4-21ms for MAP_BLOCKSIZE=16 (NOTE: probably outdated) @@ -1036,6 +1044,7 @@ 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 be56d4c58..98af92c74 100644 --- a/src/mapblock_mesh.h +++ b/src/mapblock_mesh.h @@ -45,8 +45,9 @@ struct MeshMakeData video::SColor m_highlight_mesh_color; IGameDef *m_gamedef; + bool m_use_shaders; - MeshMakeData(IGameDef *gamedef); + MeshMakeData(IGameDef *gamedef, bool use_shaders); /* Copy central data directly from block, and other data from diff --git a/src/mapgen.cpp b/src/mapgen.cpp index ba1b16d6a..17aa1dd92 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -41,6 +41,8 @@ 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}, @@ -155,6 +157,12 @@ 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) @@ -166,11 +174,13 @@ 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 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 (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; + } heightmap[index] = y; } @@ -417,9 +427,8 @@ void GenerateNotifier::getEvents( std::map > &event_map, bool peek_events) { - std::list::iterator it; - - for (it = m_notify_events.begin(); it != m_notify_events.end(); ++it) { + for (std::vector::iterator 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 5bbdd724d..01710786b 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::list m_notify_events; + std::vector m_notify_events; }; struct MapgenSpecificParams { @@ -151,6 +151,7 @@ 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 f7efc4e18..34484c7e5 100644 --- a/src/mapgen_v5.cpp +++ b/src/mapgen_v5.cpp @@ -42,7 +42,6 @@ with this program; if not, write to the Free Software Foundation, Inc., FlagDesc flagdesc_mapgen_v5[] = { - {"blobs", MGV5_BLOBS}, {NULL, 0} }; @@ -61,6 +60,8 @@ 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; @@ -73,8 +74,6 @@ 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); @@ -117,8 +116,6 @@ MapgenV5::~MapgenV5() delete noise_cave1; delete noise_cave2; delete noise_ground; - delete noise_crumble; - delete noise_wetness; delete noise_heat; delete noise_humidity; @@ -130,7 +127,7 @@ MapgenV5::~MapgenV5() MapgenV5Params::MapgenV5Params() { - spflags = MGV5_BLOBS; + spflags = 0; 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); @@ -138,18 +135,11 @@ 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) +//#define CAVE_NOISE_THRESHOLD (1.5/CAVE_NOISE_SCALE) = 0.125 void MapgenV5Params::readParams(Settings *settings) @@ -162,8 +152,6 @@ 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); } @@ -177,8 +165,6 @@ 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); } @@ -187,23 +173,20 @@ 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; @@ -247,18 +230,20 @@ void MapgenV5::makeChunk(BlockMakeData *data) // Generate base terrain s16 stone_surface_max_y = generateBaseTerrain(); + + // Create heightmap updateHeightmap(node_min, node_max); - // Calculate biomes + // Create biomemap at heightmap surface bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result, noise_humidity->result, heightmap, biomemap); // Actually place the biome-specific nodes - generateBiomes(); + generateBiomes(noise_heat->result, noise_humidity->result); // Generate caves if ((flags & MG_CAVES) && (stone_surface_max_y >= node_min.Y)) - generateCaves(); + generateCaves(stone_surface_max_y); // Generate dungeons and desert temples if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) { @@ -269,11 +254,6 @@ 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); @@ -311,11 +291,6 @@ 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); @@ -326,8 +301,6 @@ 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]); @@ -351,22 +324,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 = water_level + noise_height->result[index2d]; + float h = 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); @@ -385,7 +358,7 @@ int MapgenV5::generateBaseTerrain() } -void MapgenV5::generateBiomes() +void MapgenV5::generateBiomes(float *heat_map, float *humidity_map) { if (node_max.Y < water_level) return; @@ -399,12 +372,11 @@ void MapgenV5::generateBiomes() 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 = (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; + Biome *biome = NULL; + s16 dfiller = 0; + s16 y0_top = 0; + s16 y0_filler = 0; + s16 depth_water_top = 0; s16 nplaced = 0; u32 i = vm->m_area.index(x, node_max.Y, z); @@ -415,25 +387,23 @@ void MapgenV5::generateBiomes() 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) { - 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); + vm->m_data[i] = MapNode(biome->c_top); nplaced++; } else if (nplaced < y0_filler && nplaced >= y0_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_filler); - else - vm->m_data[i] = MapNode(biome->c_filler); + vm->m_data[i] = MapNode(biome->c_filler); nplaced++; } else if (c == c_stone) { have_air = false; @@ -470,18 +440,18 @@ void MapgenV5::generateBiomes() } -void MapgenV5::generateCaves() +void MapgenV5::generateCaves(int max_stone_y) { 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)) @@ -489,43 +459,22 @@ void MapgenV5::generateCaves() 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; -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); - } - } - } + 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); } } diff --git a/src/mapgen_v5.h b/src/mapgen_v5.h index 1949bf5db..e95874e84 100644 --- a/src/mapgen_v5.h +++ b/src/mapgen_v5.h @@ -23,7 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapgen.h" /////////////////// Mapgen V5 flags -#define MGV5_BLOBS 0x01 +//#define MGV5_ 0x01 + +class BiomeManager; extern FlagDesc flagdesc_mapgen_v5[]; @@ -36,8 +38,6 @@ struct MapgenV5Params : public MapgenSpecificParams { NoiseParams np_cave1; NoiseParams np_cave2; NoiseParams np_ground; - NoiseParams np_crumble; - NoiseParams np_wetness; MapgenV5Params(); ~MapgenV5Params() {} @@ -67,8 +67,6 @@ public: Noise *noise_cave1; Noise *noise_cave2; Noise *noise_ground; - Noise *noise_crumble; - Noise *noise_wetness; Noise *noise_heat; Noise *noise_humidity; @@ -95,9 +93,8 @@ public: int getGroundLevelAtPoint(v2s16 p); void calculateNoise(); int generateBaseTerrain(); - void generateBiomes(); - void generateCaves(); - void generateBlobs(); + void generateBiomes(float *heat_map, float *humidity_map); + void generateCaves(int max_stone_y); void dustTopNodes(); }; diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index 95cdbd279..8ea4cd21d 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -55,6 +55,10 @@ 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; @@ -115,6 +119,8 @@ MapgenV6::~MapgenV6() delete noise_mud; delete noise_beach; delete noise_biome; + + delete[] heightmap; } @@ -498,6 +504,9 @@ 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 a7b9076b3..21ee967c6 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -64,6 +64,8 @@ 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; @@ -239,14 +241,15 @@ 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); - // Calculate biomes + // Create biomemap at heightmap surface bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result, noise_humidity->result, heightmap, biomemap); - // Actually place the biome-specific nodes and what not - generateBiomes(); + // Actually place the biome-specific nodes + generateBiomes(noise_heat->result, noise_humidity->result); if (flags & MG_CAVES) generateCaves(stone_surface_max_y); @@ -534,7 +537,7 @@ void MapgenV7::generateRidgeTerrain() } -void MapgenV7::generateBiomes() +void MapgenV7::generateBiomes(float *heat_map, float *humidity_map) { if (node_max.Y < water_level) return; @@ -548,12 +551,11 @@ void MapgenV7::generateBiomes() 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 = (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; + Biome *biome = NULL; + s16 dfiller = 0; + s16 y0_top = 0; + s16 y0_filler = 0; + s16 depth_water_top = 0; s16 nplaced = 0; u32 i = vm->m_area.index(x, node_max.Y, z); @@ -574,25 +576,23 @@ void MapgenV7::generateBiomes() 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) { - 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); + vm->m_data[i] = MapNode(biome->c_top); nplaced++; } else if (nplaced < y0_filler && nplaced >= y0_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_filler); - else - vm->m_data[i] = MapNode(biome->c_filler); + 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, true); + CaveV7 cave(this, &ps); cave.makeCave(node_min, node_max, max_stone_y); } } diff --git a/src/mapgen_v7.h b/src/mapgen_v7.h index bcf362ac9..8a02bf564 100644 --- a/src/mapgen_v7.h +++ b/src/mapgen_v7.h @@ -114,7 +114,7 @@ public: int generateMountainTerrain(int ymax); void generateRidgeTerrain(); - void generateBiomes(); + void generateBiomes(float *heat_map, float *humidity_map); void dustTopNodes(); //void addTopNodes(); diff --git a/src/mapnode.cpp b/src/mapnode.cpp index 056b94054..44525b644 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -74,6 +74,22 @@ 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] @@ -88,7 +104,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) +u8 MapNode::getLightNoChecks(enum LightBank bank, const ContentFeatures *f) const { return MYMAX(f->light_source, bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f); diff --git a/src/mapnode.h b/src/mapnode.h index 82c53e7d4..7cc25c60c 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -192,6 +192,14 @@ 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; /** @@ -209,7 +217,7 @@ struct MapNode * @pre f != NULL * @pre f->param_type == CPT_LIGHT */ - u8 getLightNoChecks(LightBank bank, const ContentFeatures *f); + u8 getLightNoChecks(LightBank bank, const ContentFeatures *f) const; bool getLightBanks(u8 &lightday, u8 &lightnight, INodeDefManager *nodemgr) const; diff --git a/src/mapsector.cpp b/src/mapsector.cpp index 0d40a659d..7bc4bd3a3 100644 --- a/src/mapsector.cpp +++ b/src/mapsector.cpp @@ -133,7 +133,7 @@ void MapSector::deleteBlock(MapBlock *block) delete block; } -void MapSector::getBlocks(std::list &dest) +void MapSector::getBlocks(MapBlockVect &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 dac4ee8d6..e89247a92 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(std::list &dest); + void getBlocks(MapBlockVect &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 0d17ae5ed..e076d3092 100644 --- a/src/mg_biome.cpp +++ b/src/mg_biome.cpp @@ -43,7 +43,6 @@ 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; @@ -53,9 +52,6 @@ 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"); @@ -126,9 +122,6 @@ 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 3577960a9..3648c085d 100644 --- a/src/mg_biome.h +++ b/src/mg_biome.h @@ -39,9 +39,6 @@ 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; @@ -49,7 +46,6 @@ 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 a67c3cd8c..ab9401e28 100644 --- a/src/mg_decoration.cpp +++ b/src/mg_decoration.cpp @@ -31,6 +31,7 @@ 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} }; @@ -140,6 +141,7 @@ 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) @@ -333,6 +335,8 @@ 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; @@ -344,7 +348,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, false, m_ndef); + schematic->blitToVManip(p, vm, rot, force_placement, m_ndef); return 1; } diff --git a/src/mg_decoration.h b/src/mg_decoration.h index ab4a9377b..fd7739b92 100644 --- a/src/mg_decoration.h +++ b/src/mg_decoration.h @@ -35,10 +35,11 @@ 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_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 extern FlagDesc flagdesc_deco[]; diff --git a/src/mods.cpp b/src/mods.cpp index 6126de7a1..cb5a6b9fd 100644 --- a/src/mods.cpp +++ b/src/mods.cpp @@ -47,6 +47,11 @@ 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/nodedef.cpp b/src/nodedef.cpp index bcf51a072..d43bc16a4 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -443,7 +443,7 @@ private: content_t m_next_id; // List of node strings and node resolver callbacks to perform - std::list m_pending_node_lookups; + std::vector 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::list::iterator + for (std::vector::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::list::iterator + for (std::vector::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.pop_front(); + m_pending_node_lookups.erase(m_pending_node_lookups.begin()); 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.pop_front(); + nri->nodenames.erase(nri->nodenames.begin()); 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.pop_front(); + nri->nodenames.erase(nri->nodenames.begin()); if (name.substr(0,6) != "group:") { if (getId(name, c)) { diff --git a/src/nodedef.h b/src/nodedef.h index 7280bb8ea..7401c8e46 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -309,7 +309,7 @@ struct NodeResolveInfo { resolver = nr; } - std::list nodenames; + std::vector nodenames; std::list nodelistinfo; NodeResolver *resolver; }; diff --git a/src/particles.cpp b/src/particles.cpp index 603e38cdd..64b8936bd 100644 --- a/src/particles.cpp +++ b/src/particles.cpp @@ -107,20 +107,13 @@ Particle::~Particle() void Particle::OnRegisterSceneNode() { if (IsVisible) - { - SceneManager->registerNodeForRendering - (this, scene::ESNRP_TRANSPARENT); - SceneManager->registerNodeForRendering - (this, scene::ESNRP_SOLID); - } + SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT_EFFECT); 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/porting.h b/src/porting.h index 8387453e8..3d2677564 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_SOURCE) +#if (defined(linux) || defined(__linux) || defined(__GNU__)) && !defined(_GNU_SOURCE) #define _GNU_SOURCE #endif @@ -228,7 +228,7 @@ void initIrrlicht(irr::IrrlichtDevice * ); #else // Posix #include #include -#ifdef __MACH__ +#if defined(__MACH__) && defined(__APPLE__) #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 -#ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time +#if defined(__MACH__) && defined(__APPLE__) // 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) +#elif defined(_WIN32) || defined(__GNU__) 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 cd5d253ac..1f1d8bffa 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -406,19 +406,6 @@ 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) @@ -530,9 +517,8 @@ int ModApiEnvMod::l_find_node_near(lua_State *L) } for(int d=1; d<=radius; d++){ - std::list list; - getFacePositions(list, d); - for(std::list::iterator i = list.begin(); + std::vector list = FacePositionCache::getFacePositions(d); + for(std::vector::iterator i = list.begin(); i != list.end(); ++i){ v3s16 p = pos + (*i); content_t c = env->getMap().getNodeNoEx(p).getContent(); @@ -555,17 +541,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); } @@ -584,6 +570,59 @@ 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) @@ -881,6 +920,7 @@ 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 bfaea1c4d..5c9afd2f1 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -119,6 +119,10 @@ 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 28c3d193d..2bed2a255 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -472,6 +472,7 @@ int ModApiMainMenu::l_get_favorites(lua_State *L) for (unsigned int i = 0; i < servers.size(); i++) { + lua_pushnumber(L,index); lua_newtable(L); @@ -509,6 +510,18 @@ 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()); @@ -859,19 +872,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::CreateAllDirs(fullpath) ) { + if (!files_in_zip->isDirectory(i)) { + if (!fs::PathExists(fullpath_dir) && !fs::CreateAllDirs(fullpath_dir)) { 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"); @@ -883,7 +896,7 @@ int ModApiMainMenu::l_extract_zip(lua_State *L) } char read_buffer[1024]; - unsigned int total_read = 0; + long total_read = 0; while (total_read < toread->getSize()) { @@ -1082,6 +1095,19 @@ 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) { @@ -1142,6 +1168,8 @@ 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 ff61dd97a..8b21a93aa 100644 --- a/src/script/lua_api/l_mainmenu.h +++ b/src/script/lua_api/l_mainmenu.h @@ -137,6 +137,12 @@ 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 d470cef88..54ec69010 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -444,8 +444,7 @@ 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", 3); - b->height_shore = getintfield_default(L, index, "height_shore", 3); + b->depth_filler = getintfield_default(L, index, "depth_filler", 2); 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); @@ -460,12 +459,9 @@ int ModApiMapgen::l_register_biome(lua_State *L) } NodeResolveInfo *nri = new NodeResolveInfo(b); - std::list &nnames = nri->nodenames; + std::vector &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 4286840fe..73f6e93b3 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -26,7 +26,6 @@ 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" @@ -132,6 +131,7 @@ 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; diff --git a/src/script/lua_api/l_rollback.cpp b/src/script/lua_api/l_rollback.cpp index f55a72d1b..5744e6813 100644 --- a/src/script/lua_api/l_rollback.cpp +++ b/src/script/lua_api/l_rollback.cpp @@ -44,6 +44,9 @@ 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(); @@ -80,6 +83,13 @@ 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 8d7f6512e..fcdd8c2ff 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -367,33 +367,18 @@ int ModApiServer::l_get_modnames(lua_State *L) NO_MAP_LOCK_REQUIRED; // Get a list of mods - std::list mods_unsorted, mods_sorted; - getServer(L)->getModNames(mods_unsorted); + std::vector modlist; + getServer(L)->getModNames(modlist); // 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. - 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); - } + std::sort(modlist.begin(), modlist.end()); // Package them up for Lua - lua_createtable(L, mods_sorted.size(), 0); - std::list::iterator iter = mods_sorted.begin(); - for (u16 i = 0; iter != mods_sorted.end(); iter++) { + lua_createtable(L, modlist.size(), 0); + std::vector::iterator iter = modlist.begin(); + for (u16 i = 0; iter != modlist.end(); iter++) { lua_pushstring(L, iter->c_str()); lua_rawseti(L, -2, ++i); } diff --git a/src/server.cpp b/src/server.cpp index 399c41b70..f2bde4ab6 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -50,12 +50,9 @@ 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" @@ -64,6 +61,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #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 { @@ -244,9 +244,6 @@ 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(); @@ -354,6 +351,12 @@ 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); @@ -533,23 +536,18 @@ void Server::AsyncRunStep(bool initial_step) /* Update time of day and overall game time */ - { - JMutexAutoLock envlock(m_env_mutex); + m_env->setTimeOfDaySpeed(g_settings->getFloat("time_speed")); - m_env->setTimeOfDaySpeed(g_settings->getFloat("time_speed")); + /* + Send to clients at constant intervals + */ - /* - 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); - } + 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); } { @@ -1108,10 +1106,6 @@ 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"); } } @@ -1851,8 +1845,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) 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); + pitch = modulo360f(pitch); + yaw = modulo360f(yaw); player->setPosition(position); player->setSpeed(speed); @@ -2817,7 +2811,6 @@ void Server::setInventoryModified(const InventoryLocation &loc) if(!playersao) return; playersao->m_inventory_not_sent = true; - playersao->m_wielded_item_not_sent = true; } break; case InventoryLocation::NODEMETA: @@ -4939,10 +4932,9 @@ const ModSpec* Server::getModSpec(const std::string &modname) } return NULL; } -void Server::getModNames(std::list &modlist) +void Server::getModNames(std::vector &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); } } diff --git a/src/server.h b/src/server.h index 3d6b00d99..f773e3bec 100644 --- a/src/server.h +++ b/src/server.h @@ -295,7 +295,7 @@ public: IWritableCraftDefManager* getWritableCraftDefManager(); const ModSpec* getModSpec(const std::string &modname); - void getModNames(std::list &modlist); + void getModNames(std::vector &modlist); std::string getBuiltinLuaPath(); inline std::string getWorldPath() { return m_path_world; } @@ -553,9 +553,6 @@ private: Random stuff */ - // Mod parent directory paths - std::list m_modspaths; - bool m_shutdown_requested; /* diff --git a/src/serverlist.cpp b/src/serverlist.cpp index 472a6b85c..ae8db2b60 100644 --- a/src/serverlist.cpp +++ b/src/serverlist.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "main.h" // for g_settings #include "settings.h" #include "serverlist.h" +#include "clientserver.h" #include "filesys.h" #include "porting.h" #include "log.h" @@ -67,8 +68,11 @@ std::vector getLocal() std::vector getOnline() { - Json::Value root = fetchJsonValue( - (g_settings->get("serverlist_url") + "/list").c_str(), NULL); + 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); std::vector server_list; @@ -205,9 +209,12 @@ 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 81307bc34..9cf817859 100644 --- a/src/serverobject.cpp +++ b/src/serverobject.cpp @@ -38,15 +38,19 @@ ServerActiveObject::~ServerActiveObject() { } -ServerActiveObject* ServerActiveObject::create(u8 type, +ServerActiveObject* ServerActiveObject::create(ActiveObjectType 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()) - { + 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 factory is not found, just return. dstream<<"WARNING: ServerActiveObject: No factory for type=" <::iterator + for(std::vector::iterator i = m_stored.begin(); - i != m_stored.end(); ++i) - { + i != m_stored.end(); ++i) { StaticObject &s_obj = *i; s_obj.serialize(os); } @@ -68,8 +67,7 @@ void StaticObjectList::deSerialize(std::istream &is) u8 version = readU8(is); // count u16 count = readU16(is); - 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::list m_stored; + std::vector m_stored; std::map m_active; private: diff --git a/src/test.cpp b/src/test.cpp index 80494e07a..1f25108b7 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -147,15 +147,45 @@ 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() { - /*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)) { @@ -1709,7 +1754,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; } @@ -1722,7 +1767,15 @@ struct TestSocket: public TestBase socket.Bind(address); const char sendbuffer[] = "hello world!"; - socket.Send(Address(127, 0, 0 ,1, port), sendbuffer, sizeof(sendbuffer)); + /* + * 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)); sleep_ms(50); @@ -1734,8 +1787,15 @@ struct TestSocket: public TestBase } //FIXME: This fails on some systems UASSERT(strncmp(sendbuffer, rcvbuffer, sizeof(sendbuffer)) == 0); - UASSERT(sender.getAddress().sin_addr.s_addr == - Address(127, 0, 0, 1, 0).getAddress().sin_addr.s_addr); + + 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); + } } } }; @@ -1835,9 +1895,24 @@ 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"< m_queue; }; -#if 1 template class MutexedMap { @@ -109,9 +108,9 @@ public: return true; } - std::list getValues() + std::vector getValues() { - std::list result; + std::vector result; for(typename std::map::iterator i = m_values.begin(); i != m_values.end(); ++i){ @@ -129,7 +128,6 @@ private: std::map m_values; JMutex m_mutex; }; -#endif /* Generates ids for comparable values. diff --git a/src/hex.h b/src/util/hex.h similarity index 100% rename from src/hex.h rename to src/util/hex.h diff --git a/src/util/numeric.cpp b/src/util/numeric.cpp index 6173515ee..19f927134 100644 --- a/src/util/numeric.cpp +++ b/src/util/numeric.cpp @@ -20,79 +20,84 @@ 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 -void getFacePositions(std::list &list, u16 d) +std::vector FacePositionCache::getFacePositions(u16 d) { - if(d == 0) - { - list.push_back(v3s16(0,0,0)); + 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)); return; } - if(d == 1) - { + if(d == 1) { /* This is an optimized sequence of coordinates. */ - 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 + 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 // 6 - 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 + 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 // 18 - 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 + 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 // 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++) - { - 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)); + 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)); } } // Back and front side, excluding borders - 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)); + 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)); } } } @@ -100,10 +105,9 @@ void getFacePositions(std::list &list, u16 d) // Take the bottom and top face with borders // -d +#include +#include #include -// Calculate the borders of a "d-radius" cube -void getFacePositions(std::list &list, u16 d); + +/* + * 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; +}; class IndentationRaiser { @@ -171,57 +184,56 @@ inline void sortBoxVerticies(v3s16 &p1, v3s16 &p2) { } -/* - 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) +/** 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) { - // 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; + 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); } -/* Wrap to 0...360 */ + +/** Returns \p f wrapped to the range [0, 360] + */ inline float wrapDegrees_0_360(float f) { - // 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; + float value = modulo360f(f); + return value < 0 ? value + 360 : value; } -/* Wrap to -180...180 */ + +/** Returns \p f wrapped to the range [-180, 180] + */ inline float wrapDegrees_180(float f) { - f += 180; - f = wrapDegrees_0_360(f); - f -= 180; - return f; + float value = modulo360f(f + 180); + if (value < 0) + value += 360; + return value - 180; } /* diff --git a/src/sha1.cpp b/src/util/sha1.cpp similarity index 100% rename from src/sha1.cpp rename to src/util/sha1.cpp diff --git a/src/sha1.h b/src/util/sha1.h similarity index 100% rename from src/sha1.h rename to src/util/sha1.h diff --git a/src/util/string.cpp b/src/util/string.cpp index b4908d62d..c48abe835 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 "../sha1.h" -#include "../base64.h" -#include "../hex.h" +#include "base64.h" +#include "hex.h" +#include "sha1.h" #include "../porting.h" #include @@ -40,6 +40,7 @@ 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[\\]^_`" @@ -62,31 +63,38 @@ int wctomb(char *s, wchar_t wc) int mbtowc(wchar_t *pwc, const char *s, size_t n) { - wchar_t *intermediate = narrow_to_wide(s); - - if (intermediate.length() > 0) { - *pwc = intermediate[0]; - return 1; - } else { + if (s == NULL || *s == '\0') 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]; - for (size_t i = 0; i < mbl; i++) { + size_t i, dest_i = 0; + for (i = 0; i < mbl; i++) { if (((unsigned char) mbs[i] > 31) && ((unsigned char) mbs[i] < 127)) { - wcs[i] = wide_chars[(unsigned char) mbs[i] - 32]; + wcs[dest_i++] = wide_chars[(unsigned char) mbs[i] - 32]; } //handle newline else if (mbs[i] == '\n') { - wcs[i] = L'\n'; + wcs[dest_i++] = L'\n'; } } + wcs[dest_i] = '\0'; return wcs; } @@ -98,11 +106,13 @@ const wchar_t *narrow_to_wide_c(const char *mbs) { wchar_t *wcs = NULL; #if defined(_WIN32) - 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); + 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); + } #else size_t wcl = mbstowcs(NULL, mbs, 0); if (wcl == (size_t) -1) @@ -120,12 +130,13 @@ const wchar_t *narrow_to_wide_c(const char *mbs) std::wstring narrow_to_wide(const std::string& mbs) { - const wchar_t *wcs = narrow_to_wide_c(mbs.c_str()); - if (!wcs) + size_t wcl = mbs.size(); + Buffer wcs(wcl + 1); + size_t l = mbstowcs(*wcs, mbs.c_str(), wcl); + if (l == (size_t)(-1)) return L""; - std::wstring wstr(wcs); - delete [] wcs; - return wstr; + wcs[l] = 0; + return *wcs; } #ifdef __ANDROID__ diff --git a/src/voxel.cpp b/src/voxel.cpp index 8ac786aab..a5e0b09fe 100644 --- a/src/voxel.cpp +++ b/src/voxel.cpp @@ -621,6 +621,8 @@ 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 52274ac19..054644889 100644 --- a/src/voxel.h +++ b/src/voxel.h @@ -413,10 +413,21 @@ public: } // Stuff explodes if non-emerged area is touched with this. // Emerge first, and check VOXELFLAG_NO_DATA if appropriate. - MapNode & getNodeRefUnsafe(v3s16 p) + MapNode & getNodeRefUnsafe(const 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)]; @@ -569,6 +580,8 @@ 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 4ddae36d4..7c16bddcb 100644 --- a/src/wieldmesh.cpp +++ b/src/wieldmesh.cpp @@ -340,7 +340,9 @@ 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 { - MeshMakeData mesh_make_data(gamedef); + //// 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); 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 0b1332308..a50d5f370 100755 --- a/util/travis/before_install.sh +++ b/util/travis/before_install.sh @@ -8,12 +8,15 @@ 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 libogg-dev \ - libvorbis-dev libopenal-dev gettext + 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 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 a8e2634e9..35a62f16e 100755 --- a/util/travis/script.sh +++ b/util/travis/script.sh @@ -3,8 +3,12 @@ if [ $WINDOWS = "no" ]; then mkdir -p travisbuild cd travisbuild - cmake -DENABLE_GETTEXT=1 .. + cmake -DENABLE_GETTEXT=1 -DENABLE_LEVELDB=1 -DENABLE_REDIS=1 -DCMAKE_BUILD_TYPE=Debug .. 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