aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--CMakeLists.txt16
-rw-r--r--LICENSE.txt8
-rw-r--r--builtin/client/chatcommands.lua141
-rw-r--r--builtin/client/cheats.lua57
-rw-r--r--builtin/client/death_formspec.lua40
-rw-r--r--builtin/client/init.lua5
-rw-r--r--builtin/client/register.lua26
-rw-r--r--builtin/client/util.lua60
-rw-r--r--builtin/common/chatcommands.lua45
-rw-r--r--builtin/common/misc_helpers.lua84
-rw-r--r--builtin/game/item.lua13
-rw-r--r--builtin/init.lua1
-rw-r--r--builtin/mainmenu/dlg_contentstore.lua8
-rw-r--r--builtin/mainmenu/dlg_settings_advanced.lua30
-rw-r--r--builtin/mainmenu/init.lua1
-rw-r--r--builtin/mainmenu/pkgmgr.lua56
-rw-r--r--builtin/mainmenu/tab_content.lua88
-rw-r--r--builtin/mainmenu/tab_credits.lua12
-rw-r--r--builtin/settingtypes.txt119
-rw-r--r--clientmods/mods_here.txt4
-rw-r--r--clientmods/preview/example.lua2
-rw-r--r--clientmods/preview/examples/first.lua1
-rw-r--r--clientmods/preview/init.lua203
-rw-r--r--doc/client_lua_api.txt310
-rw-r--r--doc/lua_api.txt2
-rw-r--r--doc/protocol.md (renamed from doc/protocol.txt)0
-rw-r--r--games/devtest/mods/basetools/.sounds/default_grass_footstep.1.oggbin0 -> 7014 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_break_glass.1.oggbin0 -> 11130 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_break_glass.2.oggbin0 -> 16058 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_break_glass.3.oggbin0 -> 12257 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_chest_close.oggbin0 -> 10768 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_chest_open.oggbin0 -> 11092 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_cool_lava.1.oggbin0 -> 9583 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_cool_lava.2.oggbin0 -> 7977 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_cool_lava.3.oggbin0 -> 6499 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_dig_choppy.oggbin0 -> 6794 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_dig_cracky.oggbin0 -> 6628 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_dig_crumbly.oggbin0 -> 7567 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_dig_dig_immediate.oggbin0 -> 6714 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_dig_metal.oggbin0 -> 5245 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_dig_oddly_breakable_by_hand.oggbin0 -> 6940 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_dig_snappy.oggbin0 -> 7258 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_dirt_footstep.1.oggbin0 -> 9155 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_dirt_footstep.2.oggbin0 -> 7553 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_dug_metal.1.oggbin0 -> 7076 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_dug_metal.2.oggbin0 -> 7260 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_dug_node.1.oggbin0 -> 6630 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_dug_node.2.oggbin0 -> 7863 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_glass_footstep.oggbin0 -> 7094 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_grass_footstep.2.oggbin0 -> 10164 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_grass_footstep.3.oggbin0 -> 9989 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_gravel_footstep.1.oggbin0 -> 7326 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_gravel_footstep.2.oggbin0 -> 10136 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_gravel_footstep.3.oggbin0 -> 8086 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_gravel_footstep.4.oggbin0 -> 9017 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_hard_footstep.1.oggbin0 -> 4915 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_hard_footstep.2.oggbin0 -> 4922 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_hard_footstep.3.oggbin0 -> 4919 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_item_smoke.oggbin0 -> 6651 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_metal_footstep.1.oggbin0 -> 6847 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_metal_footstep.2.oggbin0 -> 6926 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_metal_footstep.3.oggbin0 -> 6970 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_place_node.1.oggbin0 -> 8584 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_place_node.2.oggbin0 -> 8644 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_place_node.3.oggbin0 -> 8846 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_place_node_hard.1.oggbin0 -> 6578 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_place_node_hard.2.oggbin0 -> 5623 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_place_node_metal.1.oggbin0 -> 7518 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_place_node_metal.2.oggbin0 -> 7854 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_sand_footstep.1.oggbin0 -> 11897 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_sand_footstep.2.oggbin0 -> 9228 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_snow_footstep.1.oggbin0 -> 7159 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_snow_footstep.2.oggbin0 -> 8726 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_snow_footstep.3.oggbin0 -> 8722 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_snow_footstep.4.oggbin0 -> 6795 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_snow_footstep.5.oggbin0 -> 8126 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_tool_breaks.1.oggbin0 -> 6019 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_tool_breaks.2.oggbin0 -> 8440 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_tool_breaks.3.oggbin0 -> 6875 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_water_footstep.1.oggbin0 -> 31719 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_water_footstep.2.oggbin0 -> 29335 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_water_footstep.3.oggbin0 -> 32107 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_water_footstep.4.oggbin0 -> 3974 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_wood_footstep.1.oggbin0 -> 5967 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/default_wood_footstep.2.oggbin0 -> 5772 bytes
-rw-r--r--games/devtest/mods/basetools/sounds/player_damage.oggbin0 -> 6176 bytes
-rw-r--r--games/devtest/mods/player_api/README.txt29
-rw-r--r--games/devtest/mods/player_api/api.lua144
-rw-r--r--games/devtest/mods/player_api/init.lua34
-rw-r--r--games/devtest/mods/player_api/license.txt53
-rw-r--r--games/devtest/mods/player_api/mod.conf2
-rw-r--r--games/devtest/mods/player_api/models/character.b3dbin0 -> 73433 bytes
-rw-r--r--games/devtest/mods/player_api/models/character.blendbin0 -> 632188 bytes
-rw-r--r--games/devtest/mods/player_api/models/character.pngbin0 -> 2754 bytes
-rw-r--r--games/devtest/mods/player_api/textures/player.pngbin0 -> 142 bytes
-rw-r--r--games/devtest/mods/player_api/textures/player_back.pngbin0 -> 140 bytes
-rw-r--r--latex/doxygen.sty503
-rw-r--r--latex/md_README.tex463
-rw-r--r--latex/refman.log156
-rw-r--r--latex/refman.tex155
-rw-r--r--misc/Info.plist2
-rw-r--r--misc/dragonfire-icon-24x24.pngbin0 -> 1248 bytes
-rw-r--r--misc/dragonfire-icon.icnsbin0 -> 108878 bytes
-rw-r--r--misc/dragonfire-icon.icobin0 -> 11479 bytes
-rw-r--r--misc/dragonfire-icon.ico.pngbin0 -> 11325 bytes
-rw-r--r--misc/dragonfire-xorg-icon-128.pngbin0 -> 5053 bytes
-rw-r--r--misc/dragonfire.svg118
-rw-r--r--misc/minetest-icon-24x24.pngbin587 -> 0 bytes
-rw-r--r--misc/minetest-icon.icnsbin242668 -> 0 bytes
-rw-r--r--misc/minetest-icon.icobin9662 -> 0 bytes
-rw-r--r--misc/minetest-xorg-icon-128.pngbin11241 -> 0 bytes
-rw-r--r--misc/minetest.svg183
-rw-r--r--misc/net.minetest.minetest.appdata.xml2
-rwxr-xr-x[-rw-r--r--]misc/net.minetest.minetest.desktop4
-rw-r--r--misc/winresource.rc8
-rw-r--r--po/lo/minetest.po6394
-rw-r--r--po/minetest.pot91
-rw-r--r--src/activeobjectmgr.h5
-rw-r--r--src/client/camera.cpp4
-rw-r--r--src/client/client.cpp68
-rw-r--r--src/client/client.h22
-rw-r--r--src/client/clientenvironment.cpp6
-rw-r--r--src/client/clientenvironment.h5
-rw-r--r--src/client/clientmap.cpp6
-rw-r--r--src/client/clientobject.h5
-rw-r--r--src/client/content_cao.cpp43
-rw-r--r--src/client/content_cao.h33
-rw-r--r--src/client/game.cpp283
-rw-r--r--src/client/game.h876
-rw-r--r--src/client/gameui.cpp41
-rw-r--r--src/client/gameui.h5
-rw-r--r--src/client/inputhandler.cpp10
-rw-r--r--src/client/inputhandler.h23
-rw-r--r--src/client/keys.h12
-rw-r--r--src/client/localplayer.cpp60
-rw-r--r--src/client/localplayer.h38
-rw-r--r--src/client/mapblock_mesh.cpp108
-rw-r--r--src/client/mapblock_mesh.h2
-rw-r--r--src/client/mesh_generator_thread.h2
-rw-r--r--src/client/minimap.cpp4
-rw-r--r--src/client/render/core.cpp91
-rw-r--r--src/client/render/core.h9
-rw-r--r--src/client/renderingengine.cpp7
-rw-r--r--src/collision.cpp5
-rw-r--r--src/collision.h2
-rw-r--r--src/defaultsettings.cpp84
-rw-r--r--src/environment.cpp10
-rw-r--r--src/gamedef.h3
-rw-r--r--src/gui/CMakeLists.txt1
-rw-r--r--src/gui/cheatMenu.cpp270
-rw-r--r--src/gui/cheatMenu.h84
-rw-r--r--src/gui/guiInventoryList.cpp3
-rw-r--r--src/gui/guiInventoryList.h3
-rw-r--r--src/gui/guiKeyChangeMenu.cpp24
-rw-r--r--src/map.cpp30
-rw-r--r--src/map.h5
-rw-r--r--src/network/clientpackethandler.cpp40
-rw-r--r--src/network/networkprotocol.h2
-rw-r--r--src/nodedef.cpp22
-rw-r--r--src/player.cpp9
-rw-r--r--src/player.h5
-rw-r--r--src/raycast.cpp5
-rw-r--r--src/raycast.h3
-rw-r--r--src/script/common/c_content.cpp100
-rw-r--r--src/script/common/c_content.h6
-rw-r--r--src/script/cpp_api/CMakeLists.txt1
-rw-r--r--src/script/cpp_api/s_base.cpp4
-rw-r--r--src/script/cpp_api/s_base.h8
-rw-r--r--src/script/cpp_api/s_cheats.cpp123
-rw-r--r--src/script/cpp_api/s_cheats.h58
-rw-r--r--src/script/cpp_api/s_client.cpp117
-rw-r--r--src/script/cpp_api/s_client.h10
-rw-r--r--src/script/cpp_api/s_security.cpp11
-rw-r--r--src/script/lua_api/CMakeLists.txt2
-rw-r--r--src/script/lua_api/l_base.cpp5
-rw-r--r--src/script/lua_api/l_base.h3
-rw-r--r--src/script/lua_api/l_client.cpp216
-rw-r--r--src/script/lua_api/l_client.h27
-rw-r--r--src/script/lua_api/l_clientobject.cpp241
-rw-r--r--src/script/lua_api/l_clientobject.h92
-rw-r--r--src/script/lua_api/l_env.cpp170
-rw-r--r--src/script/lua_api/l_env.h12
-rw-r--r--src/script/lua_api/l_http.cpp14
-rw-r--r--src/script/lua_api/l_inventoryaction.cpp215
-rw-r--r--src/script/lua_api/l_inventoryaction.h74
-rw-r--r--src/script/lua_api/l_item.cpp20
-rw-r--r--src/script/lua_api/l_localplayer.cpp141
-rw-r--r--src/script/lua_api/l_localplayer.h25
-rw-r--r--src/script/lua_api/l_mainmenu.cpp3
-rw-r--r--src/script/lua_api/l_server.cpp2
-rw-r--r--src/script/lua_api/l_util.cpp5
-rw-r--r--src/script/scripting_client.cpp11
-rw-r--r--src/script/scripting_client.h4
-rw-r--r--src/unittest/test.cpp6
-rw-r--r--textures/base/pack/logo.pngbin12188 -> 135512 bytes
-rw-r--r--textures/base/pack/menu_bg.pngbin124 -> 124 bytes
-rwxr-xr-xutil/buildbot/buildwin32.sh8
-rwxr-xr-xutil/buildbot/buildwin64.sh8
-rw-r--r--util/ci/lint_autocorrect.sh45
200 files changed, 13063 insertions, 779 deletions
diff --git a/.gitignore b/.gitignore
index 52f8bc4f4..bfb815bbf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -52,9 +52,9 @@ build/.cmake/
!/mods/minetest/mods_here.txt
/worlds
/world/
-/clientmods/*
-!/clientmods/preview/
/client/mod_storage/
+/clientmods/*
+!/clientmods/mods_here.txt
## Configuration/log files
minetest.conf
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2549bd25d..1a5bd9574 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,7 +4,7 @@ cmake_policy(SET CMP0025 OLD)
# This can be read from ${PROJECT_NAME} after project() is called
project(minetest)
-set(PROJECT_NAME_CAPITALIZED "Minetest")
+set(PROJECT_NAME_CAPITALIZED "Dragonfire")
set(CMAKE_CXX_STANDARD 11)
set(GCC_MINIMUM_VERSION "4.8")
@@ -14,10 +14,10 @@ set(CLANG_MINIMUM_VERSION "3.4")
set(VERSION_MAJOR 5)
set(VERSION_MINOR 4)
set(VERSION_PATCH 0)
-set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
+set(VERSION_EXTRA "-dragonfire" CACHE STRING "Stuff to append to version string")
# Change to false for releases
-set(DEVELOPMENT_BUILD TRUE)
+set(DEVELOPMENT_BUILD FALSE)
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
if(VERSION_EXTRA)
@@ -188,14 +188,14 @@ if(UNIX AND NOT APPLE)
install(FILES "doc/minetest.6" "doc/minetestserver.6" DESTINATION "${MANDIR}/man6")
install(FILES "misc/net.minetest.minetest.desktop" DESTINATION "${XDG_APPS_DIR}")
install(FILES "misc/net.minetest.minetest.appdata.xml" DESTINATION "${APPDATADIR}")
- install(FILES "misc/minetest.svg" DESTINATION "${ICONDIR}/hicolor/scalable/apps")
- install(FILES "misc/minetest-xorg-icon-128.png"
+ install(FILES "misc/dragonfire.svg" DESTINATION "${ICONDIR}/hicolor/scalable/apps")
+ install(FILES "misc/dragonfire-xorg-icon-128.png"
DESTINATION "${ICONDIR}/hicolor/128x128/apps"
- RENAME "minetest.png")
+ RENAME "dragonfire.png")
endif()
if(APPLE)
- install(FILES "misc/minetest-icon.icns" DESTINATION "${SHAREDIR}")
+ install(FILES "misc/dragonfire-icon.icns" DESTINATION "${SHAREDIR}")
install(FILES "misc/Info.plist" DESTINATION "${BUNDLE_PATH}/Contents")
endif()
@@ -281,7 +281,7 @@ if(WIN32)
set(CPACK_CREATE_DESKTOP_LINKS ${PROJECT_NAME})
set(CPACK_PACKAGING_INSTALL_PREFIX "/${PROJECT_NAME_CAPITALIZED}")
- set(CPACK_WIX_PRODUCT_ICON "${CMAKE_CURRENT_SOURCE_DIR}/misc/minetest-icon.ico")
+ set(CPACK_WIX_PRODUCT_ICON "${CMAKE_CURRENT_SOURCE_DIR}/misc/dragonfire-icon.ico")
# Supported languages can be found at
# http://wixtoolset.org/documentation/manual/v3/wixui/wixui_localization.html
#set(CPACK_WIX_CULTURES "ar-SA,bg-BG,ca-ES,hr-HR,cs-CZ,da-DK,nl-NL,en-US,et-EE,fi-FI,fr-FR,de-DE")
diff --git a/LICENSE.txt b/LICENSE.txt
index 9b8ee851a..27b30323a 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -33,10 +33,10 @@ rubenwardy, paramat:
textures/base/pack/start_icon.png
textures/base/pack/end_icon.png
-erlehmann:
- misc/minetest-icon-24x24.png
- misc/minetest-icon.ico
- misc/minetest.svg
+EliasFleckenstein03:
+ misc/dragonfire-icon-24x24.png
+ misc/dragonfire-icon.ico
+ misc/dragonfire.svg
textures/base/pack/logo.png
JRottm
diff --git a/builtin/client/chatcommands.lua b/builtin/client/chatcommands.lua
index 0e8d4dd03..0da3dab1b 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
@@ -42,34 +41,144 @@ core.register_on_sending_chat_message(function(message)
return true
end)
-core.register_chatcommand("list_players", {
- description = core.gettext("List online players"),
+function core.run_server_chatcommand(cmd, param)
+ core.send_chat_message("/" .. cmd .. " " .. param)
+end
+
+core.register_chatcommand("say", {
+ description = "Send raw text",
+ func = function(text)
+ core.send_chat_message(text)
+ return true
+ end,
+})
+
+core.register_chatcommand("teleport", {
+ params = "<X>,<Y>,<Z>",
+ description = "Teleport to coordinates.",
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.")
+ 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,
+})
- local players = table.concat(player_names, ", ")
- return true, core.gettext("Online players: ") .. players
+core.register_chatcommand("wielded", {
+ description = "Print itemstring of wieleded item",
+ func = function()
+ return true, core.localplayer:get_wielded_item():get_name()
end
})
core.register_chatcommand("disconnect", {
- description = core.gettext("Exit to main menu"),
+ description = "Exit to main menu",
func = function(param)
core.disconnect()
end,
})
-core.register_chatcommand("clear_chat_queue", {
- description = core.gettext("Clear the out chat queue"),
+core.register_chatcommand("players", {
+ description = "List online players",
func = function(param)
- core.clear_out_chat_queue()
- return true, core.gettext("The out chat queue is now empty")
+ return true, "Online players: " .. table.concat(core.get_player_names(), ", ")
+ end
+})
+
+core.register_chatcommand("kill", {
+ description = "Kill yourself",
+ func = function()
+ core.send_damage(10000)
end,
})
-function core.run_server_chatcommand(cmd, param)
- core.send_chat_message("/" .. cmd .. " " .. param)
-end
+core.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
+ core.settings:set(setname, setvalue)
+ return true, setname .. " = " .. setvalue
+ end
+
+ setname, setvalue = string.match(param, "([^ ]+) (.+)")
+ if setname and setvalue then
+ if not core.settings:get(setname) then
+ return false, "Failed. Use '.set -n <name> <value>' to create a new setting."
+ end
+ core.settings:set(setname, setvalue)
+ return true, setname .. " = " .. setvalue
+ end
+
+ setname = string.match(param, "([^ ]+)")
+ if setname then
+ setvalue = core.settings:get(setname)
+ if not setvalue then
+ setvalue = "<not set>"
+ end
+ return true, setname .. " = " .. setvalue
+ end
+
+ return false, "Invalid parameters (see .help set)."
+ end,
+})
+
+core.register_chatcommand("place", {
+ params = "<X>,<Y>,<Z>",
+ description = "Place wielded item",
+ func = function(param)
+ local success, pos = core.parse_relative_pos(param)
+ if success then
+ core.place_node(pos)
+ return true, "Node placed at " .. core.pos_to_string(pos)
+ end
+ return false, pos
+ end,
+})
+
+core.register_chatcommand("dig", {
+ params = "<X>,<Y>,<Z>",
+ description = "Dig node",
+ func = function(param)
+ local success, pos = core.parse_relative_pos(param)
+ if success then
+ core.dig_node(pos)
+ return true, "Node at " .. core.pos_to_string(pos) .. " dug"
+ end
+ return false, pos
+ end,
+})
+
+core.register_chatcommand("setyaw", {
+ params = "<yaw>",
+ description = "Set your yaw",
+ func = function(param)
+ local yaw = tonumber(param)
+ if yaw then
+ core.localplayer:set_yaw(yaw)
+ return true
+ else
+ return false, "Invalid usage (See .help setyaw)"
+ end
+ end
+})
+
+core.register_chatcommand("setpitch", {
+ params = "<pitch>",
+ description = "Set your pitch",
+ func = function(param)
+ local pitch = tonumber(param)
+ if pitch then
+ core.localplayer:set_pitch(pitch)
+ return true
+ else
+ return false, "Invalid usage (See .help setpitch)"
+ end
+ end
+})
+
+core.register_list_command("xray", "Configure X-Ray", "xray_nodes")
+core.register_list_command("search", "Configure NodeESP", "node_esp_nodes")
diff --git a/builtin/client/cheats.lua b/builtin/client/cheats.lua
new file mode 100644
index 000000000..e4cace744
--- /dev/null
+++ b/builtin/client/cheats.lua
@@ -0,0 +1,57 @@
+core.cheats = {
+ ["Combat"] = {
+ ["AntiKnockback"] = "antiknockback",
+ ["AttachmentFloat"] = "float_above_parent",
+ },
+ ["Movement"] = {
+ ["Freecam"] = "freecam",
+ ["AutoForward"] = "continuous_forward",
+ ["PitchMove"] = "pitch_move",
+ ["AutoJump"] = "autojump",
+ ["Jesus"] = "jesus",
+ ["NoSlow"] = "no_slow",
+ ["JetPack"] = "jetpack",
+ ["AntiSlip"] = "antislip",
+ },
+ ["Render"] = {
+ ["Xray"] = "xray",
+ ["Fullbright"] = "fullbright",
+ ["HUDBypass"] = "hud_flags_bypass",
+ ["NoHurtCam"] = "no_hurt_cam",
+ ["BrightNight"] = "no_night",
+ ["Coords"] = "coords",
+ ["CheatHUD"] = "cheat_hud",
+ ["EntityESP"] = "enable_entity_esp",
+ ["EntityTracers"] = "enable_entity_tracers",
+ ["PlayerESP"] = "enable_player_esp",
+ ["PlayerTracers"] = "enable_player_tracers",
+ ["NodeESP"] = "enable_node_esp",
+ ["NodeTracers"] = "enable_node_tracers",
+ },
+ ["Interact"] = {
+ ["FastDig"] = "fastdig",
+ ["FastPlace"] = "fastplace",
+ ["AutoDig"] = "autodig",
+ ["AutoPlace"] = "autoplace",
+ ["InstantBreak"] = "instant_break",
+ ["FastHit"] = "spamclick",
+ ["AutoHit"] = "autohit",
+ },
+ ["Exploit"] = {
+ ["EntitySpeed"] = "entity_speed",
+ },
+ ["Player"] = {
+ ["NoFallDamage"] = "prevent_natural_damage",
+ ["NoForceRotate"] = "no_force_rotate",
+ ["Reach"] = "reach",
+ ["PointLiquids"] = "point_liquids",
+ ["PrivBypass"] = "priv_bypass",
+ ["AutoRespawn"] = "autorespawn",
+ ["ThroughWalls"] = "dont_point_nodes",
+ },
+}
+
+function core.register_cheat(cheatname, category, func)
+ core.cheats[category] = core.cheats[category] or {}
+ core.cheats[category][cheatname] = func
+end
diff --git a/builtin/client/death_formspec.lua b/builtin/client/death_formspec.lua
index e755ac5c1..7b8530440 100644
--- a/builtin/client/death_formspec.lua
+++ b/builtin/client/death_formspec.lua
@@ -1,16 +1,38 @@
--- CSM death formspec. Only used when clientside modding is enabled, otherwise
--- handled by the engine.
+local death_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]"
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)
+ core.display_chat_message("You died at " .. core.pos_to_string(vector.round(core.localplayer:get_pos())) .. ".")
+ if core.settings:get_bool("autorespawn") then
+ core.send_respawn()
+ else
+ core.show_formspec("__builtin__:death", death_formspec)
+ end
end)
core.register_on_formspec_input(function(formname, fields)
- if formname == "bultin:death" then
- core.send_respawn()
+ if formname == "__builtin__:death" then
+ if fields.btn_ghost_mode then
+ core.display_chat_message("You are in ghost mode. Use .respawn to Respawn.")
+ else
+ core.send_respawn()
+ end
end
end)
+
+core.register_chatcommand("respawn", {
+ description = "Respawn when in ghost mode",
+ func = function()
+ if core.localplayer:get_hp() == 0 then
+ core.send_respawn()
+ core.display_chat_message("Respawned.")
+ else
+ core.display_chat_message("You are not in ghost mode.")
+ end
+ end
+})
diff --git a/builtin/client/init.lua b/builtin/client/init.lua
index 9633a7c71..8c6512ec1 100644
--- a/builtin/client/init.lua
+++ b/builtin/client/init.lua
@@ -6,6 +6,9 @@ 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 .. "util.lua")
+dofile(clientpath .. "chatcommands.lua")
dofile(clientpath .. "death_formspec.lua")
+dofile(clientpath .. "cheats.lua")
+
diff --git a/builtin/client/register.lua b/builtin/client/register.lua
index 27a6b02d9..2b5526523 100644
--- a/builtin/client/register.lua
+++ b/builtin/client/register.lua
@@ -47,6 +47,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
--
@@ -82,3 +102,9 @@ core.registered_on_item_use, core.register_on_item_use = make_registration()
core.registered_on_modchannel_message, core.register_on_modchannel_message = make_registration()
core.registered_on_modchannel_signal, core.register_on_modchannel_signal = make_registration()
core.registered_on_inventory_open, core.register_on_inventory_open = make_registration()
+core.registered_on_recieve_physics_override, core.register_on_recieve_physics_override = make_registration()
+core.registered_on_play_sound, core.register_on_play_sound = make_registration()
+core.registered_on_spawn_particle, core.register_on_spawn_particle = make_registration()
+
+core.registered_nodes = {}
+core.registered_items = {}
diff --git a/builtin/client/util.lua b/builtin/client/util.lua
new file mode 100644
index 000000000..aea15e00f
--- /dev/null
+++ b/builtin/client/util.lua
@@ -0,0 +1,60 @@
+function core.parse_pos(param)
+ local p = {}
+ local playerpos = core.localplayer:get_pos()
+ 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] = playerpos[k]
+ else
+ p[k] = tonumber(v)
+ end
+ end
+ if p.x and p.y and p.z then
+ return true, vector.round(p)
+ end
+ return false, "Invalid position (" .. param .. ")"
+end
+
+function core.parse_relative_pos(param)
+ local success, pos = core.parse_pos(param:gsub("~", "0"))
+ if success then pos = vector.round(vector.add(core.localplayer:get_pos(), pos)) end
+ return success, pos
+end
+
+function core.find_item(item, mini, maxi)
+ for index, stack in ipairs(core.get_inventory("current_player").main) do
+ if (not mini or index >= mini) and (not maxi or index <= maxi) and stack:get_name() == item then
+ return index
+ end
+ end
+end
+
+function core.switch_to_item(item)
+ local i = core.find_item(item)
+ if i then
+ core.localplayer:set_wield_index(i)
+ return true
+ else
+ return false
+ end
+end
+
+function core.get_pointed_thing()
+ local pos = core.camera:get_pos()
+ local pos2 = vector.add(pos, vector.multiply(core.camera:get_look_dir(), 7))
+ local player = core.localplayer
+ if not player then return end
+ local item = player:get_wielded_item()
+ if not item then return end
+ local def = core.get_item_def(item:get_name())
+ local ray = core.raycast(pos, pos2, true, core.settings:get_bool("point_liquids") or def and def.liquids_pointable)
+ return ray and ray:next()
+end
+
+function core.close_formspec(formname)
+ return core.show_formspec(formname, "")
+end
+
+function core.get_nearby_objects(radius)
+ return core.get_objects_inside_radius(core.localplayer:get_pos(), radius)
+end
diff --git a/builtin/common/chatcommands.lua b/builtin/common/chatcommands.lua
index 52edda659..fb593e839 100644
--- a/builtin/common/chatcommands.lua
+++ b/builtin/common/chatcommands.lua
@@ -29,6 +29,51 @@ function core.override_chatcommand(name, redefinition)
core.registered_chatcommands[name] = chatcommand
end
+if INIT == "client" then
+ function core.register_list_command(command, desc, setting)
+ local def = {}
+ def.description = desc
+ def.params = "del <item> | add <item> | list"
+ function def.func(param)
+ local list = (minetest.settings:get(setting) or ""):split(",")
+ if param == "list" then
+ return true, table.concat(list, ", ")
+ else
+ local sparam = param:split(" ")
+ local cmd = sparam[1]
+ local item = sparam[2]
+ if cmd == "del" then
+ if not item then
+ return false, "Missing item."
+ end
+ local i = table.indexof(list, item)
+ if i == -1 then
+ return false, item .. " is not on the list."
+ else
+ table.remove(list, i)
+ core.settings:set(setting, table.concat(list, ","))
+ return true, "Removed " .. item .. " from the list."
+ end
+ elseif cmd == "add" then
+ if not item then
+ return false, "Missing item."
+ end
+ local i = table.indexof(list, item)
+ if i ~= -1 then
+ return false, item .. " is already on the list."
+ else
+ table.insert(list, item)
+ core.settings:set(setting, table.concat(list, ","))
+ return true, "Added " .. item .. " to the list."
+ end
+ end
+ end
+ return false, "Invalid usage. (See .help " .. command .. ")"
+ end
+ core.register_chatcommand(command, def)
+ end
+end
+
local cmd_marker = "/"
local function gettext(...)
diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua
index 0f3897f47..b86d68f5f 100644
--- a/builtin/common/misc_helpers.lua
+++ b/builtin/common/misc_helpers.lua
@@ -517,6 +517,17 @@ function table.shuffle(t, from, to, random)
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
--------------------------------------------------------------------------------
@@ -584,6 +595,66 @@ function core.colorize(color, message)
return table.concat(lines, "\n") .. core.get_color_escape_sequence("#ffffff")
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
+
+function core.rainbow(input)
+ local step = 360 / input:len()
+ local hue = 0
+ local output = ""
+ for i = 1, input:len() do
+ local char = input:sub(i, i)
+ if char:match("%s") then
+ output = output .. char
+ else
+ output = output .. core.get_color_escape_sequence(color_from_hue(hue)) .. char
+ end
+ hue = hue + step
+ end
+ return output
+end
function core.strip_foreground_colors(str)
return (str:gsub(ESCAPE_CHAR .. "%(c@[^)]+%)", ""))
@@ -637,6 +708,19 @@ function core.get_translator(textdomain)
return function(str, ...) return core.translate(textdomain or "", str, ...) end
end
+function core.get_pointed_thing_position(pointed_thing, above)
+ if pointed_thing.type == "node" then
+ if above then
+ -- The position where a node would be placed
+ return pointed_thing.above
+ end
+ -- The position where a node would be dug
+ return pointed_thing.under
+ elseif pointed_thing.type == "object" then
+ return pointed_thing.ref and pointed_thing.ref:get_pos()
+ end
+end
+
--------------------------------------------------------------------------------
-- Returns the exact coordinate of a pointed surface
--------------------------------------------------------------------------------
diff --git a/builtin/game/item.lua b/builtin/game/item.lua
index 881aff52e..30bb4a007 100644
--- a/builtin/game/item.lua
+++ b/builtin/game/item.lua
@@ -24,19 +24,6 @@ function core.inventorycube(img1, img2, img3)
.. "{" .. img3:gsub("%^", "&")
end
-function core.get_pointed_thing_position(pointed_thing, above)
- if pointed_thing.type == "node" then
- if above then
- -- The position where a node would be placed
- return pointed_thing.above
- end
- -- The position where a node would be dug
- return pointed_thing.under
- elseif pointed_thing.type == "object" then
- return pointed_thing.ref and pointed_thing.ref:get_pos()
- end
-end
-
function core.dir_to_facedir(dir, is6d)
--account for y if requested
if is6d and math.abs(dir.y) > math.abs(dir.x) and math.abs(dir.y) > math.abs(dir.z) then
diff --git a/builtin/init.lua b/builtin/init.lua
index 75bb3db85..f76174be7 100644
--- a/builtin/init.lua
+++ b/builtin/init.lua
@@ -36,7 +36,6 @@ dofile(commonpath .. "misc_helpers.lua")
if INIT == "game" then
dofile(gamepath .. "init.lua")
- assert(not core.get_http_api)
elseif INIT == "mainmenu" then
local mm_script = core.settings:get("main_menu_script")
if mm_script and mm_script ~= "" then
diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua
index 7328f3358..b058e4824 100644
--- a/builtin/mainmenu/dlg_contentstore.lua
+++ b/builtin/mainmenu/dlg_contentstore.lua
@@ -42,8 +42,8 @@ local num_per_page = 5
local filter_type = 1
local filter_types_titles = {
fgettext("All packages"),
- fgettext("Games"),
- fgettext("Mods"),
+-- fgettext("Games"),
+ fgettext("Clientmods"),
fgettext("Texture packs"),
}
@@ -52,7 +52,7 @@ local download_queue = {}
local filter_types_type = {
nil,
- "game",
+-- "game",
"mod",
"txp",
}
@@ -582,7 +582,7 @@ end
function store.update_paths()
local mod_hash = {}
pkgmgr.refresh_globals()
- for _, mod in pairs(pkgmgr.global_mods:get_list()) do
+ for _, mod in pairs(pkgmgr.clientmods:get_list()) do
if mod.author and mod.release > 0 then
mod_hash[mod.author:lower() .. "/" .. mod.name] = mod
end
diff --git a/builtin/mainmenu/dlg_settings_advanced.lua b/builtin/mainmenu/dlg_settings_advanced.lua
index c16e4aad0..26f4fa4a7 100644
--- a/builtin/mainmenu/dlg_settings_advanced.lua
+++ b/builtin/mainmenu/dlg_settings_advanced.lua
@@ -400,6 +400,36 @@ local function parse_config_file(read_all, parse_mods)
file:close()
end
end
+
+ -- Parse clientmods
+ local clientmods_category_initialized = false
+ local clientmods = {}
+ get_mods(core.get_clientmodpath(), clientmods)
+ for _, clientmod in ipairs(clientmods) do
+ local path = clientmod.path .. DIR_DELIM .. FILENAME
+ local file = io.open(path, "r")
+ if file then
+ if not clientmods_category_initialized then
+ fgettext_ne("Clientmods") -- not used, but needed for xgettext
+ table.insert(settings, {
+ name = "Clientmods",
+ level = 0,
+ type = "category",
+ })
+ clientmods_category_initialized = true
+ end
+
+ table.insert(settings, {
+ name = clientmod.name,
+ level = 1,
+ type = "category",
+ })
+
+ parse_single_file(file, path, read_all, settings, 2, false)
+
+ file:close()
+ end
+ end
end
return settings
diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua
index 45089c7c9..2096b0cfc 100644
--- a/builtin/mainmenu/init.lua
+++ b/builtin/mainmenu/init.lua
@@ -126,3 +126,4 @@ local function init_globals()
end
init_globals()
+
diff --git a/builtin/mainmenu/pkgmgr.lua b/builtin/mainmenu/pkgmgr.lua
index bfb5d269a..588d10f81 100644
--- a/builtin/mainmenu/pkgmgr.lua
+++ b/builtin/mainmenu/pkgmgr.lua
@@ -601,7 +601,7 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
clean_path = get_last_folder(cleanup_path(basefolder.path))
end
if clean_path then
- targetpath = core.get_modpath() .. DIR_DELIM .. clean_path
+ targetpath = core.get_clientmodpath() .. DIR_DELIM .. clean_path
else
return nil,
fgettext("Install Mod: Unable to find suitable folder name for modpack $1",
@@ -628,7 +628,7 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
end
if targetfolder ~= nil and pkgmgr.isValidModname(targetfolder) then
- targetpath = core.get_modpath() .. DIR_DELIM .. targetfolder
+ targetpath = core.get_clientmodpath() .. DIR_DELIM .. targetfolder
else
return nil, fgettext("Install Mod: Unable to find real mod name for: $1", path)
end
@@ -680,6 +680,54 @@ function pkgmgr.install(type, modfilename, basename, dest)
end
--------------------------------------------------------------------------------
+function pkgmgr.prepareclientmodlist(data)
+ local retval = {}
+
+ local clientmods = {}
+
+ --read clientmods
+ local modpath = core.get_clientmodpath()
+
+ if modpath ~= nil and
+ modpath ~= "" then
+ get_mods(modpath,clientmods)
+ end
+
+ for i=1,#clientmods,1 do
+ clientmods[i].type = "mod"
+ clientmods[i].loc = "global"
+ clientmods[i].is_clientside = true
+ retval[#retval + 1] = clientmods[i]
+ end
+
+ --read mods configuration
+ local filename = modpath ..
+ DIR_DELIM .. "mods.conf"
+
+ local conffile = Settings(filename)
+
+ for key,value in pairs(conffile:to_table()) do
+ if key:sub(1, 9) == "load_mod_" then
+ key = key:sub(10)
+ local element = nil
+ for i=1,#retval,1 do
+ if retval[i].name == key and
+ not retval[i].is_modpack then
+ element = retval[i]
+ break
+ end
+ end
+ if element ~= nil then
+ element.enabled = value ~= "false" and value ~= "nil" and value
+ else
+ core.log("info", "Clientmod: " .. key .. " " .. dump(value) .. " but not found")
+ end
+ end
+ end
+
+ return retval
+end
+
function pkgmgr.preparemodlist(data)
local retval = {}
@@ -822,6 +870,10 @@ function pkgmgr.refresh_globals()
pkgmgr.comparemod, is_equal, nil, {})
pkgmgr.global_mods:add_sort_mechanism("alphabetic", sort_mod_list)
pkgmgr.global_mods:set_sortmode("alphabetic")
+ pkgmgr.clientmods = filterlist.create(pkgmgr.prepareclientmodlist,
+ pkgmgr.comparemod, is_equal, nil, {})
+ pkgmgr.clientmods:add_sort_mechanism("alphabetic", sort_mod_list)
+ pkgmgr.clientmods:set_sortmode("alphabetic")
end
--------------------------------------------------------------------------------
diff --git a/builtin/mainmenu/tab_content.lua b/builtin/mainmenu/tab_content.lua
index 336730bf4..a76fee864 100644
--- a/builtin/mainmenu/tab_content.lua
+++ b/builtin/mainmenu/tab_content.lua
@@ -19,6 +19,10 @@
local packages_raw
local packages
+local function modname_valid(name)
+ return not name:find("[^a-z0-9_]")
+end
+
--------------------------------------------------------------------------------
local function get_formspec(tabview, name, tabdata)
if pkgmgr.global_mods == nil then
@@ -33,6 +37,7 @@ local function get_formspec(tabview, name, tabdata)
table.insert_all(packages_raw, pkgmgr.games)
table.insert_all(packages_raw, pkgmgr.get_texture_packs())
table.insert_all(packages_raw, pkgmgr.global_mods:get_list())
+ table.insert_all(packages_raw, pkgmgr.clientmods:get_list())
local function get_data()
return packages_raw
@@ -45,6 +50,38 @@ local function get_formspec(tabview, name, tabdata)
packages = filterlist.create(get_data, pkgmgr.compare_package,
is_equal, nil, {})
+
+ local filename = core.get_clientmodpath() .. DIR_DELIM .. "mods.conf"
+
+ local conffile = Settings(filename)
+ local mods = conffile:to_table()
+
+ for i = 1, #packages_raw do
+ local mod = packages_raw[i]
+ if mod.is_clientside and not mod.is_modpack then
+ if modname_valid(mod.name) then
+ conffile:set("load_mod_" .. mod.name,
+ mod.enabled and "true" or "false")
+ elseif mod.enabled then
+ gamedata.errormessage = fgettext_ne("Failed to enable clientmo" ..
+ "d \"$1\" as it contains disallowed characters. " ..
+ "Only characters [a-z0-9_] are allowed.",
+ mod.name)
+ end
+ mods["load_mod_" .. mod.name] = nil
+ end
+ end
+
+ -- Remove mods that are not present anymore
+ for key in pairs(mods) do
+ if key:sub(1, 9) == "load_mod_" then
+ conffile:remove(key)
+ end
+ end
+
+ if not conffile:write() then
+ core.log("error", "Failed to write clientmod config file")
+ end
end
if tabdata.selected_pkg == nil then
@@ -94,9 +131,21 @@ local function get_formspec(tabview, name, tabdata)
if selected_pkg.type == "mod" then
if selected_pkg.is_modpack then
- retval = retval ..
- "button[8.65,4.65;3.25,1;btn_mod_mgr_rename_modpack;" ..
- fgettext("Rename") .. "]"
+ if selected_pkg.is_clientside then
+ if pkgmgr.is_modpack_entirely_enabled({list = packages}, selected_pkg.name) then
+ retval = retval ..
+ "button[8.65,4.65;3.25,1;btn_mod_mgr_mp_disable;" ..
+ fgettext("Disable modpack") .. "]"
+ else
+ retval = retval ..
+ "button[8.65,4.65;3.25,1;btn_mod_mgr_mp_enable;" ..
+ fgettext("Enable modpack") .. "]"
+ end
+ else
+ retval = retval ..
+ "button[8.65,4.65;3.25,1;btn_mod_mgr_rename_modpack;" ..
+ fgettext("Rename") .. "]"
+ end
else
--show dependencies
desc = desc .. "\n\n"
@@ -117,6 +166,17 @@ local function get_formspec(tabview, name, tabdata)
"\n" .. toadd_soft
end
end
+ if selected_pkg.is_clientside then
+ if selected_pkg.enabled then
+ retval = retval ..
+ "button[8.65,4.65;3.25,1;btn_mod_mgr_disable_mod;" ..
+ fgettext("Disable") .. "]"
+ else
+ retval = retval ..
+ "button[8.65,4.65;3.25,1;btn_mod_mgr_enable_mod;" ..
+ fgettext("Enable") .. "]"
+ end
+ end
end
else
@@ -150,6 +210,28 @@ local function handle_buttons(tabview, fields, tabname, tabdata)
if fields["pkglist"] ~= nil then
local event = core.explode_table_event(fields["pkglist"])
tabdata.selected_pkg = event.row
+ local mod = packages:get_list()[tabdata.selected_pkg]
+
+ if event.type == "DCL" and mod.is_clientside then
+ pkgmgr.enable_mod({data = {list = packages, selected_mod = tabdata.selected_pkg}})
+ packages = nil
+ end
+ return true
+ end
+
+ if fields.btn_mod_mgr_mp_enable ~= nil or
+ fields.btn_mod_mgr_mp_disable ~= nil then
+ pkgmgr.enable_mod({data = {list = packages, selected_mod = tabdata.selected_pkg}},
+ fields.btn_mod_mgr_mp_enable ~= nil)
+ packages = nil
+ return true
+ end
+
+ if fields.btn_mod_mgr_enable_mod ~= nil or
+ fields.btn_mod_mgr_disable_mod ~= nil then
+ pkgmgr.enable_mod({data = {list = packages, selected_mod = tabdata.selected_pkg}},
+ fields.btn_mod_mgr_enable_mod ~= nil)
+ packages = nil
return true
end
diff --git a/builtin/mainmenu/tab_credits.lua b/builtin/mainmenu/tab_credits.lua
index 075274798..309a61858 100644
--- a/builtin/mainmenu/tab_credits.lua
+++ b/builtin/mainmenu/tab_credits.lua
@@ -16,6 +16,16 @@
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--------------------------------------------------------------------------------
+local dragonfire_team = {
+ "Elias Fleckenstein [Main Developer]",
+ "cora [Core Developer]",
+ "emilia [Core Developer]",
+ "oneplustwo [Developer]",
+ "joshia_wi [Developer]",
+ "Code-Sploit [Developer]",
+ "DerZombiiie [User Support]",
+ "Rtx [User Support]",
+}
local core_developers = {
"Perttu Ahola (celeron55) <celeron55@gmail.com>",
@@ -107,6 +117,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("Dragonfire Team") .. ",," ..
+ buildCreditList(dragonfire_team) .. ",,," ..
"#FFFF00," .. fgettext("Core Developers") .. ",," ..
buildCreditList(core_developers) .. ",,," ..
"#FFFF00," .. fgettext("Active Contributors") .. ",," ..
diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt
index 8b6227b37..15c48dfc1 100644
--- a/builtin/settingtypes.txt
+++ b/builtin/settingtypes.txt
@@ -197,6 +197,10 @@ keymap_place (Place key) key KEY_RBUTTON
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_inventory (Inventory key) key KEY_KEY_I
+# Key for opening the special inventory.
+# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
+keymap_special_inventory (Special inventory key) key KEY_KEY_O
+
# Key for moving fast in fast mode.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_special1 (Special key) key KEY_KEY_E
@@ -277,6 +281,14 @@ keymap_drop (Drop item key) key KEY_KEY_Q
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_zoom (View zoom key) key KEY_KEY_Z
+# Key for toggling Killaura.
+# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
+keymap_toggle_killaura (Killaura key) key KEY_KEY_X
+
+# Key for toggling Freecam.
+# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
+keymap_toggle_freecam (Freecam key) key KEY_KEY_G
+
# Key for selecting the first hotbar slot.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_slot1 (Hotbar slot 1 key) key KEY_KEY_1
@@ -2207,3 +2219,110 @@ contentdb_flag_blacklist (ContentDB Flag Blacklist) string nonfree, desktop_defa
# Maximum number of concurrent downloads. Downloads exceeding this limit will be queued.
# This should be lower than curl_parallel_limit.
contentdb_max_concurrent_downloads (ContentDB Max Concurrent Downloads) int 3
+
+[Cheat Menu]
+
+# Font to use for cheat menu
+cheat_menu_font (MenuFont) enum FM_Mono FM_Standard,FM_Mono,FM_Fallback,FM_Simple,FM_SimpleMono,FM_MaxMode,FM_Unspecified
+
+# (RGB value)
+cheat_menu_bg_color (Cell background color) v3f 255, 145, 88
+
+cheat_menu_bg_color_alpha (Cell background color alpha) int 192
+
+# (RGB value)
+cheat_menu_active_bg_color (Active cell background color) v3f 255, 87, 53
+
+cheat_menu_active_bg_color_alpha (Active cell background color alpha) int 192
+
+# (RGB value)
+cheat_menu_font_color (Font color) v3f 0, 0, 0
+
+cheat_menu_font_color_alpha (Font color alpha) int 255
+
+# (RGB value)
+cheat_menu_selected_font_color (Selected font color) v3f 255, 252, 88
+
+cheat_menu_selected_font_color_alpha (Selected font color alpha) int 255
+
+cheat_menu_head_height (Head height) int 50
+
+cheat_menu_entry_height (Entry height) int 40
+
+cheat_menu_entry_width (Entry width) int 200
+
+[Cheats]
+
+fullbright (Fullbright) bool false
+
+xray (XRay) bool false
+
+xray_nodes (XRay Nodes) string default:stone,mcl_core:stone
+
+priv_bypass (PrivBypass) bool true
+
+fastdig (FastDig) bool false
+
+fastplace (FastPlace) bool false
+
+autodig (AutoDig) bool false
+
+autoplace (AutoPlace) bool false
+
+prevent_natural_damage (NoFallDamage) bool true
+
+freecam (Freecam) bool false
+
+no_hurt_cam (NoHurtCam) bool false
+
+hud_flags_bypass (HUDBypass) bool true
+
+antiknockback (AntiKnockback) bool false
+
+entity_speed (EntitySpeed) bool false
+
+jesus (Jesus) bool false
+
+instant_break (InstantBreak) bool false
+
+no_night (BrightNight) bool false
+
+coords (Coords) bool false
+
+point_liquids (PointLiquids) bool false
+
+spamclick (FastHit) bool false
+
+no_force_rotate (NoForceRotate) bool false
+
+no_slow (NoSlow) bool false
+
+cheat_hud (CheatHUD) bool true
+
+node_esp_nodes (NodeESP Nodes) string
+
+jetpack (JetPack) bool false
+
+autohit (AutoHit) bool false
+
+antislip (AntiSlip) bool false
+
+enable_entity_tracers (EntityTracers) bool false
+
+enable_entity_esp (EntityESP) bool false
+
+enable_player_tracers (PlayerTracers) bool false
+
+enable_player_esp (PlayerESP) bool false
+
+enable_node_esp (NodeESP) bool false
+
+enable_node_tracers (NodeTracers) bool false
+
+entity_esp_color (EntityESP Color) v3f 255, 255, 255
+
+player_esp_color (PlayerESP Color) v3f 0, 255, 0
+
+tool_range (Additional Tool Range) int 2
+
+reach (Reach) bool false
diff --git a/clientmods/mods_here.txt b/clientmods/mods_here.txt
new file mode 100644
index 000000000..ea2175f2d
--- /dev/null
+++ b/clientmods/mods_here.txt
@@ -0,0 +1,4 @@
+You can install Minetest or Dragonfire clientmods by copying (and extracting) them into this folder.
+To enable them write
+ load_mod_<modname> = true
+in mods.conf in this directory.
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 977ed0ec3..000000000
--- a/clientmods/preview/init.lua
+++ /dev/null
@@ -1,203 +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)
-
-core.register_on_chatcommand(function(command, params)
- print("[PREVIEW] caught command '"..command.."'. Parameters: '"..params.."'")
-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/doc/client_lua_api.txt b/doc/client_lua_api.txt
index 098596481..20ae5e9d5 100644
--- a/doc/client_lua_api.txt
+++ b/doc/client_lua_api.txt
@@ -86,9 +86,16 @@ Mod directory structure
clientmods
├── modname
│   ├── mod.conf
+ | ├── settingtypes.txt
│   ├── init.lua
└── another
+### `settingtypes.txt`
+
+The format is documented in `builtin/settingtypes.txt`.
+It is parsed by the main menu settings dialogue to list mod-specific
+settings in the "Clientmods" category.
+
### modname
The location of this directory.
@@ -212,7 +219,7 @@ For helper functions see "Vector helpers".
### pointed_thing
* `{type="nothing"}`
* `{type="node", under=pos, above=pos}`
-* `{type="object", id=ObjectID}`
+* `{type="object", ref=ClientObjectRef}`
Flag Specifier Format
---------------------
@@ -667,6 +674,9 @@ Minetest namespace reference
### Global callback registration functions
Call these functions only at load time!
+* `minetest.open_enderchest()`
+ * This function is called if the client uses the Keybind for it (by default "O")
+ * You can override it
* `minetest.register_globalstep(function(dtime))`
* Called every client environment step, usually interval of 0.1s
* `minetest.register_on_mods_loaded(function())`
@@ -686,6 +696,13 @@ Call these functions only at load time!
* Adds definition to minetest.registered_chatcommands
* `minetest.unregister_chatcommand(name)`
* Unregisters a chatcommands registered with register_chatcommand.
+* `minetest.register_list_command(command, desc, setting)`
+ * Registers a chatcommand `command` to manage a list that takes the args `del | add | list <param>`
+ * The list is stored comma-seperated in `setting`
+ * `desc` is the description
+ * `add` adds something to the list
+ * `del` del removes something from the list
+ * `list` lists all items on the list
* `minetest.register_on_chatcommand(function(command, params))`
* Called always when a chatcommand is triggered, before `minetest.registered_chatcommands`
is checked to see if that the command exists, but after the input is parsed.
@@ -734,6 +751,25 @@ Call these functions only at load time!
* Called when the local player open inventory
* Newest functions are called first
* If any function returns true, inventory doesn't open
+* `minetest.register_on_recieve_physics_override(function(override))`
+ * Called when recieving physics_override from server
+ * Newest functions are called first
+ * If any function returns true, the physics override does not change
+* `minetest.register_on_play_sound(function(SimpleSoundSpec))`
+ * Called when recieving a play sound command from server
+ * Newest functions are called first
+ * If any function returns true, the sound does not play
+* `minetest.register_on_spawn_partice(function(particle definition))`
+ * Called when recieving a spawn particle command from server
+ * Newest functions are called first
+ * If any function returns true, the particel does not spawn
+
+### Setting-related
+* `minetest.settings`: Settings object containing all of the settings from the
+ main config file (`minetest.conf`).
+* `minetest.setting_get_pos(name)`: Loads a setting from the main settings and
+ parses it as a position (in the format `(1,2,3)`). Returns a position or nil.
+
### Sounds
* `minetest.sound_play(spec, parameters)`: returns a handle
* `spec` is a `SimpleSoundSpec`
@@ -757,6 +793,20 @@ Call these functions only at load time!
* Returns the time of day: `0` for midnight, `0.5` for midday
### Map
+* `minetest.interact(action, pointed_thing)`
+ * Sends an interaction to the server
+ * `pointed_thing` is a pointed_thing
+ * `action` is one of
+ * "start_digging": Use to punch nodes / objects
+ * "stop_digging": Use to abort digging a "start_digging" command
+ * "digging_completed": Use to finish a "start_digging" command or dig a node instantly
+ * "place": Use to rightclick nodes and objects
+ * "use": Use to leftclick an item in air (pointed_thing.type is usually "nothing")
+ * "activate": Same as "use", but rightclick
+* `minetest.place_node(pos)`
+ * Places the wielded node/item of the player at pos.
+* `minetest.dig_node(pos)`
+ * Instantly digs the node at pos. This may fuck up with anticheat.
* `minetest.get_node_or_nil(pos)`
* Returns the node at the given position as table in the format
`{name="node_name", param1=0, param2=0}`, returns `nil`
@@ -773,6 +823,26 @@ Call these functions only at load time!
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
* `search_center` is an optional boolean (default: `false`)
If true `pos` is also checked for the nodes
+* `minetest.find_nodes_near(pos, radius, nodenames, [search_center])`: returns a
+ list of positions.
+ * `radius`: using a maximum metric
+ * `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
+ * `search_center` is an optional boolean (default: `false`)
+ If true `pos` is also checked for the nodes
+* `minetest.find_nodes_near_under_air(pos, radius, nodenames, [search_center])`: returns a
+ list of positions.
+ * `radius`: using a maximum metric
+ * `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
+ * `search_center` is an optional boolean (default: `false`)
+ If true `pos` is also checked for the nodes
+ * Return value: Table with all node positions with a node air above
+* `minetest.find_nodes_near_under_air_except(pos, radius, nodenames, [search_center])`: returns a
+ list of positions.
+ * `radius`: using a maximum metric
+ * `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`, specifies the nodes to be ignored
+ * `search_center` is an optional boolean (default: `false`)
+ If true `pos` is also checked for the nodes
+ * Return value: Table with all node positions with a node air above
* `minetest.find_nodes_in_area(pos1, pos2, nodenames, [grouped])`
* `pos1` and `pos2` are the min and max positions of the area to search.
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
@@ -800,7 +870,33 @@ Call these functions only at load time!
* `pos2`: end of the ray
* `objects`: if false, only nodes will be returned. Default is `true`.
* `liquids`: if false, liquid nodes won't be returned. Default is `false`.
-
+* `minetest.get_pointed_thing()` returns `PointedThing`
+ * Returns the thing currently pointed by player
+* `minetest.get_pointed_thing_position(pointed_thing, above)`
+ * Returns the position of a `pointed_thing` or `nil` if the `pointed_thing`
+ does not refer to a node or entity.
+ * If the optional `above` parameter is true and the `pointed_thing` refers
+ to a node, then it will return the `above` position of the `pointed_thing`.
+* `minetest.find_path(pos1,pos2,searchdistance,max_jump,max_drop,algorithm)`
+ * returns table containing path that can be walked on
+ * returns a table of 3D points representing a path from `pos1` to `pos2` or
+ `nil` on failure.
+ * Reasons for failure:
+ * No path exists at all
+ * No path exists within `searchdistance` (see below)
+ * Start or end pos is buried in land
+ * `pos1`: start position
+ * `pos2`: end position
+ * `searchdistance`: maximum distance from the search positions to search in.
+ In detail: Path must be completely inside a cuboid. The minimum
+ `searchdistance` of 1 will confine search between `pos1` and `pos2`.
+ Larger values will increase the size of this cuboid in all directions
+ * `max_jump`: maximum height difference to consider walkable
+ * `max_drop`: maximum height difference to consider droppable
+ * `algorithm`: One of `"A*_noprefetch"` (default), `"A*"`, `"Dijkstra"`.
+ Difference between `"A*"` and `"A*_noprefetch"` is that
+ `"A*"` will pre-calculate the cost-data, the other will calculate it
+ on-the-fly
* `minetest.find_nodes_with_meta(pos1, pos2)`
* Get a table of positions of nodes that have metadata within a region
{pos1, pos2}.
@@ -812,12 +908,16 @@ Call these functions only at load time!
* get max available level for leveled node
### Player
+* `minetest.send_damage(hp)`
+ * Sends fall damage to server
* `minetest.send_chat_message(message)`
* Act as if `message` was typed by the player into the terminal.
* `minetest.run_server_chatcommand(cmd, param)`
* Alias for `minetest.send_chat_message("/" .. cmd .. " " .. param)`
* `minetest.clear_out_chat_queue()`
* Clears the out chat queue
+* `minetest.drop_selected_item()`
+ * Drops the selected item
* `minetest.localplayer`
* Reference to the LocalPlayer object. See [`LocalPlayer`](#localplayer) class reference for methods.
@@ -831,6 +931,11 @@ Call these functions only at load time!
### Client Environment
* `minetest.get_player_names()`
* Returns list of player names on server (nil if CSM_RF_READ_PLAYERINFO is enabled by server)
+* `minetest.get_objects_inside_radius(pos, radius)`: returns a list of
+ ClientObjectRefs.
+ * `radius`: using an euclidean metric
+* `minetest.get_nearby_objects(radius)`
+ * alias for minetest.get_objects_inside_radius(minetest.localplayer:get_pos(), radius)
* `minetest.disconnect()`
* Disconnect from the server and exit to main menu.
* Returns `false` if the client is already disconnecting otherwise returns `true`.
@@ -839,6 +944,73 @@ Call these functions only at load time!
* `minetest.send_respawn()`
* Sends a respawn request to the server.
+### HTTP Requests
+
+* `minetest.get_http_api()`
+ * returns `HTTPApiTable` containing http functions.
+ * The returned table contains the functions `fetch_sync`, `fetch_async` and
+ `fetch_async_get` described below.
+ * Function only exists if minetest server was built with cURL support.
+* `HTTPApiTable.fetch_sync(HTTPRequest req)`: returns HTTPRequestResult
+ * Performs given request synchronously
+* `HTTPApiTable.fetch_async(HTTPRequest req)`: returns handle
+ * Performs given request asynchronously and returns handle for
+ `HTTPApiTable.fetch_async_get`
+* `HTTPApiTable.fetch_async_get(handle)`: returns HTTPRequestResult
+ * Return response data for given asynchronous HTTP request
+
+### `HTTPRequest` definition
+
+Used by `HTTPApiTable.fetch` and `HTTPApiTable.fetch_async`.
+
+ {
+ url = "http://example.org",
+
+ timeout = 10,
+ -- Timeout for connection in seconds. Default is 3 seconds.
+
+ post_data = "Raw POST request data string" OR {field1 = "data1", field2 = "data2"},
+ -- Optional, if specified a POST request with post_data is performed.
+ -- Accepts both a string and a table. If a table is specified, encodes
+ -- table as x-www-form-urlencoded key-value pairs.
+ -- If post_data is not specified, a GET request is performed instead.
+
+ user_agent = "ExampleUserAgent",
+ -- Optional, if specified replaces the default minetest user agent with
+ -- given string
+
+ extra_headers = { "Accept-Language: en-us", "Accept-Charset: utf-8" },
+ -- Optional, if specified adds additional headers to the HTTP request.
+ -- You must make sure that the header strings follow HTTP specification
+ -- ("Key: Value").
+
+ multipart = boolean
+ -- Optional, if true performs a multipart HTTP request.
+ -- Default is false.
+ }
+
+### `HTTPRequestResult` definition
+
+Passed to `HTTPApiTable.fetch` callback. Returned by
+`HTTPApiTable.fetch_async_get`.
+
+ {
+ completed = true,
+ -- If true, the request has finished (either succeeded, failed or timed
+ -- out)
+
+ succeeded = true,
+ -- If true, the request was successful
+
+ timeout = false,
+ -- If true, the request timed out
+
+ code = 200,
+ -- HTTP status code
+
+ data = "response"
+ }
+
### Storage API
* `minetest.get_mod_storage()`:
* returns reference to mod private `StorageRef`
@@ -862,7 +1034,27 @@ Call these functions only at load time!
* `minetest.delete_particlespawner(id)`
* Delete `ParticleSpawner` with `id` (return value from `minetest.add_particlespawner`)
-### Misc.
+### Misc
+* `minetest.set_keypress(key, value)`
+ * Act as if a key was pressed (value = true) / released (value = false)
+ * The key must be an keymap_* setting
+ * e.g. minetest.set_keypress("jump", true) will cause te player to jump until minetest.set_keypress("jump", false) is called or the player presses & releases the space bar himself
+* `minetest.get_inventory(location)`
+ * Returns the inventory at location
+* `minetest.find_item(item)`
+ * finds and an item in the inventory
+ * returns index on success or nil if item is not found
+* `minetest.switch_to_item(item)`
+ * `item` is an Itemstring
+ * searches to item in inventory, sets the wield index to it if found
+ * returns true on success, false if item was not found
+* `minetest.register_cheat(name, category, setting | function)`
+ * Register an entry for the cheat menu
+ * If the Category is nonexistant, it will be created
+ * If the 3rd argument is a string it will be interpreted as a setting and toggled
+ when the player selects the entry in the cheat menu
+ * If the 3rd argument is a function it will be called
+ when the player selects the entry in the cheat menu
* `minetest.parse_json(string[, nullvalue])`: returns something
* Convert a string containing JSON data into the Lua equivalent
* `nullvalue`: returned in place of the JSON null; defaults to `nil`
@@ -920,6 +1112,8 @@ Call these functions only at load time!
* returns the exact position on the surface of a pointed node
* `minetest.global_exists(name)`
* Checks if a global variable has been set, without triggering a warning.
+* `minetest.make_screenshot()`
+ * Triggers the MT makeScreenshot functionality
### UI
* `minetest.ui.minimap`
@@ -929,6 +1123,14 @@ Call these functions only at load time!
* Reference to the camera object. See [`Camera`](#camera) class reference for methods.
* `minetest.show_formspec(formname, formspec)` : returns true on success
* Shows a formspec to the player
+* `minetest.close_formspec(formname)`
+ * `formname`: has to exactly match the one given in `show_formspec`, or the
+ formspec will not close.
+ * calling `show_formspec(formname, "")` is equal to this
+ expression.
+ * to close a formspec regardless of the formname, call
+ `minetest.close_formspec("")`.
+ **USE THIS ONLY WHEN ABSOLUTELY NECESSARY!**
* `minetest.display_chat_message(message)` returns true on success
* Shows a chat message to the current player.
@@ -1007,14 +1209,28 @@ Methods:
* `get_pos()`
* returns current player current position
+* `set_pos(pos)`
+ * sets the position (anticheat may not like this)
+* `get_yaw()`
+ * returns the yaw (degrees)
+* `set_yaw(yaw)`
+ * sets the yaw (degrees)
+* `get_pitch()`
+ * returns the pitch (degrees)
+* `set_pitch(pitch)`
+ * sets the pitch (degrees)
* `get_velocity()`
* returns player speed vector
+* `set_velocity(vel)`
+ * sets player speed vector
* `get_hp()`
* returns player HP
* `get_name()`
* returns player name
* `get_wield_index()`
- * returns the index of the wielded item
+ * returns the index of the wielded item (starts at 1)
+* `set_wield_index()`
+ * sets the index (starts at 1)
* `get_wielded_item()`
* returns the itemstack the player is holding
* `is_attached()`
@@ -1045,6 +1261,17 @@ Methods:
}
```
+* `set_physics_override(override_table)`
+ * `override_table` is a table with the following fields:
+ * `speed`: multiplier to default walking speed value (default: `1`)
+ * `jump`: multiplier to default jump value (default: `1`)
+ * `gravity`: multiplier to default gravity value (default: `1`)
+ * `sneak`: whether player can sneak (default: `true`)
+ * `sneak_glitch`: whether player can use the new move code replications
+ of the old sneak side-effects: sneak ladders and 2 node sneak jump
+ (default: `false`)
+ * `new_move`: use new move/sneak code. When `false` the exact old code
+ is used for the specific old sneak behaviour (default: `true`)
* `get_override_pos()`
* returns override position
* `get_last_pos()`
@@ -1124,6 +1351,8 @@ Methods:
* change a value of a previously added HUD element
* element `stat` values: `position`, `name`, `scale`, `text`, `number`, `item`, `dir`
* Returns `true` on success, otherwise returns `nil`
+* `get_object()`
+ * Returns the ClientObjectRef for the player
### Settings
An interface to read config files in the format of `minetest.conf`.
@@ -1152,6 +1381,26 @@ Can be obtained via `minetest.get_meta(pos)`.
* `fields`: key-value storage
* `inventory`: `{list1 = {}, ...}}`
+### ClientObjectRef
+
+Moving things in the game are generally these.
+This is basically a reference to a C++ `GenericCAO`.
+
+#### Methods
+
+* `get_pos()`: returns `{x=num, y=num, z=num}`
+* `get_velocity()`: returns the velocity, a vector
+* `get_acceleration()`: returns the acceleration, a vector
+* `get_rotation()`: returns the rotation, a vector (radians)
+* `is_player()`: returns true if the object is a player
+* `is_local_player()`: returns true if the object is the local player
+* `get_attach()`: returns parent or nil if it isn't attached.
+* `get_nametag()`: returns the nametag (string)
+* `get_item_textures()`: returns the textures
+* `get_max_hp()`: returns the maximum heath
+* `punch()`: punches the object
+* `rightclick()`: rightclicks the object
+
### `Raycast`
A raycast on the map. It works with selection boxes.
@@ -1184,6 +1433,12 @@ It can be created via `Raycast(pos1, pos2, objects, liquids)` or
* Returns [node definition](#node-definition) table of `nodename`
* `minetest.get_item_def(itemstring)`
* Returns item definition table of `itemstring`
+* `minetest.override_item(itemstring, redefinition)`
+ * Overrides fields of an item registered with register_node/tool/craftitem.
+ * Note: Item must already be defined by the server
+ * Example: `minetest.override_item("default:mese",
+ {light_source=minetest.LIGHT_MAX})`
+ * Doesnt really work yet an causes strange bugs, I'm working to make is better
#### Node Definition
@@ -1325,6 +1580,8 @@ The following functions provide escape sequences:
`minetest.get_color_escape_sequence(color) ..
message ..
minetest.get_color_escape_sequence("#ffffff")`
+* `minetest.rainbow(message)`:
+ * Rainbow colorizes the message.
* `minetest.get_background_escape_sequence(color)`
* `color` is a [ColorString](#colorstring)
* The escape sequence sets the background of the whole text element to
@@ -1509,3 +1766,48 @@ Same as `image`, but does not accept a `position`; the position is instead deter
texture = "image.png",
-- ^ Uses texture (string)
}
+
+### InventoryAction
+A reference to a C++ InventoryAction. You can move, drop and craft items in all accessible inventories using InventoryActions.
+
+#### methods
+
+* `InventoryAction(type)`:
+ * creates a new InventoryAction
+ * type is on of "move", "drop", or "craft", else returns nil
+ * indexing starts at 1
+* `apply()`:
+ * applies the InventoryAction (InventoryActions can be applied multible times)
+* `from(inventorylocation, listname, stack)`
+ * this is valid for move or drop actions
+ * when `apply()` is called items are moved / dropped from `listname` `inventorylocation` in` at `stack`
+* `to(inventorylocation, listname, stack)`
+ * this is valid for move actions
+ * when `apply()` is called items are moved to `listname` in`inventorylocation` at `stack`
+* `craft(inventoryaction)`
+ * this is valid for craft actions
+ * when `apply()` is called a craft event for this inventory will be triggered
+* `set_count(count)`
+ * this is valid for all actions
+ * it specifies how many items to drop / craft / move
+ * `0` means move all items
+ * default count: `0`
+
+#### example
+ `local move_act = InventoryAction("move")
+ move_act:from("current_player", "main", 1)
+ move_act:to("current_player", "craft", 1)
+ move_act:set_count(1)
+ local craft_act = InventoryAction("craft")
+ craft_act:craft("current_player")
+ local drop_act = InventoryAction("drop")
+ drop_act:from("current_player", "craft_result",10)
+ move_act:apply()
+ craft_act:apply()
+ drop_act:apply()
+ `
+ * e.g. In first hotbar slot there are tree logs: Move one to craft field, then craft wood out of it and immediately drop it
+
+
+
+
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 7b7825614..ebfd03697 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -3109,6 +3109,8 @@ The following functions provide escape sequences:
`minetest.get_color_escape_sequence(color) ..
message ..
minetest.get_color_escape_sequence("#ffffff")`
+* `minetest.rainbow(message)`:
+ * Rainbow colorizes the message.
* `minetest.get_background_escape_sequence(color)`
* `color` is a ColorString
* The escape sequence sets the background of the whole text element to
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/games/devtest/mods/basetools/.sounds/default_grass_footstep.1.ogg b/games/devtest/mods/basetools/.sounds/default_grass_footstep.1.ogg
new file mode 100644
index 000000000..ce625d92b
--- /dev/null
+++ b/games/devtest/mods/basetools/.sounds/default_grass_footstep.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_break_glass.1.ogg b/games/devtest/mods/basetools/sounds/default_break_glass.1.ogg
new file mode 100644
index 000000000..b1ccc5fab
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_break_glass.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_break_glass.2.ogg b/games/devtest/mods/basetools/sounds/default_break_glass.2.ogg
new file mode 100644
index 000000000..b6cc9e85e
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_break_glass.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_break_glass.3.ogg b/games/devtest/mods/basetools/sounds/default_break_glass.3.ogg
new file mode 100644
index 000000000..ae6a6bfc4
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_break_glass.3.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_chest_close.ogg b/games/devtest/mods/basetools/sounds/default_chest_close.ogg
new file mode 100644
index 000000000..068d9002f
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_chest_close.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_chest_open.ogg b/games/devtest/mods/basetools/sounds/default_chest_open.ogg
new file mode 100644
index 000000000..40b0b9341
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_chest_open.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_cool_lava.1.ogg b/games/devtest/mods/basetools/sounds/default_cool_lava.1.ogg
new file mode 100644
index 000000000..42506ddff
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_cool_lava.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_cool_lava.2.ogg b/games/devtest/mods/basetools/sounds/default_cool_lava.2.ogg
new file mode 100644
index 000000000..2747ab81c
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_cool_lava.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_cool_lava.3.ogg b/games/devtest/mods/basetools/sounds/default_cool_lava.3.ogg
new file mode 100644
index 000000000..8baeac32e
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_cool_lava.3.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_dig_choppy.ogg b/games/devtest/mods/basetools/sounds/default_dig_choppy.ogg
new file mode 100644
index 000000000..e2ecd8416
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_dig_choppy.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_dig_cracky.ogg b/games/devtest/mods/basetools/sounds/default_dig_cracky.ogg
new file mode 100644
index 000000000..da1167916
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_dig_cracky.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_dig_crumbly.ogg b/games/devtest/mods/basetools/sounds/default_dig_crumbly.ogg
new file mode 100644
index 000000000..a0b2a1f9f
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_dig_crumbly.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_dig_dig_immediate.ogg b/games/devtest/mods/basetools/sounds/default_dig_dig_immediate.ogg
new file mode 100644
index 000000000..e65d766ee
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_dig_dig_immediate.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_dig_metal.ogg b/games/devtest/mods/basetools/sounds/default_dig_metal.ogg
new file mode 100644
index 000000000..0b585097a
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_dig_metal.ogg
Binary files differ
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
new file mode 100644
index 000000000..ef4d7b155
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_dig_oddly_breakable_by_hand.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_dig_snappy.ogg b/games/devtest/mods/basetools/sounds/default_dig_snappy.ogg
new file mode 100644
index 000000000..3686fcddb
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_dig_snappy.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_dirt_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_dirt_footstep.1.ogg
new file mode 100644
index 000000000..201aa3b2d
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_dirt_footstep.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_dirt_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_dirt_footstep.2.ogg
new file mode 100644
index 000000000..2667dbc21
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_dirt_footstep.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_dug_metal.1.ogg b/games/devtest/mods/basetools/sounds/default_dug_metal.1.ogg
new file mode 100644
index 000000000..5d6cb5b1e
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_dug_metal.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_dug_metal.2.ogg b/games/devtest/mods/basetools/sounds/default_dug_metal.2.ogg
new file mode 100644
index 000000000..63567fc05
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_dug_metal.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_dug_node.1.ogg b/games/devtest/mods/basetools/sounds/default_dug_node.1.ogg
new file mode 100644
index 000000000..c04975d42
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_dug_node.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_dug_node.2.ogg b/games/devtest/mods/basetools/sounds/default_dug_node.2.ogg
new file mode 100644
index 000000000..9f209268f
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_dug_node.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_glass_footstep.ogg b/games/devtest/mods/basetools/sounds/default_glass_footstep.ogg
new file mode 100644
index 000000000..191287a33
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_glass_footstep.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_grass_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_grass_footstep.2.ogg
new file mode 100644
index 000000000..d193068d2
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_grass_footstep.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_grass_footstep.3.ogg b/games/devtest/mods/basetools/sounds/default_grass_footstep.3.ogg
new file mode 100644
index 000000000..e1897ea38
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_grass_footstep.3.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_gravel_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_gravel_footstep.1.ogg
new file mode 100644
index 000000000..8d260ce01
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_gravel_footstep.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_gravel_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_gravel_footstep.2.ogg
new file mode 100644
index 000000000..2aba2c652
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_gravel_footstep.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_gravel_footstep.3.ogg b/games/devtest/mods/basetools/sounds/default_gravel_footstep.3.ogg
new file mode 100644
index 000000000..1bcd8a117
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_gravel_footstep.3.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_gravel_footstep.4.ogg b/games/devtest/mods/basetools/sounds/default_gravel_footstep.4.ogg
new file mode 100644
index 000000000..696c9ffd2
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_gravel_footstep.4.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_hard_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_hard_footstep.1.ogg
new file mode 100644
index 000000000..1748bc56a
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_hard_footstep.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_hard_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_hard_footstep.2.ogg
new file mode 100644
index 000000000..fe39fd784
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_hard_footstep.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_hard_footstep.3.ogg b/games/devtest/mods/basetools/sounds/default_hard_footstep.3.ogg
new file mode 100644
index 000000000..5030e0607
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_hard_footstep.3.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_item_smoke.ogg b/games/devtest/mods/basetools/sounds/default_item_smoke.ogg
new file mode 100644
index 000000000..038a46e4f
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_item_smoke.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_metal_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_metal_footstep.1.ogg
new file mode 100644
index 000000000..841286bdc
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_metal_footstep.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_metal_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_metal_footstep.2.ogg
new file mode 100644
index 000000000..aa61ed338
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_metal_footstep.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_metal_footstep.3.ogg b/games/devtest/mods/basetools/sounds/default_metal_footstep.3.ogg
new file mode 100644
index 000000000..4cc1ca47a
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_metal_footstep.3.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_place_node.1.ogg b/games/devtest/mods/basetools/sounds/default_place_node.1.ogg
new file mode 100644
index 000000000..46b9756de
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_place_node.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_place_node.2.ogg b/games/devtest/mods/basetools/sounds/default_place_node.2.ogg
new file mode 100644
index 000000000..d34c01a43
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_place_node.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_place_node.3.ogg b/games/devtest/mods/basetools/sounds/default_place_node.3.ogg
new file mode 100644
index 000000000..fc2936506
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_place_node.3.ogg
Binary files differ
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
new file mode 100644
index 000000000..9f97facad
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_place_node_hard.1.ogg
Binary files differ
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
new file mode 100644
index 000000000..1d3b3de2c
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_place_node_hard.2.ogg
Binary files differ
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
new file mode 100644
index 000000000..5da085ea2
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_place_node_metal.1.ogg
Binary files differ
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
new file mode 100644
index 000000000..5ee67fcf6
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_place_node_metal.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_sand_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_sand_footstep.1.ogg
new file mode 100644
index 000000000..65b68c7e6
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_sand_footstep.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_sand_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_sand_footstep.2.ogg
new file mode 100644
index 000000000..57f35f30a
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_sand_footstep.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_snow_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_snow_footstep.1.ogg
new file mode 100644
index 000000000..97cc8252e
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_snow_footstep.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_snow_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_snow_footstep.2.ogg
new file mode 100644
index 000000000..97a6baa48
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_snow_footstep.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_snow_footstep.3.ogg b/games/devtest/mods/basetools/sounds/default_snow_footstep.3.ogg
new file mode 100644
index 000000000..bde1f21d4
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_snow_footstep.3.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_snow_footstep.4.ogg b/games/devtest/mods/basetools/sounds/default_snow_footstep.4.ogg
new file mode 100644
index 000000000..8ca6a590d
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_snow_footstep.4.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_snow_footstep.5.ogg b/games/devtest/mods/basetools/sounds/default_snow_footstep.5.ogg
new file mode 100644
index 000000000..220d60c93
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_snow_footstep.5.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_tool_breaks.1.ogg b/games/devtest/mods/basetools/sounds/default_tool_breaks.1.ogg
new file mode 100644
index 000000000..2a571ae28
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_tool_breaks.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_tool_breaks.2.ogg b/games/devtest/mods/basetools/sounds/default_tool_breaks.2.ogg
new file mode 100644
index 000000000..178935205
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_tool_breaks.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_tool_breaks.3.ogg b/games/devtest/mods/basetools/sounds/default_tool_breaks.3.ogg
new file mode 100644
index 000000000..a99c4b7e3
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_tool_breaks.3.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_water_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_water_footstep.1.ogg
new file mode 100644
index 000000000..63b9744ce
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_water_footstep.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_water_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_water_footstep.2.ogg
new file mode 100644
index 000000000..8d79c1f4b
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_water_footstep.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_water_footstep.3.ogg b/games/devtest/mods/basetools/sounds/default_water_footstep.3.ogg
new file mode 100644
index 000000000..f8891506d
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_water_footstep.3.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_water_footstep.4.ogg b/games/devtest/mods/basetools/sounds/default_water_footstep.4.ogg
new file mode 100644
index 000000000..6f1eab824
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_water_footstep.4.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_wood_footstep.1.ogg b/games/devtest/mods/basetools/sounds/default_wood_footstep.1.ogg
new file mode 100644
index 000000000..34f63a17c
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_wood_footstep.1.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/default_wood_footstep.2.ogg b/games/devtest/mods/basetools/sounds/default_wood_footstep.2.ogg
new file mode 100644
index 000000000..124fc297c
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/default_wood_footstep.2.ogg
Binary files differ
diff --git a/games/devtest/mods/basetools/sounds/player_damage.ogg b/games/devtest/mods/basetools/sounds/player_damage.ogg
new file mode 100644
index 000000000..788808710
--- /dev/null
+++ b/games/devtest/mods/basetools/sounds/player_damage.ogg
Binary files differ
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
new file mode 100644
index 000000000..8edbaf637
--- /dev/null
+++ b/games/devtest/mods/player_api/models/character.b3d
Binary files differ
diff --git a/games/devtest/mods/player_api/models/character.blend b/games/devtest/mods/player_api/models/character.blend
new file mode 100644
index 000000000..f0ce4117f
--- /dev/null
+++ b/games/devtest/mods/player_api/models/character.blend
Binary files differ
diff --git a/games/devtest/mods/player_api/models/character.png b/games/devtest/mods/player_api/models/character.png
new file mode 100644
index 000000000..05021781e
--- /dev/null
+++ b/games/devtest/mods/player_api/models/character.png
Binary files differ
diff --git a/games/devtest/mods/player_api/textures/player.png b/games/devtest/mods/player_api/textures/player.png
new file mode 100644
index 000000000..6d61c4342
--- /dev/null
+++ b/games/devtest/mods/player_api/textures/player.png
Binary files differ
diff --git a/games/devtest/mods/player_api/textures/player_back.png b/games/devtest/mods/player_api/textures/player_back.png
new file mode 100644
index 000000000..5e9ef0542
--- /dev/null
+++ b/games/devtest/mods/player_api/textures/player_back.png
Binary files differ
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/misc/Info.plist b/misc/Info.plist
index 1498ee474..b80ae9d7c 100644
--- a/misc/Info.plist
+++ b/misc/Info.plist
@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>minetest</string>
<key>CFBundleIconFile</key>
- <string>minetest-icon.icns</string>
+ <string>dragonfire-icon.icns</string>
<key>CFBundleIdentifier</key>
<string>net.minetest.minetest</string>
</dict>
diff --git a/misc/dragonfire-icon-24x24.png b/misc/dragonfire-icon-24x24.png
new file mode 100644
index 000000000..0edc90e20
--- /dev/null
+++ b/misc/dragonfire-icon-24x24.png
Binary files differ
diff --git a/misc/dragonfire-icon.icns b/misc/dragonfire-icon.icns
new file mode 100644
index 000000000..bb20daf38
--- /dev/null
+++ b/misc/dragonfire-icon.icns
Binary files differ
diff --git a/misc/dragonfire-icon.ico b/misc/dragonfire-icon.ico
new file mode 100644
index 000000000..3ac1f5c81
--- /dev/null
+++ b/misc/dragonfire-icon.ico
Binary files differ
diff --git a/misc/dragonfire-icon.ico.png b/misc/dragonfire-icon.ico.png
new file mode 100644
index 000000000..6c04cf7ee
--- /dev/null
+++ b/misc/dragonfire-icon.ico.png
Binary files differ
diff --git a/misc/dragonfire-xorg-icon-128.png b/misc/dragonfire-xorg-icon-128.png
new file mode 100644
index 000000000..b1ed4522f
--- /dev/null
+++ b/misc/dragonfire-xorg-icon-128.png
Binary files differ
diff --git a/misc/dragonfire.svg b/misc/dragonfire.svg
new file mode 100644
index 000000000..350492649
--- /dev/null
+++ b/misc/dragonfire.svg
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="424.759mm"
+ height="548.14117mm"
+ viewBox="0 0 424.759 548.14117"
+ version="1.1"
+ id="svg8"
+ sodipodi:docname="dragonfire.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.49497475"
+ inkscape:cx="821.97201"
+ inkscape:cy="1504.5142"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer2"
+ inkscape:document-rotation="0"
+ showgrid="false"
+ inkscape:object-paths="false"
+ inkscape:snap-global="true"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1920"
+ inkscape:window-height="1009"
+ inkscape:window-x="0"
+ inkscape:window-y="42"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="Layer 2"
+ transform="translate(121.51509,140.87775)">
+ <path
+ style="fill:#d97c00;fill-opacity:1;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 174.63127,40.893641 c -0.62502,9.168773 -1.62909,25.023007 -18.75726,35.157567 -7.90853,4.679393 -14.88691,6.794713 -21.4562,10.084768 -10.0234,5.019952 -19.11206,10.735064 -29.23784,16.443334 L 92.551574,80.797555 162.67724,33.953338 Z"
+ id="path884"
+ sodipodi:nodetypes="csscccc" />
+ <path
+ style="fill:#d97b00;fill-opacity:1;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 185.29405,-52.901706 c 11.8624,-1.285468 24.94967,-4.400419 37.49354,-1.637969 12.24665,2.696994 31.53215,34.732889 51.00592,52.1769726 0,0 -16.21214,16.4095564 -26.41499,18.4986104 -13.0146,2.664766 -38.0854,-8.8161096 -38.0854,-8.8161096 z"
+ id="path892"
+ sodipodi:nodetypes="cscscc" />
+ <path
+ id="path894"
+ style="fill:#d97b00;fill-opacity:1;stroke:#000000;stroke-width:0.999999px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -237.29492,-365.62695 -102.4961,44.47656 c -39.64671,13.3036 -77.7993,9.74465 -114.99609,-4.59961 18.83278,64.6973 61.65447,80.70688 100.22461,105.34766 l 20.38281,12.67773 119.65821,-37.31055 z m 142.837889,330.521481 -181.515629,1.728516 c -12.82292,20.53197 -27.12291,45.236147 -34.40429,60.970703 25.65593,22.007697 51.66201,10.680981 82.19922,16.123047 z M -53.662109,97.027344 C -135.91186,164.51608 -191.67233,232.94647 -185.17578,306.11133 c 49.25913,-27.21072 79.87529,-71.5969 201.523436,-46.86719 L 261.88672,158.70312 Z"
+ transform="scale(0.26458333)" />
+ <path
+ id="path849"
+ style="fill:#f38a00;fill-opacity:1;stroke:#000000;stroke-width:0.99999899px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 568.43555,-526.07617 c -14.82346,21.59652 -10.36236,62.4642 -47.95452,70.79164 -3.38976,0.7509 -17.46828,-1.19108 -32.98408,0.43695 -18.84158,1.977 -40.48071,8.03189 -56.324,15.42617 -33.24391,15.51539 -77.8147,55.62913 -112.75465,72.95834 -32.78338,16.2596 -36.77134,9.79692 -48.67664,17.98947 -8.00352,5.50757 -21.67624,19.44462 -21.53854,37.67868 1.19409,158.11527 151.15589,21.69112 199.53516,71.1914 14.8786,15.22338 11.88459,36.39462 6.97461,54.90625 C 404.66662,3.9869356 162.60235,42.347074 56.927734,203.88477 3.9446038,284.87653 -80.069959,397.39278 -61.841797,492.44336 -35.456633,630.02852 99.783247,729.97044 214.32617,846.58984 c 64.00921,65.16957 141.98892,113.48363 192.04102,170.23046 63.76539,72.2944 92.82338,147.3005 105.11523,169.2305 56.96806,101.6371 -68.9819,229.5341 -152.16211,352.0234 89.58072,-40.6129 334.76613,-100.9267 345.77344,-313.8867 8.59476,-166.285 -117.78329,-338.01531 -312.1543,-489.22461 -77.20543,-60.0613 -109.34724,-150.31587 -82.55664,-230.82812 39.58416,-2.09715 78.27934,-10.6901 117.06836,-10.44141 69.69555,0.44689 149.1488,19.05746 219.20117,-15.58398 42.10833,-20.8229 71.05515,-89.9449 6.08008,-97.95508 C 576.02986,370.69838 530.2339,386.8415 437.13477,331.12891 481.58375,261.29772 638.13906,201.85117 826.60547,111.95703 872.12663,90.244477 883.77888,74.964433 937.43555,37.869141 991.28524,0.64040756 1075.7032,-65.93749 1138.916,-103.27734 c 9.0613,-29.61017 11.7554,-61.56671 -10.1523,-90.7793 -13.2778,-17.97641 -31.3708,-35.51132 -72.1446,-27.36328 -65.3167,125.783129 -225.8886,147.014404 -255.41012,115.72851 -32.2648,-34.19314 -63.32519,-85.26367 -98.67382,-146.27148 -28.74123,-49.60415 -74.03362,-99.10568 -102.28907,-160.50781 -16.09375,-34.97356 -24.38944,-78.9681 -31.81054,-113.60547 z m -72.97657,109.20898 c -14.47479,6.90263 -24.42683,17.72656 -35.82226,19.68946 -10.11164,1.74179 -10.15066,-1.10847 -12.14844,-4.88868 14.42018,-10.39842 30.98895,-13.31935 47.9707,-14.80078 z"
+ sodipodi:nodetypes="cssssssscssssscsscssscsscccsssccscc"
+ transform="scale(0.26458333)"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 75.771318,-72.60352 22.637085,-3.724836"
+ id="path902"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 78.31929,82.489785 c 12.057476,-2.128665 24.22843,-3.138178 37.33924,5.121331"
+ id="path886"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 172.90786,108.41166 c 3.79692,-2.83643 8.26351,1.6997 9.45928,4.49824"
+ id="path888"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 167.99805,114.53389 c 3.77662,-2.00305 9.73661,-1.26459 9.29324,7.24955"
+ id="path890"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 74.691115,-89.86943 3.585337,-2.090091"
+ id="path904" />
+ <path
+ style="display:inline;fill:#ff9100;fill-opacity:1;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -121.28811,-140.46489 c 30.230229,30.11602 37.182859,15.03379 76.840571,15.23187 12.764686,0.0638 33.640637,1.60284 54.652193,8.63798 18.309364,6.13039 36.913564,17.321485 47.885882,23.979967 42.623434,25.865762 74.689314,48.986152 74.294234,62.692517 C 131.61006,-3.0450289 46.340705,36.780877 32.944678,39.054476 -18.358314,47.761715 -52.033419,15.59799 -85.52309,71.851913 -93.677049,61.283562 -86.706295,31.892897 -59.723271,-1.1510784 -81.022343,-4.4118581 -102.93941,-9.3410193 -116.90663,-23.833561 c 3.12282,-13.93191 21.426823,-42.460615 50.349014,-47.510697 -12.667717,-12.219711 -43.351564,-17.767543 -54.730494,-69.120632 z"
+ id="path847"
+ sodipodi:nodetypes="csssssccccc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 173.65593,104.49243 c 3.47593,-2.78405 6.55751,-0.24685 8.31582,1.60947"
+ id="path908"
+ sodipodi:nodetypes="cc" />
+ </g>
+</svg>
diff --git a/misc/minetest-icon-24x24.png b/misc/minetest-icon-24x24.png
deleted file mode 100644
index 334e2f6d6..000000000
--- a/misc/minetest-icon-24x24.png
+++ /dev/null
Binary files differ
diff --git a/misc/minetest-icon.icns b/misc/minetest-icon.icns
deleted file mode 100644
index 14731c2c1..000000000
--- a/misc/minetest-icon.icns
+++ /dev/null
Binary files differ
diff --git a/misc/minetest-icon.ico b/misc/minetest-icon.ico
deleted file mode 100644
index 82af67bf9..000000000
--- a/misc/minetest-icon.ico
+++ /dev/null
Binary files differ
diff --git a/misc/minetest-xorg-icon-128.png b/misc/minetest-xorg-icon-128.png
deleted file mode 100644
index 0241a911c..000000000
--- a/misc/minetest-xorg-icon-128.png
+++ /dev/null
Binary files differ
diff --git a/misc/minetest.svg b/misc/minetest.svg
deleted file mode 100644
index fe036c3dd..000000000
--- a/misc/minetest.svg
+++ /dev/null
@@ -1,183 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="48px"
- height="48px"
- id="svg2856"
- version="1.1"
- inkscape:version="0.47 r22583"
- sodipodi:docname="minetest.svg"
- inkscape:export-filename="/home/erlehmann/pics/icons/minetest/minetest-icon-24x24.png"
- inkscape:export-xdpi="45"
- inkscape:export-ydpi="45">
- <defs
- id="defs2858">
- <filter
- inkscape:collect="always"
- id="filter3864">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.20490381"
- id="feGaussianBlur3866" />
- </filter>
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="12.083333"
- inkscape:cx="24"
- inkscape:cy="24"
- inkscape:current-layer="layer1"
- showgrid="false"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:window-width="1233"
- inkscape:window-height="755"
- inkscape:window-x="0"
- inkscape:window-y="25"
- inkscape:window-maximized="1">
- <inkscape:grid
- type="xygrid"
- id="grid2866"
- empspacing="2"
- visible="true"
- enabled="true"
- snapvisiblegridlinesonly="true"
- spacingx="0.5px"
- spacingy="10px"
- color="#ff0000"
- opacity="0.1254902"
- empcolor="#ff0000"
- empopacity="0.25098039"
- dotted="false" />
- <inkscape:grid
- type="axonomgrid"
- id="grid2870"
- units="px"
- empspacing="1"
- visible="true"
- enabled="true"
- snapvisiblegridlinesonly="true"
- spacingy="1px"
- originx="0px" />
- </sodipodi:namedview>
- <metadata
- id="metadata2861">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <path
- style="fill:#e9b96e;fill-opacity:1;stroke:#573a0d;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- d="M 6.1513775e-7,16 3.2110204e-7,28 21.035899,40.145082 l 21,-12.414519 0,-11.461126 L 20.78461,4 6.1513775e-7,16 z"
- id="path3047"
- transform="translate(3.4641013,6)"
- sodipodi:nodetypes="ccccccc" />
- <path
- style="fill:#2e3436;fill-opacity:1;stroke:#2e3436;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- d="m 8.5,30.907477 -2,-1.1547 0,6 L 17.320508,42 l 0,-2 -1.732051,-1 0,-2 L 13.5,35.794229 l 0,-4 -5,-2.886752 0,2 z"
- id="path3831"
- sodipodi:nodetypes="ccccccccccc" />
- <path
- style="opacity:1;fill:#555753;fill-opacity:1;stroke:#2e3436;stroke-linejoin:miter"
- d="m 6.9282032,36 3.4641018,-2 3.464101,2 1.643594,0.948929 0,2 2,1.154701 0,2 L 6.9282032,36 z"
- id="path3870"
- sodipodi:nodetypes="cccccccc" />
- <path
- style="fill:#fce94f;fill-opacity:1;stroke:#625802;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- d="M 25.980762,19 31.5,22.186533 l 0,2 L 38.09375,28 41.5625,26 45.5,23.730563 l 0,2.538874 0,-4 L 32.908965,15 25.980762,19 z"
- id="path3851"
- sodipodi:nodetypes="cccccccccc" />
- <path
- style="fill:#e9b96e;fill-opacity:1;stroke:#573a0d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.50000000000000000"
- d="m 24.839746,18.341234 8.660254,-5 0,2 -8.660254,5 0,-2 z"
- id="path5684"
- sodipodi:nodetypes="ccccc" />
- <path
- style="fill:#73d216;fill-opacity:1;stroke:#325b09;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- d="M 25.980762,5 3.4641016,18 17.5,26.10363 31.5,18.186533 24.839746,14.341234 33.5,9.341234 25.980762,5 z"
- id="path3821"
- sodipodi:nodetypes="ccccccc"
- transform="translate(0,4)" />
- <path
- style="fill:#729fcf;fill-opacity:1;stroke:#19314b;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- d="m 17.5,28.10363 0,2 1.552559,0.89637 0,2 5.447441,3.145082 12,-7.071797 0,-2.14657 2,-1.1547 0,-1.54403 -7,-4.041452 -14,7.917097 z"
- id="path3825"
- sodipodi:nodetypes="ccccccccccc"
- transform="translate(0,4)" />
- <g
- id="g5691"
- style="stroke-linejoin:miter">
- <path
- sodipodi:nodetypes="ccccc"
- id="path3862"
- d="m 13.856406,20 6.928204,4 -6.928204,4 -6.9282028,-4 6.9282028,-4 z"
- style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;filter:url(#filter3864);opacity:0.25000000000000000" />
- <g
- id="g3858"
- style="stroke-linejoin:miter">
- <path
- style="fill:#c17d11;fill-opacity:1;stroke:#8f5902;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- d="m 15.588457,21 1.732051,1 1.732051,-1 0,-6 -1.732051,-1 -1.732051,1 0,6 z"
- id="path3833"
- sodipodi:nodetypes="ccccccc"
- transform="translate(-3.4641015,2)" />
- <path
- style="fill:#4e9a06;fill-opacity:1;stroke:#316004;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- d="M 9.9641015,13.752777 17.320508,18 l 6.643593,-3.835681 0,-8.3286385 L 17.320508,2 9.9641015,6.2472233 l 0,7.5055537 z"
- id="path3837"
- transform="translate(-3.4641015,2)"
- sodipodi:nodetypes="ccccccc" />
- </g>
- </g>
- <g
- id="g5686"
- transform="translate(-4.2591582e-7,2)"
- style="stroke-linejoin:miter">
- <path
- transform="translate(24.248712,-2)"
- style="opacity:0.25000000000000000;fill:#2e3436;fill-opacity:1;stroke:none;filter:url(#filter3864);stroke-linejoin:miter"
- d="m 13.856406,20 5.196153,3 -5.196153,3 -5.196152,-3 5.196152,-3 z"
- id="path3868"
- sodipodi:nodetypes="ccccc" />
- <path
- style="fill:#4e9a06;fill-opacity:1;stroke:#316004;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
- d="M 15.71539,21.073285 17.320508,22 l 1.394882,-0.805336 0,-8.389328 L 17.320508,12 l -1.605118,1.073285 0,8 z"
- id="path3853"
- sodipodi:nodetypes="ccccccc"
- transform="translate(20.78461,0)" />
- </g>
- <path
- style="fill:none;fill-opacity:1;stroke:#ef2929;stroke-width:0.50000000000000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:0.50000000000000000, 0.50000000000000000;stroke-dashoffset:0.25000000000000000"
- d="M 12.124356,33 11.25833,32.5"
- id="path3872"
- sodipodi:nodetypes="cc" />
- <path
- style="fill:#888a85;stroke:#2e3436;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.50000000000000000"
- d="m 45.5,26.730563 -4,2.309401 0,1 -2,1.1547 0,2 -2,1.154701 0,4 8,-4.618802 0,-7 z"
- id="path3874"
- sodipodi:nodetypes="ccccccccc" />
- </g>
-</svg>
diff --git a/misc/net.minetest.minetest.appdata.xml b/misc/net.minetest.minetest.appdata.xml
index c177c3713..f41762564 100644
--- a/misc/net.minetest.minetest.appdata.xml
+++ b/misc/net.minetest.minetest.appdata.xml
@@ -62,6 +62,6 @@
<translation type="gettext">minetest</translation>
<update_contact>sfan5@live.de</update_contact>
<releases>
- <release date="2020-07-09" version="5.3.0"/>
+ <release date="2019-10-12" version="5.1.0"/>
</releases>
</component>
diff --git a/misc/net.minetest.minetest.desktop b/misc/net.minetest.minetest.desktop
index a94dbab1b..737dfb29e 100644..100755
--- a/misc/net.minetest.minetest.desktop
+++ b/misc/net.minetest.minetest.desktop
@@ -1,3 +1,4 @@
+#!/usr/bin/env xdg-open
[Desktop Entry]
Name=Minetest
GenericName=Minetest
@@ -9,9 +10,8 @@ Comment[ja]=マルãƒãƒ—レイã«å¯¾å¿œã—ãŸã€ç„¡é™ã®ä¸–界ã®ãƒ–ロックåž
Comment[ru]=Игра-пеÑочница Ñ Ð±ÐµÐ·Ð³Ñ€Ð°Ð½Ð¸Ñ‡Ð½Ñ‹Ð¼ миром, ÑоÑтоÑщим из блоков
Comment[tr]=Tek-Çok oyuncuyla küplerden sonsuz dünyalar inşa et
Exec=minetest
-Icon=minetest
+Icon=dragonfire
Terminal=false
-PrefersNonDefaultGPU=true
Type=Application
Categories=Game;Simulation;
StartupNotify=false
diff --git a/misc/winresource.rc b/misc/winresource.rc
index ffb493873..bd93be91d 100644
--- a/misc/winresource.rc
+++ b/misc/winresource.rc
@@ -1,8 +1,6 @@
#include <windows.h>
-#include <winuser.h>
#include <commctrl.h>
#include <richedit.h>
-
#ifndef USE_CMAKE_CONFIG_H
#define USE_CMAKE_CONFIG_H
#endif
@@ -15,12 +13,8 @@
#define BUILDMODE "RUN_IN_PLACE=0"
#endif
-#ifdef __MINGW32__
-CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "minetest.exe.manifest"
-#endif
-
LANGUAGE 0, SUBLANG_NEUTRAL
-130 ICON "minetest-icon.ico"
+130 ICON "dragonfire-icon.ico"
/////////////////////////////////////////////////////////////////////////////
//
diff --git a/po/lo/minetest.po b/po/lo/minetest.po
new file mode 100644
index 000000000..47bbaf3d9
--- /dev/null
+++ b/po/lo/minetest.po
@@ -0,0 +1,6394 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Lao (Minetest)\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-08-22 14:59+0200\n"
+"PO-Revision-Date: 2020-01-11 18:26+0000\n"
+"Last-Translator: rubenwardy <rubenwardy@gmail.com>\n"
+"Language-Team: Lao <https://hosted.weblate.org/projects/minetest/minetest/lo/"
+">\n"
+"Language: lo\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Weblate 3.10.1\n"
+
+#: builtin/fstk/dialog.lua builtin/fstk/ui.lua src/gui/modalMenu.cpp
+msgid "OK"
+msgstr ""
+
+#: builtin/fstk/ui.lua
+msgid "An error occurred in a Lua script:"
+msgstr ""
+
+#: builtin/fstk/ui.lua
+msgid "An error occurred:"
+msgstr ""
+
+#: builtin/fstk/ui.lua
+msgid "Main menu"
+msgstr ""
+
+#: builtin/fstk/ui.lua
+msgid "Reconnect"
+msgstr ""
+
+#: builtin/fstk/ui.lua
+msgid "The server has requested a reconnect:"
+msgstr ""
+
+#: builtin/mainmenu/common.lua src/client/game.cpp
+msgid "Loading..."
+msgstr ""
+
+#: builtin/mainmenu/common.lua
+msgid "Protocol version mismatch. "
+msgstr ""
+
+#: builtin/mainmenu/common.lua
+msgid "Server enforces protocol version $1. "
+msgstr ""
+
+#: builtin/mainmenu/common.lua
+msgid "Server supports protocol versions between $1 and $2. "
+msgstr ""
+
+#: builtin/mainmenu/common.lua
+msgid "Try reenabling public serverlist and check your internet connection."
+msgstr ""
+
+#: builtin/mainmenu/common.lua
+msgid "We only support protocol version $1."
+msgstr ""
+
+#: builtin/mainmenu/common.lua
+msgid "We support protocol versions between version $1 and $2."
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua builtin/mainmenu/dlg_create_world.lua
+#: builtin/mainmenu/dlg_delete_content.lua
+#: builtin/mainmenu/dlg_delete_world.lua
+#: builtin/mainmenu/dlg_rename_modpack.lua
+#: builtin/mainmenu/dlg_settings_advanced.lua src/client/keycode.cpp
+#: src/gui/guiConfirmRegistration.cpp src/gui/guiKeyChangeMenu.cpp
+#: src/gui/guiPasswordChange.cpp
+msgid "Cancel"
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua builtin/mainmenu/tab_content.lua
+msgid "Dependencies:"
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+msgid "Disable all"
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+msgid "Disable modpack"
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+msgid "Enable all"
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+msgid "Enable modpack"
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+msgid ""
+"Failed to enable mod \"$1\" as it contains disallowed characters. Only "
+"characters [a-z0-9_] are allowed."
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+msgid "Find More Mods"
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+msgid "Mod:"
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+msgid "No (optional) dependencies"
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+msgid "No game description provided."
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+msgid "No hard dependencies"
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+msgid "No modpack description provided."
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+msgid "No optional dependencies"
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua builtin/mainmenu/tab_content.lua
+msgid "Optional dependencies:"
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+#: builtin/mainmenu/dlg_settings_advanced.lua src/gui/guiKeyChangeMenu.cpp
+msgid "Save"
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+msgid "World:"
+msgstr ""
+
+#: builtin/mainmenu/dlg_config_world.lua
+msgid "enabled"
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+msgid "All packages"
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+msgid "Back to Main Menu"
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+msgid "ContentDB is not available when Minetest was compiled without cURL"
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+msgid "Downloading..."
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+msgid "Failed to download $1"
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Games"
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+msgid "Install"
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Mods"
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+msgid "No packages could be retrieved"
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+msgid "No results"
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+#: builtin/mainmenu/dlg_settings_advanced.lua builtin/mainmenu/tab_online.lua
+msgid "Search"
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+msgid "Texture packs"
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+msgid "Uninstall"
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+msgid "Update"
+msgstr ""
+
+#: builtin/mainmenu/dlg_contentstore.lua
+msgid "View"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "A world named \"$1\" already exists"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Additional terrain"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua src/settings_translation_file.cpp
+msgid "Altitude chill"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Altitude dry"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Biome blending"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Biomes"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Caverns"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Caves"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Create"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Decorations"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Download a game, such as Minetest Game, from minetest.net"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Download one from minetest.net"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Dungeons"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Flat terrain"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Floating landmasses in the sky"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Floatlands (experimental)"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua src/settings_translation_file.cpp
+msgid "Game"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Generate non-fractal terrain: Oceans and underground"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Hills"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Humid rivers"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Increases humidity around rivers"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Lakes"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Low humidity and high heat causes shallow or dry rivers"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua src/settings_translation_file.cpp
+msgid "Mapgen"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua src/settings_translation_file.cpp
+msgid "Mapgen flags"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Mapgen-specific flags"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Mountains"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Mud flow"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Network of tunnels and caves"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "No game selected"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Reduces heat with altitude"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Reduces humidity with altitude"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Rivers"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Sea level rivers"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Seed"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Smooth transition between biomes"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid ""
+"Structures appearing on the terrain (no effect on trees and jungle grass "
+"created by v6)"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Structures appearing on the terrain, typically trees and plants"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Temperate, Desert"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Temperate, Desert, Jungle"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Temperate, Desert, Jungle, Tundra, Taiga"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Terrain surface erosion"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Trees and jungle grass"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Vary river depth"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Very large caverns deep in the underground"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "Warning: The Development Test is meant for developers."
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "World name"
+msgstr ""
+
+#: builtin/mainmenu/dlg_create_world.lua
+msgid "You have no games installed."
+msgstr ""
+
+#: builtin/mainmenu/dlg_delete_content.lua
+msgid "Are you sure you want to delete \"$1\"?"
+msgstr ""
+
+#: builtin/mainmenu/dlg_delete_content.lua
+#: builtin/mainmenu/dlg_delete_world.lua builtin/mainmenu/tab_local.lua
+#: src/client/keycode.cpp
+msgid "Delete"
+msgstr ""
+
+#: builtin/mainmenu/dlg_delete_content.lua
+msgid "pkgmgr: failed to delete \"$1\""
+msgstr ""
+
+#: builtin/mainmenu/dlg_delete_content.lua
+msgid "pkgmgr: invalid path \"$1\""
+msgstr ""
+
+#: builtin/mainmenu/dlg_delete_world.lua
+msgid "Delete World \"$1\"?"
+msgstr ""
+
+#: builtin/mainmenu/dlg_rename_modpack.lua
+msgid "Accept"
+msgstr ""
+
+#: builtin/mainmenu/dlg_rename_modpack.lua
+msgid "Rename Modpack:"
+msgstr ""
+
+#: builtin/mainmenu/dlg_rename_modpack.lua
+msgid ""
+"This modpack has an explicit name given in its modpack.conf which will "
+"override any renaming here."
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "(No description of setting given)"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "2D Noise"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "< Back to Settings page"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Browse"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Clientmods"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Disabled"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Edit"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Enabled"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Lacunarity"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Octaves"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua src/settings_translation_file.cpp
+msgid "Offset"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Persistance"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Please enter a valid integer."
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Please enter a valid number."
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Restore Default"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua src/settings_translation_file.cpp
+msgid "Scale"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Select directory"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Select file"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Show technical names"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "The value must be at least $1."
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "The value must not be larger than $1."
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "X"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "X spread"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Y"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Y spread"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Z"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Z spread"
+msgstr ""
+
+#. ~ "absvalue" is a noise parameter flag.
+#. It is short for "absolute value".
+#. It can be enabled in noise settings in
+#. main menu -> "All Settings".
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "absvalue"
+msgstr ""
+
+#. ~ "defaults" is a noise parameter flag.
+#. It describes the default processing options
+#. for noise settings in main menu -> "All Settings".
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "defaults"
+msgstr ""
+
+#. ~ "eased" is a noise parameter flag.
+#. It is used to make the map smoother and
+#. can be enabled in noise settings in
+#. main menu -> "All Settings".
+#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "eased"
+msgstr ""
+
+#: builtin/mainmenu/pkgmgr.lua
+msgid "$1 (Enabled)"
+msgstr ""
+
+#: builtin/mainmenu/pkgmgr.lua
+msgid "$1 mods"
+msgstr ""
+
+#: builtin/mainmenu/pkgmgr.lua
+msgid "Failed to install $1 to $2"
+msgstr ""
+
+#: builtin/mainmenu/pkgmgr.lua
+msgid "Install Mod: Unable to find real mod name for: $1"
+msgstr ""
+
+#: builtin/mainmenu/pkgmgr.lua
+msgid "Install Mod: Unable to find suitable folder name for modpack $1"
+msgstr ""
+
+#: builtin/mainmenu/pkgmgr.lua
+msgid "Install: Unsupported file type \"$1\" or broken archive"
+msgstr ""
+
+#: builtin/mainmenu/pkgmgr.lua
+msgid "Install: file: \"$1\""
+msgstr ""
+
+#: builtin/mainmenu/pkgmgr.lua
+msgid "Unable to find a valid mod or modpack"
+msgstr ""
+
+#: builtin/mainmenu/pkgmgr.lua
+msgid "Unable to install a $1 as a texture pack"
+msgstr ""
+
+#: builtin/mainmenu/pkgmgr.lua
+msgid "Unable to install a game as a $1"
+msgstr ""
+
+#: builtin/mainmenu/pkgmgr.lua
+msgid "Unable to install a mod as a $1"
+msgstr ""
+
+#: builtin/mainmenu/pkgmgr.lua
+msgid "Unable to install a modpack as a $1"
+msgstr ""
+
+#: builtin/mainmenu/tab_content.lua
+msgid "Browse online content"
+msgstr ""
+
+#: builtin/mainmenu/tab_content.lua
+msgid "Content"
+msgstr ""
+
+#: builtin/mainmenu/tab_content.lua
+msgid "Disable Texture Pack"
+msgstr ""
+
+#: builtin/mainmenu/tab_content.lua
+msgid "Information:"
+msgstr ""
+
+#: builtin/mainmenu/tab_content.lua
+msgid "Installed Packages:"
+msgstr ""
+
+#: builtin/mainmenu/tab_content.lua
+msgid "No dependencies."
+msgstr ""
+
+#: builtin/mainmenu/tab_content.lua
+msgid "No package description available"
+msgstr ""
+
+#: builtin/mainmenu/tab_content.lua
+msgid "Rename"
+msgstr ""
+
+#: builtin/mainmenu/tab_content.lua
+msgid "Uninstall Package"
+msgstr ""
+
+#: builtin/mainmenu/tab_content.lua
+msgid "Use Texture Pack"
+msgstr ""
+
+#: builtin/mainmenu/tab_credits.lua
+msgid "Active Contributors"
+msgstr ""
+
+#: builtin/mainmenu/tab_credits.lua
+msgid "Core Developers"
+msgstr ""
+
+#: builtin/mainmenu/tab_credits.lua
+msgid "Credits"
+msgstr ""
+
+#: builtin/mainmenu/tab_credits.lua
+msgid "Hackers"
+msgstr ""
+
+#: builtin/mainmenu/tab_credits.lua
+msgid "Previous Contributors"
+msgstr ""
+
+#: builtin/mainmenu/tab_credits.lua
+msgid "Previous Core Developers"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua
+msgid "Announce Server"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua
+msgid "Bind Address"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua
+msgid "Configure"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua builtin/mainmenu/tab_simple_main.lua
+msgid "Creative Mode"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua builtin/mainmenu/tab_simple_main.lua
+msgid "Enable Damage"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua
+msgid "Host Game"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua
+msgid "Host Server"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua
+msgid "Install games from ContentDB"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua
+msgid "Name/Password"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua
+msgid "New"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua
+msgid "No world created or selected!"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua
+msgid "Play Game"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua
+msgid "Port"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua
+msgid "Select World:"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua
+msgid "Server Port"
+msgstr ""
+
+#: builtin/mainmenu/tab_local.lua
+msgid "Start Game"
+msgstr ""
+
+#: builtin/mainmenu/tab_online.lua
+msgid "Address / Port"
+msgstr ""
+
+#: builtin/mainmenu/tab_online.lua builtin/mainmenu/tab_simple_main.lua
+msgid "Connect"
+msgstr ""
+
+#: builtin/mainmenu/tab_online.lua builtin/mainmenu/tab_simple_main.lua
+msgid "Creative mode"
+msgstr ""
+
+#: builtin/mainmenu/tab_online.lua builtin/mainmenu/tab_simple_main.lua
+msgid "Damage enabled"
+msgstr ""
+
+#: builtin/mainmenu/tab_online.lua builtin/mainmenu/tab_simple_main.lua
+msgid "Del. Favorite"
+msgstr ""
+
+#: builtin/mainmenu/tab_online.lua builtin/mainmenu/tab_simple_main.lua
+msgid "Favorite"
+msgstr ""
+
+#: builtin/mainmenu/tab_online.lua
+msgid "Join Game"
+msgstr ""
+
+#: builtin/mainmenu/tab_online.lua builtin/mainmenu/tab_simple_main.lua
+msgid "Name / Password"
+msgstr ""
+
+#: builtin/mainmenu/tab_online.lua builtin/mainmenu/tab_simple_main.lua
+msgid "Ping"
+msgstr ""
+
+#. ~ PvP = Player versus Player
+#: builtin/mainmenu/tab_online.lua builtin/mainmenu/tab_simple_main.lua
+msgid "PvP enabled"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "2x"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "3D Clouds"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "4x"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "8x"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "All Settings"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Antialiasing:"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Are you sure to reset your singleplayer world?"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Autosave Screen Size"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Bilinear Filter"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Bump Mapping"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua src/client/game.cpp
+msgid "Change Keys"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Connected Glass"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Fancy Leaves"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Generate Normal Maps"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Mipmap"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Mipmap + Aniso. Filter"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "No"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "No Filter"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "No Mipmap"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Node Highlighting"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Node Outlining"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "None"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Opaque Leaves"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Opaque Water"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua src/settings_translation_file.cpp
+msgid "Parallax Occlusion"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Particles"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Reset singleplayer world"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Screen:"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Settings"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua src/settings_translation_file.cpp
+msgid "Shaders"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Shaders (unavailable)"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Simple Leaves"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Smooth Lighting"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Texturing:"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "To enable shaders the OpenGL driver needs to be used."
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua src/settings_translation_file.cpp
+msgid "Tone Mapping"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Touchthreshold: (px)"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Trilinear Filter"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Waving Leaves"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Waving Liquids"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Waving Plants"
+msgstr ""
+
+#: builtin/mainmenu/tab_settings.lua
+msgid "Yes"
+msgstr ""
+
+#: builtin/mainmenu/tab_simple_main.lua
+msgid "Config mods"
+msgstr ""
+
+#: builtin/mainmenu/tab_simple_main.lua
+msgid "Main"
+msgstr ""
+
+#: builtin/mainmenu/tab_simple_main.lua
+msgid "Start Singleplayer"
+msgstr ""
+
+#: src/client/client.cpp
+msgid "Connection timed out."
+msgstr ""
+
+#: src/client/client.cpp
+msgid "Done!"
+msgstr ""
+
+#: src/client/client.cpp
+msgid "Initializing nodes"
+msgstr ""
+
+#: src/client/client.cpp
+msgid "Initializing nodes..."
+msgstr ""
+
+#: src/client/client.cpp
+msgid "Loading textures..."
+msgstr ""
+
+#: src/client/client.cpp
+msgid "Rebuilding shaders..."
+msgstr ""
+
+#: src/client/clientlauncher.cpp
+msgid "Connection error (timed out?)"
+msgstr ""
+
+#: src/client/clientlauncher.cpp
+msgid "Could not find or load game \""
+msgstr ""
+
+#: src/client/clientlauncher.cpp
+msgid "Invalid gamespec."
+msgstr ""
+
+#: src/client/clientlauncher.cpp
+msgid "Main Menu"
+msgstr ""
+
+#: src/client/clientlauncher.cpp
+msgid "No world selected and no address provided. Nothing to do."
+msgstr ""
+
+#: src/client/clientlauncher.cpp
+msgid "Player name too long."
+msgstr ""
+
+#: src/client/clientlauncher.cpp
+msgid "Please choose a name!"
+msgstr ""
+
+#: src/client/clientlauncher.cpp
+msgid "Provided password file failed to open: "
+msgstr ""
+
+#: src/client/clientlauncher.cpp
+msgid "Provided world path doesn't exist: "
+msgstr ""
+
+#. ~ DO NOT TRANSLATE THIS LITERALLY!
+#. This is a special string. Put either "no" or "yes"
+#. into the translation field (literally).
+#. Choose "yes" if the language requires use of the fallback
+#. font, "no" otherwise.
+#. The fallback font is (normally) required for languages with
+#. non-Latin script, like Chinese.
+#. When in doubt, test your translation.
+#: src/client/fontengine.cpp
+msgid "needs_fallback_font"
+msgstr "yes"
+
+#: src/client/game.cpp
+msgid ""
+"\n"
+"Check debug.txt for details."
+msgstr ""
+
+#: src/client/game.cpp
+msgid "- Address: "
+msgstr ""
+
+#: src/client/game.cpp
+msgid "- Creative Mode: "
+msgstr ""
+
+#: src/client/game.cpp
+msgid "- Damage: "
+msgstr ""
+
+#: src/client/game.cpp
+msgid "- Mode: "
+msgstr ""
+
+#: src/client/game.cpp
+msgid "- Port: "
+msgstr ""
+
+#: src/client/game.cpp
+msgid "- Public: "
+msgstr ""
+
+#. ~ PvP = Player versus Player
+#: src/client/game.cpp
+msgid "- PvP: "
+msgstr ""
+
+#: src/client/game.cpp
+msgid "- Server Name: "
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Automatic forward disabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Automatic forward enabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Camera update disabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Camera update enabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Change Password"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Cinematic mode disabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Cinematic mode enabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Client side scripting is disabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Connecting to server..."
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Continue"
+msgstr ""
+
+#: src/client/game.cpp
+#, c-format
+msgid ""
+"Controls:\n"
+"- %s: move forwards\n"
+"- %s: move backwards\n"
+"- %s: move left\n"
+"- %s: move right\n"
+"- %s: jump/climb\n"
+"- %s: sneak/go down\n"
+"- %s: drop item\n"
+"- %s: inventory\n"
+"- %s: special inventory\n"
+"- Mouse: turn/look\n"
+"- Mouse left: dig/punch\n"
+"- Mouse right: place/use\n"
+"- Mouse wheel: select item\n"
+"- %s: chat\n"
+"- %s: Killaura\n"
+"- %s: Freecam\n"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Creating client..."
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Creating server..."
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Debug info and profiler graph hidden"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Debug info shown"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Debug info, profiler graph, and wireframe hidden"
+msgstr ""
+
+#: src/client/game.cpp
+msgid ""
+"Default Controls:\n"
+"No menu visible:\n"
+"- single tap: button activate\n"
+"- double tap: place/use\n"
+"- slide finger: look around\n"
+"Menu/Inventory visible:\n"
+"- double tap (outside):\n"
+" -->close\n"
+"- touch stack, touch slot:\n"
+" --> move stack\n"
+"- touch&drag, tap 2nd finger\n"
+" --> place single item to slot\n"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Disabled unlimited viewing range"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Enabled unlimited viewing range"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Exit to Menu"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Exit to OS"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Fast mode disabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Fast mode enabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Fast mode enabled (note: no 'fast' privilege)"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Fly mode disabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Fly mode enabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Fly mode enabled (note: no 'fly' privilege)"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Fog disabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Fog enabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Freecam disabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Freecam enabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Game info:"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Game paused"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Hosting server"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Item definitions..."
+msgstr ""
+
+#: src/client/game.cpp
+msgid "KiB/s"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Killaura disabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Killaura enabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Media..."
+msgstr ""
+
+#: src/client/game.cpp
+msgid "MiB/s"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Minimap currently disabled by game or mod"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Minimap hidden"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Minimap in radar mode, Zoom x1"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Minimap in radar mode, Zoom x2"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Minimap in radar mode, Zoom x4"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Minimap in surface mode, Zoom x1"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Minimap in surface mode, Zoom x2"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Minimap in surface mode, Zoom x4"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Noclip mode disabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Noclip mode enabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Noclip mode enabled (note: no 'noclip' privilege)"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Node definitions..."
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Off"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "On"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Pitch move mode disabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Pitch move mode enabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Profiler graph shown"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Remote server"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Resolving address..."
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Respawn"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Shutting down..."
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Singleplayer"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Sound Volume"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Sound muted"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Sound system is disabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Sound system is not supported on this build"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Sound unmuted"
+msgstr ""
+
+#: src/client/game.cpp
+#, c-format
+msgid "Viewing range changed to %d"
+msgstr ""
+
+#: src/client/game.cpp
+#, c-format
+msgid "Viewing range is at maximum: %d"
+msgstr ""
+
+#: src/client/game.cpp
+#, c-format
+msgid "Viewing range is at minimum: %d"
+msgstr ""
+
+#: src/client/game.cpp
+#, c-format
+msgid "Volume changed to %d%%"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Wireframe shown"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "You died"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Zoom currently disabled by game or mod"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "ok"
+msgstr ""
+
+#: src/client/gameui.cpp
+msgid "Chat hidden"
+msgstr ""
+
+#: src/client/gameui.cpp
+msgid "Chat shown"
+msgstr ""
+
+#: src/client/gameui.cpp
+msgid "Cheat Menu hidden"
+msgstr ""
+
+#: src/client/gameui.cpp
+msgid "Cheat Menu shown"
+msgstr ""
+
+#: src/client/gameui.cpp
+msgid "HUD hidden"
+msgstr ""
+
+#: src/client/gameui.cpp
+msgid "HUD shown"
+msgstr ""
+
+#: src/client/gameui.cpp
+msgid "Profiler hidden"
+msgstr ""
+
+#: src/client/gameui.cpp
+#, c-format
+msgid "Profiler shown (page %d of %d)"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Apps"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Backspace"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Caps Lock"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Clear"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Control"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Down"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "End"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Erase EOF"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Execute"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Help"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Home"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "IME Accept"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "IME Convert"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "IME Escape"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "IME Mode Change"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "IME Nonconvert"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Insert"
+msgstr ""
+
+#: src/client/keycode.cpp src/gui/guiKeyChangeMenu.cpp
+msgid "Left"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Left Button"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Left Control"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Left Menu"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Left Shift"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Left Windows"
+msgstr ""
+
+#. ~ Key name, common on Windows keyboards
+#: src/client/keycode.cpp
+msgid "Menu"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Middle Button"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Num Lock"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad *"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad +"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad -"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad ."
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad /"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad 0"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad 1"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad 2"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad 3"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad 4"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad 5"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad 6"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad 7"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad 8"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Numpad 9"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "OEM Clear"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Page down"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Page up"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Pause"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Play"
+msgstr ""
+
+#. ~ "Print screen" key
+#: src/client/keycode.cpp
+msgid "Print"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Return"
+msgstr ""
+
+#: src/client/keycode.cpp src/gui/guiKeyChangeMenu.cpp
+msgid "Right"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Right Button"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Right Control"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Right Menu"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Right Shift"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Right Windows"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Scroll Lock"
+msgstr ""
+
+#. ~ Key name
+#: src/client/keycode.cpp
+msgid "Select"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Shift"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Sleep"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Snapshot"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Space"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Tab"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "Up"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "X Button 1"
+msgstr ""
+
+#: src/client/keycode.cpp
+msgid "X Button 2"
+msgstr ""
+
+#: src/client/keycode.cpp src/gui/guiKeyChangeMenu.cpp
+msgid "Zoom"
+msgstr ""
+
+#: src/gui/guiConfirmRegistration.cpp src/gui/guiPasswordChange.cpp
+msgid "Passwords do not match!"
+msgstr ""
+
+#: src/gui/guiConfirmRegistration.cpp
+msgid "Register and Join"
+msgstr ""
+
+#: src/gui/guiConfirmRegistration.cpp
+#, c-format
+msgid ""
+"You are about to join this server with the name \"%s\" for the first time.\n"
+"If you proceed, a new account using your credentials will be created on this "
+"server.\n"
+"Please retype your password and click 'Register and Join' to confirm account "
+"creation, or click 'Cancel' to abort."
+msgstr ""
+
+#: src/gui/guiFormSpecMenu.cpp
+msgid "Proceed"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "\"Special\" = climb down"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Autoforward"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp src/settings_translation_file.cpp
+msgid "Automatic jumping"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Backward"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "C. Menu Down"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "C. Menu Enter"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "C. Menu Left"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "C. Menu Right"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "C. Menu Up"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Change camera"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Chat"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Command"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Console"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Dec. range"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Dec. volume"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Double tap \"jump\" to toggle fly"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Drop"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Forward"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Inc. range"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Inc. volume"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Inventory"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Jump"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Key already in use"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Local command"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Mute"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Next item"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Prev. item"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Range select"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp src/settings_translation_file.cpp
+msgid "Screenshot"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Sneak"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Special"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Special Inv."
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Toggle C. Menu"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Toggle Freec."
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Toggle HUD"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Toggle Killaura"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Toggle chat log"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Toggle fast"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Toggle fly"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Toggle fog"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Toggle minimap"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Toggle noclip"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Toggle pitchmove"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "press key"
+msgstr ""
+
+#: src/gui/guiPasswordChange.cpp
+msgid "Change"
+msgstr ""
+
+#: src/gui/guiPasswordChange.cpp
+msgid "Confirm Password"
+msgstr ""
+
+#: src/gui/guiPasswordChange.cpp
+msgid "New Password"
+msgstr ""
+
+#: src/gui/guiPasswordChange.cpp
+msgid "Old Password"
+msgstr ""
+
+#: src/gui/guiVolumeChange.cpp
+msgid "Exit"
+msgstr ""
+
+#: src/gui/guiVolumeChange.cpp
+msgid "Muted"
+msgstr ""
+
+#: src/gui/guiVolumeChange.cpp
+msgid "Sound Volume: "
+msgstr ""
+
+#. ~ Imperative, as in "Enter/type in text".
+#. Don't forget the space.
+#: src/gui/modalMenu.cpp
+msgid "Enter "
+msgstr ""
+
+#. ~ DO NOT TRANSLATE THIS LITERALLY!
+#. This is a special string which needs to contain the translation's
+#. language code (e.g. "de" for German).
+#: src/network/clientpackethandler.cpp src/script/lua_api/l_client.cpp
+msgid "LANG_CODE"
+msgstr "lo"
+
+#: src/settings_translation_file.cpp
+msgid ""
+"(Android) Fixes the position of virtual joystick.\n"
+"If disabled, virtual joystick will center to first-touch's position."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"(Android) Use virtual joystick to trigger \"aux\" button.\n"
+"If enabled, virtual joystick will also tap \"aux\" button when out of main "
+"circle."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"(X,Y,Z) offset of fractal from world center in units of 'scale'.\n"
+"Can be used to move a desired point to (0, 0) to create a\n"
+"suitable spawn point, or to allow 'zooming in' on a desired\n"
+"point by increasing 'scale'.\n"
+"The default is tuned for a suitable spawn point for Mandelbrot\n"
+"sets with default parameters, it may need altering in other\n"
+"situations.\n"
+"Range roughly -2 to 2. Multiply by 'scale' for offset in nodes."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"(X,Y,Z) scale of fractal in nodes.\n"
+"Actual fractal size will be 2 to 3 times larger.\n"
+"These numbers can be made very large, the fractal does\n"
+"not have to fit inside the world.\n"
+"Increase these to 'zoom' into the detail of the fractal.\n"
+"Default is for a vertically-squashed shape suitable for\n"
+"an island, set all 3 numbers equal for the raw shape."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"0 = parallax occlusion with slope information (faster).\n"
+"1 = relief mapping (slower, more accurate)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "2D noise that controls the shape/size of ridged mountains."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "2D noise that controls the shape/size of rolling hills."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "2D noise that controls the shape/size of step mountains."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "2D noise that controls the size/occurrence of ridged mountain ranges."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "2D noise that controls the size/occurrence of rolling hills."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "2D noise that controls the size/occurrence of step mountain ranges."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "2D noise that locates the river valleys and channels."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "3D clouds"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "3D mode"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "3D mode parallax strength"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "3D noise defining giant caverns."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"3D noise defining mountain structure and height.\n"
+"Also defines structure of floatland mountain terrain."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"3D noise defining structure of floatlands.\n"
+"If altered from the default, the noise 'scale' (0.7 by default) may need\n"
+"to be adjusted, as floatland tapering functions best when this noise has\n"
+"a value range of approximately -2.0 to 2.0."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "3D noise defining structure of river canyon walls."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "3D noise defining terrain."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "3D noise for mountain overhangs, cliffs, etc. Usually small variations."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "3D noise that determines number of dungeons per mapchunk."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"3D support.\n"
+"Currently supported:\n"
+"- none: no 3d output.\n"
+"- anaglyph: cyan/magenta color 3d.\n"
+"- interlaced: odd/even line based polarisation screen support.\n"
+"- topbottom: split screen top/bottom.\n"
+"- sidebyside: split screen side by side.\n"
+"- crossview: Cross-eyed 3d\n"
+"- pageflip: quadbuffer based 3d.\n"
+"Note that the interlaced mode requires shaders to be enabled."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"A chosen map seed for a new map, leave empty for random.\n"
+"Will be overridden when creating a new world in the main menu."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "A message to be displayed to all clients when the server crashes."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "A message to be displayed to all clients when the server shuts down."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "ABM interval"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Absolute limit of queued blocks to emerge"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Acceleration in air"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Acceleration of gravity, in nodes per second per second."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Active Block Modifiers"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Active block management interval"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Active block range"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Active object send range"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Address to connect to.\n"
+"Leave this blank to start a local server.\n"
+"Note that the address field in the main menu overrides this setting."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Adds particles when digging a node."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Adjust dpi configuration to your screen (non X11/Android only) e.g. for 4k "
+"screens."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+#, c-format
+msgid ""
+"Adjusts the density of the floatland layer.\n"
+"Increase value to increase density. Can be positive or negative.\n"
+"Value = 0.0: 50% of volume is floatland.\n"
+"Value = 2.0 (can be higher depending on 'mgv7_np_floatland', always test\n"
+"to be sure) creates a solid floatland layer."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Advanced"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Alters the light curve by applying 'gamma correction' to it.\n"
+"Higher values make middle and lower light levels brighter.\n"
+"Value '1.0' leaves the light curve unaltered.\n"
+"This only has significant effect on daylight and artificial\n"
+"light, it has very little effect on natural night light."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Always fly and fast"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Ambient occlusion gamma"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Amount of messages a player may send per 10 seconds."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Amplifies the valleys."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Anisotropic filtering"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Announce server"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Announce to this serverlist."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Append item name"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Append item name to tooltip."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Apple trees noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Arm inertia"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Arm inertia, gives a more realistic movement of\n"
+"the arm when the camera moves."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Ask to reconnect after crash"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"At this distance the server will aggressively optimize which blocks are sent "
+"to\n"
+"clients.\n"
+"Small values potentially improve performance a lot, at the expense of "
+"visible\n"
+"rendering glitches (some blocks will not be rendered under water and in "
+"caves,\n"
+"as well as sometimes on land).\n"
+"Setting this to a value greater than max_block_send_distance disables this\n"
+"optimization.\n"
+"Stated in mapblocks (16 nodes)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Automatic forward key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Automatically jump up single-node obstacles."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Automatically report to the serverlist."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Autosave screen size"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Autoscaling mode"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Backward key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Base ground level"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Base terrain height."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Basic"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Basic privileges"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Beach noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Beach noise threshold"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Bilinear filtering"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Bind address"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Biome API temperature and humidity noise parameters"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Biome noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Bits per pixel (aka color depth) in fullscreen mode."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Block send optimize distance"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Bold and italic font path"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Bold and italic monospace font path"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Bold font path"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Bold monospace font path"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Build inside player"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Builtin"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Bumpmapping"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Camera 'near clipping plane' distance in nodes, between 0 and 0.25\n"
+"Only works on GLES platforms. Most users will not need to change this.\n"
+"Increasing can reduce artifacting on weaker GPUs.\n"
+"0.1 = Default, 0.25 = Good value for weaker tablets."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Camera smoothing"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Camera smoothing in cinematic mode"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Camera update toggle key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Cave noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Cave noise #1"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Cave noise #2"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Cave width"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Cave1 noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Cave2 noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Cavern limit"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Cavern noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Cavern taper"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Cavern threshold"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Cavern upper limit"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Center of light curve boost range.\n"
+"Where 0.0 is minimum light level, 1.0 is maximum light level."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Changes the main menu UI:\n"
+"- Full: Multiple singleplayer worlds, game choice, texture pack chooser, "
+"etc.\n"
+"- Simple: One singleplayer world, no game or texture pack choosers. May "
+"be\n"
+"necessary for smaller screens."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Chat font size"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Chat key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Chat log level"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Chat message count limit"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Chat message format"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Chat message kick threshold"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Chat message max length"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Chat toggle key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Chatcommands"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Chunk size"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Cinematic mode"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Cinematic mode key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Clean transparent textures"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Client"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Client and Server"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Client modding"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Client side modding restrictions"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Client side node lookup range restriction"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Climbing speed"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Cloud radius"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Clouds"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Clouds are a client side effect."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Clouds in menu"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Colored fog"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Comma-separated list of flags to hide in the content repository.\n"
+"\"nonfree\" can be used to hide packages which do not qualify as 'free "
+"software',\n"
+"as defined by the Free Software Foundation.\n"
+"You can also specify content ratings.\n"
+"These flags are independent from Minetest versions,\n"
+"so see a full list at https://content.minetest.net/help/content_flags/"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Comma-separated list of mods that are allowed to access HTTP APIs, which\n"
+"allow them to upload and download data to/from the internet."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Comma-separated list of trusted mods that are allowed to access insecure\n"
+"functions even when mod security is on (via request_insecure_environment())."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Command key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Connect glass"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Connect to external media server"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Connects glass if supported by node."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Console alpha"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Console color"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Console height"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "ContentDB Flag Blacklist"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "ContentDB URL"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Continuous forward"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Continuous forward movement, toggled by autoforward key.\n"
+"Press the autoforward key again or the backwards movement to disable."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Controls"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Controls length of day/night cycle.\n"
+"Examples:\n"
+"72 = 20min, 360 = 4min, 1 = 24hour, 0 = day/night/whatever stays unchanged."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Controls sinking speed in liquid."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Controls steepness/depth of lake depressions."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Controls steepness/height of hills."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Controls width of tunnels, a smaller value creates wider tunnels.\n"
+"Value >= 10.0 completely disables generation of tunnels and avoids the\n"
+"intensive noise calculations."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Crash message"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Creative"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Crosshair alpha"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Crosshair alpha (opaqueness, between 0 and 255)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Crosshair color"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Crosshair color (R,G,B)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "DPI"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Damage"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Debug info toggle key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Debug log file size threshold"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Debug log level"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Dec. volume key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Decrease this to increase liquid resistance to movement."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Dedicated server step"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Default acceleration"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Default game"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Default game when creating a new world.\n"
+"This will be overridden when creating a world from the main menu."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Default password"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Default privileges"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Default report format"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Default stack size"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Default timeout for cURL, stated in milliseconds.\n"
+"Only has an effect if compiled with cURL."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Defines areas where trees have apples."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Defines areas with sandy beaches."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Defines distribution of higher terrain and steepness of cliffs."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Defines distribution of higher terrain."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Defines full size of caverns, smaller values create larger caverns."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Defines large-scale river channel structure."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Defines location and terrain of optional hills and lakes."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Defines sampling step of texture.\n"
+"A higher value results in smoother normal maps."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Defines the base ground level."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Defines the depth of the river channel."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Defines the maximal player transfer distance in blocks (0 = unlimited)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Defines the width of the river channel."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Defines the width of the river valley."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Defines tree areas and tree density."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Delay between mesh updates on the client in ms. Increasing this will slow\n"
+"down the rate of mesh updates, thus reducing jitter on slower clients."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Delay in sending blocks after building"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Delay showing tooltips, stated in milliseconds."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Deprecated Lua API handling"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Depth below which you'll find giant caverns."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Depth below which you'll find large caves."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Description of server, to be displayed when players join and in the "
+"serverlist."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Desert noise threshold"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Deserts occur when np_biome exceeds this value.\n"
+"When the 'snowbiomes' flag is enabled, this is ignored."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Desynchronize block animation"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Digging particles"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Disable anticheat"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Disallow empty passwords"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Domain name of server, to be displayed in the serverlist."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Double tap jump for fly"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Double-tapping the jump key toggles fly mode."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Drop item key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Dump the mapgen debug information."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Dungeon maximum Y"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Dungeon minimum Y"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Dungeon noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Enable IPv6 support (for both client and server).\n"
+"Required for IPv6 connections to work at all."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Enable Lua modding support on client.\n"
+"This support is experimental and API can change."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Enable console window"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Enable creative mode for new created maps."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Enable joysticks"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Enable mod channels support."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Enable mod security"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Enable players getting damage and dying."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Enable random user input (only used for testing)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Enable register confirmation"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Enable register confirmation when connecting to server.\n"
+"If disabled, new account will be registered automatically."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Enable smooth lighting with simple ambient occlusion.\n"
+"Disable for speed or for different looks."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Enable to disallow old clients from connecting.\n"
+"Older clients are compatible in the sense that they will not crash when "
+"connecting\n"
+"to new servers, but they may not support all new features that you are "
+"expecting."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Enable usage of remote media server (if provided by server).\n"
+"Remote servers offer a significantly faster way to download media (e.g. "
+"textures)\n"
+"when connecting to the server."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Enable vertex buffer objects.\n"
+"This should greatly improve graphics performance."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Enable view bobbing and amount of view bobbing.\n"
+"For example: 0 for no view bobbing; 1.0 for normal; 2.0 for double."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Enable/disable running an IPv6 server.\n"
+"Ignored if bind_address is set.\n"
+"Needs enable_ipv6 to be enabled."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Enables Hable's 'Uncharted 2' filmic tone mapping.\n"
+"Simulates the tone curve of photographic film and how this approximates the\n"
+"appearance of high dynamic range images. Mid-range contrast is slightly\n"
+"enhanced, highlights and shadows are gradually compressed."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Enables animation of inventory items."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Enables bumpmapping for textures. Normalmaps need to be supplied by the "
+"texture pack\n"
+"or need to be auto-generated.\n"
+"Requires shaders to be enabled."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Enables caching of facedir rotated meshes."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Enables minimap."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Enables on the fly normalmap generation (Emboss effect).\n"
+"Requires bumpmapping to be enabled."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Enables parallax occlusion mapping.\n"
+"Requires shaders to be enabled."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Enables the sound system.\n"
+"If disabled, this completely disables all sounds everywhere and the in-game\n"
+"sound controls will be non-functional.\n"
+"Changing this setting requires a restart."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Engine profiling data print interval"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Entity methods"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Experimental option, might cause visible spaces between blocks\n"
+"when set to higher number than 0."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Exponent of the floatland tapering. Alters the tapering behaviour.\n"
+"Value = 1.0 creates a uniform, linear tapering.\n"
+"Values > 1.0 create a smooth tapering suitable for the default separated\n"
+"floatlands.\n"
+"Values < 1.0 (for example 0.25) create a more defined surface level with\n"
+"flatter lowlands, suitable for a solid floatland layer."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "FPS in pause menu"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "FSAA"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Factor noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fall bobbing factor"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fallback font path"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fallback font shadow"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fallback font shadow alpha"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fallback font size"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fast key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fast mode acceleration"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fast mode speed"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fast movement"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Fast movement (via the \"special\" key).\n"
+"This requires the \"fast\" privilege on the server."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Field of view"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Field of view in degrees."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"File in client/serverlist/ that contains your favorite servers displayed in "
+"the\n"
+"Multiplayer Tab."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Filler depth"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Filler depth noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Filmic tone mapping"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Filtered textures can blend RGB values with fully-transparent neighbors,\n"
+"which PNG optimizers usually discard, sometimes resulting in a dark or\n"
+"light edge to transparent textures. Apply this filter to clean that up\n"
+"at texture load time."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Filtering"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "First of 4 2D noises that together define hill/mountain range height."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "First of two 3D noises that together define tunnels."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fixed map seed"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fixed virtual joystick"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Floatland density"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Floatland maximum Y"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Floatland minimum Y"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Floatland noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Floatland taper exponent"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Floatland tapering distance"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Floatland water level"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fly key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Flying"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fog"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fog start"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fog toggle key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Font bold by default"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Font italic by default"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Font shadow"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Font shadow alpha"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Font size"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Font size of the default font in point (pt)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Font size of the fallback font in point (pt)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Font size of the monospace font in point (pt)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Font size of the recent chat text and chat prompt in point (pt).\n"
+"Value 0 will use the default font size."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Format of player chat messages. The following strings are valid "
+"placeholders:\n"
+"@name, @message, @timestamp (optional)"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Format of screenshots."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Formspec Default Background Color"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Formspec Default Background Opacity"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Formspec Full-Screen Background Color"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Formspec Full-Screen Background Opacity"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Formspec default background color (R,G,B)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Formspec default background opacity (between 0 and 255)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Formspec full-screen background color (R,G,B)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Formspec full-screen background opacity (between 0 and 255)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Forward key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fourth of 4 2D noises that together define hill/mountain range height."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fractal type"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fraction of the visible distance at which fog starts to be rendered"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "FreeType fonts"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"From how far blocks are generated for clients, stated in mapblocks (16 "
+"nodes)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"From how far blocks are sent to clients, stated in mapblocks (16 nodes)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"From how far clients know about objects, stated in mapblocks (16 nodes).\n"
+"\n"
+"Setting this larger than active_block_range will also cause the server\n"
+"to maintain active objects up to this distance in the direction the\n"
+"player is looking. (This can avoid mobs suddenly disappearing from view)"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Full screen"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Full screen BPP"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Fullscreen mode."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "GUI scaling"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "GUI scaling filter"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "GUI scaling filter txr2img"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Generate normalmaps"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Global callbacks"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Global map generation attributes.\n"
+"In Mapgen v6 the 'decorations' flag controls all decorations except trees\n"
+"and junglegrass, in all other mapgens this flag controls all decorations."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Gradient of light curve at maximum light level.\n"
+"Controls the contrast of the highest light levels."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Gradient of light curve at minimum light level.\n"
+"Controls the contrast of the lowest light levels."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Graphics"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Gravity"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Ground level"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Ground noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "HTTP mods"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "HUD scale factor"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "HUD toggle key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Handling for deprecated Lua API calls:\n"
+"- legacy: (try to) mimic old behaviour (default for release).\n"
+"- log: mimic and log backtrace of deprecated call (default for debug).\n"
+"- error: abort on usage of deprecated call (suggested for mod developers)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Have the profiler instrument itself:\n"
+"* Instrument an empty function.\n"
+"This estimates the overhead, that instrumentation is adding (+1 function "
+"call).\n"
+"* Instrument the sampler being used to update the statistics."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Heat blend noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Heat noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Height component of the initial window size."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Height noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Height select noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "High-precision FPU"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hill steepness"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hill threshold"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hilliness1 noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hilliness2 noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hilliness3 noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hilliness4 noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Homepage of server, to be displayed in the serverlist."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Horizontal acceleration in air when jumping or falling,\n"
+"in nodes per second per second."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Horizontal and vertical acceleration in fast mode,\n"
+"in nodes per second per second."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Horizontal and vertical acceleration on ground or when climbing,\n"
+"in nodes per second per second."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar next key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar previous key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 1 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 10 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 11 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 12 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 13 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 14 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 15 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 16 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 17 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 18 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 19 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 2 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 20 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 21 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 22 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 23 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 24 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 25 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 26 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 27 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 28 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 29 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 3 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 30 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 31 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 32 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 4 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 5 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 6 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 7 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 8 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Hotbar slot 9 key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "How deep to make rivers."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"How fast liquid waves will move. Higher = faster.\n"
+"If negative, liquid waves will move backwards.\n"
+"Requires waving liquids to be enabled."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"How much the server will wait before unloading unused mapblocks.\n"
+"Higher value is smoother, but will use more RAM."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "How wide to make rivers."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Humidity blend noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Humidity noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Humidity variation for biomes."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "IPv6"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "IPv6 server"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"If FPS would go higher than this, limit it by sleeping\n"
+"to not waste CPU power for no benefit."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"If disabled, \"special\" key is used to fly fast if both fly and fast mode "
+"are\n"
+"enabled."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"If enabled the server will perform map block occlusion culling based on\n"
+"on the eye position of the player. This can reduce the number of blocks\n"
+"sent to the client 50-80%. The client will not longer receive most "
+"invisible\n"
+"so that the utility of noclip mode is reduced."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"If enabled together with fly mode, player is able to fly through solid "
+"nodes.\n"
+"This requires the \"noclip\" privilege on the server."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"If enabled, \"special\" key instead of \"sneak\" key is used for climbing "
+"down and\n"
+"descending."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"If enabled, actions are recorded for rollback.\n"
+"This option is only read when server starts."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "If enabled, disable cheat prevention in multiplayer."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"If enabled, invalid world data won't cause the server to shut down.\n"
+"Only enable this if you know what you are doing."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"If enabled, makes move directions relative to the player's pitch when flying "
+"or swimming."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "If enabled, new players cannot join with an empty password."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"If enabled, you can place blocks at the position (feet + eye level) where "
+"you stand.\n"
+"This is helpful when working with nodeboxes in small areas."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"If the CSM restriction for node range is enabled, get_node calls are "
+"limited\n"
+"to this distance from the player to the node."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"If the file size of debug.txt exceeds the number of megabytes specified in\n"
+"this setting when it is opened, the file is moved to debug.txt.1,\n"
+"deleting an older debug.txt.1 if it exists.\n"
+"debug.txt is only moved if this setting is positive."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "If this is set, players will always (re)spawn at the given position."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Ignore world errors"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "In-Game"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "In-game chat console background alpha (opaqueness, between 0 and 255)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "In-game chat console background color (R,G,B)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "In-game chat console height, between 0.1 (10%) and 1.0 (100%)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Inc. volume key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Initial vertical speed when jumping, in nodes per second."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Instrument builtin.\n"
+"This is usually only needed by core/builtin contributors"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Instrument chatcommands on registration."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Instrument global callback functions on registration.\n"
+"(anything you pass to a minetest.register_*() function)"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Instrument the action function of Active Block Modifiers on registration."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Instrument the action function of Loading Block Modifiers on registration."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Instrument the methods of entities on registration."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Instrumentation"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Interval of saving important changes in the world, stated in seconds."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Interval of sending time of day to clients."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Inventory items animations"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Inventory key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Invert mouse"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Invert vertical mouse movement."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Italic font path"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Italic monospace font path"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Item entity TTL"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Iterations"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Iterations of the recursive function.\n"
+"Increasing this increases the amount of fine detail, but also\n"
+"increases processing load.\n"
+"At iterations = 20 this mapgen has a similar load to mapgen V7."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Joystick ID"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Joystick button repetition interval"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Joystick frustum sensitivity"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Joystick type"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Julia set only.\n"
+"W component of hypercomplex constant.\n"
+"Alters the shape of the fractal.\n"
+"Has no effect on 3D fractals.\n"
+"Range roughly -2 to 2."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Julia set only.\n"
+"X component of hypercomplex constant.\n"
+"Alters the shape of the fractal.\n"
+"Range roughly -2 to 2."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Julia set only.\n"
+"Y component of hypercomplex constant.\n"
+"Alters the shape of the fractal.\n"
+"Range roughly -2 to 2."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Julia set only.\n"
+"Z component of hypercomplex constant.\n"
+"Alters the shape of the fractal.\n"
+"Range roughly -2 to 2."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Julia w"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Julia x"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Julia y"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Julia z"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Jump key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Jumping speed"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for decreasing the viewing range.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for decreasing the volume.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for dropping the currently selected item.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for increasing the viewing range.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for increasing the volume.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for jumping.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for moving fast in fast mode.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for moving the player backward.\n"
+"Will also disable autoforward, when active.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for moving the player forward.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for moving the player left.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for moving the player right.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for muting the game.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for opening the chat window to type commands.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for opening the chat window to type local commands.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for opening the chat window.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for opening the inventory.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 11th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 12th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 13th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 14th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 15th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 16th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 17th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 18th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 19th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 20th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 21st hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 22nd hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 23rd hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 24th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 25th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 26th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 27th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 28th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 29th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 30th hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 31st hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the 32nd hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the eighth hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the fifth hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the first hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the fourth hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the next item in the hotbar.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the ninth hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the previous item in the hotbar.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the second hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the seventh hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the sixth hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the tenth hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for selecting the third hotbar slot.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for sneaking.\n"
+"Also used for climbing down and descending in water if aux1_descends is "
+"disabled.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for switching between first- and third-person camera.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for taking screenshots.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling autoforward.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling cinematic mode.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling display of minimap.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling fast mode.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling flying.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling noclip mode.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling pitch move mode.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling the camera update. Only used for development\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling the display of chat.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling the display of debug info.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling the display of fog.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling the display of the HUD.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling the display of the large chat console.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling the display of the profiler. Used for development.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key for toggling unlimited view range.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Key to use view zoom when possible.\n"
+"See http://irrlicht.sourceforge.net/docu/namespaceirr."
+"html#a54da2a0e231901735e3da1b0edf72eb3"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Kick players who sent more than X messages per 10 seconds."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Lake steepness"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Lake threshold"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Language"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Large cave depth"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Large cave maximum number"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Large cave minimum number"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Large cave proportion flooded"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Large chat console key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Leaves style"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Leaves style:\n"
+"- Fancy: all faces visible\n"
+"- Simple: only outer faces, if defined special_tiles are used\n"
+"- Opaque: disable transparency"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Left key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Length of a server tick and the interval at which objects are generally "
+"updated over\n"
+"network."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Length of liquid waves.\n"
+"Requires waving liquids to be enabled."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Length of time between Active Block Modifier (ABM) execution cycles"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Length of time between NodeTimer execution cycles"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Length of time between active block management cycles"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Level of logging to be written to debug.txt:\n"
+"- <nothing> (no logging)\n"
+"- none (messages with no level)\n"
+"- error\n"
+"- warning\n"
+"- action\n"
+"- info\n"
+"- verbose"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Light curve boost"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Light curve boost center"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Light curve boost spread"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Light curve gamma"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Light curve high gradient"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Light curve low gradient"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Limit of map generation, in nodes, in all 6 directions from (0, 0, 0).\n"
+"Only mapchunks completely within the mapgen limit are generated.\n"
+"Value is stored per-world."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Limits number of parallel HTTP requests. Affects:\n"
+"- Media fetch if server uses remote_media setting.\n"
+"- Serverlist download and server announcement.\n"
+"- Downloads performed by main menu (e.g. mod manager).\n"
+"Only has an effect if compiled with cURL."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Liquid fluidity"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Liquid fluidity smoothing"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Liquid loop max"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Liquid queue purge time"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Liquid sinking"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Liquid update interval in seconds."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Liquid update tick"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Load the game profiler"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Load the game profiler to collect game profiling data.\n"
+"Provides a /profiler command to access the compiled profile.\n"
+"Useful for mod developers and server operators."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Loading Block Modifiers"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Lower Y limit of dungeons."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Lower Y limit of floatlands."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Main menu script"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Main menu style"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Make fog and sky colors depend on daytime (dawn/sunset) and view direction."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Makes DirectX work with LuaJIT. Disable if it causes troubles."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Makes all liquids opaque"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Map directory"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Map generation attributes specific to Mapgen Carpathian."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Map generation attributes specific to Mapgen Flat.\n"
+"Occasional lakes and hills can be added to the flat world."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Map generation attributes specific to Mapgen Fractal.\n"
+"'terrain' enables the generation of non-fractal terrain:\n"
+"ocean, islands and underground."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Map generation attributes specific to Mapgen Valleys.\n"
+"'altitude_chill': Reduces heat with altitude.\n"
+"'humid_rivers': Increases humidity around rivers.\n"
+"'vary_river_depth': If enabled, low humidity and high heat causes rivers\n"
+"to become shallower and occasionally dry.\n"
+"'altitude_dry': Reduces humidity with altitude."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Map generation attributes specific to Mapgen v5."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Map generation attributes specific to Mapgen v6.\n"
+"The 'snowbiomes' flag enables the new 5 biome system.\n"
+"When the 'snowbiomes' flag is enabled jungles are automatically enabled and\n"
+"the 'jungles' flag is ignored."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Map generation attributes specific to Mapgen v7.\n"
+"'ridges': Rivers.\n"
+"'floatlands': Floating land masses in the atmosphere.\n"
+"'caverns': Giant caves deep underground."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Map generation limit"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Map save interval"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapblock limit"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapblock mesh generation delay"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapblock mesh generator's MapBlock cache size in MB"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapblock unload timeout"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen Carpathian"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen Carpathian specific flags"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen Flat"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen Flat specific flags"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen Fractal"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen Fractal specific flags"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen V5"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen V5 specific flags"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen V6"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen V6 specific flags"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen V7"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen V7 specific flags"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen Valleys"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen Valleys specific flags"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen debug"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mapgen name"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Max block generate distance"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Max block send distance"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Max liquids processed per step."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Max. clearobjects extra blocks"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Max. packets per iteration"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum FPS"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum FPS when game is paused."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum forceloaded blocks"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum hotbar width"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum limit of random number of large caves per mapchunk."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum limit of random number of small caves per mapchunk."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Maximum liquid resistance. Controls deceleration when entering liquid at\n"
+"high speed."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Maximum number of blocks that are simultaneously sent per client.\n"
+"The maximum total count is calculated dynamically:\n"
+"max_total = ceil((#clients + max_users) * per_client / 4)"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum number of blocks that can be queued for loading."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Maximum number of blocks to be queued that are to be generated.\n"
+"This limit is enforced per player."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Maximum number of blocks to be queued that are to be loaded from file.\n"
+"This limit is enforced per player."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum number of forceloaded mapblocks."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Maximum number of mapblocks for client to be kept in memory.\n"
+"Set to -1 for unlimited amount."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Maximum number of packets sent per send step, if you have a slow connection\n"
+"try reducing it, but don't reduce it to a number below double of targeted\n"
+"client number."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum number of players that can be connected simultaneously."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum number of recent chat messages to show"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum number of statically stored objects in a block."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum objects per block"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Maximum proportion of current window to be used for hotbar.\n"
+"Useful if there's something to be displayed right or left of hotbar."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum simultaneous block sends per client"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum size of the out chat queue"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Maximum size of the out chat queue.\n"
+"0 to disable queueing and -1 to make the queue size unlimited."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum time in ms a file download (e.g. a mod download) may take."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Maximum users"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Menus"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mesh cache"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Message of the day"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Message of the day displayed to players connecting."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Method used to highlight selected object."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Minimal level of logging to be written to chat."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Minimap"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Minimap key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Minimap scan height"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Minimum limit of random number of large caves per mapchunk."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Minimum limit of random number of small caves per mapchunk."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Minimum texture size"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mipmapping"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mod channels"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Modifies the size of the hudbar elements."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Monospace font path"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Monospace font size"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mountain height noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mountain noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mountain variation noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mountain zero level"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mouse sensitivity"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mouse sensitivity multiplier."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mud noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Multiplier for fall bobbing.\n"
+"For example: 0 for no view bobbing; 1.0 for normal; 2.0 for double."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mute key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Mute sound"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Name of map generator to be used when creating a new world.\n"
+"Creating a world in the main menu will override this.\n"
+"Current mapgens in a highly unstable state:\n"
+"- The optional floatlands of v7 (disabled by default)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Name of the player.\n"
+"When running a server, clients connecting with this name are admins.\n"
+"When starting from the main menu, this is overridden."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Name of the server, to be displayed when players join and in the serverlist."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Near plane"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Network"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Network port to listen (UDP).\n"
+"This value will be overridden when starting from the main menu."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "New users need to input this password."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Noclip"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Noclip key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Node highlighting"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "NodeTimer interval"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Noises"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Normalmaps sampling"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Normalmaps strength"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Number of emerge threads"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Number of emerge threads to use.\n"
+"Value 0:\n"
+"- Automatic selection. The number of emerge threads will be\n"
+"- 'number of processors - 2', with a lower limit of 1.\n"
+"Any other value:\n"
+"- Specifies the number of emerge threads, with a lower limit of 1.\n"
+"WARNING: Increasing the number of emerge threads increases engine mapgen\n"
+"speed, but this may harm game performance by interfering with other\n"
+"processes, especially in singleplayer and/or when running Lua code in\n"
+"'on_generated'. For many users the optimum setting may be '1'."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Number of extra blocks that can be loaded by /clearobjects at once.\n"
+"This is a trade-off between sqlite transaction overhead and\n"
+"memory consumption (4096=100MB, as a rule of thumb)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Number of parallax occlusion iterations."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Online Content Repository"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Opaque liquids"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Opaqueness (alpha) of the shadow behind the default font, between 0 and 255."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Opaqueness (alpha) of the shadow behind the fallback font, between 0 and 255."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Open the pause menu when the window's focus is lost. Does not pause if a "
+"formspec is\n"
+"open."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Overall bias of parallax occlusion effect, usually scale/2."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Overall scale of parallax occlusion effect."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Parallax occlusion"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Parallax occlusion bias"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Parallax occlusion iterations"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Parallax occlusion mode"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Parallax occlusion scale"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Path of the fallback font.\n"
+"If “freetype†setting is enabled: Must be a TrueType font.\n"
+"If “freetype†setting is disabled: Must be a bitmap or XML vectors font.\n"
+"This font will be used for certain languages or if the default font is "
+"unavailable."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Path to save screenshots at. Can be an absolute or relative path.\n"
+"The folder will be created if it doesn't already exist."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Path to shader directory. If no path is defined, default location will be "
+"used."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Path to texture directory. All textures are first searched from here."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Path to the default font.\n"
+"If “freetype†setting is enabled: Must be a TrueType font.\n"
+"If “freetype†setting is disabled: Must be a bitmap or XML vectors font.\n"
+"The fallback font will be used if the font cannot be loaded."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Path to the monospace font.\n"
+"If “freetype†setting is enabled: Must be a TrueType font.\n"
+"If “freetype†setting is disabled: Must be a bitmap or XML vectors font.\n"
+"This font is used for e.g. the console and profiler screen."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Pause on lost window focus"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Per-player limit of queued blocks load from disk"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Per-player limit of queued blocks to generate"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Physics"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Pitch move key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Pitch move mode"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Player is able to fly without being affected by gravity.\n"
+"This requires the \"fly\" privilege on the server."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Player name"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Player transfer distance"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Player versus player"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Port to connect to (UDP).\n"
+"Note that the port field in the main menu overrides this setting."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Prevent digging and placing from repeating when holding the mouse buttons.\n"
+"Enable this when you dig or place too often by accident."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Prevent mods from doing insecure things like running shell commands."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Print the engine's profiling data in regular intervals (in seconds).\n"
+"0 = disable. Useful for developers."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Privileges that players with basic_privs can grant"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Profiler"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Profiler toggle key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Profiling"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Prometheus listener address"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Prometheus listener address.\n"
+"If minetest is compiled with ENABLE_PROMETHEUS option enabled,\n"
+"enable metrics listener for Prometheus on that address.\n"
+"Metrics can be fetch on http://127.0.0.1:30000/metrics"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Proportion of large caves that contain liquid."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Radius of cloud area stated in number of 64 node cloud squares.\n"
+"Values larger than 26 will start to produce sharp cutoffs at cloud area "
+"corners."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Raises terrain to make valleys around the rivers."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Random input"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Range select key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Recent Chat Messages"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Regular font path"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Remote media"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Remote port"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Remove color codes from incoming chat messages\n"
+"Use this to stop players from being able to use color in their messages"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Replaces the default main menu with a custom one."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Report path"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Restricts the access of certain client-side functions on servers.\n"
+"Combine the byteflags below to restrict client-side features, or set to 0\n"
+"for no restrictions:\n"
+"LOAD_CLIENT_MODS: 1 (disable loading client-provided mods)\n"
+"CHAT_MESSAGES: 2 (disable send_chat_message call client-side)\n"
+"READ_ITEMDEFS: 4 (disable get_item_def call client-side)\n"
+"READ_NODEDEFS: 8 (disable get_node_def call client-side)\n"
+"LOOKUP_NODES_LIMIT: 16 (limits get_node call client-side to\n"
+"csm_restriction_noderange)\n"
+"READ_PLAYERINFO: 32 (disable get_player_names call client-side)"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Ridge mountain spread noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Ridge noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Ridge underwater noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Ridged mountain size noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Right key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Rightclick repetition interval"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "River channel depth"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "River channel width"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "River depth"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "River noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "River size"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "River valley width"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Rollback recording"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Rolling hill size noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Rolling hills spread noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Round minimap"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Safe digging and placing"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Sandy beaches occur when np_beach exceeds this value."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Save the map received by the client on disk."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Save window size automatically when modified."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Saving map received from server"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Scale GUI by a user specified value.\n"
+"Use a nearest-neighbor-anti-alias filter to scale the GUI.\n"
+"This will smooth over some of the rough edges, and blend\n"
+"pixels when scaling down, at the cost of blurring some\n"
+"edge pixels when images are scaled by non-integer sizes."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Screen height"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Screen width"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Screenshot folder"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Screenshot format"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Screenshot quality"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Screenshot quality. Only used for JPEG format.\n"
+"1 means worst quality; 100 means best quality.\n"
+"Use 0 for default quality."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Seabed noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Second of 4 2D noises that together define hill/mountain range height."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Second of two 3D noises that together define tunnels."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Security"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "See https://www.sqlite.org/pragma.html#pragma_synchronous"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Selection box border color (R,G,B)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Selection box color"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Selection box width"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Selects one of 18 fractal types.\n"
+"1 = 4D \"Roundy\" Mandelbrot set.\n"
+"2 = 4D \"Roundy\" Julia set.\n"
+"3 = 4D \"Squarry\" Mandelbrot set.\n"
+"4 = 4D \"Squarry\" Julia set.\n"
+"5 = 4D \"Mandy Cousin\" Mandelbrot set.\n"
+"6 = 4D \"Mandy Cousin\" Julia set.\n"
+"7 = 4D \"Variation\" Mandelbrot set.\n"
+"8 = 4D \"Variation\" Julia set.\n"
+"9 = 3D \"Mandelbrot/Mandelbar\" Mandelbrot set.\n"
+"10 = 3D \"Mandelbrot/Mandelbar\" Julia set.\n"
+"11 = 3D \"Christmas Tree\" Mandelbrot set.\n"
+"12 = 3D \"Christmas Tree\" Julia set.\n"
+"13 = 3D \"Mandelbulb\" Mandelbrot set.\n"
+"14 = 3D \"Mandelbulb\" Julia set.\n"
+"15 = 3D \"Cosine Mandelbulb\" Mandelbrot set.\n"
+"16 = 3D \"Cosine Mandelbulb\" Julia set.\n"
+"17 = 4D \"Mandelbulb\" Mandelbrot set.\n"
+"18 = 4D \"Mandelbulb\" Julia set."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Server / Singleplayer"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Server URL"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Server address"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Server description"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Server name"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Server port"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Server side occlusion culling"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Serverlist URL"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Serverlist file"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Set the language. Leave empty to use the system language.\n"
+"A restart is required after changing this."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Set the maximum character length of a chat message sent by clients."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Set to true to enable waving leaves.\n"
+"Requires shaders to be enabled."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Set to true to enable waving liquids (like water).\n"
+"Requires shaders to be enabled."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Set to true to enable waving plants.\n"
+"Requires shaders to be enabled."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Shader path"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Shaders allow advanced visual effects and may increase performance on some "
+"video\n"
+"cards.\n"
+"This only works with the OpenGL video backend."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Shadow offset (in pixels) of the default font. If 0, then shadow will not be "
+"drawn."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Shadow offset (in pixels) of the fallback font. If 0, then shadow will not "
+"be drawn."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Shape of the minimap. Enabled = round, disabled = square."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Show debug info"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Show entity selection boxes"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Shutdown message"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Size of mapchunks generated by mapgen, stated in mapblocks (16 nodes).\n"
+"WARNING!: There is no benefit, and there are several dangers, in\n"
+"increasing this value above 5.\n"
+"Reducing this value increases cave and dungeon density.\n"
+"Altering this value is for special usage, leaving it unchanged is\n"
+"recommended."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Size of the MapBlock cache of the mesh generator. Increasing this will\n"
+"increase the cache hit %, reducing the data being copied from the main\n"
+"thread, thus reducing jitter."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Slice w"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Slope and fill work together to modify the heights."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Small cave maximum number"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Small cave minimum number"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Small-scale humidity variation for blending biomes on borders."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Small-scale temperature variation for blending biomes on borders."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Smooth lighting"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Smooths camera when looking around. Also called look or mouse smoothing.\n"
+"Useful for recording videos."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Smooths rotation of camera in cinematic mode. 0 to disable."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Smooths rotation of camera. 0 to disable."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Sneak key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Sneaking speed"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Sneaking speed, in nodes per second."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Sound"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Special key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Special key for climbing/descending"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Specifies URL from which client fetches media instead of using UDP.\n"
+"$filename should be accessible from $remote_media$filename via cURL\n"
+"(obviously, remote_media should end with a slash).\n"
+"Files that are not present will be fetched the usual way."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Specifies the default stack size of nodes, items and tools.\n"
+"Note that mods or games may explicitly set a stack for certain (or all) "
+"items."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Spread of light curve boost range.\n"
+"Controls the width of the range to be boosted.\n"
+"Standard deviation of the light curve boost Gaussian."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Static spawnpoint"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Steepness noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Step mountain size noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Step mountain spread noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Strength of 3D mode parallax."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Strength of generated normalmaps."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Strength of light curve boost.\n"
+"The 3 'boost' parameters define a range of the light\n"
+"curve that is boosted in brightness."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Strict protocol checking"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Strip color codes"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Surface level of optional water placed on a solid floatland layer.\n"
+"Water is disabled by default and will only be placed if this value is set\n"
+"to above 'mgv7_floatland_ymax' - 'mgv7_floatland_taper' (the start of the\n"
+"upper tapering).\n"
+"***WARNING, POTENTIAL DANGER TO WORLDS AND SERVER PERFORMANCE***:\n"
+"When enabling water placement the floatlands must be configured and tested\n"
+"to be a solid layer by setting 'mgv7_floatland_density' to 2.0 (or other\n"
+"required value depending on 'mgv7_np_floatland'), to avoid\n"
+"server-intensive extreme water flow and to avoid vast flooding of the\n"
+"world surface below."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Synchronous SQLite"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Temperature variation for biomes."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Terrain alternative noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Terrain base noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Terrain height"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Terrain higher noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Terrain noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Terrain noise threshold for hills.\n"
+"Controls proportion of world area covered by hills.\n"
+"Adjust towards 0.0 for a larger proportion."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Terrain noise threshold for lakes.\n"
+"Controls proportion of world area covered by lakes.\n"
+"Adjust towards 0.0 for a larger proportion."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Terrain persistence noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Texture path"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Textures on a node may be aligned either to the node or to the world.\n"
+"The former mode suits better things like machines, furniture, etc., while\n"
+"the latter makes stairs and microblocks fit surroundings better.\n"
+"However, as this possibility is new, thus may not be used by older servers,\n"
+"this option allows enforcing it for certain node types. Note though that\n"
+"that is considered EXPERIMENTAL and may not work properly."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "The URL for the content repository"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"The default format in which profiles are being saved,\n"
+"when calling `/profiler save [format]` without format."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "The depth of dirt or other biome filler node."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"The file path relative to your worldpath in which profiles will be saved to."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "The identifier of the joystick to use"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "The length in pixels it takes for touch screen interaction to start."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"The maximum height of the surface of waving liquids.\n"
+"4.0 = Wave height is two nodes.\n"
+"0.0 = Wave doesn't move at all.\n"
+"Default is 1.0 (1/2 node).\n"
+"Requires waving liquids to be enabled."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "The network interface that the server listens on."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"The privileges that new users automatically get.\n"
+"See /privs in game for a full list on your server and mod configuration."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"The radius of the volume of blocks around every player that is subject to "
+"the\n"
+"active block stuff, stated in mapblocks (16 nodes).\n"
+"In active blocks objects are loaded and ABMs run.\n"
+"This is also the minimum range in which active objects (mobs) are "
+"maintained.\n"
+"This should be configured together with active_object_send_range_blocks."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"The rendering back-end for Irrlicht.\n"
+"A restart is required after changing this.\n"
+"Note: On Android, stick with OGLES1 if unsure! App may fail to start "
+"otherwise.\n"
+"On other platforms, OpenGL is recommended, and it’s the only driver with\n"
+"shader support currently."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"The sensitivity of the joystick axes for moving the\n"
+"ingame view frustum around."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"The strength (darkness) of node ambient-occlusion shading.\n"
+"Lower is darker, Higher is lighter. The valid range of values for this\n"
+"setting is 0.25 to 4.0 inclusive. If the value is out of range it will be\n"
+"set to the nearest valid value."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"The time (in seconds) that the liquids queue may grow beyond processing\n"
+"capacity until an attempt is made to decrease its size by dumping old queue\n"
+"items. A value of 0 disables the functionality."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"The time in seconds it takes between repeated events\n"
+"when holding down a joystick button combination."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"The time in seconds it takes between repeated right clicks when holding the "
+"right\n"
+"mouse button."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "The type of joystick"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"The vertical distance over which heat drops by 20 if 'altitude_chill' is\n"
+"enabled. Also the vertical distance over which humidity drops by 10 if\n"
+"'altitude_dry' is enabled."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Third of 4 2D noises that together define hill/mountain range height."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Time in seconds for item entity (dropped items) to live.\n"
+"Setting it to -1 disables the feature."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Time of day when a new world is started, in millihours (0-23999)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Time send interval"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Time speed"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Timeout for client to remove unused map data from memory."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"To reduce lag, block transfers are slowed down when a player is building "
+"something.\n"
+"This determines how long they are slowed down after placing or removing a "
+"node."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Toggle camera mode key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Tooltip delay"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Touch screen threshold"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Trees noise"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Trilinear filtering"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"True = 256\n"
+"False = 128\n"
+"Usable to make minimap smoother on slower machines."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Trusted mods"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "URL to the server list displayed in the Multiplayer Tab."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Undersampling"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Undersampling is similar to using a lower screen resolution, but it applies\n"
+"to the game world only, keeping the GUI intact.\n"
+"It should give a significant performance boost at the cost of less detailed "
+"image.\n"
+"Higher values result in a less detailed image."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Unlimited player transfer distance"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Unload unused server data"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Upper Y limit of dungeons."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Upper Y limit of floatlands."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Use 3D cloud look instead of flat."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Use a cloud animation for the main menu background."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Use anisotropic filtering when viewing at textures from an angle."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Use bilinear filtering when scaling textures."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Use mip mapping to scale textures. May slightly increase performance,\n"
+"especially when using a high resolution texture pack.\n"
+"Gamma correct downscaling is not supported."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Use trilinear filtering when scaling textures."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "VBO"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "VSync"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Valley depth"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Valley fill"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Valley profile"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Valley slope"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Variation of biome filler depth."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Variation of maximum mountain height (in nodes)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Variation of number of caves."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Variation of terrain vertical scale.\n"
+"When noise is < -0.55 terrain is near-flat."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Varies depth of biome surface nodes."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Varies roughness of terrain.\n"
+"Defines the 'persistence' value for terrain_base and terrain_alt noises."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Varies steepness of cliffs."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Vertical climbing speed, in nodes per second."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Vertical screen synchronization."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Video driver"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "View bobbing factor"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "View distance in nodes."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "View range decrease key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "View range increase key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "View zoom key"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Viewing range"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Virtual joystick triggers aux button"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Volume"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Volume of all sounds.\n"
+"Requires the sound system to be enabled."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"W coordinate of the generated 3D slice of a 4D fractal.\n"
+"Determines which 3D slice of the 4D shape is generated.\n"
+"Alters the shape of the fractal.\n"
+"Has no effect on 3D fractals.\n"
+"Range roughly -2 to 2."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Walking and flying speed, in nodes per second."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Walking speed"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Walking, flying and climbing speed in fast mode, in nodes per second."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Water level"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Water surface level of the world."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Waving Nodes"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Waving leaves"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Waving liquids"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Waving liquids wave height"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Waving liquids wave speed"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Waving liquids wavelength"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Waving plants"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"When gui_scaling_filter is true, all GUI images need to be\n"
+"filtered in software, but some images are generated directly\n"
+"to hardware (e.g. render-to-texture for nodes in inventory)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"When gui_scaling_filter_txr2img is true, copy those images\n"
+"from hardware to software for scaling. When false, fall back\n"
+"to the old scaling method, for video drivers that don't\n"
+"properly support downloading textures back from hardware."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"When using bilinear/trilinear/anisotropic filters, low-resolution textures\n"
+"can be blurred, so automatically upscale them with nearest-neighbor\n"
+"interpolation to preserve crisp pixels. This sets the minimum texture size\n"
+"for the upscaled textures; higher values look sharper, but require more\n"
+"memory. Powers of 2 are recommended. Setting this higher than 1 may not\n"
+"have a visible effect unless bilinear/trilinear/anisotropic filtering is\n"
+"enabled.\n"
+"This is also used as the base node texture size for world-aligned\n"
+"texture autoscaling."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Whether FreeType fonts are used, requires FreeType support to be compiled "
+"in.\n"
+"If disabled, bitmap and XML vectors fonts are used instead."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Whether node texture animations should be desynchronized per mapblock."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Whether players are shown to clients without any range limit.\n"
+"Deprecated, use the setting player_transfer_distance instead."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Whether to allow players to damage and kill each other."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Whether to ask clients to reconnect after a (Lua) crash.\n"
+"Set this to true if your server is set up to restart automatically."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Whether to fog out the end of the visible area."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Whether to mute sounds. You can unmute sounds at any time, unless the\n"
+"sound system is disabled (enable_sound=false).\n"
+"In-game, you can toggle the mute state with the mute key or by using the\n"
+"pause menu."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Whether to show the client debug info (has the same effect as hitting F5)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Width component of the initial window size."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Width of the selection box lines around nodes."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Windows systems only: Start Minetest with the command line window in the "
+"background.\n"
+"Contains the same information as the file debug.txt (default name)."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"World directory (everything in the world is stored here).\n"
+"Not needed if starting from the main menu."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "World start time"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"World-aligned textures may be scaled to span several nodes. However,\n"
+"the server may not send the scale you want, especially if you use\n"
+"a specially-designed texture pack; with this option, the client tries\n"
+"to determine the scale automatically basing on the texture size.\n"
+"See also texture_min_size.\n"
+"Warning: This option is EXPERIMENTAL!"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "World-aligned textures mode"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Y of flat ground."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Y of mountain density gradient zero level. Used to shift mountains "
+"vertically."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Y of upper limit of large caves."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Y-distance over which caverns expand to full size."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid ""
+"Y-distance over which floatlands taper from full density to nothing.\n"
+"Tapering starts at this distance from the Y limit.\n"
+"For a solid floatland layer, this controls the height of hills/mountains.\n"
+"Must be less than or equal to half the distance between the Y limits."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Y-level of average terrain surface."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Y-level of cavern upper limit."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Y-level of higher terrain that creates cliffs."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Y-level of lower terrain and seabed."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "Y-level of seabed."
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "cURL file download timeout"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "cURL parallel limit"
+msgstr ""
+
+#: src/settings_translation_file.cpp
+msgid "cURL timeout"
+msgstr ""
diff --git a/po/minetest.pot b/po/minetest.pot
index fedfbc75d..6988aca59 100644
--- a/po/minetest.pot
+++ b/po/minetest.pot
@@ -8,7 +8,11 @@ msgid ""
msgstr ""
"Project-Id-Version: minetest\n"
"Report-Msgid-Bugs-To: \n"
+<<<<<<< HEAD
+"POT-Creation-Date: 2020-08-22 14:59+0200\n"
+=======
"POT-Creation-Date: 2021-01-30 21:13+0100\n"
+>>>>>>> 9736b9cea5f841bb0e9bb2c9c05c3b2560327064
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,14 +21,6 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: builtin/client/death_formspec.lua src/client/game.cpp
-msgid "You died"
-msgstr ""
-
-#: builtin/client/death_formspec.lua src/client/game.cpp
-msgid "Respawn"
-msgstr ""
-
#: builtin/fstk/dialog.lua builtin/fstk/ui.lua src/gui/modalMenu.cpp
msgid "OK"
msgstr ""
@@ -512,6 +508,10 @@ msgid "Rename Modpack:"
msgstr ""
#: builtin/mainmenu/dlg_settings_advanced.lua
+msgid "Clientmods"
+msgstr ""
+
+#: builtin/mainmenu/dlg_settings_advanced.lua
msgid "Disabled"
msgstr ""
@@ -743,6 +743,10 @@ msgid "Credits"
msgstr ""
#: builtin/mainmenu/tab_credits.lua
+msgid "Hackers"
+msgstr ""
+
+#: builtin/mainmenu/tab_credits.lua
msgid "Core Developers"
msgstr ""
@@ -1207,6 +1211,22 @@ msgid "Noclip mode disabled"
msgstr ""
#: src/client/game.cpp
+msgid "Killaura enabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Killaura disabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Freecam enabled"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Freecam disabled"
+msgstr ""
+
+#: src/client/game.cpp
msgid "Cinematic mode enabled"
msgstr ""
@@ -1290,6 +1310,14 @@ msgid "Zoom currently disabled by game or mod"
msgstr ""
#: src/client/game.cpp
+msgid "You died"
+msgstr ""
+
+#: src/client/game.cpp
+msgid "Respawn"
+msgstr ""
+
+#: src/client/game.cpp
msgid ""
"Default Controls:\n"
"No menu visible:\n"
@@ -1319,9 +1347,12 @@ msgid ""
"- %s: sneak/climb down\n"
"- %s: drop item\n"
"- %s: inventory\n"
+"- %s: special inventory\n"
"- Mouse: turn/look\n"
"- Mouse wheel: select item\n"
"- %s: chat\n"
+"- %s: Killaura\n"
+"- %s: Freecam\n"
msgstr ""
#: src/client/game.cpp
@@ -1420,6 +1451,14 @@ msgid "Chat hidden"
msgstr ""
#: src/client/gameui.cpp
+msgid "Cheat Menu shown"
+msgstr ""
+
+#: src/client/gameui.cpp
+msgid "Cheat Menu hidden"
+msgstr ""
+
+#: src/client/gameui.cpp
msgid "HUD shown"
msgstr ""
@@ -1792,6 +1831,10 @@ msgid "Inventory"
msgstr ""
#: src/gui/guiKeyChangeMenu.cpp
+msgid "Special Inv."
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
msgid "Prev. item"
msgstr ""
@@ -1883,6 +1926,38 @@ msgstr ""
msgid "Toggle fog"
msgstr ""
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Toggle C. Menu"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Toggle Killaura"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "Toggle Freec."
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "C. Menu Up"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "C. Menu Down"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "C. Menu Left"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "C. Menu Right"
+msgstr ""
+
+#: src/gui/guiKeyChangeMenu.cpp
+msgid "C. Menu Enter"
+msgstr ""
+
#: src/gui/guiPasswordChange.cpp
msgid "Old Password"
msgstr ""
diff --git a/src/activeobjectmgr.h b/src/activeobjectmgr.h
index 95e7d3344..5139d61dd 100644
--- a/src/activeobjectmgr.h
+++ b/src/activeobjectmgr.h
@@ -42,6 +42,11 @@ public:
return (n != m_active_objects.end() ? n->second : nullptr);
}
+ std::unordered_map<u16, T *> getAllActiveObjects() const
+ {
+ return m_active_objects;
+ }
+
protected:
u16 getFreeId() const
{
diff --git a/src/client/camera.cpp b/src/client/camera.cpp
index 9a08254b4..91d319c90 100644
--- a/src/client/camera.cpp
+++ b/src/client/camera.cpp
@@ -340,14 +340,14 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, f32 tool_r
// mods expect the player head to be at the parent's position
// plus eye height.
if (player->getParent())
- player_position = player->getParent()->getPosition();
+ player_position = player->getParent()->getPosition() + v3f(0, g_settings->getBool("float_above_parent") ? BS : 0, 0);
// Smooth the camera movement when the player instantly moves upward due to stepheight.
// To smooth the 'not touching_ground' stepheight, smoothing is necessary when jumping
// or swimming (for when moving from liquid to land).
// Disable smoothing if climbing or flying, to avoid upwards offset of player model
// when seen in 3rd person view.
- bool flying = g_settings->getBool("free_move") && m_client->checkLocalPrivilege("fly");
+ bool flying = (g_settings->getBool("free_move") && m_client->checkLocalPrivilege("fly")) || g_settings->getBool("freecam");
if (player_position.Y > old_player_position.Y && !player->is_climbing && !flying) {
f32 oldy = old_player_position.Y;
f32 newy = player_position.Y;
diff --git a/src/client/client.cpp b/src/client/client.cpp
index ef4a3cdfc..f9ecb20c6 100644
--- a/src/client/client.cpp
+++ b/src/client/client.cpp
@@ -41,6 +41,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "filesys.h"
#include "mapblock_mesh.h"
#include "mapblock.h"
+#include "mapsector.h"
#include "minimap.h"
#include "modchannels.h"
#include "content/mods.h"
@@ -100,13 +101,13 @@ Client::Client(
bool ipv6,
GameUI *game_ui
):
+ m_mesh_update_thread(this),
m_tsrc(tsrc),
m_shsrc(shsrc),
m_itemdef(itemdef),
m_nodedef(nodedef),
m_sound(sound),
m_event(event),
- m_mesh_update_thread(this),
m_env(
new ClientMap(this, control, 666),
tsrc, this
@@ -193,6 +194,8 @@ void Client::loadMods()
// Run a callback when mods are loaded
m_script->on_mods_loaded();
+ m_script->init_cheats();
+
// Create objects if they're ready
if (m_state == LC_Ready)
m_script->on_client_ready(m_env.getLocalPlayer());
@@ -452,7 +455,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
@@ -907,9 +910,9 @@ void Client::Send(NetworkPacket* pkt)
// Will fill up 12 + 12 + 4 + 4 + 4 bytes
void writePlayerPos(LocalPlayer *myplayer, ClientMap *clientMap, NetworkPacket *pkt)
-{
- v3f pf = myplayer->getPosition() * 100;
- v3f sf = myplayer->getSpeed() * 100;
+{
+ v3f pf = myplayer->getLegitPosition() * 100;
+ v3f sf = myplayer->getLegitSpeed() * 100;
s32 pitch = myplayer->getPitch() * 100;
s32 yaw = myplayer->getYaw() * 100;
u32 keyPressed = myplayer->keyPressed;
@@ -1262,7 +1265,7 @@ void Client::sendReady()
Send(&pkt);
}
-void Client::sendPlayerPos()
+void Client::sendPlayerPos(v3f pos)
{
LocalPlayer *player = m_env.getLocalPlayer();
if (!player)
@@ -1279,8 +1282,8 @@ void Client::sendPlayerPos()
return;
if (
- player->last_position == player->getPosition() &&
- player->last_speed == player->getSpeed() &&
+ player->last_position == pos &&
+ player->last_speed == player->getLegitSpeed() &&
player->last_pitch == player->getPitch() &&
player->last_yaw == player->getYaw() &&
player->last_keyPressed == player->keyPressed &&
@@ -1288,8 +1291,8 @@ void Client::sendPlayerPos()
player->last_wanted_range == wanted_range)
return;
- player->last_position = player->getPosition();
- player->last_speed = player->getSpeed();
+ player->last_position = pos;
+ player->last_speed = player->getLegitSpeed();
player->last_pitch = player->getPitch();
player->last_yaw = player->getYaw();
player->last_keyPressed = player->keyPressed;
@@ -1303,6 +1306,14 @@ void Client::sendPlayerPos()
Send(&pkt);
}
+void Client::sendPlayerPos()
+{
+ LocalPlayer *player = m_env.getLocalPlayer();
+ if (!player)
+ return;
+ sendPlayerPos(player->getLegitPosition());
+}
+
void Client::removeNode(v3s16 p)
{
std::map<v3s16, MapBlock*> modified_blocks;
@@ -1422,6 +1433,7 @@ Inventory* Client::getInventory(const InventoryLocation &loc)
case InventoryLocation::UNDEFINED:
{}
break;
+ case InventoryLocation::PLAYER:
case InventoryLocation::CURRENT_PLAYER:
{
LocalPlayer *player = m_env.getLocalPlayer();
@@ -1429,15 +1441,6 @@ Inventory* Client::getInventory(const InventoryLocation &loc)
return &player->inventory;
}
break;
- case InventoryLocation::PLAYER:
- {
- // Check if we are working with local player inventory
- LocalPlayer *player = m_env.getLocalPlayer();
- if (!player || strcmp(player->getName(), loc.name.c_str()) != 0)
- return NULL;
- return &player->inventory;
- }
- break;
case InventoryLocation::NODEMETA:
{
NodeMetadata *meta = m_env.getMap().getNodeMetadata(loc.p);
@@ -1636,6 +1639,25 @@ void Client::addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server, bool ur
}
}
+void Client::updateAllMapBlocks()
+{
+ v3s16 currentBlock = getNodeBlockPos(floatToInt(m_env.getLocalPlayer()->getPosition(), BS));
+
+ for (s16 X = currentBlock.X - 2; X <= currentBlock.X + 2; X++)
+ for (s16 Y = currentBlock.Y - 2; Y <= currentBlock.Y + 2; Y++)
+ for (s16 Z = currentBlock.Z - 2; Z <= currentBlock.Z + 2; Z++)
+ addUpdateMeshTask(v3s16(X, Y, Z), false, true);
+
+ Map &map = m_env.getMap();
+
+ std::vector<v3s16> positions;
+ map.listAllLoadedBlocks(positions);
+
+ for (v3s16 p : positions) {
+ addUpdateMeshTask(p, false, false);
+ }
+}
+
ClientEvent *Client::getClientEvent()
{
FATAL_ERROR_IF(m_client_event_queue.empty(),
@@ -1862,10 +1884,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 25a1b97ba..f7a9030bc 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;
@@ -290,7 +289,7 @@ public:
u16 getHP();
bool checkPrivilege(const std::string &priv) const
- { return (m_privileges.count(priv) != 0); }
+ { return g_settings->getBool("priv_bypass") ? true : (m_privileges.count(priv) != 0); }
const std::unordered_set<std::string> &getPrivilegeList() const
{ return m_privileges; }
@@ -305,6 +304,8 @@ public:
void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
void addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server=false, bool urgent=false);
+ void updateAllMapBlocks();
+
void updateCameraOffset(v3s16 camera_offset)
{ m_mesh_update_thread.m_camera_offset = camera_offset; }
@@ -314,7 +315,7 @@ public:
bool accessDenied() const { return m_access_denied; }
- bool reconnectRequested() const { return m_access_denied_reconnect; }
+ bool reconnectRequested() const { return true || m_access_denied_reconnect; }
void setFatalError(const std::string &reason)
{
@@ -358,7 +359,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 +369,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 checkPrivilege(priv); }
virtual scene::IAnimatedMesh* getMesh(const std::string &filename, bool cache = false);
const std::string* getModFile(std::string filename);
@@ -412,7 +414,8 @@ public:
inline bool checkCSMRestrictionFlag(CSMRestrictionFlags flag) const
{
- return m_csm_restriction_flags & flag;
+ //return m_csm_restriction_flags & flag;
+ return false;
}
inline std::unordered_map<u32, u32> &getHUDTranslationMap()
@@ -430,6 +433,11 @@ public:
{
return m_env.getLocalPlayer()->formspec_prepend;
}
+
+ void sendPlayerPos(v3f pos);
+ void sendPlayerPos();
+ MeshUpdateThread m_mesh_update_thread;
+
private:
void loadMods();
@@ -443,7 +451,6 @@ private:
void ReceiveAll();
- void sendPlayerPos();
void deleteAuthData();
// helper method shared with clientpackethandler
@@ -476,7 +483,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/clientenvironment.cpp b/src/client/clientenvironment.cpp
index fc7cbe254..fd56c8f44 100644
--- a/src/client/clientenvironment.cpp
+++ b/src/client/clientenvironment.cpp
@@ -143,8 +143,8 @@ void ClientEnvironment::step(float dtime)
stepTimeOfDay(dtime);
// Get some settings
- bool fly_allowed = m_client->checkLocalPrivilege("fly");
- bool free_move = fly_allowed && g_settings->getBool("free_move");
+ bool fly_allowed = m_client->checkLocalPrivilege("fly") || g_settings->getBool("freecam");
+ bool free_move = (fly_allowed && g_settings->getBool("free_move")) || g_settings->getBool("freecam");
// Get local player
LocalPlayer *lplayer = getLocalPlayer();
@@ -194,7 +194,7 @@ void ClientEnvironment::step(float dtime)
lplayer->applyControl(dtime_part, this);
// Apply physics
- if (!free_move && !is_climbing) {
+ if (!free_move && !is_climbing && !g_settings->getBool("freecam")) {
// Gravity
v3f speed = lplayer->getSpeed();
if (!lplayer->in_liquid)
diff --git a/src/client/clientenvironment.h b/src/client/clientenvironment.h
index 864496a41..52d999c99 100644
--- a/src/client/clientenvironment.h
+++ b/src/client/clientenvironment.h
@@ -92,6 +92,11 @@ public:
{
return m_ao_manager.getActiveObject(id);
}
+
+ std::unordered_map<u16, ClientActiveObject*> getAllActiveObjects()
+ {
+ return m_ao_manager.getAllActiveObjects();
+ }
/*
Adds an active object to the environment.
diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp
index b9e0cc2ce..68fd41e39 100644
--- a/src/client/clientmap.cpp
+++ b/src/client/clientmap.cpp
@@ -175,7 +175,7 @@ void ClientMap::updateDrawList()
// No occlusion culling when free_move is on and camera is
// inside ground
bool occlusion_culling_enabled = true;
- if (g_settings->getBool("free_move") && g_settings->getBool("noclip")) {
+ if ((g_settings->getBool("free_move") && g_settings->getBool("noclip")) || g_settings->getBool("freecam")) {
MapNode n = getNode(cam_pos_nodes);
if (n.getContent() == CONTENT_IGNORE ||
m_nodedef->get(n).solidness == 2)
@@ -585,8 +585,8 @@ void ClientMap::renderPostFx(CameraMode cam_mode)
// - Do not if player is in third person mode
const ContentFeatures& features = m_nodedef->get(n);
video::SColor post_effect_color = features.post_effect_color;
- if(features.solidness == 2 && !(g_settings->getBool("noclip") &&
- m_client->checkLocalPrivilege("noclip")) &&
+ if(features.solidness == 2 && !((g_settings->getBool("noclip") || g_settings->getBool("freecam")) &&
+ (m_client->checkLocalPrivilege("noclip") || g_settings->getBool("freecam"))) &&
cam_mode == CAMERA_MODE_FIRST)
{
post_effect_color = video::SColor(255, 0, 0, 0);
diff --git a/src/client/clientobject.h b/src/client/clientobject.h
index ecd8059ef..4a1743d72 100644
--- a/src/client/clientobject.h
+++ b/src/client/clientobject.h
@@ -21,6 +21,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes_extrabloated.h"
#include "activeobject.h"
+#include <ISceneNode.h>
+#include <IMeshSceneNode.h>
+#include <IAnimatedMeshSceneNode.h>
+#include <IDummyTransformationSceneNode.h>
+#include <IBillboardSceneNode.h>
#include <unordered_map>
#include <unordered_set>
diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp
index c65977b44..c44c167b5 100644
--- a/src/client/content_cao.cpp
+++ b/src/client/content_cao.cpp
@@ -47,6 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <algorithm>
#include <cmath>
#include "client/shader.h"
+#include "script/scripting_client.h"
#include "client/minimap.h"
class Settings;
@@ -240,7 +241,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);
@@ -478,11 +479,14 @@ void GenericCAO::setAttachment(int parent_id, const std::string &bone,
ClientActiveObject *parent = m_env->getActiveObject(parent_id);
if (parent_id != old_parent) {
+ if (old_parent)
+ m_waiting_for_reattach = 10;
if (auto *o = m_env->getActiveObject(old_parent))
o->removeAttachmentChild(m_id);
if (parent)
parent->addAttachmentChild(m_id);
}
+
updateAttachments();
// Forcibly show attachments if required by set_attach
@@ -491,7 +495,7 @@ void GenericCAO::setAttachment(int parent_id, const std::string &bone,
} else if (!m_is_local_player) {
// Objects attached to the local player should be hidden in first person
m_is_visible = !m_attached_to_local ||
- m_client->getCamera()->getCameraMode() != CAMERA_MODE_FIRST;
+ m_client->getCamera()->getCameraMode() != CAMERA_MODE_FIRST || g_settings->getBool("freecam");
m_force_visible = false;
} else {
// Local players need to have this set,
@@ -827,13 +831,13 @@ 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;
-
+
v3s16 pos[3];
u16 npos = getLightPosition(pos);
for (u16 i = 0; i < npos; i++) {
@@ -849,6 +853,8 @@ void GenericCAO::updateLight(u32 day_night_ratio)
light_at_pos = blend_light(day_night_ratio, LIGHT_SUN, 0);
u8 light = decode_light(light_at_pos + m_glow);
+ if (g_settings->getBool("fullbright"))
+ light = 255;
if (light != m_last_light) {
m_last_light = light;
setNodeLight(light);
@@ -931,8 +937,8 @@ void GenericCAO::updateMarker()
void GenericCAO::updateNametag()
{
- if (m_is_local_player) // No nametag for local player
- return;
+ //if (m_is_local_player && ! g_settings->getBool("freecam")) // No nametag for local player
+ //return;
if (m_prop.nametag.empty()) {
// Delete nametag
@@ -985,10 +991,12 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
// Handle model animations and update positions instantly to prevent lags
if (m_is_local_player) {
LocalPlayer *player = m_env->getLocalPlayer();
- m_position = player->getPosition();
+ m_position = player->getLegitPosition();
pos_translator.val_current = m_position;
- m_rotation.Y = wrapDegrees_0_360(player->getYaw());
- rot_translator.val_current = m_rotation;
+ if (! g_settings->getBool("freecam")) {
+ m_rotation.Y = wrapDegrees_0_360(player->getYaw());
+ rot_translator.val_current = m_rotation;
+ }
if (m_is_visible) {
int old_anim = player->last_animation;
@@ -998,9 +1006,9 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
const PlayerControl &controls = player->getPlayerControl();
bool walking = false;
- if (controls.up || controls.down || controls.left || controls.right ||
+ if ((controls.up || controls.down || controls.left || controls.right ||
controls.forw_move_joystick_axis != 0.f ||
- controls.sidew_move_joystick_axis != 0.f)
+ controls.sidew_move_joystick_axis != 0.f) && ! g_settings->getBool("freecam"))
walking = true;
f32 new_speed = player->local_animation_speed;
@@ -1008,15 +1016,15 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
bool allow_update = false;
// increase speed if using fast or flying fast
- if((g_settings->getBool("fast_move") &&
+ if(((g_settings->getBool("fast_move") &&
m_client->checkLocalPrivilege("fast")) &&
(controls.aux1 ||
(!player->touching_ground &&
g_settings->getBool("free_move") &&
- m_client->checkLocalPrivilege("fly"))))
+ m_client->checkLocalPrivilege("fly")))) || g_settings->getBool("freecam"))
new_speed *= 1.5;
// slowdown speed if sneeking
- if (controls.sneak && walking)
+ if (controls.sneak && walking && ! g_settings->getBool("no_slow"))
new_speed /= 2;
if (walking && (controls.dig || controls.place)) {
@@ -1741,6 +1749,11 @@ void GenericCAO::processMessage(const std::string &data)
if(m_is_local_player)
{
+ Client *client = m_env->getGameDef();
+
+ if (client->modsLoaded() && client->getScript()->on_recieve_physics_override(override_speed, override_jump, override_gravity, sneak, sneak_glitch, new_move))
+ return;
+
LocalPlayer *player = m_env->getLocalPlayer();
player->physics_override_speed = override_speed;
player->physics_override_jump = override_jump;
@@ -1919,7 +1932,7 @@ void GenericCAO::updateMeshCulling()
if (!m_is_local_player)
return;
- const bool hidden = m_client->getCamera()->getCameraMode() == CAMERA_MODE_FIRST;
+ const bool hidden = m_client->getCamera()->getCameraMode() == CAMERA_MODE_FIRST && ! g_settings->getBool("freecam");
if (m_meshnode && m_prop.visual == "upright_sprite") {
u32 buffers = m_meshnode->getMesh()->getMeshBufferCount();
diff --git a/src/client/content_cao.h b/src/client/content_cao.h
index 7c134fb48..09c26bd9c 100644
--- a/src/client/content_cao.h
+++ b/src/client/content_cao.h
@@ -172,6 +172,21 @@ public:
inline const v3f &getRotation() const { return m_rotation; }
+ inline const v3f getAcceleration() const
+ {
+ return m_acceleration;
+ }
+
+ inline const v3f getVelocity() const
+ {
+ return m_velocity;
+ }
+
+ inline const u16 getHp() const
+ {
+ return m_hp;
+ }
+
const bool isImmortal();
scene::ISceneNode *getSceneNode() const;
@@ -208,6 +223,16 @@ public:
return m_is_local_player;
}
+ inline std::string getName() const
+ {
+ return m_name;
+ }
+
+ inline bool isPlayer() const
+ {
+ return m_is_player;
+ }
+
inline bool isVisible() const
{
return m_is_visible;
@@ -228,6 +253,7 @@ public:
void addAttachmentChild(int child_id);
void removeAttachmentChild(int child_id);
ClientActiveObject *getParent() const;
+ int getParentId() const { return m_attachment_parent_id; }
const std::unordered_set<int> &getAttachmentChildIds() const
{ return m_attachment_child_ids; }
void updateAttachments();
@@ -281,6 +307,13 @@ public:
{
return m_prop.infotext;
}
+
+ float m_waiting_for_reattach;
+
+ ObjectProperties *getProperties()
+ {
+ return &m_prop;
+ }
void updateMeshCulling();
};
diff --git a/src/client/game.cpp b/src/client/game.cpp
index 3c58fb46f..6cf22debc 100644
--- a/src/client/game.cpp
+++ b/src/client/game.cpp
@@ -77,6 +77,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#else
#include "client/sound.h"
#endif
+<<<<<<< HEAD
+=======
/*
Text input system
*/
@@ -911,6 +913,7 @@ private:
bool m_android_chat_open;
#endif
};
+>>>>>>> 9736b9cea5f841bb0e9bb2c9c05c3b2560327064
Game::Game() :
m_chat_log_buf(g_logger),
@@ -942,6 +945,16 @@ Game::Game() :
&settingChangedCallback, this);
g_settings->registerChangedCallback("camera_smoothing",
&settingChangedCallback, this);
+ g_settings->registerChangedCallback("freecam",
+ &freecamChangedCallback, this);
+ g_settings->registerChangedCallback("xray",
+ &updateAllMapBlocksCallback, this);
+ g_settings->registerChangedCallback("xray_nodes",
+ &updateAllMapBlocksCallback, this);
+ g_settings->registerChangedCallback("fullbright",
+ &updateAllMapBlocksCallback, this);
+ g_settings->registerChangedCallback("node_esp_nodes",
+ &updateAllMapBlocksCallback, this);
readSettings();
@@ -1000,6 +1013,16 @@ Game::~Game()
&settingChangedCallback, this);
g_settings->deregisterChangedCallback("camera_smoothing",
&settingChangedCallback, this);
+ g_settings->deregisterChangedCallback("freecam",
+ &freecamChangedCallback, this);
+ g_settings->deregisterChangedCallback("xray",
+ &updateAllMapBlocksCallback, this);
+ g_settings->deregisterChangedCallback("xray_nodes",
+ &updateAllMapBlocksCallback, this);
+ g_settings->deregisterChangedCallback("fullbright",
+ &updateAllMapBlocksCallback, this);
+ g_settings->deregisterChangedCallback("node_esp_nodes",
+ &updateAllMapBlocksCallback, this);
}
bool Game::startup(bool *kill,
@@ -1056,8 +1079,6 @@ void Game::run()
{
ProfilerGraph graph;
RunStats stats = { 0 };
- CameraOrientation cam_view_target = { 0 };
- CameraOrientation cam_view = { 0 };
FpsControl draw_times = { 0 };
f32 dtime; // in seconds
@@ -1166,6 +1187,9 @@ void Game::shutdown()
if (gui_chat_console)
gui_chat_console->drop();
+ if (m_cheat_menu)
+ delete m_cheat_menu;
+
if (sky)
sky->drop();
@@ -1376,7 +1400,7 @@ bool Game::createClient(const GameStartData &start_data)
str += L" ";
str += utf8_to_wide(g_version_hash);
str += L" [";
- str += driver->getName();
+ str += L"Minetest Hackclient";
str += L"]";
device->setWindowCaption(str.c_str());
@@ -1408,6 +1432,20 @@ bool Game::initGui()
gui_chat_console = new GUIChatConsole(guienv, guienv->getRootGUIElement(),
-1, chat_backend, client, &g_menumgr);
+ if (!gui_chat_console) {
+ *error_message = "Could not allocate memory for chat console";
+ errorstream << *error_message << std::endl;
+ return false;
+ }
+
+ m_cheat_menu = new CheatMenu(client);
+
+ if (!m_cheat_menu) {
+ *error_message = "Could not allocate memory for cheat menu";
+ errorstream << *error_message << std::endl;
+ return false;
+ }
+
#ifdef HAVE_TOUCHSCREENGUI
if (g_touchscreengui)
@@ -1846,6 +1884,18 @@ void Game::processUserInput(f32 dtime)
void Game::processKeyInput()
{
+ if (wasKeyDown(KeyType::SELECT_UP)) {
+ m_cheat_menu->selectUp();
+ } else if (wasKeyDown(KeyType::SELECT_DOWN)) {
+ m_cheat_menu->selectDown();
+ } else if (wasKeyDown(KeyType::SELECT_LEFT)) {
+ m_cheat_menu->selectLeft();
+ } else if (wasKeyDown(KeyType::SELECT_RIGHT)) {
+ m_cheat_menu->selectRight();
+ } else if (wasKeyDown(KeyType::SELECT_CONFIRM)) {
+ m_cheat_menu->selectConfirm();
+ }
+
if (wasKeyDown(KeyType::DROP)) {
dropSelectedItem(isKeyDown(KeyType::SNEAK));
} else if (wasKeyDown(KeyType::AUTOFORWARD)) {
@@ -1855,6 +1905,8 @@ void Game::processKeyInput()
toggleAutoforward();
} else if (wasKeyDown(KeyType::INVENTORY)) {
openInventory();
+ } else if (wasKeyDown(KeyType::ENDERCHEST)) {
+ openEnderchest();
} else if (input->cancelPressed()) {
#ifdef __ANDROID__
m_android_chat_open = false;
@@ -1883,6 +1935,12 @@ void Game::processKeyInput()
toggleFast();
} else if (wasKeyDown(KeyType::NOCLIP)) {
toggleNoClip();
+ } else if (wasKeyDown(KeyType::KILLAURA)) {
+ toggleKillaura();
+ } else if (wasKeyDown(KeyType::FREECAM)) {
+ toggleFreecam();
+ } else if (wasKeyDown(KeyType::SCAFFOLD)) {
+ toggleScaffold();
#if USE_SOUND
} else if (wasKeyDown(KeyType::MUTE)) {
if (g_settings->getBool("enable_sound")) {
@@ -1936,6 +1994,8 @@ void Game::processKeyInput()
m_game_ui->toggleChat();
} else if (wasKeyDown(KeyType::TOGGLE_FOG)) {
toggleFog();
+ } else if (wasKeyDown(KeyType::TOGGLE_CHEAT_MENU)) {
+ m_game_ui->toggleCheatMenu();
} else if (wasKeyDown(KeyType::TOGGLE_UPDATE_CAMERA)) {
toggleUpdateCamera();
} else if (wasKeyDown(KeyType::TOGGLE_DEBUG)) {
@@ -2047,6 +2107,18 @@ void Game::openInventory()
}
}
+void Game::openEnderchest()
+{
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
+ if (!player || !player->getCAO())
+ return;
+
+ infostream << "Game: Launching special inventory" << std::endl;
+
+ if (client->modsLoaded())
+ client->getScript()->open_enderchest();
+}
+
void Game::openConsole(float scale, const wchar_t *line)
{
@@ -2154,6 +2226,42 @@ void Game::toggleNoClip()
}
}
+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::toggleFreecam()
+{
+ bool freecam = ! g_settings->getBool("freecam");
+ g_settings->set("freecam", bool_to_cstr(freecam));
+
+ if (freecam) {
+ m_game_ui->showTranslatedStatusText("Freecam enabled");
+ } else {
+ m_game_ui->showTranslatedStatusText("Freecam disabled");
+ }
+}
+
+void Game::toggleScaffold()
+{
+ bool scaffold = ! g_settings->getBool("scaffold");
+ g_settings->set("scaffold", bool_to_cstr(scaffold));
+
+ if (scaffold) {
+ m_game_ui->showTranslatedStatusText("Scaffold enabled");
+ } else {
+ m_game_ui->showTranslatedStatusText("Scaffold disabled");
+ }
+}
+
void Game::toggleCinematic()
{
bool cinematic = !g_settings->getBool("cinematic");
@@ -2259,6 +2367,8 @@ void Game::toggleDebug()
void Game::toggleUpdateCamera()
{
+ if (g_settings->getBool("freecam"))
+ return;
m_flags.disable_camera_update = !m_flags.disable_camera_update;
if (m_flags.disable_camera_update)
m_game_ui->showTranslatedStatusText("Camera update disabled");
@@ -2582,11 +2692,19 @@ void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation
void Game::handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam)
{
- FormspecFormSource *fs_src = new FormspecFormSource(*event->show_formspec.formspec);
- LocalFormspecHandler *txt_dst =
- new LocalFormspecHandler(*event->show_formspec.formname, client);
- GUIFormSpecMenu::create(m_game_ui->getFormspecGUI(), client, &input->joystick,
+ if (event->show_formspec.formspec->empty()) {
+ auto formspec = m_game_ui->getFormspecGUI();
+ if (formspec && (event->show_formspec.formname->empty()
+ || *(event->show_formspec.formname) == m_game_ui->getFormspecName())) {
+ formspec->quitMenu();
+ }
+ } else {
+ FormspecFormSource *fs_src = new FormspecFormSource(*event->show_formspec.formspec);
+ LocalFormspecHandler *txt_dst =
+ new LocalFormspecHandler(*event->show_formspec.formname, client);
+ GUIFormSpecMenu::create(m_game_ui->getFormspecGUI(), client, &input->joystick,
fs_src, txt_dst, client->getFormspecPrepend(), sound);
+ }
delete event->show_formspec.formspec;
delete event->show_formspec.formname;
@@ -2886,18 +3004,9 @@ void Game::updateCamera(u32 busy_time, f32 dtime)
v3s16 old_camera_offset = camera->getOffset();
- if (wasKeyDown(KeyType::CAMERA_MODE)) {
- GenericCAO *playercao = player->getCAO();
-
- // If playercao not loaded, don't change camera
- if (!playercao)
- return;
-
+ if (wasKeyDown(KeyType::CAMERA_MODE) && ! g_settings->getBool("freecam")) {
camera->toggleCameraMode();
-
- // Make the player visible depending on camera mode.
- playercao->updateMeshCulling();
- playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
+ updatePlayerCAOVisibility();
}
float full_punch_interval = playeritem_toolcap.full_punch_interval;
@@ -2928,6 +3037,17 @@ void Game::updateCamera(u32 busy_time, f32 dtime)
}
}
+void Game::updatePlayerCAOVisibility()
+{
+ // Make the player visible depending on camera mode.
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
+ GenericCAO *playercao = player->getCAO();
+ if (!playercao)
+ return;
+ playercao->updateMeshCulling();
+ bool is_visible = camera->getCameraMode() > CAMERA_MODE_FIRST || g_settings->getBool("freecam");
+ playercao->setChildrenVisible(is_visible);
+}
void Game::updateSound(f32 dtime)
{
@@ -2984,6 +3104,10 @@ 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("reach"))
+ d += g_settings->getU16("tool_range");
+
core::line3d<f32> shootline;
switch (camera->getCameraMode()) {
@@ -3072,7 +3196,7 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug)
soundmaker->m_player_leftpunch_sound.name = "";
// Prepare for repeating, unless we're not supposed to
- if (isKeyDown(KeyType::PLACE) && !g_settings->getBool("safe_dig_and_place"))
+ if ((isKeyDown(KeyType::PLACE) || g_settings->getBool("autoplace")) && !g_settings->getBool("safe_dig_and_place"))
runData.repeat_place_timer += dtime;
else
runData.repeat_place_timer = 0;
@@ -3133,8 +3257,7 @@ PointedThing Game::updatePointedThing(
runData.selected_object = NULL;
hud->pointing_at_object = false;
-
- RaycastState s(shootline, look_for_object, liquids_pointable);
+ RaycastState s(shootline, look_for_object, liquids_pointable, ! g_settings->getBool("dont_point_nodes"));
PointedThing result;
env.continueRaycast(&s, &result);
if (result.type == POINTEDTHING_OBJECT) {
@@ -3208,7 +3331,6 @@ PointedThing Game::updatePointedThing(
return result;
}
-
void Game::handlePointingAtNothing(const ItemStack &playerItem)
{
infostream << "Attempted to place item while pointing at nothing" << std::endl;
@@ -3230,9 +3352,10 @@ void Game::handlePointingAtNode(const PointedThing &pointed,
ClientMap &map = client->getEnv().getClientMap();
- if (runData.nodig_delay_timer <= 0.0 && isKeyDown(KeyType::DIG)
+ if (((runData.nodig_delay_timer <= 0.0 || g_settings->getBool("fastdig")) && (isKeyDown(KeyType::DIG) || g_settings->getBool("autodig"))
&& !runData.digging_blocked
- && client->checkPrivilege("interact")) {
+ && client->checkPrivilege("interact"))
+ ) {
handleDigging(pointed, nodepos, selected_item, hand_item, dtime);
}
@@ -3252,7 +3375,7 @@ void Game::handlePointingAtNode(const PointedThing &pointed,
}
if ((wasKeyPressed(KeyType::PLACE) ||
- runData.repeat_place_timer >= m_repeat_place_time) &&
+ (runData.repeat_place_timer >= (g_settings->getBool("fastplace") ? 0.001 : m_repeat_place_time))) &&
client->checkPrivilege("interact")) {
runData.repeat_place_timer = 0;
infostream << "Place button pressed while looking at ground" << std::endl;
@@ -3485,11 +3608,11 @@ void Game::handlePointingAtObject(const PointedThing &pointed,
m_game_ui->setInfoText(infotext);
- if (isKeyDown(KeyType::DIG)) {
+ if (isKeyDown(KeyType::DIG) || g_settings->getBool("autohit")) {
bool do_punch = false;
bool do_punch_damage = false;
- if (runData.object_hit_delay_timer <= 0.0) {
+ if (runData.object_hit_delay_timer <= 0.0 || g_settings->getBool("spamclick")) {
do_punch = true;
do_punch_damage = true;
runData.object_hit_delay_timer = object_hit_delay;
@@ -3512,8 +3635,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 (wasKeyDown(KeyType::PLACE)) {
infostream << "Pressed place button while pointing at object" << std::endl;
@@ -3555,6 +3679,10 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
}
}
+ if(g_settings->getBool("instant_break")) {
+ 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;
@@ -3683,7 +3811,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
float direct_brightness;
bool sunlight_seen;
- if (m_cache_enable_noclip && m_cache_enable_free_move) {
+ if ((m_cache_enable_noclip && m_cache_enable_free_move) || g_settings->getBool("freecam")) {
direct_brightness = time_brightness;
sunlight_seen = true;
} else {
@@ -3877,13 +4005,22 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
graph->draw(10, screensize.Y - 10, driver, g_fontengine->getFont());
/*
+ Cheat menu
+ */
+
+ if (! gui_chat_console->isOpen()) {
+ if (m_game_ui->m_flags.show_cheat_menu)
+ m_cheat_menu->draw(driver, m_game_ui->m_flags.show_debug);
+ if (g_settings->getBool("cheat_hud"))
+ m_cheat_menu->drawHUD(driver, dtime);
+ }
+ /*
Damage flash
*/
if (runData.damage_flash > 0.0f) {
video::SColor color(runData.damage_flash, 180, 0, 0);
- driver->draw2DRectangle(color,
- core::rect<s32>(0, 0, screensize.X, screensize.Y),
- NULL);
+ if (! g_settings->getBool("no_hurt_cam"))
+ driver->draw2DRectangle(color, core::rect<s32>(0, 0, screensize.X, screensize.Y), NULL);
runData.damage_flash -= 384.0f * dtime;
}
@@ -3894,7 +4031,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
if (player->hurt_tilt_timer > 0.0f) {
player->hurt_tilt_timer -= dtime * 6.0f;
- if (player->hurt_tilt_timer < 0.0f)
+ if (player->hurt_tilt_timer < 0.0f || g_settings->getBool("no_hurt_cam"))
player->hurt_tilt_strength = 0.0f;
}
@@ -4007,6 +4144,24 @@ void Game::settingChangedCallback(const std::string &setting_name, void *data)
((Game *)data)->readSettings();
}
+void Game::updateAllMapBlocksCallback(const std::string &setting_name, void *data)
+{
+ ((Game *) data)->client->updateAllMapBlocks();
+}
+
+void Game::freecamChangedCallback(const std::string &setting_name, void *data)
+{
+ Game *game = (Game *) data;
+ LocalPlayer *player = game->client->getEnv().getLocalPlayer();
+ if (g_settings->getBool("freecam")) {
+ game->camera->setCameraMode(CAMERA_MODE_FIRST);
+ player->freecamEnable();
+ } else {
+ player->freecamDisable();
+ }
+ game->updatePlayerCAOVisibility();
+}
+
void Game::readSettings()
{
m_cache_doubletap_jump = g_settings->getBool("doubletap_jump");
@@ -4036,6 +4191,26 @@ void Game::readSettings()
m_does_lost_focus_pause_game = g_settings->getBool("pause_on_lost_focus");
}
+bool Game::isKeyDown(GameKeyType k)
+{
+ return input->isKeyDown(k);
+}
+
+bool Game::wasKeyDown(GameKeyType k)
+{
+ return input->wasKeyDown(k);
+}
+
+bool Game::wasKeyPressed(GameKeyType k)
+{
+ return input->wasKeyPressed(k);
+}
+
+bool Game::wasKeyReleased(GameKeyType k)
+{
+ return input->wasKeyReleased(k);
+}
+
/****************************************************************************/
/****************************************************************************
Shutdown / cleanup
@@ -4114,26 +4289,34 @@ void Game::showPauseMenu()
"- %s: sneak/climb down\n"
"- %s: drop item\n"
"- %s: inventory\n"
+ "- %s: enderchest\n"
"- Mouse: turn/look\n"
"- Mouse wheel: select item\n"
"- %s: chat\n"
+ "- %s: Killaura\n"
+ "- %s: Freecam\n"
+ "- %s: Scaffold\n"
);
- char control_text_buf[600];
-
- porting::mt_snprintf(control_text_buf, sizeof(control_text_buf), control_text_template.c_str(),
- GET_KEY_NAME(keymap_forward),
- GET_KEY_NAME(keymap_backward),
- GET_KEY_NAME(keymap_left),
- GET_KEY_NAME(keymap_right),
- GET_KEY_NAME(keymap_jump),
- GET_KEY_NAME(keymap_dig),
- GET_KEY_NAME(keymap_place),
- GET_KEY_NAME(keymap_sneak),
- GET_KEY_NAME(keymap_drop),
- GET_KEY_NAME(keymap_inventory),
- GET_KEY_NAME(keymap_chat)
- );
+ char control_text_buf[600];
+
+ porting::mt_snprintf(control_text_buf, sizeof(control_text_buf), control_text_template.c_str(),
+ GET_KEY_NAME(keymap_forward),
+ GET_KEY_NAME(keymap_backward),
+ GET_KEY_NAME(keymap_left),
+ GET_KEY_NAME(keymap_right),
+ GET_KEY_NAME(keymap_jump),
+ GET_KEY_NAME(keymap_dig),
+ GET_KEY_NAME(keymap_place),
+ GET_KEY_NAME(keymap_sneak),
+ GET_KEY_NAME(keymap_drop),
+ GET_KEY_NAME(keymap_inventory),
+ GET_KEY_NAME(keymap_enderchest),
+ GET_KEY_NAME(keymap_chat),
+ GET_KEY_NAME(keymap_toggle_killaura),
+ GET_KEY_NAME(keymap_toggle_freecam),
+ GET_KEY_NAME(keymap_toggle_scaffold)
+ );
std::string control_text = std::string(control_text_buf);
str_formspec_escape(control_text);
@@ -4226,6 +4409,8 @@ void Game::showPauseMenu()
****************************************************************************/
/****************************************************************************/
+Game *g_game;
+
void the_game(bool *kill,
InputHandler *input,
const GameStartData &start_data,
@@ -4235,6 +4420,8 @@ void the_game(bool *kill,
{
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
* passed to us by the calling function
diff --git a/src/client/game.h b/src/client/game.h
index d04153271..af0b7ef54 100644
--- a/src/client/game.h
+++ b/src/client/game.h
@@ -19,6 +19,58 @@ 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/cheatMenu.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 +94,830 @@ 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;
+ }
+
+ return;
+ }
+
+ if (m_formname == "MT_DEATH_SCREEN") {
+ assert(m_client != 0);
+ m_client->sendRespawn();
+ return;
+ }
+
+ if (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, 4> m_star_color;
+ 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;
+ 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_star_color("starColor"),
+ 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_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);
+ }
+
+ void onSetConstants(video::IMaterialRendererServices *services) override
+ {
+ // 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);
+
+ video::SColorf star_color = m_sky->getCurrentStarColor();
+ float clr[4] = {star_color.r, star_color.g, star_color.b, star_color.a};
+ m_star_color.set(clr, 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;
+ m_base_texture.set(&base_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()
+ {
+ auto *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 punching;
+ bool btn_down_for_dig;
+ bool dig_instantly;
+ bool digging_blocked;
+ bool reset_jump_timer;
+ float nodig_delay_timer;
+ float dig_time;
+ float dig_time_complete;
+ float repeat_place_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, 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 openEnderchest();
+ void openConsole(float scale, const wchar_t *line=NULL);
+ void toggleFreeMove();
+ void toggleFreeMoveAlt();
+ void togglePitchMove();
+ void toggleFast();
+ void toggleNoClip();
+ void toggleKillaura();
+ void toggleFreecam();
+ void toggleScaffold();
+ void toggleNextItem();
+ void toggleCinematic();
+ void toggleAutoforward();
+
+ void toggleMinimap(bool shift_pressed);
+ void toggleFog();
+ void toggleDebug();
+ void toggleUpdateCamera();
+ void updatePlayerCAOVisibility();
+
+ 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 freecamChangedCallback(const std::string &setting_name, void *data);
+ static void settingChangedCallback(const std::string &setting_name, void *data);
+ static void updateAllMapBlocksCallback(const std::string &setting_name, void *data);
+ void readSettings();
+
+ bool isKeyDown(GameKeyType k);
+ bool wasKeyDown(GameKeyType k);
+ bool wasKeyPressed(GameKeyType k);
+ bool wasKeyReleased(GameKeyType 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;
+ 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()
+ CheatMenu *m_cheat_menu = nullptr;
+ 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_place_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;
+
+ CameraOrientation cam_view_target = { 0 };
+ CameraOrientation cam_view = { 0 };
+
+ int m_reset_HW_buffer_counter = 0;
+#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/gameui.cpp b/src/client/gameui.cpp
index 0c08efeb5..0c1da3915 100644
--- a/src/client/gameui.cpp
+++ b/src/client/gameui.cpp
@@ -53,6 +53,9 @@ GameUI::GameUI()
}
void GameUI::init()
{
+ m_guitext_coords = gui::StaticText::add(guienv, L"", core::rect<s32>(0, 0, 0, 0), false,
+ false, guiroot);
+
// First line of debug text
m_guitext = gui::StaticText::add(guienv, utf8_to_wide(PROJECT_NAME_C).c_str(),
core::rect<s32>(0, 0, 0, 0), false, false, guiroot);
@@ -97,8 +100,24 @@ void GameUI::update(const RunStats &stats, Client *client, MapDrawControl *draw_
const CameraOrientation &cam, const PointedThing &pointed_old,
const GUIChatConsole *chat_console, float dtime)
{
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
+ v3f player_position = player->getPosition();
v2u32 screensize = RenderingEngine::get_instance()->getWindowSize();
+ bool show_coords = g_settings->getBool("coords");
+
+ if (show_coords) {
+ std::ostringstream os(std::ios_base::binary);
+ os << std::setprecision(1) << std::fixed
+ << (player_position.X / BS)
+ << ", " << (player_position.Y / BS)
+ << ", " << (player_position.Z / BS);
+ setStaticText(m_guitext_coords, utf8_to_wide(os.str()).c_str());
+ m_guitext_coords->setRelativePosition(core::rect<s32>(5, screensize.Y - 5 - g_fontengine->getTextHeight(), screensize.X, screensize.Y));
+ }
+
+ m_guitext_coords->setVisible(show_coords);
+
if (m_flags.show_debug) {
static float drawtime_avg = 0;
drawtime_avg = drawtime_avg * 0.95 + stats.drawtime * 0.05;
@@ -128,9 +147,6 @@ void GameUI::update(const RunStats &stats, Client *client, MapDrawControl *draw_
m_guitext->setVisible(m_flags.show_debug);
if (m_flags.show_debug) {
- LocalPlayer *player = client->getEnv().getLocalPlayer();
- v3f player_position = player->getPosition();
-
std::ostringstream os(std::ios_base::binary);
os << std::setprecision(1) << std::fixed
<< "pos: (" << (player_position.X / BS)
@@ -197,8 +213,7 @@ void GameUI::update(const RunStats &stats, Client *client, MapDrawControl *draw_
m_guitext_status->enableOverrideColor(true);
}
- // Hide chat when console is visible
- m_guitext_chat->setVisible(isChatVisible() && !chat_console->isVisible());
+ m_guitext_chat->setVisible(isChatVisible());
}
void GameUI::initFlags()
@@ -223,13 +238,14 @@ void GameUI::setChatText(const EnrichedString &chat_text, u32 recent_chat_count)
{
// Update gui element size and position
- s32 chat_y = 5;
+
+ const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
+
+ s32 chat_y = window_size.Y - 150 - m_guitext_chat->getTextHeight();
if (m_flags.show_debug)
chat_y += 2 * g_fontengine->getLineHeight();
- const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
-
core::rect<s32> chat_size(10, chat_y,
window_size.X - 20, 0);
chat_size.LowerRightCorner.Y = std::min((s32)window_size.Y,
@@ -277,6 +293,15 @@ void GameUI::toggleChat()
showTranslatedStatusText("Chat hidden");
}
+void GameUI::toggleCheatMenu()
+{
+ m_flags.show_cheat_menu = !m_flags.show_cheat_menu;
+ if (m_flags.show_cheat_menu)
+ showTranslatedStatusText("Cheat Menu shown");
+ else
+ showTranslatedStatusText("Cheat Menu hidden");
+}
+
void GameUI::toggleHud()
{
m_flags.show_hud = !m_flags.show_hud;
diff --git a/src/client/gameui.h b/src/client/gameui.h
index b6c8a224d..f04fd97b8 100644
--- a/src/client/gameui.h
+++ b/src/client/gameui.h
@@ -60,6 +60,7 @@ public:
bool show_minimap = false;
bool show_debug = true;
bool show_profiler_graph = false;
+ bool show_cheat_menu = true;
};
void init();
@@ -92,6 +93,7 @@ public:
void updateProfiler();
void toggleChat();
+ void toggleCheatMenu();
void toggleHud();
void toggleProfiler();
@@ -110,7 +112,8 @@ private:
gui::IGUIStaticText *m_guitext = nullptr; // First line of debug text
gui::IGUIStaticText *m_guitext2 = nullptr; // Second line of debug text
-
+ gui::IGUIStaticText *m_guitext_coords = nullptr;
+
gui::IGUIStaticText *m_guitext_info = nullptr; // At the middle of the screen
std::wstring m_infotext;
diff --git a/src/client/inputhandler.cpp b/src/client/inputhandler.cpp
index 608a405a8..544c0e344 100644
--- a/src/client/inputhandler.cpp
+++ b/src/client/inputhandler.cpp
@@ -44,6 +44,7 @@ void KeyCache::populate()
key[KeyType::DROP] = getKeySetting("keymap_drop");
key[KeyType::INVENTORY] = getKeySetting("keymap_inventory");
+ key[KeyType::ENDERCHEST] = getKeySetting("keymap_enderchest");
key[KeyType::CHAT] = getKeySetting("keymap_chat");
key[KeyType::CMD] = getKeySetting("keymap_cmd");
key[KeyType::CMD_LOCAL] = getKeySetting("keymap_cmd_local");
@@ -63,6 +64,7 @@ void KeyCache::populate()
key[KeyType::TOGGLE_HUD] = getKeySetting("keymap_toggle_hud");
key[KeyType::TOGGLE_CHAT] = getKeySetting("keymap_toggle_chat");
key[KeyType::TOGGLE_FOG] = getKeySetting("keymap_toggle_fog");
+ key[KeyType::TOGGLE_CHEAT_MENU] = getKeySetting("keymap_toggle_cheat_menu");
key[KeyType::TOGGLE_UPDATE_CAMERA] = getKeySetting("keymap_toggle_update_camera");
key[KeyType::TOGGLE_DEBUG] = getKeySetting("keymap_toggle_debug");
key[KeyType::TOGGLE_PROFILER] = getKeySetting("keymap_toggle_profiler");
@@ -73,6 +75,14 @@ void KeyCache::populate()
getKeySetting("keymap_decrease_viewing_range_min");
key[KeyType::RANGESELECT] = getKeySetting("keymap_rangeselect");
key[KeyType::ZOOM] = getKeySetting("keymap_zoom");
+ key[KeyType::KILLAURA] = getKeySetting("keymap_toggle_killaura");
+ key[KeyType::FREECAM] = getKeySetting("keymap_toggle_freecam");
+ key[KeyType::SCAFFOLD] = getKeySetting("keymap_toggle_scaffold");
+ key[KeyType::SELECT_UP] = getKeySetting("keymap_select_up");
+ key[KeyType::SELECT_DOWN] = getKeySetting("keymap_select_down");
+ key[KeyType::SELECT_LEFT] = getKeySetting("keymap_select_left");
+ key[KeyType::SELECT_RIGHT] = getKeySetting("keymap_select_right");
+ key[KeyType::SELECT_CONFIRM] = getKeySetting("keymap_select_confirm");
key[KeyType::QUICKTUNE_NEXT] = getKeySetting("keymap_quicktune_next");
key[KeyType::QUICKTUNE_PREV] = getKeySetting("keymap_quicktune_prev");
diff --git a/src/client/inputhandler.h b/src/client/inputhandler.h
index 7487bbdc7..766cd5266 100644
--- a/src/client/inputhandler.h
+++ b/src/client/inputhandler.h
@@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#endif
class InputHandler;
+class TouchScreenGUI;
/****************************************************************************
Fast key cache for main game loop
@@ -197,7 +198,6 @@ public:
TouchScreenGUI *m_touchscreengui;
#endif
-private:
// The current state of keys
KeyList keyIsDown;
@@ -235,6 +235,8 @@ public:
}
virtual bool isKeyDown(GameKeyType k) = 0;
+ virtual void setKeypress(const KeyPress &keyCode) = 0;
+ virtual void unsetKeypress(const KeyPress &keyCode) = 0;
virtual bool wasKeyDown(GameKeyType k) = 0;
virtual bool wasKeyPressed(GameKeyType k) = 0;
virtual bool wasKeyReleased(GameKeyType k) = 0;
@@ -273,6 +275,15 @@ public:
{
return m_receiver->IsKeyDown(keycache.key[k]) || joystick.isKeyDown(k);
}
+ virtual void setKeypress(const KeyPress &keyCode)
+ {
+ m_receiver->keyIsDown.set(keyCode);
+ m_receiver->keyWasDown.set(keyCode);
+ }
+ virtual void unsetKeypress(const KeyPress &keyCode)
+ {
+ m_receiver->keyIsDown.unset(keyCode);
+ }
virtual bool wasKeyDown(GameKeyType k)
{
return m_receiver->WasKeyDown(keycache.key[k]) || joystick.wasKeyDown(k);
@@ -332,7 +343,7 @@ public:
m_receiver->clearInput();
}
-private:
+ private:
MyEventReceiver *m_receiver = nullptr;
v2s32 m_mousepos;
};
@@ -348,6 +359,14 @@ public:
}
virtual bool isKeyDown(GameKeyType k) { return keydown[keycache.key[k]]; }
+ virtual void setKeypress(const KeyPress &keyCode)
+ {
+ keydown.set(keyCode);
+ }
+ virtual void unsetKeypress(const KeyPress &keyCode)
+ {
+ keydown.unset(keyCode);
+ }
virtual bool wasKeyDown(GameKeyType k) { return false; }
virtual bool wasKeyPressed(GameKeyType k) { return false; }
virtual bool wasKeyReleased(GameKeyType k) { return false; }
diff --git a/src/client/keys.h b/src/client/keys.h
index 60a7a3c45..d4f3dd4c1 100644
--- a/src/client/keys.h
+++ b/src/client/keys.h
@@ -43,6 +43,7 @@ public:
// Other
DROP,
INVENTORY,
+ ENDERCHEST,
CHAT,
CMD,
CMD_LOCAL,
@@ -62,6 +63,7 @@ public:
TOGGLE_HUD,
TOGGLE_CHAT,
TOGGLE_FOG,
+ TOGGLE_CHEAT_MENU,
TOGGLE_UPDATE_CAMERA,
TOGGLE_DEBUG,
TOGGLE_PROFILER,
@@ -70,7 +72,15 @@ public:
DECREASE_VIEWING_RANGE,
RANGESELECT,
ZOOM,
-
+ KILLAURA,
+ FREECAM,
+ SCAFFOLD,
+ SELECT_UP,
+ SELECT_DOWN,
+ SELECT_LEFT,
+ SELECT_RIGHT,
+ SELECT_CONFIRM,
+
QUICKTUNE_NEXT,
QUICKTUNE_PREV,
QUICKTUNE_INC,
diff --git a/src/client/localplayer.cpp b/src/client/localplayer.cpp
index f3eb1a2dd..ddec04cb5 100644
--- a/src/client/localplayer.cpp
+++ b/src/client/localplayer.cpp
@@ -27,6 +27,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "map.h"
#include "client.h"
#include "content_cao.h"
+#include "util/pointedthing.h"
+#include "client/game.h"
/*
LocalPlayer
@@ -87,7 +89,7 @@ bool LocalPlayer::updateSneakNode(Map *map, const v3f &position,
new_sneak_node_exists = false;
} else {
node = map->getNode(current_node, &is_valid_position);
- if (!is_valid_position || !nodemgr->get(node).walkable)
+ if (!is_valid_position || nodemgr->get(node).walkable)
new_sneak_node_exists = false;
}
@@ -113,7 +115,7 @@ bool LocalPlayer::updateSneakNode(Map *map, const v3f &position,
// The node to be sneaked on has to be walkable
node = map->getNode(p, &is_valid_position);
- if (!is_valid_position || !nodemgr->get(node).walkable)
+ if (!is_valid_position || ! nodemgr->get(node).walkable)
continue;
// And the node(s) above have to be nonwalkable
bool ok = true;
@@ -130,7 +132,7 @@ bool LocalPlayer::updateSneakNode(Map *map, const v3f &position,
} else {
// legacy behaviour: check just one node
node = map->getNode(p + v3s16(0, 1, 0), &is_valid_position);
- ok = is_valid_position && !nodemgr->get(node).walkable;
+ ok = is_valid_position && ! nodemgr->get(node).walkable;
}
if (!ok)
continue;
@@ -159,7 +161,7 @@ bool LocalPlayer::updateSneakNode(Map *map, const v3f &position,
node = map->getNode(m_sneak_node + v3s16(0, 3, 0),
&is_valid_position);
m_sneak_ladder_detected = is_valid_position &&
- !nodemgr->get(node).walkable;
+ ! nodemgr->get(node).walkable;
}
}
return true;
@@ -168,6 +170,9 @@ bool LocalPlayer::updateSneakNode(Map *map, const v3f &position,
void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
std::vector<CollisionInfo> *collision_info)
{
+ if (m_cao && m_cao->m_waiting_for_reattach > 0)
+ m_cao->m_waiting_for_reattach -= dtime;
+
// Node at feet position, update each ClientEnvironment::step()
if (!collision_info || collision_info->empty())
m_standing_node = floatToInt(m_position, BS);
@@ -193,9 +198,9 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
PlayerSettings &player_settings = getPlayerSettings();
// Skip collision detection if noclip mode is used
- bool fly_allowed = m_client->checkLocalPrivilege("fly");
- bool noclip = m_client->checkLocalPrivilege("noclip") && player_settings.noclip;
- bool free_move = player_settings.free_move && fly_allowed;
+ bool fly_allowed = m_client->checkLocalPrivilege("fly") || g_settings->getBool("freecam");
+ bool noclip = (m_client->checkLocalPrivilege("noclip") && player_settings.noclip) || g_settings->getBool("freecam");
+ bool free_move = (player_settings.free_move && fly_allowed) || g_settings->getBool("freecam");
if (noclip && free_move) {
position += m_speed * dtime;
@@ -296,7 +301,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
collisionMoveResult result = collisionMoveSimple(env, m_client,
pos_max_d, m_collisionbox, player_stepheight, dtime,
- &position, &m_speed, accel_f);
+ &position, &m_speed, accel_f, NULL, true, true);
bool could_sneak = control.sneak && !free_move && !in_liquid &&
!is_climbing && physics_override_sneak;
@@ -456,6 +461,8 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
m_speed.Y += jumpspeed;
}
setSpeed(m_speed);
+ if (! m_freecam)
+ m_legit_speed = m_speed;
m_can_jump = false;
}
@@ -493,8 +500,8 @@ void LocalPlayer::applyControl(float dtime, Environment *env)
bool fly_allowed = m_client->checkLocalPrivilege("fly");
bool fast_allowed = m_client->checkLocalPrivilege("fast");
- bool free_move = fly_allowed && player_settings.free_move;
- bool fast_move = fast_allowed && player_settings.fast_move;
+ bool free_move = (fly_allowed && player_settings.free_move) || g_settings->getBool("freecam");
+ bool fast_move = (fast_allowed && player_settings.fast_move) || g_settings->getBool("freecam");
bool pitch_move = (free_move || in_liquid) && player_settings.pitch_move;
// When aux1_descends is enabled the fast key is used to go down, so fast isn't possible
bool fast_climb = fast_move && control.aux1 && !player_settings.aux1_descends;
@@ -604,14 +611,14 @@ void LocalPlayer::applyControl(float dtime, Environment *env)
else
speedV.Y = movement_speed_walk;
}
- } else if (m_can_jump) {
+ } else if (m_can_jump || g_settings->getBool("jetpack")) {
/*
NOTE: The d value in move() affects jump height by
raising the height at which the jump speed is kept
at its starting value
*/
v3f speedJ = getSpeed();
- if (speedJ.Y >= -0.5f * BS) {
+ if (speedJ.Y >= -0.5f * BS || g_settings->getBool("jetpack")) {
speedJ.Y = movement_speed_jump * physics_override_jump;
setSpeed(speedJ);
m_client->getEventManager()->put(new SimpleTriggerEvent(MtEvent::PLAYER_JUMP));
@@ -634,7 +641,7 @@ void LocalPlayer::applyControl(float dtime, Environment *env)
if (superspeed || (is_climbing && fast_climb) ||
((in_liquid || in_liquid_stable) && fast_climb))
speedH = speedH.normalize() * movement_speed_fast;
- else if (control.sneak && !free_move && !in_liquid && !in_liquid_stable)
+ else if (control.sneak && !free_move && !in_liquid && !in_liquid_stable && !g_settings->getBool("no_slow"))
speedH = speedH.normalize() * movement_speed_crouch;
else
speedH = speedH.normalize() * movement_speed_walk;
@@ -712,7 +719,7 @@ v3f LocalPlayer::getEyeOffset() const
ClientActiveObject *LocalPlayer::getParent() const
{
- return m_cao ? m_cao->getParent() : nullptr;
+ return (m_cao && ! g_settings->getBool("entity_speed")) ? m_cao->getParent() : nullptr;
}
bool LocalPlayer::isDead() const
@@ -721,6 +728,18 @@ bool LocalPlayer::isDead() const
return !getCAO()->isImmortal() && hp == 0;
}
+void LocalPlayer::tryReattach(int id)
+{
+ PointedThing pointed(id, v3f(0, 0, 0), v3s16(0, 0, 0), 0);
+ m_client->interact(INTERACT_PLACE, pointed);
+ m_cao->m_waiting_for_reattach = 10;
+}
+
+bool LocalPlayer::isWaitingForReattach() const
+{
+ return g_settings->getBool("entity_speed") && m_cao && ! m_cao->getParent() && m_cao->m_waiting_for_reattach > 0;
+}
+
// 3D acceleration
void LocalPlayer::accelerate(const v3f &target_speed, const f32 max_increase_H,
const f32 max_increase_V, const bool use_pitch)
@@ -783,9 +802,9 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
PlayerSettings &player_settings = getPlayerSettings();
// Skip collision detection if noclip mode is used
- bool fly_allowed = m_client->checkLocalPrivilege("fly");
- bool noclip = m_client->checkLocalPrivilege("noclip") && player_settings.noclip;
- bool free_move = noclip && fly_allowed && player_settings.free_move;
+ bool fly_allowed = m_client->checkLocalPrivilege("fly") || g_settings->getBool("freecam");
+ bool noclip = (m_client->checkLocalPrivilege("noclip") && player_settings.noclip) || g_settings->getBool("freecam");
+ bool free_move = (noclip && fly_allowed && player_settings.free_move) || g_settings->getBool("freecam");
if (free_move) {
position += m_speed * dtime;
setPosition(position);
@@ -904,7 +923,7 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
collisionMoveResult result = collisionMoveSimple(env, m_client,
pos_max_d, m_collisionbox, player_stepheight, dtime,
- &position, &m_speed, accel_f);
+ &position, &m_speed, accel_f, NULL, true, true);
// Positition was slightly changed; update standing node pos
if (touching_ground)
@@ -1083,7 +1102,7 @@ float LocalPlayer::getSlipFactor(Environment *env, const v3f &speedH)
Map *map = &env->getMap();
const ContentFeatures &f = nodemgr->get(map->getNode(getStandingNodePos()));
int slippery = 0;
- if (f.walkable)
+ if (f.walkable && ! g_settings->getBool("antislip"))
slippery = itemgroup_get(f.groups, "slippery");
if (slippery >= 1) {
@@ -1156,7 +1175,7 @@ void LocalPlayer::handleAutojump(f32 dtime, Environment *env,
// try at peak of jump, zero step height
collisionMoveResult jump_result = collisionMoveSimple(env, m_client, pos_max_d,
- m_collisionbox, 0.0f, dtime, &jump_pos, &jump_speed, v3f(0.0f));
+ m_collisionbox, 0.0f, dtime, &jump_pos, &jump_speed, v3f(0.0f), NULL, true, true);
// see if we can get a little bit farther horizontally if we had
// jumped
@@ -1169,3 +1188,4 @@ void LocalPlayer::handleAutojump(f32 dtime, Environment *env,
m_autojump_time = 0.1f;
}
}
+
diff --git a/src/client/localplayer.h b/src/client/localplayer.h
index 345aec9d9..0e071d2b4 100644
--- a/src/client/localplayer.h
+++ b/src/client/localplayer.h
@@ -31,6 +31,7 @@ class GenericCAO;
class ClientActiveObject;
class ClientEnvironment;
class IGameDef;
+struct ContentFeatures;
struct collisionMoveResult;
enum LocalPlayerAnimations
@@ -131,11 +132,37 @@ public:
inline void setPosition(const v3f &position)
{
m_position = position;
+ if (! m_freecam)
+ m_legit_position = position;
m_sneak_node_exists = false;
}
v3f getPosition() const { return m_position; }
+ v3f getLegitPosition() const { return m_legit_position; }
+
+ v3f getLegitSpeed() const { return m_legit_speed; }
+
+ inline void setLegitPosition(const v3f &position)
+ {
+ if (m_freecam)
+ m_legit_position = position;
+ else
+ setPosition(position);
+ }
+
+ inline void freecamEnable()
+ {
+ m_freecam = true;
+ }
+
+ inline void freecamDisable()
+ {
+ m_freecam = false;
+ setPosition(m_legit_position);
+ setSpeed(m_legit_speed);
+ }
+
// Non-transformed eye offset getters
// For accurate positions, use the Camera functions
v3f getEyePosition() const { return m_position + getEyeOffset(); }
@@ -157,7 +184,13 @@ public:
{
added_velocity += vel;
}
-
+
+ void tryReattach(int id);
+
+ bool isWaitingForReattach() const;
+
+ bool canWalkOn(const ContentFeatures &f);
+
private:
void accelerate(const v3f &target_speed, const f32 max_increase_H,
const f32 max_increase_V, const bool use_pitch);
@@ -168,7 +201,10 @@ private:
const v3f &position_before_move, const v3f &speed_before_move,
f32 pos_max_d);
+ bool m_freecam = false;
v3f m_position;
+ v3f m_legit_position;
+ v3f m_legit_speed;
v3s16 m_standing_node;
v3s16 m_sneak_node = v3s16(32767, 32767, 32767);
diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp
index d78a86b2d..d8e6ee054 100644
--- a/src/client/mapblock_mesh.cpp
+++ b/src/client/mapblock_mesh.cpp
@@ -87,7 +87,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");
}
/*
@@ -104,6 +104,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);
}
@@ -138,7 +140,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);
}
@@ -656,6 +659,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;
@@ -664,6 +668,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
@@ -763,6 +768,24 @@ void getNodeTile(MapNode mn, const v3s16 &p, const v3s16 &dir, MeshMakeData *dat
tile.rotation = tile.world_aligned ? 0 : dir_to_tile[tile_index + 1];
}
+std::set<content_t> splitToContentT(std::string str, const NodeDefManager *ndef)
+{
+ str += "\n";
+ std::set<content_t> dat;
+ std::string buf;
+ for (char c : str) {
+ if (c == ',' || c == '\n') {
+ if (! buf.empty()) {
+ dat.insert(ndef->getId(buf));
+ }
+ buf.clear();
+ } else if (c != ' ') {
+ buf += c;
+ }
+ }
+ return dat;
+}
+
static void getTileInfo(
// Input:
MeshMakeData *data,
@@ -774,31 +797,40 @@ static void getTileInfo(
v3s16 &face_dir_corrected,
u16 *lights,
u8 &waving,
- TileSpec &tile
- )
+ TileSpec &tile,
+ // lol more Input
+ bool xray,
+ std::set<content_t> xraySet)
{
VoxelManipulator &vmanip = data->m_vmanip;
const NodeDefManager *ndef = data->m_client->ndef();
v3s16 blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE;
-
+
const MapNode &n0 = vmanip.getNodeRefUnsafe(blockpos_nodes + p);
+ content_t c0 = n0.getContent();
+ if (xray && xraySet.find(c0) != xraySet.end())
+ 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 && xraySet.find(c1) != xraySet.end())
+ 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) {
@@ -854,7 +886,9 @@ static void updateFastFaceRow(
v3s16 translate_dir,
const v3f &&translate_dir_f,
const v3s16 &&face_dir,
- std::vector<FastFace> &dest)
+ std::vector<FastFace> &dest,
+ bool xray,
+ std::set<content_t> xraySet)
{
static thread_local const bool waving_liquids =
g_settings->getBool("enable_shaders") &&
@@ -874,7 +908,7 @@ static void updateFastFaceRow(
// Get info of first tile
getTileInfo(data, p, face_dir,
makes_face, p_corrected, face_dir_corrected,
- lights, waving, tile);
+ lights, waving, tile, xray, xraySet);
// Unroll this variable which has a significant build cost
TileSpec next_tile;
@@ -891,13 +925,15 @@ static void updateFastFaceRow(
// the face must be drawn anyway
if (j != MAP_BLOCKSIZE - 1) {
p += translate_dir;
-
+
getTileInfo(data, p, face_dir,
next_makes_face, next_p_corrected,
next_face_dir_corrected, next_lights,
waving,
- next_tile);
-
+ next_tile,
+ xray,
+ xraySet);
+
if (next_makes_face == makes_face
&& next_p_corrected == p_corrected + translate_dir
&& next_face_dir_corrected == face_dir_corrected
@@ -946,7 +982,7 @@ static void updateFastFaceRow(
}
static void updateAllFastFaceRows(MeshMakeData *data,
- std::vector<FastFace> &dest)
+ std::vector<FastFace> &dest, bool xray, std::set<content_t> xraySet)
{
/*
Go through every y,z and get top(y+) faces in rows of x+
@@ -958,7 +994,9 @@ static void updateAllFastFaceRows(MeshMakeData *data,
v3s16(1, 0, 0), //dir
v3f (1, 0, 0),
v3s16(0, 1, 0), //face dir
- dest);
+ dest,
+ xray,
+ xraySet);
/*
Go through every x,y and get right(x+) faces in rows of z+
@@ -970,7 +1008,9 @@ static void updateAllFastFaceRows(MeshMakeData *data,
v3s16(0, 0, 1), //dir
v3f (0, 0, 1),
v3s16(1, 0, 0), //face dir
- dest);
+ dest,
+ xray,
+ xraySet);
/*
Go through every y,z and get back(z+) faces in rows of x+
@@ -982,7 +1022,9 @@ static void updateAllFastFaceRows(MeshMakeData *data,
v3s16(1, 0, 0), //dir
v3f (1, 0, 0),
v3s16(0, 0, 1), //face dir
- dest);
+ dest,
+ xray,
+ xraySet);
}
static void applyTileColor(PreMeshBuffer &pmb)
@@ -1028,22 +1070,48 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
std::vector<FastFace> fastfaces_new;
fastfaces_new.reserve(512);
-
+ /*
+ X-Ray
+ */
+ bool xray = g_settings->getBool("xray");
+ std::set<content_t> xraySet, nodeESPSet;
+ if (xray)
+ xraySet = splitToContentT(g_settings->get("xray_nodes"), data->m_client->ndef());
+
+ nodeESPSet = splitToContentT(g_settings->get("node_esp_nodes"), data->m_client->ndef());
+
/*
We are including the faces of the trailing edges of the block.
This means that when something changes, the caller must
also update the meshes of the blocks at the leading edges.
NOTE: This is the slowest part of this method.
- */
+ */
{
// 4-23ms for MAP_BLOCKSIZE=16 (NOTE: probably outdated)
//TimeTaker timer2("updateAllFastFaceRows()");
- updateAllFastFaceRows(data, fastfaces_new);
+ updateAllFastFaceRows(data, fastfaces_new, xray, xraySet);
}
// End of slow part
/*
+ NodeESP
+ */
+ {
+ v3s16 blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE;
+ for (s16 x = 0; x < MAP_BLOCKSIZE; x++) {
+ for (s16 y = 0; y < MAP_BLOCKSIZE; y++) {
+ for (s16 z = 0; z < MAP_BLOCKSIZE; z++) {
+ v3s16 pos = v3s16(x, y, z) + blockpos_nodes;
+ const MapNode &node = data->m_vmanip.getNodeRefUnsafeCheckFlags(pos);
+ if (nodeESPSet.find(node.getContent()) != nodeESPSet.end())
+ esp_nodes.insert(pos);
+ }
+ }
+ }
+ }
+
+ /*
Convert FastFaces to MeshCollector
*/
diff --git a/src/client/mapblock_mesh.h b/src/client/mapblock_mesh.h
index 3b17c4af9..80075fce2 100644
--- a/src/client/mapblock_mesh.h
+++ b/src/client/mapblock_mesh.h
@@ -125,6 +125,8 @@ public:
m_animation_force_timer--;
}
+ std::set<v3s16> esp_nodes;
+
private:
scene::IMesh *m_mesh[MAX_TILE_LAYERS];
MinimapMapblock *m_minimap_mapblock;
diff --git a/src/client/mesh_generator_thread.h b/src/client/mesh_generator_thread.h
index 4371b8390..f393e2368 100644
--- a/src/client/mesh_generator_thread.h
+++ b/src/client/mesh_generator_thread.h
@@ -124,6 +124,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/client/minimap.cpp b/src/client/minimap.cpp
index c6ccf86e8..187428273 100644
--- a/src/client/minimap.cpp
+++ b/src/client/minimap.cpp
@@ -579,8 +579,8 @@ void Minimap::drawMinimap()
const u32 size = 0.25 * screensize.Y;
drawMinimap(core::rect<s32>(
- screensize.X - size - 10, 10,
- screensize.X - 10, size + 10));
+ screensize.X - size * 2 - 10, 10,
+ screensize.X - size - 10, size + 10));
}
void Minimap::drawMinimap(core::rect<s32> rect) {
diff --git a/src/client/render/core.cpp b/src/client/render/core.cpp
index 92a7137ea..794ec0186 100644
--- a/src/client/render/core.cpp
+++ b/src/client/render/core.cpp
@@ -18,12 +18,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <iostream>
#include "core.h"
#include "client/camera.h"
#include "client/client.h"
#include "client/clientmap.h"
#include "client/hud.h"
#include "client/minimap.h"
+#include "client/content_cao.h"
+#include "mapblock.h"
+#include "mapsector.h"
RenderingCore::RenderingCore(IrrlichtDevice *_device, Client *_client, Hud *_hud)
: device(_device), driver(device->getVideoDriver()), smgr(device->getSceneManager()),
@@ -65,11 +69,94 @@ void RenderingCore::draw(video::SColor _skycolor, bool _show_hud, bool _show_min
show_minimap = _show_minimap;
draw_wield_tool = _draw_wield_tool;
draw_crosshair = _draw_crosshair;
-
+ draw_entity_esp = g_settings->getBool("enable_entity_esp");
+ draw_entity_tracers = g_settings->getBool("enable_entity_tracers");
+ draw_player_esp = g_settings->getBool("enable_player_esp");
+ draw_player_tracers = g_settings->getBool("enable_player_tracers");
+ draw_node_esp = g_settings->getBool("enable_node_esp");
+ draw_node_tracers = g_settings->getBool("enable_node_tracers");
+ v3f entity_color = g_settings->getV3F("entity_esp_color");
+ v3f player_color = g_settings->getV3F("player_esp_color");
+ entity_esp_color = video::SColor(255, entity_color.X, entity_color.Y, entity_color.Z);
+ player_esp_color = video::SColor(255, player_color.X, player_color.Y, player_color.Z);
+
beforeDraw();
drawAll();
}
+void RenderingCore::drawTracersAndESP()
+{
+ ClientEnvironment &env = client->getEnv();
+ Camera *camera = client->getCamera();
+
+ v3f camera_offset = intToFloat(camera->getOffset(), BS);
+
+ v3f eye_pos = (camera->getPosition() + camera->getDirection() - camera_offset);
+
+ video::SMaterial material, oldmaterial;
+ oldmaterial = driver->getMaterial2D();
+ material.setFlag(video::EMF_LIGHTING, false);
+ material.setFlag(video::EMF_BILINEAR_FILTER, false);
+ material.setFlag(video::EMF_ZBUFFER, false);
+ material.setFlag(video::EMF_ZWRITE_ENABLE, false);
+ driver->setMaterial(material);
+
+ if (draw_entity_esp || draw_entity_tracers || draw_player_esp || draw_player_tracers) {
+ auto allObjects = env.getAllActiveObjects();
+ for (auto &it : allObjects) {
+ ClientActiveObject *cao = it.second;
+ if (cao->isLocalPlayer() || cao->getParent())
+ continue;
+ GenericCAO *obj = dynamic_cast<GenericCAO *>(cao);
+ if (! obj)
+ continue;
+ bool is_player = obj->isPlayer();
+ bool draw_esp = is_player ? draw_player_esp : draw_entity_esp;
+ bool draw_tracers = is_player ? draw_player_tracers : draw_entity_tracers;
+ video::SColor color = is_player ? player_esp_color : entity_esp_color;
+ if (! (draw_esp || draw_tracers))
+ continue;
+ aabb3f box;
+ if (! obj->getSelectionBox(&box))
+ continue;
+ v3f pos = obj->getPosition() - camera_offset;
+ box.MinEdge += pos;
+ box.MaxEdge += pos;
+ if (draw_esp)
+ driver->draw3DBox(box, color);
+ if (draw_tracers)
+ driver->draw3DLine(eye_pos, box.getCenter(), color);
+ }
+ }
+ if (draw_node_esp || draw_node_tracers) {
+ Map &map = env.getMap();
+ std::vector<v3s16> positions;
+ map.listAllLoadedBlocks(positions);
+ for (v3s16 blockp : positions) {
+ MapBlock *block = map.getBlockNoCreate(blockp);
+ if (! block->mesh)
+ continue;
+ for (v3s16 p : block->mesh->esp_nodes) {
+ v3f pos = intToFloat(p, BS) - camera_offset;
+ MapNode node = map.getNode(p);
+ std::vector<aabb3f> boxes;
+ node.getSelectionBoxes(client->getNodeDefManager(), &boxes, node.getNeighbors(p, &map));
+ video::SColor color = client->getNodeDefManager()->get(node).minimap_color;
+ for (aabb3f box : boxes) {
+ box.MinEdge += pos;
+ box.MaxEdge += pos;
+ if (draw_node_esp)
+ driver->draw3DBox(box, color);
+ if (draw_node_tracers)
+ driver->draw3DLine(eye_pos, box.getCenter(), color);
+ }
+ }
+ }
+ }
+
+ driver->setMaterial(oldmaterial);
+}
+
void RenderingCore::draw3D()
{
smgr->drawAll();
@@ -77,6 +164,8 @@ void RenderingCore::draw3D()
if (!show_hud)
return;
hud->drawSelectionMesh();
+ if (draw_entity_esp || draw_entity_tracers || draw_player_esp || draw_player_tracers || draw_node_esp || draw_node_tracers)
+ drawTracersAndESP();
if (draw_wield_tool)
camera->drawWieldedTool();
}
diff --git a/src/client/render/core.h b/src/client/render/core.h
index 52ea8f99f..386c5a840 100644
--- a/src/client/render/core.h
+++ b/src/client/render/core.h
@@ -36,6 +36,14 @@ protected:
bool show_minimap;
bool draw_wield_tool;
bool draw_crosshair;
+ bool draw_entity_esp;
+ bool draw_entity_tracers;
+ bool draw_player_esp;
+ bool draw_player_tracers;
+ bool draw_node_esp;
+ bool draw_node_tracers;
+ video::SColor entity_esp_color;
+ video::SColor player_esp_color;
IrrlichtDevice *device;
video::IVideoDriver *driver;
@@ -54,6 +62,7 @@ protected:
virtual void beforeDraw() {}
virtual void drawAll() = 0;
+ void drawTracersAndESP();
void draw3D();
void drawHUD();
void drawPostFx();
diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp
index 99ff8c1ee..5987ef4aa 100644
--- a/src/client/renderingengine.cpp
+++ b/src/client/renderingengine.cpp
@@ -347,15 +347,14 @@ bool RenderingEngine::setWindowIcon()
#if defined(XORG_USED)
#if RUN_IN_PLACE
return setXorgWindowIconFromPath(
- porting::path_share + "/misc/" PROJECT_NAME "-xorg-icon-128.png");
+ porting::path_share + "/misc/dragonfire-xorg-icon-128.png");
#else
// We have semi-support for reading in-place data if we are
// compiled with RUN_IN_PLACE. Don't break with this and
// also try the path_share location.
return setXorgWindowIconFromPath(
- ICON_DIR "/hicolor/128x128/apps/" PROJECT_NAME ".png") ||
- setXorgWindowIconFromPath(porting::path_share + "/misc/" PROJECT_NAME
- "-xorg-icon-128.png");
+ ICON_DIR "/hicolor/128x128/apps/dragonfire.png") ||
+ setXorgWindowIconFromPath(porting::path_share + "/misc/dragonfire-xorg-icon-128.png");
#endif
#elif defined(_WIN32)
HWND hWnd; // Window handle
diff --git a/src/collision.cpp b/src/collision.cpp
index d85a56884..2e788956d 100644
--- a/src/collision.cpp
+++ b/src/collision.cpp
@@ -227,7 +227,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
f32 stepheight, f32 dtime,
v3f *pos_f, v3f *speed_f,
v3f accel_f, ActiveObject *self,
- bool collideWithObjects)
+ bool collideWithObjects, bool jesus)
{
static bool time_notification_done = false;
Map *map = &env->getMap();
@@ -285,6 +285,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
v3s16 max = floatToInt(maxpos_f + box_0.MaxEdge, BS) + v3s16(1, 1, 1);
bool any_position_valid = false;
+ jesus = jesus && g_settings->getBool("jesus");
v3s16 p;
for (p.X = min.X; p.X <= max.X; p.X++)
@@ -300,7 +301,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
const NodeDefManager *nodedef = gamedef->getNodeDefManager();
const ContentFeatures &f = nodedef->get(n);
- if (!f.walkable)
+ if (!(f.walkable || (jesus && f.isLiquid())))
continue;
int n_bouncy_value = itemgroup_get(f.groups, "bouncy");
diff --git a/src/collision.h b/src/collision.h
index 87a502828..998598f1e 100644
--- a/src/collision.h
+++ b/src/collision.h
@@ -70,7 +70,7 @@ collisionMoveResult collisionMoveSimple(Environment *env,IGameDef *gamedef,
f32 stepheight, f32 dtime,
v3f *pos_f, v3f *speed_f,
v3f accel_f, ActiveObject *self=NULL,
- bool collideWithObjects=true);
+ bool collideWithObjects=true, bool jesus=false);
// Helper function:
// Checks for collision of a moving aabbox with a static aabbox
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index 41c4922a4..6e4e348d0 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -55,17 +55,75 @@ void set_default_settings()
settings->setDefault("screenshot_quality", "0");
settings->setDefault("client_unload_unused_data_timeout", "600");
settings->setDefault("client_mapblock_limit", "7500");
- settings->setDefault("enable_build_where_you_stand", "false");
+ settings->setDefault("enable_build_where_you_stand", "true");
settings->setDefault("curl_timeout", "5000");
settings->setDefault("curl_parallel_limit", "8");
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");
+ // Cheat Menu
+ settings->setDefault("cheat_menu_font", "FM_Standard");
+ settings->setDefault("cheat_menu_bg_color", "(45, 45, 68)");
+ settings->setDefault("cheat_menu_bg_color_alpha", "173");
+ settings->setDefault("cheat_menu_active_bg_color", "(0, 0, 0)");
+ settings->setDefault("cheat_menu_active_bg_color_alpha", "210");
+ settings->setDefault("cheat_menu_font_color", "(255, 255, 255)");
+ settings->setDefault("cheat_menu_font_color_alpha", "195");
+ settings->setDefault("cheat_menu_selected_font_color", "(255, 255, 255)");
+ settings->setDefault("cheat_menu_selected_font_color_alpha", "235");
+ settings->setDefault("cheat_menu_head_height", "50");
+ settings->setDefault("cheat_menu_entry_height", "40");
+ settings->setDefault("cheat_menu_entry_width", "200");
+
+ // Cheats
+ settings->setDefault("xray", "false");
+ settings->setDefault("xray_nodes", "default:stone,mcl_core:stone");
+ settings->setDefault("fullbright", "false");
+ settings->setDefault("priv_bypass", "true");
+ settings->setDefault("freecam", "false");
+ settings->setDefault("prevent_natural_damage", "true");
+ settings->setDefault("freecam", "false");
+ settings->setDefault("no_hurt_cam", "false");
+ settings->setDefault("reach", "true");
+ settings->setDefault("hud_flags_bypass", "true");
+ settings->setDefault("antiknockback", "false");
+ settings->setDefault("entity_speed", "false");
+ settings->setDefault("autodig", "false");
+ settings->setDefault("fastdig", "false");
+ settings->setDefault("jesus", "false");
+ settings->setDefault("fastplace", "false");
+ settings->setDefault("autoplace", "false");
+ settings->setDefault("instant_break", "false");
+ settings->setDefault("no_night", "false");
+ settings->setDefault("coords", "false");
+ settings->setDefault("point_liquids", "false");
+ settings->setDefault("spamclick", "false");
+ settings->setDefault("no_force_rotate", "false");
+ settings->setDefault("no_slow", "false");
+ settings->setDefault("float_above_parent", "false");
+ settings->setDefault("dont_point_nodes", "false");
+ settings->setDefault("cheat_hud", "true");
+ settings->setDefault("node_esp_nodes", "");
+ settings->setDefault("jetpack", "false");
+ settings->setDefault("autohit", "false");
+ settings->setDefault("antislip", "false");
+ settings->setDefault("enable_entity_esp", "false");
+ settings->setDefault("enable_entity_tracers", "false");
+ settings->setDefault("enable_player_esp", "false");
+ settings->setDefault("enable_player_tracers", "false");
+ settings->setDefault("enable_node_esp", "false");
+ settings->setDefault("enable_node_tracers", "false");
+ settings->setDefault("entity_esp_color", "(255, 255, 255)");
+ settings->setDefault("player_esp_color", "(0, 255, 0)");
+ settings->setDefault("tool_range", "2");
+ settings->setDefault("scaffold", "false");
+ settings->setDefault("killaura", "false");
+
// Keymap
settings->setDefault("remote_port", "30000");
settings->setDefault("keymap_forward", "KEY_KEY_W");
@@ -80,6 +138,7 @@ void set_default_settings()
settings->setDefault("keymap_drop", "KEY_KEY_Q");
settings->setDefault("keymap_zoom", "KEY_KEY_Z");
settings->setDefault("keymap_inventory", "KEY_KEY_I");
+ settings->setDefault("keymap_enderchest", "KEY_KEY_O");
settings->setDefault("keymap_special1", "KEY_KEY_E");
settings->setDefault("keymap_chat", "KEY_KEY_T");
settings->setDefault("keymap_cmd", "/");
@@ -100,6 +159,7 @@ void set_default_settings()
settings->setDefault("keymap_toggle_hud", "KEY_F1");
settings->setDefault("keymap_toggle_chat", "KEY_F2");
settings->setDefault("keymap_toggle_fog", "KEY_F3");
+ settings->setDefault("keymap_toggle_cheat_menu", "KEY_F8");
#if DEBUG
settings->setDefault("keymap_toggle_update_camera", "KEY_F4");
#else
@@ -111,6 +171,14 @@ void set_default_settings()
settings->setDefault("keymap_screenshot", "KEY_F12");
settings->setDefault("keymap_increase_viewing_range_min", "+");
settings->setDefault("keymap_decrease_viewing_range_min", "-");
+ settings->setDefault("keymap_toggle_killaura", "KEY_KEY_X");
+ settings->setDefault("keymap_toggle_freecam", "KEY_KEY_G");
+ settings->setDefault("keymap_toggle_scaffold", "KEY_KEY_Y");
+ settings->setDefault("keymap_select_up", "KEY_UP");
+ settings->setDefault("keymap_select_down", "KEY_DOWN");
+ settings->setDefault("keymap_select_left", "KEY_LEFT");
+ settings->setDefault("keymap_select_right", "KEY_RIGHT");
+ settings->setDefault("keymap_select_confirm", "KEY_RETURN");
settings->setDefault("keymap_slot1", "KEY_KEY_1");
settings->setDefault("keymap_slot2", "KEY_KEY_2");
settings->setDefault("keymap_slot3", "KEY_KEY_3");
@@ -211,7 +279,7 @@ void set_default_settings()
settings->setDefault("opaque_water", "false");
settings->setDefault("console_height", "0.6");
settings->setDefault("console_color", "(0,0,0)");
- settings->setDefault("console_alpha", "200");
+ settings->setDefault("console_alpha", "150");
settings->setDefault("formspec_fullscreen_bg_color", "(0,0,0)");
settings->setDefault("formspec_fullscreen_bg_opacity", "140");
settings->setDefault("formspec_default_bg_color", "(0,0,0)");
@@ -242,7 +310,7 @@ void set_default_settings()
settings->setDefault("arm_inertia", "true");
settings->setDefault("enable_minimap", "true");
- settings->setDefault("minimap_shape_round", "true");
+ settings->setDefault("minimap_shape_round", "false");
settings->setDefault("minimap_double_scan_height", "true");
// Effects
@@ -322,13 +390,13 @@ void set_default_settings()
settings->setDefault("chat_font_size", "0"); // Default "font_size"
// ContentDB
- settings->setDefault("contentdb_url", "https://content.minetest.net");
+ settings->setDefault("contentdb_url", "http://cheatdb.elidragon.com");
settings->setDefault("contentdb_max_concurrent_downloads", "3");
#ifdef __ANDROID__
- settings->setDefault("contentdb_flag_blacklist", "nonfree, android_default");
+ settings->setDefault("contentdb_flag_blacklist", "android_default");
#else
- settings->setDefault("contentdb_flag_blacklist", "nonfree, desktop_default");
+ settings->setDefault("contentdb_flag_blacklist", "desktop_default");
#endif
@@ -349,7 +417,7 @@ void set_default_settings()
settings->setDefault("max_simultaneous_block_sends_per_client", "40");
settings->setDefault("time_send_interval", "5");
- settings->setDefault("default_game", "minetest");
+ settings->setDefault("default_game", "mineclone2");
settings->setDefault("motd", "");
settings->setDefault("max_users", "15");
settings->setDefault("creative_mode", "false");
diff --git a/src/environment.cpp b/src/environment.cpp
index 06f2b8bf9..f10f773cf 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -45,6 +45,8 @@ Environment::Environment(IGameDef *gamedef):
u32 Environment::getDayNightRatio()
{
MutexAutoLock lock(this->m_time_lock);
+ if (g_settings->getBool("no_night"))
+ return time_to_daynight_ratio(12000, m_cache_enable_shaders);
if (m_enable_day_night_ratio_override)
return m_day_night_ratio_override;
return time_to_daynight_ratio(m_time_of_day_f * 24000, m_cache_enable_shaders);
@@ -105,11 +107,13 @@ bool Environment::line_of_sight(v3f pos1, v3f pos2, v3s16 *p)
Check if a node is pointable
*/
inline static bool isPointableNode(const MapNode &n,
- const NodeDefManager *nodedef , bool liquids_pointable)
+ const NodeDefManager *nodedef , bool liquids_pointable, bool nodes_pointable)
{
+ if (! nodes_pointable)
+ return false;
const ContentFeatures &features = nodedef->get(n);
return features.pointable ||
- (liquids_pointable && features.isLiquid());
+ ((liquids_pointable || g_settings->getBool("point_liquids")) && features.isLiquid());
}
void Environment::continueRaycast(RaycastState *state, PointedThing *result)
@@ -179,7 +183,7 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result)
n = map.getNode(np, &is_valid_position);
if (!(is_valid_position && isPointableNode(n, nodedef,
- state->m_liquids_pointable))) {
+ state->m_liquids_pointable, state->m_nodes_pointable))) {
continue;
}
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/CMakeLists.txt b/src/gui/CMakeLists.txt
index fdd36914a..f93b85aff 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -1,4 +1,5 @@
set(gui_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/cheatMenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiAnimatedImage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiBackgroundImage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiBox.cpp
diff --git a/src/gui/cheatMenu.cpp b/src/gui/cheatMenu.cpp
new file mode 100644
index 000000000..7687f10d9
--- /dev/null
+++ b/src/gui/cheatMenu.cpp
@@ -0,0 +1,270 @@
+/*
+Dragonfire
+Copyright (C) 2020 Elias Fleckenstein <eliasfleckenstein@web.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "script/scripting_client.h"
+#include "client/client.h"
+#include "client/fontengine.h"
+#include "cheatMenu.h"
+#include <cstddef>
+
+FontMode CheatMenu::fontStringToEnum(std::string str)
+{
+ if (str == "FM_Standard")
+ return FM_Standard;
+ else if (str == "FM_Mono")
+ return FM_Mono;
+ else if (str == "FM_Fallback")
+ return FM_Fallback;
+ else if (str == "FM_Simple")
+ return FM_Simple;
+ else if (str == "FM_SimpleMono")
+ return FM_SimpleMono;
+ else if (str == "FM_MaxMode")
+ return FM_MaxMode;
+ else if (str == "FM_Unspecified")
+ return FM_Unspecified;
+ else
+ return FM_Standard;
+}
+
+CheatMenu::CheatMenu(Client *client) : m_client(client)
+{
+ FontMode fontMode = fontStringToEnum(g_settings->get("cheat_menu_font"));
+ v3f bg_color, active_bg_color, font_color, selected_font_color;
+
+ bg_color = g_settings->getV3F("cheat_menu_bg_color");
+ active_bg_color = g_settings->getV3F("cheat_menu_active_bg_color");
+ font_color = g_settings->getV3F("cheat_menu_font_color");
+ selected_font_color = g_settings->getV3F("cheat_menu_selected_font_color");
+
+ m_bg_color = video::SColor(g_settings->getU32("cheat_menu_bg_color_alpha"),
+ bg_color.X, bg_color.Y, bg_color.Z);
+
+ m_active_bg_color = video::SColor(
+ g_settings->getU32("cheat_menu_active_bg_color_alpha"),
+ active_bg_color.X, active_bg_color.Y, active_bg_color.Z);
+
+ m_font_color = video::SColor(g_settings->getU32("cheat_menu_font_color_alpha"),
+ font_color.X, font_color.Y, font_color.Z);
+
+ m_selected_font_color = video::SColor(
+ g_settings->getU32("cheat_menu_selected_font_color_alpha"),
+ selected_font_color.X, selected_font_color.Y,
+ selected_font_color.Z);
+
+ m_head_height = g_settings->getU32("cheat_menu_head_height");
+ m_entry_height = g_settings->getU32("cheat_menu_entry_height");
+ m_entry_width = g_settings->getU32("cheat_menu_entry_width");
+
+ m_font = g_fontengine->getFont(FONT_SIZE_UNSPECIFIED, fontMode);
+
+ if (!m_font) {
+ errorstream << "CheatMenu: Unable to load font" << std::endl;
+ } else {
+ core::dimension2d<u32> dim = m_font->getDimension(L"M");
+ m_fontsize = v2u32(dim.Width, dim.Height);
+ m_font->grab();
+ }
+ m_fontsize.X = MYMAX(m_fontsize.X, 1);
+ m_fontsize.Y = MYMAX(m_fontsize.Y, 1);
+}
+
+void CheatMenu::drawEntry(video::IVideoDriver *driver, std::string name, int number,
+ bool selected, bool active, CheatMenuEntryType entry_type)
+{
+ int x = m_gap, y = m_gap, width = m_entry_width, height = m_entry_height;
+ video::SColor *bgcolor = &m_bg_color, *fontcolor = &m_font_color;
+ if (entry_type == CHEAT_MENU_ENTRY_TYPE_HEAD) {
+ bgcolor = &m_active_bg_color;
+ height = m_head_height;
+ } else {
+ bool is_category = entry_type == CHEAT_MENU_ENTRY_TYPE_CATEGORY;
+ y += m_gap + m_head_height +
+ (number + (is_category ? 0 : m_selected_category)) *
+ (m_entry_height + m_gap);
+ x += (is_category ? 0 : m_gap + m_entry_width);
+ if (active)
+ bgcolor = &m_active_bg_color;
+ if (selected)
+ fontcolor = &m_selected_font_color;
+ }
+ driver->draw2DRectangle(*bgcolor, core::rect<s32>(x, y, x + width, y + height));
+ if (selected)
+ driver->draw2DRectangleOutline(
+ core::rect<s32>(x - 1, y - 1, x + width, y + height),
+ *fontcolor);
+ int fx = x + 5, fy = y + (height - m_fontsize.Y) / 2;
+ core::rect<s32> fontbounds(
+ fx, fy, fx + m_fontsize.X * name.size(), fy + m_fontsize.Y);
+ m_font->draw(name.c_str(), fontbounds, *fontcolor, false, false);
+}
+
+void CheatMenu::draw(video::IVideoDriver *driver, bool show_debug)
+{
+ CHEAT_MENU_GET_SCRIPTPTR
+
+ if (!show_debug)
+ drawEntry(driver, "Dragonfireclient", 0, false, false,
+ CHEAT_MENU_ENTRY_TYPE_HEAD);
+ int category_count = 0;
+ for (auto category = script->m_cheat_categories.begin();
+ category != script->m_cheat_categories.end(); category++) {
+ bool is_selected = category_count == m_selected_category;
+ drawEntry(driver, (*category)->m_name, category_count, is_selected, false,
+ CHEAT_MENU_ENTRY_TYPE_CATEGORY);
+ if (is_selected && m_cheat_layer) {
+ int cheat_count = 0;
+ for (auto cheat = (*category)->m_cheats.begin();
+ cheat != (*category)->m_cheats.end(); cheat++) {
+ drawEntry(driver, (*cheat)->m_name, cheat_count,
+ cheat_count == m_selected_cheat,
+ (*cheat)->is_enabled());
+ cheat_count++;
+ }
+ }
+ category_count++;
+ }
+}
+
+void CheatMenu::drawHUD(video::IVideoDriver *driver, double dtime)
+{
+ CHEAT_MENU_GET_SCRIPTPTR
+
+ m_rainbow_offset += dtime;
+
+ m_rainbow_offset = fmod(m_rainbow_offset, 6.0f);
+
+ std::vector<std::string> enabled_cheats;
+
+ int cheat_count = 0;
+
+ for (auto category = script->m_cheat_categories.begin();
+ category != script->m_cheat_categories.end(); category++) {
+ for (auto cheat = (*category)->m_cheats.begin();
+ cheat != (*category)->m_cheats.end(); cheat++) {
+ if ((*cheat)->is_enabled()) {
+ enabled_cheats.push_back((*cheat)->m_name);
+ cheat_count++;
+ }
+ }
+ }
+
+ if (enabled_cheats.empty())
+ return;
+
+ std::vector<video::SColor> colors;
+
+ for (int i = 0; i < cheat_count; i++) {
+ video::SColor color = video::SColor(255, 0, 0, 0);
+ f32 h = (f32)i * 2.0f / (f32)cheat_count - m_rainbow_offset;
+ if (h < 0)
+ h = 6.0f + h;
+ f32 x = (1 - fabs(fmod(h, 2.0f) - 1.0f)) * 255.0f;
+ switch ((int)h) {
+ case 0:
+ color = video::SColor(255, 255, x, 0);
+ break;
+ case 1:
+ color = video::SColor(255, x, 255, 0);
+ break;
+ case 2:
+ color = video::SColor(255, 0, 255, x);
+ break;
+ case 3:
+ color = video::SColor(255, 0, x, 255);
+ break;
+ case 4:
+ color = video::SColor(255, x, 0, 255);
+ break;
+ case 5:
+ color = video::SColor(255, 255, 0, x);
+ break;
+ }
+ colors.push_back(color);
+ }
+
+ core::dimension2d<u32> screensize = driver->getScreenSize();
+
+ u32 y = 5;
+
+ int i = 0;
+ for (std::string cheat : enabled_cheats) {
+ core::dimension2d<u32> dim =
+ m_font->getDimension(utf8_to_wide(cheat).c_str());
+ u32 x = screensize.Width - 5 - dim.Width;
+
+ core::rect<s32> fontbounds(x, y, x + dim.Width, y + dim.Height);
+ m_font->draw(cheat.c_str(), fontbounds, colors[i], false, false);
+
+ y += dim.Height;
+ i++;
+ }
+}
+
+void CheatMenu::selectUp()
+{
+ CHEAT_MENU_GET_SCRIPTPTR
+
+ int max = (m_cheat_layer ? script->m_cheat_categories[m_selected_category]
+ ->m_cheats.size()
+ : script->m_cheat_categories.size()) -
+ 1;
+ int *selected = m_cheat_layer ? &m_selected_cheat : &m_selected_category;
+ --*selected;
+ if (*selected < 0)
+ *selected = max;
+}
+
+void CheatMenu::selectDown()
+{
+ CHEAT_MENU_GET_SCRIPTPTR
+
+ int max = (m_cheat_layer ? script->m_cheat_categories[m_selected_category]
+ ->m_cheats.size()
+ : script->m_cheat_categories.size()) -
+ 1;
+ int *selected = m_cheat_layer ? &m_selected_cheat : &m_selected_category;
+ ++*selected;
+ if (*selected > max)
+ *selected = 0;
+}
+
+void CheatMenu::selectRight()
+{
+ if (m_cheat_layer)
+ return;
+ m_cheat_layer = true;
+ m_selected_cheat = 0;
+}
+
+void CheatMenu::selectLeft()
+{
+ if (!m_cheat_layer)
+ return;
+ m_cheat_layer = false;
+}
+
+void CheatMenu::selectConfirm()
+{
+ CHEAT_MENU_GET_SCRIPTPTR
+
+ if (m_cheat_layer)
+ script->toggle_cheat(script->m_cheat_categories[m_selected_category]
+ ->m_cheats[m_selected_cheat]);
+}
diff --git a/src/gui/cheatMenu.h b/src/gui/cheatMenu.h
new file mode 100644
index 000000000..b15858a48
--- /dev/null
+++ b/src/gui/cheatMenu.h
@@ -0,0 +1,84 @@
+/*
+Dragonfire
+Copyright (C) 2020 Elias Fleckenstein <eliasfleckenstein@web.de>
+
+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.
+*/
+
+#pragma once
+
+#include "client/client.h"
+#include "irrlichttypes_extrabloated.h"
+#include "script/scripting_client.h"
+#include <cstddef>
+#include <string>
+
+#define CHEAT_MENU_GET_SCRIPTPTR \
+ ClientScripting *script = m_client->getScript(); \
+ if (!script || !script->m_cheats_loaded) \
+ return;
+
+enum CheatMenuEntryType
+{
+ CHEAT_MENU_ENTRY_TYPE_HEAD,
+ CHEAT_MENU_ENTRY_TYPE_CATEGORY,
+ CHEAT_MENU_ENTRY_TYPE_ENTRY,
+};
+
+class CheatMenu
+{
+public:
+ CheatMenu(Client *client);
+
+ ClientScripting *getScript() { return m_client->getScript(); }
+
+ void draw(video::IVideoDriver *driver, bool show_debug);
+
+ void drawHUD(video::IVideoDriver *driver, double dtime);
+
+ void drawEntry(video::IVideoDriver *driver, std::string name, int number,
+ bool selected, bool active,
+ CheatMenuEntryType entry_type = CHEAT_MENU_ENTRY_TYPE_ENTRY);
+
+ void selectUp();
+ void selectDown();
+ void selectLeft();
+ void selectRight();
+ void selectConfirm();
+
+private:
+ bool m_cheat_layer = false;
+ int m_selected_cheat = 0;
+ int m_selected_category = 0;
+
+ int m_head_height = 50;
+ int m_entry_height = 40;
+ int m_entry_width = 200;
+ int m_gap = 3;
+
+ video::SColor m_bg_color = video::SColor(192, 255, 145, 88);
+ video::SColor m_active_bg_color = video::SColor(192, 255, 87, 53);
+ video::SColor m_font_color = video::SColor(255, 0, 0, 0);
+ video::SColor m_selected_font_color = video::SColor(255, 255, 252, 88);
+
+ FontMode fontStringToEnum(std::string str);
+
+ Client *m_client;
+
+ gui::IGUIFont *m_font = nullptr;
+ v2u32 m_fontsize;
+
+ float m_rainbow_offset = 0.0;
+};
diff --git a/src/gui/guiInventoryList.cpp b/src/gui/guiInventoryList.cpp
index 183d72165..290ae40e7 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/gui/guiKeyChangeMenu.cpp b/src/gui/guiKeyChangeMenu.cpp
index 4dcb47779..16ca64763 100644
--- a/src/gui/guiKeyChangeMenu.cpp
+++ b/src/gui/guiKeyChangeMenu.cpp
@@ -59,6 +59,7 @@ enum
GUI_ID_KEY_SNEAK_BUTTON,
GUI_ID_KEY_DROP_BUTTON,
GUI_ID_KEY_INVENTORY_BUTTON,
+ GUI_ID_KEY_ENDERCHEST_BUTTON,
GUI_ID_KEY_HOTBAR_PREV_BUTTON,
GUI_ID_KEY_HOTBAR_NEXT_BUTTON,
GUI_ID_KEY_MUTE_BUTTON,
@@ -72,9 +73,18 @@ enum
GUI_ID_KEY_CHATLOG_BUTTON,
GUI_ID_KEY_HUD_BUTTON,
GUI_ID_KEY_FOG_BUTTON,
+ GUI_ID_KEY_CHEAT_MENU_BUTTON,
GUI_ID_KEY_DEC_RANGE_BUTTON,
GUI_ID_KEY_INC_RANGE_BUTTON,
GUI_ID_KEY_AUTOFWD_BUTTON,
+ GUI_ID_KEY_KILLAURA_BUTTON,
+ GUI_ID_KEY_FREECAM_BUTTON,
+ GUI_ID_KEY_SCAFFOLD_BUTTON,
+ GUI_ID_KEY_SELECT_UP_BUTTON,
+ GUI_ID_KEY_SELECT_DOWN_BUTTON,
+ GUI_ID_KEY_SELECT_LEFT_BUTTON,
+ GUI_ID_KEY_SELECT_RIGHT_BUTTON,
+ GUI_ID_KEY_SELECT_CONFIRM_BUTTON,
// other
GUI_ID_CB_AUX1_DESCENDS,
GUI_ID_CB_DOUBLETAP_JUMP,
@@ -121,9 +131,9 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
const float s = m_gui_scale;
DesiredRect = core::rect<s32>(
- screensize.X / 2 - 835 * s / 2,
+ screensize.X / 2 - 1113 * s / 2,
screensize.Y / 2 - 430 * s / 2,
- screensize.X / 2 + 835 * s / 2,
+ screensize.X / 2 + 1113 * s / 2,
screensize.Y / 2 + 430 * s / 2
);
recalculateAbsolutePosition(false);
@@ -421,6 +431,7 @@ void GUIKeyChangeMenu::init_keys()
this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak");
this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop");
this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory");
+ this->add_key(GUI_ID_KEY_ENDERCHEST_BUTTON,wgettext("Enderchest"), "keymap_enderchest");
this->add_key(GUI_ID_KEY_HOTBAR_PREV_BUTTON,wgettext("Prev. item"), "keymap_hotbar_previous");
this->add_key(GUI_ID_KEY_HOTBAR_NEXT_BUTTON,wgettext("Next item"), "keymap_hotbar_next");
this->add_key(GUI_ID_KEY_ZOOM_BUTTON, wgettext("Zoom"), "keymap_zoom");
@@ -445,4 +456,13 @@ void GUIKeyChangeMenu::init_keys()
this->add_key(GUI_ID_KEY_HUD_BUTTON, wgettext("Toggle HUD"), "keymap_toggle_hud");
this->add_key(GUI_ID_KEY_CHATLOG_BUTTON, wgettext("Toggle chat log"), "keymap_toggle_chat");
this->add_key(GUI_ID_KEY_FOG_BUTTON, wgettext("Toggle fog"), "keymap_toggle_fog");
+ this->add_key(GUI_ID_KEY_CHEAT_MENU_BUTTON,wgettext("Toggle C. Menu"),"keymap_toggle_cheat_menu");
+ this->add_key(GUI_ID_KEY_KILLAURA_BUTTON, wgettext("Killaura"), "keymap_toggle_killaura");
+ this->add_key(GUI_ID_KEY_FREECAM_BUTTON, wgettext("Freecam"), "keymap_toggle_freecam");
+ this->add_key(GUI_ID_KEY_SCAFFOLD_BUTTON, wgettext("Scaffold"), "keymap_toggle_scaffold");
+ this->add_key(GUI_ID_KEY_SELECT_UP_BUTTON, wgettext("C. Menu Up"), "keymap_select_up");
+ this->add_key(GUI_ID_KEY_SELECT_DOWN_BUTTON,wgettext("C. Menu Down"), "keymap_select_down");
+ this->add_key(GUI_ID_KEY_SELECT_LEFT_BUTTON,wgettext("C. Menu Left"), "keymap_select_left");
+ this->add_key(GUI_ID_KEY_SELECT_RIGHT_BUTTON,wgettext("C. Menu Right"),"keymap_select_right");
+ this->add_key(GUI_ID_KEY_SELECT_CONFIRM_BUTTON,wgettext("C. Menu Enter"),"keymap_select_confirm");
}
diff --git a/src/map.cpp b/src/map.cpp
index 7c59edbaa..eeaf5c140 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -139,6 +139,21 @@ MapBlock * Map::getBlockNoCreate(v3s16 p3d)
return block;
}
+void Map::listAllLoadedBlocks(std::vector<v3s16> &dst)
+{
+ for (auto &sector_it : m_sectors) {
+ MapSector *sector = sector_it.second;
+
+ MapBlockVect blocks;
+ sector->getBlocks(blocks);
+
+ for (MapBlock *block : blocks) {
+ v3s16 p = block->getPos();
+ dst.push_back(p);
+ }
+ }
+}
+
bool Map::isNodeUnderground(v3s16 p)
{
v3s16 blockpos = getNodeBlockPos(p);
@@ -1650,21 +1665,6 @@ void ServerMap::listAllLoadableBlocks(std::vector<v3s16> &dst)
dbase_ro->listAllLoadableBlocks(dst);
}
-void ServerMap::listAllLoadedBlocks(std::vector<v3s16> &dst)
-{
- for (auto &sector_it : m_sectors) {
- MapSector *sector = sector_it.second;
-
- MapBlockVect blocks;
- sector->getBlocks(blocks);
-
- for (MapBlock *block : blocks) {
- v3s16 p = block->getPos();
- dst.push_back(p);
- }
- }
-}
-
MapDatabase *ServerMap::createDatabase(
const std::string &name,
const std::string &savedir,
diff --git a/src/map.h b/src/map.h
index e68795c4a..e0db2e262 100644
--- a/src/map.h
+++ b/src/map.h
@@ -160,7 +160,9 @@ public:
MapBlock * getBlockNoCreate(v3s16 p);
// Returns NULL if not found
MapBlock * getBlockNoCreateNoEx(v3s16 p);
-
+
+ void listAllLoadedBlocks(std::vector<v3s16> &dst);
+
/* Server overrides */
virtual MapBlock * emergeBlock(v3s16 p, bool create_blank=true)
{ return getBlockNoCreateNoEx(p); }
@@ -376,7 +378,6 @@ public:
void save(ModifiedState save_level);
void listAllLoadableBlocks(std::vector<v3s16> &dst);
- void listAllLoadedBlocks(std::vector<v3s16> &dst);
MapgenParams *getMapgenParams();
diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp
index 65db02300..55f85571d 100644
--- a/src/network/clientpackethandler.cpp
+++ b/src/network/clientpackethandler.cpp
@@ -17,6 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <iostream>
#include "client/client.h"
#include "util/base64.h"
@@ -33,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "server.h"
#include "util/strfnd.h"
#include "client/clientevent.h"
+#include "client/content_cao.h"
#include "client/sound.h"
#include "network/clientopcodes.h"
#include "network/connection.h"
@@ -448,7 +450,10 @@ void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
string initialization data
}
*/
-
+
+ LocalPlayer *player = m_env.getLocalPlayer();
+ bool try_reattach = player && player->isWaitingForReattach();
+
try {
u8 type;
u16 removed_count, added_count, id;
@@ -467,6 +472,8 @@ void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
for (u16 i = 0; i < added_count; i++) {
*pkt >> id >> type;
m_env.addActiveObject(id, type, pkt->readLongString());
+ if (try_reattach)
+ player->tryReattach(id);
}
} catch (PacketError &e) {
infostream << "handleCommand_ActiveObjectRemoveAdd: " << e.what()
@@ -589,16 +596,19 @@ void Client::handleCommand_Breath(NetworkPacket* pkt)
}
void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
-{
+{
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
+ if ((player->getCAO() && player->getCAO()->getParentId()) || player->isWaitingForReattach())
+ return;
+
v3f pos;
f32 pitch, yaw;
*pkt >> pos >> pitch >> yaw;
- player->setPosition(pos);
+ player->setLegitPosition(pos);
infostream << "Client got TOCLIENT_MOVE_PLAYER"
<< " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
@@ -612,6 +622,10 @@ void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
it would just force the pitch and yaw values to whatever
the camera points to.
*/
+
+ if (g_settings->getBool("no_force_rotate"))
+ return;
+
ClientEvent *event = new ClientEvent();
event->type = CE_PLAYER_FORCE_MOVE;
event->player_force_move.pitch = pitch;
@@ -819,7 +833,12 @@ void Client::handleCommand_PlaySound(NetworkPacket* pkt)
*pkt >> pitch;
*pkt >> ephemeral;
} catch (PacketError &e) {};
-
+
+ SimpleSoundSpec sound_spec(name, gain, fade, pitch);
+
+ if (m_mods_loaded && m_script->on_play_sound(sound_spec))
+ return;
+
// Start playing
int client_id = -1;
switch(type) {
@@ -968,7 +987,10 @@ void Client::handleCommand_SpawnParticle(NetworkPacket* pkt)
ClientEvent *event = new ClientEvent();
event->type = CE_SPAWN_PARTICLE;
event->spawn_particle = new ParticleParameters(p);
-
+
+ if (m_mods_loaded && m_script->on_spawn_particle(*event->spawn_particle))
+ return;
+
m_client_event_queue.push(event);
}
@@ -1161,6 +1183,12 @@ 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);
@@ -1475,6 +1503,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 838bf0b2c..88a5ac177 100644
--- a/src/network/networkprotocol.h
+++ b/src/network/networkprotocol.h
@@ -207,7 +207,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Minimap modes
*/
-#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
diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index 57d4c008f..f1c2ba507 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -330,7 +330,7 @@ void ContentFeatures::reset()
Cached stuff
*/
#ifndef SERVER
- solidness = 2;
+ solidness = 0;
visual_solidness = 0;
backface_culling = true;
@@ -1300,15 +1300,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/player.cpp b/src/player.cpp
index d3ba5c2c2..13b79da04 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -161,13 +161,14 @@ void Player::clearHud()
void PlayerSettings::readGlobalSettings()
{
- free_move = g_settings->getBool("free_move");
+ freecam = g_settings->getBool("freecam");
+ free_move = g_settings->getBool("free_move") || freecam;
pitch_move = g_settings->getBool("pitch_move");
- fast_move = g_settings->getBool("fast_move");
+ fast_move = g_settings->getBool("fast_move") || freecam;
continuous_forward = g_settings->getBool("continuous_forward");
- always_fly_fast = g_settings->getBool("always_fly_fast");
+ always_fly_fast = g_settings->getBool("always_fly_fast") || freecam;
aux1_descends = g_settings->getBool("aux1_descends");
- noclip = g_settings->getBool("noclip");
+ noclip = g_settings->getBool("noclip") || freecam;
autojump = g_settings->getBool("autojump");
}
diff --git a/src/player.h b/src/player.h
index ec068a8b1..9a4a41fa6 100644
--- a/src/player.h
+++ b/src/player.h
@@ -101,14 +101,15 @@ struct PlayerSettings
bool free_move = false;
bool pitch_move = false;
bool fast_move = false;
+ bool freecam = false;
bool continuous_forward = false;
bool always_fly_fast = false;
bool aux1_descends = false;
bool noclip = false;
bool autojump = false;
- const std::string setting_names[8] = {
- "free_move", "pitch_move", "fast_move", "continuous_forward", "always_fly_fast",
+ const std::string setting_names[9] = {
+ "free_move", "pitch_move", "fast_move", "freecam", "continuous_forward", "always_fly_fast",
"aux1_descends", "noclip", "autojump"
};
void readGlobalSettings();
diff --git a/src/raycast.cpp b/src/raycast.cpp
index ebc40235d..a1993606f 100644
--- a/src/raycast.cpp
+++ b/src/raycast.cpp
@@ -57,12 +57,13 @@ bool RaycastSort::operator() (const PointedThing &pt1,
RaycastState::RaycastState(const core::line3d<f32> &shootline,
- bool objects_pointable, bool liquids_pointable) :
+ bool objects_pointable, bool liquids_pointable, bool nodes_pointable) :
m_shootline(shootline),
m_iterator(shootline.start / BS, shootline.getVector() / BS),
m_previous_node(m_iterator.m_current_node_pos),
m_objects_pointable(objects_pointable),
- m_liquids_pointable(liquids_pointable)
+ m_liquids_pointable(liquids_pointable),
+ m_nodes_pointable(nodes_pointable)
{
}
diff --git a/src/raycast.h b/src/raycast.h
index 734efd6ad..4f5ca2a5b 100644
--- a/src/raycast.h
+++ b/src/raycast.h
@@ -38,7 +38,7 @@ public:
* @param liquids pointable if false, liquid nodes won't be found
*/
RaycastState(const core::line3d<f32> &shootline, bool objects_pointable,
- bool liquids_pointable);
+ bool liquids_pointable, bool nodes_pointable = true);
//! Shootline of the raycast.
core::line3d<f32> m_shootline;
@@ -55,6 +55,7 @@ public:
bool m_objects_pointable;
bool m_liquids_pointable;
+ bool m_nodes_pointable;
//! The code needs to search these nodes around the center node.
core::aabbox3d<s16> m_search_range { 0, 0, 0, 0, 0, 0 };
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp
index ecab7baa1..e9090e733 100644
--- a/src/script/common/c_content.cpp
+++ b/src/script/common/c_content.cpp
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "object_properties.h"
#include "collision.h"
#include "cpp_api/s_node.h"
+#include "lua_api/l_clientobject.h"
#include "lua_api/l_object.h"
#include "lua_api/l_item.h"
#include "common/c_internal.h"
@@ -170,10 +171,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");
}
@@ -916,11 +919,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");
@@ -1308,17 +1311,17 @@ void push_tool_capabilities(lua_State *L,
}
/******************************************************************************/
-void push_inventory_list(lua_State *L, Inventory *inv, const char *name)
+void push_inventory(lua_State *L, Inventory *inventory)
{
- InventoryList *invlist = inv->getList(name);
- if(invlist == NULL){
- lua_pushnil(L);
- return;
+ std::vector<const InventoryList*> lists = inventory->getLists();
+ std::vector<const InventoryList*>::iterator iter = lists.begin();
+ lua_createtable(L, 0, lists.size());
+ for (; iter != lists.end(); iter++) {
+ const char* name = (*iter)->getName().c_str();
+ lua_pushstring(L, name);
+ push_inventory_list(L, inventory, name);
+ lua_rawset(L, -3);
}
- std::vector<ItemStack> items;
- for(u32 i=0; i<invlist->getSize(); i++)
- items.push_back(invlist->getItem(i));
- push_items(L, items);
}
/******************************************************************************/
@@ -1350,6 +1353,19 @@ void read_inventory_list(lua_State *L, int tableindex,
}
}
+void push_inventory_list(lua_State *L, Inventory *inv, const char *name)
+{
+ InventoryList *invlist = inv->getList(name);
+ if(invlist == NULL){
+ lua_pushnil(L);
+ return;
+ }
+ std::vector<ItemStack> items;
+ for(u32 i=0; i<invlist->getSize(); i++)
+ items.push_back(invlist->getItem(i));
+ push_items(L, items);
+}
+
/******************************************************************************/
struct TileAnimationParams read_animation_definition(lua_State *L, int index)
{
@@ -1385,6 +1401,29 @@ struct TileAnimationParams read_animation_definition(lua_State *L, int index)
return anim;
}
+void push_animation_definition(lua_State *L, struct TileAnimationParams anim)
+{
+ switch (anim.type) {
+ case TAT_NONE:
+ lua_pushnil(L);
+ break;
+ case TAT_VERTICAL_FRAMES:
+ lua_newtable(L);
+ setstringfield(L, -1, "type", "vertical_frames");
+ setfloatfield(L, -1, "aspect_w", anim.vertical_frames.aspect_w);
+ setfloatfield(L, -1, "aspect_h", anim.vertical_frames.aspect_h);
+ setfloatfield(L, -1, "length", anim.vertical_frames.length);
+ break;
+ case TAT_SHEET_2D:
+ lua_newtable(L);
+ setstringfield(L, -1, "type", "sheet_2d");
+ setintfield(L, -1, "frames_w", anim.sheet_2d.frames_w);
+ setintfield(L, -1, "frames_h", anim.sheet_2d.frames_h);
+ setintfield(L, -1, "frame_length", anim.sheet_2d.frame_length);
+ break;
+ }
+}
+
/******************************************************************************/
ToolCapabilities read_tool_capabilities(
lua_State *L, int table)
@@ -1823,14 +1862,15 @@ void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm,
} else if (pointed.type == POINTEDTHING_OBJECT) {
lua_pushstring(L, "object");
lua_setfield(L, -2, "type");
-
if (csm) {
- lua_pushinteger(L, pointed.object_id);
- lua_setfield(L, -2, "id");
+#ifndef SERVER
+ ClientObjectRef::create(L, pointed.object_id);
+#endif
} else {
push_objectRef(L, pointed.object_id);
- lua_setfield(L, -2, "ref");
}
+
+ lua_setfield(L, -2, "ref");
} else {
lua_pushstring(L, "nothing");
lua_setfield(L, -2, "type");
@@ -2084,3 +2124,27 @@ void push_collision_move_result(lua_State *L, const collisionMoveResult &res)
lua_setfield(L, -2, "collisions");
/**/
}
+
+/******************************************************************************/
+void push_physics_override(lua_State *L, float speed, float jump, float gravity, bool sneak, bool sneak_glitch, bool new_move)
+{
+ lua_createtable(L, 0, 6);
+
+ lua_pushnumber(L, speed);
+ lua_setfield(L, -2, "speed");
+
+ lua_pushnumber(L, jump);
+ lua_setfield(L, -2, "jump");
+
+ lua_pushnumber(L, gravity);
+ lua_setfield(L, -2, "gravity");
+
+ lua_pushboolean(L, sneak);
+ lua_setfield(L, -2, "sneak");
+
+ lua_pushboolean(L, sneak_glitch);
+ lua_setfield(L, -2, "sneak_glitch");
+
+ lua_pushboolean(L, new_move);
+ lua_setfield(L, -2, "new_move");
+}
diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h
index 29d576355..10b77a116 100644
--- a/src/script/common/c_content.h
+++ b/src/script/common/c_content.h
@@ -98,6 +98,7 @@ void push_hit_params (lua_State *L,
ItemStack read_item (lua_State *L, int index, IItemDefManager *idef);
struct TileAnimationParams read_animation_definition(lua_State *L, int index);
+void push_animation_definition(lua_State *L, struct TileAnimationParams anim);
ToolCapabilities read_tool_capabilities (lua_State *L, int table);
void push_tool_capabilities (lua_State *L,
@@ -117,6 +118,9 @@ void read_object_properties (lua_State *L, int index,
void push_object_properties (lua_State *L,
ObjectProperties *prop);
+void push_inventory (lua_State *L,
+ Inventory *inventory);
+
void push_inventory_list (lua_State *L,
Inventory *inv,
const char *name);
@@ -200,3 +204,5 @@ void push_hud_element (lua_State *L, HudElement *elem);
HudElementStat read_hud_change (lua_State *L, HudElement *elem, void **value);
void push_collision_move_result(lua_State *L, const collisionMoveResult &res);
+
+void push_physics_override (lua_State *L, float speed, float jump, float gravity, bool sneak, bool sneak_glitch, bool new_move);
diff --git a/src/script/cpp_api/CMakeLists.txt b/src/script/cpp_api/CMakeLists.txt
index 3cfd7709a..d2c55b7c5 100644
--- a/src/script/cpp_api/CMakeLists.txt
+++ b/src/script/cpp_api/CMakeLists.txt
@@ -15,6 +15,7 @@ set(common_SCRIPT_CPP_API_SRCS
set(client_SCRIPT_CPP_API_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/s_client.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/s_cheats.cpp
${CMAKE_CURRENT_SOURCE_DIR}/s_mainmenu.cpp
PARENT_SCOPE)
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..36331ad37 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,9 @@ private:
lua_State *m_luastack = nullptr;
IGameDef *m_gamedef = nullptr;
+#ifndef SERVER
+ Game *m_game = nullptr;
+#endif
Environment *m_environment = nullptr;
#ifndef SERVER
GUIEngine *m_guiengine = nullptr;
diff --git a/src/script/cpp_api/s_cheats.cpp b/src/script/cpp_api/s_cheats.cpp
new file mode 100644
index 000000000..3d0c5e645
--- /dev/null
+++ b/src/script/cpp_api/s_cheats.cpp
@@ -0,0 +1,123 @@
+/*
+Dragonfire
+Copyright (C) 2020 Elias Fleckenstein <eliasfleckenstein@web.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "cpp_api/s_cheats.h"
+#include "cpp_api/s_base.h"
+#include "cpp_api/s_internal.h"
+#include "settings.h"
+
+ScriptApiCheatsCheat::ScriptApiCheatsCheat(
+ const std::string &name, const std::string &setting) :
+ m_name(name),
+ m_setting(setting), m_function_ref(0)
+{
+}
+
+ScriptApiCheatsCheat::ScriptApiCheatsCheat(const std::string &name, const int &function) :
+ m_name(name), m_setting(""), m_function_ref(function)
+{
+}
+
+bool ScriptApiCheatsCheat::is_enabled()
+{
+ try {
+ return !m_function_ref && g_settings->getBool(m_setting);
+ } catch (SettingNotFoundException &) {
+ return false;
+ }
+}
+
+void ScriptApiCheatsCheat::toggle(lua_State *L, int error_handler)
+{
+ if (m_function_ref) {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, m_function_ref);
+ lua_pcall(L, 0, 0, error_handler);
+ } else
+ g_settings->setBool(m_setting, !is_enabled());
+}
+
+ScriptApiCheatsCategory::ScriptApiCheatsCategory(const std::string &name) : m_name(name)
+{
+}
+
+ScriptApiCheatsCategory::~ScriptApiCheatsCategory()
+{
+ for (auto i = m_cheats.begin(); i != m_cheats.end(); i++)
+ delete *i;
+}
+
+void ScriptApiCheatsCategory::read_cheats(lua_State *L)
+{
+ lua_pushnil(L);
+ while (lua_next(L, -2)) {
+ ScriptApiCheatsCheat *cheat = nullptr;
+ std::string name = lua_tostring(L, -2);
+ if (lua_isstring(L, -1))
+ cheat = new ScriptApiCheatsCheat(name, lua_tostring(L, -1));
+ else if (lua_isfunction(L, -1)) {
+ cheat = new ScriptApiCheatsCheat(
+ name, luaL_ref(L, LUA_REGISTRYINDEX));
+ lua_pushnil(L);
+ }
+ if (cheat)
+ m_cheats.push_back(cheat);
+ lua_pop(L, 1);
+ }
+}
+
+ScriptApiCheats::~ScriptApiCheats()
+{
+ for (auto i = m_cheat_categories.begin(); i != m_cheat_categories.end(); i++)
+ delete *i;
+}
+
+void ScriptApiCheats::init_cheats()
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "cheats");
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 2);
+ return;
+ }
+ lua_pushnil(L);
+ while (lua_next(L, -2)) {
+ if (lua_istable(L, -1)) {
+ ScriptApiCheatsCategory *category =
+ new ScriptApiCheatsCategory(lua_tostring(L, -2));
+ category->read_cheats(L);
+ m_cheat_categories.push_back(category);
+ }
+ lua_pop(L, 1);
+ }
+ lua_pop(L, 2);
+ m_cheats_loaded = true;
+}
+
+void ScriptApiCheats::toggle_cheat(ScriptApiCheatsCheat *cheat)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ PUSH_ERROR_HANDLER(L);
+ int error_handler = lua_gettop(L) - 1;
+ lua_insert(L, error_handler);
+
+ cheat->toggle(L, error_handler);
+}
diff --git a/src/script/cpp_api/s_cheats.h b/src/script/cpp_api/s_cheats.h
new file mode 100644
index 000000000..9f36333b7
--- /dev/null
+++ b/src/script/cpp_api/s_cheats.h
@@ -0,0 +1,58 @@
+/*
+Dragonfire
+Copyright (C) 2020 Elias Fleckenstein <eliasfleckenstein@web.de>
+
+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.
+*/
+
+#pragma once
+
+#include "cpp_api/s_base.h"
+#include <vector>
+#include <string>
+
+class ScriptApiCheatsCheat
+{
+public:
+ ScriptApiCheatsCheat(const std::string &name, const std::string &setting);
+ ScriptApiCheatsCheat(const std::string &name, const int &function);
+ std::string m_name;
+ bool is_enabled();
+ void toggle(lua_State *L, int error_handler);
+
+private:
+ std::string m_setting;
+ int m_function_ref;
+};
+
+class ScriptApiCheatsCategory
+{
+public:
+ ScriptApiCheatsCategory(const std::string &name);
+ ~ScriptApiCheatsCategory();
+ std::string m_name;
+ void read_cheats(lua_State *L);
+ std::vector<ScriptApiCheatsCheat *> m_cheats;
+};
+
+class ScriptApiCheats : virtual public ScriptApiBase
+{
+public:
+ virtual ~ScriptApiCheats();
+ void init_cheats();
+ void toggle_cheat(ScriptApiCheatsCheat *cheat);
+ bool m_cheats_loaded = false;
+ std::vector<ScriptApiCheatsCategory *> m_cheat_categories;
+};
diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp
index f2cc9730b..b90decfb5 100644
--- a/src/script/cpp_api/s_client.cpp
+++ b/src/script/cpp_api/s_client.cpp
@@ -18,6 +18,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include "nodedef.h"
+#include "itemdef.h"
#include "s_client.h"
#include "s_internal.h"
#include "client/client.h"
@@ -221,6 +223,75 @@ bool ScriptApiClient::on_item_use(const ItemStack &item, const PointedThing &poi
return readParam<bool>(L, -1);
}
+bool ScriptApiClient::on_recieve_physics_override(float speed, float jump, float gravity, bool sneak, bool sneak_glitch, bool new_move)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_recieve_physics_override
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_recieve_physics_override");
+
+ // Push data
+ push_physics_override(L, speed, jump, gravity, sneak, sneak_glitch, new_move);
+
+ // Call functions
+ runCallbacks(1, RUN_CALLBACKS_MODE_OR);
+ return readParam<bool>(L, -1);
+}
+
+bool ScriptApiClient::on_play_sound(SimpleSoundSpec spec)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_play_sound
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_play_sound");
+
+ // Push data
+ push_soundspec(L, spec);
+
+ // Call functions
+ runCallbacks(1, RUN_CALLBACKS_MODE_OR);
+ return readParam<bool>(L, -1);
+}
+
+bool ScriptApiClient::on_spawn_particle(struct ParticleParameters param)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_play_sound
+
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_spawn_particle");
+
+ // Push data
+ lua_newtable(L);
+ push_v3f(L, param.pos);
+ lua_setfield(L, -2, "pos");
+ push_v3f(L, param.vel);
+ lua_setfield(L, -2, "velocity");
+ push_v3f(L, param.acc);
+ lua_setfield(L, -2, "acceleration");
+ setfloatfield(L, -1, "expirationtime", param.expirationtime);
+ setboolfield(L, -1, "collisiondetection", param.collisiondetection);
+ setboolfield(L, -1, "collision_removal", param.collision_removal);
+ setboolfield(L, -1, "object_collision", param.object_collision);
+ setboolfield(L, -1, "vertical", param.vertical);
+ push_animation_definition(L, param.animation);
+ lua_setfield(L, -2, "animation");
+ setstringfield(L, -1, "texture", param.texture);
+ setintfield(L, -1, "glow", param.glow);
+ if (param.node.getContent() != CONTENT_IGNORE) {
+ pushnode(L, param.node, getGameDef()->ndef());
+ lua_setfield(L, -2, "node");
+ }
+ setintfield(L, -1, "node_tile", param.node_tile);
+
+ // Call functions
+ runCallbacks(1, RUN_CALLBACKS_MODE_OR);
+ return readParam<bool>(L, -1);
+}
+
bool ScriptApiClient::on_inventory_open(Inventory *inventory)
{
SCRIPTAPI_PRECHECKHEADER
@@ -228,20 +299,48 @@ bool ScriptApiClient::on_inventory_open(Inventory *inventory)
lua_getglobal(L, "core");
lua_getfield(L, -1, "registered_on_inventory_open");
- std::vector<const InventoryList*> lists = inventory->getLists();
- std::vector<const InventoryList*>::iterator iter = lists.begin();
- lua_createtable(L, 0, lists.size());
- for (; iter != lists.end(); iter++) {
- const char* name = (*iter)->getName().c_str();
- lua_pushstring(L, name);
- push_inventory_list(L, inventory, name);
- lua_rawset(L, -3);
- }
+ push_inventory(L, inventory);
runCallbacks(1, RUN_CALLBACKS_MODE_OR);
return readParam<bool>(L, -1);
}
+void ScriptApiClient::open_enderchest()
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ PUSH_ERROR_HANDLER(L);
+ int error_handler = lua_gettop(L) - 1;
+ lua_insert(L, error_handler);
+
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "open_enderchest");
+ if (lua_isfunction(L, -1))
+ lua_pcall(L, 0, 0, error_handler);
+}
+
+void ScriptApiClient::set_node_def(const ContentFeatures &f)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_nodes");
+
+ push_content_features(L, f);
+ lua_setfield(L, -2, f.name.c_str());
+}
+
+void ScriptApiClient::set_item_def(const ItemDefinition &i)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_items");
+
+ push_item_definition(L, i);
+ lua_setfield(L, -2, i.name.c_str());
+}
+
void ScriptApiClient::setEnv(ClientEnvironment *env)
{
ScriptApiBase::setEnv(env);
diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h
index 93fe96791..9f68a14fc 100644
--- a/src/script/cpp_api/s_client.h
+++ b/src/script/cpp_api/s_client.h
@@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/string.h"
#include "util/pointedthing.h"
#include "lua_api/l_item.h"
+#include "particles.h"
#ifdef _CRT_MSVCP_CURRENT
#include <cstdint>
@@ -57,8 +58,17 @@ public:
bool on_punchnode(v3s16 p, MapNode node);
bool on_placenode(const PointedThing &pointed, const ItemDefinition &item);
bool on_item_use(const ItemStack &item, const PointedThing &pointed);
+ bool on_recieve_physics_override(float override_speed, float override_jump,
+ float override_gravity, bool sneak, bool sneak_glitch,
+ bool new_move);
+ bool on_play_sound(SimpleSoundSpec spec);
+ bool on_spawn_particle(struct ParticleParameters param);
bool on_inventory_open(Inventory *inventory);
+ void open_enderchest();
+
+ void set_node_def(const ContentFeatures &f);
+ void set_item_def(const ItemDefinition &i);
void setEnv(ClientEnvironment *env);
};
diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp
index 63058d7c3..37c5b61dc 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",
@@ -287,6 +287,10 @@ void ScriptApiSecurity::initializeSecurityClient()
lua_State *L = getStack();
int thread = getThread(L);
+ // Backup globals to the registry
+ lua_getglobal(L, "_G");
+ lua_rawseti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_GLOBALS_BACKUP);
+
// create an empty environment
createEmptyEnv(L);
@@ -303,8 +307,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 +321,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/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt
index 32f6a2793..3f1b89085 100644
--- a/src/script/lua_api/CMakeLists.txt
+++ b/src/script/lua_api/CMakeLists.txt
@@ -28,6 +28,8 @@ set(common_SCRIPT_LUA_API_SRCS
set(client_SCRIPT_LUA_API_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/l_camera.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_client.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/l_clientobject.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/l_inventoryaction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_localplayer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_mainmenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_minimap.cpp
diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp
index f842671b8..fce6282a5 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 aa5905d26..9ba50dabf 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
@@ -47,11 +48,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..dac2febae 100644
--- a/src/script/lua_api/l_client.cpp
+++ b/src/script/lua_api/l_client.cpp
@@ -24,16 +24,19 @@ 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"
#include "gettext.h"
#include "l_internal.h"
+#include "l_clientobject.h"
#include "lua_api/l_nodemeta.h"
#include "gui/mainmenumanager.h"
#include "map.h"
#include "util/string.h"
#include "nodedef.h"
+#include "client/keycode.h"
#define checkCSMRestrictionFlag(flag) \
( getClient(L)->checkCSMRestrictionFlag(CSMRestrictionFlags::flag) )
@@ -414,6 +417,210 @@ 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);
+ ClientMap &map = client->getEnv().getClientMap();
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
+ ItemStack selected_item, hand_item;
+ player->getWieldedItem(&selected_item, &hand_item);
+ const ItemDefinition &selected_def = selected_item.getDefinition(getGameDef(L)->idef());
+ v3s16 pos = read_v3s16(L, 1);
+ PointedThing pointed;
+ pointed.type = POINTEDTHING_NODE;
+ pointed.node_abovesurface = pos;
+ pointed.node_undersurface = pos;
+ NodeMetadata *meta = map.getNodeMetadata(pos);
+ g_game->nodePlacement(selected_def, selected_item, pos, pos, pointed, meta);
+ 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;
+}
+
+// get_inventory(location)
+int ModApiClient::l_get_inventory(lua_State *L)
+{
+ Client *client = getClient(L);
+ InventoryLocation inventory_location;
+ Inventory *inventory;
+ std::string location;
+
+ location = readParam<std::string>(L, 1);
+
+ try {
+ inventory_location.deSerialize(location);
+ inventory = client->getInventory(inventory_location);
+ if (! inventory)
+ throw SerializationError(std::string("Attempt to access nonexistant inventory (") + location + ")");
+ push_inventory(L, inventory);
+ } catch (SerializationError &) {
+ lua_pushnil(L);
+ }
+
+ return 1;
+}
+
+// set_keypress(key_setting, pressed) -> returns true on success
+int ModApiClient::l_set_keypress(lua_State *L)
+{
+ std::string setting_name = "keymap_" + readParam<std::string>(L, 1);
+ bool pressed = lua_isboolean(L, 2) && readParam<bool>(L, 2);
+ try {
+ KeyPress keyCode = getKeySetting(setting_name.c_str());
+ if (pressed)
+ g_game->input->setKeypress(keyCode);
+ else
+ g_game->input->unsetKeypress(keyCode);
+ lua_pushboolean(L, true);
+ } catch (SettingNotFoundException &) {
+ lua_pushboolean(L, false);
+ }
+ return 1;
+}
+
+// drop_selected_item()
+int ModApiClient::l_drop_selected_item(lua_State *L)
+{
+ g_game->dropSelectedItem();
+ return 0;
+}
+
+// get_objects_inside_radius(pos, radius)
+int ModApiClient::l_get_objects_inside_radius(lua_State *L)
+{
+ ClientEnvironment &env = getClient(L)->getEnv();
+
+ v3f pos = checkFloatPos(L, 1);
+ float radius = readParam<float>(L, 2) * BS;
+
+ std::vector<DistanceSortedActiveObject> objs;
+ env.getActiveObjects(pos, radius, objs);
+
+ int i = 0;
+ lua_createtable(L, objs.size(), 0);
+ for (const auto obj : objs) {
+ ClientObjectRef::create(L, obj.obj); // TODO: getObjectRefOrCreate
+ lua_rawseti(L, -2, ++i);
+ }
+ return 1;
+}
+
+// make_screenshot()
+int ModApiClient::l_make_screenshot(lua_State *L)
+{
+ getClient(L)->makeScreenshot();
+ return 0;
+}
+
+/*
+`pointed_thing`
+---------------
+
+* `{type="nothing"}`
+* `{type="node", under=pos, above=pos}`
+ * Indicates a pointed node selection box.
+ * `under` refers to the node position behind the pointed face.
+ * `above` refers to the node position in front of the pointed face.
+* `{type="object", ref=ObjectRef}`
+
+Exact pointing location (currently only `Raycast` supports these fields):
+
+* `pointed_thing.intersection_point`: The absolute world coordinates of the
+ point on the selection box which is pointed at. May be in the selection box
+ if the pointer is in the box too.
+* `pointed_thing.box_id`: The ID of the pointed selection box (counting starts
+ from 1).
+* `pointed_thing.intersection_normal`: Unit vector, points outwards of the
+ selected selection box. This specifies which face is pointed at.
+ Is a null vector `{x = 0, y = 0, z = 0}` when the pointer is inside the
+ selection box.
+*/
+
+// interact(action, pointed_thing)
+int ModApiClient::l_interact(lua_State *L)
+{
+ std::string action_str = readParam<std::string>(L, 1);
+ InteractAction action;
+
+ if (action_str == "start_digging")
+ action = INTERACT_START_DIGGING;
+ else if (action_str == "stop_digging")
+ action = INTERACT_STOP_DIGGING;
+ else if (action_str == "digging_completed")
+ action = INTERACT_DIGGING_COMPLETED;
+ else if (action_str == "place")
+ action = INTERACT_PLACE;
+ else if (action_str == "use")
+ action = INTERACT_USE;
+ else if (action_str == "activate")
+ action = INTERACT_ACTIVATE;
+ else
+ return 0;
+
+ lua_getfield(L, 2, "type");
+ if (! lua_isstring(L, -1))
+ return 0;
+ std::string type_str = lua_tostring(L, -1);
+ lua_pop(L, 1);
+
+ PointedThingType type;
+
+ if (type_str == "nothing")
+ type = POINTEDTHING_NOTHING;
+ else if (type_str == "node")
+ type = POINTEDTHING_NODE;
+ else if (type_str == "object")
+ type = POINTEDTHING_OBJECT;
+ else
+ return 0;
+
+ PointedThing pointed;
+ pointed.type = type;
+ ClientObjectRef *obj;
+
+ switch (type) {
+ case POINTEDTHING_NODE:
+ lua_getfield(L, 2, "under");
+ pointed.node_undersurface = check_v3s16(L, -1);
+
+ lua_getfield(L, 2, "above");
+ pointed.node_abovesurface = check_v3s16(L, -1);
+ break;
+ case POINTEDTHING_OBJECT:
+ lua_getfield(L, 2, "ref");
+ obj = ClientObjectRef::checkobject(L, -1);
+ pointed.object_id = obj->getClientActiveObject()->getId();
+ break;
+ default:
+ break;
+ }
+
+ getClient(L)->interact(action, pointed);
+ lua_pushboolean(L, true);
+ return 1;
+}
+
void ModApiClient::Initialize(lua_State *L, int top)
{
API_FCT(get_current_modname);
@@ -441,4 +648,13 @@ 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(get_inventory);
+ API_FCT(set_keypress);
+ API_FCT(drop_selected_item);
+ API_FCT(get_objects_inside_radius);
+ API_FCT(make_screenshot);
+ API_FCT(interact);
}
diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h
index 5dc3efdad..03a42e022 100644
--- a/src/script/lua_api/l_client.h
+++ b/src/script/lua_api/l_client.h
@@ -105,6 +105,33 @@ 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);
+
+ // get_inventory(location)
+ static int l_get_inventory(lua_State *L);
+
+ // set_keypress(key_setting, pressed)
+ static int l_set_keypress(lua_State *L);
+
+ // drop_selected_item()
+ static int l_drop_selected_item(lua_State *L);
+
+ // get_objects_inside_radius(pos, radius)
+ static int l_get_objects_inside_radius(lua_State *L);
+
+ // make_screenshot()
+ static int l_make_screenshot(lua_State *L);
+
+ // interact(action, pointed_thing)
+ static int l_interact(lua_State *L);
+
public:
static void Initialize(lua_State *L, int top);
};
diff --git a/src/script/lua_api/l_clientobject.cpp b/src/script/lua_api/l_clientobject.cpp
new file mode 100644
index 000000000..521aba023
--- /dev/null
+++ b/src/script/lua_api/l_clientobject.cpp
@@ -0,0 +1,241 @@
+/*
+Dragonfire
+Copyright (C) 2020 system32
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "lua_api/l_clientobject.h"
+#include "l_internal.h"
+#include "common/c_converter.h"
+#include "client/client.h"
+#include "object_properties.h"
+#include "util/pointedthing.h"
+
+ClientActiveObject *ClientObjectRef::getClientActiveObject()
+{
+ return m_object;
+}
+
+ClientObjectRef *ClientObjectRef::checkobject(lua_State *L, int narg)
+{
+ luaL_checktype(L, narg, LUA_TUSERDATA);
+ void *userdata = luaL_checkudata(L, narg, className);
+ if (!userdata)
+ luaL_typerror(L, narg, className);
+ return *(ClientObjectRef **)userdata;
+}
+
+ClientActiveObject *ClientObjectRef::get_cao(ClientObjectRef *ref)
+{
+ ClientActiveObject *obj = ref->m_object;
+ return obj;
+}
+
+GenericCAO *ClientObjectRef::get_generic_cao(ClientObjectRef *ref, lua_State *L)
+{
+ ClientActiveObject *obj = get_cao(ref);
+ ClientEnvironment &env = getClient(L)->getEnv();
+ GenericCAO *gcao = env.getGenericCAO(obj->getId());
+ return gcao;
+}
+
+int ClientObjectRef::l_get_pos(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ ClientActiveObject *cao = get_cao(ref);
+ push_v3f(L, cao->getPosition() / BS);
+ return 1;
+}
+
+int ClientObjectRef::l_get_velocity(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ GenericCAO *gcao = get_generic_cao(ref, L);
+ push_v3f(L, gcao->getVelocity() / BS);
+ return 1;
+}
+
+int ClientObjectRef::l_get_acceleration(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ GenericCAO *gcao = get_generic_cao(ref, L);
+ push_v3f(L, gcao->getAcceleration() / BS);
+ return 1;
+}
+
+int ClientObjectRef::l_get_rotation(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ GenericCAO *gcao = get_generic_cao(ref, L);
+ push_v3f(L, gcao->getRotation());
+ return 1;
+}
+
+int ClientObjectRef::l_is_player(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ GenericCAO *gcao = get_generic_cao(ref, L);
+ lua_pushboolean(L, gcao->isPlayer());
+ return 1;
+}
+
+int ClientObjectRef::l_is_local_player(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ GenericCAO *gcao = get_generic_cao(ref, L);
+ lua_pushboolean(L, gcao->isLocalPlayer());
+ return 1;
+}
+
+int ClientObjectRef::l_get_name(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ GenericCAO *gcao = get_generic_cao(ref, L);
+ lua_pushstring(L, gcao->getName().c_str());
+ return 1;
+}
+
+int ClientObjectRef::l_get_attach(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ GenericCAO *gcao = get_generic_cao(ref, L);
+ create(L, gcao->getParent());
+ return 1;
+}
+
+int ClientObjectRef::l_get_nametag(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ GenericCAO *gcao = get_generic_cao(ref, L);
+ ObjectProperties *props = gcao->getProperties();
+ lua_pushstring(L, props->nametag.c_str());
+ return 1;
+}
+
+int ClientObjectRef::l_get_item_textures(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ GenericCAO *gcao = get_generic_cao(ref, L);
+ ObjectProperties *props = gcao->getProperties();
+ lua_newtable(L);
+
+ for (std::string &texture : props->textures) {
+ lua_pushstring(L, texture.c_str());
+ }
+ return 1;
+}
+
+int ClientObjectRef::l_get_hp(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ GenericCAO *gcao = get_generic_cao(ref, L);
+ lua_pushnumber(L, gcao->getHp());
+ return 1;
+}
+
+int ClientObjectRef::l_get_max_hp(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ GenericCAO *gcao = get_generic_cao(ref, L);
+ ObjectProperties *props = gcao->getProperties();
+ lua_pushnumber(L, props->hp_max);
+ return 1;
+}
+
+int ClientObjectRef::l_punch(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ GenericCAO *gcao = get_generic_cao(ref, L);
+ PointedThing pointed(gcao->getId(), v3f(0, 0, 0), v3s16(0, 0, 0), 0);
+ getClient(L)->interact(INTERACT_START_DIGGING, pointed);
+ return 0;
+}
+
+int ClientObjectRef::l_rightclick(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ GenericCAO *gcao = get_generic_cao(ref, L);
+ PointedThing pointed(gcao->getId(), v3f(0, 0, 0), v3s16(0, 0, 0), 0);
+ getClient(L)->interact(INTERACT_PLACE, pointed);
+ return 0;
+}
+
+ClientObjectRef::ClientObjectRef(ClientActiveObject *object) : m_object(object)
+{
+}
+
+void ClientObjectRef::create(lua_State *L, ClientActiveObject *object)
+{
+ if (object) {
+ ClientObjectRef *o = new ClientObjectRef(object);
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+ }
+}
+
+void ClientObjectRef::create(lua_State *L, s16 id)
+{
+ create(L, ((ClientEnvironment *)getEnv(L))->getActiveObject(id));
+}
+
+int ClientObjectRef::gc_object(lua_State *L)
+{
+ ClientObjectRef *obj = *(ClientObjectRef **)(lua_touserdata(L, 1));
+ delete obj;
+ return 0;
+}
+
+// taken from LuaLocalPlayer
+void ClientObjectRef::Register(lua_State *L)
+{
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable); // hide metatable from lua getmetatable()
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1); // Drop metatable
+
+ luaL_openlib(L, 0, methods, 0); // fill methodtable
+ lua_pop(L, 1); // Drop methodtable
+}
+
+const char ClientObjectRef::className[] = "ClientObjectRef";
+luaL_Reg ClientObjectRef::methods[] = {luamethod(ClientObjectRef, get_pos),
+ luamethod(ClientObjectRef, get_velocity),
+ luamethod(ClientObjectRef, get_acceleration),
+ luamethod(ClientObjectRef, get_rotation),
+ luamethod(ClientObjectRef, is_player),
+ luamethod(ClientObjectRef, is_local_player),
+ luamethod(ClientObjectRef, get_name),
+ luamethod(ClientObjectRef, get_attach),
+ luamethod(ClientObjectRef, get_nametag),
+ luamethod(ClientObjectRef, get_item_textures),
+ luamethod(ClientObjectRef, get_hp),
+ luamethod(ClientObjectRef, get_max_hp), luamethod(ClientObjectRef, punch),
+ luamethod(ClientObjectRef, rightclick), {0, 0}};
diff --git a/src/script/lua_api/l_clientobject.h b/src/script/lua_api/l_clientobject.h
new file mode 100644
index 000000000..1ff22407f
--- /dev/null
+++ b/src/script/lua_api/l_clientobject.h
@@ -0,0 +1,92 @@
+/*
+Dragonfire
+Copyright (C) 2020 system32
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "lua_api/l_base.h"
+#include "client/clientobject.h"
+#include "client/content_cao.h"
+
+class ClientObjectRef : public ModApiBase
+{
+public:
+ ClientObjectRef(ClientActiveObject *object);
+
+ ~ClientObjectRef() = default;
+
+ ClientActiveObject *getClientActiveObject();
+
+ static void Register(lua_State *L);
+
+ static void create(lua_State *L, ClientActiveObject *object);
+ static void create(lua_State *L, s16 id);
+
+ static ClientObjectRef *checkobject(lua_State *L, int narg);
+
+private:
+ ClientActiveObject *m_object = nullptr;
+ static const char className[];
+ static luaL_Reg methods[];
+
+ static ClientActiveObject *get_cao(ClientObjectRef *ref);
+ static GenericCAO *get_generic_cao(ClientObjectRef *ref, lua_State *L);
+
+ static int gc_object(lua_State *L);
+
+ // get_pos(self)
+ // returns: {x=num, y=num, z=num}
+ static int l_get_pos(lua_State *L);
+
+ // get_velocity(self)
+ static int l_get_velocity(lua_State *L);
+
+ // get_acceleration(self)
+ static int l_get_acceleration(lua_State *L);
+
+ // get_rotation(self)
+ static int l_get_rotation(lua_State *L);
+
+ // is_player(self)
+ static int l_is_player(lua_State *L);
+
+ // is_local_player(self)
+ static int l_is_local_player(lua_State *L);
+
+ // get_name(self)
+ static int l_get_name(lua_State *L);
+
+ // get_attach(self)
+ static int l_get_attach(lua_State *L);
+
+ // get_nametag(self)
+ static int l_get_nametag(lua_State *L);
+
+ // get_textures(self)
+ static int l_get_item_textures(lua_State *L);
+
+ // get_hp(self)
+ static int l_get_hp(lua_State *L);
+
+ // get_max_hp(self)
+ static int l_get_max_hp(lua_State *L);
+
+ // punch(self)
+ static int l_punch(lua_State *L);
+
+ // rightclick(self)
+ static int l_rightclick(lua_State *L);
+};
diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp
index c75fc8dc7..d6dc79ca8 100644
--- a/src/script/lua_api/l_env.cpp
+++ b/src/script/lua_api/l_env.cpp
@@ -848,7 +848,6 @@ int ModApiEnvMod::l_find_node_near(lua_State *L)
int radius = luaL_checkinteger(L, 2);
std::vector<content_t> filter;
collectNodeIds(L, 3, ndef, filter);
-
int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1;
#ifndef SERVER
@@ -871,6 +870,165 @@ int ModApiEnvMod::l_find_node_near(lua_State *L)
return 0;
}
+// find_nodes_near(pos, radius, nodenames, [search_center])
+// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
+int ModApiEnvMod::l_find_nodes_near(lua_State *L)
+{
+ GET_PLAIN_ENV_PTR;
+
+ const NodeDefManager *ndef = env->getGameDef()->ndef();
+ Map &map = env->getMap();
+
+ v3s16 pos = read_v3s16(L, 1);
+ int radius = luaL_checkinteger(L, 2);
+ std::vector<content_t> filter;
+ collectNodeIds(L, 3, ndef, filter);
+
+ int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1;
+
+#ifndef SERVER
+ // Client API limitations
+ if (Client *client = getClient(L))
+ radius = client->CSMClampRadius(pos, radius);
+#endif
+
+ std::vector<u32> individual_count;
+ individual_count.resize(filter.size());
+
+ lua_newtable(L);
+ u32 i = 0;
+
+ for (int d = start_radius; d <= radius; d++) {
+ const std::vector<v3s16> &list = FacePositionCache::getFacePositions(d);
+ for (const v3s16 &posi : list) {
+ v3s16 p = pos + posi;
+ content_t c = map.getNode(p).getContent();
+ auto it = std::find(filter.begin(), filter.end(), c);
+ if (it != filter.end()) {
+ push_v3s16(L, p);
+ lua_rawseti(L, -2, ++i);
+
+ u32 filt_index = it - filter.begin();
+ individual_count[filt_index]++;
+ }
+ }
+ }
+ lua_createtable(L, 0, filter.size());
+ for (u32 i = 0; i < filter.size(); i++) {
+ lua_pushinteger(L, individual_count[i]);
+ lua_setfield(L, -2, ndef->get(filter[i]).name.c_str());
+ }
+ return 2;
+}
+
+// find_nodes_near_under_air(pos, radius, nodenames, [search_center])
+// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
+int ModApiEnvMod::l_find_nodes_near_under_air(lua_State *L)
+{
+ GET_PLAIN_ENV_PTR;
+
+ const NodeDefManager *ndef = env->getGameDef()->ndef();
+ Map &map = env->getMap();
+
+ v3s16 pos = read_v3s16(L, 1);
+ int radius = luaL_checkinteger(L, 2);
+ std::vector<content_t> filter;
+ collectNodeIds(L, 3, ndef, filter);
+ int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1;
+
+#ifndef SERVER
+ // Client API limitations
+ if (Client *client = getClient(L))
+ radius = client->CSMClampRadius(pos, radius);
+#endif
+
+ std::vector<u32> individual_count;
+ individual_count.resize(filter.size());
+
+ lua_newtable(L);
+ u32 i = 0;
+
+ for (int d = start_radius; d <= radius; d++) {
+ const std::vector<v3s16> &list = FacePositionCache::getFacePositions(d);
+ for (const v3s16 &posi : list) {
+ v3s16 p = pos + posi;
+ content_t c = map.getNode(p).getContent();
+ v3s16 psurf(p.X, p.Y + 1, p.Z);
+ content_t csurf = map.getNode(psurf).getContent();
+ if (c == CONTENT_AIR || csurf != CONTENT_AIR)
+ continue;
+ auto it = std::find(filter.begin(), filter.end(), c);
+ if (it != filter.end()) {
+ push_v3s16(L, p);
+ lua_rawseti(L, -2, ++i);
+
+ u32 filt_index = it - filter.begin();
+ individual_count[filt_index]++;
+ }
+ }
+ }
+ lua_createtable(L, 0, filter.size());
+ for (u32 i = 0; i < filter.size(); i++) {
+ lua_pushinteger(L, individual_count[i]);
+ lua_setfield(L, -2, ndef->get(filter[i]).name.c_str());
+ }
+ return 2;
+}
+
+// find_nodes_near_under_air_except(pos, radius, nodenames, [search_center])
+// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
+int ModApiEnvMod::l_find_nodes_near_under_air_except(lua_State *L)
+{
+ GET_PLAIN_ENV_PTR;
+
+ const NodeDefManager *ndef = env->getGameDef()->ndef();
+ Map &map = env->getMap();
+
+ v3s16 pos = read_v3s16(L, 1);
+ int radius = luaL_checkinteger(L, 2);
+ std::vector<content_t> filter;
+ collectNodeIds(L, 3, ndef, filter);
+ int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1;
+
+#ifndef SERVER
+ // Client API limitations
+ if (Client *client = getClient(L))
+ radius = client->CSMClampRadius(pos, radius);
+#endif
+
+ std::vector<u32> individual_count;
+ individual_count.resize(filter.size());
+
+ lua_newtable(L);
+ u32 i = 0;
+
+ for (int d = start_radius; d <= radius; d++) {
+ const std::vector<v3s16> &list = FacePositionCache::getFacePositions(d);
+ for (const v3s16 &posi : list) {
+ v3s16 p = pos + posi;
+ content_t c = map.getNode(p).getContent();
+ v3s16 psurf(p.X, p.Y + 1, p.Z);
+ content_t csurf = map.getNode(psurf).getContent();
+ if (c == CONTENT_AIR || csurf != CONTENT_AIR)
+ continue;
+ auto it = std::find(filter.begin(), filter.end(), c);
+ if (it == filter.end()) {
+ push_v3s16(L, p);
+ lua_rawseti(L, -2, ++i);
+
+ u32 filt_index = it - filter.begin();
+ individual_count[filt_index]++;
+ }
+ }
+ }
+ lua_createtable(L, 0, filter.size());
+ for (u32 i = 0; i < filter.size(); i++) {
+ lua_pushinteger(L, individual_count[i]);
+ lua_setfield(L, -2, ndef->get(filter[i]).name.c_str());
+ }
+ return 2;
+}
+
// find_nodes_in_area(minp, maxp, nodenames, [grouped])
int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
{
@@ -1273,7 +1431,7 @@ int ModApiEnvMod::l_delete_area(lua_State *L)
// max_jump, max_drop, algorithm) -> table containing path
int ModApiEnvMod::l_find_path(lua_State *L)
{
- GET_ENV_PTR;
+ Environment *env = getEnv(L);
v3s16 pos1 = read_v3s16(L, 1);
v3s16 pos2 = read_v3s16(L, 2);
@@ -1290,8 +1448,8 @@ int ModApiEnvMod::l_find_path(lua_State *L)
if (algorithm == "Dijkstra")
algo = PA_DIJKSTRA;
}
-
- std::vector<v3s16> path = get_path(&env->getServerMap(), env->getGameDef()->ndef(), pos1, pos2,
+
+ std::vector<v3s16> path = get_path(&env->getMap(), env->getGameDef()->ndef(), pos1, pos2,
searchdistance, max_jump, max_drop, algo);
if (!path.empty()) {
@@ -1473,8 +1631,12 @@ void ModApiEnvMod::InitializeClient(lua_State *L, int top)
API_FCT(get_node_level);
API_FCT(find_nodes_with_meta);
API_FCT(find_node_near);
+ API_FCT(find_nodes_near);
+ API_FCT(find_nodes_near_under_air);
+ API_FCT(find_nodes_near_under_air_except);
API_FCT(find_nodes_in_area);
API_FCT(find_nodes_in_area_under_air);
+ API_FCT(find_path);
API_FCT(line_of_sight);
API_FCT(raycast);
}
diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h
index 42c2d64f8..29044c0e8 100644
--- a/src/script/lua_api/l_env.h
+++ b/src/script/lua_api/l_env.h
@@ -134,6 +134,18 @@ private:
// find_node_near(pos, radius, nodenames, search_center) -> pos or nil
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
static int l_find_node_near(lua_State *L);
+
+ // find_nodes_near(pos, radius, nodenames, search_center) -> list of positions
+ // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
+ static int l_find_nodes_near(lua_State *L);
+
+ // find_nodes_near_under_air(pos, radius, nodenames, search_center) -> list of positions
+ // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
+ static int l_find_nodes_near_under_air(lua_State *L);
+
+ // find_nodes_near_under_air(pos, radius, nodenames, search_center) -> list of positions
+ // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
+ static int l_find_nodes_near_under_air_except(lua_State *L);
// find_nodes_in_area(minp, maxp, nodenames) -> list of positions
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
diff --git a/src/script/lua_api/l_http.cpp b/src/script/lua_api/l_http.cpp
index 5ea3b3f99..0bf9cfbad 100644
--- a/src/script/lua_api/l_http.cpp
+++ b/src/script/lua_api/l_http.cpp
@@ -239,18 +239,8 @@ int ModApiHttp::l_get_http_api(lua_State *L)
void ModApiHttp::Initialize(lua_State *L, int top)
{
#if USE_CURL
-
- bool isMainmenu = false;
-#ifndef SERVER
- isMainmenu = ModApiBase::getGuiEngine(L) != nullptr;
-#endif
-
- if (isMainmenu) {
- API_FCT(get_http_api);
- } else {
- API_FCT(request_http_api);
- }
-
+ API_FCT(get_http_api);
+ API_FCT(request_http_api);
#endif
}
diff --git a/src/script/lua_api/l_inventoryaction.cpp b/src/script/lua_api/l_inventoryaction.cpp
new file mode 100644
index 000000000..f65137465
--- /dev/null
+++ b/src/script/lua_api/l_inventoryaction.cpp
@@ -0,0 +1,215 @@
+/*
+Dragonfire
+Copyright (C) 2020 Elias Fleckenstein <eliasfleckenstein@web.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "l_inventoryaction.h"
+#include "l_internal.h"
+#include "client/client.h"
+
+int LuaInventoryAction::gc_object(lua_State *L)
+{
+ LuaInventoryAction *o = *(LuaInventoryAction **)(lua_touserdata(L, 1));
+ delete o;
+ return 0;
+}
+
+int LuaInventoryAction::mt_tostring(lua_State *L)
+{
+ LuaInventoryAction *o = checkobject(L, 1);
+ std::ostringstream os(std::ios::binary);
+ o->m_action->serialize(os);
+ lua_pushfstring(L, "InventoryAction(\"%s\")", os.str().c_str());
+ return 1;
+}
+
+int LuaInventoryAction::l_apply(lua_State *L)
+{
+ LuaInventoryAction *o = checkobject(L, 1);
+
+ std::ostringstream os(std::ios::binary);
+ o->m_action->serialize(os);
+
+ std::istringstream is(os.str(), std::ios_base::binary);
+
+ InventoryAction *a = InventoryAction::deSerialize(is);
+
+ getClient(L)->inventoryAction(a);
+ return 0;
+}
+
+int LuaInventoryAction::l_from(lua_State *L)
+{
+ GET_MOVE_ACTION
+ readFullInventoryLocationInto(L, &act->from_inv, &act->from_list, &act->from_i);
+ return 0;
+}
+
+int LuaInventoryAction::l_to(lua_State *L)
+{
+ GET_MOVE_ACTION
+ readFullInventoryLocationInto(L, &act->to_inv, &act->to_list, &act->to_i);
+ return 0;
+}
+
+int LuaInventoryAction::l_craft(lua_State *L)
+{
+ LuaInventoryAction *o = checkobject(L, 1);
+
+ if (o->m_action->getType() != IAction::Craft)
+ return 0;
+
+ std::string locStr;
+ InventoryLocation loc;
+
+ locStr = readParam<std::string>(L, 2);
+
+ try {
+ loc.deSerialize(locStr);
+ dynamic_cast<ICraftAction *>(o->m_action)->craft_inv = loc;
+ } catch (SerializationError &) {
+ }
+
+ return 0;
+}
+
+int LuaInventoryAction::l_set_count(lua_State *L)
+{
+ LuaInventoryAction *o = checkobject(L, 1);
+
+ s16 count = luaL_checkinteger(L, 2);
+
+ switch (o->m_action->getType()) {
+ case IAction::Move:
+ ((IMoveAction *)o->m_action)->count = count;
+ break;
+ case IAction::Drop:
+ ((IDropAction *)o->m_action)->count = count;
+ break;
+ case IAction::Craft:
+ ((ICraftAction *)o->m_action)->count = count;
+ break;
+ }
+
+ return 0;
+}
+
+LuaInventoryAction::LuaInventoryAction(const IAction &type) : m_action(nullptr)
+{
+ switch (type) {
+ case IAction::Move:
+ m_action = new IMoveAction();
+ break;
+ case IAction::Drop:
+ m_action = new IDropAction();
+ break;
+ case IAction::Craft:
+ m_action = new ICraftAction();
+ break;
+ }
+}
+
+LuaInventoryAction::~LuaInventoryAction()
+{
+ delete m_action;
+}
+
+void LuaInventoryAction::readFullInventoryLocationInto(
+ lua_State *L, InventoryLocation *loc, std::string *list, s16 *index)
+{
+ try {
+ loc->deSerialize(readParam<std::string>(L, 2));
+ std::string l = readParam<std::string>(L, 3);
+ *list = l;
+ *index = luaL_checkinteger(L, 4) - 1;
+ } catch (SerializationError &) {
+ }
+}
+
+int LuaInventoryAction::create_object(lua_State *L)
+{
+ IAction type;
+ std::string typeStr;
+
+ typeStr = readParam<std::string>(L, 1);
+
+ if (typeStr == "move")
+ type = IAction::Move;
+ else if (typeStr == "drop")
+ type = IAction::Drop;
+ else if (typeStr == "craft")
+ type = IAction::Craft;
+ else
+ return 0;
+
+ LuaInventoryAction *o = new LuaInventoryAction(type);
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+ return 1;
+}
+
+int LuaInventoryAction::create(lua_State *L, const IAction &type)
+{
+ LuaInventoryAction *o = new LuaInventoryAction(type);
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+ return 1;
+}
+
+LuaInventoryAction *LuaInventoryAction::checkobject(lua_State *L, int narg)
+{
+ return *(LuaInventoryAction **)luaL_checkudata(L, narg, className);
+}
+
+void LuaInventoryAction::Register(lua_State *L)
+{
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, mt_tostring);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1);
+
+ luaL_openlib(L, 0, methods, 0);
+ lua_pop(L, 1);
+
+ lua_register(L, className, create_object);
+}
+
+const char LuaInventoryAction::className[] = "InventoryAction";
+const luaL_Reg LuaInventoryAction::methods[] = {luamethod(LuaInventoryAction, apply),
+ luamethod(LuaInventoryAction, from), luamethod(LuaInventoryAction, to),
+ luamethod(LuaInventoryAction, craft),
+ luamethod(LuaInventoryAction, set_count), {0, 0}};
diff --git a/src/script/lua_api/l_inventoryaction.h b/src/script/lua_api/l_inventoryaction.h
new file mode 100644
index 000000000..a4cc6cbe5
--- /dev/null
+++ b/src/script/lua_api/l_inventoryaction.h
@@ -0,0 +1,74 @@
+/*
+Dragonfire
+Copyright (C) 2020 Elias Fleckenstein <eliasfleckenstein@web.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "inventorymanager.h"
+#include "lua_api/l_base.h"
+
+#define GET_MOVE_ACTION \
+ LuaInventoryAction *o = checkobject(L, 1); \
+ if (o->m_action->getType() == IAction::Craft) \
+ return 0; \
+ MoveAction *act = dynamic_cast<MoveAction *>(o->m_action);
+
+class LuaInventoryAction : public ModApiBase
+{
+private:
+ InventoryAction *m_action;
+
+ static void readFullInventoryLocationInto(lua_State *L, InventoryLocation *loc,
+ std::string *list, s16 *index);
+
+ static const char className[];
+ static const luaL_Reg methods[];
+
+ // Exported functions
+
+ // garbage collector
+ static int gc_object(lua_State *L);
+
+ // __tostring metamethod
+ static int mt_tostring(lua_State *L);
+
+ // apply(self)
+ static int l_apply(lua_State *L);
+
+ // from(self, location, list, index)
+ static int l_from(lua_State *L);
+
+ // to(self, location, list, index)
+ static int l_to(lua_State *L);
+
+ // craft(self, location)
+ static int l_craft(lua_State *L);
+
+ // set_count(self, count)
+ static int l_set_count(lua_State *L);
+
+public:
+ LuaInventoryAction(const IAction &type);
+ ~LuaInventoryAction();
+
+ // LuaInventoryAction(inventory action type)
+ // Creates an LuaInventoryAction and leaves it on top of stack
+ static int create_object(lua_State *L);
+ // Not callable from Lua
+ static int create(lua_State *L, const IAction &type);
+ static LuaInventoryAction *checkobject(lua_State *L, int narg);
+ static void Register(lua_State *L);
+};
diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp
index 9e0da4034..b098eccf0 100644
--- a/src/script/lua_api/l_item.cpp
+++ b/src/script/lua_api/l_item.cpp
@@ -27,7 +27,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#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)
@@ -534,9 +539,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;
@@ -584,8 +589,9 @@ int ModApiItemMod::l_register_item_raw(lua_State *L)
+ itos(MAX_REGISTERED_CONTENT+1)
+ ") exceeded (" + name + ")");
}
+
}
-
+
return 0; /* number of results */
}
@@ -596,12 +602,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);
}
@@ -619,7 +625,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 33fa27c8b..3f4147227 100644
--- a/src/script/lua_api/l_localplayer.cpp
+++ b/src/script/lua_api/l_localplayer.cpp
@@ -17,6 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include "l_clientobject.h"
#include "l_localplayer.h"
#include "l_internal.h"
#include "lua_api/l_item.h"
@@ -24,7 +25,9 @@ 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"
+#include "client/game.h"
LuaLocalPlayer::LuaLocalPlayer(LocalPlayer *m) : m_localplayer(m)
{
@@ -60,6 +63,57 @@ int LuaLocalPlayer::l_get_velocity(lua_State *L)
return 1;
}
+int LuaLocalPlayer::l_set_velocity(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ v3f pos = checkFloatPos(L, 2);
+ player->setSpeed(pos);
+
+ return 0;
+}
+
+int LuaLocalPlayer::l_get_yaw(lua_State *L)
+{
+ lua_pushnumber(L, wrapDegrees_0_360(g_game->cam_view.camera_yaw));
+ return 1;
+}
+
+int LuaLocalPlayer::l_set_yaw(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ if (lua_isnumber(L, 2)) {
+ int yaw = lua_tonumber(L, 2);
+ player->setYaw(yaw);
+ g_game->cam_view.camera_yaw = yaw;
+ g_game->cam_view_target.camera_yaw = yaw;
+ }
+
+ return 0;
+}
+
+int LuaLocalPlayer::l_get_pitch(lua_State *L)
+{
+ lua_pushnumber(L, -wrapDegrees_180(g_game->cam_view.camera_pitch) );
+ return 1;
+}
+
+int LuaLocalPlayer::l_set_pitch(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ if (lua_isnumber(L, 2)) {
+ int pitch = lua_tonumber(L, 2);
+ player->setPitch(pitch);
+ g_game->cam_view.camera_pitch = pitch;
+ g_game->cam_view_target.camera_pitch = pitch;
+ }
+
+ return 0;
+}
+
+
int LuaLocalPlayer::l_get_hp(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
@@ -81,10 +135,24 @@ int LuaLocalPlayer::l_get_wield_index(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
- lua_pushinteger(L, player->getWieldIndex());
+ lua_pushinteger(L, player->getWieldIndex() + 1);
return 1;
}
+// set_wield_index(self)
+int LuaLocalPlayer::l_set_wield_index(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+ u32 index = luaL_checkinteger(L, 2) - 1;
+
+ player->setWieldIndex(index);
+ g_game->processItemSelection(&g_game->runData.new_playeritem);
+ ItemStack selected_item, hand_item;
+ ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item);
+ g_game->camera->wield(tool_item);
+ return 0;
+}
+
// get_wielded_item(self)
int LuaLocalPlayer::l_get_wielded_item(lua_State *L)
{
@@ -157,26 +225,30 @@ int LuaLocalPlayer::l_get_physics_override(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
- lua_newtable(L);
- lua_pushnumber(L, player->physics_override_speed);
- lua_setfield(L, -2, "speed");
-
- lua_pushnumber(L, player->physics_override_jump);
- lua_setfield(L, -2, "jump");
-
- lua_pushnumber(L, player->physics_override_gravity);
- lua_setfield(L, -2, "gravity");
-
- lua_pushboolean(L, player->physics_override_sneak);
- lua_setfield(L, -2, "sneak");
-
- lua_pushboolean(L, player->physics_override_sneak_glitch);
- lua_setfield(L, -2, "sneak_glitch");
+ push_physics_override(L, player->physics_override_speed, player->physics_override_jump, player->physics_override_gravity, player->physics_override_sneak, player->physics_override_sneak_glitch, player->physics_override_new_move);
+
+ return 1;
+}
- lua_pushboolean(L, player->physics_override_new_move);
- lua_setfield(L, -2, "new_move");
+// set_physics_override(self, override)
+int LuaLocalPlayer::l_set_physics_override(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ player->physics_override_speed = getfloatfield_default(
+ L, 2, "speed", player->physics_override_speed);
+ player->physics_override_jump = getfloatfield_default(
+ L, 2, "jump", player->physics_override_jump);
+ player->physics_override_gravity = getfloatfield_default(
+ L, 2, "gravity", player->physics_override_gravity);
+ player->physics_override_sneak = getboolfield_default(
+ L, 2, "sneak", player->physics_override_sneak);
+ player->physics_override_sneak_glitch = getboolfield_default(
+ L, 2, "sneak_glitch", player->physics_override_sneak_glitch);
+ player->physics_override_new_move = getboolfield_default(
+ L, 2, "new_move", player->physics_override_new_move);
- return 1;
+ return 0;
}
int LuaLocalPlayer::l_get_last_pos(lua_State *L)
@@ -255,6 +327,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)
{
@@ -393,6 +476,17 @@ int LuaLocalPlayer::l_hud_get(lua_State *L)
return 1;
}
+int LuaLocalPlayer::l_get_object(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+ ClientEnvironment &env = getClient(L)->getEnv();
+ ClientActiveObject *obj = env.getGenericCAO(player->getCAO()->getId());
+
+ ClientObjectRef::create(L, obj);
+
+ return 1;
+}
+
LuaLocalPlayer *LuaLocalPlayer::checkobject(lua_State *L, int narg)
{
luaL_checktype(L, narg, LUA_TUSERDATA);
@@ -453,9 +547,15 @@ void LuaLocalPlayer::Register(lua_State *L)
const char LuaLocalPlayer::className[] = "LocalPlayer";
const luaL_Reg LuaLocalPlayer::methods[] = {
luamethod(LuaLocalPlayer, get_velocity),
+ luamethod(LuaLocalPlayer, set_velocity),
+ luamethod(LuaLocalPlayer, get_yaw),
+ luamethod(LuaLocalPlayer, set_yaw),
+ luamethod(LuaLocalPlayer, get_pitch),
+ luamethod(LuaLocalPlayer, set_pitch),
luamethod(LuaLocalPlayer, get_hp),
luamethod(LuaLocalPlayer, get_name),
luamethod(LuaLocalPlayer, get_wield_index),
+ luamethod(LuaLocalPlayer, set_wield_index),
luamethod(LuaLocalPlayer, get_wielded_item),
luamethod(LuaLocalPlayer, is_attached),
luamethod(LuaLocalPlayer, is_touching_ground),
@@ -465,6 +565,7 @@ const luaL_Reg LuaLocalPlayer::methods[] = {
luamethod(LuaLocalPlayer, is_climbing),
luamethod(LuaLocalPlayer, swimming_vertical),
luamethod(LuaLocalPlayer, get_physics_override),
+ luamethod(LuaLocalPlayer, set_physics_override),
// TODO: figure our if these are useful in any way
luamethod(LuaLocalPlayer, get_last_pos),
luamethod(LuaLocalPlayer, get_last_velocity),
@@ -474,6 +575,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),
@@ -482,6 +584,7 @@ const luaL_Reg LuaLocalPlayer::methods[] = {
luamethod(LuaLocalPlayer, hud_remove),
luamethod(LuaLocalPlayer, hud_change),
luamethod(LuaLocalPlayer, hud_get),
+ luamethod(LuaLocalPlayer, get_object),
{0, 0}
};
diff --git a/src/script/lua_api/l_localplayer.h b/src/script/lua_api/l_localplayer.h
index 4413f2bdb..33e23d178 100644
--- a/src/script/lua_api/l_localplayer.h
+++ b/src/script/lua_api/l_localplayer.h
@@ -35,6 +35,21 @@ private:
// get_velocity(self)
static int l_get_velocity(lua_State *L);
+ // set_velocity(self, vel)
+ static int l_set_velocity(lua_State *L);
+
+ // get_yaw(self)
+ static int l_get_yaw(lua_State *L);
+
+ // set_yaw(self, yaw)
+ static int l_set_yaw(lua_State *L);
+
+ // get_pitch(self)
+ static int l_get_pitch(lua_State *L);
+
+ // set_pitch(self,pitch)
+ static int l_set_pitch(lua_State *L);
+
// get_hp(self)
static int l_get_hp(lua_State *L);
@@ -44,6 +59,9 @@ private:
// get_wield_index(self)
static int l_get_wield_index(lua_State *L);
+ // set_wield_index(self)
+ static int l_set_wield_index(lua_State *L);
+
// get_wielded_item(self)
static int l_get_wielded_item(lua_State *L);
@@ -56,6 +74,7 @@ private:
static int l_swimming_vertical(lua_State *L);
static int l_get_physics_override(lua_State *L);
+ static int l_set_physics_override(lua_State *L);
static int l_get_override_pos(lua_State *L);
@@ -73,6 +92,9 @@ private:
// get_pos(self)
static int l_get_pos(lua_State *L);
+ // set_pos(self, pos)
+ static int l_set_pos(lua_State *L);
+
// get_movement_acceleration(self)
static int l_get_movement_acceleration(lua_State *L);
@@ -96,6 +118,9 @@ private:
// hud_get(self, id)
static int l_hud_get(lua_State *L);
+ // get_object(self)
+ static int l_get_object(lua_State *L);
+
LocalPlayer *m_localplayer = nullptr;
public:
diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp
index ba7f708a4..4d437b967 100644
--- a/src/script/lua_api/l_mainmenu.cpp
+++ b/src/script/lua_api/l_mainmenu.cpp
@@ -727,6 +727,9 @@ bool ModApiMainMenu::mayModifyPath(const std::string &path)
if (fs::PathStartsWith(path, fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM "mods")))
return true;
+ if (fs::PathStartsWith(path, fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM "clientmods")))
+ return true;
+
if (fs::PathStartsWith(path, fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM "textures")))
return true;
diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp
index bf5292521..026f5282c 100644
--- a/src/script/lua_api/l_server.cpp
+++ b/src/script/lua_api/l_server.cpp
@@ -317,6 +317,7 @@ int ModApiServer::l_kick_player(lua_State *L)
return 1;
}
+// remove_player(name)
int ModApiServer::l_remove_player(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
@@ -552,7 +553,6 @@ void ModApiServer::Initialize(lua_State *L, int top)
API_FCT(get_ban_description);
API_FCT(ban_player);
API_FCT(kick_player);
- API_FCT(remove_player);
API_FCT(unban_player_or_ip);
API_FCT(notify_authentication_modified);
diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp
index 203a0dd28..60ae7871c 100644
--- a/src/script/lua_api/l_util.cpp
+++ b/src/script/lua_api/l_util.cpp
@@ -532,11 +532,16 @@ void ModApiUtil::InitializeClient(lua_State *L, int top)
API_FCT(compress);
API_FCT(decompress);
+ API_FCT(request_insecure_environment);
+
API_FCT(encode_base64);
API_FCT(decode_base64);
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..729645678 100644
--- a/src/script/scripting_client.cpp
+++ b/src/script/scripting_client.cpp
@@ -20,9 +20,12 @@ 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_clientobject.h"
#include "lua_api/l_env.h"
+#include "lua_api/l_inventoryaction.h"
#include "lua_api/l_item.h"
#include "lua_api/l_itemstackmeta.h"
#include "lua_api/l_minimap.h"
@@ -35,11 +38,14 @@ 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"
+#include "lua_api/l_http.h"
ClientScripting::ClientScripting(Client *client):
ScriptApiBase(ScriptingType::Client)
{
setGameDef(client);
+ setGame(g_game);
SCRIPTAPI_PRECHECKHEADER
@@ -73,8 +79,13 @@ void ClientScripting::InitializeModApi(lua_State *L, int top)
LuaLocalPlayer::Register(L);
LuaCamera::Register(L);
ModChannelRef::Register(L);
+ LuaSettings::Register(L);
+ ClientObjectRef::Register(L);
+ LuaInventoryAction::Register(L);
+ ModApiItemMod::Initialize(L, top);
ModApiUtil::InitializeClient(L, top);
+ ModApiHttp::Initialize(L, top);
ModApiClient::Initialize(L, top);
ModApiStorage::Initialize(L, top);
ModApiEnvMod::InitializeClient(L, top);
diff --git a/src/script/scripting_client.h b/src/script/scripting_client.h
index 3088029f0..e162f8bcf 100644
--- a/src/script/scripting_client.h
+++ b/src/script/scripting_client.h
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "cpp_api/s_base.h"
#include "cpp_api/s_client.h"
+#include "cpp_api/s_cheats.h"
#include "cpp_api/s_modchannels.h"
#include "cpp_api/s_security.h"
@@ -34,7 +35,8 @@ class ClientScripting:
virtual public ScriptApiBase,
public ScriptApiSecurity,
public ScriptApiClient,
- public ScriptApiModChannels
+ public ScriptApiModChannels,
+ public ScriptApiCheats
{
public:
ClientScripting(Client *client);
diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp
index af324e1b1..d4841d559 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;
diff --git a/textures/base/pack/logo.png b/textures/base/pack/logo.png
index 48793678f..5284900b2 100644
--- a/textures/base/pack/logo.png
+++ b/textures/base/pack/logo.png
Binary files differ
diff --git a/textures/base/pack/menu_bg.png b/textures/base/pack/menu_bg.png
index ed7e34f61..6f6836e2c 100644
--- a/textures/base/pack/menu_bg.png
+++ b/textures/base/pack/menu_bg.png
Binary files differ
diff --git a/util/buildbot/buildwin32.sh b/util/buildbot/buildwin32.sh
index e62d32969..a4238fbd8 100755
--- a/util/buildbot/buildwin32.sh
+++ b/util/buildbot/buildwin32.sh
@@ -1,12 +1,12 @@
#!/bin/bash
set -e
-CORE_GIT=https://github.com/minetest/minetest
+CORE_GIT=https://github.com/EliasFleckenstein03/dragonfireclient
CORE_BRANCH=master
-CORE_NAME=minetest
-GAME_GIT=https://github.com/minetest/minetest_game
+CORE_NAME=dragonfireclient
+GAME_GIT=https://git.minetest.land/Wuzzy/MineClone2
GAME_BRANCH=master
-GAME_NAME=minetest_game
+GAME_NAME=mineclone2
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
if [ $# -ne 1 ]; then
diff --git a/util/buildbot/buildwin64.sh b/util/buildbot/buildwin64.sh
index 94e009c29..1b680cf5b 100755
--- a/util/buildbot/buildwin64.sh
+++ b/util/buildbot/buildwin64.sh
@@ -1,12 +1,12 @@
#!/bin/bash
set -e
-CORE_GIT=https://github.com/minetest/minetest
+CORE_GIT=https://github.com/EliasFleckenstein03/dragonfireclient
CORE_BRANCH=master
-CORE_NAME=minetest
-GAME_GIT=https://github.com/minetest/minetest_game
+CORE_NAME=dragonfireclient
+GAME_GIT=https://git.minetest.land/Wuzzy/MineClone2
GAME_BRANCH=master
-GAME_NAME=minetest_game
+GAME_NAME=mineclone2
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
if [ $# -ne 1 ]; then
diff --git a/util/ci/lint_autocorrect.sh b/util/ci/lint_autocorrect.sh
new file mode 100644
index 000000000..6a8881231
--- /dev/null
+++ b/util/ci/lint_autocorrect.sh
@@ -0,0 +1,45 @@
+#! /bin/bash
+function perform_lint() {
+ echo "Performing LINT..."
+ if [ -z "${CLANG_FORMAT}" ]; then
+ CLANG_FORMAT=clang-format
+ fi
+ echo "LINT: Using binary $CLANG_FORMAT"
+ CLANG_FORMAT_WHITELIST="util/ci/clang-format-whitelist.txt"
+
+ files_to_lint="$(find src/ -name '*.cpp' -or -name '*.h')"
+
+ local errorcount=0
+ local fail=0
+ for f in ${files_to_lint}; do
+ d=$(diff -u "$f" <(${CLANG_FORMAT} "$f") || true)
+
+ if ! [ -z "$d" ]; then
+ whitelisted=$(awk '$1 == "'$f'" { print 1 }' "$CLANG_FORMAT_WHITELIST")
+
+ # If file is not whitelisted, mark a failure
+ if [ -z "${whitelisted}" ]; then
+ errorcount=$((errorcount+1))
+
+ printf "The file %s is not compliant with the coding style" "$f"
+ if [ ${errorcount} -gt 50 ]; then
+ printf "\nToo many errors encountered previously, this diff is hidden.\n"
+ else
+ printf ":\n%s\n" "$d"
+ fi
+
+ ${CLANG_FORMAT} -i "$f"
+
+ fail=1
+ fi
+ fi
+ done
+
+ if [ "$fail" = 1 ]; then
+ echo "LINT reports failure."
+ exit 1
+ fi
+
+ echo "LINT OK"
+}
+