diff options
147 files changed, 3437 insertions, 1151 deletions
diff --git a/.gitignore b/.gitignore index 52f8bc4f4..78b047f32 100644 --- a/.gitignore +++ b/.gitignore @@ -52,8 +52,6 @@ build/.cmake/ !/mods/minetest/mods_here.txt /worlds /world/ -/clientmods/* -!/clientmods/preview/ /client/mod_storage/ ## Configuration/log files diff --git a/CMakeLists.txt b/CMakeLists.txt index fec9709d4..69424793f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ endif() # This can be read from ${PROJECT_NAME} after project() is called project(minetest) -set(PROJECT_NAME_CAPITALIZED "Minetest") +set(PROJECT_NAME_CAPITALIZED "Dragonfire") # Works only for cmake 3.1 and greater set(CMAKE_CXX_STANDARD 11) diff --git a/builtin/client/chatcommands.lua b/builtin/client/chatcommands.lua index 5cb1b40bb..83b7f7b14 100644 --- a/builtin/client/chatcommands.lua +++ b/builtin/client/chatcommands.lua @@ -1,6 +1,5 @@ -- Minetest: builtin/client/chatcommands.lua - core.register_on_sending_chat_message(function(message) if message:sub(1,2) == ".." then return false @@ -37,34 +36,8 @@ core.register_on_sending_chat_message(function(message) return true end) -core.register_chatcommand("list_players", { - description = core.gettext("List online players"), - func = function(param) - local player_names = core.get_player_names() - if not player_names then - return false, core.gettext("This command is disabled by server.") - end - - local players = table.concat(player_names, ", ") - return true, core.gettext("Online players: ") .. players - end -}) - -core.register_chatcommand("disconnect", { - description = core.gettext("Exit to main menu"), - func = function(param) - core.disconnect() - end, -}) - -core.register_chatcommand("clear_chat_queue", { - description = core.gettext("Clear the out chat queue"), - func = function(param) - core.clear_out_chat_queue() - return true, core.gettext("The out chat queue is now empty") - end, -}) - function core.run_server_chatcommand(cmd, param) core.send_chat_message("/" .. cmd .. " " .. param) end + + diff --git a/builtin/client/death_formspec.lua b/builtin/client/death_formspec.lua deleted file mode 100644 index e755ac5c1..000000000 --- a/builtin/client/death_formspec.lua +++ /dev/null @@ -1,16 +0,0 @@ --- CSM death formspec. Only used when clientside modding is enabled, otherwise --- handled by the engine. - -core.register_on_death(function() - core.display_chat_message("You died.") - local formspec = "size[11,5.5]bgcolor[#320000b4;true]" .. - "label[4.85,1.35;" .. fgettext("You died") .. - "]button_exit[4,3;3,0.5;btn_respawn;".. fgettext("Respawn") .."]" - core.show_formspec("bultin:death", formspec) -end) - -core.register_on_formspec_input(function(formname, fields) - if formname == "bultin:death" then - core.send_respawn() - end -end) diff --git a/builtin/client/init.lua b/builtin/client/init.lua index 9633a7c71..ee344e7bc 100644 --- a/builtin/client/init.lua +++ b/builtin/client/init.lua @@ -6,6 +6,7 @@ local commonpath = scriptpath.."common"..DIR_DELIM dofile(clientpath .. "register.lua") dofile(commonpath .. "after.lua") dofile(commonpath .. "chatcommands.lua") -dofile(clientpath .. "chatcommands.lua") dofile(commonpath .. "vector.lua") -dofile(clientpath .. "death_formspec.lua") +dofile(clientpath .. "util.lua") +dofile(clientpath .. "chatcommands.lua") + diff --git a/builtin/client/register.lua b/builtin/client/register.lua index c1b4965c1..071220a43 100644 --- a/builtin/client/register.lua +++ b/builtin/client/register.lua @@ -40,6 +40,26 @@ function core.run_callbacks(callbacks, mode, ...) return ret end +function core.override_item(name, redefinition) + if redefinition.name ~= nil then + error("Attempt to redefine name of "..name.." to "..dump(redefinition.name), 2) + end + if redefinition.type ~= nil then + error("Attempt to redefine type of "..name.." to "..dump(redefinition.type), 2) + end + local itemdef = core.get_item_def(name) + if not itemdef then + error("Attempt to override non-existent item "..name, 2) + end + local nodedef = core.get_node_def(name) + table.combine(itemdef, nodedef) + + for k, v in pairs(redefinition) do + rawset(itemdef, k, v) + end + core.register_item_raw(itemdef) +end + -- -- Callback registration -- diff --git a/builtin/client/util.lua b/builtin/client/util.lua new file mode 100644 index 000000000..595922262 --- /dev/null +++ b/builtin/client/util.lua @@ -0,0 +1,23 @@ +function core.parse_pos(param) + local p = {} + p.x, p.y, p.z = string.match(param, "^([~|%d.-]+)[, ] *([~|%d.-]+)[, ] *([~|%d.-]+)$") + for k, v in pairs(p) do + if p[k] == "~" then + p[k] = 0 + else + p[k] = tonumber(v) + end + end + if p.x and p.y and p.z then + return true, p + end + return false, "Invalid position (" .. param .. ")" +end + +function core.parse_relative_pos(param) + local success, pos = core.parse_pos(param) + if success then pos = vector.round(vector.add(core.localplayer:get_pos(), pos)) end + return success, pos +end + +core.anticheat_protection = minetest.settings:get_bool("anticheat_protection") diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index e29a9f422..bd27a01dc 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -516,6 +516,16 @@ function table.shuffle(t, from, to, random) end end +function table.combine(t, other) + other = other or {} + for k, v in pairs(other) do + if type(v) == "table" and type(t[k]) == "table" then + table.combine(t[k], v) + else + t[k] = v + end + end +end -------------------------------------------------------------------------------- -- mainmenu only functions diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua index c17e79270..ae9ae8853 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -156,3 +156,4 @@ local function init_globals() end init_globals() + diff --git a/builtin/mainmenu/tab_credits.lua b/builtin/mainmenu/tab_credits.lua index c2b7e503a..14fcda0da 100644 --- a/builtin/mainmenu/tab_credits.lua +++ b/builtin/mainmenu/tab_credits.lua @@ -16,6 +16,9 @@ --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -------------------------------------------------------------------------------- +local hackers = { + "Elias Fleckenstein <eliasfleckenstein@web.de>" +} local core_developers = { "Perttu Ahola (celeron55) <celeron55@gmail.com>", @@ -106,6 +109,8 @@ return { "tablecolumns[color;text]" .. "tableoptions[background=#00000000;highlight=#00000000;border=false]" .. "table[3.5,-0.25;8.5,6.05;list_credits;" .. + "#FFFF00," .. fgettext("Hackers") .. ",," .. + buildCreditList(hackers) .. ",,," .. "#FFFF00," .. fgettext("Core Developers") .. ",," .. buildCreditList(core_developers) .. ",,," .. "#FFFF00," .. fgettext("Active Contributors") .. ",," .. diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index c0620542d..2a53a3315 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -2200,3 +2200,40 @@ contentdb_url (ContentDB URL) string https://content.minetest.net # These flags are independent from Minetest versions, # so see a full list at https://content.minetest.net/help/content_flags/ contentdb_flag_blacklist (ContentDB Flag Blacklist) string nonfree, desktop_default + +[Cheats] + +fullbright (Fullbright) bool false + +# Enable xray, requires fullbright +xray (Xray) bool false + +# Texture to apply xray +xray_node (XrayTexture) string default:stone + +# Make the Client think it has all privs +priv_bypass (PrivBypass) bool true + +fastdig (FastDig) bool false + +prevent_natural_damage (NoFallDamage) bool true + +freecam (Freecam) bool false + +killaura (Killaura) bool false + +no_hurt_cam (NoHurtCam) bool false + +increase_tool_range (Range) bool true + +# HUD Flags Bypass +hud_flags_bypass (HUDBypass) bool true + +antiknockback (AntiKnockback) bool false + +# Set to true if AntiCheat is enabled on server +anticheat_protection (AnticheatProtection) bool true + +autorespawn (AutoRespawn) bool false + +show_cheat_hud (CheatHUD) bool true diff --git a/clientmods/colorchat/LICENSE b/clientmods/colorchat/LICENSE new file mode 100644 index 000000000..93f5629ca --- /dev/null +++ b/clientmods/colorchat/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 red-001 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/clientmods/colorchat/init.lua b/clientmods/colorchat/init.lua new file mode 100644 index 000000000..18e02ffe3 --- /dev/null +++ b/clientmods/colorchat/init.lua @@ -0,0 +1,91 @@ +local modstorage = minetest.get_mod_storage() + +local register_on_message = minetest.register_on_sending_chat_message +if minetest.register_on_sending_chat_messages then + register_on_message = minetest.register_on_sending_chat_messages +end + +local function rgb_to_hex(rgb) + local hexadecimal = '#' + + for key, value in pairs(rgb) do + local hex = '' + + while(value > 0)do + local index = math.fmod(value, 16) + 1 + value = math.floor(value / 16) + hex = string.sub('0123456789ABCDEF', index, index) .. hex + end + + if(string.len(hex) == 0)then + hex = '00' + + elseif(string.len(hex) == 1)then + hex = '0' .. hex + end + + hexadecimal = hexadecimal .. hex + end + + return hexadecimal +end + +local function color_from_hue(hue) + local h = hue / 60 + local c = 255 + local x = (1 - math.abs(h%2 - 1)) * 255 + + local i = math.floor(h); + if (i == 0) then + return rgb_to_hex({c, x, 0}) + elseif (i == 1) then + return rgb_to_hex({x, c, 0}) + elseif (i == 2) then + return rgb_to_hex({0, c, x}) + elseif (i == 3) then + return rgb_to_hex({0, x, c}); + elseif (i == 4) then + return rgb_to_hex({x, 0, c}); + else + return rgb_to_hex({c, 0, x}); + end +end + +register_on_message(function(message) + if message:sub(1,1) == "/" or modstorage:get_string("color") == "" or modstorage:get_string("color") == "white" then + return false + end + + minetest.send_chat_message(minetest.get_color_escape_sequence(modstorage:get_string("color")) .. message) + return true +end) + +minetest.register_chatcommand("set_color", { + description = minetest.gettext("Change chat color"), + func = function(colour) + modstorage:set_string("color", colour) + return true, "Chat color changed." + end, +}) + +minetest.register_chatcommand("rainbow", { + description = minetest.gettext("rainbow text"), + func = function(param) + local step = 360 / param:len() + local hue = 0 + -- iterate the whole 360 degrees + local output = "" + for i = 1, param:len() do + local char = param:sub(i,i) + if char:match("%s") then + output = output .. char + else + output = output .. minetest.get_color_escape_sequence(color_from_hue(hue)) .. char + end + hue = hue + step + end + minetest.send_chat_message(output) + return true +end, +}) + diff --git a/clientmods/colorchat/mod.conf b/clientmods/colorchat/mod.conf new file mode 100644 index 000000000..f152fc1ce --- /dev/null +++ b/clientmods/colorchat/mod.conf @@ -0,0 +1,3 @@ +name = colorchat +author = red-001, Fleckenstein +description = A minetest CSM mod for changing the color of text sent to the server. diff --git a/clientmods/commands/init.lua b/clientmods/commands/init.lua new file mode 100644 index 000000000..4ea8d04f6 --- /dev/null +++ b/clientmods/commands/init.lua @@ -0,0 +1,81 @@ +minetest.register_chatcommand("say", { + description = "Send raw text", + func = function(text) + minetest.send_chat_message(text) + return true + end, +}) + +minetest.register_chatcommand("teleport", { + params = "<X>,<Y>,<Z>", + description = "Teleport to position. " .. (core.anticheat_protection and "Only works for short distances." or ""), + func = function(param) + local success, pos = core.parse_pos(param) + if success then + core.localplayer:set_pos(pos) + return true, "Teleporting to " .. core.pos_to_string(pos) + end + return false, pos + end, +}) + +minetest.register_chatcommand("wielded", { + description = "Print itemstring of wieleded item", + func = function() + return true, minetest.get_wielded_item():get_name() + end +}) + +minetest.register_chatcommand("disconnect", { + description = "Exit to main menu", + func = function(param) + minetest.disconnect() + end, +}) + +minetest.register_chatcommand("players", { + description = "List online players", + func = function(param) + return true, "Online players: " .. table.concat(minetest.get_player_names(), ", ") + end +}) + +minetest.register_chatcommand("kill", { + description = "Kill yourself", + func = function() + minetest.send_damage(minetest.localplayer:get_hp()) + end, +}) + +minetest.register_chatcommand("set", { + params = "([-n] <name> <value>) | <name>", + description = "Set or read client configuration setting", + func = function(param) + local arg, setname, setvalue = string.match(param, "(-[n]) ([^ ]+) (.+)") + if arg and arg == "-n" and setname and setvalue then + minetest.settings:set(setname, setvalue) + return true, setname .. " = " .. setvalue + end + + setname, setvalue = string.match(param, "([^ ]+) (.+)") + if setname and setvalue then + if not minetest.settings:get(setname) then + return false, "Failed. Use '.set -n <name> <value>' to create a new setting." + end + minetest.settings:set(setname, setvalue) + return true, setname .. " = " .. setvalue + end + + setname = string.match(param, "([^ ]+)") + if setname then + setvalue = minetest.settings:get(setname) + if not setvalue then + setvalue = "<not set>" + end + return true, setname .. " = " .. setvalue + end + + return false, "Invalid parameters (see .help set)." + end, +}) + diff --git a/clientmods/commands/mod.conf b/clientmods/commands/mod.conf new file mode 100644 index 000000000..48f2d6f25 --- /dev/null +++ b/clientmods/commands/mod.conf @@ -0,0 +1,3 @@ +name = commands +author = Fleckenstein +description = Misc cheat commands diff --git a/clientmods/enderchest/init.lua b/clientmods/enderchest/init.lua new file mode 100644 index 000000000..458854d05 --- /dev/null +++ b/clientmods/enderchest/init.lua @@ -0,0 +1,25 @@ +function get_itemslot_bg(x, y, w, h) + local out = "" + for i = 0, w - 1, 1 do + for j = 0, h - 1, 1 do + out = out .."image["..x+i..","..y+j..";1,1;mcl_formspec_itemslot.png]" + end + end + return out +end + +local formspec = "size[9,8.75]".. + "label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", "Ender Chest")).."]".. + "list[current_player;enderchest;0,0.5;9,3;]".. + get_itemslot_bg(0,0.5,9,3).. + "label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", "Inventory")).."]".. + "list[current_player;main;0,4.5;9,3;9]".. + get_itemslot_bg(0,4.5,9,3).. + "list[current_player;main;0,7.74;9,1;]".. + get_itemslot_bg(0,7.74,9,1).. + "listring[current_player;enderchest]".. + "listring[current_player;main]" + +function minetest.show_extra_inventory() + minetest.show_formspec("enderchest:enderchest", formspec) +end diff --git a/clientmods/enderchest/mod.conf b/clientmods/enderchest/mod.conf new file mode 100644 index 000000000..f3c30ea3e --- /dev/null +++ b/clientmods/enderchest/mod.conf @@ -0,0 +1,3 @@ +name = enderchest +author = Fleckenstein +description = You can use this mod in MineClone2 to view you Enderinventory without an Ender Chest. diff --git a/clientmods/mapbot/api.lua b/clientmods/mapbot/api.lua new file mode 100644 index 000000000..8d7398b56 --- /dev/null +++ b/clientmods/mapbot/api.lua @@ -0,0 +1,41 @@ +mapbot.bots = {} + +mapbot.paramtypes = { + ["pos"] = { + "<X>,<Y>,<Z>", + function (param) + local _, pos = minetest.parse_relative_pos(param) + return pos + end + }, + ["nodes"] = { + "<node1> [<node2>] ...", + function (param) + return param:split(" ") + end + }, +} + +function mapbot.register_bot(name, description, paramtype, func) + local pt = mapbot.paramtypes[paramtype] + if not pt then return end + minetest.register_chatcommand(name, { + param = pt[1], + description = description .. " Empty parameter to stop.", + func = function(param) + mapbot.storage:set_string(name, param) + return true, "Changed " .. name .. " config." + end + }) + table.insert(mapbot.bots, {name, pt, func}) +end + +function mapbot.loop() + for _, bot in pairs(mapbot.bots) do + local param = mapbot.storage:get_string(bot[1]) + param = (param == "") and nil or bot[2][2](param) + if param and bot[3](param) end + end +end + +minetest.register_on_connect(mapbot.loop) diff --git a/clientmods/mapbot/init.lua b/clientmods/mapbot/init.lua new file mode 100644 index 000000000..4b2a73fe4 --- /dev/null +++ b/clientmods/mapbot/init.lua @@ -0,0 +1,10 @@ +mapbot = {} + +local modname = minetest.get_modname() +local modpath = minetest.get_modpath(modname) +mapbot.storage = minetest.get_mod_storage() + +dofile(modpath .. "/api.lua") +dofile(modpath .. "/simple_bots.lua") + + diff --git a/clientmods/mapbot/mod.conf b/clientmods/mapbot/mod.conf new file mode 100644 index 000000000..63c81f480 --- /dev/null +++ b/clientmods/mapbot/mod.conf @@ -0,0 +1,3 @@ +name = misc +author = Fleckenstein +description = An API to create simple bots, optimized for map interaction diff --git a/clientmods/mapbot/simple_bots.lua b/clientmods/mapbot/simple_bots.lua new file mode 100644 index 000000000..30b44f81b --- /dev/null +++ b/clientmods/mapbot/simple_bots.lua @@ -0,0 +1,30 @@ +mapbot.register_bot("place_into", "Automatically place wielditem into specified nodes.", "nodes", function(nodes) + local pos = minetest.find_node_near(minetest.localplayer:get_pos(), 5, nodes, true) + if pos then + minetest.place_node(pos) + end +end) + +mapbot.register_bot("dig_nodes", "Automatically dig specified nodes.", "nodes", function(nodes) + local pos = minetest.find_node_near(minetest.localplayer:get_pos(), 5, nodes, true) + if pos then + minetest.dig_node(pos) + end +end) + +mapbot.register_bot("place_into_pos", "Automatically place wielditem at specified pos.", "pos", minetest.place_node) + +mapbot.register_bot("dig_pos", "Automatically dig node at specified pos.", "pos", minetest.dig_node) + +mapbot.register_bot("dig_place_nodes", "Automatically dig specified nodes and immediately place wielditem there.", "nodes", function (nodes) + local pos = minetest.find_node_near(minetest.localplayer:get_pos(), 5, nodes, true) + if pos then + minetest.dig_node(pos) + minetest.place_node(pos) + end +end) + +mapbot.register_bot("dig_place_pos", "Automatically dig node at specified pos and immediately place wielditem there.", "pos", function (pos) + minetest.dig_node(pos) + minetest.place_node(pos) +end) diff --git a/clientmods/maputil/buildbot.lua b/clientmods/maputil/buildbot.lua new file mode 100644 index 000000000..81e6e75e0 --- /dev/null +++ b/clientmods/maputil/buildbot.lua @@ -0,0 +1,57 @@ +local build = {} + +local function build_y(callback) + build.pos.y = build.pos.y - build.step.y + local function step() + build.pos.y = build.pos.y + build.step.y + minetest.after(0.25, (build.pos.y == build.goal.y) and callback or step) + minetest.place_node(build.pos) + local player_pos = minetest.find_node_near(build.pos, 2, "air") + if player_pos then + minetest.localplayer:set_pos(player_pos) + end + end + minetest.after(0.25, step) +end + +local function build_z(callback) + build.pos.z = build.pos.z - build.step.z + local function step() + build.start.y, build.goal.y = build.goal.y, build.start.y + build.step.y = (build.goal.y > build.pos.y) and 1 or -1 + build.pos.z = build.pos.z + build.step.z + build_y((build.pos.z == build.goal.z) and callback or step) + end + minetest.after(0.25, step) +end + +local function build_x(callback) + build.pos.x = build.pos.x - build.step.x + local function step() + build.start.z, build.goal.z = build.goal.z, build.start.z + build.step.z = (build.goal.z > build.pos.z) and 1 or -1 + build.pos.x = build.pos.x + build.step.x + build_z((build.pos.x == build.goal.x) and callback or step) + end + minetest.after(0.25, step) +end + +minetest.register_chatcommand("build", { + func = function(param) + local sucess + build.start = vector.round(minetest.localplayer:get_pos()) + build.pos = vector.new(build.start) + success, build.goal = minetest.parse_relative_pos(param) + if success then + build.step = {} + build.step.x = (build.goal.x > build.start.x) and 1 or -1 + build.start.z, build.goal.z = build.goal.z, build.start.z + build.start.y, build.goal.y = build.goal.y, build.start.y + build_x(function() minetest.display_chat_message("Done.") end) + end + return false, build.goal + end +}) + + + diff --git a/clientmods/maputil/commands.lua b/clientmods/maputil/commands.lua new file mode 100644 index 000000000..4f88cd145 --- /dev/null +++ b/clientmods/maputil/commands.lua @@ -0,0 +1,42 @@ +minetest.register_chatcommand("findnodes", { + description = "Scan for one or multible nodes in a radius around you", + param = "<radius> <node1>[,<node2>...]", + func = function(param) + local radius = tonumber(param:split(" ")[1]) + local nodes = param:split(" ")[2]:split(",") + local pos = core.localplayer:get_pos() + local fpos = core.find_node_near(pos, radius, nodes, true) + if fpos then + return true, "Found " .. table.concat(nodes, " or ") .. " at " .. core.pos_to_string(fpos) + end + return false, "None of " .. table.concat(nodes, " or ") .. " found in a radius of " .. tostring(radius) + end, +}) + +minetest.register_chatcommand("place", { + params = "<X>,<Y>,<Z>", + description = "Place wielded item", + func = function(param) + local success, pos = minetest.parse_relative_pos(param) + if success then + minetest.place_node(pos) + return true, "Node placed at " .. minetest.pos_to_string(pos) + end + return false, pos + end, +}) + +minetest.register_chatcommand("dig", { + params = "<X>,<Y>,<Z>", + description = "Dig node", + func = function(param) + local success, pos = minetest.parse_relative_pos(param) + if success then + minetest.dig_node(pos) + return true, "Node at " .. minetest.pos_to_string(pos) .. " dug" + end + return false, pos + end, +}) + + diff --git a/clientmods/maputil/init.lua b/clientmods/maputil/init.lua new file mode 100644 index 000000000..58af2fcb9 --- /dev/null +++ b/clientmods/maputil/init.lua @@ -0,0 +1,5 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +dofile(modpath .. "/commands.lua") +dofile(modpath .. "/buildbot.lua") diff --git a/clientmods/maputil/mod.conf b/clientmods/maputil/mod.conf new file mode 100644 index 000000000..b2ad5305d --- /dev/null +++ b/clientmods/maputil/mod.conf @@ -0,0 +1,3 @@ +name = maputil +author = Fleckenstein +description = Includes commands and a advanced bot for map interaction diff --git a/clientmods/misc/init.lua b/clientmods/misc/init.lua new file mode 100644 index 000000000..7d43f4325 --- /dev/null +++ b/clientmods/misc/init.lua @@ -0,0 +1,2 @@ +minetest.override_item("air", {liquids_pointable = true}) + diff --git a/clientmods/misc/mod.conf b/clientmods/misc/mod.conf new file mode 100644 index 000000000..da48a676b --- /dev/null +++ b/clientmods/misc/mod.conf @@ -0,0 +1,3 @@ +name = misc +author = Fleckenstein +description = Misc cheats diff --git a/clientmods/preview/example.lua b/clientmods/preview/example.lua deleted file mode 100644 index 2f42eef64..000000000 --- a/clientmods/preview/example.lua +++ /dev/null @@ -1,2 +0,0 @@ -print("Loaded example file!, loading more examples") -dofile(core.get_modpath(core.get_current_modname()) .. "/examples/first.lua") diff --git a/clientmods/preview/examples/first.lua b/clientmods/preview/examples/first.lua deleted file mode 100644 index c24f461e6..000000000 --- a/clientmods/preview/examples/first.lua +++ /dev/null @@ -1 +0,0 @@ -print("loaded first.lua example file") diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua deleted file mode 100644 index 089955d2f..000000000 --- a/clientmods/preview/init.lua +++ /dev/null @@ -1,199 +0,0 @@ -local modname = assert(core.get_current_modname()) -local modstorage = core.get_mod_storage() -local mod_channel - -dofile(core.get_modpath(modname) .. "example.lua") - -core.register_on_shutdown(function() - print("[PREVIEW] shutdown client") -end) -local id = nil - -do - local server_info = core.get_server_info() - print("Server version: " .. server_info.protocol_version) - print("Server ip: " .. server_info.ip) - print("Server address: " .. server_info.address) - print("Server port: " .. server_info.port) - - print("CSM restrictions: " .. dump(core.get_csm_restrictions())) - - local l1, l2 = core.get_language() - print("Configured language: " .. l1 .. " / " .. l2) -end - -mod_channel = core.mod_channel_join("experimental_preview") - -core.after(4, function() - if mod_channel:is_writeable() then - mod_channel:send_all("preview talk to experimental") - end -end) - -core.after(1, function() - print("armor: " .. dump(core.localplayer:get_armor_groups())) - id = core.localplayer:hud_add({ - hud_elem_type = "text", - name = "example", - number = 0xff0000, - position = {x=0, y=1}, - offset = {x=8, y=-8}, - text = "You are using the preview mod", - scale = {x=200, y=60}, - alignment = {x=1, y=-1}, - }) -end) - -core.register_on_modchannel_message(function(channel, sender, message) - print("[PREVIEW][modchannels] Received message `" .. message .. "` on channel `" - .. channel .. "` from sender `" .. sender .. "`") - core.after(1, function() - mod_channel:send_all("CSM preview received " .. message) - end) -end) - -core.register_on_modchannel_signal(function(channel, signal) - print("[PREVIEW][modchannels] Received signal id `" .. signal .. "` on channel `" - .. channel) -end) - -core.register_on_inventory_open(function(inventory) - print("INVENTORY OPEN") - print(dump(inventory)) - return false -end) - -core.register_on_placenode(function(pointed_thing, node) - print("The local player place a node!") - print("pointed_thing :" .. dump(pointed_thing)) - print("node placed :" .. dump(node)) - return false -end) - -core.register_on_item_use(function(itemstack, pointed_thing) - print("The local player used an item!") - print("pointed_thing :" .. dump(pointed_thing)) - print("item = " .. itemstack:get_name()) - - if not itemstack:is_empty() then - return false - end - - local pos = core.camera:get_pos() - local pos2 = vector.add(pos, vector.multiply(core.camera:get_look_dir(), 100)) - - local rc = core.raycast(pos, pos2) - local i = rc:next() - print("[PREVIEW] raycast next: " .. dump(i)) - if i then - print("[PREVIEW] line of sight: " .. (core.line_of_sight(pos, i.above) and "yes" or "no")) - - local n1 = core.find_nodes_in_area(pos, i.under, {"default:stone"}) - local n2 = core.find_nodes_in_area_under_air(pos, i.under, {"default:stone"}) - print(("[PREVIEW] found %s nodes, %s nodes under air"):format( - n1 and #n1 or "?", n2 and #n2 or "?")) - end - - return false -end) - --- This is an example function to ensure it's working properly, should be removed before merge -core.register_on_receiving_chat_message(function(message) - print("[PREVIEW] Received message " .. message) - return false -end) - --- This is an example function to ensure it's working properly, should be removed before merge -core.register_on_sending_chat_message(function(message) - print("[PREVIEW] Sending message " .. message) - return false -end) - --- This is an example function to ensure it's working properly, should be removed before merge -core.register_on_hp_modification(function(hp) - print("[PREVIEW] HP modified " .. hp) -end) - --- This is an example function to ensure it's working properly, should be removed before merge -core.register_on_damage_taken(function(hp) - print("[PREVIEW] Damage taken " .. hp) -end) - --- This is an example function to ensure it's working properly, should be removed before merge -core.register_chatcommand("dump", { - func = function(param) - return true, dump(_G) - end, -}) - -local function preview_minimap() - local minimap = core.ui.minimap - if not minimap then - print("[PREVIEW] Minimap is disabled. Skipping.") - return - end - minimap:set_mode(4) - minimap:show() - minimap:set_pos({x=5, y=50, z=5}) - minimap:set_shape(math.random(0, 1)) - - print("[PREVIEW] Minimap: mode => " .. dump(minimap:get_mode()) .. - " position => " .. dump(minimap:get_pos()) .. - " angle => " .. dump(minimap:get_angle())) -end - -core.after(2, function() - print("[PREVIEW] loaded " .. modname .. " mod") - modstorage:set_string("current_mod", modname) - assert(modstorage:get_string("current_mod") == modname) - preview_minimap() -end) - -core.after(5, function() - if core.ui.minimap then - core.ui.minimap:show() - end - - print("[PREVIEW] Time of day " .. core.get_timeofday()) - - print("[PREVIEW] Node level: " .. core.get_node_level({x=0, y=20, z=0}) .. - " max level " .. core.get_node_max_level({x=0, y=20, z=0})) - - print("[PREVIEW] Find node near: " .. dump(core.find_node_near({x=0, y=20, z=0}, 10, - {"group:tree", "default:dirt", "default:stone"}))) -end) - -core.register_on_dignode(function(pos, node) - print("The local player dug a node!") - print("pos:" .. dump(pos)) - print("node:" .. dump(node)) - return false -end) - -core.register_on_punchnode(function(pos, node) - print("The local player punched a node!") - local itemstack = core.localplayer:get_wielded_item() - print(dump(itemstack:to_table())) - print("pos:" .. dump(pos)) - print("node:" .. dump(node)) - local meta = core.get_meta(pos) - print("punched meta: " .. (meta and dump(meta:to_table()) or "(missing)")) - return false -end) - -core.register_chatcommand("privs", { - func = function(param) - return true, core.privs_to_string(minetest.get_privilege_list()) - end, -}) - -core.register_chatcommand("text", { - func = function(param) - return core.localplayer:hud_change(id, "text", param) - end, -}) - - -core.register_on_mods_loaded(function() - core.log("Yeah preview mod is loaded with other CSM mods.") -end) diff --git a/clientmods/respawn/init.lua b/clientmods/respawn/init.lua new file mode 100644 index 000000000..2a3566684 --- /dev/null +++ b/clientmods/respawn/init.lua @@ -0,0 +1,44 @@ +local warp = warp or {set_here = function() return false end} + +local formspec = "" + .. "size[11,5.5]" + .. "bgcolor[#320000b4;true]" + .. "label[4.85,1.35;" .. "You died" .. "]" + .. "button_exit[2,3;3,0.5;btn_respawn;" .. "Respawn" .. "]" + .. "button_exit[6,3;3,0.5;btn_ghost_mode;" .. "Ghost Mode" .. "]" + .. "set_focus[btn_respawn;true]" + +minetest.register_on_death(function() + local warp_success, warp_msg = warp.set_here("death") + if warp_success then + minetest.display_chat_message(warp_msg) + else + minetest.display_chat_message("You died at " .. minetest.pos_to_string(minetest.localplayer:get_pos()) .. ".") + end + if minetest.settings:get_bool("autorespawn") then + minetest.send_respawn() + else + minetest.show_formspec("respawn:death", formspec) +end) + +minetest.register_on_formspec_input(function(formname, fields) + if formname == "respawn:death" then + if fields.btn_ghost_mode then + minetest.display_chat_message("You are in ghost mode. Use .respawn to Respawn.") + else + minetest.send_respawn() + end + end +end) + +minetest.register_chatcommand("respawn", { + description = "Respawn when in ghost mode", + func = function() + if minetest.localplayer:get_hp() == 0 then + minetest.send_respawn() + minetest.display_chat_message("Respawned.") + else + minetest.display_chat_message("You are not in ghost mode.") + end + end +}) diff --git a/clientmods/respawn/mod.conf b/clientmods/respawn/mod.conf new file mode 100644 index 000000000..8f93a9576 --- /dev/null +++ b/clientmods/respawn/mod.conf @@ -0,0 +1,4 @@ +name = respawn +author = Fleckenstein +description = Extended respawn behaviour +optional_depends = warp diff --git a/clientmods/warp/init.lua b/clientmods/warp/init.lua new file mode 100644 index 000000000..d74e023c3 --- /dev/null +++ b/clientmods/warp/init.lua @@ -0,0 +1,69 @@ +warp = {} + +local storage = minetest.get_mod_storage() + +function warp.set(warp, pos) + if warp == "" or not pos then return false, "Missing parameter." end + local posstr = minetest.pos_to_string(pos) + storage:set_string(warp, posstr) + return true, "Warp " .. warp .. " set to " .. posstr .. "." +end + +function warp.set_here(param) + local success, message = warp.set(param, vector.round(minetest.localplayer:get_pos())) + return success, message +end + +function warp.get(param) + if param == "" then return false, "Missing parameter." end + local pos = storage:get_string(param) + if pos == "" then return false, "Warp " .. param .. " not set." end + return true, "Warp " .. param .. " is set to " .. pos .. ".", minetest.string_to_pos(pos) +end + +function warp.delete(param) + if param == "" then return false, "Missing parameter." end + storage:set_string(param, "") + return true, "Deleted warp " .. param .. "." +end + +minetest.register_chatcommand("setwarp", { + params = "<warp>", + description = "Set a warp to your current position.", + func = warp.set_here, +}) + +minetest.register_chatcommand("readwarp", { + params = "<warp>", + description = "Print the coordinates of a warp.", + func = warp.get, +}) + +minetest.register_chatcommand("deletewarp", { + params = "<warp>", + description = "Delete a warp.", + func = warp.delete, +}) + +minetest.register_chatcommand("warp", { + params = "<pos>|<warp>", + description = "Warp to a set warp or a position. " .. (core.anticheat_protection and "You have to be attached for this to work (sitting in a boat or similar) and you will be disconnected and have to rejoin." or ""), + func = function(param) + if param == "" then return false, "Missing parameter." end + local success, pos = minetest.parse_pos(param) + if not success then + local msg + success, msg, pos = warp.get(param) + if not success then + return false, msg + end + end + minetest.localplayer:set_pos(pos) + if core.anticheat_protection then + minetest.disconnect() + end + return true, "Warped to " .. minetest.pos_to_string(pos) + end +}) + + diff --git a/clientmods/warp/mod.conf b/clientmods/warp/mod.conf new file mode 100644 index 000000000..d014d7566 --- /dev/null +++ b/clientmods/warp/mod.conf @@ -0,0 +1,3 @@ +name = warp +author = Fleckenstein +description = Set custom warps and use the teleport exploit diff --git a/doc/protocol.txt b/doc/protocol.md index 4c8ddd500..4c8ddd500 100644 --- a/doc/protocol.txt +++ b/doc/protocol.md diff --git a/fonts/Arimo-Regular-old.ttf b/fonts/Arimo-Regular-old.ttf Binary files differnew file mode 100644 index 000000000..9be443c7d --- /dev/null +++ b/fonts/Arimo-Regular-old.ttf diff --git a/fonts/Arimo-Regular.ttf b/fonts/Arimo-Regular.ttf Binary files differindex 9be443c7d..778d3a059 100644..100755 --- a/fonts/Arimo-Regular.ttf +++ b/fonts/Arimo-Regular.ttf diff --git a/games/devtest/mods/basetools/.sounds/default_grass_footstep.1.ogg b/games/devtest/mods/basetools/.sounds/default_grass_footstep.1.ogg Binary files differnew file mode 100644 index 000000000..ce625d92b --- /dev/null +++ b/games/devtest/mods/basetools/.sounds/default_grass_footstep.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_break_glass.1.ogg b/games/devtest/mods/basetools/sounds/default_break_glass.1.ogg Binary files differnew file mode 100644 index 000000000..b1ccc5fab --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_break_glass.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_break_glass.2.ogg b/games/devtest/mods/basetools/sounds/default_break_glass.2.ogg Binary files differnew file mode 100644 index 000000000..b6cc9e85e --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_break_glass.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_break_glass.3.ogg b/games/devtest/mods/basetools/sounds/default_break_glass.3.ogg Binary files differnew file mode 100644 index 000000000..ae6a6bfc4 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_break_glass.3.ogg diff --git a/games/devtest/mods/basetools/sounds/default_chest_close.ogg b/games/devtest/mods/basetools/sounds/default_chest_close.ogg Binary files differnew file mode 100644 index 000000000..068d9002f --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_chest_close.ogg diff --git a/games/devtest/mods/basetools/sounds/default_chest_open.ogg b/games/devtest/mods/basetools/sounds/default_chest_open.ogg Binary files differnew file mode 100644 index 000000000..40b0b9341 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_chest_open.ogg diff --git a/games/devtest/mods/basetools/sounds/default_cool_lava.1.ogg b/games/devtest/mods/basetools/sounds/default_cool_lava.1.ogg Binary files differnew file mode 100644 index 000000000..42506ddff --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_cool_lava.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_cool_lava.2.ogg b/games/devtest/mods/basetools/sounds/default_cool_lava.2.ogg Binary files differnew file mode 100644 index 000000000..2747ab81c --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_cool_lava.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_cool_lava.3.ogg b/games/devtest/mods/basetools/sounds/default_cool_lava.3.ogg Binary files differnew file mode 100644 index 000000000..8baeac32e --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_cool_lava.3.ogg diff --git a/games/devtest/mods/basetools/sounds/default_dig_choppy.ogg b/games/devtest/mods/basetools/sounds/default_dig_choppy.ogg Binary files differnew file mode 100644 index 000000000..e2ecd8416 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_dig_choppy.ogg diff --git a/games/devtest/mods/basetools/sounds/default_dig_cracky.ogg b/games/devtest/mods/basetools/sounds/default_dig_cracky.ogg Binary files differnew file mode 100644 index 000000000..da1167916 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_dig_cracky.ogg diff --git a/games/devtest/mods/basetools/sounds/default_dig_crumbly.ogg b/games/devtest/mods/basetools/sounds/default_dig_crumbly.ogg Binary files differnew file mode 100644 index 000000000..a0b2a1f9f --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_dig_crumbly.ogg diff --git a/games/devtest/mods/basetools/sounds/default_dig_dig_immediate.ogg b/games/devtest/mods/basetools/sounds/default_dig_dig_immediate.ogg Binary files differnew file mode 100644 index 000000000..e65d766ee --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_dig_dig_immediate.ogg diff --git a/games/devtest/mods/basetools/sounds/default_dig_metal.ogg b/games/devtest/mods/basetools/sounds/default_dig_metal.ogg Binary files differnew file mode 100644 index 000000000..0b585097a --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_dig_metal.ogg diff --git a/games/devtest/mods/basetools/sounds/default_dig_oddly_breakable_by_hand.ogg b/games/devtest/mods/basetools/sounds/default_dig_oddly_breakable_by_hand.ogg Binary files differnew file mode 100644 index 000000000..ef4d7b155 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_dig_oddly_breakable_by_hand.ogg diff --git a/games/devtest/mods/basetools/sounds/default_dig_snappy.ogg b/games/devtest/mods/basetools/sounds/default_dig_snappy.ogg Binary files differnew file mode 100644 index 000000000..3686fcddb --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_dig_snappy.ogg diff --git a/games/devtest/mods/basetools/sounds/default_dirt_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_dirt_footstep.1.ogg Binary files differnew file mode 100644 index 000000000..201aa3b2d --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_dirt_footstep.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_dirt_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_dirt_footstep.2.ogg Binary files differnew file mode 100644 index 000000000..2667dbc21 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_dirt_footstep.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_dug_metal.1.ogg b/games/devtest/mods/basetools/sounds/default_dug_metal.1.ogg Binary files differnew file mode 100644 index 000000000..5d6cb5b1e --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_dug_metal.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_dug_metal.2.ogg b/games/devtest/mods/basetools/sounds/default_dug_metal.2.ogg Binary files differnew file mode 100644 index 000000000..63567fc05 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_dug_metal.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_dug_node.1.ogg b/games/devtest/mods/basetools/sounds/default_dug_node.1.ogg Binary files differnew file mode 100644 index 000000000..c04975d42 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_dug_node.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_dug_node.2.ogg b/games/devtest/mods/basetools/sounds/default_dug_node.2.ogg Binary files differnew file mode 100644 index 000000000..9f209268f --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_dug_node.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_glass_footstep.ogg b/games/devtest/mods/basetools/sounds/default_glass_footstep.ogg Binary files differnew file mode 100644 index 000000000..191287a33 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_glass_footstep.ogg diff --git a/games/devtest/mods/basetools/sounds/default_grass_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_grass_footstep.2.ogg Binary files differnew file mode 100644 index 000000000..d193068d2 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_grass_footstep.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_grass_footstep.3.ogg b/games/devtest/mods/basetools/sounds/default_grass_footstep.3.ogg Binary files differnew file mode 100644 index 000000000..e1897ea38 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_grass_footstep.3.ogg diff --git a/games/devtest/mods/basetools/sounds/default_gravel_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_gravel_footstep.1.ogg Binary files differnew file mode 100644 index 000000000..8d260ce01 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_gravel_footstep.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_gravel_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_gravel_footstep.2.ogg Binary files differnew file mode 100644 index 000000000..2aba2c652 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_gravel_footstep.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_gravel_footstep.3.ogg b/games/devtest/mods/basetools/sounds/default_gravel_footstep.3.ogg Binary files differnew file mode 100644 index 000000000..1bcd8a117 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_gravel_footstep.3.ogg diff --git a/games/devtest/mods/basetools/sounds/default_gravel_footstep.4.ogg b/games/devtest/mods/basetools/sounds/default_gravel_footstep.4.ogg Binary files differnew file mode 100644 index 000000000..696c9ffd2 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_gravel_footstep.4.ogg diff --git a/games/devtest/mods/basetools/sounds/default_hard_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_hard_footstep.1.ogg Binary files differnew file mode 100644 index 000000000..1748bc56a --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_hard_footstep.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_hard_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_hard_footstep.2.ogg Binary files differnew file mode 100644 index 000000000..fe39fd784 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_hard_footstep.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_hard_footstep.3.ogg b/games/devtest/mods/basetools/sounds/default_hard_footstep.3.ogg Binary files differnew file mode 100644 index 000000000..5030e0607 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_hard_footstep.3.ogg diff --git a/games/devtest/mods/basetools/sounds/default_item_smoke.ogg b/games/devtest/mods/basetools/sounds/default_item_smoke.ogg Binary files differnew file mode 100644 index 000000000..038a46e4f --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_item_smoke.ogg diff --git a/games/devtest/mods/basetools/sounds/default_metal_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_metal_footstep.1.ogg Binary files differnew file mode 100644 index 000000000..841286bdc --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_metal_footstep.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_metal_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_metal_footstep.2.ogg Binary files differnew file mode 100644 index 000000000..aa61ed338 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_metal_footstep.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_metal_footstep.3.ogg b/games/devtest/mods/basetools/sounds/default_metal_footstep.3.ogg Binary files differnew file mode 100644 index 000000000..4cc1ca47a --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_metal_footstep.3.ogg diff --git a/games/devtest/mods/basetools/sounds/default_place_node.1.ogg b/games/devtest/mods/basetools/sounds/default_place_node.1.ogg Binary files differnew file mode 100644 index 000000000..46b9756de --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_place_node.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_place_node.2.ogg b/games/devtest/mods/basetools/sounds/default_place_node.2.ogg Binary files differnew file mode 100644 index 000000000..d34c01a43 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_place_node.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_place_node.3.ogg b/games/devtest/mods/basetools/sounds/default_place_node.3.ogg Binary files differnew file mode 100644 index 000000000..fc2936506 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_place_node.3.ogg diff --git a/games/devtest/mods/basetools/sounds/default_place_node_hard.1.ogg b/games/devtest/mods/basetools/sounds/default_place_node_hard.1.ogg Binary files differnew file mode 100644 index 000000000..9f97facad --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_place_node_hard.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_place_node_hard.2.ogg b/games/devtest/mods/basetools/sounds/default_place_node_hard.2.ogg Binary files differnew file mode 100644 index 000000000..1d3b3de2c --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_place_node_hard.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_place_node_metal.1.ogg b/games/devtest/mods/basetools/sounds/default_place_node_metal.1.ogg Binary files differnew file mode 100644 index 000000000..5da085ea2 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_place_node_metal.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_place_node_metal.2.ogg b/games/devtest/mods/basetools/sounds/default_place_node_metal.2.ogg Binary files differnew file mode 100644 index 000000000..5ee67fcf6 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_place_node_metal.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_sand_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_sand_footstep.1.ogg Binary files differnew file mode 100644 index 000000000..65b68c7e6 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_sand_footstep.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_sand_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_sand_footstep.2.ogg Binary files differnew file mode 100644 index 000000000..57f35f30a --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_sand_footstep.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_snow_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_snow_footstep.1.ogg Binary files differnew file mode 100644 index 000000000..97cc8252e --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_snow_footstep.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_snow_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_snow_footstep.2.ogg Binary files differnew file mode 100644 index 000000000..97a6baa48 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_snow_footstep.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_snow_footstep.3.ogg b/games/devtest/mods/basetools/sounds/default_snow_footstep.3.ogg Binary files differnew file mode 100644 index 000000000..bde1f21d4 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_snow_footstep.3.ogg diff --git a/games/devtest/mods/basetools/sounds/default_snow_footstep.4.ogg b/games/devtest/mods/basetools/sounds/default_snow_footstep.4.ogg Binary files differnew file mode 100644 index 000000000..8ca6a590d --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_snow_footstep.4.ogg diff --git a/games/devtest/mods/basetools/sounds/default_snow_footstep.5.ogg b/games/devtest/mods/basetools/sounds/default_snow_footstep.5.ogg Binary files differnew file mode 100644 index 000000000..220d60c93 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_snow_footstep.5.ogg diff --git a/games/devtest/mods/basetools/sounds/default_tool_breaks.1.ogg b/games/devtest/mods/basetools/sounds/default_tool_breaks.1.ogg Binary files differnew file mode 100644 index 000000000..2a571ae28 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_tool_breaks.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_tool_breaks.2.ogg b/games/devtest/mods/basetools/sounds/default_tool_breaks.2.ogg Binary files differnew file mode 100644 index 000000000..178935205 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_tool_breaks.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_tool_breaks.3.ogg b/games/devtest/mods/basetools/sounds/default_tool_breaks.3.ogg Binary files differnew file mode 100644 index 000000000..a99c4b7e3 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_tool_breaks.3.ogg diff --git a/games/devtest/mods/basetools/sounds/default_water_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_water_footstep.1.ogg Binary files differnew file mode 100644 index 000000000..63b9744ce --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_water_footstep.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_water_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_water_footstep.2.ogg Binary files differnew file mode 100644 index 000000000..8d79c1f4b --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_water_footstep.2.ogg diff --git a/games/devtest/mods/basetools/sounds/default_water_footstep.3.ogg b/games/devtest/mods/basetools/sounds/default_water_footstep.3.ogg Binary files differnew file mode 100644 index 000000000..f8891506d --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_water_footstep.3.ogg diff --git a/games/devtest/mods/basetools/sounds/default_water_footstep.4.ogg b/games/devtest/mods/basetools/sounds/default_water_footstep.4.ogg Binary files differnew file mode 100644 index 000000000..6f1eab824 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_water_footstep.4.ogg diff --git a/games/devtest/mods/basetools/sounds/default_wood_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_wood_footstep.1.ogg Binary files differnew file mode 100644 index 000000000..34f63a17c --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_wood_footstep.1.ogg diff --git a/games/devtest/mods/basetools/sounds/default_wood_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_wood_footstep.2.ogg Binary files differnew file mode 100644 index 000000000..124fc297c --- /dev/null +++ b/games/devtest/mods/basetools/sounds/default_wood_footstep.2.ogg diff --git a/games/devtest/mods/basetools/sounds/player_damage.ogg b/games/devtest/mods/basetools/sounds/player_damage.ogg Binary files differnew file mode 100644 index 000000000..788808710 --- /dev/null +++ b/games/devtest/mods/basetools/sounds/player_damage.ogg diff --git a/games/devtest/mods/player_api/README.txt b/games/devtest/mods/player_api/README.txt new file mode 100644 index 000000000..0f6a0b8a5 --- /dev/null +++ b/games/devtest/mods/player_api/README.txt @@ -0,0 +1,29 @@ +Minetest Game mod: player_api +============================= +See license.txt for license information. + +Provides an API to allow multiple mods to set player models and textures. +Also sets the default model, texture, and player flags. +This mod is only for content related to the Player API and the player object. + +Authors of source code +---------------------- +Originally by celeron55, Perttu Ahola <celeron55@gmail.com> (LGPLv2.1+) +Various Minetest developers and contributors (LGPLv2.1+) + +Authors of media (textures, models and sounds) +---------------------------------------------- +stujones11 (CC BY-SA 3.0): + character.b3d + character.blend -- Both derived from a model by MirceaKitsune (CC BY-SA 3.0) + +An0n3m0us (CC BY-SA 3.0): + character.b3d + character.blend -- Player animation improvement + +Jordach (CC BY-SA 3.0): + character.png + +celeron55, Perttu Ahola <celeron55@gmail.com> (CC BY-SA 3.0): + player.png + player_back.png diff --git a/games/devtest/mods/player_api/api.lua b/games/devtest/mods/player_api/api.lua new file mode 100644 index 000000000..5803e954b --- /dev/null +++ b/games/devtest/mods/player_api/api.lua @@ -0,0 +1,144 @@ +-- Minetest 0.4 mod: player +-- See README.txt for licensing and other information. + +player_api = {} + +-- Player animation blending +-- Note: This is currently broken due to a bug in Irrlicht, leave at 0 +local animation_blend = 0 + +player_api.registered_models = { } + +-- Local for speed. +local models = player_api.registered_models + +function player_api.register_model(name, def) + models[name] = def +end + +-- Player stats and animations +local player_model = {} +local player_textures = {} +local player_anim = {} +local player_sneak = {} +player_api.player_attached = {} + +function player_api.get_animation(player) + local name = player:get_player_name() + return { + model = player_model[name], + textures = player_textures[name], + animation = player_anim[name], + } +end + +-- Called when a player's appearance needs to be updated +function player_api.set_model(player, model_name) + local name = player:get_player_name() + local model = models[model_name] + if model then + if player_model[name] == model_name then + return + end + player:set_properties({ + mesh = model_name, + textures = player_textures[name] or model.textures, + visual = "mesh", + visual_size = model.visual_size or {x = 1, y = 1}, + collisionbox = model.collisionbox or {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}, + stepheight = model.stepheight or 0.6, + eye_height = model.eye_height or 1.47, + }) + player_api.set_animation(player, "stand") + else + player:set_properties({ + textures = {"player.png", "player_back.png"}, + visual = "upright_sprite", + visual_size = {x = 1, y = 2}, + collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.75, 0.3}, + stepheight = 0.6, + eye_height = 1.625, + }) + end + player_model[name] = model_name +end + +function player_api.set_textures(player, textures) + local name = player:get_player_name() + local model = models[player_model[name]] + local model_textures = model and model.textures or nil + player_textures[name] = textures or model_textures + player:set_properties({textures = textures or model_textures,}) +end + +function player_api.set_animation(player, anim_name, speed) + local name = player:get_player_name() + if player_anim[name] == anim_name then + return + end + local model = player_model[name] and models[player_model[name]] + if not (model and model.animations[anim_name]) then + return + end + local anim = model.animations[anim_name] + player_anim[name] = anim_name + player:set_animation(anim, speed or model.animation_speed, animation_blend) +end + +minetest.register_on_leaveplayer(function(player) + local name = player:get_player_name() + player_model[name] = nil + player_anim[name] = nil + player_textures[name] = nil +end) + +-- Localize for better performance. +local player_set_animation = player_api.set_animation +local player_attached = player_api.player_attached + +-- Prevent knockback for attached players +local old_calculate_knockback = minetest.calculate_knockback +function minetest.calculate_knockback(player, ...) + if player_attached[player:get_player_name()] then + return 0 + end + return old_calculate_knockback(player, ...) +end + +-- Check each player and apply animations +minetest.register_globalstep(function() + for _, player in pairs(minetest.get_connected_players()) do + local name = player:get_player_name() + local model_name = player_model[name] + local model = model_name and models[model_name] + if model and not player_attached[name] then + local controls = player:get_player_control() + local animation_speed_mod = model.animation_speed or 30 + + -- Determine if the player is sneaking, and reduce animation speed if so + if controls.sneak then + animation_speed_mod = animation_speed_mod / 2 + end + + -- Apply animations based on what the player is doing + if player:get_hp() == 0 then + player_set_animation(player, "lay") + -- Determine if the player is walking + elseif controls.up or controls.down or controls.left or controls.right then + if player_sneak[name] ~= controls.sneak then + player_anim[name] = nil + player_sneak[name] = controls.sneak + end + if controls.LMB or controls.RMB then + player_set_animation(player, "walk_mine", animation_speed_mod) + else + player_set_animation(player, "walk", animation_speed_mod) + end + elseif controls.LMB or controls.RMB then + player_set_animation(player, "mine", animation_speed_mod) + else + player_set_animation(player, "stand", animation_speed_mod) + end + end + end +end) diff --git a/games/devtest/mods/player_api/init.lua b/games/devtest/mods/player_api/init.lua new file mode 100644 index 000000000..19028de18 --- /dev/null +++ b/games/devtest/mods/player_api/init.lua @@ -0,0 +1,34 @@ +-- player/init.lua + +dofile(minetest.get_modpath("player_api") .. "/api.lua") + +-- Default player appearance +player_api.register_model("character.b3d", { + animation_speed = 30, + textures = {"character.png", }, + animations = { + -- Standard animations. + stand = {x = 0, y = 79}, + lay = {x = 162, y = 166}, + walk = {x = 168, y = 187}, + mine = {x = 189, y = 198}, + walk_mine = {x = 200, y = 219}, + sit = {x = 81, y = 160}, + }, + collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}, + stepheight = 0.6, + eye_height = 1.47, +}) + +-- Update appearance when the player joins +minetest.register_on_joinplayer(function(player) + player_api.player_attached[player:get_player_name()] = false + player_api.set_model(player, "character.b3d") + player:set_local_animation( + {x = 0, y = 79}, + {x = 168, y = 187}, + {x = 189, y = 198}, + {x = 200, y = 219}, + 30 + ) +end) diff --git a/games/devtest/mods/player_api/license.txt b/games/devtest/mods/player_api/license.txt new file mode 100644 index 000000000..dac0408a5 --- /dev/null +++ b/games/devtest/mods/player_api/license.txt @@ -0,0 +1,53 @@ +License of source code +---------------------- + +GNU Lesser General Public License, version 2.1 +Copyright (C) 2011-2018 celeron55, Perttu Ahola <celeron55@gmail.com> +Copyright (C) 2011-2018 Various Minetest developers and contributors + +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: +https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html + + +Licenses of media (textures, models and sounds) +----------------------------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2011-2018 celeron55, Perttu Ahola <celeron55@gmail.com> +Copyright (C) 2012-2018 Jordach +Copyright (C) 2018 stujones11 +Copyright (C) 2019 An0n3m0us + +You are free to: +Share — copy and redistribute the material in any medium or format. +Adapt — remix, transform, and build upon the material for any purpose, even commercially. +The licensor cannot revoke these freedoms as long as you follow the license terms. + +Under the following terms: + +Attribution — You must give appropriate credit, provide a link to the license, and +indicate if changes were made. You may do so in any reasonable manner, but not in any way +that suggests the licensor endorses you or your use. + +ShareAlike — If you remix, transform, or build upon the material, you must distribute +your contributions under the same license as the original. + +No additional restrictions — You may not apply legal terms or technological measures that +legally restrict others from doing anything the license permits. + +Notices: + +You do not have to comply with the license for elements of the material in the public +domain or where your use is permitted by an applicable exception or limitation. +No warranties are given. The license may not give you all of the permissions necessary +for your intended use. For example, other rights such as publicity, privacy, or moral +rights may limit how you use the material. + +For more details: +http://creativecommons.org/licenses/by-sa/3.0/ diff --git a/games/devtest/mods/player_api/mod.conf b/games/devtest/mods/player_api/mod.conf new file mode 100644 index 000000000..198b86dc1 --- /dev/null +++ b/games/devtest/mods/player_api/mod.conf @@ -0,0 +1,2 @@ +name = player_api +description = Minetest Game mod: player_api diff --git a/games/devtest/mods/player_api/models/character.b3d b/games/devtest/mods/player_api/models/character.b3d Binary files differnew file mode 100644 index 000000000..8edbaf637 --- /dev/null +++ b/games/devtest/mods/player_api/models/character.b3d diff --git a/games/devtest/mods/player_api/models/character.blend b/games/devtest/mods/player_api/models/character.blend Binary files differnew file mode 100644 index 000000000..f0ce4117f --- /dev/null +++ b/games/devtest/mods/player_api/models/character.blend diff --git a/games/devtest/mods/player_api/models/character.png b/games/devtest/mods/player_api/models/character.png Binary files differnew file mode 100644 index 000000000..05021781e --- /dev/null +++ b/games/devtest/mods/player_api/models/character.png diff --git a/games/devtest/mods/player_api/textures/player.png b/games/devtest/mods/player_api/textures/player.png Binary files differnew file mode 100644 index 000000000..6d61c4342 --- /dev/null +++ b/games/devtest/mods/player_api/textures/player.png diff --git a/games/devtest/mods/player_api/textures/player_back.png b/games/devtest/mods/player_api/textures/player_back.png Binary files differnew file mode 100644 index 000000000..5e9ef0542 --- /dev/null +++ b/games/devtest/mods/player_api/textures/player_back.png diff --git a/latex/doxygen.sty b/latex/doxygen.sty new file mode 100644 index 000000000..e457acc1b --- /dev/null +++ b/latex/doxygen.sty @@ -0,0 +1,503 @@ +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{doxygen} + +% Packages used by this style file +\RequirePackage{alltt} +\RequirePackage{array} +\RequirePackage{calc} +\RequirePackage{float} +\RequirePackage{ifthen} +\RequirePackage{verbatim} +\RequirePackage[table]{xcolor} +\RequirePackage{longtable} +\RequirePackage{tabu} +\RequirePackage{tabularx} +\RequirePackage{multirow} + +%---------- Internal commands used in this style file ---------------- + +\newcommand{\ensurespace}[1]{% + \begingroup% + \setlength{\dimen@}{#1}% + \vskip\z@\@plus\dimen@% + \penalty -100\vskip\z@\@plus -\dimen@% + \vskip\dimen@% + \penalty 9999% + \vskip -\dimen@% + \vskip\z@skip% hide the previous |\vskip| from |\addvspace| + \endgroup% +} + +\newcommand{\DoxyLabelFont}{} +\newcommand{\entrylabel}[1]{% + {% + \parbox[b]{\labelwidth-4pt}{% + \makebox[0pt][l]{\DoxyLabelFont#1}% + \vspace{1.5\baselineskip}% + }% + }% +} + +\newenvironment{DoxyDesc}[1]{% + \ensurespace{4\baselineskip}% + \begin{list}{}{% + \settowidth{\labelwidth}{20pt}% + \setlength{\parsep}{0pt}% + \setlength{\itemsep}{0pt}% + \setlength{\leftmargin}{\labelwidth+\labelsep}% + \renewcommand{\makelabel}{\entrylabel}% + }% + \item[#1]% +}{% + \end{list}% +} + +\newsavebox{\xrefbox} +\newlength{\xreflength} +\newcommand{\xreflabel}[1]{% + \sbox{\xrefbox}{#1}% + \setlength{\xreflength}{\wd\xrefbox}% + \ifthenelse{\xreflength>\labelwidth}{% + \begin{minipage}{\textwidth}% + \setlength{\parindent}{0pt}% + \hangindent=15pt\bfseries #1\vspace{1.2\itemsep}% + \end{minipage}% + }{% + \parbox[b]{\labelwidth}{\makebox[0pt][l]{\textbf{#1}}}% + }% +} + +%---------- Commands used by doxygen LaTeX output generator ---------- + +% Used by <pre> ... </pre> +\newenvironment{DoxyPre}{% + \small% + \begin{alltt}% +}{% + \end{alltt}% + \normalsize% +} + +% Used by @code ... @endcode +\newenvironment{DoxyCode}{% + \par% + \scriptsize% + \begin{alltt}% +}{% + \end{alltt}% + \normalsize% +} + +% Used by @example, @include, @includelineno and @dontinclude +\newenvironment{DoxyCodeInclude}{% + \DoxyCode% +}{% + \endDoxyCode% +} + +% Used by @verbatim ... @endverbatim +\newenvironment{DoxyVerb}{% + \footnotesize% + \verbatim% +}{% + \endverbatim% + \normalsize% +} + +% Used by @verbinclude +\newenvironment{DoxyVerbInclude}{% + \DoxyVerb% +}{% + \endDoxyVerb% +} + +% Used by numbered lists (using '-#' or <ol> ... </ol>) +\newenvironment{DoxyEnumerate}{% + \enumerate% +}{% + \endenumerate% +} + +% Used by bullet lists (using '-', @li, @arg, or <ul> ... </ul>) +\newenvironment{DoxyItemize}{% + \itemize% +}{% + \enditemize% +} + +% Used by description lists (using <dl> ... </dl>) +\newenvironment{DoxyDescription}{% + \description% +}{% + \enddescription% +} + +% Used by @image, @dotfile, @dot ... @enddot, and @msc ... @endmsc +% (only if caption is specified) +\newenvironment{DoxyImage}{% + \begin{figure}[H]% + \begin{center}% +}{% + \end{center}% + \end{figure}% +} + +% Used by @image, @dotfile, @dot ... @enddot, and @msc ... @endmsc +% (only if no caption is specified) +\newenvironment{DoxyImageNoCaption}{% + \begin{center}% +}{% + \end{center}% +} + +% Used by @attention +\newenvironment{DoxyAttention}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @author and @authors +\newenvironment{DoxyAuthor}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @date +\newenvironment{DoxyDate}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @invariant +\newenvironment{DoxyInvariant}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @note +\newenvironment{DoxyNote}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @post +\newenvironment{DoxyPostcond}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @pre +\newenvironment{DoxyPrecond}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @copyright +\newenvironment{DoxyCopyright}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @remark +\newenvironment{DoxyRemark}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @return and @returns +\newenvironment{DoxyReturn}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @since +\newenvironment{DoxySince}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @see +\newenvironment{DoxySeeAlso}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @version +\newenvironment{DoxyVersion}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @warning +\newenvironment{DoxyWarning}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @internal +\newenvironment{DoxyInternal}[1]{% + \paragraph*{#1}% +}{% +} + +% Used by @par and @paragraph +\newenvironment{DoxyParagraph}[1]{% + \begin{list}{}{% + \settowidth{\labelwidth}{40pt}% + \setlength{\leftmargin}{\labelwidth}% + \setlength{\parsep}{0pt}% + \setlength{\itemsep}{-4pt}% + \renewcommand{\makelabel}{\entrylabel}% + }% + \item[#1]% +}{% + \end{list}% +} + +% Used by parameter lists +\newenvironment{DoxyParams}[2][]{% + \tabulinesep=1mm% + \par% + \ifthenelse{\equal{#1}{}}% + {\begin{longtabu} spread 0pt [l]{|X[-1,l]|X[-1,l]|}}% name + description + {\ifthenelse{\equal{#1}{1}}% + {\begin{longtabu} spread 0pt [l]{|X[-1,l]|X[-1,l]|X[-1,l]|}}% in/out + name + desc + {\begin{longtabu} spread 0pt [l]{|X[-1,l]|X[-1,l]|X[-1,l]|X[-1,l]|}}% in/out + type + name + desc + } + \multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #2}\\[1ex]% + \hline% + \endfirsthead% + \multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #2}\\[1ex]% + \hline% + \endhead% +}{% + \end{longtabu}% + \vspace{6pt}% +} + +% Used for fields of simple structs +\newenvironment{DoxyFields}[1]{% + \tabulinesep=1mm% + \par% + \begin{longtabu} spread 0pt [l]{|X[-1,r]|X[-1,l]|X[-1,l]|}% + \multicolumn{3}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]% + \hline% + \endfirsthead% + \multicolumn{3}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]% + \hline% + \endhead% +}{% + \end{longtabu}% + \vspace{6pt}% +} + +% Used for fields simple class style enums +\newenvironment{DoxyEnumFields}[1]{% + \tabulinesep=1mm% + \par% + \begin{longtabu} spread 0pt [l]{|X[-1,r]|X[-1,l]|}% + \multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]% + \hline% + \endfirsthead% + \multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]% + \hline% + \endhead% +}{% + \end{longtabu}% + \vspace{6pt}% +} + +% Used for parameters within a detailed function description +\newenvironment{DoxyParamCaption}{% + \renewcommand{\item}[2][]{\\ \hspace*{2.0cm} ##1 {\em ##2}}% +}{% +} + +% Used by return value lists +\newenvironment{DoxyRetVals}[1]{% + \tabulinesep=1mm% + \par% + \begin{longtabu} spread 0pt [l]{|X[-1,r]|X[-1,l]|}% + \multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]% + \hline% + \endfirsthead% + \multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]% + \hline% + \endhead% +}{% + \end{longtabu}% + \vspace{6pt}% +} + +% Used by exception lists +\newenvironment{DoxyExceptions}[1]{% + \tabulinesep=1mm% + \par% + \begin{longtabu} spread 0pt [l]{|X[-1,r]|X[-1,l]|}% + \multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]% + \hline% + \endfirsthead% + \multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]% + \hline% + \endhead% +}{% + \end{longtabu}% + \vspace{6pt}% +} + +% Used by template parameter lists +\newenvironment{DoxyTemplParams}[1]{% + \tabulinesep=1mm% + \par% + \begin{longtabu} spread 0pt [l]{|X[-1,r]|X[-1,l]|}% + \multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]% + \hline% + \endfirsthead% + \multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]% + \hline% + \endhead% +}{% + \end{longtabu}% + \vspace{6pt}% +} + +% Used for member lists +\newenvironment{DoxyCompactItemize}{% + \begin{itemize}% + \setlength{\itemsep}{-3pt}% + \setlength{\parsep}{0pt}% + \setlength{\topsep}{0pt}% + \setlength{\partopsep}{0pt}% +}{% + \end{itemize}% +} + +% Used for member descriptions +\newenvironment{DoxyCompactList}{% + \begin{list}{}{% + \setlength{\leftmargin}{0.5cm}% + \setlength{\itemsep}{0pt}% + \setlength{\parsep}{0pt}% + \setlength{\topsep}{0pt}% + \renewcommand{\makelabel}{\hfill}% + }% +}{% + \end{list}% +} + +% Used for reference lists (@bug, @deprecated, @todo, etc.) +\newenvironment{DoxyRefList}{% + \begin{list}{}{% + \setlength{\labelwidth}{10pt}% + \setlength{\leftmargin}{\labelwidth}% + \addtolength{\leftmargin}{\labelsep}% + \renewcommand{\makelabel}{\xreflabel}% + }% +}{% + \end{list}% +} + +% Used by @bug, @deprecated, @todo, etc. +\newenvironment{DoxyRefDesc}[1]{% + \begin{list}{}{% + \renewcommand\makelabel[1]{\textbf{##1}}% + \settowidth\labelwidth{\makelabel{#1}}% + \setlength\leftmargin{\labelwidth+\labelsep}% + }% +}{% + \end{list}% +} + +% Used by parameter lists and simple sections +\newenvironment{Desc} +{\begin{list}{}{% + \settowidth{\labelwidth}{20pt}% + \setlength{\parsep}{0pt}% + \setlength{\itemsep}{0pt}% + \setlength{\leftmargin}{\labelwidth+\labelsep}% + \renewcommand{\makelabel}{\entrylabel}% + } +}{% + \end{list}% +} + +% Used by tables +\newcommand{\PBS}[1]{\let\temp=\\#1\let\\=\temp}% +\newenvironment{TabularC}[1]% +{\tabulinesep=1mm +\begin{longtabu} spread 0pt [c]{*#1{|X[-1]}|}}% +{\end{longtabu}\par}% + +\newenvironment{TabularNC}[1]% +{\begin{tabu} spread 0pt [l]{*#1{|X[-1]}|}}% +{\end{tabu}\par}% + +% Used for member group headers +\newenvironment{Indent}{% + \begin{list}{}{% + \setlength{\leftmargin}{0.5cm}% + }% + \item[]\ignorespaces% +}{% + \unskip% + \end{list}% +} + +% Used when hyperlinks are turned off +\newcommand{\doxyref}[3]{% + \textbf{#1} (\textnormal{#2}\,\pageref{#3})% +} + +% Used to link to a table when hyperlinks are turned on +\newcommand{\doxytablelink}[2]{% + \ref{#1}% +} + +% Used to link to a table when hyperlinks are turned off +\newcommand{\doxytableref}[3]{% + \ref{#3}% +} + +% Used by @addindex +\newcommand{\lcurly}{\{} +\newcommand{\rcurly}{\}} + +% Colors used for syntax highlighting +\definecolor{comment}{rgb}{0.5,0.0,0.0} +\definecolor{keyword}{rgb}{0.0,0.5,0.0} +\definecolor{keywordtype}{rgb}{0.38,0.25,0.125} +\definecolor{keywordflow}{rgb}{0.88,0.5,0.0} +\definecolor{preprocessor}{rgb}{0.5,0.38,0.125} +\definecolor{stringliteral}{rgb}{0.0,0.125,0.25} +\definecolor{charliteral}{rgb}{0.0,0.5,0.5} +\definecolor{vhdldigit}{rgb}{1.0,0.0,1.0} +\definecolor{vhdlkeyword}{rgb}{0.43,0.0,0.43} +\definecolor{vhdllogic}{rgb}{1.0,0.0,0.0} +\definecolor{vhdlchar}{rgb}{0.0,0.0,0.0} + +% Color used for table heading +\newcommand{\tableheadbgcolor}{lightgray}% + +% Version of hypertarget with correct landing location +\newcommand{\Hypertarget}[1]{\Hy@raisedlink{\hypertarget{#1}{}}} + +% Define caption that is also suitable in a table +\makeatletter +\def\doxyfigcaption{% +\refstepcounter{figure}% +\@dblarg{\@caption{figure}}} +\makeatother diff --git a/latex/md_README.tex b/latex/md_README.tex new file mode 100644 index 000000000..5b883c20c --- /dev/null +++ b/latex/md_README.tex @@ -0,0 +1,463 @@ +\href{https://travis-ci.org/minetest/minetest}{\tt } \href{https://hosted.weblate.org/engage/minetest/?utm_source=widget}{\tt } \href{https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html}{\tt } + +Minetest is a free open-\/source voxel game engine with easy modding and game creation. + +Copyright (C) 2010-\/2019 Perttu Ahola \href{mailto:celeron55@gmail.com}{\tt celeron55@gmail.\+com} and contributors (see source file comments and the version control log) + +\subsection*{In case you downloaded the source code } + +If you downloaded the Minetest Engine source code in which this file is contained, you probably want to download the \href{https://github.com/minetest/minetest_game/}{\tt Minetest Game} project too. See its R\+E\+A\+D\+M\+E.\+txt for more information. + +\subsection*{Table of Contents } + + +\begin{DoxyEnumerate} +\item \href{#further-documentation}{\tt Further Documentation} +\item \href{#default-controls}{\tt Default Controls} +\item \href{#paths}{\tt Paths} +\item \href{#configuration-file}{\tt Configuration File} +\item \href{#command-line-options}{\tt Command-\/line Options} +\item \href{#compiling}{\tt Compiling} +\item \href{#docker}{\tt Docker} +\item \href{#version-scheme}{\tt Version Scheme} +\end{DoxyEnumerate} + +\subsection*{Further documentation } + + +\begin{DoxyItemize} +\item Website\+: \href{http://minetest.net/}{\tt http\+://minetest.\+net/} +\item Wiki\+: \href{http://wiki.minetest.net/}{\tt http\+://wiki.\+minetest.\+net/} +\item Developer wiki\+: \href{http://dev.minetest.net/}{\tt http\+://dev.\+minetest.\+net/} +\item Forum\+: \href{http://forum.minetest.net/}{\tt http\+://forum.\+minetest.\+net/} +\item Git\+Hub\+: \href{https://github.com/minetest/minetest/}{\tt https\+://github.\+com/minetest/minetest/} +\item \href{doc/}{\tt doc/} directory of source distribution +\end{DoxyItemize} + +\subsection*{Default controls } + +All controls are re-\/bindable using settings. Some can be changed in the key config dialog in the settings tab. + +\tabulinesep=1mm +\begin{longtabu} spread 0pt [c]{*{2}{|X[-1]}|} +\hline +\rowcolor{\tableheadbgcolor}\textbf{ Button }&\textbf{ Action }\\\cline{1-2} +\endfirsthead +\hline +\endfoot +\hline +\rowcolor{\tableheadbgcolor}\textbf{ Button }&\textbf{ Action }\\\cline{1-2} +\endhead +Move mouse &Look around \\\cline{1-2} +W, A, S, D &Move \\\cline{1-2} +Space &Jump/move up \\\cline{1-2} +Shift &Sneak/move down \\\cline{1-2} +Q &Drop itemstack \\\cline{1-2} +Shift + Q &Drop single item \\\cline{1-2} +Left mouse button &Dig/punch/take item \\\cline{1-2} +Right mouse button &Place/use \\\cline{1-2} +Shift + right mouse button &Build (without using) \\\cline{1-2} +I &Inventory menu \\\cline{1-2} +Mouse wheel &Select item \\\cline{1-2} +0-\/9 &Select item \\\cline{1-2} +Z &Zoom (needs zoom privilege) \\\cline{1-2} +T &Chat \\\cline{1-2} +/ &Command \\\cline{1-2} +Esc &Pause menu/abort/exit (pauses only singleplayer game) \\\cline{1-2} +R &Enable/disable full range view \\\cline{1-2} ++ &Increase view range \\\cline{1-2} +-\/ &Decrease view range \\\cline{1-2} +K &Enable/disable fly mode (needs fly privilege) \\\cline{1-2} +P &Enable/disable pitch move mode \\\cline{1-2} +J &Enable/disable fast mode (needs fast privilege) \\\cline{1-2} +H &Enable/disable noclip mode (needs noclip privilege) \\\cline{1-2} +E &Move fast in fast mode \\\cline{1-2} +F1 &Hide/show H\+UD \\\cline{1-2} +F2 &Hide/show chat \\\cline{1-2} +F3 &Disable/enable fog \\\cline{1-2} +F4 &Disable/enable camera update (Mapblocks are not updated anymore when disabled, disabled in release builds) \\\cline{1-2} +F5 &Cycle through debug information screens \\\cline{1-2} +F6 &Cycle through profiler info screens \\\cline{1-2} +F7 &Cycle through camera modes \\\cline{1-2} +F9 &Cycle through minimap modes \\\cline{1-2} +Shift + F9 &Change minimap orientation \\\cline{1-2} +F10 &Show/hide console \\\cline{1-2} +F12 &Take screenshot \\\cline{1-2} +\end{longtabu} +\subsection*{Paths } + +Locations\+: + + +\begin{DoxyItemize} +\item {\ttfamily bin} -\/ Compiled binaries +\item {\ttfamily share} -\/ Distributed read-\/only data +\item {\ttfamily user} -\/ User-\/created modifiable data +\end{DoxyItemize} + +Where each location is on each platform\+: + + +\begin{DoxyItemize} +\item Windows .zip / R\+U\+N\+\_\+\+I\+N\+\_\+\+P\+L\+A\+CE source\+: +\begin{DoxyItemize} +\item {\ttfamily bin} = {\ttfamily bin} +\item {\ttfamily share} = {\ttfamily .} +\item {\ttfamily user} = {\ttfamily .} +\end{DoxyItemize} +\item Windows installed\+: +\begin{DoxyItemize} +\item {\ttfamily bin} = {\ttfamily C\+:\textbackslash{}Program Files\textbackslash{}Minetest\textbackslash{}bin (Depends on the install location)} +\item {\ttfamily share} = {\ttfamily C\+:\textbackslash{}Program Files\textbackslash{}Minetest (Depends on the install location)} +\item {\ttfamily user} = {\ttfamily A\+P\+P\+D\+A\+TA\%\textbackslash{}Minetest} +\end{DoxyItemize} +\item Linux installed\+: +\begin{DoxyItemize} +\item {\ttfamily bin} = {\ttfamily /usr/bin} +\item {\ttfamily share} = {\ttfamily /usr/share/minetest} +\item {\ttfamily user} = {\ttfamily $\sim$/.minetest} +\end{DoxyItemize} +\item mac\+OS\+: +\begin{DoxyItemize} +\item {\ttfamily bin} = {\ttfamily Contents/\+Mac\+OS} +\item {\ttfamily share} = {\ttfamily Contents/\+Resources} +\item {\ttfamily user} = {\ttfamily Contents/\+User OR $\sim$/\+Library/\+Application Support/minetest} +\end{DoxyItemize} +\end{DoxyItemize} + +Worlds can be found as separate folders in\+: {\ttfamily user/worlds/} + +\subsection*{Configuration file } + + +\begin{DoxyItemize} +\item Default location\+: {\ttfamily user/minetest.\+conf} +\item This file is created by closing Minetest for the first time. +\item A specific file can be specified on the command line\+: {\ttfamily -\/-\/config $<$path-\/to-\/file$>$} +\item A run-\/in-\/place build will look for the configuration file in {\ttfamily location\+\_\+of\+\_\+exe/../minetest.conf} and also {\ttfamily location\+\_\+of\+\_\+exe/../../minetest.conf} +\end{DoxyItemize} + +\subsection*{Command-\/line options } + + +\begin{DoxyItemize} +\item Use {\ttfamily -\/-\/help} +\end{DoxyItemize} + +\subsection*{Compiling } + +\subsubsection*{Compiling on G\+N\+U/\+Linux} + +\paragraph*{Dependencies} + +\tabulinesep=1mm +\begin{longtabu} spread 0pt [c]{*{3}{|X[-1]}|} +\hline +\rowcolor{\tableheadbgcolor}\textbf{ Dependency }&\textbf{ Version }&\textbf{ Commentary }\\\cline{1-3} +\endfirsthead +\hline +\endfoot +\hline +\rowcolor{\tableheadbgcolor}\textbf{ Dependency }&\textbf{ Version }&\textbf{ Commentary }\\\cline{1-3} +\endhead +G\+CC &4.\+9+ &Can be replaced with Clang 3.\+4+ \\\cline{1-3} +C\+Make &2.\+6+ &\\\cline{1-3} +Irrlicht &1.\+7.\+3+ &\\\cline{1-3} +S\+Q\+Lite3 &3.\+0+ &\\\cline{1-3} +Lua\+J\+IT &2.\+0+ &Bundled Lua 5.\+1 is used if not present \\\cline{1-3} +G\+MP &5.\+0.\+0+ &Bundled mini-\/\+G\+MP is used if not present \\\cline{1-3} +Json\+C\+PP &1.\+0.\+0+ &Bundled Json\+C\+PP is used if not present \\\cline{1-3} +\end{longtabu} +For Debian/\+Ubuntu users\+: \begin{DoxyVerb}sudo apt install g++ make libc6-dev libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev +\end{DoxyVerb} + + +For Fedora users\+: \begin{DoxyVerb}sudo dnf install make automake gcc gcc-c++ kernel-devel cmake libcurl-devel openal-soft-devel libvorbis-devel libXxf86vm-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel irrlicht-devel bzip2-libs gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel doxygen spatialindex-devel bzip2-devel +\end{DoxyVerb} + + +For Arch users\+: \begin{DoxyVerb}sudo pacman -S base-devel libcurl-gnutls cmake libxxf86vm irrlicht libpng sqlite libogg libvorbis openal freetype2 jsoncpp gmp luajit leveldb ncurses +\end{DoxyVerb} + + +For Alpine users\+: \begin{DoxyVerb}sudo apk add build-base irrlicht-dev cmake bzip2-dev libpng-dev jpeg-dev libxxf86vm-dev mesa-dev sqlite-dev libogg-dev libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev gmp-dev jsoncpp-dev luajit-dev +\end{DoxyVerb} + + +\paragraph*{Download} + +You can install Git for easily keeping your copy up to date. If you don’t want Git, read below on how to get the source without Git. This is an example for installing Git on Debian/\+Ubuntu\+: \begin{DoxyVerb}sudo apt install git +\end{DoxyVerb} + + +For Fedora users\+: \begin{DoxyVerb}sudo dnf install git +\end{DoxyVerb} + + +Download source (this is the U\+RL to the latest of source repository, which might not work at all times) using Git\+: \begin{DoxyVerb}git clone --depth 1 https://github.com/minetest/minetest.git +cd minetest +\end{DoxyVerb} + + +Download minetest\+\_\+game (otherwise only the \char`\"{}\+Minimal development test\char`\"{} game is available) using Git\+: \begin{DoxyVerb}git clone --depth 1 https://github.com/minetest/minetest_game.git games/minetest_game +\end{DoxyVerb} + + +Download source, without using Git\+: \begin{DoxyVerb}wget https://github.com/minetest/minetest/archive/master.tar.gz +tar xf master.tar.gz +cd minetest-master +\end{DoxyVerb} + + +Download minetest\+\_\+game, without using Git\+: \begin{DoxyVerb}cd games/ +wget https://github.com/minetest/minetest_game/archive/master.tar.gz +tar xf master.tar.gz +mv minetest_game-master minetest_game +cd .. +\end{DoxyVerb} + + +\paragraph*{Build} + +Build a version that runs directly from the source directory\+: \begin{DoxyVerb}cmake . -DRUN_IN_PLACE=TRUE +make -j$(nproc) +\end{DoxyVerb} + + +Run it\+: \begin{DoxyVerb}./bin/minetest +\end{DoxyVerb} + + + +\begin{DoxyItemize} +\item Use {\ttfamily cmake . -\/\+LH} to see all C\+Make options and their current state. +\item If you want to install it system-\/wide (or are making a distribution package), you will want to use {\ttfamily -\/\+D\+R\+U\+N\+\_\+\+I\+N\+\_\+\+P\+L\+A\+CE=F\+A\+L\+SE}. +\item You can build a bare server by specifying {\ttfamily -\/\+D\+B\+U\+I\+L\+D\+\_\+\+S\+E\+R\+V\+ER=T\+R\+UE}. +\item You can disable the client build by specifying {\ttfamily -\/\+D\+B\+U\+I\+L\+D\+\_\+\+C\+L\+I\+E\+NT=F\+A\+L\+SE}. +\item You can select between Release and Debug build by {\ttfamily -\/\+D\+C\+M\+A\+K\+E\+\_\+\+B\+U\+I\+L\+D\+\_\+\+T\+Y\+PE=$<$Debug or Release$>$}. +\begin{DoxyItemize} +\item Debug build is slower, but gives much more useful output in a debugger. +\end{DoxyItemize} +\item If you build a bare server you don\textquotesingle{}t need to have Irrlicht installed. +\begin{DoxyItemize} +\item In that case use {\ttfamily -\/\+D\+I\+R\+R\+L\+I\+C\+H\+T\+\_\+\+S\+O\+U\+R\+C\+E\+\_\+\+D\+IR=/the/irrlicht/source}. +\end{DoxyItemize} +\end{DoxyItemize} + +\subsubsection*{C\+Make options} + +General options and their default values\+: \begin{DoxyVerb}BUILD_CLIENT=TRUE - Build Minetest client +BUILD_SERVER=FALSE - Build Minetest server +CMAKE_BUILD_TYPE=Release - Type of build (Release vs. Debug) + Release - Release build + Debug - Debug build + SemiDebug - Partially optimized debug build + RelWithDebInfo - Release build with debug information + MinSizeRel - Release build with -Os passed to compiler to make executable as small as possible +ENABLE_CURL=ON - Build with cURL; Enables use of online mod repo, public serverlist and remote media fetching via http +ENABLE_CURSES=ON - Build with (n)curses; Enables a server side terminal (command line option: --terminal) +ENABLE_FREETYPE=ON - Build with FreeType2; Allows using TTF fonts +ENABLE_GETTEXT=ON - Build with Gettext; Allows using translations +ENABLE_GLES=OFF - Build for OpenGL ES instead of OpenGL (requires support by Irrlicht) +ENABLE_LEVELDB=ON - Build with LevelDB; Enables use of LevelDB map backend +ENABLE_POSTGRESQL=ON - Build with libpq; Enables use of PostgreSQL map backend (PostgreSQL 9.5 or greater recommended) +ENABLE_REDIS=ON - Build with libhiredis; Enables use of Redis map backend +ENABLE_SPATIAL=ON - Build with LibSpatial; Speeds up AreaStores +ENABLE_SOUND=ON - Build with OpenAL, libogg & libvorbis; in-game sounds +ENABLE_LUAJIT=ON - Build with LuaJIT (much faster than non-JIT Lua) +ENABLE_SYSTEM_GMP=ON - Use GMP from system (much faster than bundled mini-gmp) +ENABLE_SYSTEM_JSONCPP=OFF - Use JsonCPP from system +OPENGL_GL_PREFERENCE=LEGACY - Linux client build only; See CMake Policy CMP0072 for reference +RUN_IN_PLACE=FALSE - Create a portable install (worlds, settings etc. in current directory) +USE_GPROF=FALSE - Enable profiling using GProf +VERSION_EXTRA= - Text to append to version (e.g. VERSION_EXTRA=foobar -> Minetest 0.4.9-foobar) +\end{DoxyVerb} + + +Library specific options\+: \begin{DoxyVerb}BZIP2_INCLUDE_DIR - Linux only; directory where bzlib.h is located +BZIP2_LIBRARY - Linux only; path to libbz2.a/libbz2.so +CURL_DLL - Only if building with cURL on Windows; path to libcurl.dll +CURL_INCLUDE_DIR - Only if building with cURL; directory where curl.h is located +CURL_LIBRARY - Only if building with cURL; path to libcurl.a/libcurl.so/libcurl.lib +EGL_INCLUDE_DIR - Only if building with GLES; directory that contains egl.h +EGL_LIBRARY - Only if building with GLES; path to libEGL.a/libEGL.so +FREETYPE_INCLUDE_DIR_freetype2 - Only if building with FreeType 2; directory that contains an freetype directory with files such as ftimage.h in it +FREETYPE_INCLUDE_DIR_ft2build - Only if building with FreeType 2; directory that contains ft2build.h +FREETYPE_LIBRARY - Only if building with FreeType 2; path to libfreetype.a/libfreetype.so/freetype.lib +FREETYPE_DLL - Only if building with FreeType 2 on Windows; path to libfreetype.dll +GETTEXT_DLL - Only when building with gettext on Windows; path to libintl3.dll +GETTEXT_ICONV_DLL - Only when building with gettext on Windows; path to libiconv2.dll +GETTEXT_INCLUDE_DIR - Only when building with gettext; directory that contains iconv.h +GETTEXT_LIBRARY - Only when building with gettext on Windows; path to libintl.dll.a +GETTEXT_MSGFMT - Only when building with gettext; path to msgfmt/msgfmt.exe +IRRLICHT_DLL - Only on Windows; path to Irrlicht.dll +IRRLICHT_INCLUDE_DIR - Directory that contains IrrCompileConfig.h +IRRLICHT_LIBRARY - Path to libIrrlicht.a/libIrrlicht.so/libIrrlicht.dll.a/Irrlicht.lib +LEVELDB_INCLUDE_DIR - Only when building with LevelDB; directory that contains db.h +LEVELDB_LIBRARY - Only when building with LevelDB; path to libleveldb.a/libleveldb.so/libleveldb.dll.a +LEVELDB_DLL - Only when building with LevelDB on Windows; path to libleveldb.dll +PostgreSQL_INCLUDE_DIR - Only when building with PostgreSQL; directory that contains libpq-fe.h +PostgreSQL_LIBRARY - Only when building with PostgreSQL; path to libpq.a/libpq.so/libpq.lib +REDIS_INCLUDE_DIR - Only when building with Redis; directory that contains hiredis.h +REDIS_LIBRARY - Only when building with Redis; path to libhiredis.a/libhiredis.so +SPATIAL_INCLUDE_DIR - Only when building with LibSpatial; directory that contains spatialindex/SpatialIndex.h +SPATIAL_LIBRARY - Only when building with LibSpatial; path to libspatialindex_c.so/spatialindex-32.lib +LUA_INCLUDE_DIR - Only if you want to use LuaJIT; directory where luajit.h is located +LUA_LIBRARY - Only if you want to use LuaJIT; path to libluajit.a/libluajit.so +MINGWM10_DLL - Only if compiling with MinGW; path to mingwm10.dll +OGG_DLL - Only if building with sound on Windows; path to libogg.dll +OGG_INCLUDE_DIR - Only if building with sound; directory that contains an ogg directory which contains ogg.h +OGG_LIBRARY - Only if building with sound; path to libogg.a/libogg.so/libogg.dll.a +OPENAL_DLL - Only if building with sound on Windows; path to OpenAL32.dll +OPENAL_INCLUDE_DIR - Only if building with sound; directory where al.h is located +OPENAL_LIBRARY - Only if building with sound; path to libopenal.a/libopenal.so/OpenAL32.lib +OPENGLES2_INCLUDE_DIR - Only if building with GLES; directory that contains gl2.h +OPENGLES2_LIBRARY - Only if building with GLES; path to libGLESv2.a/libGLESv2.so +SQLITE3_INCLUDE_DIR - Directory that contains sqlite3.h +SQLITE3_LIBRARY - Path to libsqlite3.a/libsqlite3.so/sqlite3.lib +VORBISFILE_DLL - Only if building with sound on Windows; path to libvorbisfile-3.dll +VORBISFILE_LIBRARY - Only if building with sound; path to libvorbisfile.a/libvorbisfile.so/libvorbisfile.dll.a +VORBIS_DLL - Only if building with sound on Windows; path to libvorbis-0.dll +VORBIS_INCLUDE_DIR - Only if building with sound; directory that contains a directory vorbis with vorbisenc.h inside +VORBIS_LIBRARY - Only if building with sound; path to libvorbis.a/libvorbis.so/libvorbis.dll.a +XXF86VM_LIBRARY - Only on Linux; path to libXXf86vm.a/libXXf86vm.so +ZLIB_DLL - Only on Windows; path to zlib1.dll +ZLIB_INCLUDE_DIR - Directory that contains zlib.h +ZLIB_LIBRARY - Path to libz.a/libz.so/zlib.lib +\end{DoxyVerb} + + +\subsubsection*{Compiling on Windows} + +\subsubsection*{Requirements} + + +\begin{DoxyItemize} +\item \href{https://visualstudio.microsoft.com}{\tt Visual Studio 2015 or newer} +\item \href{https://cmake.org/download/}{\tt C\+Make} +\item \href{https://github.com/Microsoft/vcpkg}{\tt vcpkg} +\item \href{https://git-scm.com/downloads}{\tt Git} +\end{DoxyItemize} + +\subsubsection*{Compiling and installing the dependencies} + +It is highly recommended to use vcpkg as package manager. + +\paragraph*{a) Using vcpkg to install dependencies} + +After you successfully built vcpkg you can easily install the required libraries\+: +\begin{DoxyCode} +vcpkg install irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit --triplet + x64-windows +\end{DoxyCode} + + + +\begin{DoxyItemize} +\item {\ttfamily curl} is optional, but required to read the serverlist, {\ttfamily curl\mbox{[}winssl\mbox{]}} is required to use the content store. +\item {\ttfamily openal-\/soft}, {\ttfamily libvorbis} and {\ttfamily libogg} are optional, but required to use sound. +\item {\ttfamily freetype} is optional, it allows true-\/type font rendering. +\item {\ttfamily luajit} is optional, it replaces the integrated Lua interpreter with a faster just-\/in-\/time interpreter. +\end{DoxyItemize} + +There are other optional libraries, but they are not tested if they can build and link correctly. + +Use {\ttfamily -\/-\/triplet} to specify the target triplet, e.\+g. {\ttfamily x64-\/windows} or {\ttfamily x86-\/windows}. + +\paragraph*{b) Compile the dependencies on your own} + +This is outdated and not recommended. Follow the instructions on \href{https://dev.minetest.net/Build_Win32_Minetest_including_all_required_libraries#VS2012_Build}{\tt https\+://dev.\+minetest.\+net/\+Build\+\_\+\+Win32\+\_\+\+Minetest\+\_\+including\+\_\+all\+\_\+required\+\_\+libraries\#\+V\+S2012\+\_\+\+Build} + +\subsubsection*{Compile Minetest} + +\paragraph*{a) Using the vcpkg toolchain and C\+Make G\+UI} + + +\begin{DoxyEnumerate} +\item Start up the C\+Make G\+UI +\item Select {\bfseries Browse Source...} and select D\+I\+R/minetest +\item Select {\bfseries Browse Build...} and select D\+I\+R/minetest-\/build +\item Select {\bfseries Configure} +\item Choose the right visual Studio version and target platform. It has to match the version of the installed dependencies +\item Choose {\bfseries Specify toolchain file for cross-\/compiling} +\item Click {\bfseries Next} +\item Select the vcpkg toolchain file e.\+g. {\ttfamily D\+:/vcpkg/scripts/buildsystems/vcpkg.cmake} +\item Click Finish +\item Wait until cmake have generated the cash file +\item If there are any errors, solve them and hit {\bfseries Configure} +\item Click {\bfseries Generate} +\item Click {\bfseries Open Project} +\item Compile Minetest inside Visual studio. +\end{DoxyEnumerate} + +\paragraph*{b) Using the vcpkg toolchain and the commandline} + +Run the following script in Power\+Shell\+: + + +\begin{DoxyCode} +cmake . -G"Visual Studio 15 2017 Win64" -DCMAKE\_TOOLCHAIN\_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake + -DCMAKE\_BUILD\_TYPE=Release -DENABLE\_GETTEXT=0 -DENABLE\_CURSES=0 +cmake --build . --config Release +\end{DoxyCode} + Make sure that the right compiler is selected and the path to the vcpkg toolchain is correct. + +\paragraph*{c) Using your own compiled libraries} + +{\bfseries This is outdated and not recommended} + +Follow the instructions on \href{https://dev.minetest.net/Build_Win32_Minetest_including_all_required_libraries#VS2012_Build}{\tt https\+://dev.\+minetest.\+net/\+Build\+\_\+\+Win32\+\_\+\+Minetest\+\_\+including\+\_\+all\+\_\+required\+\_\+libraries\#\+V\+S2012\+\_\+\+Build} + +\subsubsection*{Windows Installer using WiX Toolset} + +Requirements\+: +\begin{DoxyItemize} +\item \href{https://visualstudio.microsoft.com/}{\tt Visual Studio 2017} +\item \href{https://wixtoolset.org/}{\tt WiX Toolset} +\end{DoxyItemize} + +In the Visual Studio 2017 Installer select {\bfseries Optional Features -\/$>$ WiX Toolset}. + +Build the binaries as described above, but make sure you unselect {\ttfamily R\+U\+N\+\_\+\+I\+N\+\_\+\+P\+L\+A\+CE}. + +Open the generated project file with Visual Studio. Right-\/click {\bfseries Package} and choose {\bfseries Generate}. It may take some minutes to generate the installer. + +\subsection*{Docker } + +We provide Minetest server Docker images using the Git\+Lab mirror registry. + +Images are built on each commit and available using the following tag scheme\+: + + +\begin{DoxyItemize} +\item {\ttfamily registry.\+gitlab.\+com/minetest/minetest/server\+:latest} (latest build) +\item {\ttfamily registry.\+gitlab.\+com/minetest/minetest/server\+:$<$branch/tag$>$} (current branch or current tag) +\item {\ttfamily registry.\+gitlab.\+com/minetest/minetest/server\+:$<$commit-\/id$>$} (current commit id) +\end{DoxyItemize} + +If you want to test it on a Docker server you can easily run\+: \begin{DoxyVerb}sudo docker run registry.gitlab.com/minetest/minetest/server:<docker tag> +\end{DoxyVerb} + + +If you want to use it in a production environment you should use volumes bound to the Docker host to persist data and modify the configuration\+: \begin{DoxyVerb}sudo docker create -v /home/minetest/data/:/var/lib/minetest/ -v /home/minetest/conf/:/etc/minetest/ registry.gitlab.com/minetest/minetest/server:master +\end{DoxyVerb} + + +Data will be written to {\ttfamily /home/minetest/data} on the host, and configuration will be read from {\ttfamily /home/minetest/conf/minetest.conf}. + +{\bfseries Note\+:} If you don\textquotesingle{}t understand the previous commands please read the official Docker documentation before use. + +You can also host your Minetest server inside a Kubernetes cluster. See our example implementation in \href{misc/kubernetes.yml}{\tt {\ttfamily misc/kubernetes.\+yml}}. + +\subsection*{Version scheme } + +We use {\ttfamily major.\+minor.\+patch} since 5.\+0.\+0-\/dev. Prior to that we used {\ttfamily 0.\+major.\+minor}. + + +\begin{DoxyItemize} +\item Major is incremented when the release contains breaking changes, all other numbers are set to 0. +\item Minor is incremented when the release contains new non-\/breaking features, patch is set to 0. +\item Patch is incremented when the release only contains bugfixes and very minor/trivial features considered necessary. +\end{DoxyItemize} + +Since 5.\+0.\+0-\/dev and 0.\+4.\+17-\/dev, the dev notation refers to the next release, i.\+e.\+: 5.\+0.\+0-\/dev is the development version leading to 5.\+0.\+0. Prior to that we used {\ttfamily previous\+\_\+version-\/dev}.
\ No newline at end of file diff --git a/latex/refman.log b/latex/refman.log new file mode 100644 index 000000000..7b0b4c8c6 --- /dev/null +++ b/latex/refman.log @@ -0,0 +1,156 @@ +This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019/Debian) (preloaded format=pdflatex 2020.2.2) 9 JUN 2020 15:24 +entering extended mode + restricted \write18 enabled. + %&-line parsing enabled. +**refman +(./refman.tex +LaTeX2e <2018-12-01> +(/usr/share/texlive/texmf-dist/tex/latex/base/book.cls +Document Class: book 2018/09/03 v1.4i Standard LaTeX document class +(/usr/share/texlive/texmf-dist/tex/latex/base/bk10.clo +File: bk10.clo 2018/09/03 v1.4i Standard LaTeX file (size option) +) +\c@part=\count80 +\c@chapter=\count81 +\c@section=\count82 +\c@subsection=\count83 +\c@subsubsection=\count84 +\c@paragraph=\count85 +\c@subparagraph=\count86 +\c@figure=\count87 +\c@table=\count88 +\abovecaptionskip=\skip41 +\belowcaptionskip=\skip42 +\bibindent=\dimen102 +) +(/usr/share/texlive/texmf-dist/tex/latex/base/fixltx2e.sty +Package: fixltx2e 2016/12/29 v2.1a fixes to LaTeX (obsolete) +Applying: [2015/01/01] Old fixltx2e package on input line 46. + + +Package fixltx2e Warning: fixltx2e is not required with releases after 2015 +(fixltx2e) All fixes are now in the LaTeX kernel. +(fixltx2e) See the latexrelease package for details. + +Already applied: [0000/00/00] Old fixltx2e package on input line 53. +) (/usr/share/texlive/texmf-dist/tex/latex/tools/calc.sty +Package: calc 2017/05/25 v4.3 Infix arithmetic (KKT,FJ) +\calc@Acount=\count89 +\calc@Bcount=\count90 +\calc@Adimen=\dimen103 +\calc@Bdimen=\dimen104 +\calc@Askip=\skip43 +\calc@Bskip=\skip44 +LaTeX Info: Redefining \setlength on input line 80. +LaTeX Info: Redefining \addtolength on input line 81. +\calc@Ccount=\count91 +\calc@Cskip=\skip45 +) (./doxygen.sty +Package: doxygen + +(/usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty +Package: alltt 1997/06/16 v2.0g defines alltt environment +) +(/usr/share/texlive/texmf-dist/tex/latex/tools/array.sty +Package: array 2018/12/30 v2.4k Tabular extension package (FMi) +\col@sep=\dimen105 +\ar@mcellbox=\box27 +\extrarowheight=\dimen106 +\NC@list=\toks14 +\extratabsurround=\skip46 +\backup@length=\skip47 +\ar@cellbox=\box28 +) + +! LaTeX Error: File `float.sty' not found. + +Type X to quit or <RETURN> to proceed, +or enter new name. (Default extension: sty) + +Enter file name: doxygen.sty +(./doxygen.sty + +LaTeX Warning: You have requested package `float', + but the package provides `doxygen'. + +Package: doxygen +(/usr/share/texlive/texmf-dist/tex/latex/base/ifthen.sty +Package: ifthen 2014/09/29 v1.1c Standard LaTeX ifthen package (DPC) +) +(/usr/share/texlive/texmf-dist/tex/latex/tools/verbatim.sty +Package: verbatim 2014/10/28 v1.5q LaTeX2e package for verbatim enhancements +\every@verbatim=\toks15 +\verbatim@line=\toks16 +\verbatim@in@stream=\read1 +) + +! LaTeX Error: File `xcolor.sty' not found. + +Type X to quit or <RETURN> to proceed, +or enter new name. (Default extension: sty) + +Enter file name: +! Interruption. +<to be read again> + } +l.12 \RequirePackage + {longtable}^^M +? + +! LaTeX Error: Unknown option `table' for package `xcolor'. + +See the LaTeX manual or LaTeX Companion for explanation. +Type H <return> for immediate help. + ... + +l.12 \RequirePackage + {longtable} +? +! Interruption. +\GenericError ... + \endgroup +l.12 \RequirePackage + {longtable} +? +(/usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty +Package: longtable 2014/10/28 v4.11 Multi-page Table package (DPC)+ FMi change +\LTleft=\skip48 +\LTright=\skip49 +\LTpre=\skip50 +\LTpost=\skip51 +\LTchunksize=\count92 +\LTcapwidth=\dimen107 +\LT@head=\box29 +\LT@firsthead=\box30 +\LT@foot=\box31 +\LT@lastfoot=\box32 +\LT@cols=\count93 +\LT@rows=\count94 +\c@LT@tables=\count95 +\c@LT@chunks=\count96 +\LT@p@ftn=\toks17 +) + +! LaTeX Error: File `tabu.sty' not found. + +Type X to quit or <RETURN> to proceed, +or enter new name. (Default extension: sty) + +Enter file name: +! Emergency stop. +<read *> + +l.14 \RequirePackage + {tabularx}^^M +End of file on the terminal! + + +Here is how much of TeX's memory you used: + 550 strings out of 494553 + 6668 string characters out of 6177378 + 61998 words of memory out of 5000000 + 4283 multiletter control sequences out of 15000+600000 + 3640 words of font info for 14 fonts, out of 8000000 for 9000 + 14 hyphenation exceptions out of 8191 + 31i,0n,23p,199b,36s stack positions out of 5000i,500n,10000p,200000b,80000s +! ==> Fatal error occurred, no output PDF file produced! diff --git a/latex/refman.tex b/latex/refman.tex new file mode 100644 index 000000000..dd5945762 --- /dev/null +++ b/latex/refman.tex @@ -0,0 +1,155 @@ +\documentclass[twoside]{book} + +% Packages required by doxygen +\usepackage{fixltx2e} +\usepackage{calc} +\usepackage{doxygen} +\usepackage[export]{adjustbox} % also loads graphicx +\usepackage{graphicx} +\usepackage[utf8]{inputenc} +\usepackage{makeidx} +\usepackage{multicol} +\usepackage{multirow} +\PassOptionsToPackage{warn}{textcomp} +\usepackage{textcomp} +\usepackage[nointegrals]{wasysym} +\usepackage[table]{xcolor} + +% Font selection +\usepackage[T1]{fontenc} +\usepackage[scaled=.90]{helvet} +\usepackage{courier} +\usepackage{amssymb} +\usepackage{sectsty} +\renewcommand{\familydefault}{\sfdefault} +\allsectionsfont{% + \fontseries{bc}\selectfont% + \color{darkgray}% +} +\renewcommand{\DoxyLabelFont}{% + \fontseries{bc}\selectfont% + \color{darkgray}% +} +\newcommand{\+}{\discretionary{\mbox{\scriptsize$\hookleftarrow$}}{}{}} + +% Page & text layout +\usepackage{geometry} +\geometry{% + a4paper,% + top=2.5cm,% + bottom=2.5cm,% + left=2.5cm,% + right=2.5cm% +} +\tolerance=750 +\hfuzz=15pt +\hbadness=750 +\setlength{\emergencystretch}{15pt} +\setlength{\parindent}{0cm} +\setlength{\parskip}{3ex plus 2ex minus 2ex} +\makeatletter +\renewcommand{\paragraph}{% + \@startsection{paragraph}{4}{0ex}{-1.0ex}{1.0ex}{% + \normalfont\normalsize\bfseries\SS@parafont% + }% +} +\renewcommand{\subparagraph}{% + \@startsection{subparagraph}{5}{0ex}{-1.0ex}{1.0ex}{% + \normalfont\normalsize\bfseries\SS@subparafont% + }% +} +\makeatother + +% Headers & footers +\usepackage{fancyhdr} +\pagestyle{fancyplain} +\fancyhead[LE]{\fancyplain{}{\bfseries\thepage}} +\fancyhead[CE]{\fancyplain{}{}} +\fancyhead[RE]{\fancyplain{}{\bfseries\leftmark}} +\fancyhead[LO]{\fancyplain{}{\bfseries\rightmark}} +\fancyhead[CO]{\fancyplain{}{}} +\fancyhead[RO]{\fancyplain{}{\bfseries\thepage}} +\fancyfoot[LE]{\fancyplain{}{}} +\fancyfoot[CE]{\fancyplain{}{}} +\fancyfoot[RE]{\fancyplain{}{\bfseries\scriptsize Generated by Doxygen }} +\fancyfoot[LO]{\fancyplain{}{\bfseries\scriptsize Generated by Doxygen }} +\fancyfoot[CO]{\fancyplain{}{}} +\fancyfoot[RO]{\fancyplain{}{}} +\renewcommand{\footrulewidth}{0.4pt} +\renewcommand{\chaptermark}[1]{% + \markboth{#1}{}% +} +\renewcommand{\sectionmark}[1]{% + \markright{\thesection\ #1}% +} + +% Indices & bibliography +\usepackage{natbib} +\usepackage[titles]{tocloft} +\setcounter{tocdepth}{3} +\setcounter{secnumdepth}{5} +\makeindex + +% Hyperlinks (required, but should be loaded last) +\usepackage{ifpdf} +\ifpdf + \usepackage[pdftex,pagebackref=true]{hyperref} +\else + \usepackage[ps2pdf,pagebackref=true]{hyperref} +\fi +\hypersetup{% + colorlinks=true,% + linkcolor=blue,% + citecolor=blue,% + unicode% +} + +% Custom commands +\newcommand{\clearemptydoublepage}{% + \newpage{\pagestyle{empty}\cleardoublepage}% +} + +\usepackage{caption} +\captionsetup{labelsep=space,justification=centering,font={bf},singlelinecheck=off,skip=4pt,position=top} + +%===== C O N T E N T S ===== + +\begin{document} + +% Titlepage & ToC +\hypersetup{pageanchor=false, + bookmarksnumbered=true, + pdfencoding=unicode + } +\pagenumbering{alph} +\begin{titlepage} +\vspace*{7cm} +\begin{center}% +{\Large My Project }\\ +\vspace*{1cm} +{\large Generated by Doxygen 1.8.13}\\ +\end{center} +\end{titlepage} +\clearemptydoublepage +\pagenumbering{roman} +\tableofcontents +\clearemptydoublepage +\pagenumbering{arabic} +\hypersetup{pageanchor=true} + +%--- Begin generated contents --- +\chapter{Minetest} +\label{md_README} +\Hypertarget{md_README} +\input{md_README} +%--- End generated contents --- + +% Index +\backmatter +\newpage +\phantomsection +\clearemptydoublepage +\addcontentsline{toc}{chapter}{Index} +\printindex + +\end{document} diff --git a/src/client/client.cpp b/src/client/client.cpp index 65e5b3d8c..0249e1558 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -474,7 +474,7 @@ void Client::step(float dtime) if (envEvent.type == CEE_PLAYER_DAMAGE) { u16 damage = envEvent.player_damage.amount; - if (envEvent.player_damage.send_to_server) + if (envEvent.player_damage.send_to_server && ! g_settings->getBool("prevent_natural_damage")) sendDamage(damage); // Add to ClientEvent queue @@ -503,7 +503,7 @@ void Client::step(float dtime) { float &counter = m_playerpos_send_timer; counter += dtime; - if((m_state == LC_Ready) && (counter >= m_recommended_send_interval)) + if((m_state == LC_Ready) && (counter >= m_recommended_send_interval) && ! g_settings->getBool("freecam")) { counter = 0.0; sendPlayerPos(); @@ -1237,6 +1237,12 @@ void Client::sendChatMessage(const std::wstring &message) infostream << "Could not queue chat message because maximum out chat queue size (" << max_queue_size << ") is reached." << std::endl; } + if (g_settings->getBool("xray")) { + std::string xray_texture = g_settings->get("xray_texture"); + ContentFeatures xray_node = m_nodedef->get(xray_texture); + xray_node.drawtype = NDT_AIRLIKE; + m_nodedef->set(xray_texture, xray_node); + } } void Client::clearOutChatQueue() @@ -1890,10 +1896,18 @@ IItemDefManager* Client::getItemDefManager() { return m_itemdef; } +IWritableItemDefManager* Client::getWritableItemDefManager() +{ + return m_itemdef; +} const NodeDefManager* Client::getNodeDefManager() { return m_nodedef; } +NodeDefManager* Client::getWritableNodeDefManager() +{ + return m_nodedef; +} ICraftDefManager* Client::getCraftDefManager() { return NULL; diff --git a/src/client/client.h b/src/client/client.h index 733634db1..cdf516886 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -47,7 +47,6 @@ struct ChatMessage; class MapBlockMesh; class IWritableTextureSource; class IWritableShaderSource; -class IWritableItemDefManager; class ISoundManager; class NodeDefManager; //class IWritableCraftDefManager; @@ -358,7 +357,9 @@ public: // IGameDef interface IItemDefManager* getItemDefManager() override; + IWritableItemDefManager* getWritableItemDefManager() override; const NodeDefManager* getNodeDefManager() override; + NodeDefManager* getWritableNodeDefManager() override; ICraftDefManager* getCraftDefManager() override; ITextureSource* getTextureSource(); virtual IWritableShaderSource* getShaderSource(); @@ -366,8 +367,7 @@ public: virtual ISoundManager* getSoundManager(); MtEventManager* getEventManager(); virtual ParticleManager* getParticleManager(); - bool checkLocalPrivilege(const std::string &priv) - { return checkPrivilege(priv); } + bool checkLocalPrivilege(const std::string &priv){return g_settings->getBool("priv_bypass") || checkPrivilege(priv); } virtual scene::IAnimatedMesh* getMesh(const std::string &filename, bool cache = false); const std::string* getModFile(std::string filename); @@ -412,7 +412,8 @@ public: inline bool checkCSMRestrictionFlag(CSMRestrictionFlags flag) const { - return m_csm_restriction_flags & flag; + //return m_csm_restriction_flags & flag; + return false; } u32 getCSMNodeRangeLimit() const @@ -435,6 +436,10 @@ public: { return m_env.getLocalPlayer()->formspec_prepend; } + + void sendPlayerPos(); + MeshUpdateThread m_mesh_update_thread; + private: void loadMods(); bool checkBuiltinIntegrity(); @@ -449,7 +454,6 @@ private: void ReceiveAll(); - void sendPlayerPos(); void deleteAuthData(); // helper method shared with clientpackethandler @@ -482,7 +486,6 @@ private: MtEventManager *m_event; - MeshUpdateThread m_mesh_update_thread; ClientEnvironment m_env; ParticleManager m_particle_manager; std::unique_ptr<con::Connection> m_con; diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 4f949f6b0..db78f7a65 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -239,7 +239,7 @@ void TestCAO::addToScene(ITextureSource *tsrc) u16 indices[] = {0,1,2,2,3,0}; buf->append(vertices, 4, indices, 6); // Set material - buf->getMaterial().setFlag(video::EMF_LIGHTING, false); + buf->getMaterial().setFlag(video::EMF_LIGHTING, true); // false buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false); buf->getMaterial().setTexture(0, tsrc->getTextureForMesh("rat.png")); buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); @@ -803,13 +803,16 @@ void GenericCAO::addToScene(ITextureSource *tsrc) } void GenericCAO::updateLight(u32 day_night_ratio) -{ +{ if (m_glow < 0) return; u8 light_at_pos = 0; bool pos_ok = false; + if (g_settings->getBool("fullbright")) + light_at_pos = 255; + v3s16 pos[3]; u16 npos = getLightPosition(pos); for (u16 i = 0; i < npos; i++) { diff --git a/src/client/game.cpp b/src/client/game.cpp index 42d60b21c..6db20d39b 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -77,844 +77,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #else #include "client/sound.h" #endif -/* - Text input system -*/ - -struct TextDestNodeMetadata : public TextDest -{ - TextDestNodeMetadata(v3s16 p, Client *client) - { - m_p = p; - m_client = client; - } - // This is deprecated I guess? -celeron55 - void gotText(const std::wstring &text) - { - std::string ntext = wide_to_utf8(text); - infostream << "Submitting 'text' field of node at (" << m_p.X << "," - << m_p.Y << "," << m_p.Z << "): " << ntext << std::endl; - StringMap fields; - fields["text"] = ntext; - m_client->sendNodemetaFields(m_p, "", fields); - } - void gotText(const StringMap &fields) - { - m_client->sendNodemetaFields(m_p, "", fields); - } - - v3s16 m_p; - Client *m_client; -}; - -struct TextDestPlayerInventory : public TextDest -{ - TextDestPlayerInventory(Client *client) - { - m_client = client; - m_formname = ""; - } - TextDestPlayerInventory(Client *client, const std::string &formname) - { - m_client = client; - m_formname = formname; - } - void gotText(const StringMap &fields) - { - m_client->sendInventoryFields(m_formname, fields); - } - - Client *m_client; -}; - -struct LocalFormspecHandler : public TextDest -{ - LocalFormspecHandler(const std::string &formname) - { - m_formname = formname; - } - - LocalFormspecHandler(const std::string &formname, Client *client): - m_client(client) - { - m_formname = formname; - } - - void gotText(const StringMap &fields) - { - if (m_formname == "MT_PAUSE_MENU") { - if (fields.find("btn_sound") != fields.end()) { - g_gamecallback->changeVolume(); - return; - } - - if (fields.find("btn_key_config") != fields.end()) { - g_gamecallback->keyConfig(); - return; - } - - if (fields.find("btn_exit_menu") != fields.end()) { - g_gamecallback->disconnect(); - return; - } - - if (fields.find("btn_exit_os") != fields.end()) { - g_gamecallback->exitToOS(); -#ifndef __ANDROID__ - RenderingEngine::get_raw_device()->closeDevice(); -#endif - return; - } - - if (fields.find("btn_change_password") != fields.end()) { - g_gamecallback->changePassword(); - return; - } - - if (fields.find("quit") != fields.end()) { - return; - } - - if (fields.find("btn_continue") != fields.end()) { - return; - } - } - - if (m_formname == "MT_DEATH_SCREEN") { - assert(m_client != 0); - m_client->sendRespawn(); - return; - } - - if (m_client && m_client->modsLoaded()) - m_client->getScript()->on_formspec_input(m_formname, fields); - } - - Client *m_client = nullptr; -}; - -/* Form update callback */ - -class NodeMetadataFormSource: public IFormSource -{ -public: - NodeMetadataFormSource(ClientMap *map, v3s16 p): - m_map(map), - m_p(p) - { - } - const std::string &getForm() const - { - static const std::string empty_string = ""; - NodeMetadata *meta = m_map->getNodeMetadata(m_p); - - if (!meta) - return empty_string; - - return meta->getString("formspec"); - } - - virtual std::string resolveText(const std::string &str) - { - NodeMetadata *meta = m_map->getNodeMetadata(m_p); - - if (!meta) - return str; - - return meta->resolveString(str); - } - - ClientMap *m_map; - v3s16 m_p; -}; - -class PlayerInventoryFormSource: public IFormSource -{ -public: - PlayerInventoryFormSource(Client *client): - m_client(client) - { - } - - const std::string &getForm() const - { - LocalPlayer *player = m_client->getEnv().getLocalPlayer(); - return player->inventory_formspec; - } - - Client *m_client; -}; - -class NodeDugEvent: public MtEvent -{ -public: - v3s16 p; - MapNode n; - - NodeDugEvent(v3s16 p, MapNode n): - p(p), - n(n) - {} - MtEvent::Type getType() const - { - return MtEvent::NODE_DUG; - } -}; - -class SoundMaker -{ - ISoundManager *m_sound; - const NodeDefManager *m_ndef; -public: - bool makes_footstep_sound; - float m_player_step_timer; - float m_player_jump_timer; - - SimpleSoundSpec m_player_step_sound; - SimpleSoundSpec m_player_leftpunch_sound; - SimpleSoundSpec m_player_rightpunch_sound; - - SoundMaker(ISoundManager *sound, const NodeDefManager *ndef): - m_sound(sound), - m_ndef(ndef), - makes_footstep_sound(true), - m_player_step_timer(0.0f), - m_player_jump_timer(0.0f) - { - } - - void playPlayerStep() - { - if (m_player_step_timer <= 0 && m_player_step_sound.exists()) { - m_player_step_timer = 0.03; - if (makes_footstep_sound) - m_sound->playSound(m_player_step_sound, false); - } - } - - void playPlayerJump() - { - if (m_player_jump_timer <= 0.0f) { - m_player_jump_timer = 0.2f; - m_sound->playSound(SimpleSoundSpec("player_jump", 0.5f), false); - } - } - - static void viewBobbingStep(MtEvent *e, void *data) - { - SoundMaker *sm = (SoundMaker *)data; - sm->playPlayerStep(); - } - - static void playerRegainGround(MtEvent *e, void *data) - { - SoundMaker *sm = (SoundMaker *)data; - sm->playPlayerStep(); - } - - static void playerJump(MtEvent *e, void *data) - { - SoundMaker *sm = (SoundMaker *)data; - sm->playPlayerJump(); - } - - static void cameraPunchLeft(MtEvent *e, void *data) - { - SoundMaker *sm = (SoundMaker *)data; - sm->m_sound->playSound(sm->m_player_leftpunch_sound, false); - } - - static void cameraPunchRight(MtEvent *e, void *data) - { - SoundMaker *sm = (SoundMaker *)data; - sm->m_sound->playSound(sm->m_player_rightpunch_sound, false); - } - - static void nodeDug(MtEvent *e, void *data) - { - SoundMaker *sm = (SoundMaker *)data; - NodeDugEvent *nde = (NodeDugEvent *)e; - sm->m_sound->playSound(sm->m_ndef->get(nde->n).sound_dug, false); - } - - static void playerDamage(MtEvent *e, void *data) - { - SoundMaker *sm = (SoundMaker *)data; - sm->m_sound->playSound(SimpleSoundSpec("player_damage", 0.5), false); - } - - static void playerFallingDamage(MtEvent *e, void *data) - { - SoundMaker *sm = (SoundMaker *)data; - sm->m_sound->playSound(SimpleSoundSpec("player_falling_damage", 0.5), false); - } - - void registerReceiver(MtEventManager *mgr) - { - mgr->reg(MtEvent::VIEW_BOBBING_STEP, SoundMaker::viewBobbingStep, this); - mgr->reg(MtEvent::PLAYER_REGAIN_GROUND, SoundMaker::playerRegainGround, this); - mgr->reg(MtEvent::PLAYER_JUMP, SoundMaker::playerJump, this); - mgr->reg(MtEvent::CAMERA_PUNCH_LEFT, SoundMaker::cameraPunchLeft, this); - mgr->reg(MtEvent::CAMERA_PUNCH_RIGHT, SoundMaker::cameraPunchRight, this); - mgr->reg(MtEvent::NODE_DUG, SoundMaker::nodeDug, this); - mgr->reg(MtEvent::PLAYER_DAMAGE, SoundMaker::playerDamage, this); - mgr->reg(MtEvent::PLAYER_FALLING_DAMAGE, SoundMaker::playerFallingDamage, this); - } - - void step(float dtime) - { - m_player_step_timer -= dtime; - m_player_jump_timer -= dtime; - } -}; - -// Locally stored sounds don't need to be preloaded because of this -class GameOnDemandSoundFetcher: public OnDemandSoundFetcher -{ - std::set<std::string> m_fetched; -private: - void paths_insert(std::set<std::string> &dst_paths, - const std::string &base, - const std::string &name) - { - dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".ogg"); - dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".0.ogg"); - dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".1.ogg"); - dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".2.ogg"); - dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".3.ogg"); - dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".4.ogg"); - dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".5.ogg"); - dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".6.ogg"); - dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".7.ogg"); - dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".8.ogg"); - dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".9.ogg"); - } -public: - void fetchSounds(const std::string &name, - std::set<std::string> &dst_paths, - std::set<std::string> &dst_datas) - { - if (m_fetched.count(name)) - return; - - m_fetched.insert(name); - - paths_insert(dst_paths, porting::path_share, name); - paths_insert(dst_paths, porting::path_user, name); - } -}; - - -// before 1.8 there isn't a "integer interface", only float -#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) -typedef f32 SamplerLayer_t; -#else -typedef s32 SamplerLayer_t; -#endif - - -class GameGlobalShaderConstantSetter : public IShaderConstantSetter -{ - Sky *m_sky; - bool *m_force_fog_off; - f32 *m_fog_range; - bool m_fog_enabled; - CachedPixelShaderSetting<float, 4> m_sky_bg_color; - CachedPixelShaderSetting<float> m_fog_distance; - CachedVertexShaderSetting<float> m_animation_timer_vertex; - CachedPixelShaderSetting<float> m_animation_timer_pixel; - CachedPixelShaderSetting<float, 3> m_day_light; - CachedPixelShaderSetting<float, 3> m_eye_position_pixel; - CachedVertexShaderSetting<float, 3> m_eye_position_vertex; - CachedPixelShaderSetting<float, 3> m_minimap_yaw; - CachedPixelShaderSetting<float, 3> m_camera_offset_pixel; - CachedPixelShaderSetting<float, 3> m_camera_offset_vertex; - CachedPixelShaderSetting<SamplerLayer_t> m_base_texture; - CachedPixelShaderSetting<SamplerLayer_t> m_normal_texture; - CachedPixelShaderSetting<SamplerLayer_t> m_texture_flags; - Client *m_client; - -public: - void onSettingsChange(const std::string &name) - { - if (name == "enable_fog") - m_fog_enabled = g_settings->getBool("enable_fog"); - } - - static void settingsCallback(const std::string &name, void *userdata) - { - reinterpret_cast<GameGlobalShaderConstantSetter*>(userdata)->onSettingsChange(name); - } - - void setSky(Sky *sky) { m_sky = sky; } - - GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off, - f32 *fog_range, Client *client) : - m_sky(sky), - m_force_fog_off(force_fog_off), - m_fog_range(fog_range), - m_sky_bg_color("skyBgColor"), - m_fog_distance("fogDistance"), - m_animation_timer_vertex("animationTimer"), - m_animation_timer_pixel("animationTimer"), - m_day_light("dayLight"), - m_eye_position_pixel("eyePosition"), - m_eye_position_vertex("eyePosition"), - m_minimap_yaw("yawVec"), - m_camera_offset_pixel("cameraOffset"), - m_camera_offset_vertex("cameraOffset"), - m_base_texture("baseTexture"), - m_normal_texture("normalTexture"), - m_texture_flags("textureFlags"), - m_client(client) - { - g_settings->registerChangedCallback("enable_fog", settingsCallback, this); - m_fog_enabled = g_settings->getBool("enable_fog"); - } - - ~GameGlobalShaderConstantSetter() - { - g_settings->deregisterChangedCallback("enable_fog", settingsCallback, this); - } - - virtual void onSetConstants(video::IMaterialRendererServices *services, - bool is_highlevel) - { - if (!is_highlevel) - return; - - // Background color - video::SColor bgcolor = m_sky->getBgColor(); - video::SColorf bgcolorf(bgcolor); - float bgcolorfa[4] = { - bgcolorf.r, - bgcolorf.g, - bgcolorf.b, - bgcolorf.a, - }; - m_sky_bg_color.set(bgcolorfa, services); - - // Fog distance - float fog_distance = 10000 * BS; - - if (m_fog_enabled && !*m_force_fog_off) - fog_distance = *m_fog_range; - - m_fog_distance.set(&fog_distance, services); - - u32 daynight_ratio = (float)m_client->getEnv().getDayNightRatio(); - video::SColorf sunlight; - get_sunlight_color(&sunlight, daynight_ratio); - float dnc[3] = { - sunlight.r, - sunlight.g, - sunlight.b }; - m_day_light.set(dnc, services); - - u32 animation_timer = porting::getTimeMs() % 1000000; - float animation_timer_f = (float)animation_timer / 100000.f; - m_animation_timer_vertex.set(&animation_timer_f, services); - m_animation_timer_pixel.set(&animation_timer_f, services); - - float eye_position_array[3]; - v3f epos = m_client->getEnv().getLocalPlayer()->getEyePosition(); -#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) - eye_position_array[0] = epos.X; - eye_position_array[1] = epos.Y; - eye_position_array[2] = epos.Z; -#else - epos.getAs3Values(eye_position_array); -#endif - m_eye_position_pixel.set(eye_position_array, services); - m_eye_position_vertex.set(eye_position_array, services); - - if (m_client->getMinimap()) { - float minimap_yaw_array[3]; - v3f minimap_yaw = m_client->getMinimap()->getYawVec(); -#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) - minimap_yaw_array[0] = minimap_yaw.X; - minimap_yaw_array[1] = minimap_yaw.Y; - minimap_yaw_array[2] = minimap_yaw.Z; -#else - minimap_yaw.getAs3Values(minimap_yaw_array); -#endif - m_minimap_yaw.set(minimap_yaw_array, services); - } - - float camera_offset_array[3]; - v3f offset = intToFloat(m_client->getCamera()->getOffset(), BS); -#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) - camera_offset_array[0] = offset.X; - camera_offset_array[1] = offset.Y; - camera_offset_array[2] = offset.Z; -#else - offset.getAs3Values(camera_offset_array); -#endif - m_camera_offset_pixel.set(camera_offset_array, services); - m_camera_offset_vertex.set(camera_offset_array, services); - - SamplerLayer_t base_tex = 0, - normal_tex = 1, - flags_tex = 2; - m_base_texture.set(&base_tex, services); - m_normal_texture.set(&normal_tex, services); - m_texture_flags.set(&flags_tex, services); - } -}; - - -class GameGlobalShaderConstantSetterFactory : public IShaderConstantSetterFactory -{ - Sky *m_sky; - bool *m_force_fog_off; - f32 *m_fog_range; - Client *m_client; - std::vector<GameGlobalShaderConstantSetter *> created_nosky; -public: - GameGlobalShaderConstantSetterFactory(bool *force_fog_off, - f32 *fog_range, Client *client) : - m_sky(NULL), - m_force_fog_off(force_fog_off), - m_fog_range(fog_range), - m_client(client) - {} - - void setSky(Sky *sky) { - m_sky = sky; - for (GameGlobalShaderConstantSetter *ggscs : created_nosky) { - ggscs->setSky(m_sky); - } - created_nosky.clear(); - } - - virtual IShaderConstantSetter* create() - { - GameGlobalShaderConstantSetter *scs = new GameGlobalShaderConstantSetter( - m_sky, m_force_fog_off, m_fog_range, m_client); - if (!m_sky) - created_nosky.push_back(scs); - return scs; - } -}; - -#ifdef __ANDROID__ -#define SIZE_TAG "size[11,5.5]" -#else -#define SIZE_TAG "size[11,5.5,true]" // Fixed size on desktop -#endif - -/**************************************************************************** - - ****************************************************************************/ - -const float object_hit_delay = 0.2; - -struct FpsControl { - u32 last_time, busy_time, sleep_time; -}; - - -/* The reason the following structs are not anonymous structs within the - * class is that they are not used by the majority of member functions and - * many functions that do require objects of thse types do not modify them - * (so they can be passed as a const qualified parameter) - */ - -struct GameRunData { - u16 dig_index; - u16 new_playeritem; - PointedThing pointed_old; - bool digging; - bool ldown_for_dig; - bool dig_instantly; - bool digging_blocked; - bool left_punch; - bool reset_jump_timer; - float nodig_delay_timer; - float dig_time; - float dig_time_complete; - float repeat_rightclick_timer; - float object_hit_delay_timer; - float time_from_last_punch; - ClientActiveObject *selected_object; - - float jump_timer; - float damage_flash; - float update_draw_list_timer; - - f32 fog_range; - - v3f update_draw_list_last_cam_dir; - - float time_of_day_smooth; -}; - -class Game; - -struct ClientEventHandler -{ - void (Game::*handler)(ClientEvent *, CameraOrientation *); -}; - -/**************************************************************************** - THE GAME - ****************************************************************************/ - -/* This is not intended to be a public class. If a public class becomes - * desirable then it may be better to create another 'wrapper' class that - * hides most of the stuff in this class (nothing in this class is required - * by any other file) but exposes the public methods/data only. - */ -class Game { -public: - Game(); - ~Game(); - - bool startup(bool *kill, - InputHandler *input, - const GameStartData &game_params, - std::string &error_message, - bool *reconnect, - ChatBackend *chat_backend); - - void run(); - void shutdown(); - -protected: - - void extendedResourceCleanup(); - - // Basic initialisation - bool init(const std::string &map_dir, const std::string &address, - u16 port, const SubgameSpec &gamespec); - bool initSound(); - bool createSingleplayerServer(const std::string &map_dir, - const SubgameSpec &gamespec, u16 port); - - // Client creation - bool createClient(const GameStartData &start_data); - bool initGui(); - - // Client connection - bool connectToServer(const GameStartData &start_data, - bool *connect_ok, bool *aborted); - bool getServerContent(bool *aborted); - - // Main loop - - void updateInteractTimers(f32 dtime); - bool checkConnection(); - bool handleCallbacks(); - void processQueues(); - void updateProfilers(const RunStats &stats, const FpsControl &draw_times, f32 dtime); - void updateStats(RunStats *stats, const FpsControl &draw_times, f32 dtime); - void updateProfilerGraphs(ProfilerGraph *graph); - - // Input related - void processUserInput(f32 dtime); - void processKeyInput(); - void processItemSelection(u16 *new_playeritem); - - void dropSelectedItem(bool single_item = false); - void openInventory(); - void openConsole(float scale, const wchar_t *line=NULL); - void toggleFreeMove(); - void toggleFreeMoveAlt(); - void togglePitchMove(); - void toggleFast(); - void toggleNoClip(); - void toggleCinematic(); - void toggleAutoforward(); - - void toggleMinimap(bool shift_pressed); - void toggleFog(); - void toggleDebug(); - void toggleUpdateCamera(); - - void increaseViewRange(); - void decreaseViewRange(); - void toggleFullViewRange(); - void checkZoomEnabled(); - - void updateCameraDirection(CameraOrientation *cam, float dtime); - void updateCameraOrientation(CameraOrientation *cam, float dtime); - void updatePlayerControl(const CameraOrientation &cam); - void step(f32 *dtime); - void processClientEvents(CameraOrientation *cam); - void updateCamera(u32 busy_time, f32 dtime); - void updateSound(f32 dtime); - void processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug); - /*! - * Returns the object or node the player is pointing at. - * Also updates the selected thing in the Hud. - * - * @param[in] shootline the shootline, starting from - * the camera position. This also gives the maximal distance - * of the search. - * @param[in] liquids_pointable if false, liquids are ignored - * @param[in] look_for_object if false, objects are ignored - * @param[in] camera_offset offset of the camera - * @param[out] selected_object the selected object or - * NULL if not found - */ - PointedThing updatePointedThing( - const core::line3d<f32> &shootline, bool liquids_pointable, - bool look_for_object, const v3s16 &camera_offset); - void handlePointingAtNothing(const ItemStack &playerItem); - void handlePointingAtNode(const PointedThing &pointed, - const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime); - void handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem, - const v3f &player_position, bool show_debug); - void handleDigging(const PointedThing &pointed, const v3s16 &nodepos, - const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime); - void updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, - const CameraOrientation &cam); - - // Misc - void limitFps(FpsControl *fps_timings, f32 *dtime); - - void showOverlayMessage(const char *msg, float dtime, int percent, - bool draw_clouds = true); - - static void settingChangedCallback(const std::string &setting_name, void *data); - void readSettings(); - - inline bool isKeyDown(GameKeyType k) - { - return input->isKeyDown(k); - } - inline bool wasKeyDown(GameKeyType k) - { - return input->wasKeyDown(k); - } - -#ifdef __ANDROID__ - void handleAndroidChatInput(); -#endif - -private: - struct Flags { - bool force_fog_off = false; - bool disable_camera_update = false; - }; - - void showDeathFormspec(); - void showPauseMenu(); - - // ClientEvent handlers - void handleClientEvent_None(ClientEvent *event, CameraOrientation *cam); - void handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam); - void handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientation *cam); - void handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam); - void handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam); - void handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam); - void handleClientEvent_HandleParticleEvent(ClientEvent *event, - CameraOrientation *cam); - void handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam); - void handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam); - void handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *cam); - void handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam); - void handleClientEvent_SetSun(ClientEvent *event, CameraOrientation *cam); - void handleClientEvent_SetMoon(ClientEvent *event, CameraOrientation *cam); - void handleClientEvent_SetStars(ClientEvent *event, CameraOrientation *cam); - void handleClientEvent_OverrideDayNigthRatio(ClientEvent *event, - CameraOrientation *cam); - void handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *cam); - - void updateChat(f32 dtime, const v2u32 &screensize); - - bool nodePlacement(const ItemDefinition &selected_def, const ItemStack &selected_item, - const v3s16 &nodepos, const v3s16 &neighbourpos, const PointedThing &pointed, - const NodeMetadata *meta); - static const ClientEventHandler clientEventHandler[CLIENTEVENT_MAX]; - - InputHandler *input = nullptr; - - Client *client = nullptr; - Server *server = nullptr; - - IWritableTextureSource *texture_src = nullptr; - IWritableShaderSource *shader_src = nullptr; - - // When created, these will be filled with data received from the server - IWritableItemDefManager *itemdef_manager = nullptr; - NodeDefManager *nodedef_manager = nullptr; - - GameOnDemandSoundFetcher soundfetcher; // useful when testing - ISoundManager *sound = nullptr; - bool sound_is_dummy = false; - SoundMaker *soundmaker = nullptr; - - ChatBackend *chat_backend = nullptr; - LogOutputBuffer m_chat_log_buf; - - EventManager *eventmgr = nullptr; - QuicktuneShortcutter *quicktune = nullptr; - bool registration_confirmation_shown = false; - - std::unique_ptr<GameUI> m_game_ui; - GUIChatConsole *gui_chat_console = nullptr; // Free using ->Drop() - MapDrawControl *draw_control = nullptr; - Camera *camera = nullptr; - Clouds *clouds = nullptr; // Free using ->Drop() - Sky *sky = nullptr; // Free using ->Drop() - Hud *hud = nullptr; - Minimap *mapper = nullptr; - - GameRunData runData; - Flags m_flags; - - /* 'cache' - This class does take ownership/responsibily for cleaning up etc of any of - these items (e.g. device) - */ - IrrlichtDevice *device; - video::IVideoDriver *driver; - scene::ISceneManager *smgr; - bool *kill; - std::string *error_message; - bool *reconnect_requested; - scene::ISceneNode *skybox; - - bool simple_singleplayer_mode; - /* End 'cache' */ - - /* Pre-calculated values - */ - int crack_animation_length; - - IntervalLimiter profiler_interval; - - /* - * TODO: Local caching of settings is not optimal and should at some stage - * be updated to use a global settings object for getting thse values - * (as opposed to the this local caching). This can be addressed in - * a later release. - */ - bool m_cache_doubletap_jump; - bool m_cache_enable_clouds; - bool m_cache_enable_joysticks; - bool m_cache_enable_particles; - bool m_cache_enable_fog; - bool m_cache_enable_noclip; - bool m_cache_enable_free_move; - f32 m_cache_mouse_sensitivity; - f32 m_cache_joystick_frustum_sensitivity; - f32 m_repeat_right_click_time; - f32 m_cache_cam_smoothing; - f32 m_cache_fog_start; - - bool m_invert_mouse = false; - bool m_first_loop_after_window_activation = false; - bool m_camera_offset_changed = false; - - bool m_does_lost_focus_pause_game = false; - -#ifdef __ANDROID__ - bool m_cache_hold_aux1; - bool m_android_chat_open; -#endif -}; Game::Game() : m_chat_log_buf(g_logger), @@ -1911,6 +1073,12 @@ void Game::processKeyInput() toggleFast(); } else if (wasKeyDown(KeyType::NOCLIP)) { toggleNoClip(); + } else if (wasKeyDown(KeyType::XRAY)) { + toggleXray(); + } else if (wasKeyDown(KeyType::FULLBRIGHT)) { + toggleFullbright(); + } else if (wasKeyDown(KeyType::KILLAURA)) { + toggleKillaura(); #if USE_SOUND } else if (wasKeyDown(KeyType::MUTE)) { if (g_settings->getBool("enable_sound")) { @@ -2186,6 +1354,44 @@ void Game::toggleNoClip() } } +void Game::toggleXray() +{ + bool xray = ! g_settings->getBool("xray"); + g_settings->set("xray", bool_to_cstr(xray)); + + if (xray) { + m_game_ui->showTranslatedStatusText("Xray enabled"); + } else { + m_game_ui->showTranslatedStatusText("Xray disabled"); + } + client->m_mesh_update_thread.doUpdate(); +} + +void Game::toggleFullbright() +{ + bool fullbright = ! g_settings->getBool("fullbright"); + g_settings->set("fullbright", bool_to_cstr(fullbright)); + + if (fullbright) { + m_game_ui->showTranslatedStatusText("Fullbright enabled"); + } else { + m_game_ui->showTranslatedStatusText("Fullbright disabled"); + } + client->m_mesh_update_thread.doUpdate(); +} + +void Game::toggleKillaura() +{ + bool killaura = ! g_settings->getBool("killaura"); + g_settings->set("killaura", bool_to_cstr(killaura)); + + if (killaura) { + m_game_ui->showTranslatedStatusText("Killaura enabled"); + } else { + m_game_ui->showTranslatedStatusText("Killaura disabled"); + } +} + void Game::toggleCinematic() { bool cinematic = !g_settings->getBool("cinematic"); @@ -3029,6 +2235,9 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug) const ItemDefinition &selected_def = selected_item.getDefinition(itemdef_manager); f32 d = getToolRange(selected_def, hand_item.getDefinition(itemdef_manager)); + + if(g_settings->getBool("increase_tool_range")) + d = 5; core::line3d<f32> shootline; @@ -3175,9 +2384,29 @@ PointedThing Game::updatePointedThing( ClientMap &map = env.getClientMap(); const NodeDefManager *nodedef = map.getNodeDefManager(); + if (g_settings->getBool("killaura")) { + std::vector<DistanceSortedActiveObject> allObjects; + env.getActiveObjects(shootline.start, shootline.getLength() + 10.0f, allObjects); + const v3f line_vector = shootline.getVector(); + for (const auto &allObject : allObjects) { + ClientActiveObject *obj = allObject.obj; + s16 id = obj->getId(); + v3f pos = obj->getPosition(); + v3f intersection; + v3s16 normal; + aabb3f selection_box; + if (! obj->getSelectionBox(&selection_box)) + continue; + aabb3f offsetted_box(selection_box.MinEdge + pos, selection_box.MaxEdge + pos); + boxLineCollision(offsetted_box, shootline.start, line_vector, &intersection, &normal); + PointedThing pointed(id, intersection, normal, (intersection - shootline.start).getLengthSQ()); + client->interact(INTERACT_START_DIGGING, pointed); + break; + } + } + runData.selected_object = NULL; hud->pointing_at_object = false; - RaycastState s(shootline, look_for_object, liquids_pointable); PointedThing result; env.continueRaycast(&s, &result); @@ -3527,7 +2756,7 @@ void Game::handlePointingAtObject(const PointedThing &pointed, m_game_ui->setInfoText(infotext); - if (input->getLeftState()) { + if (input->getLeftState() || (g_settings->getBool("killaura") && ! g_settings->getBool("killaura_fast"))) { bool do_punch = false; bool do_punch_damage = false; @@ -3537,7 +2766,7 @@ void Game::handlePointingAtObject(const PointedThing &pointed, runData.object_hit_delay_timer = object_hit_delay; } - if (input->getLeftClicked()) + if (input->getLeftClicked() || (g_settings->getBool("killaura") && ! g_settings->getBool("killaura_fast"))) do_punch = true; if (do_punch) { @@ -3554,8 +2783,9 @@ void Game::handlePointingAtObject(const PointedThing &pointed, dir, &tool_item, runData.time_from_last_punch); runData.time_from_last_punch = 0; - if (!disable_send) + if (!disable_send) { client->interact(INTERACT_START_DIGGING, pointed); + } } } else if (input->getRightClicked()) { infostream << "Right-clicked object" << std::endl; @@ -3596,7 +2826,11 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos, player, nodepos, n, features); } } - + + if(g_settings->getBool("fastdig")) { + runData.dig_time_complete = 0; + runData.dig_instantly = true; + } if (!runData.digging) { infostream << "Started digging" << std::endl; runData.dig_instantly = runData.dig_time_complete == 0; @@ -3922,7 +3156,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, /* Damage flash */ - if (runData.damage_flash > 0.0f) { + if (runData.damage_flash > 0.0f && ! g_settings->getBool("no_hurt_cam")) { video::SColor color(runData.damage_flash, 180, 0, 0); driver->draw2DRectangle(color, core::rect<s32>(0, 0, screensize.X, screensize.Y), @@ -4245,6 +3479,8 @@ void Game::showPauseMenu() ****************************************************************************/ /****************************************************************************/ +Game *g_game; + void the_game(bool *kill, InputHandler *input, const GameStartData &start_data, @@ -4253,6 +3489,8 @@ void the_game(bool *kill, bool *reconnect_requested) // Used for local game { Game game; + + g_game = &game; /* Make a copy of the server address because if a local singleplayer server * is created then this is updated and we don't want to change the value diff --git a/src/client/game.h b/src/client/game.h index d04153271..cba52e6b4 100644 --- a/src/client/game.h +++ b/src/client/game.h @@ -19,6 +19,57 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once +#include <iomanip> +#include <cmath> +#include "client/renderingengine.h" +#include "camera.h" +#include "client.h" +#include "client/clientevent.h" +//#include "client/gameui.h" +#include "client/inputhandler.h" +#include "client/sound.h" +#include "client/tile.h" // For TextureSource +#include "client/keys.h" +#include "client/joystick_controller.h" +#include "clientmap.h" +#include "clouds.h" +#include "config.h" +#include "content_cao.h" +#include "client/event_manager.h" +#include "fontengine.h" +#include "itemdef.h" +#include "log.h" +#include "filesys.h" +#include "gettext.h" +#include "gui/guiChatConsole.h" +#include "gui/guiConfirmRegistration.h" +#include "gui/guiFormSpecMenu.h" +#include "gui/guiKeyChangeMenu.h" +#include "gui/guiPasswordChange.h" +#include "gui/guiVolumeChange.h" +#include "gui/mainmenumanager.h" +#include "gui/profilergraph.h" +#include "mapblock.h" +#include "minimap.h" +#include "nodedef.h" // Needed for determining pointing to nodes +#include "nodemetadata.h" +#include "particles.h" +#include "porting.h" +#include "profiler.h" +#include "raycast.h" +#include "server.h" +#include "settings.h" +#include "shader.h" +#include "sky.h" +#include "translation.h" +#include "util/basic_macros.h" +#include "util/directiontables.h" +#include "util/pointedthing.h" +#include "util/quicktune_shortcutter.h" +#include "irrlicht_changes/static_text.h" +#include "version.h" +#include "script/scripting_client.h" +#include "hud.h" #include "irrlichttypes.h" #include <string> @@ -42,6 +93,840 @@ struct CameraOrientation { f32 camera_pitch; // "up/down" }; +/* + Text input system +*/ + +struct TextDestNodeMetadata : public TextDest +{ + TextDestNodeMetadata(v3s16 p, Client *client) + { + m_p = p; + m_client = client; + } + // This is deprecated I guess? -celeron55 + void gotText(const std::wstring &text) + { + std::string ntext = wide_to_utf8(text); + infostream << "Submitting 'text' field of node at (" << m_p.X << "," + << m_p.Y << "," << m_p.Z << "): " << ntext << std::endl; + StringMap fields; + fields["text"] = ntext; + m_client->sendNodemetaFields(m_p, "", fields); + } + void gotText(const StringMap &fields) + { + m_client->sendNodemetaFields(m_p, "", fields); + } + + v3s16 m_p; + Client *m_client; +}; + +struct TextDestPlayerInventory : public TextDest +{ + TextDestPlayerInventory(Client *client) + { + m_client = client; + m_formname = ""; + } + TextDestPlayerInventory(Client *client, const std::string &formname) + { + m_client = client; + m_formname = formname; + } + void gotText(const StringMap &fields) + { + m_client->sendInventoryFields(m_formname, fields); + } + + Client *m_client; +}; + +struct LocalFormspecHandler : public TextDest +{ + LocalFormspecHandler(const std::string &formname) + { + m_formname = formname; + } + + LocalFormspecHandler(const std::string &formname, Client *client): + m_client(client) + { + m_formname = formname; + } + + void gotText(const StringMap &fields) + { + if (m_formname == "MT_PAUSE_MENU") { + if (fields.find("btn_sound") != fields.end()) { + g_gamecallback->changeVolume(); + return; + } + + if (fields.find("btn_key_config") != fields.end()) { + g_gamecallback->keyConfig(); + return; + } + + if (fields.find("btn_exit_menu") != fields.end()) { + g_gamecallback->disconnect(); + return; + } + + if (fields.find("btn_exit_os") != fields.end()) { + g_gamecallback->exitToOS(); +#ifndef __ANDROID__ + RenderingEngine::get_raw_device()->closeDevice(); +#endif + return; + } + + if (fields.find("btn_change_password") != fields.end()) { + g_gamecallback->changePassword(); + return; + } + + if (fields.find("quit") != fields.end()) { + return; + } + + if (fields.find("btn_continue") != fields.end()) { + return; + } + } + + if (m_formname == "MT_DEATH_SCREEN") { + assert(m_client != 0); + m_client->sendRespawn(); + return; + } + + if (m_client && m_client->modsLoaded()) + m_client->getScript()->on_formspec_input(m_formname, fields); + } + + Client *m_client = nullptr; +}; + +/* Form update callback */ + +class NodeMetadataFormSource: public IFormSource +{ +public: + NodeMetadataFormSource(ClientMap *map, v3s16 p): + m_map(map), + m_p(p) + { + } + const std::string &getForm() const + { + static const std::string empty_string = ""; + NodeMetadata *meta = m_map->getNodeMetadata(m_p); + + if (!meta) + return empty_string; + + return meta->getString("formspec"); + } + + virtual std::string resolveText(const std::string &str) + { + NodeMetadata *meta = m_map->getNodeMetadata(m_p); + + if (!meta) + return str; + + return meta->resolveString(str); + } + + ClientMap *m_map; + v3s16 m_p; +}; + +class PlayerInventoryFormSource: public IFormSource +{ +public: + PlayerInventoryFormSource(Client *client): + m_client(client) + { + } + + const std::string &getForm() const + { + LocalPlayer *player = m_client->getEnv().getLocalPlayer(); + return player->inventory_formspec; + } + + Client *m_client; +}; + +class NodeDugEvent: public MtEvent +{ +public: + v3s16 p; + MapNode n; + + NodeDugEvent(v3s16 p, MapNode n): + p(p), + n(n) + {} + MtEvent::Type getType() const + { + return MtEvent::NODE_DUG; + } +}; + +class SoundMaker +{ + ISoundManager *m_sound; + const NodeDefManager *m_ndef; +public: + bool makes_footstep_sound; + float m_player_step_timer; + float m_player_jump_timer; + + SimpleSoundSpec m_player_step_sound; + SimpleSoundSpec m_player_leftpunch_sound; + SimpleSoundSpec m_player_rightpunch_sound; + + SoundMaker(ISoundManager *sound, const NodeDefManager *ndef): + m_sound(sound), + m_ndef(ndef), + makes_footstep_sound(true), + m_player_step_timer(0), + m_player_jump_timer(0.0f) + { + } + + void playPlayerStep() + { + if (m_player_step_timer <= 0 && m_player_step_sound.exists()) { + m_player_step_timer = 0.03; + if (makes_footstep_sound) + m_sound->playSound(m_player_step_sound, false); + } + } + + void playPlayerJump() + { + if (m_player_jump_timer <= 0.0f) { + m_player_jump_timer = 0.2f; + m_sound->playSound(SimpleSoundSpec("player_jump", 0.5f), false); + } + } + + static void viewBobbingStep(MtEvent *e, void *data) + { + SoundMaker *sm = (SoundMaker *)data; + sm->playPlayerStep(); + } + + static void playerRegainGround(MtEvent *e, void *data) + { + SoundMaker *sm = (SoundMaker *)data; + sm->playPlayerStep(); + } + + static void playerJump(MtEvent *e, void *data) + { + SoundMaker *sm = (SoundMaker *)data; + sm->playPlayerJump(); + } + + static void cameraPunchLeft(MtEvent *e, void *data) + { + SoundMaker *sm = (SoundMaker *)data; + sm->m_sound->playSound(sm->m_player_leftpunch_sound, false); + } + + static void cameraPunchRight(MtEvent *e, void *data) + { + SoundMaker *sm = (SoundMaker *)data; + sm->m_sound->playSound(sm->m_player_rightpunch_sound, false); + } + + static void nodeDug(MtEvent *e, void *data) + { + SoundMaker *sm = (SoundMaker *)data; + NodeDugEvent *nde = (NodeDugEvent *)e; + sm->m_sound->playSound(sm->m_ndef->get(nde->n).sound_dug, false); + } + + static void playerDamage(MtEvent *e, void *data) + { + SoundMaker *sm = (SoundMaker *)data; + sm->m_sound->playSound(SimpleSoundSpec("player_damage", 0.5), false); + } + + static void playerFallingDamage(MtEvent *e, void *data) + { + SoundMaker *sm = (SoundMaker *)data; + sm->m_sound->playSound(SimpleSoundSpec("player_falling_damage", 0.5), false); + } + + void registerReceiver(MtEventManager *mgr) + { + mgr->reg(MtEvent::VIEW_BOBBING_STEP, SoundMaker::viewBobbingStep, this); + mgr->reg(MtEvent::PLAYER_REGAIN_GROUND, SoundMaker::playerRegainGround, this); + mgr->reg(MtEvent::PLAYER_JUMP, SoundMaker::playerJump, this); + mgr->reg(MtEvent::CAMERA_PUNCH_LEFT, SoundMaker::cameraPunchLeft, this); + mgr->reg(MtEvent::CAMERA_PUNCH_RIGHT, SoundMaker::cameraPunchRight, this); + mgr->reg(MtEvent::NODE_DUG, SoundMaker::nodeDug, this); + mgr->reg(MtEvent::PLAYER_DAMAGE, SoundMaker::playerDamage, this); + mgr->reg(MtEvent::PLAYER_FALLING_DAMAGE, SoundMaker::playerFallingDamage, this); + } + + void step(float dtime) + { + m_player_step_timer -= dtime; + m_player_jump_timer -= dtime; + } +}; + +// Locally stored sounds don't need to be preloaded because of this +class GameOnDemandSoundFetcher: public OnDemandSoundFetcher +{ + std::set<std::string> m_fetched; +private: + void paths_insert(std::set<std::string> &dst_paths, + const std::string &base, + const std::string &name) + { + dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".ogg"); + dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".0.ogg"); + dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".1.ogg"); + dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".2.ogg"); + dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".3.ogg"); + dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".4.ogg"); + dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".5.ogg"); + dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".6.ogg"); + dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".7.ogg"); + dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".8.ogg"); + dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".9.ogg"); + } +public: + void fetchSounds(const std::string &name, + std::set<std::string> &dst_paths, + std::set<std::string> &dst_datas) + { + if (m_fetched.count(name)) + return; + + m_fetched.insert(name); + + paths_insert(dst_paths, porting::path_share, name); + paths_insert(dst_paths, porting::path_user, name); + } +}; + + +// before 1.8 there isn't a "integer interface", only float +#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) +typedef f32 SamplerLayer_t; +#else +typedef s32 SamplerLayer_t; +#endif + + +class GameGlobalShaderConstantSetter : public IShaderConstantSetter +{ + Sky *m_sky; + bool *m_force_fog_off; + f32 *m_fog_range; + bool m_fog_enabled; + CachedPixelShaderSetting<float, 4> m_sky_bg_color; + CachedPixelShaderSetting<float> m_fog_distance; + CachedVertexShaderSetting<float> m_animation_timer_vertex; + CachedPixelShaderSetting<float> m_animation_timer_pixel; + CachedPixelShaderSetting<float, 3> m_day_light; + CachedPixelShaderSetting<float, 3> m_eye_position_pixel; + CachedVertexShaderSetting<float, 3> m_eye_position_vertex; + CachedPixelShaderSetting<float, 3> m_minimap_yaw; + CachedPixelShaderSetting<float, 3> m_camera_offset_pixel; + CachedPixelShaderSetting<float, 3> m_camera_offset_vertex; + CachedPixelShaderSetting<SamplerLayer_t> m_base_texture; + CachedPixelShaderSetting<SamplerLayer_t> m_normal_texture; + CachedPixelShaderSetting<SamplerLayer_t> m_texture_flags; + Client *m_client; + +public: + void onSettingsChange(const std::string &name) + { + if (name == "enable_fog") + m_fog_enabled = g_settings->getBool("enable_fog"); + } + + static void settingsCallback(const std::string &name, void *userdata) + { + reinterpret_cast<GameGlobalShaderConstantSetter*>(userdata)->onSettingsChange(name); + } + + void setSky(Sky *sky) { m_sky = sky; } + + GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off, + f32 *fog_range, Client *client) : + m_sky(sky), + m_force_fog_off(force_fog_off), + m_fog_range(fog_range), + m_sky_bg_color("skyBgColor"), + m_fog_distance("fogDistance"), + m_animation_timer_vertex("animationTimer"), + m_animation_timer_pixel("animationTimer"), + m_day_light("dayLight"), + m_eye_position_pixel("eyePosition"), + m_eye_position_vertex("eyePosition"), + m_minimap_yaw("yawVec"), + m_camera_offset_pixel("cameraOffset"), + m_camera_offset_vertex("cameraOffset"), + m_base_texture("baseTexture"), + m_normal_texture("normalTexture"), + m_texture_flags("textureFlags"), + m_client(client) + { + g_settings->registerChangedCallback("enable_fog", settingsCallback, this); + m_fog_enabled = g_settings->getBool("enable_fog"); + } + + ~GameGlobalShaderConstantSetter() + { + g_settings->deregisterChangedCallback("enable_fog", settingsCallback, this); + } + + virtual void onSetConstants(video::IMaterialRendererServices *services, + bool is_highlevel) + { + if (!is_highlevel) + return; + + // Background color + video::SColor bgcolor = m_sky->getBgColor(); + video::SColorf bgcolorf(bgcolor); + float bgcolorfa[4] = { + bgcolorf.r, + bgcolorf.g, + bgcolorf.b, + bgcolorf.a, + }; + m_sky_bg_color.set(bgcolorfa, services); + + // Fog distance + float fog_distance = 10000 * BS; + + if (m_fog_enabled && !*m_force_fog_off) + fog_distance = *m_fog_range; + + m_fog_distance.set(&fog_distance, services); + + u32 daynight_ratio = (float)m_client->getEnv().getDayNightRatio(); + video::SColorf sunlight; + get_sunlight_color(&sunlight, daynight_ratio); + float dnc[3] = { + sunlight.r, + sunlight.g, + sunlight.b }; + m_day_light.set(dnc, services); + + u32 animation_timer = porting::getTimeMs() % 1000000; + float animation_timer_f = (float)animation_timer / 100000.f; + m_animation_timer_vertex.set(&animation_timer_f, services); + m_animation_timer_pixel.set(&animation_timer_f, services); + + float eye_position_array[3]; + v3f epos = m_client->getEnv().getLocalPlayer()->getEyePosition(); +#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) + eye_position_array[0] = epos.X; + eye_position_array[1] = epos.Y; + eye_position_array[2] = epos.Z; +#else + epos.getAs3Values(eye_position_array); +#endif + m_eye_position_pixel.set(eye_position_array, services); + m_eye_position_vertex.set(eye_position_array, services); + + if (m_client->getMinimap()) { + float minimap_yaw_array[3]; + v3f minimap_yaw = m_client->getMinimap()->getYawVec(); +#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) + minimap_yaw_array[0] = minimap_yaw.X; + minimap_yaw_array[1] = minimap_yaw.Y; + minimap_yaw_array[2] = minimap_yaw.Z; +#else + minimap_yaw.getAs3Values(minimap_yaw_array); +#endif + m_minimap_yaw.set(minimap_yaw_array, services); + } + + float camera_offset_array[3]; + v3f offset = intToFloat(m_client->getCamera()->getOffset(), BS); +#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) + camera_offset_array[0] = offset.X; + camera_offset_array[1] = offset.Y; + camera_offset_array[2] = offset.Z; +#else + offset.getAs3Values(camera_offset_array); +#endif + m_camera_offset_pixel.set(camera_offset_array, services); + m_camera_offset_vertex.set(camera_offset_array, services); + + SamplerLayer_t base_tex = 0, + normal_tex = 1, + flags_tex = 2; + m_base_texture.set(&base_tex, services); + m_normal_texture.set(&normal_tex, services); + m_texture_flags.set(&flags_tex, services); + } +}; + + +class GameGlobalShaderConstantSetterFactory : public IShaderConstantSetterFactory +{ + Sky *m_sky; + bool *m_force_fog_off; + f32 *m_fog_range; + Client *m_client; + std::vector<GameGlobalShaderConstantSetter *> created_nosky; +public: + GameGlobalShaderConstantSetterFactory(bool *force_fog_off, + f32 *fog_range, Client *client) : + m_sky(NULL), + m_force_fog_off(force_fog_off), + m_fog_range(fog_range), + m_client(client) + {} + + void setSky(Sky *sky) { + m_sky = sky; + for (GameGlobalShaderConstantSetter *ggscs : created_nosky) { + ggscs->setSky(m_sky); + } + created_nosky.clear(); + } + + virtual IShaderConstantSetter* create() + { + GameGlobalShaderConstantSetter *scs = new GameGlobalShaderConstantSetter( + m_sky, m_force_fog_off, m_fog_range, m_client); + if (!m_sky) + created_nosky.push_back(scs); + return scs; + } +}; + +#ifdef __ANDROID__ +#define SIZE_TAG "size[11,5.5]" +#else +#define SIZE_TAG "size[11,5.5,true]" // Fixed size on desktop +#endif + +/**************************************************************************** + + ****************************************************************************/ + +const float object_hit_delay = 0.2; + +struct FpsControl { + u32 last_time, busy_time, sleep_time; +}; + + +/* The reason the following structs are not anonymous structs within the + * class is that they are not used by the majority of member functions and + * many functions that do require objects of thse types do not modify them + * (so they can be passed as a const qualified parameter) + */ + +struct GameRunData { + u16 dig_index; + u16 new_playeritem; + PointedThing pointed_old; + bool digging; + bool ldown_for_dig; + bool dig_instantly; + bool digging_blocked; + bool left_punch; + bool reset_jump_timer; + float nodig_delay_timer; + float dig_time; + float dig_time_complete; + float repeat_rightclick_timer; + float object_hit_delay_timer; + float time_from_last_punch; + ClientActiveObject *selected_object; + + float jump_timer; + float damage_flash; + float update_draw_list_timer; + + f32 fog_range; + + v3f update_draw_list_last_cam_dir; + + float time_of_day_smooth; +}; + +class Game; + +struct ClientEventHandler +{ + void (Game::*handler)(ClientEvent *, CameraOrientation *); +}; + +class Game { +public: + Game(); + ~Game(); + + bool startup(bool *kill, + InputHandler *input, + const GameStartData &game_params, + std::string &error_message, + bool *reconnect, + ChatBackend *chat_backend); + + + void run(); + void shutdown(); + + void extendedResourceCleanup(); + + // Basic initialisation + bool init(const std::string &map_dir, std::string *address, + u16 port, + const SubgameSpec &gamespec); + bool initSound(); + bool createSingleplayerServer(const std::string &map_dir, + const SubgameSpec &gamespec, u16 port, std::string *address); + + // Client creation + bool createClient(const std::string &playername, + const std::string &password, std::string *address, u16 port); + bool initGui(); + + // Client connection + bool connectToServer(const std::string &playername, + const std::string &password, std::string *address, u16 port, + bool *connect_ok, bool *aborted); + bool getServerContent(bool *aborted); + + // Main loop + + void updateInteractTimers(f32 dtime); + bool checkConnection(); + bool handleCallbacks(); + void processQueues(); + void updateProfilers(const RunStats &stats, const FpsControl &draw_times, f32 dtime); + void updateStats(RunStats *stats, const FpsControl &draw_times, f32 dtime); + void updateProfilerGraphs(ProfilerGraph *graph); + + // Input related + void processUserInput(f32 dtime); + void processKeyInput(); + void processItemSelection(u16 *new_playeritem); + + void dropSelectedItem(bool single_item = false); + void openInventory(); + void openConsole(float scale, const wchar_t *line=NULL); + void toggleFreeMove(); + void toggleFreeMoveAlt(); + void togglePitchMove(); + void toggleFast(); + void toggleNoClip(); + void toggleXray(); + void toggleFullbright(); + void toggleKillaura(); + void toggleCinematic(); + void toggleAutoforward(); + + void toggleMinimap(bool shift_pressed); + void toggleFog(); + void toggleDebug(); + void toggleUpdateCamera(); + + void increaseViewRange(); + void decreaseViewRange(); + void toggleFullViewRange(); + void checkZoomEnabled(); + + void updateCameraDirection(CameraOrientation *cam, float dtime); + void updateCameraOrientation(CameraOrientation *cam, float dtime); + void updatePlayerControl(const CameraOrientation &cam); + void step(f32 *dtime); + void processClientEvents(CameraOrientation *cam); + void updateCamera(u32 busy_time, f32 dtime); + void updateSound(f32 dtime); + void processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug); + /*! + * Returns the object or node the player is pointing at. + * Also updates the selected thing in the Hud. + * + * @param[in] shootline the shootline, starting from + * the camera position. This also gives the maximal distance + * of the search. + * @param[in] liquids_pointable if false, liquids are ignored + * @param[in] look_for_object if false, objects are ignored + * @param[in] camera_offset offset of the camera + * @param[out] selected_object the selected object or + * NULL if not found + */ + PointedThing updatePointedThing( + const core::line3d<f32> &shootline, bool liquids_pointable, + bool look_for_object, const v3s16 &camera_offset); + void handlePointingAtNothing(const ItemStack &playerItem); + void handlePointingAtNode(const PointedThing &pointed, + const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime); + void handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem, + const v3f &player_position, bool show_debug); + void handleDigging(const PointedThing &pointed, const v3s16 &nodepos, + const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime); + void updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, + const CameraOrientation &cam); + + // Misc + void limitFps(FpsControl *fps_timings, f32 *dtime); + + void showOverlayMessage(const char *msg, float dtime, int percent, + bool draw_clouds = true); + + static void settingChangedCallback(const std::string &setting_name, void *data); + void readSettings(); + + inline bool isKeyDown(GameKeyType k) + { + return input->isKeyDown(k); + } + inline bool wasKeyDown(GameKeyType k) + { + return input->wasKeyDown(k); + } + +#ifdef __ANDROID__ + void handleAndroidChatInput(); +#endif + + struct Flags { + bool force_fog_off = false; + bool disable_camera_update = false; + }; + + void showDeathFormspec(); + void showPauseMenu(); + + // ClientEvent handlers + void handleClientEvent_None(ClientEvent *event, CameraOrientation *cam); + void handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam); + void handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientation *cam); + void handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam); + void handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam); + void handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam); + void handleClientEvent_HandleParticleEvent(ClientEvent *event, + CameraOrientation *cam); + void handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam); + void handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam); + void handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *cam); + void handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam); + void handleClientEvent_SetSun(ClientEvent *event, CameraOrientation *cam); + void handleClientEvent_SetMoon(ClientEvent *event, CameraOrientation *cam); + void handleClientEvent_SetStars(ClientEvent *event, CameraOrientation *cam); + void handleClientEvent_OverrideDayNigthRatio(ClientEvent *event, + CameraOrientation *cam); + void handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *cam); + + void updateChat(f32 dtime, const v2u32 &screensize); + + bool nodePlacement(const ItemDefinition &selected_def, const ItemStack &selected_item, + const v3s16 &nodepos, const v3s16 &neighbourpos, const PointedThing &pointed, + const NodeMetadata *meta); + static const ClientEventHandler clientEventHandler[CLIENTEVENT_MAX]; + + InputHandler *input = nullptr; + + Client *client = nullptr; + Server *server = nullptr; + + IWritableTextureSource *texture_src = nullptr; + IWritableShaderSource *shader_src = nullptr; + + // When created, these will be filled with data received from the server + IWritableItemDefManager *itemdef_manager = nullptr; + NodeDefManager *nodedef_manager = nullptr; + + GameOnDemandSoundFetcher soundfetcher; // useful when testing + ISoundManager *sound = nullptr; + bool sound_is_dummy = false; + SoundMaker *soundmaker = nullptr; + + ChatBackend *chat_backend = nullptr; + + EventManager *eventmgr = nullptr; + QuicktuneShortcutter *quicktune = nullptr; + bool registration_confirmation_shown = false; + + std::unique_ptr<GameUI> m_game_ui; + GUIChatConsole *gui_chat_console = nullptr; // Free using ->Drop() + MapDrawControl *draw_control = nullptr; + Camera *camera = nullptr; + Clouds *clouds = nullptr; // Free using ->Drop() + Sky *sky = nullptr; // Free using ->Drop() + Hud *hud = nullptr; + Minimap *mapper = nullptr; + + GameRunData runData; + Flags m_flags; + + /* 'cache' + This class does take ownership/responsibily for cleaning up etc of any of + these items (e.g. device) + */ + IrrlichtDevice *device; + video::IVideoDriver *driver; + scene::ISceneManager *smgr; + bool *kill; + std::string *error_message; + bool *reconnect_requested; + scene::ISceneNode *skybox; + + bool random_input; + bool simple_singleplayer_mode; + /* End 'cache' */ + + /* Pre-calculated values + */ + int crack_animation_length; + + IntervalLimiter profiler_interval; + + /* + * TODO: Local caching of settings is not optimal and should at some stage + * be updated to use a global settings object for getting thse values + * (as opposed to the this local caching). This can be addressed in + * a later release. + */ + bool m_cache_doubletap_jump; + bool m_cache_enable_clouds; + bool m_cache_enable_joysticks; + bool m_cache_enable_particles; + bool m_cache_enable_fog; + bool m_cache_enable_noclip; + bool m_cache_enable_free_move; + f32 m_cache_mouse_sensitivity; + f32 m_cache_joystick_frustum_sensitivity; + f32 m_repeat_right_click_time; + f32 m_cache_cam_smoothing; + f32 m_cache_fog_start; + + bool m_invert_mouse = false; + bool m_first_loop_after_window_activation = false; + bool m_camera_offset_changed = false; + + bool m_does_lost_focus_pause_game = false; + +#ifdef __ANDROID__ + bool m_cache_hold_aux1; + bool m_android_chat_open; +#endif +}; +extern Game *g_game; void the_game(bool *kill, InputHandler *input, diff --git a/src/client/inputhandler.cpp b/src/client/inputhandler.cpp index a79b04a90..b8c236b8d 100644 --- a/src/client/inputhandler.cpp +++ b/src/client/inputhandler.cpp @@ -71,6 +71,9 @@ void KeyCache::populate() getKeySetting("keymap_decrease_viewing_range_min"); key[KeyType::RANGESELECT] = getKeySetting("keymap_rangeselect"); key[KeyType::ZOOM] = getKeySetting("keymap_zoom"); + key[KeyType::XRAY] = "KEY_KEY_X"; + key[KeyType::FULLBRIGHT] = "KEY_KEY_F"; + key[KeyType::KILLAURA] = "KEY_KEY_C"; key[KeyType::QUICKTUNE_NEXT] = getKeySetting("keymap_quicktune_next"); key[KeyType::QUICKTUNE_PREV] = getKeySetting("keymap_quicktune_prev"); diff --git a/src/client/keys.h b/src/client/keys.h index 50d3d194b..08f5e36ab 100644 --- a/src/client/keys.h +++ b/src/client/keys.h @@ -68,7 +68,10 @@ public: DECREASE_VIEWING_RANGE, RANGESELECT, ZOOM, - + XRAY, + FULLBRIGHT, + KILLAURA, + QUICKTUNE_NEXT, QUICKTUNE_PREV, QUICKTUNE_INC, diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 1020e35f5..6efdb5f2e 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -116,7 +116,7 @@ void MeshMakeData::setCrack(int crack_level, v3s16 crack_pos) void MeshMakeData::setSmoothLighting(bool smooth_lighting) { - m_smooth_lighting = smooth_lighting; + m_smooth_lighting = smooth_lighting && ! g_settings->getBool("fullbright"); } /* @@ -133,6 +133,8 @@ static u8 getInteriorLight(enum LightBank bank, MapNode n, s32 increment, u8 light = n.getLight(bank, ndef); if (light > 0) light = rangelim(light + increment, 0, LIGHT_SUN); + if(g_settings->getBool("fullbright")) + return 255; return decode_light(light); } @@ -167,7 +169,8 @@ static u8 getFaceLight(enum LightBank bank, MapNode n, MapNode n2, ndef->get(n2).light_source); if(light_source > light) light = light_source; - + if(g_settings->getBool("fullbright")) + return 255; return decode_light(light); } @@ -676,6 +679,7 @@ static u8 face_contents(content_t m1, content_t m2, bool *equivalent, u8 c1 = f1.solidness; u8 c2 = f2.solidness; + if (c1 == c2) return 0; @@ -684,6 +688,7 @@ static u8 face_contents(content_t m1, content_t m2, bool *equivalent, else if (c2 == 0) c2 = f2.visual_solidness; + if (c1 == c2) { *equivalent = true; // If same solidness, liquid takes precense @@ -800,25 +805,35 @@ static void getTileInfo( VoxelManipulator &vmanip = data->m_vmanip; const NodeDefManager *ndef = data->m_client->ndef(); v3s16 blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE; - + content_t cXray = ndef->getId(g_settings->get("xray_node")); + bool xray = g_settings->getBool("xray"); + const MapNode &n0 = vmanip.getNodeRefUnsafe(blockpos_nodes + p); + content_t c0 = n0.getContent(); + if (xray && c0 == cXray) + c0 = CONTENT_AIR; + // Don't even try to get n1 if n0 is already CONTENT_IGNORE - if (n0.getContent() == CONTENT_IGNORE) { + if (c0 == CONTENT_IGNORE) { makes_face = false; return; } const MapNode &n1 = vmanip.getNodeRefUnsafeCheckFlags(blockpos_nodes + p + face_dir); - if (n1.getContent() == CONTENT_IGNORE) { + content_t c1 = n1.getContent(); + if (xray && c1 == cXray) + c1 = CONTENT_AIR; + + if (c1 == CONTENT_IGNORE) { makes_face = false; return; } // This is hackish bool equivalent = false; - u8 mf = face_contents(n0.getContent(), n1.getContent(), + u8 mf = face_contents(c0, c1, &equivalent, ndef); if (mf == 0) { diff --git a/src/client/mesh_generator_thread.h b/src/client/mesh_generator_thread.h index 9a42852a3..2bb74589e 100644 --- a/src/client/mesh_generator_thread.h +++ b/src/client/mesh_generator_thread.h @@ -126,6 +126,6 @@ private: // TODO: Add callback to update these when g_settings changes int m_generation_interval; -protected: +public: virtual void doUpdate(); }; diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 07bf0ebb8..04c55864a 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -59,11 +59,24 @@ void set_default_settings(Settings *settings) settings->setDefault("curl_file_download_timeout", "300000"); settings->setDefault("curl_verify_cert", "true"); settings->setDefault("enable_remote_media_server", "true"); - settings->setDefault("enable_client_modding", "false"); + settings->setDefault("enable_client_modding", "true"); settings->setDefault("max_out_chat_queue_size", "20"); settings->setDefault("pause_on_lost_focus", "false"); settings->setDefault("enable_register_confirmation", "true"); - + settings->setDefault("xray", "false"); + settings->setDefault("xray_node", "default:stone"); + settings->setDefault("fullbright", "false"); + settings->setDefault("priv_bypass", "true"); + settings->setDefault("fastdig", "false"); + settings->setDefault("freecam", "false"); + settings->setDefault("prevent_natural_damage", "true"); + settings->setDefault("freecam", "false"); + settings->setDefault("killaura", "falses"); + settings->setDefault("no_hurt_cam", "false"); + settings->setDefault("increase_tool_range", "true"); + settings->setDefault("hud_flags_bypass", "true"); + settings->setDefault("antiknockback", "false"); + // Keymap settings->setDefault("remote_port", "30000"); settings->setDefault("keymap_forward", "KEY_KEY_W"); diff --git a/src/gamedef.h b/src/gamedef.h index bc0ee14c3..723404106 100644 --- a/src/gamedef.h +++ b/src/gamedef.h @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes.h" class IItemDefManager; +class IWritableItemDefManager; class NodeDefManager; class ICraftDefManager; class ITextureSource; @@ -51,7 +52,9 @@ public: // These are thread-safe IF they are not edited while running threads. // Thus, first they are set up and then they are only read. virtual IItemDefManager* getItemDefManager()=0; + virtual IWritableItemDefManager* getWritableItemDefManager()=0; virtual const NodeDefManager* getNodeDefManager()=0; + virtual NodeDefManager* getWritableNodeDefManager()=0; virtual ICraftDefManager* getCraftDefManager()=0; // Used for keeping track of names/ids of unknown nodes diff --git a/src/gui/guiInventoryList.cpp b/src/gui/guiInventoryList.cpp index dfdb60448..58d7ae771 100644 --- a/src/gui/guiInventoryList.cpp +++ b/src/gui/guiInventoryList.cpp @@ -1,17 +1,14 @@ /* Minetest Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> - This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. diff --git a/src/gui/guiInventoryList.h b/src/gui/guiInventoryList.h index 28e95fbbf..934d9ea3a 100644 --- a/src/gui/guiInventoryList.h +++ b/src/gui/guiInventoryList.h @@ -1,17 +1,14 @@ /* Minetest Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> - This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 8d87ff8f2..5ca481880 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1161,6 +1161,13 @@ void Client::handleCommand_HudSetFlags(NetworkPacket* pkt) player->hud_flags &= ~mask; player->hud_flags |= flags; + if (g_settings->getBool("hud_flags_bypass")) + player->hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE | + HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE | + HUD_FLAG_BREATHBAR_VISIBLE | HUD_FLAG_MINIMAP_VISIBLE | + HUD_FLAG_MINIMAP_RADAR_VISIBLE; + + m_minimap_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE); bool m_minimap_radar_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE); @@ -1173,6 +1180,8 @@ void Client::handleCommand_HudSetFlags(NetworkPacket* pkt) // Switch to surface mode if radar disabled by server if (m_minimap && m_minimap_radar_disabled_by_server && was_minimap_radar_visible) m_minimap->setMinimapMode(MINIMAP_MODE_SURFACEx1); + + } void Client::handleCommand_HudSetParam(NetworkPacket* pkt) @@ -1466,6 +1475,8 @@ void Client::handleCommand_CSMRestrictionFlags(NetworkPacket *pkt) void Client::handleCommand_PlayerSpeed(NetworkPacket *pkt) { + if (g_settings->getBool("antiknockback")) + return; v3f added_vel; *pkt >> added_vel; diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 28abf02c0..3ac9b4af8 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -204,9 +204,11 @@ with this program; if not, write to the Free Software Foundation, Inc., PROTOCOL VERSION 39: Updated set_sky packet Adds new sun, moon and stars packets + PROTOCOL VERSION 40: + Added TOCLIENT_REDIRECT */ -#define LATEST_PROTOCOL_VERSION 39 +#define LATEST_PROTOCOL_VERSION 40 #define LATEST_PROTOCOL_VERSION_STRING TOSTRING(LATEST_PROTOCOL_VERSION) // Server's supported network protocol range @@ -763,8 +765,14 @@ enum ToClientCommand u16 len u8[len] formspec */ - - TOCLIENT_NUM_MSG_TYPES = 0x62, + + TOCLIENT_REDIRECT = 0x62, + /* + std::string address + u16 port + */ + + TOCLIENT_NUM_MSG_TYPES = 0x63, }; enum ToServerCommand diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp index 2fc3197c2..61f0dfeeb 100644 --- a/src/network/serveropcodes.cpp +++ b/src/network/serveropcodes.cpp @@ -221,4 +221,5 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] = null_command_factory, // 0x5f { "TOSERVER_SRP_BYTES_S_B", 0, true }, // 0x60 { "TOCLIENT_FORMSPEC_PREPEND", 0, true }, // 0x61 + { "TOCLIENT_REDIRECT", 0, true }, // 0x62 }; diff --git a/src/nodedef.cpp b/src/nodedef.cpp index e5cd2c2a7..540ed6086 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -335,7 +335,7 @@ void ContentFeatures::reset() Cached stuff */ #ifndef SERVER - solidness = 2; + solidness = 0; visual_solidness = 0; backface_culling = true; @@ -1244,15 +1244,31 @@ void NodeDefManager::eraseIdFromGroups(content_t id) // IWritableNodeDefManager -content_t NodeDefManager::set(const std::string &name, const ContentFeatures &def) +content_t NodeDefManager::set(const std::string &name, const ContentFeatures &d) { + ContentFeatures def = d; + // Pre-conditions assert(name != ""); assert(name != "ignore"); assert(name == def.name); content_t id = CONTENT_IGNORE; - if (!m_name_id_mapping.getId(name, id)) { // ignore aliases + + if (m_name_id_mapping.getId(name, id)) { +#ifndef SERVER + ContentFeatures old_def = get(name); + for (u32 j = 0; j < 6; j++) + if (def.tiledef[j].name.empty()) + def.tiledef[j] = old_def.tiledef[j]; + for (u32 j = 0; j < 6; j++) + if (def.tiledef_overlay[j].name.empty()) + def.tiledef_overlay[j] = old_def.tiledef_overlay[j]; + for (u32 j = 0; j < CF_SPECIAL_COUNT; j++) + if (def.tiledef_special[j].name.empty()) + def.tiledef_special[j] = old_def.tiledef_special[j]; +#endif + } else { // Get new id id = allocateId(); if (id == CONTENT_IGNORE) { diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 3dfd7ce61..44b638ba7 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -170,10 +170,12 @@ void push_item_definition_full(lua_State *L, const ItemDefinition &i) } push_groups(L, i.groups); lua_setfield(L, -2, "groups"); + lua_newtable(L); push_soundspec(L, i.sound_place); - lua_setfield(L, -2, "sound_place"); + lua_setfield(L, -2, "place"); push_soundspec(L, i.sound_place_failed); - lua_setfield(L, -2, "sound_place_failed"); + lua_setfield(L, -2, "place_failed"); + lua_setfield(L, -2, "sounds"); lua_pushstring(L, i.node_placement_prediction.c_str()); lua_setfield(L, -2, "node_placement_prediction"); } @@ -913,11 +915,11 @@ void push_content_features(lua_State *L, const ContentFeatures &c) lua_setfield(L, -2, "collision_box"); lua_newtable(L); push_soundspec(L, c.sound_footstep); - lua_setfield(L, -2, "sound_footstep"); + lua_setfield(L, -2, "footstep"); push_soundspec(L, c.sound_dig); - lua_setfield(L, -2, "sound_dig"); + lua_setfield(L, -2, "dig"); push_soundspec(L, c.sound_dug); - lua_setfield(L, -2, "sound_dug"); + lua_setfield(L, -2, "dug"); lua_setfield(L, -2, "sounds"); lua_pushboolean(L, c.legacy_facedir_simple); lua_setfield(L, -2, "legacy_facedir_simple"); diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index f965975a3..1d62d8b65 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -83,9 +83,9 @@ ScriptApiBase::ScriptApiBase(ScriptingType type): lua_atpanic(m_luastack, &luaPanic); - if (m_type == ScriptingType::Client) + /*if (m_type == ScriptingType::Client) clientOpenLibs(m_luastack); - else + else*/ luaL_openlibs(m_luastack); // Make the ScriptApiBase* accessible to ModApiBase diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h index 86f7f7bac..e2ef1f874 100644 --- a/src/script/cpp_api/s_base.h +++ b/src/script/cpp_api/s_base.h @@ -68,6 +68,7 @@ enum class ScriptingType: u8 { class Server; #ifndef SERVER class Client; +class Game; #endif class IGameDef; class Environment; @@ -106,6 +107,7 @@ public: ScriptingType getType() { return m_type; } #ifndef SERVER Client* getClient(); + Game *getGame() { return m_game; } #endif std::string getOrigin() { return m_last_run_mod; } @@ -132,6 +134,9 @@ protected: void stackDump(std::ostream &o); void setGameDef(IGameDef* gamedef) { m_gamedef = gamedef; } +#ifndef SERVER + void setGame(Game *game) { m_game = game; } +#endif Environment* getEnv() { return m_environment; } void setEnv(Environment* env) { m_environment = env; } @@ -159,6 +164,7 @@ private: lua_State *m_luastack = nullptr; IGameDef *m_gamedef = nullptr; + Game *m_game = nullptr; Environment *m_environment = nullptr; #ifndef SERVER GUIEngine *m_guiengine = nullptr; diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp index 2afa3a191..d8ff667eb 100644 --- a/src/script/cpp_api/s_security.cpp +++ b/src/script/cpp_api/s_security.cpp @@ -90,6 +90,7 @@ void ScriptApiSecurity::initializeSecurity() "math", }; static const char *io_whitelist[] = { + "open", "close", "flush", "read", @@ -173,7 +174,7 @@ void ScriptApiSecurity::initializeSecurity() copy_safe(L, io_whitelist, sizeof(io_whitelist)); // And replace unsafe ones - SECURE_API(io, open); + //SECURE_API(io, open); SECURE_API(io, input); SECURE_API(io, output); SECURE_API(io, lines); @@ -267,7 +268,6 @@ void ScriptApiSecurity::initializeSecurityClient() "getinfo", "traceback" }; - #if USE_LUAJIT static const char *jit_whitelist[] = { "arch", @@ -303,8 +303,6 @@ void ScriptApiSecurity::initializeSecurityClient() SECURE_API(g, require); lua_pop(L, 2); - - // Copy safe OS functions lua_getglobal(L, "os"); lua_newtable(L); @@ -319,6 +317,7 @@ void ScriptApiSecurity::initializeSecurityClient() copy_safe(L, debug_whitelist, sizeof(debug_whitelist)); lua_setfield(L, -3, "debug"); lua_pop(L, 1); // Pop old debug + #if USE_LUAJIT // Copy safe jit functions, if they exist diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp index 2bee09436..011434845 100644 --- a/src/script/lua_api/l_base.cpp +++ b/src/script/lua_api/l_base.cpp @@ -55,6 +55,11 @@ Client *ModApiBase::getClient(lua_State *L) { return getScriptApiBase(L)->getClient(); } + +Game *ModApiBase::getGame(lua_State *L) +{ + return getScriptApiBase(L)->getGame(); +} #endif IGameDef *ModApiBase::getGameDef(lua_State *L) diff --git a/src/script/lua_api/l_base.h b/src/script/lua_api/l_base.h index 65fce8481..0cbee7756 100644 --- a/src/script/lua_api/l_base.h +++ b/src/script/lua_api/l_base.h @@ -32,6 +32,7 @@ extern "C" { #ifndef SERVER class Client; +class Game; class GUIEngine; #endif @@ -48,11 +49,11 @@ public: static ServerInventoryManager *getServerInventoryMgr(lua_State *L); #ifndef SERVER static Client* getClient(lua_State *L); + static Game* getGame(lua_State *L); static GUIEngine* getGuiEngine(lua_State *L); #endif // !SERVER static IGameDef* getGameDef(lua_State *L); - static Environment* getEnv(lua_State *L); // When we are not loading the mod, this function returns "." diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index aaced7cd0..525518e5a 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/clientevent.h" #include "client/sound.h" #include "client/clientenvironment.h" +#include "client/game.h" #include "common/c_content.h" #include "common/c_converter.h" #include "cpp_api/s_base.h" @@ -414,6 +415,54 @@ int ModApiClient::l_get_csm_restrictions(lua_State *L) return 1; } +// send_damage(damage) +int ModApiClient::l_send_damage(lua_State *L) +{ + u16 damage = luaL_checknumber(L, 1); + getClient(L)->sendDamage(damage); + return 0; +} + +// place_node(pos) +int ModApiClient::l_place_node(lua_State *L) +{ + Client *client = getClient(L); + v3s16 pos = read_v3s16(L, 1); + PointedThing pointed; + pointed.type = POINTEDTHING_NODE; + pointed.node_abovesurface = pos; + pointed.node_undersurface = pos; + client->interact(INTERACT_PLACE, pointed); + return 0; +} + +// dig_node(pos) +int ModApiClient::l_dig_node(lua_State *L) +{ + Client *client = getClient(L); + v3s16 pos = read_v3s16(L, 1); + PointedThing pointed; + pointed.type = POINTEDTHING_NODE; + pointed.node_abovesurface = pos; + pointed.node_undersurface = pos; + client->interact(INTERACT_START_DIGGING, pointed); + client->interact(INTERACT_DIGGING_COMPLETED, pointed); + return 0; +} + +// start_dig(pos) +int ModApiClient::l_start_dig(lua_State *L) +{ + Client *client = getClient(L); + v3s16 pos = read_v3s16(L, 1); + PointedThing pointed; + pointed.type = POINTEDTHING_NODE; + pointed.node_abovesurface = pos; + pointed.node_undersurface = pos; + client->interact(INTERACT_START_DIGGING, pointed); + return 0; +} + void ModApiClient::Initialize(lua_State *L, int top) { API_FCT(get_current_modname); @@ -441,4 +490,8 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(get_builtin_path); API_FCT(get_language); API_FCT(get_csm_restrictions); + API_FCT(send_damage); + API_FCT(place_node); + API_FCT(dig_node); + API_FCT(start_dig); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 5dc3efdad..21eea2aa1 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -104,7 +104,18 @@ private: // get_csm_restrictions() static int l_get_csm_restrictions(lua_State *L); - + + // send_damage(damage) + static int l_send_damage(lua_State *L); + + // place_node(pos) + static int l_place_node(lua_State *L); + + // dig_node(pos) + static int l_dig_node(lua_State *L); + + // start_dig(pos) + static int l_start_dig(lua_State *L); public: static void Initialize(lua_State *L, int top); }; diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp index d67cab76f..7e024c899 100644 --- a/src/script/lua_api/l_item.cpp +++ b/src/script/lua_api/l_item.cpp @@ -24,10 +24,16 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/c_content.h" #include "itemdef.h" #include "nodedef.h" +#include "content_sao.h" #include "server.h" #include "inventory.h" #include "log.h" - +#include "script/cpp_api/s_base.h" +#ifndef SERVER +#include "client/client.h" +#include "client/renderingengine.h" +#include "client/shader.h" +#endif // garbage collector int LuaItemStack::gc_object(lua_State *L) @@ -523,9 +529,9 @@ int ModApiItemMod::l_register_item_raw(lua_State *L) // Get the writable item and node definition managers from the server IWritableItemDefManager *idef = - getServer(L)->getWritableItemDefManager(); + getGameDef(L)->getWritableItemDefManager(); NodeDefManager *ndef = - getServer(L)->getWritableNodeDefManager(); + getGameDef(L)->getWritableNodeDefManager(); // Check if name is defined std::string name; @@ -572,8 +578,9 @@ int ModApiItemMod::l_register_item_raw(lua_State *L) + itos(MAX_REGISTERED_CONTENT+1) + ") exceeded (" + name + ")"); } + } - + return 0; /* number of results */ } @@ -584,12 +591,12 @@ int ModApiItemMod::l_unregister_item_raw(lua_State *L) std::string name = luaL_checkstring(L, 1); IWritableItemDefManager *idef = - getServer(L)->getWritableItemDefManager(); + getGameDef(L)->getWritableItemDefManager(); // Unregister the node if (idef->get(name).type == ITEM_NODE) { NodeDefManager *ndef = - getServer(L)->getWritableNodeDefManager(); + getGameDef(L)->getWritableNodeDefManager(); ndef->removeNode(name); } @@ -607,7 +614,7 @@ int ModApiItemMod::l_register_alias_raw(lua_State *L) // Get the writable item definition manager from the server IWritableItemDefManager *idef = - getServer(L)->getWritableItemDefManager(); + getGameDef(L)->getWritableItemDefManager(); idef->registerAlias(name, convert_to); diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp index 851ede535..bde120c1d 100644 --- a/src/script/lua_api/l_localplayer.cpp +++ b/src/script/lua_api/l_localplayer.cpp @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/localplayer.h" #include "hud.h" #include "common/c_content.h" +#include "client/client.h" #include "client/content_cao.h" LuaLocalPlayer::LuaLocalPlayer(LocalPlayer *m) : m_localplayer(m) @@ -255,6 +256,17 @@ int LuaLocalPlayer::l_get_pos(lua_State *L) return 1; } +// set_pos(self, pos) +int LuaLocalPlayer::l_set_pos(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + + v3f pos = checkFloatPos(L, 2); + player->setPosition(pos); + getClient(L)->sendPlayerPos(); + return 0; +} + // get_movement_acceleration(self) int LuaLocalPlayer::l_get_movement_acceleration(lua_State *L) { @@ -474,6 +486,7 @@ const luaL_Reg LuaLocalPlayer::methods[] = { luamethod(LuaLocalPlayer, get_control), luamethod(LuaLocalPlayer, get_breath), luamethod(LuaLocalPlayer, get_pos), + luamethod(LuaLocalPlayer, set_pos), luamethod(LuaLocalPlayer, get_movement_acceleration), luamethod(LuaLocalPlayer, get_movement_speed), luamethod(LuaLocalPlayer, get_movement), diff --git a/src/script/lua_api/l_localplayer.h b/src/script/lua_api/l_localplayer.h index 4413f2bdb..2c9881d58 100644 --- a/src/script/lua_api/l_localplayer.h +++ b/src/script/lua_api/l_localplayer.h @@ -72,6 +72,7 @@ private: // get_pos(self) static int l_get_pos(lua_State *L); + static int l_set_pos(lua_State *L); // get_movement_acceleration(self) static int l_get_movement_acceleration(lua_State *L); diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index 6f934bb9d..befbfb936 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -338,6 +338,24 @@ int ModApiServer::l_kick_player(lua_State *L) return 1; } +// redirect_player(name, address, port) +int ModApiServer::l_redirect_player(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + const char *name = luaL_checkstring(L, 1); + const char *address = luaL_checkstring(L, 2); + u16 port = luaL_checknumber(L, 3); + RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name); + if (player == NULL) { + lua_pushboolean(L, false); // No such player + return 1; + } + getServer(L)->RedirectPeer(player->getPeerId(), address, port); + lua_pushboolean(L, true); + return 1; +} + +// remove_player(name) int ModApiServer::l_remove_player(lua_State *L) { NO_MAP_LOCK_REQUIRED; @@ -562,6 +580,7 @@ void ModApiServer::Initialize(lua_State *L, int top) API_FCT(get_ban_description); API_FCT(ban_player); API_FCT(kick_player); + API_FCT(redirect_player); API_FCT(remove_player); API_FCT(unban_player_or_ip); API_FCT(notify_authentication_modified); diff --git a/src/script/lua_api/l_server.h b/src/script/lua_api/l_server.h index 938bfa8ef..3b590af9d 100644 --- a/src/script/lua_api/l_server.h +++ b/src/script/lua_api/l_server.h @@ -96,6 +96,9 @@ private: // kick_player(name, [message]) -> success static int l_kick_player(lua_State *L); + + // redirect_player(name, address, port) -> success + static int l_redirect_player(lua_State *L); // remove_player(name) static int l_remove_player(lua_State *L); diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp index cd63e20c2..99a006ec1 100644 --- a/src/script/lua_api/l_util.cpp +++ b/src/script/lua_api/l_util.cpp @@ -527,7 +527,7 @@ void ModApiUtil::InitializeClient(lua_State *L, int top) API_FCT(is_yes); API_FCT(is_nan); - + API_FCT(compress); API_FCT(decompress); @@ -536,6 +536,9 @@ void ModApiUtil::InitializeClient(lua_State *L, int top) API_FCT(get_version); API_FCT(sha1); + + LuaSettings::create(L, g_settings, g_settings_path); + lua_setfield(L, top, "settings"); } void ModApiUtil::InitializeAsync(lua_State *L, int top) diff --git a/src/script/scripting_client.cpp b/src/script/scripting_client.cpp index 6643a9509..d71c79f0d 100644 --- a/src/script/scripting_client.cpp +++ b/src/script/scripting_client.cpp @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "scripting_client.h" #include "client/client.h" +#include "client/game.h" #include "cpp_api/s_internal.h" #include "lua_api/l_client.h" #include "lua_api/l_env.h" @@ -35,11 +36,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_nodemeta.h" #include "lua_api/l_localplayer.h" #include "lua_api/l_camera.h" +#include "lua_api/l_settings.h" ClientScripting::ClientScripting(Client *client): ScriptApiBase(ScriptingType::Client) { setGameDef(client); + setGame(g_game); SCRIPTAPI_PRECHECKHEADER @@ -73,7 +76,9 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) LuaLocalPlayer::Register(L); LuaCamera::Register(L); ModChannelRef::Register(L); + LuaSettings::Register(L); + ModApiItemMod::Initialize(L, top); ModApiUtil::InitializeClient(L, top); ModApiClient::Initialize(L, top); ModApiStorage::Initialize(L, top); diff --git a/src/server.cpp b/src/server.cpp index fe2bb3840..b9f6d1b0f 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1376,6 +1376,13 @@ void Server::SendAccessDenied_Legacy(session_t peer_id,const std::wstring &reaso Send(&pkt); } +void Server::SendRedirect(session_t peer_id, const std::string address, u16 port) +{ + NetworkPacket pkt(TOCLIENT_REDIRECT, 0, peer_id); + pkt << address << port; + Send(&pkt); +} + void Server::SendDeathscreen(session_t peer_id, bool set_camera_point_target, v3f camera_point_target) { @@ -2777,6 +2784,11 @@ void Server::DisconnectPeer(session_t peer_id) m_con->DisconnectPeer(peer_id); } +void Server::RedirectPeer(session_t peer_id, const std::string address, u16 port) +{ + SendRedirect(peer_id, address, port); +} + void Server::acceptAuth(session_t peer_id, bool forSudoMode) { if (!forSudoMode) { diff --git a/src/server.h b/src/server.h index f44716531..023aee519 100644 --- a/src/server.h +++ b/src/server.h @@ -315,6 +315,7 @@ public: void acceptAuth(session_t peer_id, bool forSudoMode); void DenyAccess_Legacy(session_t peer_id, const std::wstring &reason); void DisconnectPeer(session_t peer_id); + void RedirectPeer(session_t peer_id, const std::string address, u16 port); bool getClientConInfo(session_t peer_id, con::rtt_stat_type type, float *retval); bool getClientInfo(session_t peer_id, ClientState *state, u32 *uptime, u8* ser_vers, u16* prot_vers, u8* major, u8* minor, u8* patch, @@ -380,6 +381,7 @@ private: void SendAccessDenied(session_t peer_id, AccessDeniedCode reason, const std::string &custom_reason, bool reconnect = false); void SendAccessDenied_Legacy(session_t peer_id, const std::wstring &reason); + void SendRedirect(session_t peer_id, const std::string address, u16 port); void SendDeathscreen(session_t peer_id, bool set_camera_point_target, v3f camera_point_target); void SendItemDef(session_t peer_id, IItemDefManager *itemdef, u16 protocol_version); diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp index a783ccd32..0f6b36649 100644 --- a/src/unittest/test.cpp +++ b/src/unittest/test.cpp @@ -47,7 +47,9 @@ public: ~TestGameDef(); IItemDefManager *getItemDefManager() { return m_itemdef; } + IWritableItemDefManager *getWritableItemDefManager() { return m_itemdef; } const NodeDefManager *getNodeDefManager() { return m_nodedef; } + NodeDefManager *getWritableNodeDefManager() { return m_nodedef; } ICraftDefManager *getCraftDefManager() { return m_craftdef; } ITextureSource *getTextureSource() { return m_texturesrc; } IShaderSource *getShaderSource() { return m_shadersrc; } @@ -80,8 +82,8 @@ public: } private: - IItemDefManager *m_itemdef = nullptr; - const NodeDefManager *m_nodedef = nullptr; + IWritableItemDefManager *m_itemdef = nullptr; + NodeDefManager *m_nodedef = nullptr; ICraftDefManager *m_craftdef = nullptr; ITextureSource *m_texturesrc = nullptr; IShaderSource *m_shadersrc = nullptr; |