From 45a2ca0af2285ab32003bd0d07690551b895b480 Mon Sep 17 00:00:00 2001 From: Paramat Date: Fri, 3 Apr 2020 02:57:15 +0100 Subject: Add warning to set_sky() docs about unstable dawn and night sky colours (#9578) Also clean up confusing double meaning usage of the word 'skybox'. --- doc/lua_api.txt | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 86e8d6575..bd95062a5 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -5991,19 +5991,27 @@ object you are working with still exists. * `clouds`: Boolean for whether clouds appear. (default: `true`) * `sky_color`: A table containing the following values, alpha is ignored: * `day_sky`: ColorSpec, for the top half of the `"regular"` - skybox during the day. (default: `#8cbafa`) + sky during the day. (default: `#8cbafa`) * `day_horizon`: ColorSpec, for the bottom half of the - `"regular"` skybox during the day. (default: `#9bc1f0`) + `"regular"` sky during the day. (default: `#9bc1f0`) * `dawn_sky`: ColorSpec, for the top half of the `"regular"` - skybox during dawn/sunset. (default: `#b4bafa`) + sky during dawn/sunset. (default: `#b4bafa`) + The resulting sky color will be a darkened version of the ColorSpec. + Warning: The darkening of the ColorSpec is subject to change. * `dawn_horizon`: ColorSpec, for the bottom half of the `"regular"` - skybox during dawn/sunset. (default: `#bac1f0`) + sky during dawn/sunset. (default: `#bac1f0`) + The resulting sky color will be a darkened version of the ColorSpec. + Warning: The darkening of the ColorSpec is subject to change. * `night_sky`: ColorSpec, for the top half of the `"regular"` - skybox during the night. (default: `#006aff`) + sky during the night. (default: `#006aff`) + The resulting sky color will be a dark version of the ColorSpec. + Warning: The darkening of the ColorSpec is subject to change. * `night_horizon`: ColorSpec, for the bottom half of the `"regular"` - skybox during the night. (default: `#4090ff`) + sky during the night. (default: `#4090ff`) + The resulting sky color will be a dark version of the ColorSpec. + Warning: The darkening of the ColorSpec is subject to change. * `indoors`: ColorSpec, for when you're either indoors or - underground. Only applies to the `"regular"` skybox. + underground. Only applies to the `"regular"` sky. (default: `#646464`) * `fog_sun_tint`: ColorSpec, changes the fog tinting for the sun at sunrise and sunset. @@ -6047,7 +6055,7 @@ object you are working with still exists. * `visible`: Boolean for whether the stars are visible. (default: `true`) * `count`: Integer number to set the number of stars in - the skybox. Only applies to `"skybox"` and `"regular"` skyboxes. + the skybox. Only applies to `"skybox"` and `"regular"` sky types. (default: `1000`) * `star_color`: ColorSpec, sets the colors of the stars, alpha channel is used to set overall star brightness. -- cgit v1.2.3 From 528b162d9fb5acd517b3af1e5de79ec170903af8 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sun, 5 Apr 2020 18:31:52 +0200 Subject: Continue with 5.3.0-dev --- CMakeLists.txt | 4 ++-- doc/client_lua_api.txt | 2 +- doc/menu_lua_api.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'doc') diff --git a/CMakeLists.txt b/CMakeLists.txt index 7613e684c..bf409c124 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,12 +16,12 @@ set(CLANG_MINIMUM_VERSION "3.4") # Also remember to set PROTOCOL_VERSION in network/networkprotocol.h when releasing set(VERSION_MAJOR 5) -set(VERSION_MINOR 2) +set(VERSION_MINOR 3) set(VERSION_PATCH 0) set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string") # Change to false for releases -set(DEVELOPMENT_BUILD FALSE) +set(DEVELOPMENT_BUILD TRUE) set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") if(VERSION_EXTRA) diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index c24de8d85..3612f851b 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -1,4 +1,4 @@ -Minetest Lua Client Modding API Reference 5.2.0 +Minetest Lua Client Modding API Reference 5.3.0 ================================================ * More information at * Developer Wiki: diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index 4861ed0d9..df6424ad7 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -1,4 +1,4 @@ -Minetest Lua Mainmenu API Reference 5.2.0 +Minetest Lua Mainmenu API Reference 5.3.0 ========================================= Introduction -- cgit v1.2.3 From faedde08f96b671078d9d3273da468db3454713c Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 6 Apr 2020 16:05:27 +0200 Subject: Some minor Lua API documentation clarifications (#9461) See #5854 --- doc/lua_api.txt | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index bd95062a5..d0b07a4b2 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1010,22 +1010,24 @@ The function of `param2` is determined by `paramtype2` in node definition. * Values range 0 - 179. The value stored in `param2` is multiplied by two to get the actual rotation in degrees of the node. * `paramtype2 = "meshoptions"` - * Only valid for "plantlike" drawtype. The value of `param2` becomes a - bitfield which can be used to change how the client draws plantlike nodes. - * Bits 0, 1 and 2 form a mesh selector. - Currently the following meshes are choosable: + * Only valid for "plantlike" drawtype. `param2` encodes the shape and + optional modifiers of the "plant". `param2` is a bitfield. + * Bits 0 to 2 select the shape. + Use only one of the values below: * 0 = a "x" shaped plant (ordinary plant) * 1 = a "+" shaped plant (just rotated 45 degrees) * 2 = a "*" shaped plant with 3 faces instead of 2 * 3 = a "#" shaped plant with 4 faces instead of 2 * 4 = a "#" shaped plant with 4 faces that lean outwards * 5-7 are unused and reserved for future meshes. - * Bits 3 through 7 are optional flags that can be combined and give these - effects: - * bit 3 (0x08) - Makes the plant slightly vary placement horizontally - * bit 4 (0x10) - Makes the plant mesh 1.4x larger - * bit 5 (0x20) - Moves each face randomly a small bit down (1/8 max) - * bits 6-7 are reserved for future use. + * Bits 3 to 7 are used to enable any number of optional modifiers. + Just add the corresponding value(s) below to `param2`: + * 8 - Makes the plant slightly vary placement horizontally + * 16 - Makes the plant mesh 1.4x larger + * 32 - Moves each face randomly a small bit down (1/8 max) + * values 64 and 128 (bits 6-7) are reserved for future use. + * Example: `param2 = 0` selects a normal "x" shaped plant + * Example: `param2 = 17` selects a "+" shaped plant, 1.4x larger (1+16) * `paramtype2 = "color"` * `param2` tells which color is picked from the palette. The palette should have 256 pixels. @@ -2332,8 +2334,8 @@ Elements * `name` fieldname data is transferred to Lua * `caption 1`...: name shown on top of tab * `current_tab`: index of selected tab 1... -* `transparent` (optional): show transparent -* `draw_border` (optional): draw border +* `transparent` (optional): if true, tabs are semi-transparent +* `draw_border` (optional): if true, draw a thin line at tab base ### `tabheader[,;;;,,...,;;;]` @@ -7020,6 +7022,7 @@ Used by `minetest.register_node`. -- node is deleted from the world or the drops are added. This is -- generally the result of either the node being dug or an attached node -- becoming detached. + -- oldmeta is the NodeMetaRef of the oldnode before deletion. -- drops is a table of ItemStacks, so any metadata to be preserved can -- be added directly to one or more of the dropped items. See -- "ItemStackMetaRef". @@ -7044,10 +7047,14 @@ Used by `minetest.register_node`. on_punch = function(pos, node, puncher, pointed_thing), -- default: minetest.node_punch + -- Called when puncher (an ObjectRef) punches the node at pos. -- By default calls minetest.register_on_punchnode callbacks. on_rightclick = function(pos, node, clicker, itemstack, pointed_thing), -- default: nil + -- Called when clicker (an ObjectRef) "rightclicks" + -- ("rightclick" here stands for the placement key) while pointing at + -- the node at pos with 'node' being the node table. -- itemstack will hold clicker's wielded item. -- Shall return the leftover itemstack. -- Note: pointed_thing can be nil, if a mod calls this function. -- cgit v1.2.3 From f91124a0c0d8c448b3d3d0767b3c8b2352c92d6e Mon Sep 17 00:00:00 2001 From: Wren Turkal Date: Mon, 6 Apr 2020 07:06:16 -0700 Subject: Add allowed_mapgens option in game.conf. (#9263) The game.conf has a disallowed_mapgens option. However, some games require a certain mapgen to be used, like the CTF plugin. This change adds an option to specify allowed mapgens so that the setting can be specified in a way that needn't be updated as map generators are added to Minetest. --- builtin/mainmenu/dlg_create_world.lua | 13 +++++++++++++ doc/lua_api.txt | 8 ++++++++ 2 files changed, 21 insertions(+) (limited to 'doc') diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua index 31d41d693..f28ae6960 100644 --- a/builtin/mainmenu/dlg_create_world.lua +++ b/builtin/mainmenu/dlg_create_world.lua @@ -39,11 +39,24 @@ local function create_world_formspec(dialogdata) local gamepath = game_by_gameidx.path local gameconfig = Settings(gamepath.."/game.conf") + local allowed_mapgens = (gameconfig:get("allowed_mapgens") or ""):split() + for key, value in pairs(allowed_mapgens) do + allowed_mapgens[key] = value:trim() + end + local disallowed_mapgens = (gameconfig:get("disallowed_mapgens") or ""):split() for key, value in pairs(disallowed_mapgens) do disallowed_mapgens[key] = value:trim() end + if #allowed_mapgens > 0 then + for i = #mapgens, 1, -1 do + if table.indexof(allowed_mapgens, mapgens[i]) == -1 then + table.remove(mapgens, i) + end + end + end + if disallowed_mapgens then for i = #mapgens, 1, -1 do if table.indexof(disallowed_mapgens, mapgens[i]) > 0 then diff --git a/doc/lua_api.txt b/doc/lua_api.txt index d0b07a4b2..ce9fc61b2 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -64,9 +64,17 @@ The game directory can contain the following files: * `game.conf`, with the following keys: * `name`: Required, human readable name e.g. `name = Minetest` * `description`: Short description to be shown in the content tab + * `allowed_mapgens = ` + e.g. `allowed_mapgens = v5,v6,flat` + Mapgens not in this list are removed from the list of mapgens for + the game. + If not specified, all mapgens are allowed. * `disallowed_mapgens = ` e.g. `disallowed_mapgens = v5,v6,flat` These mapgens are removed from the list of mapgens for the game. + When both `allowed_mapgens` and `disallowed_mapgens` are + specified, `allowed_mapgens` is applied before + `disallowed_mapgens`. * `minetest.conf`: Used to set default settings when running this game. * `settingtypes.txt`: -- cgit v1.2.3 From 143a37e947d809ac68da56bac0f61cf8b5fd0d46 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Mon, 6 Apr 2020 15:54:27 +0100 Subject: Clarify use of minetest.request_insecure_environment() (#9597) --- doc/lua_api.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index ce9fc61b2..6ba87d619 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -5413,8 +5413,8 @@ Misc. insecure functions if the calling mod has been listed as trusted in the `secure.trusted_mods` setting or security is disabled, otherwise returns `nil`. - * Only works at init time and must be called from the mod's main scope (not - from a function). + * Only works at init time and must be called from the mod's main scope + (ie: the init.lua of the mod, not from another Lua file or within a function). * **DO NOT ALLOW ANY OTHER MODS TO ACCESS THE RETURNED ENVIRONMENT, STORE IT IN A LOCAL VARIABLE!** @@ -6002,7 +6002,7 @@ object you are working with still exists. * `sky_color`: A table containing the following values, alpha is ignored: * `day_sky`: ColorSpec, for the top half of the `"regular"` sky during the day. (default: `#8cbafa`) - * `day_horizon`: ColorSpec, for the bottom half of the + * `day_horizon`: ColorSpec, for the bottom half of the `"regular"` sky during the day. (default: `#9bc1f0`) * `dawn_sky`: ColorSpec, for the top half of the `"regular"` sky during dawn/sunset. (default: `#b4bafa`) @@ -6020,7 +6020,7 @@ object you are working with still exists. sky during the night. (default: `#4090ff`) The resulting sky color will be a dark version of the ColorSpec. Warning: The darkening of the ColorSpec is subject to change. - * `indoors`: ColorSpec, for when you're either indoors or + * `indoors`: ColorSpec, for when you're either indoors or underground. Only applies to the `"regular"` sky. (default: `#646464`) * `fog_sun_tint`: ColorSpec, changes the fog tinting for the sun @@ -6064,7 +6064,7 @@ object you are working with still exists. * `parameters` is a table with the following optional fields: * `visible`: Boolean for whether the stars are visible. (default: `true`) - * `count`: Integer number to set the number of stars in + * `count`: Integer number to set the number of stars in the skybox. Only applies to `"skybox"` and `"regular"` sky types. (default: `1000`) * `star_color`: ColorSpec, sets the colors of the stars, -- cgit v1.2.3 From 5f3a17eb65c1ad9259f03bde346a8d69fe0c1069 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Fri, 10 Apr 2020 22:53:08 +0200 Subject: Implement minetest.sound_fade() --- doc/client_lua_api.txt | 7 +++++++ src/script/lua_api/l_client.cpp | 22 +++++++++++++++++++--- src/script/lua_api/l_client.h | 6 ++++++ src/script/lua_api/l_nodemeta.cpp | 2 ++ 4 files changed, 34 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index 3612f851b..2c8ffd4d4 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -734,6 +734,13 @@ Call these functions only at load time! * `spec` is a `SimpleSoundSpec` * `parameters` is a sound parameter table * `minetest.sound_stop(handle)` + * `handle` is a handle returned by `minetest.sound_play` +* `minetest.sound_fade(handle, step, gain)` + * `handle` is a handle returned by `minetest.sound_play` + * `step` determines how fast a sound will fade. + Negative step will lower the sound volume, positive step will increase + the sound volume. + * `gain` the target gain for the fade. ### Timing * `minetest.after(time, func, ...)` diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index fba182492..e30c05260 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -209,7 +209,7 @@ int ModApiClient::l_gettext(lua_State *L) return 1; } -// get_node(pos) +// get_node_or_nil(pos) // pos = {x=num, y=num, z=num} int ModApiClient::l_get_node_or_nil(lua_State *L) { @@ -228,6 +228,7 @@ int ModApiClient::l_get_node_or_nil(lua_State *L) return 1; } +// get_langauge() int ModApiClient::l_get_language(lua_State *L) { #ifdef _WIN32 @@ -244,6 +245,7 @@ int ModApiClient::l_get_language(lua_State *L) return 2; } +// get_wielded_item() int ModApiClient::l_get_wielded_item(lua_State *L) { Client *client = getClient(L); @@ -266,12 +268,14 @@ int ModApiClient::l_get_meta(lua_State *L) return 1; } +// sound_play(spec, parameters) int ModApiClient::l_sound_play(lua_State *L) { ISoundManager *sound = getClient(L)->getSoundManager(); SimpleSoundSpec spec; read_soundspec(L, 1, spec); + float gain = 1.0f; float pitch = 1.0f; bool looped = false; @@ -293,21 +297,32 @@ int ModApiClient::l_sound_play(lua_State *L) } } - handle = sound->playSound(spec.name, looped, gain * spec.gain, 0.0f, pitch); + handle = sound->playSound(spec.name, looped, gain * spec.gain, spec.fade, pitch); lua_pushinteger(L, handle); return 1; } +// sound_stop(handle) int ModApiClient::l_sound_stop(lua_State *L) { - u32 handle = luaL_checkinteger(L, 1); + s32 handle = luaL_checkinteger(L, 1); getClient(L)->getSoundManager()->stopSound(handle); return 0; } +// sound_fade(handle, step, gain) +int ModApiClient::l_sound_fade(lua_State *L) +{ + s32 handle = luaL_checkinteger(L, 1); + float step = readParam(L, 2); + float gain = readParam(L, 3); + getClient(L)->getSoundManager()->fadeSound(handle, step, gain); + return 0; +} + // get_server_info() int ModApiClient::l_get_server_info(lua_State *L) { @@ -426,6 +441,7 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(get_meta); API_FCT(sound_play); API_FCT(sound_stop); + API_FCT(sound_fade); API_FCT(get_server_info); API_FCT(get_item_def); API_FCT(get_node_def); diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 6d1f70b1d..5dc3efdad 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -69,6 +69,7 @@ private: // get_node(pos) static int l_get_node_or_nil(lua_State *L); + // get_language() static int l_get_language(lua_State *L); // get_wielded_item() @@ -77,10 +78,15 @@ private: // get_meta(pos) static int l_get_meta(lua_State *L); + // sound_play(spec, parameters) static int l_sound_play(lua_State *L); + // sound_stop(handle) static int l_sound_stop(lua_State *L); + // sound_fade(handle, step, gain) + static int l_sound_fade(lua_State *L); + // get_server_info() static int l_get_server_info(lua_State *L); diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp index 229ce73db..57052cb42 100644 --- a/src/script/lua_api/l_nodemeta.cpp +++ b/src/script/lua_api/l_nodemeta.cpp @@ -55,11 +55,13 @@ Metadata* NodeMetaRef::getmeta(bool auto_create) void NodeMetaRef::clearMeta() { + SANITY_CHECK(!m_is_local); m_env->getMap().removeNodeMetadata(m_p); } void NodeMetaRef::reportMetadataChange(const std::string *name) { + SANITY_CHECK(!m_is_local); // NOTE: This same code is in rollback_interface.cpp // Inform other things that the metadata has changed NodeMetadata *meta = dynamic_cast(m_meta); -- cgit v1.2.3 From 1292bdbbcec45613c95aff9f2ea88aa49af25011 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sat, 11 Apr 2020 00:09:11 +0200 Subject: Various features and fixes --- clientmods/preview/init.lua | 40 +++---------------- doc/client_lua_api.txt | 31 ++++++++++++--- src/script/lua_api/l_client.cpp | 26 +++++-------- src/script/lua_api/l_localplayer.cpp | 74 ++++++++++++++++++++++++++++++------ src/script/lua_api/l_localplayer.h | 21 +++++++++- 5 files changed, 123 insertions(+), 69 deletions(-) (limited to 'doc') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 5777adcaf..d2440369a 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -31,6 +31,7 @@ core.after(4, function() end) core.after(1, function() + print("armor: " .. dump(core.localplayer:get_armor_groups())) id = core.localplayer:hud_add({ hud_elem_type = "text", name = "example", @@ -125,19 +126,6 @@ core.register_chatcommand("dump", { end, }) -core.register_chatcommand("colorize_test", { - func = function(param) - return true, core.colorize("red", param) - end, -}) - -core.register_chatcommand("test_node", { - func = function(param) - core.display_chat_message(dump(core.get_node({x=0, y=0, z=0}))) - core.display_chat_message(dump(core.get_node_or_nil({x=0, y=0, z=0}))) - end, -}) - local function preview_minimap() local minimap = core.ui.minimap if not minimap then @@ -157,7 +145,7 @@ end core.after(2, function() print("[PREVIEW] loaded " .. modname .. " mod") modstorage:set_string("current_mod", modname) - print(modstorage:get_string("current_mod")) + assert(modstorage:get_string("current_mod") == modname) preview_minimap() end) @@ -184,30 +172,12 @@ end) core.register_on_punchnode(function(pos, node) print("The local player punched a node!") - local itemstack = core.get_wielded_item() - --[[ - -- getters - print(dump(itemstack:is_empty())) - print(dump(itemstack:get_name())) - print(dump(itemstack:get_count())) - print(dump(itemstack:get_wear())) - print(dump(itemstack:get_meta())) - print(dump(itemstack:get_metadata() - print(dump(itemstack:is_known())) - --print(dump(itemstack:get_definition())) - print(dump(itemstack:get_tool_capabilities())) - print(dump(itemstack:to_string())) - print(dump(itemstack:to_table())) - -- setters - print(dump(itemstack:set_name("default:dirt"))) - print(dump(itemstack:set_count("95"))) - print(dump(itemstack:set_wear(934))) - print(dump(itemstack:get_meta())) - print(dump(itemstack:get_metadata())) - --]] + 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) diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index 2c8ffd4d4..71df91c68 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -804,8 +804,6 @@ Call these functions only at load time! * get max available level for leveled node ### Player -* `minetest.get_wielded_item()` - * Returns the itemstack the local player is holding * `minetest.send_chat_message(message)` * Act as if `message` was typed by the player into the terminal. * `minetest.run_server_chatcommand(cmd, param)` @@ -1006,6 +1004,10 @@ Methods: * returns player HP * `get_name()` * returns player name +* `get_wield_index()` + * returns the index of the wielded item +* `get_wielded_item()` + * returns the itemstack the player is holding * `is_attached()` * returns true if player is attached * `is_touching_ground()` @@ -1029,7 +1031,8 @@ Methods: jump = float, gravity = float, sneak = boolean, - sneak_glitch = boolean + sneak_glitch = boolean, + new_move = boolean, } ``` @@ -1081,8 +1084,26 @@ Methods: * returns last look horizontal angle * `get_last_look_vertical()`: * returns last look vertical angle -* `get_key_pressed()`: - * returns last key typed by the player +* `get_control()`: + * returns pressed player controls + +```lua + { + up = boolean, + down = boolean, + left = boolean, + right = boolean, + jump = boolean, + aux1 = boolean, + sneak = boolean, + zoom = boolean, + LMB = boolean, + RMB = boolean, + } +``` + +* `get_armor_groups()` + * returns a table with the armor group ratings * `hud_add(definition)` * add a HUD element described by HUD def, returns ID number on success and `nil` on failure. * See [`HUD definition`](#hud-definition-hud_add-hud_get) diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index e30c05260..aaced7cd0 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -29,7 +29,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cpp_api/s_base.h" #include "gettext.h" #include "l_internal.h" -#include "lua_api/l_item.h" #include "lua_api/l_nodemeta.h" #include "gui/mainmenumanager.h" #include "map.h" @@ -245,25 +244,18 @@ int ModApiClient::l_get_language(lua_State *L) return 2; } -// get_wielded_item() -int ModApiClient::l_get_wielded_item(lua_State *L) -{ - Client *client = getClient(L); - LocalPlayer *player = client->getEnv().getLocalPlayer(); - if (!player) - return 0; - - ItemStack selected_item; - player->getWieldedItem(&selected_item, nullptr); - LuaItemStack::create(L, selected_item); - return 1; -} - // get_meta(pos) int ModApiClient::l_get_meta(lua_State *L) { v3s16 p = read_v3s16(L, 1); - NodeMetadata *meta = getClient(L)->getEnv().getMap().getNodeMetadata(p); + + // check restrictions first + bool pos_ok; + getClient(L)->CSMGetNode(p, &pos_ok); + if (!pos_ok) + return 0; + + NodeMetadata *meta = getEnv(L)->getMap().getNodeMetadata(p); NodeMetaRef::createClient(L, meta); return 1; } @@ -390,6 +382,7 @@ int ModApiClient::l_get_node_def(lua_State *L) return 1; } +// get_privilege_list() int ModApiClient::l_get_privilege_list(lua_State *L) { const Client *client = getClient(L); @@ -436,7 +429,6 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(send_respawn); API_FCT(gettext); API_FCT(get_node_or_nil); - API_FCT(get_wielded_item); API_FCT(disconnect); API_FCT(get_meta); API_FCT(sound_play); diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp index 821b1cb66..851ede535 100644 --- a/src/script/lua_api/l_localplayer.cpp +++ b/src/script/lua_api/l_localplayer.cpp @@ -19,10 +19,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "l_localplayer.h" #include "l_internal.h" +#include "lua_api/l_item.h" #include "script/common/c_converter.h" #include "client/localplayer.h" #include "hud.h" #include "common/c_content.h" +#include "client/content_cao.h" LuaLocalPlayer::LuaLocalPlayer(LocalPlayer *m) : m_localplayer(m) { @@ -74,6 +76,26 @@ int LuaLocalPlayer::l_get_name(lua_State *L) return 1; } +// get_wield_index(self) +int LuaLocalPlayer::l_get_wield_index(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + + lua_pushinteger(L, player->getWieldIndex()); + return 1; +} + +// get_wielded_item(self) +int LuaLocalPlayer::l_get_wielded_item(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + + ItemStack selected_item; + player->getWieldedItem(&selected_item, nullptr); + LuaItemStack::create(L, selected_item); + return 1; +} + int LuaLocalPlayer::l_is_attached(lua_State *L) { LocalPlayer *player = getobject(L, 1); @@ -130,6 +152,7 @@ int LuaLocalPlayer::l_swimming_vertical(lua_State *L) return 1; } +// get_physics_override(self) int LuaLocalPlayer::l_get_physics_override(lua_State *L) { LocalPlayer *player = getobject(L, 1); @@ -150,14 +173,9 @@ int LuaLocalPlayer::l_get_physics_override(lua_State *L) lua_pushboolean(L, player->physics_override_sneak_glitch); lua_setfield(L, -2, "sneak_glitch"); - return 1; -} - -int LuaLocalPlayer::l_get_override_pos(lua_State *L) -{ - LocalPlayer *player = getobject(L, 1); + lua_pushboolean(L, player->physics_override_new_move); + lua_setfield(L, -2, "new_move"); - push_v3f(L, player->getPosition()); return 1; } @@ -193,14 +211,33 @@ int LuaLocalPlayer::l_get_last_look_horizontal(lua_State *L) return 1; } -int LuaLocalPlayer::l_get_key_pressed(lua_State *L) +// get_control(self) +int LuaLocalPlayer::l_get_control(lua_State *L) { LocalPlayer *player = getobject(L, 1); + const PlayerControl &c = player->getPlayerControl(); + + auto set = [L] (const char *name, bool value) { + lua_pushboolean(L, value); + lua_setfield(L, -2, name); + }; + + lua_createtable(L, 0, 12); + set("up", c.up); + set("down", c.down); + set("left", c.left); + set("right", c.right); + set("jump", c.jump); + set("aux1", c.aux1); + set("sneak", c.sneak); + set("zoom", c.zoom); + set("LMB", c.LMB); + set("RMB", c.RMB); - lua_pushinteger(L, player->last_keyPressed); return 1; } +// get_breath(self) int LuaLocalPlayer::l_get_breath(lua_State *L) { LocalPlayer *player = getobject(L, 1); @@ -209,6 +246,7 @@ int LuaLocalPlayer::l_get_breath(lua_State *L) return 1; } +// get_pos(self) int LuaLocalPlayer::l_get_pos(lua_State *L) { LocalPlayer *player = getobject(L, 1); @@ -217,6 +255,7 @@ int LuaLocalPlayer::l_get_pos(lua_State *L) return 1; } +// get_movement_acceleration(self) int LuaLocalPlayer::l_get_movement_acceleration(lua_State *L) { LocalPlayer *player = getobject(L, 1); @@ -234,6 +273,7 @@ int LuaLocalPlayer::l_get_movement_acceleration(lua_State *L) return 1; } +// get_movement_speed(self) int LuaLocalPlayer::l_get_movement_speed(lua_State *L) { LocalPlayer *player = getobject(L, 1); @@ -257,6 +297,7 @@ int LuaLocalPlayer::l_get_movement_speed(lua_State *L) return 1; } +// get_movement(self) int LuaLocalPlayer::l_get_movement(lua_State *L) { LocalPlayer *player = getobject(L, 1); @@ -278,6 +319,13 @@ int LuaLocalPlayer::l_get_movement(lua_State *L) return 1; } +// get_armor_groups(self) +int LuaLocalPlayer::l_get_armor_groups(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + push_groups(L, player->getCAO()->getGroups()); + return 1; +} // hud_add(self, form) int LuaLocalPlayer::l_hud_add(lua_State *L) @@ -407,6 +455,8 @@ const luaL_Reg LuaLocalPlayer::methods[] = { luamethod(LuaLocalPlayer, get_velocity), luamethod(LuaLocalPlayer, get_hp), luamethod(LuaLocalPlayer, get_name), + luamethod(LuaLocalPlayer, get_wield_index), + luamethod(LuaLocalPlayer, get_wielded_item), luamethod(LuaLocalPlayer, is_attached), luamethod(LuaLocalPlayer, is_touching_ground), luamethod(LuaLocalPlayer, is_in_liquid), @@ -415,17 +465,19 @@ const luaL_Reg LuaLocalPlayer::methods[] = { luamethod(LuaLocalPlayer, is_climbing), luamethod(LuaLocalPlayer, swimming_vertical), luamethod(LuaLocalPlayer, get_physics_override), - luamethod(LuaLocalPlayer, get_override_pos), + // TODO: figure our if these are useful in any way luamethod(LuaLocalPlayer, get_last_pos), luamethod(LuaLocalPlayer, get_last_velocity), luamethod(LuaLocalPlayer, get_last_look_horizontal), luamethod(LuaLocalPlayer, get_last_look_vertical), - luamethod(LuaLocalPlayer, get_key_pressed), + // + luamethod(LuaLocalPlayer, get_control), luamethod(LuaLocalPlayer, get_breath), luamethod(LuaLocalPlayer, get_pos), luamethod(LuaLocalPlayer, get_movement_acceleration), luamethod(LuaLocalPlayer, get_movement_speed), luamethod(LuaLocalPlayer, get_movement), + luamethod(LuaLocalPlayer, get_armor_groups), luamethod(LuaLocalPlayer, hud_add), luamethod(LuaLocalPlayer, hud_remove), luamethod(LuaLocalPlayer, hud_change), diff --git a/src/script/lua_api/l_localplayer.h b/src/script/lua_api/l_localplayer.h index 01de2ed4e..4413f2bdb 100644 --- a/src/script/lua_api/l_localplayer.h +++ b/src/script/lua_api/l_localplayer.h @@ -32,12 +32,21 @@ private: // garbage collector static int gc_object(lua_State *L); + // get_velocity(self) static int l_get_velocity(lua_State *L); + // get_hp(self) static int l_get_hp(lua_State *L); + // get_name(self) static int l_get_name(lua_State *L); + // get_wield_index(self) + static int l_get_wield_index(lua_State *L); + + // get_wielded_item(self) + static int l_get_wielded_item(lua_State *L); + static int l_is_attached(lua_State *L); static int l_is_touching_ground(lua_State *L); static int l_is_in_liquid(lua_State *L); @@ -54,18 +63,28 @@ private: static int l_get_last_velocity(lua_State *L); static int l_get_last_look_vertical(lua_State *L); static int l_get_last_look_horizontal(lua_State *L); - static int l_get_key_pressed(lua_State *L); + // get_control(self) + static int l_get_control(lua_State *L); + + // get_breath(self) static int l_get_breath(lua_State *L); + // get_pos(self) static int l_get_pos(lua_State *L); + // get_movement_acceleration(self) static int l_get_movement_acceleration(lua_State *L); + // get_movement_speed(self) static int l_get_movement_speed(lua_State *L); + // get_movement(self) static int l_get_movement(lua_State *L); + // get_armor_groups(self) + static int l_get_armor_groups(lua_State *L); + // hud_add(self, id, form) static int l_hud_add(lua_State *L); -- cgit v1.2.3 From 840b17ce63615424e566b056077b9dfa50d67293 Mon Sep 17 00:00:00 2001 From: Paul Ouellette Date: Sat, 11 Apr 2020 14:38:39 -0400 Subject: Update API site build (#9622) --- .gitlab-ci.yml | 3 +-- doc/mkdocs/lua_highlight.patch | 12 +----------- 2 files changed, 2 insertions(+), 13 deletions(-) (limited to 'doc') diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9781f9f85..a3d634261 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -300,9 +300,8 @@ package:docker: pages: stage: deploy - image: python:3.7 + image: python:3.8 before_script: - - pip install pip==18.1 - pip install git+https://github.com/Python-Markdown/markdown.git - pip install git+https://github.com/mkdocs/mkdocs.git - pip install pygments diff --git a/doc/mkdocs/lua_highlight.patch b/doc/mkdocs/lua_highlight.patch index 034a63a33..e231081d6 100644 --- a/doc/mkdocs/lua_highlight.patch +++ b/doc/mkdocs/lua_highlight.patch @@ -1,4 +1,4 @@ -@@ -77,7 +77,7 @@ +@@ -75,7 +75,7 @@ css_class="codehilite", lang=None, style='default', noclasses=False, tab_length=4, hl_lines=None, use_pygments=True): self.src = src @@ -7,13 +7,3 @@ self.linenums = linenums self.guess_lang = guess_lang self.css_class = css_class -@@ -119,7 +119,8 @@ - cssclass=self.css_class, - style=self.style, - noclasses=self.noclasses, -- hl_lines=self.hl_lines) -+ hl_lines=self.hl_lines, -+ wrapcode=True) - return highlight(self.src, lexer, formatter) - else: - # just escape and build markup usable by JS highlighting libs -- cgit v1.2.3 From f780bae05cc2fdd23a6d7326c770783da8d94ea3 Mon Sep 17 00:00:00 2001 From: Hugues Ross Date: Sat, 11 Apr 2020 16:39:30 -0400 Subject: Formspecs: Add state-selection to style elements (#9378) --- doc/lua_api.txt | 61 +++++++++--- games/minimal/mods/test/formspec.lua | 5 +- src/client/game.cpp | 9 +- src/gui/StyleSpec.h | 65 ++++++++++-- src/gui/guiButton.cpp | 163 +++++++++++++++--------------- src/gui/guiButton.h | 34 ++++--- src/gui/guiButtonImage.cpp | 102 ++++--------------- src/gui/guiButtonImage.h | 26 ++--- src/gui/guiButtonItemImage.cpp | 15 +-- src/gui/guiButtonItemImage.h | 9 +- src/gui/guiConfirmRegistration.cpp | 8 +- src/gui/guiConfirmRegistration.h | 4 +- src/gui/guiFormSpecMenu.cpp | 187 ++++++++++++++++++++++++----------- src/gui/guiFormSpecMenu.h | 8 +- src/gui/guiKeyChangeMenu.cpp | 12 ++- src/gui/guiKeyChangeMenu.h | 5 +- src/gui/guiPasswordChange.cpp | 10 +- src/gui/guiPasswordChange.h | 5 +- src/gui/guiVolumeChange.cpp | 7 +- src/gui/guiVolumeChange.h | 7 +- src/script/lua_api/l_mainmenu.cpp | 19 ++-- src/util/numeric.h | 10 ++ 22 files changed, 454 insertions(+), 317 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 6ba87d619..b083b2907 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2188,12 +2188,12 @@ Elements * 9-sliced background. See https://en.wikipedia.org/wiki/9-slice_scaling * Middle is a rect which defines the middle of the 9-slice. - * `x` - The middle will be x pixels from all sides. - * `x,y` - The middle will be x pixels from the horizontal and y from the vertical. - * `x,y,x2,y2` - The middle will start at x,y, and end at x2, y2. Negative x2 and y2 values - will be added to the width and height of the texture, allowing it to be used as the - distance from the far end. - * All numbers in middle are integers. + * `x` - The middle will be x pixels from all sides. + * `x,y` - The middle will be x pixels from the horizontal and y from the vertical. + * `x,y,x2,y2` - The middle will start at x,y, and end at x2, y2. Negative x2 and y2 values + will be added to the width and height of the texture, allowing it to be used as the + distance from the far end. + * All numbers in middle are integers. * Example for formspec 8x4 in 16x resolution: image shall be sized 8 times 16px times 4 times 16px * If `auto_clip` is `true`, the background is clipped to the formspec size @@ -2508,16 +2508,28 @@ Elements * `span=`: number of following columns to affect (default: infinite). -### `style[,,...;;;...]` +### `style[,;;;...]` -* Set the style for the named element(s) `name`. +* Set the style for the element(s) matching `selector` by name. +* `selector` can be one of: + * `` - An element name. + * `:` - An element name, a colon, and one or more states. +* `state` is a list of states separated by the `+` character. + * If a state is provided, the style will only take effect when the element is in that state. + * All provided states must be active for the style to apply. * Note: this **must** be before the element is defined. * See [Styling Formspecs]. -### `style_type[,,...;;;...]` +### `style_type[,;;;...]` -* Sets the style for all elements of type(s) `type` which appear after this element. +* Set the style for the element(s) matching `selector` by type. +* `selector` can be one of: + * `` - An element type. + * `:` - An element type, a colon, and one or more states. +* `state` is a list of states separated by the `+` character. + * If a state is provided, the style will only take effect when the element is in that state. + * All provided states must be active for the style to apply. * See [Styling Formspecs]. Migrating to Real Coordinates @@ -2560,23 +2572,32 @@ Styling Formspecs Formspec elements can be themed using the style elements: - style[,,...;;;...] - style_type[,,...;;;...] + style[,;;;...] + style[:,:;;;...] + style_type[,;;;...] + style_type[:,:;;;...] Where a prop is: property_name=property_value +For example: + + style_type[button;bgcolor=#006699] + style[world_delete;bgcolor=red;textcolor=yellow] + button[4,3.95;2.6,1;world_delete;Delete] + A name/type can optionally be a comma separated list of names/types, like so: world_delete,world_create,world_configure button,image_button -For example: +Any name/type in the list can also be accompanied by a `+`-separated list of states, like so: - style_type[button;bgcolor=#006699] - style[world_delete;bgcolor=red;textcolor=yellow] - button[4,3.95;2.6,1;world_delete;Delete] + world_delete:hovered+pressed + button:pressed + +States allow you to apply styles in response to changes in the element, instead of applying at all times. Setting a property to nothing will reset it to the default value. For example: @@ -2654,6 +2675,14 @@ Some types may inherit styles from parent types. * noclip - boolean, set to true to allow the element to exceed formspec bounds. * textcolor - color. Default white. +### Valid States + +* *all elements* + * default - Equivalent to providing no states +* button, button_exit, image_button, item_image_button + * hovered - Active when the mouse is hovering over the element + * pressed - Active when the button is pressed + Markup Language --------------- diff --git a/games/minimal/mods/test/formspec.lua b/games/minimal/mods/test/formspec.lua index d2123b4af..14886aad2 100644 --- a/games/minimal/mods/test/formspec.lua +++ b/games/minimal/mods/test/formspec.lua @@ -65,7 +65,10 @@ local style_fs = [[ style[one_btn13;border=false] item_image_button[1.25,8.35;1,1;default:sword_steel;one_btn13;NoBor] - style[one_btn14;border=false;bgimg=test_bg.png;bgimg_hovered=test_bg_hovered.png;bgimg_pressed=test_bg_pressed.png;fgimg=bubble.png;fgimg_hovered=default_apple.png;fgimg_pressed=heart.png] + style[one_btn14;border=false;bgimg=test_bg.png;fgimg=bubble.png] + style[one_btn14:hovered;bgimg=test_bg_hovered.png;fgimg=default_apple.png;textcolor=red] + style[one_btn14:pressed;bgimg=test_bg_pressed.png;fgimg=heart.png;textcolor=green] + style[one_btn14:hovered+pressed;textcolor=blue] image_button[0,9.6;1,1;bubble.png;one_btn14;Bg] style[one_btn15;border=false;bgimg=test_bg.png;bgimg_hovered=test_bg_hovered.png;bgimg_pressed=test_bg_pressed.png] diff --git a/src/client/game.cpp b/src/client/game.cpp index 505108caf..06e76d170 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1556,7 +1556,8 @@ bool Game::connectToServer(const std::string &playername, } else { registration_confirmation_shown = true; (new GUIConfirmRegistration(guienv, guienv->getRootGUIElement(), -1, - &g_menumgr, client, playername, password, connection_aborted))->drop(); + &g_menumgr, client, playername, password, + connection_aborted, texture_src))->drop(); } } else { wait_time += dtime; @@ -1711,19 +1712,19 @@ inline bool Game::handleCallbacks() if (g_gamecallback->changepassword_requested) { (new GUIPasswordChange(guienv, guiroot, -1, - &g_menumgr, client))->drop(); + &g_menumgr, client, texture_src))->drop(); g_gamecallback->changepassword_requested = false; } if (g_gamecallback->changevolume_requested) { (new GUIVolumeChange(guienv, guiroot, -1, - &g_menumgr))->drop(); + &g_menumgr, texture_src))->drop(); g_gamecallback->changevolume_requested = false; } if (g_gamecallback->keyconfig_requested) { (new GUIKeyChangeMenu(guienv, guiroot, -1, - &g_menumgr))->drop(); + &g_menumgr, texture_src))->drop(); g_gamecallback->keyconfig_requested = false; } diff --git a/src/gui/StyleSpec.h b/src/gui/StyleSpec.h index 999c1d237..799fbf46d 100644 --- a/src/gui/StyleSpec.h +++ b/src/gui/StyleSpec.h @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "client/tile.h" // ITextureSource +#include "debug.h" #include "irrlichttypes_extrabloated.h" #include "util/string.h" #include @@ -31,25 +32,34 @@ public: { TEXTCOLOR, BGCOLOR, - BGCOLOR_HOVERED, - BGCOLOR_PRESSED, + BGCOLOR_HOVERED, // Note: Deprecated property + BGCOLOR_PRESSED, // Note: Deprecated property NOCLIP, BORDER, BGIMG, - BGIMG_HOVERED, + BGIMG_HOVERED, // Note: Deprecated property BGIMG_MIDDLE, - BGIMG_PRESSED, + BGIMG_PRESSED, // Note: Deprecated property FGIMG, - FGIMG_HOVERED, - FGIMG_PRESSED, + FGIMG_HOVERED, // Note: Deprecated property + FGIMG_PRESSED, // Note: Deprecated property ALPHA, NUM_PROPERTIES, NONE }; + enum State + { + STATE_DEFAULT = 0, + STATE_HOVERED = 1 << 0, + STATE_PRESSED = 1 << 1, + NUM_STATES = 1 << 2, + STATE_INVALID = 1 << 3, + }; private: std::array property_set{}; std::array properties; + State state_map = STATE_DEFAULT; public: static Property GetPropertyByName(const std::string &name) @@ -99,6 +109,49 @@ public: property_set[prop] = true; } + //! Parses a name and returns the corresponding state enum + static State getStateByName(const std::string &name) + { + if (name == "default") { + return STATE_DEFAULT; + } else if (name == "hovered") { + return STATE_HOVERED; + } else if (name == "pressed") { + return STATE_PRESSED; + } else { + return STATE_INVALID; + } + } + + //! Gets the state that this style is intended for + State getState() const + { + return state_map; + } + + //! Set the given state on this style + void addState(State state) + { + FATAL_ERROR_IF(state >= NUM_STATES, "Out-of-bounds state received"); + + state_map = static_cast(state_map | state); + } + + //! Using a list of styles mapped to state values, calculate the final + // combined style for a state by propagating values in its component states + static StyleSpec getStyleFromStatePropagation(const std::array &styles, State state) + { + StyleSpec temp = styles[StyleSpec::STATE_DEFAULT]; + temp.state_map = state; + for (int i = StyleSpec::STATE_DEFAULT + 1; i <= state; i++) { + if ((state & i) != 0) { + temp = temp | styles[i]; + } + } + + return temp; + } + video::SColor getColor(Property prop, video::SColor def) const { const auto &val = properties[prop]; diff --git a/src/gui/guiButton.cpp b/src/gui/guiButton.cpp index 4c16ee237..9dfe36bc4 100644 --- a/src/gui/guiButton.cpp +++ b/src/gui/guiButton.cpp @@ -14,6 +14,7 @@ #include "irrlicht_changes/static_text.h" #include "porting.h" #include "StyleSpec.h" +#include "util/numeric.h" using namespace irr; using namespace gui; @@ -26,14 +27,15 @@ using namespace gui; //! constructor GUIButton::GUIButton(IGUIEnvironment* environment, IGUIElement* parent, - s32 id, core::rect rectangle, bool noclip) + s32 id, core::rect rectangle, ISimpleTextureSource *tsrc, + bool noclip) : IGUIButton(environment, parent, id, rectangle), SpriteBank(0), OverrideFont(0), OverrideColorEnabled(false), OverrideColor(video::SColor(101,255,255,255)), ClickTime(0), HoverTime(0), FocusTime(0), ClickShiftState(false), ClickControlState(false), IsPushButton(false), Pressed(false), - UseAlphaChannel(false), DrawBorder(true), ScaleImage(false) + UseAlphaChannel(false), DrawBorder(true), ScaleImage(false), TSrc(tsrc) { setNotClipped(noclip); @@ -44,14 +46,6 @@ GUIButton::GUIButton(IGUIEnvironment* environment, IGUIElement* parent, // PATCH for (size_t i = 0; i < 4; i++) { Colors[i] = Environment->getSkin()->getColor((EGUI_DEFAULT_COLOR)i); - HoveredColors[i] = irr::video::SColor(Colors[i].getAlpha(), - core::clamp(Colors[i].getRed() * COLOR_HOVERED_MOD, 0, 255), - core::clamp(Colors[i].getGreen() * COLOR_HOVERED_MOD, 0, 255), - core::clamp(Colors[i].getBlue() * COLOR_HOVERED_MOD, 0, 255)); - PressedColors[i] = irr::video::SColor(Colors[i].getAlpha(), - core::clamp(Colors[i].getRed() * COLOR_PRESSED_MOD, 0, 255), - core::clamp(Colors[i].getGreen() * COLOR_PRESSED_MOD, 0, 255), - core::clamp(Colors[i].getBlue() * COLOR_PRESSED_MOD, 0, 255)); } StaticText = gui::StaticText::add(Environment, Text.c_str(), core::rect(0,0,rectangle.getWidth(),rectangle.getHeight()), false, false, this, id); StaticText->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER); @@ -262,6 +256,13 @@ void GUIButton::draw() return; // PATCH + // Track hovered state, if it has changed then we need to update the style. + bool hovered = isHovered(); + if (hovered != WasHovered) { + WasHovered = hovered; + setFromState(); + } + GUISkin* skin = dynamic_cast(Environment->getSkin()); video::IVideoDriver* driver = Environment->getVideoDriver(); // END PATCH @@ -271,21 +272,24 @@ void GUIButton::draw() if (!Pressed) { // PATCH - skin->drawColored3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect, - isHovered() ? HoveredColors : Colors); + skin->drawColored3DButtonPaneStandard(this, AbsoluteRect, + &AbsoluteClippingRect, Colors); // END PATCH } else { // PATCH - skin->drawColored3DButtonPanePressed(this, - AbsoluteRect, &AbsoluteClippingRect, PressedColors); + skin->drawColored3DButtonPanePressed(this, AbsoluteRect, + &AbsoluteClippingRect, Colors); // END PATCH } } const core::position2di buttonCenter(AbsoluteRect.getCenter()); - EGUI_BUTTON_IMAGE_STATE imageState = getImageState(Pressed); + // PATCH + // The image changes based on the state, so we use the default every time. + EGUI_BUTTON_IMAGE_STATE imageState = EGBIS_IMAGE_UP; + // END PATCH if ( ButtonImages[(u32)imageState].Texture ) { core::position2d pos(buttonCenter); @@ -548,18 +552,6 @@ void GUIButton::setPressedImage(video::ITexture* image, const core::rect& p setImage(gui::EGBIS_IMAGE_DOWN, image, pos); } -void GUIButton::setHoveredImage(video::ITexture* image) -{ - setImage(gui::EGBIS_IMAGE_UP_MOUSEOVER, image); - setImage(gui::EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, image); -} - -void GUIButton::setHoveredImage(video::ITexture* image, const core::rect& pos) -{ - setImage(gui::EGBIS_IMAGE_UP_MOUSEOVER, image, pos); - setImage(gui::EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, image, pos); -} - //! Sets the text displayed by the button void GUIButton::setText(const wchar_t* text) { @@ -618,6 +610,8 @@ void GUIButton::setPressed(bool pressed) skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y))); } } + + setFromState(); } } @@ -729,10 +723,12 @@ void GUIButton::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWri } // PATCH -GUIButton* GUIButton::addButton(IGUIEnvironment *environment, const core::rect& rectangle, - IGUIElement* parent, s32 id, const wchar_t* text, const wchar_t *tooltiptext) +GUIButton* GUIButton::addButton(IGUIEnvironment *environment, + const core::rect& rectangle, ISimpleTextureSource *tsrc, + IGUIElement* parent, s32 id, const wchar_t* text, + const wchar_t *tooltiptext) { - GUIButton* button = new GUIButton(environment, parent ? parent : environment->getRootGUIElement(), id, rectangle); + GUIButton* button = new GUIButton(environment, parent ? parent : environment->getRootGUIElement(), id, rectangle, tsrc); if (text) button->setText(text); @@ -749,76 +745,87 @@ void GUIButton::setColor(video::SColor color) for (size_t i = 0; i < 4; i++) { video::SColor base = Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i); Colors[i] = base.getInterpolated(color, d); - HoveredColors[i] = irr::video::SColor(Colors[i].getAlpha(), - core::clamp(Colors[i].getRed() * COLOR_HOVERED_MOD, 0, 255), - core::clamp(Colors[i].getGreen() * COLOR_HOVERED_MOD, 0, 255), - core::clamp(Colors[i].getBlue() * COLOR_HOVERED_MOD, 0, 255)); - PressedColors[i] = irr::video::SColor(Colors[i].getAlpha(), - core::clamp(Colors[i].getRed() * COLOR_PRESSED_MOD, 0, 255), - core::clamp(Colors[i].getGreen() * COLOR_PRESSED_MOD, 0, 255), - core::clamp(Colors[i].getBlue() * COLOR_PRESSED_MOD, 0, 255)); } } -void GUIButton::setHoveredColor(video::SColor color) -{ - float d = 0.65f; - for (size_t i = 0; i < 4; i++) { - video::SColor base = Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i); - HoveredColors[i] = base.getInterpolated(color, d); - } -} -void GUIButton::setPressedColor(video::SColor color) + +//! Set element properties from a StyleSpec corresponding to the button state +void GUIButton::setFromState() { - float d = 0.65f; - for (size_t i = 0; i < 4; i++) { - video::SColor base = Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i); - PressedColors[i] = base.getInterpolated(color, d); - } + StyleSpec::State state = StyleSpec::STATE_DEFAULT; + + if (isPressed()) + state = static_cast(state | StyleSpec::STATE_PRESSED); + + if (isHovered()) + state = static_cast(state | StyleSpec::STATE_HOVERED); + + setFromStyle(StyleSpec::getStyleFromStatePropagation(Styles, state)); } //! Set element properties from a StyleSpec -void GUIButton::setFromStyle(const StyleSpec& style, ISimpleTextureSource *tsrc) +void GUIButton::setFromStyle(const StyleSpec& style) { + bool hovered = (style.getState() & StyleSpec::STATE_HOVERED) != 0; + bool pressed = (style.getState() & StyleSpec::STATE_PRESSED) != 0; + if (style.isNotDefault(StyleSpec::BGCOLOR)) { + setColor(style.getColor(StyleSpec::BGCOLOR)); - } - if (style.isNotDefault(StyleSpec::BGCOLOR_HOVERED)) { - setHoveredColor(style.getColor(StyleSpec::BGCOLOR_HOVERED)); - } - if (style.isNotDefault(StyleSpec::BGCOLOR_PRESSED)) { - setPressedColor(style.getColor(StyleSpec::BGCOLOR_PRESSED)); + + // If we have a propagated hover/press color, we need to automatically + // lighten/darken it + if (!Styles[style.getState()].isNotDefault(StyleSpec::BGCOLOR)) { + for (size_t i = 0; i < 4; i++) { + if (pressed) { + Colors[i] = multiplyColorValue(Colors[i], COLOR_PRESSED_MOD); + } else if (hovered) { + Colors[i] = multiplyColorValue(Colors[i], COLOR_HOVERED_MOD); + } + } + } + + } else { + for (size_t i = 0; i < 4; i++) { + video::SColor base = + Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i); + if (pressed) { + Colors[i] = multiplyColorValue(base, COLOR_PRESSED_MOD); + } else if (hovered) { + Colors[i] = multiplyColorValue(base, COLOR_HOVERED_MOD); + } else { + Colors[i] = base; + } + } } if (style.isNotDefault(StyleSpec::TEXTCOLOR)) { setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR)); + } else { + setOverrideColor(video::SColor(255,255,255,255)); + OverrideColorEnabled = false; } - setNotClipped(style.getBool(StyleSpec::NOCLIP, isNotClipped())); - setDrawBorder(style.getBool(StyleSpec::BORDER, DrawBorder)); + setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + setDrawBorder(style.getBool(StyleSpec::BORDER, true)); setUseAlphaChannel(style.getBool(StyleSpec::ALPHA, true)); const core::position2di buttonCenter(AbsoluteRect.getCenter()); core::position2d geom(buttonCenter); if (style.isNotDefault(StyleSpec::BGIMG)) { - video::ITexture *texture = style.getTexture(StyleSpec::BGIMG, tsrc); - + video::ITexture *texture = style.getTexture(StyleSpec::BGIMG, + getTextureSource()); setImage(guiScalingImageButton( - Environment->getVideoDriver(), texture, geom.X, geom.Y)); - setScaleImage(true); - } - if (style.isNotDefault(StyleSpec::BGIMG_HOVERED)) { - video::ITexture *hovered_texture = style.getTexture(StyleSpec::BGIMG_HOVERED, tsrc); - - setHoveredImage(guiScalingImageButton( - Environment->getVideoDriver(), hovered_texture, geom.X, geom.Y)); - setScaleImage(true); - } - if (style.isNotDefault(StyleSpec::BGIMG_PRESSED)) { - video::ITexture *pressed_texture = style.getTexture(StyleSpec::BGIMG_PRESSED, tsrc); - - setPressedImage(guiScalingImageButton( - Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y)); + Environment->getVideoDriver(), texture, geom.X, geom.Y)); setScaleImage(true); + } else { + setImage(nullptr); } BgMiddle = style.getRect(StyleSpec::BGIMG_MIDDLE, BgMiddle); } + +//! Set the styles used for each state +void GUIButton::setStyles(const std::array& styles) +{ + Styles = styles; + setFromState(); +} // END PATCH diff --git a/src/gui/guiButton.h b/src/gui/guiButton.h index 3d1f98c32..ef10f926e 100644 --- a/src/gui/guiButton.h +++ b/src/gui/guiButton.h @@ -13,6 +13,7 @@ #include "ITexture.h" #include "SColor.h" #include "guiSkin.h" +#include "StyleSpec.h" using namespace irr; @@ -67,7 +68,6 @@ using namespace irr; #endif class ISimpleTextureSource; -class StyleSpec; class GUIButton : public gui::IGUIButton { @@ -75,7 +75,8 @@ public: //! constructor GUIButton(gui::IGUIEnvironment* environment, gui::IGUIElement* parent, - s32 id, core::rect rectangle, bool noclip=false); + s32 id, core::rect rectangle, ISimpleTextureSource *tsrc, + bool noclip=false); //! destructor virtual ~GUIButton(); @@ -125,16 +126,10 @@ public: //! Sets an image which should be displayed on the button when it is in pressed state. virtual void setPressedImage(video::ITexture* image, const core::rect& pos) override; - //! Sets an image which should be displayed on the button when it is in hovered state. - virtual void setHoveredImage(video::ITexture* image=nullptr); - //! Sets the text displayed by the button virtual void setText(const wchar_t* text) override; // END PATCH - //! Sets an image which should be displayed on the button when it is in hovered state. - virtual void setHoveredImage(video::ITexture* image, const core::rect& pos); - //! Sets the sprite bank used by the button virtual void setSpriteBank(gui::IGUISpriteBank* bank=0) override; @@ -225,22 +220,29 @@ public: void setColor(video::SColor color); // PATCH - void setHoveredColor(video::SColor color); - void setPressedColor(video::SColor color); + //! Set element properties from a StyleSpec corresponding to the button state + void setFromState(); //! Set element properties from a StyleSpec - virtual void setFromStyle(const StyleSpec& style, ISimpleTextureSource *tsrc); + virtual void setFromStyle(const StyleSpec& style); + + //! Set the styles used for each state + void setStyles(const std::array& styles); // END PATCH //! Do not drop returned handle - static GUIButton* addButton(gui::IGUIEnvironment *environment, const core::rect& rectangle, - IGUIElement* parent, s32 id, const wchar_t* text, const wchar_t *tooltiptext=L""); + static GUIButton* addButton(gui::IGUIEnvironment *environment, + const core::rect& rectangle, ISimpleTextureSource *tsrc, + IGUIElement* parent, s32 id, const wchar_t* text, + const wchar_t *tooltiptext=L""); protected: void drawSprite(gui::EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center); gui::EGUI_BUTTON_IMAGE_STATE getImageState(bool pressed) const; + ISimpleTextureSource *getTextureSource() { return TSrc; } + struct ButtonImage { ButtonImage() : Texture(0), SourceRect(core::rect(0,0,0,0)) @@ -308,6 +310,8 @@ private: ButtonImage ButtonImages[gui::EGBIS_COUNT]; + std::array Styles; + gui::IGUIFont* OverrideFont; bool OverrideColorEnabled; @@ -326,8 +330,8 @@ private: video::SColor Colors[4]; // PATCH - video::SColor HoveredColors[4]; - video::SColor PressedColors[4]; + bool WasHovered = false; + ISimpleTextureSource *TSrc; gui::IGUIStaticText *StaticText; diff --git a/src/gui/guiButtonImage.cpp b/src/gui/guiButtonImage.cpp index 02d920277..2658ad967 100644 --- a/src/gui/guiButtonImage.cpp +++ b/src/gui/guiButtonImage.cpp @@ -30,8 +30,9 @@ using namespace irr; using namespace gui; GUIButtonImage::GUIButtonImage(gui::IGUIEnvironment *environment, - gui::IGUIElement *parent, s32 id, core::rect rectangle, bool noclip) - : GUIButton (environment, parent, id, rectangle, noclip) + gui::IGUIElement *parent, s32 id, core::rect rectangle, + ISimpleTextureSource *tsrc, bool noclip) + : GUIButton (environment, parent, id, rectangle, tsrc, noclip) { m_image = Environment->addImage( core::rect(0,0,rectangle.getWidth(),rectangle.getHeight()), this); @@ -39,100 +40,38 @@ GUIButtonImage::GUIButtonImage(gui::IGUIEnvironment *environment, sendToBack(m_image); } -bool GUIButtonImage::OnEvent(const SEvent& event) -{ - bool result = GUIButton::OnEvent(event); - - EGUI_BUTTON_IMAGE_STATE imageState = getImageState(isPressed(), m_foreground_images); - video::ITexture *texture = m_foreground_images[(u32)imageState].Texture; - if (texture != nullptr) - { - m_image->setImage(texture); - } - - m_image->setVisible(texture != nullptr); - - return result; -} - -void GUIButtonImage::setForegroundImage(EGUI_BUTTON_IMAGE_STATE state, - video::ITexture *image, const core::rect &sourceRect) +void GUIButtonImage::setForegroundImage(video::ITexture *image) { - if (state >= EGBIS_COUNT) + if (image == m_foreground_image) return; - if (image) + if (image != nullptr) image->grab(); - u32 stateIdx = (u32)state; - if (m_foreground_images[stateIdx].Texture) - m_foreground_images[stateIdx].Texture->drop(); - - m_foreground_images[stateIdx].Texture = image; - m_foreground_images[stateIdx].SourceRect = sourceRect; - - EGUI_BUTTON_IMAGE_STATE imageState = getImageState(isPressed(), m_foreground_images); - if (imageState == stateIdx) - m_image->setImage(image); -} - -void GUIButtonImage::setForegroundImage(video::ITexture *image) -{ - setForegroundImage(gui::EGBIS_IMAGE_UP, image); -} - -void GUIButtonImage::setForegroundImage(video::ITexture *image, const core::rect &pos) -{ - setForegroundImage(gui::EGBIS_IMAGE_UP, image, pos); -} - -void GUIButtonImage::setPressedForegroundImage(video::ITexture *image) -{ - setForegroundImage(gui::EGBIS_IMAGE_DOWN, image); -} + if (m_foreground_image != nullptr) + m_foreground_image->drop(); -void GUIButtonImage::setPressedForegroundImage(video::ITexture *image, const core::rect &pos) -{ - setForegroundImage(gui::EGBIS_IMAGE_DOWN, image, pos); + m_foreground_image = image; + m_image->setImage(image); } -void GUIButtonImage::setHoveredForegroundImage(video::ITexture *image) +//! Set element properties from a StyleSpec +void GUIButtonImage::setFromStyle(const StyleSpec& style) { - setForegroundImage(gui::EGBIS_IMAGE_UP_MOUSEOVER, image); - setForegroundImage(gui::EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, image); -} - -void GUIButtonImage::setHoveredForegroundImage(video::ITexture *image, const core::rect &pos) -{ - setForegroundImage(gui::EGBIS_IMAGE_UP_MOUSEOVER, image, pos); - setForegroundImage(gui::EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, image, pos); -} - -void GUIButtonImage::setFromStyle(const StyleSpec &style, ISimpleTextureSource *tsrc) -{ - GUIButton::setFromStyle(style, tsrc); + GUIButton::setFromStyle(style); video::IVideoDriver *driver = Environment->getVideoDriver(); const core::position2di buttonCenter(AbsoluteRect.getCenter()); core::position2d geom(buttonCenter); if (style.isNotDefault(StyleSpec::FGIMG)) { - video::ITexture *texture = style.getTexture(StyleSpec::FGIMG, tsrc); + video::ITexture *texture = style.getTexture(StyleSpec::FGIMG, + getTextureSource()); setForegroundImage(guiScalingImageButton(driver, texture, geom.X, geom.Y)); setScaleImage(true); - } - if (style.isNotDefault(StyleSpec::FGIMG_HOVERED)) { - video::ITexture *hovered_texture = style.getTexture(StyleSpec::FGIMG_HOVERED, tsrc); - - setHoveredForegroundImage(guiScalingImageButton(driver, hovered_texture, geom.X, geom.Y)); - setScaleImage(true); - } - if (style.isNotDefault(StyleSpec::FGIMG_PRESSED)) { - video::ITexture *pressed_texture = style.getTexture(StyleSpec::FGIMG_PRESSED, tsrc); - - setPressedForegroundImage(guiScalingImageButton(driver, pressed_texture, geom.X, geom.Y)); - setScaleImage(true); + } else { + setForegroundImage(nullptr); } } @@ -143,11 +82,12 @@ void GUIButtonImage::setScaleImage(bool scaleImage) } GUIButtonImage *GUIButtonImage::addButton(IGUIEnvironment *environment, - const core::rect &rectangle, IGUIElement *parent, s32 id, - const wchar_t *text, const wchar_t *tooltiptext) + const core::rect &rectangle, ISimpleTextureSource *tsrc, + IGUIElement *parent, s32 id, const wchar_t *text, + const wchar_t *tooltiptext) { GUIButtonImage *button = new GUIButtonImage(environment, - parent ? parent : environment->getRootGUIElement(), id, rectangle); + parent ? parent : environment->getRootGUIElement(), id, rectangle, tsrc); if (text) button->setText(text); diff --git a/src/gui/guiButtonImage.h b/src/gui/guiButtonImage.h index 15901ee5d..a948d772b 100644 --- a/src/gui/guiButtonImage.h +++ b/src/gui/guiButtonImage.h @@ -27,33 +27,23 @@ class GUIButtonImage : public GUIButton public: //! constructor GUIButtonImage(gui::IGUIEnvironment *environment, gui::IGUIElement *parent, - s32 id, core::rect rectangle, bool noclip = false); - - virtual bool OnEvent(const SEvent& event) override; - - void setForegroundImage(gui::EGUI_BUTTON_IMAGE_STATE state, - video::ITexture *image = nullptr, - const core::rect &sourceRect = core::rect(0, 0, 0, 0)); + s32 id, core::rect rectangle, ISimpleTextureSource *tsrc, + bool noclip = false); void setForegroundImage(video::ITexture *image = nullptr); - void setForegroundImage(video::ITexture *image, const core::rect &pos); - - void setPressedForegroundImage(video::ITexture *image = nullptr); - void setPressedForegroundImage(video::ITexture *image, const core::rect &pos); - - void setHoveredForegroundImage(video::ITexture *image = nullptr); - void setHoveredForegroundImage(video::ITexture *image, const core::rect &pos); - virtual void setFromStyle(const StyleSpec &style, ISimpleTextureSource *tsrc) override; + //! Set element properties from a StyleSpec + virtual void setFromStyle(const StyleSpec& style) override; virtual void setScaleImage(bool scaleImage=true) override; //! Do not drop returned handle static GUIButtonImage *addButton(gui::IGUIEnvironment *environment, - const core::rect &rectangle, IGUIElement *parent, s32 id, - const wchar_t *text, const wchar_t *tooltiptext = L""); + const core::rect &rectangle, ISimpleTextureSource *tsrc, + IGUIElement *parent, s32 id, const wchar_t *text, + const wchar_t *tooltiptext = L""); private: - ButtonImage m_foreground_images[gui::EGBIS_COUNT]; + video::ITexture *m_foreground_image = nullptr; gui::IGUIImage *m_image; }; diff --git a/src/gui/guiButtonItemImage.cpp b/src/gui/guiButtonItemImage.cpp index 5c48b2acd..d8b9042ac 100644 --- a/src/gui/guiButtonItemImage.cpp +++ b/src/gui/guiButtonItemImage.cpp @@ -28,9 +28,11 @@ with this program; if not, write to the Free Software Foundation, Inc., using namespace irr; using namespace gui; -GUIButtonItemImage::GUIButtonItemImage(gui::IGUIEnvironment *environment, gui::IGUIElement *parent, - s32 id, core::rect rectangle, std::string item, Client *client, bool noclip) - : GUIButton (environment, parent, id, rectangle, noclip) +GUIButtonItemImage::GUIButtonItemImage(gui::IGUIEnvironment *environment, + gui::IGUIElement *parent, s32 id, core::rect rectangle, + ISimpleTextureSource *tsrc, std::string item, Client *client, + bool noclip) + : GUIButton (environment, parent, id, rectangle, tsrc, noclip) { m_image = new GUIItemImage(environment, this, id, core::rect(0,0,rectangle.getWidth(),rectangle.getHeight()), @@ -42,12 +44,13 @@ GUIButtonItemImage::GUIButtonItemImage(gui::IGUIEnvironment *environment, gui::I } GUIButtonItemImage *GUIButtonItemImage::addButton(IGUIEnvironment *environment, - const core::rect &rectangle, IGUIElement *parent, s32 id, - const wchar_t *text, std::string item, Client *client) + const core::rect &rectangle, ISimpleTextureSource *tsrc, + IGUIElement *parent, s32 id, const wchar_t *text, std::string item, + Client *client) { GUIButtonItemImage *button = new GUIButtonItemImage(environment, parent ? parent : environment->getRootGUIElement(), - id, rectangle, item, client); + id, rectangle, tsrc, item, client); if (text) button->setText(text); diff --git a/src/gui/guiButtonItemImage.h b/src/gui/guiButtonItemImage.h index 0a61874da..9cd0f6188 100644 --- a/src/gui/guiButtonItemImage.h +++ b/src/gui/guiButtonItemImage.h @@ -30,13 +30,14 @@ class GUIButtonItemImage : public GUIButton public: //! constructor GUIButtonItemImage(gui::IGUIEnvironment *environment, gui::IGUIElement *parent, - s32 id, core::rect rectangle, std::string item, - Client *client, bool noclip = false); + s32 id, core::rect rectangle, ISimpleTextureSource *tsrc, + std::string item, Client *client, bool noclip = false); //! Do not drop returned handle static GUIButtonItemImage *addButton(gui::IGUIEnvironment *environment, - const core::rect &rectangle, IGUIElement *parent, s32 id, - const wchar_t *text, std::string item, Client *client); + const core::rect &rectangle, ISimpleTextureSource *tsrc, + IGUIElement *parent, s32 id, const wchar_t *text, std::string item, + Client *client); private: std::string m_item_name; diff --git a/src/gui/guiConfirmRegistration.cpp b/src/gui/guiConfirmRegistration.cpp index 0d8bdf54e..58ac42740 100644 --- a/src/gui/guiConfirmRegistration.cpp +++ b/src/gui/guiConfirmRegistration.cpp @@ -40,10 +40,10 @@ const int ID_message = 266; GUIConfirmRegistration::GUIConfirmRegistration(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id, IMenuManager *menumgr, Client *client, const std::string &playername, const std::string &password, - bool *aborted) : + bool *aborted, ISimpleTextureSource *tsrc) : GUIModalMenu(env, parent, id, menumgr), m_client(client), m_playername(playername), m_password(password), - m_aborted(aborted) + m_aborted(aborted), m_tsrc(tsrc) { #ifdef __ANDROID__ m_touchscreen_visible = false; @@ -130,14 +130,14 @@ void GUIConfirmRegistration::regenerateGui(v2u32 screensize) core::rect rect2(0, 0, 230 * s, 35 * s); rect2 = rect2 + v2s32(size.X / 2 - 220 * s, ypos); text = wgettext("Register and Join"); - GUIButton::addButton(Environment, rect2, this, ID_confirm, text); + GUIButton::addButton(Environment, rect2, m_tsrc, this, ID_confirm, text); delete[] text; } { core::rect rect2(0, 0, 120 * s, 35 * s); rect2 = rect2 + v2s32(size.X / 2 + 70 * s, ypos); text = wgettext("Cancel"); - GUIButton::addButton(Environment, rect2, this, ID_cancel, text); + GUIButton::addButton(Environment, rect2, m_tsrc, this, ID_cancel, text); delete[] text; } { diff --git a/src/gui/guiConfirmRegistration.h b/src/gui/guiConfirmRegistration.h index 42c07e4ed..d8387201d 100644 --- a/src/gui/guiConfirmRegistration.h +++ b/src/gui/guiConfirmRegistration.h @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include class Client; +class ISimpleTextureSource; class GUIConfirmRegistration : public GUIModalMenu { @@ -32,7 +33,7 @@ public: GUIConfirmRegistration(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id, IMenuManager *menumgr, Client *client, const std::string &playername, const std::string &password, - bool *aborted); + bool *aborted, ISimpleTextureSource *tsrc); ~GUIConfirmRegistration(); void removeChildren(); @@ -63,4 +64,5 @@ private: const std::string &m_password; bool *m_aborted = nullptr; std::wstring m_pass_confirm = L""; + ISimpleTextureSource *m_tsrc; }; diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index acb153569..6a383a791 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -553,7 +553,7 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data, const std::string &element gui::IGUICheckBox *e = Environment->addCheckBox(fselected, rect, this, spec.fid, spec.flabel.c_str()); - auto style = getStyleForElement("checkbox", name); + auto style = getDefaultStyleForElement("checkbox", name); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); if (spec.fname == data->focused_fieldname) { @@ -613,7 +613,7 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, const std::string &elemen GUIScrollBar *e = new GUIScrollBar(Environment, this, spec.fid, rect, is_horizontal, true); - auto style = getStyleForElement("scrollbar", name); + auto style = getDefaultStyleForElement("scrollbar", name); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); e->setArrowsVisible(data->scrollbar_options.arrow_visiblity); @@ -740,7 +740,7 @@ void GUIFormSpecMenu::parseImage(parserData* data, const std::string &element) gui::IGUIImage *e = Environment->addImage(rect, this, spec.fid, 0, true); e->setImage(texture); e->setScaleImage(true); - auto style = getStyleForElement("image", spec.fname); + auto style = getDefaultStyleForElement("image", spec.fname); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, m_formspec_version < 3)); m_fields.push_back(spec); @@ -776,7 +776,7 @@ void GUIFormSpecMenu::parseImage(parserData* data, const std::string &element) ); gui::IGUIImage *e = Environment->addImage(texture, pos, true, this, spec.fid, 0); - auto style = getStyleForElement("image", spec.fname); + auto style = getDefaultStyleForElement("image", spec.fname); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, m_formspec_version < 3)); m_fields.push_back(spec); @@ -841,7 +841,7 @@ void GUIFormSpecMenu::parseAnimatedImage(parserData *data, const std::string &el if (parts.size() >= 7) e->setFrameIndex(stoi(parts[6]) - 1); - auto style = getStyleForElement("animated_image", spec.fname, "image"); + auto style = getDefaultStyleForElement("animated_image", spec.fname, "image"); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); e->drop(); @@ -888,7 +888,7 @@ void GUIFormSpecMenu::parseItemImage(parserData* data, const std::string &elemen GUIItemImage *e = new GUIItemImage(Environment, this, spec.fid, core::rect(pos, pos + geom), name, m_font, m_client); - auto style = getStyleForElement("item_image", spec.fname); + auto style = getDefaultStyleForElement("item_image", spec.fname); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); // item images should let events through @@ -949,10 +949,11 @@ void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element, if(type == "button_exit") spec.is_exit = true; - GUIButton *e = GUIButton::addButton(Environment, rect, this, spec.fid, spec.flabel.c_str()); + GUIButton *e = GUIButton::addButton(Environment, rect, m_tsrc, this, + spec.fid, spec.flabel.c_str()); auto style = getStyleForElement(type, name, (type != "button") ? "button" : ""); - e->setFromStyle(style, m_tsrc); + e->setStyles(style); if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); @@ -1155,7 +1156,7 @@ void GUIFormSpecMenu::parseTable(parserData* data, const std::string &element) if (!str_initial_selection.empty() && str_initial_selection != "0") e->setSelected(stoi(str_initial_selection)); - auto style = getStyleForElement("table", name); + auto style = getDefaultStyleForElement("table", name); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); m_tables.emplace_back(spec, e); @@ -1231,7 +1232,7 @@ void GUIFormSpecMenu::parseTextList(parserData* data, const std::string &element if (!str_initial_selection.empty() && str_initial_selection != "0") e->setSelected(stoi(str_initial_selection)); - auto style = getStyleForElement("textlist", name); + auto style = getDefaultStyleForElement("textlist", name); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); m_tables.emplace_back(spec, e); @@ -1306,7 +1307,7 @@ void GUIFormSpecMenu::parseDropDown(parserData* data, const std::string &element if (!str_initial_selection.empty()) e->setSelected(stoi(str_initial_selection)-1); - auto style = getStyleForElement("dropdown", name); + auto style = getDefaultStyleForElement("dropdown", name); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); m_fields.push_back(spec); @@ -1394,7 +1395,7 @@ void GUIFormSpecMenu::parsePwdField(parserData* data, const std::string &element e->setPasswordBox(true,L'*'); - auto style = getStyleForElement("pwdfield", name, "field"); + auto style = getDefaultStyleForElement("pwdfield", name, "field"); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); e->setDrawBorder(style.getBool(StyleSpec::BORDER, true)); e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF))); @@ -1454,7 +1455,7 @@ void GUIFormSpecMenu::createTextField(parserData *data, FieldSpec &spec, } } - auto style = getStyleForElement(is_multiline ? "textarea" : "field", spec.fname); + auto style = getDefaultStyleForElement(is_multiline ? "textarea" : "field", spec.fname); if (e) { if (is_editable && spec.fname == data->focused_fieldname) @@ -1752,7 +1753,7 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element) spec.flabel.c_str(), rect, false, false, this, spec.fid); e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_CENTER); - auto style = getStyleForElement("label", spec.fname); + auto style = getDefaultStyleForElement("label", spec.fname); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF))); @@ -1832,7 +1833,7 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data, const std::string &elemen rect, false, false, this, spec.fid); e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); - auto style = getStyleForElement("vertlabel", spec.fname, "label"); + auto style = getDefaultStyleForElement("vertlabel", spec.fname, "label"); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF))); @@ -1863,17 +1864,8 @@ void GUIFormSpecMenu::parseImageButton(parserData* data, const std::string &elem MY_CHECKPOS("imagebutton",0); MY_CHECKGEOM("imagebutton",1); - bool noclip = false; - bool drawborder = true; std::string pressed_image_name; - if (parts.size() >= 7) { - if (parts[5] == "true") - noclip = true; - if (parts[6] == "false") - drawborder = false; - } - if (parts.size() >= 8) { pressed_image_name = parts[7]; } @@ -1911,35 +1903,30 @@ void GUIFormSpecMenu::parseImageButton(parserData* data, const std::string &elem if (type == "image_button_exit") spec.is_exit = true; - GUIButtonImage *e = GUIButtonImage::addButton(Environment, rect, this, spec.fid, spec.flabel.c_str()); + GUIButtonImage *e = GUIButtonImage::addButton(Environment, rect, m_tsrc, + this, spec.fid, spec.flabel.c_str()); if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); } auto style = getStyleForElement("image_button", spec.fname); - e->setFromStyle(style, m_tsrc); - // We explicitly handle these arguments *after* the style properties in - // order to override them if they are provided + // Override style properties with values specified directly in the element if (!image_name.empty()) - { - video::ITexture *texture = m_tsrc->getTexture(image_name); - e->setForegroundImage(guiScalingImageButton( - Environment->getVideoDriver(), texture, geom.X, geom.Y)); - } - if (!pressed_image_name.empty()) { - video::ITexture *pressed_texture = m_tsrc->getTexture(pressed_image_name); - e->setPressedForegroundImage(guiScalingImageButton( - Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y)); - } - e->setScaleImage(true); + style[StyleSpec::STATE_DEFAULT].set(StyleSpec::FGIMG, image_name); + + if (!pressed_image_name.empty()) + style[StyleSpec::STATE_PRESSED].set(StyleSpec::FGIMG, pressed_image_name); if (parts.size() >= 7) { - e->setNotClipped(noclip); - e->setDrawBorder(drawborder); + style[StyleSpec::STATE_DEFAULT].set(StyleSpec::NOCLIP, parts[5]); + style[StyleSpec::STATE_DEFAULT].set(StyleSpec::BORDER, parts[6]); } + e->setStyles(style); + e->setScaleImage(true); + m_fields.push_back(spec); return; } @@ -2033,7 +2020,7 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data, const std::string &elemen Environment->setFocus(e); } - auto style = getStyleForElement("tabheader", name); + auto style = getDefaultStyleForElement("tabheader", name); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, true)); for (const std::string &button : buttons) { @@ -2118,10 +2105,12 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string & 2 ); - GUIButtonItemImage *e_btn = GUIButtonItemImage::addButton(Environment, rect, this, spec_btn.fid, spec_btn.flabel.c_str(), item_name, m_client); + GUIButtonItemImage *e_btn = GUIButtonItemImage::addButton(Environment, + rect, m_tsrc, this, spec_btn.fid, spec_btn.flabel.c_str(), + item_name, m_client); auto style = getStyleForElement("item_image_button", spec_btn.fname, "image_button"); - e_btn->setFromStyle(style, m_tsrc); + e_btn->setStyles(style); if (spec_btn.fname == data->focused_fieldname) { Environment->setFocus(e_btn); @@ -2177,7 +2166,7 @@ void GUIFormSpecMenu::parseBox(parserData* data, const std::string &element) GUIBox *e = new GUIBox(Environment, this, spec.fid, rect, tmp_color); - auto style = getStyleForElement("box", spec.fname); + auto style = getDefaultStyleForElement("box", spec.fname); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, m_formspec_version < 3)); e->drop(); @@ -2469,6 +2458,7 @@ bool GUIFormSpecMenu::parseStyle(parserData *data, const std::string &element, b StyleSpec spec; + // Parse properties for (size_t i = 1; i < parts.size(); i++) { size_t equal_pos = parts[i].find('='); if (equal_pos == std::string::npos) { @@ -2500,16 +2490,92 @@ bool GUIFormSpecMenu::parseStyle(parserData *data, const std::string &element, b for (size_t sel = 0; sel < selectors.size(); sel++) { std::string selector = trim(selectors[sel]); - if (selector.empty()) { - errorstream << "Invalid style element (Empty selector): '" << element - << "'" << std::endl; + // Copy the style properties to a new StyleSpec + // This allows a separate state mask per-selector + StyleSpec selector_spec = spec; + + // Parse state information, if it exists + bool state_valid = true; + size_t state_pos = selector.find(':'); + if (state_pos != std::string::npos) { + std::string state_str = selector.substr(state_pos + 1); + selector = selector.substr(0, state_pos); + + if (state_str.empty()) { + errorstream << "Invalid style element (Invalid state): '" << element + << "'" << std::endl; + state_valid = false; + } else { + std::vector states = split(state_str, '+'); + for (std::string &state : states) { + StyleSpec::State converted = StyleSpec::getStateByName(state); + if (converted == StyleSpec::STATE_INVALID) { + infostream << "Unknown style state " << state << + " in element '" << element << "'" << std::endl; + state_valid = false; + break; + } + + selector_spec.addState(converted); + } + } + } + + if(!state_valid) { + // Skip this selector continue; } if (style_type) { - theme_by_type[selector] |= spec; + theme_by_type[selector].push_back(selector_spec); } else { - theme_by_name[selector] |= spec; + theme_by_name[selector].push_back(selector_spec); + } + + // Backwards-compatibility for existing _hovered/_pressed properties + if (selector_spec.hasProperty(StyleSpec::BGCOLOR_HOVERED) + || selector_spec.hasProperty(StyleSpec::BGIMG_HOVERED) + || selector_spec.hasProperty(StyleSpec::FGIMG_HOVERED)) { + StyleSpec hover_spec; + hover_spec.addState(StyleSpec::STATE_HOVERED); + + if (selector_spec.hasProperty(StyleSpec::BGCOLOR_HOVERED)) { + hover_spec.set(StyleSpec::BGCOLOR, selector_spec.get(StyleSpec::BGCOLOR_HOVERED, "")); + } + if (selector_spec.hasProperty(StyleSpec::BGIMG_HOVERED)) { + hover_spec.set(StyleSpec::BGIMG, selector_spec.get(StyleSpec::BGIMG_HOVERED, "")); + } + if (selector_spec.hasProperty(StyleSpec::FGIMG_HOVERED)) { + hover_spec.set(StyleSpec::FGIMG, selector_spec.get(StyleSpec::FGIMG_HOVERED, "")); + } + + if (style_type) { + theme_by_type[selector].push_back(hover_spec); + } else { + theme_by_name[selector].push_back(hover_spec); + } + } + if (selector_spec.hasProperty(StyleSpec::BGCOLOR_PRESSED) + || selector_spec.hasProperty(StyleSpec::BGIMG_PRESSED) + || selector_spec.hasProperty(StyleSpec::FGIMG_PRESSED)) { + StyleSpec press_spec; + press_spec.addState(StyleSpec::STATE_PRESSED); + + if (selector_spec.hasProperty(StyleSpec::BGCOLOR_PRESSED)) { + press_spec.set(StyleSpec::BGCOLOR, selector_spec.get(StyleSpec::BGCOLOR_PRESSED, "")); + } + if (selector_spec.hasProperty(StyleSpec::BGIMG_PRESSED)) { + press_spec.set(StyleSpec::BGIMG, selector_spec.get(StyleSpec::BGIMG_PRESSED, "")); + } + if (selector_spec.hasProperty(StyleSpec::FGIMG_PRESSED)) { + press_spec.set(StyleSpec::FGIMG, selector_spec.get(StyleSpec::FGIMG_PRESSED, "")); + } + + if (style_type) { + theme_by_type[selector].push_back(press_spec); + } else { + theme_by_name[selector].push_back(press_spec); + } } } @@ -3080,7 +3146,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) size.X / 2 - 70 + 140, pos.Y + m_btn_height * 2 ); const wchar_t *text = wgettext("Proceed"); - GUIButton::addButton(Environment, mydata.rect, this, 257, text); + GUIButton::addButton(Environment, mydata.rect, m_tsrc, this, 257, text); delete[] text; } } @@ -4432,25 +4498,34 @@ std::wstring GUIFormSpecMenu::getLabelByID(s32 id) return L""; } -StyleSpec GUIFormSpecMenu::getStyleForElement(const std::string &type, +StyleSpec GUIFormSpecMenu::getDefaultStyleForElement(const std::string &type, const std::string &name, const std::string &parent_type) { - StyleSpec ret; + return getStyleForElement(type, name, parent_type)[StyleSpec::STATE_DEFAULT]; +} + +std::array GUIFormSpecMenu::getStyleForElement(const std::string &type, + const std::string &name, const std::string &parent_type) +{ + std::array ret; if (!parent_type.empty()) { auto it = theme_by_type.find(parent_type); if (it != theme_by_type.end()) { - ret |= it->second; + for (const StyleSpec &spec : it->second) + ret[(u32)spec.getState()] |= spec; } } auto it = theme_by_type.find(type); if (it != theme_by_type.end()) { - ret |= it->second; + for (const StyleSpec &spec : it->second) + ret[(u32)spec.getState()] |= spec; } it = theme_by_name.find(name); if (it != theme_by_name.end()) { - ret |= it->second; + for (const StyleSpec &spec : it->second) + ret[(u32)spec.getState()] |= spec; } return ret; diff --git a/src/gui/guiFormSpecMenu.h b/src/gui/guiFormSpecMenu.h index 17bfef205..b3bf67110 100644 --- a/src/gui/guiFormSpecMenu.h +++ b/src/gui/guiFormSpecMenu.h @@ -274,11 +274,13 @@ protected: v2s32 getRealCoordinateBasePos(const std::vector &v_pos); v2s32 getRealCoordinateGeometry(const std::vector &v_geom); - std::unordered_map theme_by_type; - std::unordered_map theme_by_name; + std::unordered_map> theme_by_type; + std::unordered_map> theme_by_name; std::unordered_set property_warned; - StyleSpec getStyleForElement(const std::string &type, + StyleSpec getDefaultStyleForElement(const std::string &type, + const std::string &name="", const std::string &parent_type=""); + std::array getStyleForElement(const std::string &type, const std::string &name="", const std::string &parent_type=""); v2s32 padding; diff --git a/src/gui/guiKeyChangeMenu.cpp b/src/gui/guiKeyChangeMenu.cpp index 3f270fc7a..da0e25c23 100644 --- a/src/gui/guiKeyChangeMenu.cpp +++ b/src/gui/guiKeyChangeMenu.cpp @@ -82,8 +82,10 @@ enum }; GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env, - gui::IGUIElement* parent, s32 id, IMenuManager *menumgr) : -GUIModalMenu(env, parent, id, menumgr) + gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, + ISimpleTextureSource *tsrc) : + GUIModalMenu(env, parent, id, menumgr), + m_tsrc(tsrc) { init_keys(); } @@ -157,7 +159,7 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) core::rect rect(0, 0, 100 * s, 30 * s); rect += topleft + v2s32(offset.X + 150 * s, offset.Y - 5 * s); const wchar_t *text = wgettext(k->key.name()); - k->button = GUIButton::addButton(Environment, rect, this, k->id, text); + k->button = GUIButton::addButton(Environment, rect, m_tsrc, this, k->id, text); delete[] text; } if ((i + 1) % KMaxButtonPerColumns == 0) { @@ -217,14 +219,14 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) core::rect rect(0, 0, 100 * s, 30 * s); rect += topleft + v2s32(size.X / 2 - 105 * s, size.Y - 40 * s); const wchar_t *text = wgettext("Save"); - GUIButton::addButton(Environment, rect, this, GUI_ID_BACK_BUTTON, text); + GUIButton::addButton(Environment, rect, m_tsrc, this, GUI_ID_BACK_BUTTON, text); delete[] text; } { core::rect rect(0, 0, 100 * s, 30 * s); rect += topleft + v2s32(size.X / 2 + 5 * s, size.Y - 40 * s); const wchar_t *text = wgettext("Cancel"); - GUIButton::addButton(Environment, rect, this, GUI_ID_ABORT_BUTTON, text); + GUIButton::addButton(Environment, rect, m_tsrc, this, GUI_ID_ABORT_BUTTON, text); delete[] text; } } diff --git a/src/gui/guiKeyChangeMenu.h b/src/gui/guiKeyChangeMenu.h index 528827fd9..1c0f40247 100644 --- a/src/gui/guiKeyChangeMenu.h +++ b/src/gui/guiKeyChangeMenu.h @@ -28,6 +28,8 @@ #include #include +class ISimpleTextureSource; + struct key_setting { int id; @@ -41,7 +43,7 @@ class GUIKeyChangeMenu : public GUIModalMenu { public: GUIKeyChangeMenu(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id, - IMenuManager *menumgr); + IMenuManager *menumgr, ISimpleTextureSource *tsrc); ~GUIKeyChangeMenu(); void removeChildren(); @@ -74,4 +76,5 @@ private: key_setting *active_key = nullptr; gui::IGUIStaticText *key_used_text = nullptr; std::vector key_settings; + ISimpleTextureSource *m_tsrc; }; diff --git a/src/gui/guiPasswordChange.cpp b/src/gui/guiPasswordChange.cpp index af91ce84c..965a2d6f7 100644 --- a/src/gui/guiPasswordChange.cpp +++ b/src/gui/guiPasswordChange.cpp @@ -38,10 +38,12 @@ const int ID_cancel = 261; GUIPasswordChange::GUIPasswordChange(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, - Client* client + Client* client, + ISimpleTextureSource *tsrc ): GUIModalMenu(env, parent, id, menumgr), - m_client(client) + m_client(client), + m_tsrc(tsrc) { } @@ -146,14 +148,14 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) core::rect rect(0, 0, 100 * s, 30 * s); rect = rect + v2s32(size.X / 4 + 56 * s, ypos); text = wgettext("Change"); - GUIButton::addButton(Environment, rect, this, ID_change, text); + GUIButton::addButton(Environment, rect, m_tsrc, this, ID_change, text); delete[] text; } { core::rect rect(0, 0, 100 * s, 30 * s); rect = rect + v2s32(size.X / 4 + 185 * s, ypos); text = wgettext("Cancel"); - GUIButton::addButton(Environment, rect, this, ID_cancel, text); + GUIButton::addButton(Environment, rect, m_tsrc, this, ID_cancel, text); delete[] text; } diff --git a/src/gui/guiPasswordChange.h b/src/gui/guiPasswordChange.h index 58541a399..7141100c0 100644 --- a/src/gui/guiPasswordChange.h +++ b/src/gui/guiPasswordChange.h @@ -23,12 +23,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include class Client; +class ISimpleTextureSource; class GUIPasswordChange : public GUIModalMenu { public: GUIPasswordChange(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id, - IMenuManager *menumgr, Client *client); + IMenuManager *menumgr, Client *client, + ISimpleTextureSource *tsrc); ~GUIPasswordChange(); void removeChildren(); @@ -57,4 +59,5 @@ private: std::wstring m_oldpass = L""; std::wstring m_newpass = L""; std::wstring m_newpass_confirm = L""; + ISimpleTextureSource *m_tsrc; }; diff --git a/src/gui/guiVolumeChange.cpp b/src/gui/guiVolumeChange.cpp index 9428cde83..07b11248c 100644 --- a/src/gui/guiVolumeChange.cpp +++ b/src/gui/guiVolumeChange.cpp @@ -38,9 +38,10 @@ const int ID_soundMuteButton = 266; GUIVolumeChange::GUIVolumeChange(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, - IMenuManager *menumgr + IMenuManager *menumgr, ISimpleTextureSource *tsrc ): - GUIModalMenu(env, parent, id, menumgr) + GUIModalMenu(env, parent, id, menumgr), + m_tsrc(tsrc) { } @@ -104,7 +105,7 @@ void GUIVolumeChange::regenerateGui(v2u32 screensize) core::rect rect(0, 0, 80 * s, 30 * s); rect = rect + v2s32(size.X / 2 - 80 * s / 2, size.Y / 2 + 55 * s); const wchar_t *text = wgettext("Exit"); - GUIButton::addButton(Environment, rect, this, ID_soundExitButton, text); + GUIButton::addButton(Environment, rect, m_tsrc, this, ID_soundExitButton, text); delete[] text; } { diff --git a/src/gui/guiVolumeChange.h b/src/gui/guiVolumeChange.h index f4f4e9eea..466e17f9d 100644 --- a/src/gui/guiVolumeChange.h +++ b/src/gui/guiVolumeChange.h @@ -23,12 +23,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "modalMenu.h" #include +class ISimpleTextureSource; + class GUIVolumeChange : public GUIModalMenu { public: GUIVolumeChange(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, - IMenuManager *menumgr); + IMenuManager *menumgr, ISimpleTextureSource *tsrc); ~GUIVolumeChange(); void removeChildren(); @@ -46,4 +48,7 @@ public: protected: std::wstring getLabelByID(s32 id) { return L""; } std::string getNameByID(s32 id) { return ""; } + +private: + ISimpleTextureSource *m_tsrc; }; diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 76db7ed13..867e84e13 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -571,9 +571,10 @@ int ModApiMainMenu::l_show_keys_menu(lua_State *L) sanity_check(engine != NULL); GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(RenderingEngine::get_gui_env(), - engine->m_parent, - -1, - engine->m_menumanager); + engine->m_parent, + -1, + engine->m_menumanager, + engine->m_texture_source); kmenu->drop(); return 0; } @@ -904,12 +905,12 @@ int ModApiMainMenu::l_show_path_select_dialog(lua_State *L) GUIFileSelectMenu* fileOpenMenu = new GUIFileSelectMenu(RenderingEngine::get_gui_env(), - engine->m_parent, - -1, - engine->m_menumanager, - title, - formname, - is_file_select); + engine->m_parent, + -1, + engine->m_menumanager, + title, + formname, + is_file_select); fileOpenMenu->setTextDest(engine->m_buttonhandler); fileOpenMenu->drop(); return 0; diff --git a/src/util/numeric.h b/src/util/numeric.h index 6f82a18c1..864ab7543 100644 --- a/src/util/numeric.h +++ b/src/util/numeric.h @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irr_v2d.h" #include "irr_v3d.h" #include "irr_aabb3d.h" +#include "SColor.h" #include #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d) > (max) ? (max) : (d))) @@ -432,3 +433,12 @@ inline v3f getPitchYawRoll(const core::matrix4 &m) { return getPitchYawRollRad(m) * core::RADTODEG64; } + +// Muliply the RGB value of a color linearly, and clamp to black/white +inline irr::video::SColor multiplyColorValue(const irr::video::SColor &color, float mod) +{ + return irr::video::SColor(color.getAlpha(), + core::clamp(color.getRed() * mod, 0, 255), + core::clamp(color.getGreen() * mod, 0, 255), + core::clamp(color.getBlue() * mod, 0, 255)); +} -- cgit v1.2.3 From af2e6a6a10121cf971d4ce4c33d523b6dc037d31 Mon Sep 17 00:00:00 2001 From: Lars Müller <34514239+appgurueu@users.noreply.github.com> Date: Sat, 11 Apr 2020 23:09:46 +0200 Subject: Improve waypoints and add image variant (#9480) --- doc/client_lua_api.txt | 25 ++++++++- doc/lua_api.txt | 20 ++++++++ src/client/hud.cpp | 111 ++++++++++++++++++++++++---------------- src/client/hud.h | 1 + src/hud.cpp | 1 + src/hud.h | 1 + src/script/common/c_content.cpp | 6 ++- 7 files changed, 118 insertions(+), 47 deletions(-) (limited to 'doc') diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index 71df91c68..53ed680d0 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -1416,12 +1416,35 @@ Displays a horizontal bar made up of half-images. * `offset`: offset in pixels from position. ### `waypoint` + Displays distance to selected world position. * `name`: The name of the waypoint. * `text`: Distance suffix. Can be blank. -* `number:` An integer containing the RGB value of the color used to draw the text. +* `precision`: Waypoint precision, integer >= 0. Defaults to 10. + If set to 0, distance is not shown. Shown value is `floor(distance*precision)/precision`. + When the precision is an integer multiple of 10, there will be `log_10(precision)` digits after the decimal point. + `precision = 1000`, for example, will show 3 decimal places (eg: `0.999`). + `precision = 2` will show multiples of `0.5`; precision = 5 will show multiples of `0.2` and so on: + `precision = n` will show multiples of `1/n` +* `number:` An integer containing the RGB value of the color used to draw the + text. * `world_pos`: World position of the waypoint. +* `offset`: offset in pixels from position. +* `alignment`: The alignment of the waypoint. + +### `image_waypoint` + +Same as `image`, but does not accept a `position`; the position is instead determined by `world_pos`, the world position of the waypoint. + +* `scale`: The scale of the image, with 1 being the original texture size. + Only the X coordinate scale is used (positive values). + Negative values represent that percentage of the screen it + should take; e.g. `x=-100` means 100% (width). +* `text`: The name of the texture that is displayed. +* `alignment`: The alignment of the image. +* `world_pos`: World position of the waypoint. +* `offset`: offset in pixels from position. ### Particle definition (`add_particle`) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index b083b2907..1a9aad344 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1364,10 +1364,30 @@ Displays distance to selected world position. * `name`: The name of the waypoint. * `text`: Distance suffix. Can be blank. +* `precision`: Waypoint precision, integer >= 0. Defaults to 10. + If set to 0, distance is not shown. Shown value is `floor(distance*precision)/precision`. + When the precision is an integer multiple of 10, there will be `log_10(precision)` digits after the decimal point. + `precision = 1000`, for example, will show 3 decimal places (eg: `0.999`). + `precision = 2` will show multiples of `0.5`; precision = 5 will show multiples of `0.2` and so on: + `precision = n` will show multiples of `1/n` * `number:` An integer containing the RGB value of the color used to draw the text. * `world_pos`: World position of the waypoint. +* `offset`: offset in pixels from position. +* `alignment`: The alignment of the waypoint. + +### `image_waypoint` + +Same as `image`, but does not accept a `position`; the position is instead determined by `world_pos`, the world position of the waypoint. +* `scale`: The scale of the image, with 1 being the original texture size. + Only the X coordinate scale is used (positive values). + Negative values represent that percentage of the screen it + should take; e.g. `x=-100` means 100% (width). +* `text`: The name of the texture that is displayed. +* `alignment`: The alignment of the image. +* `world_pos`: World position of the waypoint. +* `offset`: offset in pixels from position. diff --git a/src/client/hud.cpp b/src/client/hud.cpp index 37de6640b..56763e7e4 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -272,6 +272,25 @@ void Hud::drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount, } } +// Calculates screen position of waypoint. Returns true if waypoint is visible (in front of the player), else false. +bool Hud::calculateScreenPos(const v3s16 &camera_offset, HudElement *e, v2s32 *pos) +{ + v3f w_pos = e->world_pos * BS; + scene::ICameraSceneNode* camera = + RenderingEngine::get_scene_manager()->getActiveCamera(); + w_pos -= intToFloat(camera_offset, BS); + core::matrix4 trans = camera->getProjectionMatrix(); + trans *= camera->getViewMatrix(); + f32 transformed_pos[4] = { w_pos.X, w_pos.Y, w_pos.Z, 1.0f }; + trans.multiplyWith1x4Matrix(transformed_pos); + if (transformed_pos[3] < 0) + return false; + f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f : + core::reciprocal(transformed_pos[3]); + pos->X = m_screensize.X * (0.5 * transformed_pos[0] * zDiv + 0.5); + pos->Y = m_screensize.Y * (0.5 - transformed_pos[1] * zDiv * 0.5); + return true; +} void Hud::drawLuaElements(const v3s16 &camera_offset) { @@ -299,28 +318,6 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) v2s32 pos(floor(e->pos.X * (float) m_screensize.X + 0.5), floor(e->pos.Y * (float) m_screensize.Y + 0.5)); switch (e->type) { - case HUD_ELEM_IMAGE: { - video::ITexture *texture = tsrc->getTexture(e->text); - if (!texture) - continue; - - const video::SColor color(255, 255, 255, 255); - const video::SColor colors[] = {color, color, color, color}; - core::dimension2di imgsize(texture->getOriginalSize()); - v2s32 dstsize(imgsize.Width * e->scale.X, - imgsize.Height * e->scale.Y); - if (e->scale.X < 0) - dstsize.X = m_screensize.X * (e->scale.X * -0.01); - if (e->scale.Y < 0) - dstsize.Y = m_screensize.Y * (e->scale.Y * -0.01); - v2s32 offset((e->align.X - 1.0) * dstsize.X / 2, - (e->align.Y - 1.0) * dstsize.Y / 2); - core::rect rect(0, 0, dstsize.X, dstsize.Y); - rect += pos + offset + v2s32(e->offset.X, e->offset.Y); - draw2DImageFilterScaled(driver, texture, rect, - core::rect(core::position2d(0,0), imgsize), - NULL, colors, true); - break; } case HUD_ELEM_TEXT: { video::SColor color(255, (e->number >> 16) & 0xFF, (e->number >> 8) & 0xFF, @@ -343,34 +340,58 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) inv, e->item, e->dir); break; } case HUD_ELEM_WAYPOINT: { - v3f p_pos = player->getPosition() / BS; - v3f w_pos = e->world_pos * BS; - float distance = std::floor(10 * p_pos.getDistanceFrom(e->world_pos)) / - 10.0f; - scene::ICameraSceneNode* camera = - RenderingEngine::get_scene_manager()->getActiveCamera(); - w_pos -= intToFloat(camera_offset, BS); - core::matrix4 trans = camera->getProjectionMatrix(); - trans *= camera->getViewMatrix(); - f32 transformed_pos[4] = { w_pos.X, w_pos.Y, w_pos.Z, 1.0f }; - trans.multiplyWith1x4Matrix(transformed_pos); - if (transformed_pos[3] < 0) + if (!calculateScreenPos(camera_offset, e, &pos)) break; - f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f : - core::reciprocal(transformed_pos[3]); - pos.X = m_screensize.X * (0.5 * transformed_pos[0] * zDiv + 0.5); - pos.Y = m_screensize.Y * (0.5 - transformed_pos[1] * zDiv * 0.5); + v3f p_pos = player->getPosition() / BS; + pos += v2s32(e->offset.X, e->offset.Y); video::SColor color(255, (e->number >> 16) & 0xFF, (e->number >> 8) & 0xFF, (e->number >> 0) & 0xFF); - core::rect size(0, 0, 200, 2 * text_height); std::wstring text = unescape_translate(utf8_to_wide(e->name)); - font->draw(text.c_str(), size + pos, color); - std::ostringstream os; - os << distance << e->text; - text = unescape_translate(utf8_to_wide(os.str())); - pos.Y += text_height; - font->draw(text.c_str(), size + pos, color); + const std::string &unit = e->text; + // waypoints reuse the item field to store precision, item = precision + 1 + u32 item = e->item; + float precision = (item == 0) ? 10.0f : (item - 1.f); + bool draw_precision = precision > 0; + + core::rect bounds(0, 0, font->getDimension(text.c_str()).Width, (draw_precision ? 2:1) * text_height); + pos.Y += (e->align.Y - 1.0) * bounds.getHeight() / 2; + bounds += pos; + font->draw(text.c_str(), bounds + v2s32((e->align.X - 1.0) * bounds.getWidth() / 2, 0), color); + if (draw_precision) { + std::ostringstream os; + float distance = std::floor(precision * p_pos.getDistanceFrom(e->world_pos)) / precision; + os << distance << unit; + text = unescape_translate(utf8_to_wide(os.str())); + bounds.LowerRightCorner.X = bounds.UpperLeftCorner.X + font->getDimension(text.c_str()).Width; + font->draw(text.c_str(), bounds + v2s32((e->align.X - 1.0f) * bounds.getWidth() / 2, text_height), color); + } + break; } + case HUD_ELEM_IMAGE_WAYPOINT: { + if (!calculateScreenPos(camera_offset, e, &pos)) + break; + } + case HUD_ELEM_IMAGE: { + video::ITexture *texture = tsrc->getTexture(e->text); + if (!texture) + continue; + + const video::SColor color(255, 255, 255, 255); + const video::SColor colors[] = {color, color, color, color}; + core::dimension2di imgsize(texture->getOriginalSize()); + v2s32 dstsize(imgsize.Width * e->scale.X, + imgsize.Height * e->scale.Y); + if (e->scale.X < 0) + dstsize.X = m_screensize.X * (e->scale.X * -0.01); + if (e->scale.Y < 0) + dstsize.Y = m_screensize.Y * (e->scale.Y * -0.01); + v2s32 offset((e->align.X - 1.0) * dstsize.X / 2, + (e->align.Y - 1.0) * dstsize.Y / 2); + core::rect rect(0, 0, dstsize.X, dstsize.Y); + rect += pos + offset + v2s32(e->offset.X, e->offset.Y); + draw2DImageFilterScaled(driver, texture, rect, + core::rect(core::position2d(0,0), imgsize), + NULL, colors, true); break; } default: infostream << "Hud::drawLuaElements: ignoring drawform " << e->type << diff --git a/src/client/hud.h b/src/client/hud.h index d9b5e0686..cab115990 100644 --- a/src/client/hud.h +++ b/src/client/hud.h @@ -81,6 +81,7 @@ public: void drawLuaElements(const v3s16 &camera_offset); private: + bool calculateScreenPos(const v3s16 &camera_offset, HudElement *e, v2s32 *pos); void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, const std::string &texture, s32 count, v2s32 offset, v2s32 size = v2s32()); diff --git a/src/hud.cpp b/src/hud.cpp index 7711e3a4a..39625b5fd 100644 --- a/src/hud.cpp +++ b/src/hud.cpp @@ -27,6 +27,7 @@ const struct EnumString es_HudElementType[] = {HUD_ELEM_STATBAR, "statbar"}, {HUD_ELEM_INVENTORY, "inventory"}, {HUD_ELEM_WAYPOINT, "waypoint"}, + {HUD_ELEM_IMAGE_WAYPOINT, "image_waypoint"}, {0, NULL}, }; diff --git a/src/hud.h b/src/hud.h index 23f189dff..b0977c6a4 100644 --- a/src/hud.h +++ b/src/hud.h @@ -61,6 +61,7 @@ enum HudElementType { HUD_ELEM_STATBAR = 2, HUD_ELEM_INVENTORY = 3, HUD_ELEM_WAYPOINT = 4, + HUD_ELEM_IMAGE_WAYPOINT = 5 }; enum HudElementStat { diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index c8cd7539f..ff9ceec6d 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -1850,7 +1850,11 @@ void read_hud_element(lua_State *L, HudElement *elem) elem->name = getstringfield_default(L, 2, "name", ""); elem->text = getstringfield_default(L, 2, "text", ""); elem->number = getintfield_default(L, 2, "number", 0); - elem->item = getintfield_default(L, 2, "item", 0); + if (elem->type == HUD_ELEM_WAYPOINT) + // waypoints reuse the item field to store precision, item = precision + 1 + elem->item = getintfield_default(L, 2, "precision", -1) + 1; + else + elem->item = getintfield_default(L, 2, "item", 0); elem->dir = getintfield_default(L, 2, "direction", 0); elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX, getintfield_default(L, 2, "z_index", 0))); -- cgit v1.2.3 From a24d3b360048bde87113d435ab0cfef78851153c Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Sun, 12 Apr 2020 01:50:40 +0200 Subject: Play 'player_jump' when player jumps (#9373) --- doc/lua_api.txt | 1 + src/client/game.cpp | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 1a9aad344..dff6c728e 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -897,6 +897,7 @@ These sound files are played back by the engine if provided. * `player_damage`: Played when the local player takes damage (gain = 0.5) * `player_falling_damage`: Played when the local player takes damage by falling (gain = 0.5) + * `player_jump`: Played when the local player jumps * `default_dig_`: Default node digging sound (see node sound definition for details) diff --git a/src/client/game.cpp b/src/client/game.cpp index 06e76d170..ac6045190 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -266,6 +266,7 @@ class SoundMaker 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; @@ -275,7 +276,8 @@ public: m_sound(sound), m_ndef(ndef), makes_footstep_sound(true), - m_player_step_timer(0) + m_player_step_timer(0.0f), + m_player_jump_timer(0.0f) { } @@ -288,6 +290,14 @@ public: } } + 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; @@ -302,7 +312,8 @@ public: static void playerJump(MtEvent *e, void *data) { - //SoundMaker *sm = (SoundMaker*)data; + SoundMaker *sm = (SoundMaker *)data; + sm->playPlayerJump(); } static void cameraPunchLeft(MtEvent *e, void *data) @@ -351,6 +362,7 @@ public: void step(float dtime) { m_player_step_timer -= dtime; + m_player_jump_timer -= dtime; } }; -- cgit v1.2.3 From 0ac999ded725f8efcd26db284161683e37efeecf Mon Sep 17 00:00:00 2001 From: DS Date: Mon, 13 Apr 2020 10:50:07 +0200 Subject: Add scroll_container formspec element (redo) (#9101) New formspec elements: - `scroll_container[,;,;;;]` - `scroll_container_end[]` Other elements can be embedded in this element. Scrollbar must be placed manually. --- build/android/jni/Android.mk | 1 + doc/lua_api.txt | 20 ++++ games/minimal/mods/test/formspec.lua | 69 ++++++++++- src/gui/CMakeLists.txt | 1 + src/gui/guiFormSpecMenu.cpp | 216 +++++++++++++++++++++++++++++------ src/gui/guiFormSpecMenu.h | 5 + src/gui/guiHyperText.cpp | 20 ++-- src/gui/guiHyperText.h | 2 +- src/gui/guiScrollContainer.cpp | 70 ++++++++++++ src/gui/guiScrollContainer.h | 56 +++++++++ src/network/networkprotocol.h | 1 + 11 files changed, 411 insertions(+), 50 deletions(-) create mode 100644 src/gui/guiScrollContainer.cpp create mode 100644 src/gui/guiScrollContainer.h (limited to 'doc') diff --git a/build/android/jni/Android.mk b/build/android/jni/Android.mk index fdbfba9bc..b67322d79 100644 --- a/build/android/jni/Android.mk +++ b/build/android/jni/Android.mk @@ -194,6 +194,7 @@ LOCAL_SRC_FILES := \ jni/src/gui/guiPasswordChange.cpp \ jni/src/gui/guiPathSelectMenu.cpp \ jni/src/gui/guiScrollBar.cpp \ + jni/src/gui/guiScrollContainer.cpp \ jni/src/gui/guiSkin.cpp \ jni/src/gui/guiTable.cpp \ jni/src/gui/guiVolumeChange.cpp \ diff --git a/doc/lua_api.txt b/doc/lua_api.txt index dff6c728e..f43987cd8 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2102,6 +2102,26 @@ Elements * End of a container, following elements are no longer relative to this container. +### `scroll_container[,;,;;;]` + +* Start of a scroll_container block. All contained elements will ... + * take the scroll_container coordinate as position origin, + * be additionally moved by the current value of the scrollbar with the name + `scrollbar name` times `scroll factor` along the orientation `orientation` and + * be clipped to the rectangle defined by `X`, `Y`, `W` and `H`. +* `orientation`: possible values are `vertical` and `horizontal`. +* `scroll factor`: optional, defaults to `0.1`. +* Nesting is possible. +* Some elements might work a little different if they are in a scroll_container. +* Note: If you want the scroll_container to actually work, you also need to add a + scrollbar element with the specified name. Furthermore, it is highly recommended + to use a scrollbaroptions element on this scrollbar. + +### `scroll_container_end[]` + +* End of a scroll_container, following elements are no longer bound to this + container. + ### `list[;;,;,;]` * Show an inventory list if it has been sent to the client. Nothing will diff --git a/games/minimal/mods/test/formspec.lua b/games/minimal/mods/test/formspec.lua index 14886aad2..53e92b243 100644 --- a/games/minimal/mods/test/formspec.lua +++ b/games/minimal/mods/test/formspec.lua @@ -1,5 +1,35 @@ local color = minetest.colorize +local hypertext = minetest.formspec_escape([[ + +
Furnace
+ are crafted and used by the player for the purpose of cooking food and smelting various items. + + Solid block + Itself + No + Inactive:No Active:Yes (8) + No + No + Yes + Yes (99) + default:furnace default:furnace_active + Usage + The furnace menu can be accessed by using the furnace. + The furnace has 3 inventories: An input slot, a fuel slot and 4 output slots. The fire in the furnace will automatically start when there is a smeltable item in the input slot and a fuel in the fuel slot. + As long as the fire is on, the furnace will smelt any smeltable item in the input slot, one by one, until it is empty. When the fire goes off, it will smelt the next item until there are no smeltable items and no fuel items left. + The current stage of cooking can be seen by pointing the furnace or by viewing the furnace menu. In the furnace menu, the flame symbol roughly shows the remaining burning time. The arrow symbol shows the progress of the current smelting process. + Renewing + Furnaces can be crafted from e.g. cobblestone, a renewable resource. + Crafting + Sorry no way to display crafting yet in formspec pages. + Fuel + See Smelting for a list of furnace fuels. + Recipes + See the Smelting page. +]]) + + local clip_fs = [[ style_type[label,button,image_button,item_image_button, tabheader,scrollbar,table,animated_image @@ -188,13 +218,48 @@ Number] animated_image[3,4.25;1,1;;test_animation.png;4;0;3] animated_image[5.5,0.5;5,2;;test_animation.png;4;100] animated_image[5.5,2.75;5,2;;test_animation.jpg;4;100] - ]] + ]], + + "formspec_version[3]".. + "size[12,12]".. + "button[8.5,1;1,1;bla;Bla]".. + "box[1,1;8,6;#00aa]".. + "scroll_container[1,1;8,6;scrbar;vertical]".. + "button[0,1;1,1;lorem;Lorem]".. + "button[0,10;1,1;ipsum;Ipsum]".. + "pwdfield[2,2;1,1;lorem2;Lorem]".. + "list[current_player;main;4,4;1,5;]".. + "box[2,5;3,2;#ffff00]".. + "image[1,10;3,2;bubble.png]".. + "image[3,1;bubble.png]".. + "item_image[2,6;3,2;default:mese]".. + "label[2,15;bla Bli\nfoo bar]".. + "item_image_button[2,3;1,1;default:dirt_with_grass;itemimagebutton;ItemImageButton]".. + "tooltip[0,11;3,2;Buz;#f00;#000]".. + "box[0,11;3,2;#00ff00]".. + "hypertext[3,13;3,3;;" .. hypertext .. "]" .. + "container[0,18]".. + "box[1,2;3,2;#0a0a]".. + "scroll_container[1,2;3,2;scrbar2;horizontal;0.06]".. + "button[0,0;6,1;butnest;Nest]".. + "label[10,0.5;nest]".. + "scroll_container_end[]".. + "scrollbar[1,0;3.5,0.3;horizontal;scrbar2;0]".. + "container_end[]".. + "dropdown[0,6;2;hmdrpdwn;apple,bulb;1]".. + "image_button[0,4;2,2;bubble.png;bubblebutton;bbbbtt;false;true;heart.png]".. + "box[1,22.5;4,1;#a00a]".. + "scroll_container_end[]".. + "scrollbaroptions[max=170]".. -- lowest seen pos is: 0.1*170+6=23 (factor*max+height) + "scrollbar[7.5,0;0.3,4;vertical;scrbar;0]".. + "scrollbar[8,0;0.3,4;vertical;scrbarhmmm;0]".. + "dropdown[0,6;2;hmdrpdwnnn;apple,bulb;1]", } local function show_test_formspec(pname, page_id) page_id = page_id or 2 - local fs = pages[page_id] .. "tabheader[0,0;6,0.65;maintabs;Real Coord,Styles,Noclip,MiscEle;" .. page_id .. ";false;false]" + local fs = pages[page_id] .. "tabheader[0,0;8,0.65;maintabs;Real Coord,Styles,Noclip,MiscEle,Scroll Container;" .. page_id .. ";false;false]" minetest.show_formspec(pname, "test:formspec", fs) end diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 110a00595..147f445f4 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -16,6 +16,7 @@ set(gui_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/guiPasswordChange.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiPathSelectMenu.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiScrollBar.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/guiScrollContainer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiSkin.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiTable.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiHyperText.cpp diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index f3bf04275..aac039ad6 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -65,6 +65,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "guiInventoryList.h" #include "guiItemImage.h" #include "guiScrollBar.h" +#include "guiScrollContainer.h" #include "guiTable.h" #include "intlGUIEditBox.h" #include "guiHyperText.h" @@ -143,6 +144,8 @@ GUIFormSpecMenu::~GUIFormSpecMenu() tooltip_rect_it.first->drop(); for (auto &clickthrough_it : m_clickthrough_elements) clickthrough_it->drop(); + for (auto &scroll_container_it : m_scroll_containers) + scroll_container_it.second->drop(); delete m_selected_item; delete m_form_src; @@ -351,6 +354,102 @@ void GUIFormSpecMenu::parseContainerEnd(parserData* data) } } +void GUIFormSpecMenu::parseScrollContainer(parserData *data, const std::string &element) +{ + std::vector parts = split(element, ';'); + + if (parts.size() < 4 || + (parts.size() > 5 && m_formspec_version <= FORMSPEC_API_VERSION)) { + errorstream << "Invalid scroll_container start element (" << parts.size() + << "): '" << element << "'" << std::endl; + return; + } + + std::vector v_pos = split(parts[0], ','); + std::vector v_geom = split(parts[1], ','); + std::string scrollbar_name = parts[2]; + std::string orientation = parts[3]; + f32 scroll_factor = 0.1f; + if (parts.size() >= 5 && !parts[4].empty()) + scroll_factor = stof(parts[4]); + + MY_CHECKPOS("scroll_container", 0); + MY_CHECKGEOM("scroll_container", 1); + + v2s32 pos = getRealCoordinateBasePos(v_pos); + v2s32 geom = getRealCoordinateGeometry(v_geom); + + if (orientation == "vertical") + scroll_factor *= -imgsize.Y; + else if (orientation == "horizontal") + scroll_factor *= -imgsize.X; + else + warningstream << "GUIFormSpecMenu::parseScrollContainer(): " + << "Invalid scroll_container orientation: " << orientation + << std::endl; + + // old parent (at first: this) + // ^ is parent of clipper + // ^ is parent of mover + // ^ is parent of other elements + + // make clipper + core::rect rect_clipper = core::rect(pos, pos + geom); + + gui::IGUIElement *clipper = new gui::IGUIElement(EGUIET_ELEMENT, Environment, + data->current_parent, 0, rect_clipper); + + // make mover + FieldSpec spec_mover( + "", + L"", + L"", + 258 + m_fields.size() + ); + + core::rect rect_mover = core::rect(0, 0, geom.X, geom.Y); + + GUIScrollContainer *mover = new GUIScrollContainer(Environment, + clipper, spec_mover.fid, rect_mover, orientation, scroll_factor); + + data->current_parent = mover; + + m_scroll_containers.emplace_back(scrollbar_name, mover); + + m_fields.push_back(spec_mover); + + clipper->drop(); + + // remove interferring offset of normal containers + container_stack.push(pos_offset); + pos_offset.X = 0.0f; + pos_offset.Y = 0.0f; +} + +void GUIFormSpecMenu::parseScrollContainerEnd(parserData *data) +{ + if (data->current_parent == this || data->current_parent->getParent() == this || + container_stack.empty()) { + errorstream << "Invalid scroll_container end element, " + << "no matching scroll_container start element" << std::endl; + return; + } + + if (pos_offset.getLengthSQ() != 0.0f) { + // pos_offset is only set by containers and scroll_containers. + // scroll_containers always set it to 0,0 which means that if it is + // not 0,0, it is a normal container that was opened last, not a + // scroll_container + errorstream << "Invalid scroll_container end element, " + << "an inner container was left open" << std::endl; + return; + } + + data->current_parent = data->current_parent->getParent()->getParent(); + pos_offset = container_stack.top(); + container_stack.pop(); +} + void GUIFormSpecMenu::parseList(parserData *data, const std::string &element) { if (m_client == 0) { @@ -443,9 +542,9 @@ void GUIFormSpecMenu::parseList(parserData *data, const std::string &element) pos.X + (geom.X - 1) * slot_spacing.X + imgsize.X, pos.Y + (geom.Y - 1) * slot_spacing.Y + imgsize.Y); - GUIInventoryList *e = new GUIInventoryList(Environment, this, spec.fid, - rect, m_invmgr, loc, listname, geom, start_i, imgsize, slot_spacing, - this, data->inventorylist_options, m_font); + GUIInventoryList *e = new GUIInventoryList(Environment, data->current_parent, + spec.fid, rect, m_invmgr, loc, listname, geom, start_i, imgsize, + slot_spacing, this, data->inventorylist_options, m_font); m_inventorylists.push_back(e); m_fields.push_back(spec); @@ -550,8 +649,8 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data, const std::string &element spec.ftype = f_CheckBox; - gui::IGUICheckBox *e = Environment->addCheckBox(fselected, rect, this, - spec.fid, spec.flabel.c_str()); + gui::IGUICheckBox *e = Environment->addCheckBox(fselected, rect, + data->current_parent, spec.fid, spec.flabel.c_str()); auto style = getDefaultStyleForElement("checkbox", name); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); @@ -610,8 +709,8 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, const std::string &elemen spec.ftype = f_ScrollBar; spec.send = true; - GUIScrollBar *e = new GUIScrollBar(Environment, this, spec.fid, rect, - is_horizontal, true); + GUIScrollBar *e = new GUIScrollBar(Environment, data->current_parent, + spec.fid, rect, is_horizontal, true); auto style = getDefaultStyleForElement("scrollbar", name); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); @@ -737,7 +836,8 @@ void GUIFormSpecMenu::parseImage(parserData* data, const std::string &element) 1 ); core::rect rect(pos, pos + geom); - gui::IGUIImage *e = Environment->addImage(rect, this, spec.fid, 0, true); + gui::IGUIImage *e = Environment->addImage(rect, data->current_parent, + spec.fid, 0, true); e->setImage(texture); e->setScaleImage(true); auto style = getDefaultStyleForElement("image", spec.fname); @@ -774,8 +874,8 @@ void GUIFormSpecMenu::parseImage(parserData* data, const std::string &element) L"", 258 + m_fields.size() ); - gui::IGUIImage *e = Environment->addImage(texture, pos, true, this, - spec.fid, 0); + gui::IGUIImage *e = Environment->addImage(texture, pos, true, + data->current_parent, spec.fid, 0); auto style = getDefaultStyleForElement("image", spec.fname); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, m_formspec_version < 3)); m_fields.push_back(spec); @@ -886,7 +986,7 @@ void GUIFormSpecMenu::parseItemImage(parserData* data, const std::string &elemen ); spec.ftype = f_ItemImage; - GUIItemImage *e = new GUIItemImage(Environment, this, spec.fid, + GUIItemImage *e = new GUIItemImage(Environment, data->current_parent, spec.fid, core::rect(pos, pos + geom), name, m_font, m_client); auto style = getDefaultStyleForElement("item_image", spec.fname); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); @@ -949,8 +1049,8 @@ void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element, if(type == "button_exit") spec.is_exit = true; - GUIButton *e = GUIButton::addButton(Environment, rect, m_tsrc, this, - spec.fid, spec.flabel.c_str()); + GUIButton *e = GUIButton::addButton(Environment, rect, m_tsrc, + data->current_parent, spec.fid, spec.flabel.c_str()); auto style = getStyleForElement(type, name, (type != "button") ? "button" : ""); e->setStyles(style); @@ -1141,7 +1241,8 @@ void GUIFormSpecMenu::parseTable(parserData* data, const std::string &element) } //now really show table - GUITable *e = new GUITable(Environment, this, spec.fid, rect, m_tsrc); + GUITable *e = new GUITable(Environment, data->current_parent, spec.fid, + rect, m_tsrc); if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); @@ -1217,7 +1318,8 @@ void GUIFormSpecMenu::parseTextList(parserData* data, const std::string &element } //now really show list - GUITable *e = new GUITable(Environment, this, spec.fid, rect, m_tsrc); + GUITable *e = new GUITable(Environment, data->current_parent, spec.fid, + rect, m_tsrc); if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); @@ -1293,7 +1395,8 @@ void GUIFormSpecMenu::parseDropDown(parserData* data, const std::string &element spec.send = true; //now really show list - gui::IGUIComboBox *e = Environment->addComboBox(rect, this, spec.fid); + gui::IGUIComboBox *e = Environment->addComboBox(rect, data->current_parent, + spec.fid); if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); @@ -1379,7 +1482,8 @@ void GUIFormSpecMenu::parsePwdField(parserData* data, const std::string &element ); spec.send = true; - gui::IGUIEditBox * e = Environment->addEditBox(0, rect, true, this, spec.fid); + gui::IGUIEditBox *e = Environment->addEditBox(0, rect, true, + data->current_parent, spec.fid); if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); @@ -1390,7 +1494,7 @@ void GUIFormSpecMenu::parsePwdField(parserData* data, const std::string &element rect.UpperLeftCorner.Y -= font_height; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height; gui::StaticText::add(Environment, spec.flabel.c_str(), rect, false, true, - this, 0); + data->current_parent, 0); } e->setPasswordBox(true,L'*'); @@ -1425,7 +1529,7 @@ void GUIFormSpecMenu::createTextField(parserData *data, FieldSpec &spec, if (!is_editable && !is_multiline) { // spec field id to 0, this stops submit searching for a value that isn't there gui::StaticText::add(Environment, spec.flabel.c_str(), rect, false, true, - this, 0); + data->current_parent, 0); return; } @@ -1443,14 +1547,14 @@ void GUIFormSpecMenu::createTextField(parserData *data, FieldSpec &spec, if (use_intl_edit_box && g_settings->getBool("freetype")) { e = new gui::intlGUIEditBox(spec.fdefault.c_str(), true, Environment, - this, spec.fid, rect, is_editable, is_multiline); + data->current_parent, spec.fid, rect, is_editable, is_multiline); } else { if (is_multiline) { - e = new GUIEditBoxWithScrollBar(spec.fdefault.c_str(), true, - Environment, this, spec.fid, rect, is_editable, true); + e = new GUIEditBoxWithScrollBar(spec.fdefault.c_str(), true, Environment, + data->current_parent, spec.fid, rect, is_editable, true); } else if (is_editable) { - e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, - spec.fid); + e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, + data->current_parent, spec.fid); e->grab(); } } @@ -1491,7 +1595,7 @@ void GUIFormSpecMenu::createTextField(parserData *data, FieldSpec &spec, rect.UpperLeftCorner.Y -= font_height; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height; IGUIElement *t = gui::StaticText::add(Environment, spec.flabel.c_str(), - rect, false, true, this, 0); + rect, false, true, data->current_parent, 0); if (t) t->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); @@ -1671,8 +1775,8 @@ void GUIFormSpecMenu::parseHyperText(parserData *data, const std::string &elemen ); spec.ftype = f_HyperText; - GUIHyperText *e = new GUIHyperText(spec.flabel.c_str(), Environment, this, - spec.fid, rect, m_client, m_tsrc); + GUIHyperText *e = new GUIHyperText(spec.flabel.c_str(), Environment, + data->current_parent, spec.fid, rect, m_client, m_tsrc); e->drop(); m_fields.push_back(spec); @@ -1750,7 +1854,8 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element) 4 ); gui::IGUIStaticText *e = gui::StaticText::add(Environment, - spec.flabel.c_str(), rect, false, false, this, spec.fid); + spec.flabel.c_str(), rect, false, false, data->current_parent, + spec.fid); e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_CENTER); auto style = getDefaultStyleForElement("label", spec.fname); @@ -1830,7 +1935,7 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data, const std::string &elemen 258 + m_fields.size() ); gui::IGUIStaticText *e = gui::StaticText::add(Environment, spec.flabel.c_str(), - rect, false, false, this, spec.fid); + rect, false, false, data->current_parent, spec.fid); e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); auto style = getDefaultStyleForElement("vertlabel", spec.fname, "label"); @@ -1904,7 +2009,7 @@ void GUIFormSpecMenu::parseImageButton(parserData* data, const std::string &elem spec.is_exit = true; GUIButtonImage *e = GUIButtonImage::addButton(Environment, rect, m_tsrc, - this, spec.fid, spec.flabel.c_str()); + data->current_parent, spec.fid, spec.flabel.c_str()); if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); @@ -2010,8 +2115,8 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data, const std::string &elemen core::rect rect = core::rect(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y); - gui::IGUITabControl *e = Environment->addTabControl(rect, this, - show_background, show_border, spec.fid); + gui::IGUITabControl *e = Environment->addTabControl(rect, + data->current_parent, show_background, show_border, spec.fid); e->setAlignment(irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_LOWERRIGHT); e->setTabHeight(geom.Y); @@ -2046,7 +2151,6 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data, const std::string &elemen void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string &element) { - if (m_client == 0) { warningstream << "invalid use of item_image_button with m_client==0" << std::endl; @@ -2106,7 +2210,7 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string & ); GUIButtonItemImage *e_btn = GUIButtonItemImage::addButton(Environment, - rect, m_tsrc, this, spec_btn.fid, spec_btn.flabel.c_str(), + rect, m_tsrc, data->current_parent, spec_btn.fid, spec_btn.flabel.c_str(), item_name, m_client); auto style = getStyleForElement("item_image_button", spec_btn.fname, "image_button"); @@ -2164,7 +2268,8 @@ void GUIFormSpecMenu::parseBox(parserData* data, const std::string &element) core::rect rect(pos, pos + geom); - GUIBox *e = new GUIBox(Environment, this, spec.fid, rect, tmp_color); + GUIBox *e = new GUIBox(Environment, data->current_parent, spec.fid, + rect, tmp_color); auto style = getDefaultStyleForElement("box", spec.fname); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, m_formspec_version < 3)); @@ -2316,7 +2421,7 @@ void GUIFormSpecMenu::parseTooltip(parserData* data, const std::string &element) core::rect rect(pos, pos + geom); gui::IGUIElement *e = new gui::IGUIElement(EGUIET_ELEMENT, Environment, - this, fieldspec.fid, rect); + data->current_parent, fieldspec.fid, rect); // the element the rect tooltip is bound to should not block mouse-clicks e->setVisible(false); @@ -2775,6 +2880,16 @@ void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element) return; } + if (type == "scroll_container") { + parseScrollContainer(data, description); + return; + } + + if (type == "scroll_container_end") { + parseScrollContainerEnd(data); + return; + } + // Ignore others infostream << "Unknown DrawSpec: type=" << type << ", data=\"" << description << "\"" << std::endl; @@ -2831,8 +2946,10 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) tooltip_rect_it.first->drop(); for (auto &clickthrough_it : m_clickthrough_elements) clickthrough_it->drop(); + for (auto &scroll_container_it : m_scroll_containers) + scroll_container_it.second->drop(); - mydata.size= v2s32(100,100); + mydata.size = v2s32(100, 100); mydata.screensize = screensize; mydata.offset = v2f32(0.5f, 0.5f); mydata.anchor = v2f32(0.5f, 0.5f); @@ -2841,6 +2958,9 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) // Base position of contents of form mydata.basepos = getBasePos(); + // the parent for the parsed elements + mydata.current_parent = this; + m_inventorylists.clear(); m_backgrounds.clear(); m_tables.clear(); @@ -2851,6 +2971,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) m_tooltip_rects.clear(); m_inventory_rings.clear(); m_dropdowns.clear(); + m_scroll_containers.clear(); theme_by_name.clear(); theme_by_type.clear(); m_clickthrough_elements.clear(); @@ -3117,11 +3238,24 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) parseElement(&mydata, elements[i]); } - if (!container_stack.empty()) { + if (mydata.current_parent != this) { + errorstream << "Invalid formspec string: scroll_container was never closed!" + << std::endl; + } else if (!container_stack.empty()) { errorstream << "Invalid formspec string: container was never closed!" << std::endl; } + // get the scrollbar elements for scroll_containers + for (const std::pair &c : m_scroll_containers) { + for (const std::pair &b : m_scrollbars) { + if (c.first == b.first.fname) { + c.second->setScrollBar(b.second); + break; + } + } + } + // If there are fields without explicit size[], add a "Proceed" // button and adjust size to fit all the fields. if (mydata.simple_field_count > 0 && !mydata.explicit_size) { @@ -4418,6 +4552,12 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) } } + if (event.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED) { + // move scroll_containers + for (const std::pair &c : m_scroll_containers) + c.second->onScrollEvent(event.GUIEvent.Caller); + } + if (event.GUIEvent.EventType == gui::EGET_EDITBOX_ENTER) { if (event.GUIEvent.Caller->getID() > 257) { bool close_on_enter = true; diff --git a/src/gui/guiFormSpecMenu.h b/src/gui/guiFormSpecMenu.h index dc22e8b54..28088416d 100644 --- a/src/gui/guiFormSpecMenu.h +++ b/src/gui/guiFormSpecMenu.h @@ -39,6 +39,7 @@ class ISimpleTextureSource; class Client; class GUIScrollBar; class TexturePool; +class GUIScrollContainer; typedef enum { f_Button, @@ -310,6 +311,7 @@ protected: std::vector> m_scrollbars; std::vector>> m_dropdowns; std::vector m_clickthrough_elements; + std::vector> m_scroll_containers; GUIInventoryList::ItemSpec *m_selected_item = nullptr; u16 m_selected_amount = 0; @@ -359,6 +361,7 @@ private: std::string focused_fieldname; GUITable::TableOptions table_options; GUITable::TableColumns table_columns; + gui::IGUIElement *current_parent = nullptr; GUIInventoryList::Options inventorylist_options; @@ -391,6 +394,8 @@ private: void parseSize(parserData* data, const std::string &element); void parseContainer(parserData* data, const std::string &element); void parseContainerEnd(parserData* data); + void parseScrollContainer(parserData *data, const std::string &element); + void parseScrollContainerEnd(parserData *data); void parseList(parserData* data, const std::string &element); void parseListRing(parserData* data, const std::string &element); void parseCheckbox(parserData* data, const std::string &element); diff --git a/src/gui/guiHyperText.cpp b/src/gui/guiHyperText.cpp index e107b5a3e..88931cdf9 100644 --- a/src/gui/guiHyperText.cpp +++ b/src/gui/guiHyperText.cpp @@ -917,20 +917,20 @@ void TextDrawer::place(const core::rect &dest_rect) // Draw text in a rectangle with a given offset. Items are actually placed in // relative (to upper left corner) coordinates. -void TextDrawer::draw(const core::rect &dest_rect, +void TextDrawer::draw(const core::rect &clip_rect, const core::position2d &dest_offset) { irr::video::IVideoDriver *driver = m_environment->getVideoDriver(); - core::position2d offset = dest_rect.UpperLeftCorner + dest_offset; + core::position2d offset = dest_offset; offset.Y += m_voffset; if (m_text.background_type == ParsedText::BACKGROUND_COLOR) - driver->draw2DRectangle(m_text.background_color, dest_rect); + driver->draw2DRectangle(m_text.background_color, clip_rect); for (auto &p : m_text.m_paragraphs) { for (auto &el : p.elements) { core::rect rect(el.pos + offset, el.dim); - if (!rect.isRectCollided(dest_rect)) + if (!rect.isRectCollided(clip_rect)) continue; switch (el.type) { @@ -947,7 +947,7 @@ void TextDrawer::draw(const core::rect &dest_rect, if (el.type == ParsedText::ELEMENT_TEXT) el.font->draw(el.text, rect, color, false, true, - &dest_rect); + &clip_rect); if (el.underline && el.drawwidth) { s32 linepos = el.pos.Y + offset.Y + @@ -958,7 +958,7 @@ void TextDrawer::draw(const core::rect &dest_rect, el.pos.X + offset.X + el.drawwidth, linepos + (el.baseline >> 3)); - driver->draw2DRectangle(color, linerect, &dest_rect); + driver->draw2DRectangle(color, linerect, &clip_rect); } } break; @@ -972,7 +972,7 @@ void TextDrawer::draw(const core::rect &dest_rect, irr::core::rect( core::position2d(0, 0), texture->getOriginalSize()), - &dest_rect, 0, true); + &clip_rect, 0, true); } break; case ParsedText::ELEMENT_ITEM: { @@ -982,7 +982,7 @@ void TextDrawer::draw(const core::rect &dest_rect, drawItemStack( m_environment->getVideoDriver(), - g_fontengine->getFont(), item, rect, &dest_rect, + g_fontengine->getFont(), item, rect, &clip_rect, m_client, IT_ROT_OTHER, el.angle, el.rotation ); } break; @@ -1094,6 +1094,7 @@ bool GUIHyperText::OnEvent(const SEvent &event) m_text_scrollpos.Y = -m_vscrollbar->getPos(); m_drawer.draw(m_display_text_rect, m_text_scrollpos); checkHover(event.MouseInput.X, event.MouseInput.Y); + return true; } else if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { ParsedText::Element *element = getElementAt( @@ -1151,7 +1152,8 @@ void GUIHyperText::draw() m_vscrollbar->setPos(0); m_vscrollbar->setVisible(false); } - m_drawer.draw(m_display_text_rect, m_text_scrollpos); + m_drawer.draw(AbsoluteClippingRect, + m_display_text_rect.UpperLeftCorner + m_text_scrollpos); // draw children IGUIElement::draw(); diff --git a/src/gui/guiHyperText.h b/src/gui/guiHyperText.h index c55f8a705..5b936262e 100644 --- a/src/gui/guiHyperText.h +++ b/src/gui/guiHyperText.h @@ -174,7 +174,7 @@ public: void place(const core::rect &dest_rect); inline s32 getHeight() { return m_height; }; - void draw(const core::rect &dest_rect, + void draw(const core::rect &clip_rect, const core::position2d &dest_offset); ParsedText::Element *getElementAt(core::position2d pos); ParsedText::Tag *m_hovertag; diff --git a/src/gui/guiScrollContainer.cpp b/src/gui/guiScrollContainer.cpp new file mode 100644 index 000000000..88cdc7057 --- /dev/null +++ b/src/gui/guiScrollContainer.cpp @@ -0,0 +1,70 @@ +/* +Minetest +Copyright (C) 2020 DS + +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 "guiScrollContainer.h" + +GUIScrollContainer::GUIScrollContainer(gui::IGUIEnvironment *env, + gui::IGUIElement *parent, s32 id, const core::rect &rectangle, + const std::string &orientation, f32 scrollfactor) : + gui::IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, rectangle), + m_scrollbar(nullptr), m_scrollfactor(scrollfactor) +{ + if (orientation == "vertical") + m_orientation = VERTICAL; + else if (orientation == "horizontal") + m_orientation = HORIZONTAL; + else + m_orientation = UNDEFINED; +} + +bool GUIScrollContainer::OnEvent(const SEvent &event) +{ + if (event.EventType == EET_MOUSE_INPUT_EVENT && + event.MouseInput.Event == EMIE_MOUSE_WHEEL && + !event.MouseInput.isLeftPressed() && m_scrollbar) { + Environment->setFocus(m_scrollbar); + bool retval = m_scrollbar->OnEvent(event); + + // a hacky fix for updating the hovering and co. + IGUIElement *hovered_elem = getElementFromPoint(core::position2d( + event.MouseInput.X, event.MouseInput.Y)); + SEvent mov_event = event; + mov_event.MouseInput.Event = EMIE_MOUSE_MOVED; + Environment->postEventFromUser(mov_event); + if (hovered_elem) + hovered_elem->OnEvent(mov_event); + + return retval; + } + + return IGUIElement::OnEvent(event); +} + +void GUIScrollContainer::updateScrolling() +{ + s32 pos = m_scrollbar->getPos(); + core::rect rect = getRelativePosition(); + + if (m_orientation == VERTICAL) + rect.UpperLeftCorner.Y = pos * m_scrollfactor; + else if (m_orientation == HORIZONTAL) + rect.UpperLeftCorner.X = pos * m_scrollfactor; + + setRelativePosition(rect); +} diff --git a/src/gui/guiScrollContainer.h b/src/gui/guiScrollContainer.h new file mode 100644 index 000000000..9eaa880bf --- /dev/null +++ b/src/gui/guiScrollContainer.h @@ -0,0 +1,56 @@ +/* +Minetest +Copyright (C) 2020 DS + +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 "irrlichttypes_extrabloated.h" +#include "util/string.h" +#include "guiScrollBar.h" + +class GUIScrollContainer : public gui::IGUIElement +{ +public: + GUIScrollContainer(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id, + const core::rect &rectangle, const std::string &orientation, + f32 scrollfactor); + + virtual bool OnEvent(const SEvent &event) override; + + inline void onScrollEvent(gui::IGUIElement *caller) + { + if (caller == m_scrollbar) + updateScrolling(); + } + + inline void setScrollBar(GUIScrollBar *scrollbar) { m_scrollbar = scrollbar; } + +private: + enum OrientationEnum + { + VERTICAL, + HORIZONTAL, + UNDEFINED + }; + + GUIScrollBar *m_scrollbar; + OrientationEnum m_orientation; + f32 m_scrollfactor; + + void updateScrolling(); +}; diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 7223ce05c..4b7345b15 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -237,6 +237,7 @@ with this program; if not, write to the Free Software Foundation, Inc., Formspec elements are drawn in the order of definition bgcolor[]: use 3 parameters (bgcolor, formspec (now an enum), fbgcolor) box[] and image[] elements enable clipping by default + new element: scroll_container[] */ #define FORMSPEC_API_VERSION 3 -- cgit v1.2.3 From 27d611fe5561db20b380a16fdc6bcf1fefaf5d39 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Mon, 13 Apr 2020 10:53:10 +0200 Subject: Add default stack size setting (#8873) New setting "default_stack_max" to alter the default stack sizes of all items when desired. Co-authored-by: Pascal Abresch --- builtin/game/item.lua | 8 +++++--- builtin/settingtypes.txt | 4 ++++ doc/lua_api.txt | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/builtin/game/item.lua b/builtin/game/item.lua index 513c3a5e1..3aaa71ef2 100644 --- a/builtin/game/item.lua +++ b/builtin/game/item.lua @@ -675,6 +675,8 @@ end -- Item definition defaults -- +local default_stack_max = tonumber(minetest.settings:get("default_stack_max")) or 99 + core.nodedef_default = { -- Item properties type="node", @@ -684,7 +686,7 @@ core.nodedef_default = { inventory_image = "", wield_image = "", wield_scale = {x=1,y=1,z=1}, - stack_max = 99, + stack_max = default_stack_max, usable = false, liquids_pointable = false, tool_capabilities = nil, @@ -748,7 +750,7 @@ core.craftitemdef_default = { inventory_image = "", wield_image = "", wield_scale = {x=1,y=1,z=1}, - stack_max = 99, + stack_max = default_stack_max, liquids_pointable = false, tool_capabilities = nil, @@ -786,7 +788,7 @@ core.noneitemdef_default = { -- This is used for the hand and unknown items inventory_image = "", wield_image = "", wield_scale = {x=1,y=1,z=1}, - stack_max = 99, + stack_max = default_stack_max, liquids_pointable = false, tool_capabilities = nil, diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 101b32a24..b9228f384 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1079,6 +1079,10 @@ map-dir (Map directory) path # Setting it to -1 disables the feature. item_entity_ttl (Item entity TTL) int 900 +# Specifies the default stack size of nodes, items and tools. +# Note that mods or games may explicitly set a stack for certain (or all) items. +default_stack_max (Default stack size) int 99 + # Enable players getting damage and dying. enable_damage (Damage) bool false diff --git a/doc/lua_api.txt b/doc/lua_api.txt index f43987cd8..ccb605c8e 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6735,6 +6735,8 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and wield_scale = {x = 1, y = 1, z = 1}, + -- The default value of 99 may be configured by + -- users using the setting "default_stack_max" stack_max = 99, range = 4.0, -- cgit v1.2.3 From 5cf6318117edcae6bf30d829d9e9dd9dbf1d4bf7 Mon Sep 17 00:00:00 2001 From: Hugues Ross Date: Tue, 14 Apr 2020 14:41:29 -0400 Subject: Refactor texture overrides and add new features (#9600) * Refactor texture overrides, and add new features: - Texture overrides can support multiple targets in one line - Texture override files can have comment lines - Item images/wield images can be overridden * Formatting changes * Address soime feedback - Pass vectors by const reference - Log syntax errors as warnings - Remove 'C' prefix from TextureOverrideSource * Simplify override target checks with an inline helper function * make linter happy * Apply feedback suggestions Co-Authored-By: rubenwardy * Remove remaining != 0 checks * Update copyright notice Co-authored-by: sfan5 Co-authored-by: rubenwardy --- doc/texture_packs.txt | 45 +++++++++---- src/CMakeLists.txt | 1 + src/client/client.cpp | 7 +- src/itemdef.cpp | 19 ++++++ src/itemdef.h | 5 ++ src/nodedef.cpp | 67 ++++++------------ src/nodedef.h | 12 ++-- src/server.cpp | 7 +- src/texture_override.cpp | 120 +++++++++++++++++++++++++++++++++ src/texture_override.h | 72 ++++++++++++++++++++ util/travis/clang-format-whitelist.txt | 1 + 11 files changed, 285 insertions(+), 71 deletions(-) create mode 100644 src/texture_override.cpp create mode 100644 src/texture_override.h (limited to 'doc') diff --git a/doc/texture_packs.txt b/doc/texture_packs.txt index 7ab0aca94..4e7bc93c4 100644 --- a/doc/texture_packs.txt +++ b/doc/texture_packs.txt @@ -145,34 +145,51 @@ are placeholders intended to be overwritten by the game. Texture Overrides ----------------- -You can override the textures of a node from a texture pack using -texture overrides. To do this, create a file in a texture pack -called override.txt +You can override the textures of nodes and items from a +texture pack using texture overrides. To do this, create one or +more files in a texture pack called override.txt Each line in an override.txt file is a rule. It consists of - nodename face-selector texture + itemname target texture For example, default:dirt_with_grass sides default_stone.png -You can use ^ operators as usual: +or + + default:sword_steel inventory my_steel_sword.png + +You can list multiple targets on one line as a comma-separated list: + + default:tree top,bottom my_special_tree.png + +You can use texture modifiers, as usual: default:dirt_with_grass sides default_stone.png^[brighten -Here are face selectors you can choose from: +Finally, if a line is empty or starts with '#' it will be considered +a comment and not read as a rule. You can use this to better organize +your override.txt files. + +Here are targets you can choose from: -| face-selector | behavior | +| target | behavior | |---------------|---------------------------------------------------| -| left | x- | -| right | x+ | -| front | z- | -| back | z+ | -| top | y+ | -| bottom | y- | -| sides | x-, x+, z-, z+ | +| left | x- face | +| right | x+ face | +| front | z- face | +| back | z+ face | +| top | y+ face | +| bottom | y- face | +| sides | x-, x+, z-, z+ faces | | all | All faces. You can also use '*' instead of 'all'. | +| inventory | The inventory texture | +| wield | The texture used when held by the player | + +Nodes support all targets, but other items only support 'inventory' +and 'wield' Designing leaves textures for the leaves rendering options ---------------------------------------------------------- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0b550c09c..fa261547b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -423,6 +423,7 @@ set(common_SRCS settings.cpp staticobject.cpp terminal_chat_console.cpp + texture_override.cpp tileanimation.cpp tool.cpp translation.cpp diff --git a/src/client/client.cpp b/src/client/client.cpp index c3e2a4d2a..8ee0869cd 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -1742,8 +1742,11 @@ void Client::afterContentReceived() text = wgettext("Initializing nodes..."); RenderingEngine::draw_load_screen(text, guienv, m_tsrc, 0, 72); m_nodedef->updateAliases(m_itemdef); - for (const auto &path : getTextureDirs()) - m_nodedef->applyTextureOverrides(path + DIR_DELIM + "override.txt"); + for (const auto &path : getTextureDirs()) { + TextureOverrideSource override_source(path + DIR_DELIM + "override.txt"); + m_nodedef->applyTextureOverrides(override_source.getNodeTileOverrides()); + m_itemdef->applyTextureOverrides(override_source.getItemTextureOverrides()); + } m_nodedef->setNodeRegistrationStatus(true); m_nodedef->runNodeResolveCallbacks(); delete[] text; diff --git a/src/itemdef.cpp b/src/itemdef.cpp index ba7bd6a0b..a13b3f7d4 100644 --- a/src/itemdef.cpp +++ b/src/itemdef.cpp @@ -422,6 +422,25 @@ public: return get(stack.name).color; } #endif + void applyTextureOverrides(const std::vector &overrides) + { + infostream << "ItemDefManager::applyTextureOverrides(): Applying " + "overrides to textures" << std::endl; + + for (const TextureOverride& texture_override : overrides) { + if (m_item_definitions.find(texture_override.id) == m_item_definitions.end()) { + continue; // Ignore unknown item + } + + ItemDefinition* itemdef = m_item_definitions[texture_override.id]; + + if (texture_override.hasTarget(OverrideTarget::INVENTORY)) + itemdef->inventory_image = texture_override.texture; + + if (texture_override.hasTarget(OverrideTarget::WIELD)) + itemdef->wield_image = texture_override.texture; + } + } void clear() { for(std::map::const_iterator diff --git a/src/itemdef.h b/src/itemdef.h index 45cff582a..f47e6cbe7 100644 --- a/src/itemdef.h +++ b/src/itemdef.h @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "itemgroup.h" #include "sound.h" +#include "texture_override.h" // TextureOverride class IGameDef; class Client; struct ToolCapabilities; @@ -157,6 +158,10 @@ public: Client *client) const=0; #endif + // Replace the textures of registered nodes with the ones specified in + // the texture pack's override.txt files + virtual void applyTextureOverrides(const std::vector &overrides)=0; + // Remove all registered item and node definitions and aliases // Then re-add the builtin item definitions virtual void clear()=0; diff --git a/src/nodedef.cpp b/src/nodedef.cpp index b6eca9497..37332c3c6 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -1304,60 +1304,35 @@ void NodeDefManager::updateAliases(IItemDefManager *idef) } } -void NodeDefManager::applyTextureOverrides(const std::string &override_filepath) +void NodeDefManager::applyTextureOverrides(const std::vector &overrides) { infostream << "NodeDefManager::applyTextureOverrides(): Applying " - "overrides to textures from " << override_filepath << std::endl; - - std::ifstream infile(override_filepath.c_str()); - std::string line; - int line_c = 0; - while (std::getline(infile, line)) { - line_c++; - // Also trim '\r' on DOS-style files - line = trim(line); - if (line.empty()) - continue; - - std::vector splitted = str_split(line, ' '); - if (splitted.size() != 3) { - errorstream << override_filepath - << ":" << line_c << " Could not apply texture override \"" - << line << "\": Syntax error" << std::endl; - continue; - } + "overrides to textures" << std::endl; + for (const TextureOverride& texture_override : overrides) { content_t id; - if (!getId(splitted[0], id)) + if (!getId(texture_override.id, id)) continue; // Ignore unknown node ContentFeatures &nodedef = m_content_features[id]; - if (splitted[1] == "top") - nodedef.tiledef[0].name = splitted[2]; - else if (splitted[1] == "bottom") - nodedef.tiledef[1].name = splitted[2]; - else if (splitted[1] == "right") - nodedef.tiledef[2].name = splitted[2]; - else if (splitted[1] == "left") - nodedef.tiledef[3].name = splitted[2]; - else if (splitted[1] == "back") - nodedef.tiledef[4].name = splitted[2]; - else if (splitted[1] == "front") - nodedef.tiledef[5].name = splitted[2]; - else if (splitted[1] == "all" || splitted[1] == "*") - for (TileDef &i : nodedef.tiledef) - i.name = splitted[2]; - else if (splitted[1] == "sides") - for (int i = 2; i < 6; i++) - nodedef.tiledef[i].name = splitted[2]; - else { - errorstream << override_filepath - << ":" << line_c << " Could not apply texture override \"" - << line << "\": Unknown node side \"" - << splitted[1] << "\"" << std::endl; - continue; - } + if (texture_override.hasTarget(OverrideTarget::TOP)) + nodedef.tiledef[0].name = texture_override.texture; + + if (texture_override.hasTarget(OverrideTarget::BOTTOM)) + nodedef.tiledef[1].name = texture_override.texture; + + if (texture_override.hasTarget(OverrideTarget::RIGHT)) + nodedef.tiledef[2].name = texture_override.texture; + + if (texture_override.hasTarget(OverrideTarget::LEFT)) + nodedef.tiledef[3].name = texture_override.texture; + + if (texture_override.hasTarget(OverrideTarget::BACK)) + nodedef.tiledef[4].name = texture_override.texture; + + if (texture_override.hasTarget(OverrideTarget::FRONT)) + nodedef.tiledef[5].name = texture_override.texture; } } diff --git a/src/nodedef.h b/src/nodedef.h index 1a12aae93..c77d53324 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -33,6 +33,7 @@ class Client; #include "itemgroup.h" #include "sound.h" // SimpleSoundSpec #include "constants.h" // BS +#include "texture_override.h" // TextureOverride #include "tileanimation.h" // PROTOCOL_VERSION >= 37 @@ -583,15 +584,12 @@ public: void updateAliases(IItemDefManager *idef); /*! - * Reads the used texture pack's override.txt, and replaces the textures - * of registered nodes with the ones specified there. + * Replaces the textures of registered nodes with the ones specified in + * the texturepack's override.txt file * - * Format of the input file: in each line - * `node_name top|bottom|right|left|front|back|all|*|sides texture_name.png` - * - * @param override_filepath path to 'texturepack/override.txt' + * @param overrides the texture overrides */ - void applyTextureOverrides(const std::string &override_filepath); + void applyTextureOverrides(const std::vector &overrides); /*! * Only the client uses this. Loads textures and shaders required for diff --git a/src/server.cpp b/src/server.cpp index 85d07fbc4..b3992b9b1 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -373,8 +373,11 @@ void Server::init() std::vector paths; fs::GetRecursiveDirs(paths, g_settings->get("texture_path")); fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures"); - for (const std::string &path : paths) - m_nodedef->applyTextureOverrides(path + DIR_DELIM + "override.txt"); + for (const std::string &path : paths) { + TextureOverrideSource override_source(path + DIR_DELIM + "override.txt"); + m_nodedef->applyTextureOverrides(override_source.getNodeTileOverrides()); + m_itemdef->applyTextureOverrides(override_source.getItemTextureOverrides()); + } m_nodedef->setNodeRegistrationStatus(true); diff --git a/src/texture_override.cpp b/src/texture_override.cpp new file mode 100644 index 000000000..10d129b87 --- /dev/null +++ b/src/texture_override.cpp @@ -0,0 +1,120 @@ +/* +Minetest +Copyright (C) 2020 Hugues Ross + +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 "texture_override.h" + +#include "log.h" +#include "util/string.h" +#include +#include + +TextureOverrideSource::TextureOverrideSource(std::string filepath) +{ + std::ifstream infile(filepath.c_str()); + std::string line; + int line_index = 0; + while (std::getline(infile, line)) { + line_index++; + + // Also trim '\r' on DOS-style files + line = trim(line); + + // Ignore empty lines and comments + if (line.empty() || line[0] == '#') + continue; + + std::vector splitted = str_split(line, ' '); + if (splitted.size() != 3) { + warningstream << filepath << ":" << line_index + << " Syntax error in texture override \"" << line + << "\": Expected 3 arguments, got " << splitted.size() + << std::endl; + continue; + } + + TextureOverride texture_override = {}; + texture_override.id = splitted[0]; + texture_override.texture = splitted[2]; + + // Parse the target mask + std::vector targets = str_split(splitted[1], ','); + for (const std::string &target : targets) { + if (target == "top") + texture_override.target |= static_cast(OverrideTarget::TOP); + else if (target == "bottom") + texture_override.target |= static_cast(OverrideTarget::BOTTOM); + else if (target == "left") + texture_override.target |= static_cast(OverrideTarget::LEFT); + else if (target == "right") + texture_override.target |= static_cast(OverrideTarget::RIGHT); + else if (target == "front") + texture_override.target |= static_cast(OverrideTarget::FRONT); + else if (target == "back") + texture_override.target |= static_cast(OverrideTarget::BACK); + else if (target == "inventory") + texture_override.target |= static_cast(OverrideTarget::INVENTORY); + else if (target == "wield") + texture_override.target |= static_cast(OverrideTarget::WIELD); + else if (target == "sides") + texture_override.target |= static_cast(OverrideTarget::SIDES); + else if (target == "all" || target == "*") + texture_override.target |= static_cast(OverrideTarget::ALL_FACES); + else { + // Report invalid target + warningstream << filepath << ":" << line_index + << " Syntax error in texture override \"" << line + << "\": Unknown target \"" << target << "\"" + << std::endl; + } + } + + // If there are no valid targets, skip adding this override + if (texture_override.target == static_cast(OverrideTarget::INVALID)) { + continue; + } + + m_overrides.push_back(texture_override); + } +} + +//! Get all overrides that apply to item definitions +std::vector TextureOverrideSource::getItemTextureOverrides() +{ + std::vector found_overrides; + + for (const TextureOverride &texture_override : m_overrides) { + if (texture_override.hasTarget(OverrideTarget::ITEM_TARGETS)) + found_overrides.push_back(texture_override); + } + + return found_overrides; +} + +//! Get all overrides that apply to node definitions +std::vector TextureOverrideSource::getNodeTileOverrides() +{ + std::vector found_overrides; + + for (const TextureOverride &texture_override : m_overrides) { + if (texture_override.hasTarget(OverrideTarget::ALL_FACES)) + found_overrides.push_back(texture_override); + } + + return found_overrides; +} diff --git a/src/texture_override.h b/src/texture_override.h new file mode 100644 index 000000000..db03bd014 --- /dev/null +++ b/src/texture_override.h @@ -0,0 +1,72 @@ +/* +Minetest +Copyright (C) 2020 Hugues Ross + +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 "irrlichttypes.h" +#include +#include + +//! Bitmask enum specifying what a texture override should apply to +enum class OverrideTarget : u8 +{ + INVALID = 0, + TOP = 1 << 0, + BOTTOM = 1 << 1, + LEFT = 1 << 2, + RIGHT = 1 << 3, + FRONT = 1 << 4, + BACK = 1 << 5, + INVENTORY = 1 << 6, + WIELD = 1 << 7, + + SIDES = LEFT | RIGHT | FRONT | BACK, + ALL_FACES = TOP | BOTTOM | SIDES, + ITEM_TARGETS = INVENTORY | WIELD, +}; + +struct TextureOverride +{ + std::string id; + std::string texture; + u8 target; + + // Helper function for checking if an OverrideTarget is found in + // a TextureOverride without casting + inline bool hasTarget(OverrideTarget overrideTarget) const + { + return (target & static_cast(overrideTarget)) != 0; + } +}; + +//! Class that provides texture override information from a texture pack +class TextureOverrideSource +{ +public: + TextureOverrideSource(std::string filepath); + + //! Get all overrides that apply to item definitions + std::vector getItemTextureOverrides(); + + //! Get all overrides that apply to node definitions + std::vector getNodeTileOverrides(); + +private: + std::vector m_overrides; +}; diff --git a/util/travis/clang-format-whitelist.txt b/util/travis/clang-format-whitelist.txt index bb97da7b5..02c8b2660 100644 --- a/util/travis/clang-format-whitelist.txt +++ b/util/travis/clang-format-whitelist.txt @@ -423,6 +423,7 @@ src/subgame.cpp src/subgame.h src/terminal_chat_console.cpp src/terminal_chat_console.h +src/texture_override.cpp src/threading/atomic.h src/threading/event.cpp src/threading/mutex_auto_lock.h -- cgit v1.2.3 From 62c62f382984bd1a6f5cd7c6edb00453ff758f9b Mon Sep 17 00:00:00 2001 From: DS Date: Tue, 14 Apr 2020 21:22:49 +0200 Subject: Add all src folders to doxygen (#9603) --- doc/Doxyfile.in | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'doc') diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 3618b852d..d7816f0e4 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -20,18 +20,10 @@ PREDEFINED = "USE_SPATIAL=1" \ "USE_GETTEXT=1" # Input -RECURSIVE = NO +RECURSIVE = YES STRIP_FROM_PATH = @CMAKE_CURRENT_SOURCE_DIR@/src INPUT = @CMAKE_CURRENT_SOURCE_DIR@/doc/main_page.dox \ - @CMAKE_CURRENT_SOURCE_DIR@/src/ \ - @CMAKE_CURRENT_SOURCE_DIR@/src/client \ - @CMAKE_CURRENT_SOURCE_DIR@/src/network \ - @CMAKE_CURRENT_SOURCE_DIR@/src/util \ - @CMAKE_CURRENT_SOURCE_DIR@/src/script \ - @CMAKE_CURRENT_SOURCE_DIR@/src/script/common \ - @CMAKE_CURRENT_SOURCE_DIR@/src/script/cpp_api \ - @CMAKE_CURRENT_SOURCE_DIR@/src/script/lua_api \ - @CMAKE_CURRENT_SOURCE_DIR@/src/threading + @CMAKE_CURRENT_SOURCE_DIR@/src/ # Dot graphs HAVE_DOT = @DOXYGEN_DOT_FOUND@ -- cgit v1.2.3 From 62ae7adab2bebde04864c12543caefbffab24963 Mon Sep 17 00:00:00 2001 From: Maksim Date: Wed, 15 Apr 2020 16:27:40 +0200 Subject: Android: add Android Studio support, completely redone java part (#9066) --- .gitignore | 20 +- build/android/.gitignore | 11 + build/android/Makefile | 763 --------------------- build/android/app/build.gradle | 108 +++ build/android/app/src/main/AndroidManifest.xml | 60 ++ .../java/net/minetest/minetest/CopyZipTask.java | 82 +++ .../java/net/minetest/minetest/GameActivity.java | 120 ++++ .../net/minetest/minetest/InputDialogActivity.java | 98 +++ .../java/net/minetest/minetest/MainActivity.java | 139 ++++ .../java/net/minetest/minetest/UnzipService.java | 153 +++++ .../app/src/main/res/drawable/background.png | Bin 0 -> 83 bytes build/android/app/src/main/res/drawable/bg.xml | 4 + .../app/src/main/res/layout/activity_main.xml | 30 + .../app/src/main/res/mipmap/ic_launcher.png | Bin 0 -> 5780 bytes build/android/app/src/main/res/values/strings.xml | 10 + build/android/app/src/main/res/values/styles.xml | 22 + build/android/build.gradle | 175 +---- build/android/gradle.properties | 11 +- build/android/gradle/wrapper/gradle-wrapper.jar | Bin 54731 -> 55616 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- build/android/gradlew | 22 +- build/android/gradlew.bat | 18 +- build/android/jni/Android.mk | 448 ------------ build/android/jni/Application.mk | 9 - build/android/jni/Deps.mk | 7 - build/android/jni/Irrlicht.mk | 8 - build/android/native/build.gradle | 59 ++ build/android/native/jni/Android.mk | 218 ++++++ build/android/native/jni/Application.mk | 32 + build/android/native/src/main/AndroidManifest.xml | 1 + build/android/patches/irrlicht-back_button.patch | 20 - .../android/patches/irrlicht-native_activity.patch | 13 - build/android/patches/irrlicht-texturehack.patch | 240 ------- build/android/patches/irrlicht-touchcount.patch | 30 - build/android/patches/libvorbis-libogg-fpu.patch | 37 - build/android/patches/openssl_arch.patch | 13 - build/android/settings.gradle | 1 + build/android/src/main/AndroidManifest.xml | 60 -- .../java/net.minetest.minetest/MainActivity.java | 77 --- .../net.minetest.minetest/MinetestAssetCopy.java | 371 ---------- .../net.minetest.minetest/MinetestTextEntry.java | 87 --- .../net.minetest.minetest/MtNativeActivity.java | 108 --- build/android/src/main/res/drawable/background.png | Bin 83 -> 0 bytes build/android/src/main/res/drawable/bg.xml | 4 - build/android/src/main/res/layout/assetcopy.xml | 24 - build/android/src/main/res/mipmap/ic_launcher.png | Bin 5780 -> 0 bytes build/android/src/main/res/values-v21/styles.xml | 17 - build/android/src/main/res/values/strings.xml | 5 - build/android/src/main/res/values/styles.xml | 14 - doc/README.android | 75 +- src/config.h | 6 +- src/main.cpp | 1 - src/porting_android.cpp | 17 +- src/porting_android.h | 5 - src/version.cpp | 5 +- 55 files changed, 1235 insertions(+), 2626 deletions(-) create mode 100644 build/android/.gitignore delete mode 100644 build/android/Makefile create mode 100644 build/android/app/build.gradle create mode 100644 build/android/app/src/main/AndroidManifest.xml create mode 100644 build/android/app/src/main/java/net/minetest/minetest/CopyZipTask.java create mode 100644 build/android/app/src/main/java/net/minetest/minetest/GameActivity.java create mode 100644 build/android/app/src/main/java/net/minetest/minetest/InputDialogActivity.java create mode 100644 build/android/app/src/main/java/net/minetest/minetest/MainActivity.java create mode 100644 build/android/app/src/main/java/net/minetest/minetest/UnzipService.java create mode 100644 build/android/app/src/main/res/drawable/background.png create mode 100644 build/android/app/src/main/res/drawable/bg.xml create mode 100644 build/android/app/src/main/res/layout/activity_main.xml create mode 100644 build/android/app/src/main/res/mipmap/ic_launcher.png create mode 100644 build/android/app/src/main/res/values/strings.xml create mode 100644 build/android/app/src/main/res/values/styles.xml delete mode 100644 build/android/jni/Android.mk delete mode 100644 build/android/jni/Application.mk delete mode 100644 build/android/jni/Deps.mk delete mode 100644 build/android/jni/Irrlicht.mk create mode 100644 build/android/native/build.gradle create mode 100644 build/android/native/jni/Android.mk create mode 100644 build/android/native/jni/Application.mk create mode 100644 build/android/native/src/main/AndroidManifest.xml delete mode 100644 build/android/patches/irrlicht-back_button.patch delete mode 100644 build/android/patches/irrlicht-native_activity.patch delete mode 100644 build/android/patches/irrlicht-texturehack.patch delete mode 100644 build/android/patches/irrlicht-touchcount.patch delete mode 100644 build/android/patches/libvorbis-libogg-fpu.patch delete mode 100644 build/android/patches/openssl_arch.patch delete mode 100644 build/android/src/main/AndroidManifest.xml delete mode 100644 build/android/src/main/java/net.minetest.minetest/MainActivity.java delete mode 100644 build/android/src/main/java/net.minetest.minetest/MinetestAssetCopy.java delete mode 100644 build/android/src/main/java/net.minetest.minetest/MinetestTextEntry.java delete mode 100644 build/android/src/main/java/net.minetest.minetest/MtNativeActivity.java delete mode 100644 build/android/src/main/res/drawable/background.png delete mode 100644 build/android/src/main/res/drawable/bg.xml delete mode 100644 build/android/src/main/res/layout/assetcopy.xml delete mode 100644 build/android/src/main/res/mipmap/ic_launcher.png delete mode 100644 build/android/src/main/res/values-v21/styles.xml delete mode 100644 build/android/src/main/res/values/strings.xml delete mode 100644 build/android/src/main/res/values/styles.xml (limited to 'doc') diff --git a/.gitignore b/.gitignore index aae9bf437..9ab69b30e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.swp *.bak* *.orig +.DS_Store # Vim *.vim # Kate @@ -77,17 +78,11 @@ doc/mkdocs/mkdocs.yml ## Build files CMakeFiles Makefile -!build/android/Makefile -build/android/path.cfg -build/android/*.apk -build/android/.externalNativeBuild cmake_install.cmake CMakeCache.txt CPackConfig.cmake CPackSourceConfig.cmake src/test_config.h -src/android_version.h -src/android_version_githash.h src/cmake_config.h src/cmake_config_githash.h src/unittest/test_world/world.mt @@ -109,16 +104,3 @@ cmake_config.h cmake_config_githash.h CMakeDoxy* compile_commands.json - -## Android build files -build/android/src/main/assets -build/android/build -build/android/deps -build/android/libs -build/android/jni/lib -build/android/jni/src -build/android/src/main/jniLibs -build/android/obj -build/android/local.properties -build/android/.gradle -timestamp diff --git a/build/android/.gitignore b/build/android/.gitignore new file mode 100644 index 000000000..e0613f8b3 --- /dev/null +++ b/build/android/.gitignore @@ -0,0 +1,11 @@ +*.iml +.externalNativeBuild +.gradle +app/build +app/release +app/src/main/assets +build +local.properties +native/.* +native/build +native/deps diff --git a/build/android/Makefile b/build/android/Makefile deleted file mode 100644 index 9ec237a75..000000000 --- a/build/android/Makefile +++ /dev/null @@ -1,763 +0,0 @@ -# build options - -OS := $(shell uname) - -# compile with GPROF -# GPROF = 1 - -# build for build platform -API = 14 -APP_PLATFORM = android-$(API) - -ANDR_ROOT = $(shell pwd) -PROJ_ROOT = $(shell realpath $(ANDR_ROOT)/../..) -APP_ROOT = $(ANDR_ROOT)/src/main - -VERSION_MAJOR := $(shell cat $(PROJ_ROOT)/CMakeLists.txt | \ - grep ^set\(VERSION_MAJOR\ | sed 's/)/ /' | cut -f2 -d' ') -VERSION_MINOR := $(shell cat $(PROJ_ROOT)/CMakeLists.txt | \ - grep ^set\(VERSION_MINOR\ | sed 's/)/ /' | cut -f2 -d' ') -VERSION_PATCH := $(shell cat $(PROJ_ROOT)/CMakeLists.txt | \ - grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | cut -f2 -d' ') - -################################################################################ -# toolchain config for arm new processors -################################################################################ -TARGET_HOST = arm-linux -TARGET_ABI = armeabi-v7a -TARGET_LIBDIR = armeabi-v7a -TARGET_TOOLCHAIN = arm-linux-androideabi- -TARGET_CFLAGS_ADDON = -mfloat-abi=softfp -mfpu=vfpv3 -O3 -TARGET_CXXFLAGS_ADDON = $(TARGET_CFLAGS_ADDON) -TARGET_ARCH = armv7 -CROSS_CC = clang -CROSS_CXX = clang++ -COMPILER_VERSION = clang -HAVE_LEVELDB = 0 - -################################################################################ -# toolchain config for little endian mips -################################################################################ -#TARGET_HOST = mipsel-linux -#TARGET_ABI = mips -#TARGET_LIBDIR = mips -#TARGET_TOOLCHAIN = mipsel-linux-android- -#TARGET_ARCH = mips32 -#CROSS_CC = mipsel-linux-android-gcc -#CROSS_CXX = mipsel-linux-android-g++ -#COMPILER_VERSION = 4.9 -#HAVE_LEVELDB = 0 - -################################################################################ -# toolchain config for x86 -################################################################################ -#TARGET_HOST = x86-linux -#TARGET_ABI = x86 -#TARGET_LIBDIR = x86 -#TARGET_TOOLCHAIN = x86- -#TARGET_ARCH = x86 -#CROSS_CC = clang -#CROSS_CXX = clang++ -#COMPILER_VERSION = clang -#HAVE_LEVELDB = 0 - -################################################################################ -ASSETS_TIMESTAMP = deps/assets_timestamp - -LEVELDB_DIR = $(ANDR_ROOT)/deps/leveldb/ -LEVELDB_LIB = $(LEVELDB_DIR)libleveldb.a -LEVELDB_TIMESTAMP = $(LEVELDB_DIR)/timestamp -LEVELDB_TIMESTAMP_INT = $(ANDR_ROOT)/deps/leveldb_timestamp -LEVELDB_URL_GIT = https://github.com/google/leveldb -LEVELDB_COMMIT = 2d0320a458d0e6a20fff46d5f80b18bfdcce7018 - -OPENAL_DIR = $(ANDR_ROOT)/deps/openal-soft/ -OPENAL_LIB = $(OPENAL_DIR)libs/$(TARGET_ABI)/libopenal.so -OPENAL_TIMESTAMP = $(OPENAL_DIR)/timestamp -OPENAL_TIMESTAMP_INT = $(ANDR_ROOT)/deps/openal_timestamp -OPENAL_URL_GIT = https://github.com/apportable/openal-soft - -OGG_DIR = $(ANDR_ROOT)/deps/libvorbis-libogg-android/ -OGG_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so -VORBIS_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so -OGG_TIMESTAMP = $(OGG_DIR)timestamp -OGG_TIMESTAMP_INT = $(ANDR_ROOT)/deps/ogg_timestamp -OGG_URL_GIT = https://gitlab.com/minetest/libvorbis-libogg-android - -IRRLICHT_REVISION = 5150 -IRRLICHT_DIR = $(ANDR_ROOT)/deps/irrlicht/ -IRRLICHT_LIB = $(IRRLICHT_DIR)lib/Android/libIrrlicht.a -IRRLICHT_TIMESTAMP = $(IRRLICHT_DIR)timestamp -IRRLICHT_TIMESTAMP_INT = $(ANDR_ROOT)/deps/irrlicht_timestamp -IRRLICHT_URL_SVN = https://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@$(IRRLICHT_REVISION) - -OPENSSL_VERSION = 1.0.2n -OPENSSL_BASEDIR = openssl-$(OPENSSL_VERSION) -OPENSSL_DIR = $(ANDR_ROOT)/deps/$(OPENSSL_BASEDIR)/ -OPENSSL_LIB = $(OPENSSL_DIR)/libssl.a -OPENSSL_TIMESTAMP = $(OPENSSL_DIR)timestamp -OPENSSL_TIMESTAMP_INT = $(ANDR_ROOT)/deps/openssl_timestamp -OPENSSL_URL = https://www.openssl.org/source/openssl-$(OPENSSL_VERSION).tar.gz - -CURL_VERSION = 7.60.0 -CURL_DIR = $(ANDR_ROOT)/deps/curl-$(CURL_VERSION) -CURL_LIB = $(CURL_DIR)/lib/.libs/libcurl.a -CURL_TIMESTAMP = $(CURL_DIR)/timestamp -CURL_TIMESTAMP_INT = $(ANDR_ROOT)/deps/curl_timestamp -CURL_URL_HTTP = https://curl.haxx.se/download/curl-${CURL_VERSION}.tar.bz2 - -FREETYPE_DIR = $(ANDR_ROOT)/deps/freetype2-android/ -FREETYPE_LIB = $(FREETYPE_DIR)/Android/obj/local/$(TARGET_ABI)/libfreetype2-static.a -FREETYPE_TIMESTAMP = $(FREETYPE_DIR)timestamp -FREETYPE_TIMESTAMP_INT = $(ANDR_ROOT)/deps/freetype_timestamp -FREETYPE_URL_GIT = https://github.com/cdave1/freetype2-android - -ICONV_VERSION = 1.16 -ICONV_DIR = $(ANDR_ROOT)/deps/libiconv/ -ICONV_LIB = $(ICONV_DIR)/lib/.libs/libiconv.so -ICONV_TIMESTAMP = $(ICONV_DIR)timestamp -ICONV_TIMESTAMP_INT = $(ANDR_ROOT)/deps/iconv_timestamp -ICONV_URL_HTTP = https://ftp.gnu.org/pub/gnu/libiconv/libiconv-$(ICONV_VERSION).tar.gz - -SQLITE3_FOLDER = sqlite-amalgamation-3240000 -SQLITE3_URL = https://www.sqlite.org/2018/$(SQLITE3_FOLDER).zip - -ANDROID_SDK = $(shell grep '^sdk\.dir' local.properties | sed 's/^.*=[[:space:]]*//') -ANDROID_NDK = $(shell grep '^ndk\.dir' local.properties | sed 's/^.*=[[:space:]]*//') - -#use interim target variable to switch leveldb on or off -ifeq ($(HAVE_LEVELDB),1) - LEVELDB_TARGET = $(LEVELDB_LIB) -endif - -.PHONY : debug release reconfig delconfig \ - leveldb_download clean_leveldb leveldb\ - irrlicht_download clean_irrlicht irrlicht \ - clean_assets assets sqlite3_download \ - freetype_download clean_freetype freetype \ - apk clean_apk \ - clean_all clean prep_srcdir \ - install_debug install_release envpaths all \ - $(ASSETS_TIMESTAMP) $(LEVELDB_TIMESTAMP) \ - $(OPENAL_TIMESTAMP) $(OGG_TIMESTAMP) \ - $(IRRLICHT_TIMESTAMP) $(CURL_TIMESTAMP) \ - $(OPENSSL_TIMESTAMP) \ - $(ANDR_ROOT)/jni/src/android_version.h \ - $(ANDR_ROOT)/jni/src/android_version_githash.h - -debug : local.properties - export NDEBUG=; \ - export BUILD_TYPE=debug; \ - $(MAKE) apk - -all : debug release - -release : local.properties - @export NDEBUG=1; \ - export BUILD_TYPE=release; \ - $(MAKE) apk - -reconfig: delconfig - @$(MAKE) local.properties - -delconfig: - $(RM) local.properties - -local.properties: - @echo "Please specify path of ANDROID NDK"; \ - echo "e.g. $$HOME/Android/Sdk/ndk-bundle/"; \ - read ANDROID_NDK ; \ - if [ ! -d $$ANDROID_NDK ] ; then \ - echo "$$ANDROID_NDK is not a valid folder"; \ - exit 1; \ - fi; \ - echo "ndk.dir = $$ANDROID_NDK" > local.properties; \ - echo "Please specify path of ANDROID SDK"; \ - echo "e.g. $$HOME/Android/Sdk/"; \ - read SDKFLDR ; \ - if [ ! -d $$SDKFLDR ] ; then \ - echo "$$SDKFLDR is not a valid folder"; \ - exit 1; \ - fi; \ - echo "sdk.dir = $$SDKFLDR" >> local.properties; - - -$(OPENAL_TIMESTAMP) : openal_download - @LAST_MODIF=$$(find ${OPENAL_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ - if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ - touch ${OPENAL_TIMESTAMP}; \ - fi - -openal_download : - @if [ ! -d ${OPENAL_DIR} ] ; then \ - echo "openal sources missing, downloading..."; \ - mkdir -p ${ANDR_ROOT}/deps; \ - cd ${ANDR_ROOT}/deps ; \ - git clone ${OPENAL_URL_GIT} || exit 1; \ - fi - -openal : $(OPENAL_LIB) - -$(OPENAL_LIB): $(OPENAL_TIMESTAMP) - + @REFRESH=0; \ - if [ ! -e ${OPENAL_TIMESTAMP_INT} ] ; then \ - REFRESH=1; \ - fi; \ - if [ ${OPENAL_TIMESTAMP} -nt ${OPENAL_TIMESTAMP_INT} ] ; then \ - REFRESH=1; \ - fi; \ - if [ $$REFRESH -ne 0 ] ; then \ - echo "changed timestamp for openal detected building..."; \ - cd ${OPENAL_DIR}; \ - export APP_PLATFORM=${APP_PLATFORM}; \ - export TARGET_ABI=${TARGET_ABI}; \ - export TARGET_CFLAGS_ADDON="${TARGET_CFLAGS_ADDON}"; \ - export TARGET_CXXFLAGS_ADDON="${TARGET_CXXFLAGS_ADDON}"; \ - export COMPILER_VERSION=${COMPILER_VERSION}; \ - ${ANDROID_NDK}/ndk-build \ - NDK_APPLICATION_MK=${ANDR_ROOT}/jni/Deps.mk || exit 1; \ - touch ${OPENAL_TIMESTAMP}; \ - touch ${OPENAL_TIMESTAMP_INT}; \ - else \ - echo "nothing to be done for openal"; \ - fi - -clean_openal : - $(RM) -rf ${OPENAL_DIR} - -$(OGG_TIMESTAMP) : ogg_download - @LAST_MODIF=$$(find ${OGG_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ - if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ - touch ${OGG_TIMESTAMP}; \ - fi - -ogg_download : - @if [ ! -d ${OGG_DIR} ] ; then \ - echo "ogg sources missing, downloading..."; \ - mkdir -p ${ANDR_ROOT}/deps; \ - cd ${ANDR_ROOT}/deps ; \ - git clone ${OGG_URL_GIT}|| exit 1; \ - cd libvorbis-libogg-android ; \ - patch -p1 < ${ANDR_ROOT}/patches/libvorbis-libogg-fpu.patch || exit 1; \ - fi - -ogg : $(OGG_LIB) - -$(OGG_LIB): $(OGG_TIMESTAMP) - + @REFRESH=0; \ - if [ ! -e ${OGG_TIMESTAMP_INT} ] ; then \ - echo "${OGG_TIMESTAMP_INT} doesn't exist"; \ - REFRESH=1; \ - fi; \ - if [ ${OGG_TIMESTAMP} -nt ${OGG_TIMESTAMP_INT} ] ; then \ - REFRESH=1; \ - fi; \ - if [ $$REFRESH -ne 0 ] ; then \ - echo "changed timestamp for ogg detected building..."; \ - cd ${OGG_DIR}; \ - export APP_PLATFORM=${APP_PLATFORM}; \ - export TARGET_ABI=${TARGET_ABI}; \ - ${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \ - --toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \ - --platform=${APP_PLATFORM} \ - --install-dir=$${TOOLCHAIN}; \ - touch ${OGG_TIMESTAMP}; \ - touch ${OGG_TIMESTAMP_INT}; \ - else \ - echo "nothing to be done for libogg/libvorbis"; \ - fi - -clean_ogg : - $(RM) -rf ${OGG_DIR} - -$(OPENSSL_TIMESTAMP) : openssl_download - @LAST_MODIF=$$(find ${OPENSSL_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ - if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ - touch ${OPENSSL_TIMESTAMP}; \ - fi - -openssl_download : - @if [ ! -d ${OPENSSL_DIR} ] ; then \ - echo "openssl sources missing, downloading..."; \ - mkdir -p ${ANDR_ROOT}/deps; \ - cd ${ANDR_ROOT}/deps ; \ - wget ${OPENSSL_URL} || exit 1; \ - tar -xzf ${OPENSSL_BASEDIR}.tar.gz; \ - cd ${OPENSSL_BASEDIR}; \ - patch -p1 < ${ANDR_ROOT}/patches/openssl_arch.patch; \ - sed -i 's/-mandroid //g' Configure; \ - fi - -openssl : $(OPENSSL_LIB) - -$(OPENSSL_LIB): $(OPENSSL_TIMESTAMP) - @REFRESH=0; \ - if [ ! -e ${OPENSSL_TIMESTAMP_INT} ] ; then \ - echo "${OPENSSL_TIMESTAMP_INT} doesn't exist"; \ - REFRESH=1; \ - fi; \ - if [ ${OPENSSL_TIMESTAMP} -nt ${OPENSSL_TIMESTAMP_INT} ] ; then \ - REFRESH=1; \ - fi; \ - if [ $$REFRESH -ne 0 ] ; then \ - echo "changed timestamp for openssl detected building..."; \ - cd ${OPENSSL_DIR}; \ - ln -s ${OPENSSL_DIR} ../openssl; \ - export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-openssl; \ - ${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \ - --toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \ - --platform=${APP_PLATFORM} \ - --stl=libc++ \ - --install-dir=$${TOOLCHAIN}; \ - export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \ - export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \ - export LDFLAGS="$${LDFLAGS} ${TARGET_LDFLAGS_ADDON}"; \ - CC=${CROSS_CC} ./Configure -DL_ENDIAN no-asm android-${TARGET_ARCH} \ - -D__ANDROID_API__=$(API); \ - CC=${CROSS_CC} ANDROID_DEV=/tmp/ndk-${TARGET_HOST} make depend; \ - CC=${CROSS_CC} ANDROID_DEV=/tmp/ndk-${TARGET_HOST} make build_libs; \ - touch ${OPENSSL_TIMESTAMP}; \ - touch ${OPENSSL_TIMESTAMP_INT}; \ - $(RM) -rf $${TOOLCHAIN}; \ - else \ - echo "nothing to be done for openssl"; \ - fi - -clean_openssl : - $(RM) -rf ${OPENSSL_DIR}; \ - $(RM) -rf $(ANDR_ROOT)/deps/${OPENSSL_BASEDIR}.tar.gz; \ - $(RM) -rf $(ANDR_ROOT)/deps/openssl - -$(LEVELDB_TIMESTAMP) : leveldb_download - @LAST_MODIF=$$(find ${LEVELDB_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ - if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ - touch ${LEVELDB_TIMESTAMP}; \ - fi - -leveldb_download : - @if [ ! -d ${LEVELDB_DIR} ] ; then \ - echo "leveldb sources missing, downloading..."; \ - mkdir -p ${ANDR_ROOT}/deps; \ - cd ${ANDR_ROOT}/deps ; \ - git clone ${LEVELDB_URL_GIT} || exit 1; \ - cd ${LEVELDB_DIR} || exit 1; \ - git checkout ${LEVELDB_COMMIT} || exit 1; \ - fi - -leveldb : $(LEVELDB_LIB) -ifeq ($(HAVE_LEVELDB),1) -$(LEVELDB_LIB): $(LEVELDB_TIMESTAMP) - @REFRESH=0; \ - if [ ! -e ${LEVELDB_TIMESTAMP_INT} ] ; then \ - REFRESH=1; \ - fi; \ - if [ ${LEVELDB_TIMESTAMP} -nt ${LEVELDB_TIMESTAMP_INT} ] ; then \ - REFRESH=1; \ - fi; \ - if [ $$REFRESH -ne 0 ] ; then \ - echo "changed timestamp for leveldb detected building..."; \ - cd deps/leveldb; \ - export CROSS_PREFIX=${TARGET_TOOLCHAIN}; \ - export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-leveldb; \ - ${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \ - --toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \ - --platform=${APP_PLATFORM} \ - --stl=libc++ \ - --install-dir=$${TOOLCHAIN}; \ - export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \ - export CC=${CROSS_CC}; \ - export CXX=${CROSS_CXX}; \ - export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \ - export CPPFLAGS="$${CPPFLAGS} ${TARGET_CXXFLAGS_ADDON}"; \ - export LDFLAGS="$${LDFLAGS} ${TARGET_LDFLAGS_ADDON}"; \ - export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \ - $(MAKE) || exit 1; \ - touch ${LEVELDB_TIMESTAMP}; \ - touch ${LEVELDB_TIMESTAMP_INT}; \ - $(RM) -rf $${TOOLCHAIN}; \ - else \ - echo "nothing to be done for leveldb"; \ - fi -endif - -clean_leveldb : - ./gradlew cleanLevelDB - -$(FREETYPE_TIMESTAMP) : freetype_download - @LAST_MODIF=$$(find ${FREETYPE_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ - if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ - touch ${FREETYPE_TIMESTAMP}; \ - fi - -freetype_download : - @if [ ! -d ${FREETYPE_DIR} ] ; then \ - echo "freetype sources missing, downloading..."; \ - mkdir -p ${ANDR_ROOT}/deps; \ - cd deps; \ - git clone ${FREETYPE_URL_GIT} || exit 1; \ - fi - -freetype : $(FREETYPE_LIB) - -$(FREETYPE_LIB) : $(FREETYPE_TIMESTAMP) - + @REFRESH=0; \ - if [ ! -e ${FREETYPE_TIMESTAMP_INT} ] ; then \ - REFRESH=1; \ - fi; \ - if [ ! -e ${FREETYPE_LIB} ] ; then \ - REFRESH=1; \ - fi; \ - if [ ${FREETYPE_TIMESTAMP} -nt ${FREETYPE_TIMESTAMP_INT} ] ; then \ - REFRESH=1; \ - fi; \ - if [ $$REFRESH -ne 0 ] ; then \ - mkdir -p ${FREETYPE_DIR}; \ - echo "changed timestamp for freetype detected building..."; \ - cd ${FREETYPE_DIR}/Android/jni; \ - export APP_PLATFORM=${APP_PLATFORM}; \ - export TARGET_ABI=${TARGET_ABI}; \ - export TARGET_CFLAGS_ADDON="${TARGET_CFLAGS_ADDON}"; \ - export TARGET_CXXFLAGS_ADDON="${TARGET_CXXFLAGS_ADDON}"; \ - export COMPILER_VERSION=${COMPILER_VERSION}; \ - ${ANDROID_NDK}/ndk-build \ - NDK_APPLICATION_MK=${ANDR_ROOT}/jni/Deps.mk || exit 1; \ - touch ${FREETYPE_TIMESTAMP}; \ - touch ${FREETYPE_TIMESTAMP_INT}; \ - else \ - echo "nothing to be done for freetype"; \ - fi - -clean_freetype : - ./gradlew cleanFreetype - -$(ICONV_TIMESTAMP) : iconv_download - @LAST_MODIF=$$(find ${ICONV_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ - if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ - touch ${ICONV_TIMESTAMP}; \ - fi - -iconv_download : - @if [ ! -d ${ICONV_DIR} ] ; then \ - echo "iconv sources missing, downloading..."; \ - mkdir -p ${ANDR_ROOT}/deps; \ - cd ${ANDR_ROOT}/deps; \ - wget ${ICONV_URL_HTTP} || exit 1; \ - tar -xzf libiconv-${ICONV_VERSION}.tar.gz || exit 1; \ - rm libiconv-${ICONV_VERSION}.tar.gz; \ - ln -s libiconv-${ICONV_VERSION} libiconv; \ - fi - -iconv : $(ICONV_LIB) - -$(ICONV_LIB) : $(ICONV_TIMESTAMP) - @REFRESH=0; \ - if [ ! -e ${ICONV_TIMESTAMP_INT} ] ; then \ - REFRESH=1; \ - fi; \ - if [ ! -e ${ICONV_LIB} ] ; then \ - REFRESH=1; \ - fi; \ - if [ ${ICONV_TIMESTAMP} -nt ${ICONV_TIMESTAMP_INT} ] ; then \ - REFRESH=1; \ - fi; \ - if [ $$REFRESH -ne 0 ] ; then \ - mkdir -p ${ICONV_DIR}; \ - echo "changed timestamp for iconv detected building..."; \ - cd ${ICONV_DIR}; \ - export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-iconv; \ - ${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \ - --toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \ - --platform=${APP_PLATFORM} \ - --stl=libc++ \ - --install-dir=$${TOOLCHAIN}; \ - export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \ - export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \ - export LDFLAGS="$${LDFLAGS} ${TARGET_LDFLAGS_ADDON} -lstdc++"; \ - export CC=${CROSS_CC}; \ - export CXX=${CROSS_CXX}; \ - export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \ - ./configure --host=${TARGET_HOST} || exit 1; \ - sed -i 's/LIBICONV_VERSION_INFO) /LIBICONV_VERSION_INFO) -avoid-version /g' lib/Makefile; \ - grep "iconv_LDFLAGS" src/Makefile; \ - $(MAKE) -s || exit 1; \ - touch ${ICONV_TIMESTAMP}; \ - touch ${ICONV_TIMESTAMP_INT}; \ - rm -rf ${TOOLCHAIN}; \ - else \ - echo "nothing to be done for iconv"; \ - fi - -clean_iconv : - ./gradlew cleanIconv - -#Note: Texturehack patch is required for gpu's not supporting color format -# correctly. Known bad GPU: -# -geforce on emulator -# -Vivante Corporation GC1000 core (e.g. Galaxy Tab 3) - -irrlicht_download : - @if [ ! -d "deps/irrlicht" ] ; then \ - echo "irrlicht sources missing, downloading..."; \ - mkdir -p ${ANDR_ROOT}/deps; \ - cd deps; \ - svn co ${IRRLICHT_URL_SVN} irrlicht || exit 1; \ - cd irrlicht; \ - patch -p1 < ${ANDR_ROOT}/patches/irrlicht-touchcount.patch || exit 1; \ - patch -p1 < ${ANDR_ROOT}/patches/irrlicht-back_button.patch || exit 1; \ - patch -p1 < ${ANDR_ROOT}/patches/irrlicht-texturehack.patch || exit 1; \ - patch -p1 < ${ANDR_ROOT}/patches/irrlicht-native_activity.patch || exit 1; \ - fi - -$(IRRLICHT_TIMESTAMP) : irrlicht_download - @LAST_MODIF=$$(find ${IRRLICHT_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ - if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ - touch ${IRRLICHT_TIMESTAMP}; \ - fi - -irrlicht : $(IRRLICHT_LIB) - -$(IRRLICHT_LIB): $(IRRLICHT_TIMESTAMP) $(FREETYPE_LIB) - + @REFRESH=0; \ - if [ ! -e ${IRRLICHT_TIMESTAMP_INT} ] ; then \ - REFRESH=1; \ - fi; \ - if [ ! -e ${IRRLICHT_LIB} ] ; then \ - REFRESH=1; \ - fi; \ - if [ ${IRRLICHT_TIMESTAMP} -nt ${IRRLICHT_TIMESTAMP_INT} ] ; then \ - REFRESH=1; \ - fi; \ - if [ $$REFRESH -ne 0 ] ; then \ - mkdir -p ${IRRLICHT_DIR}; \ - echo "changed timestamp for irrlicht detected building..."; \ - cd deps/irrlicht/source/Irrlicht/Android; \ - export APP_PLATFORM=${APP_PLATFORM}; \ - export TARGET_ABI=${TARGET_ABI}; \ - export TARGET_CFLAGS_ADDON="${TARGET_CFLAGS_ADDON}"; \ - export TARGET_CXXFLAGS_ADDON="${TARGET_CXXFLAGS_ADDON}"; \ - export COMPILER_VERSION=${COMPILER_VERSION}; \ - ${ANDROID_NDK}/ndk-build \ - NDK_APPLICATION_MK=${ANDR_ROOT}/jni/Deps.mk || exit 1; \ - touch ${IRRLICHT_TIMESTAMP}; \ - touch ${IRRLICHT_TIMESTAMP_INT}; \ - else \ - echo "nothing to be done for irrlicht"; \ - fi - -clean_irrlicht : - ./gradlew cleanIrrlicht - -$(CURL_TIMESTAMP) : curl_download - @LAST_MODIF=$$(find ${CURL_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ - if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ - touch ${CURL_TIMESTAMP}; \ - fi - -curl_download : - @if [ ! -d "deps/curl-${CURL_VERSION}" ] ; then \ - echo "curl sources missing, downloading..."; \ - mkdir -p ${ANDR_ROOT}/deps; \ - cd deps; \ - wget ${CURL_URL_HTTP} || exit 1; \ - tar -xjf curl-${CURL_VERSION}.tar.bz2 || exit 1; \ - rm curl-${CURL_VERSION}.tar.bz2; \ - ln -s curl-${CURL_VERSION} curl; \ - fi - -curl : $(CURL_LIB) - -$(CURL_LIB): $(CURL_TIMESTAMP) $(OPENSSL_LIB) - @REFRESH=0; \ - if [ ! -e ${CURL_TIMESTAMP_INT} ] ; then \ - REFRESH=1; \ - fi; \ - if [ ! -e ${CURL_LIB} ] ; then \ - REFRESH=1; \ - fi; \ - if [ ${CURL_TIMESTAMP} -nt ${CURL_TIMESTAMP_INT} ] ; then \ - REFRESH=1; \ - fi; \ - if [ $$REFRESH -ne 0 ] ; then \ - mkdir -p ${CURL_DIR}; \ - echo "changed timestamp for curl detected building..."; \ - cd deps/curl-${CURL_VERSION}; \ - export CROSS_PREFIX=${TARGET_TOOLCHAIN}; \ - export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-curl; \ - ${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \ - --toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \ - --platform=${APP_PLATFORM} \ - --stl=libc++ \ - --install-dir=$${TOOLCHAIN}; \ - export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \ - export CC=${CROSS_CC}; \ - export CXX=${CROSS_CXX}; \ - export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \ - export CPPFLAGS="$${CPPFLAGS} -I${OPENSSL_DIR}/include ${TARGET_CFLAGS_ADDON}"; \ - export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \ - export LDFLAGS="$${LDFLAGS} -L${OPENSSL_DIR} ${TARGET_LDFLAGS_ADDON}"; \ - ./configure --host=${TARGET_HOST} --disable-shared --enable-static --with-ssl; \ - $(MAKE) -s || exit 1; \ - touch ${CURL_TIMESTAMP}; \ - touch ${CURL_TIMESTAMP_INT}; \ - $(RM) -rf $${TOOLCHAIN}; \ - else \ - echo "nothing to be done for curl"; \ - fi - -clean_curl : - ./gradlew cleanCURL - -sqlite3_download: deps/${SQLITE3_FOLDER}/sqlite3.c - -deps/${SQLITE3_FOLDER}/sqlite3.c : - cd deps; \ - wget ${SQLITE3_URL}; \ - unzip ${SQLITE3_FOLDER}.zip; \ - ln -s ${SQLITE3_FOLDER} sqlite; \ - cd ${SQLITE3_FOLDER}; - -clean_sqlite3: - ./gradlew cleanSQLite3 - -$(ASSETS_TIMESTAMP) : $(IRRLICHT_LIB) - @mkdir -p ${ANDR_ROOT}/deps; \ - for DIRNAME in {builtin,client,doc,fonts,games,mods,po,textures}; do \ - LAST_MODIF=$$(find ${PROJ_ROOT}/${DIRNAME} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ - if [ $$(basename $$LAST_MODIF) != "timestamp" ]; then \ - touch ${PROJ_ROOT}/${DIRNAME}/timestamp; \ - touch ${ASSETS_TIMESTAMP}; \ - echo ${DIRNAME} changed $$LAST_MODIF; \ - fi; \ - done; \ - LAST_MODIF=$$(find ${IRRLICHT_DIR}/media -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ - if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ - touch ${IRRLICHT_DIR}/media/timestamp; \ - touch ${ASSETS_TIMESTAMP}; \ - fi; \ - if [ ${PROJ_ROOT}/minetest.conf.example -nt ${ASSETS_TIMESTAMP} ] ; then \ - echo "conf changed"; \ - touch ${ASSETS_TIMESTAMP}; \ - fi; \ - if [ ${PROJ_ROOT}/README.txt -nt ${ASSETS_TIMESTAMP} ] ; then \ - touch ${ASSETS_TIMESTAMP}; \ - fi; \ - if [ ! -e $(ASSETS_TIMESTAMP) ] ; then \ - touch $(ASSETS_TIMESTAMP); \ - fi - -assets : $(ASSETS_TIMESTAMP) - @REFRESH=0; \ - if [ ! -e ${ASSETS_TIMESTAMP}.old ] ; then \ - REFRESH=1; \ - fi; \ - if [ ${ASSETS_TIMESTAMP} -nt ${ASSETS_TIMESTAMP}.old ] ; then \ - REFRESH=1; \ - fi; \ - if [ ! -d ${APP_ROOT}/assets ] ; then \ - REFRESH=1; \ - fi; \ - if [ $$REFRESH -ne 0 ] ; then \ - echo "assets changed, refreshing..."; \ - $(MAKE) clean_assets; \ - ./gradlew copyAssets; \ - cp -r ${IRRLICHT_DIR}/media/Shaders ${APP_ROOT}/assets/Minetest/media; \ - cd ${APP_ROOT}/assets || exit 1; \ - find . -name "timestamp" -exec rm {} \; ; \ - find . -name "*.blend" -exec rm {} \; ; \ - find . -name "*~" -exec rm {} \; ; \ - find . -type d -path "*.git" -exec rm -rf {} \; ; \ - find . -type d -path "*.svn" -exec rm -rf {} \; ; \ - find . -type f -path "*.gitignore" -exec rm -rf {} \; ; \ - ls -R | grep ":$$" | sed -e 's/:$$//' -e 's/\.//' -e 's/^\///' > "index.txt"; \ - find -L Minetest > filelist.txt; \ - cp ${ANDR_ROOT}/${ASSETS_TIMESTAMP} ${ANDR_ROOT}/${ASSETS_TIMESTAMP}.old; \ - else \ - echo "nothing to be done for assets"; \ - fi - -clean_assets : - ./gradlew cleanAssets - -apk: local.properties assets $(ICONV_LIB) $(IRRLICHT_LIB) $(CURL_LIB) $(LEVELDB_TARGET) \ - $(OPENAL_LIB) $(OGG_LIB) prep_srcdir $(ANDR_ROOT)/jni/src/android_version.h \ - $(ANDR_ROOT)/jni/src/android_version_githash.h sqlite3_download - + @export TARGET_LIBDIR=${TARGET_LIBDIR}; \ - export HAVE_LEVELDB=${HAVE_LEVELDB}; \ - export APP_PLATFORM=${APP_PLATFORM}; \ - export TARGET_ABI=${TARGET_ABI}; \ - export TARGET_CFLAGS_ADDON="${TARGET_CFLAGS_ADDON}"; \ - export TARGET_CXXFLAGS_ADDON="${TARGET_CXXFLAGS_ADDON}"; \ - export COMPILER_VERSION=${COMPILER_VERSION}; \ - export GPROF=${GPROF}; \ - ${ANDROID_NDK}/ndk-build || exit 1; \ - if [ ! -e ${APP_ROOT}/jniLibs ]; then \ - ln -s ${ANDR_ROOT}/libs ${APP_ROOT}/jniLibs || exit 1; \ - fi; \ - export VERSION_STR="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" && \ - export BUILD_TYPE_C=$$(echo "$${BUILD_TYPE}" | sed 's/./\U&/') && \ - ./gradlew assemble$$BUILD_TYPE_C && \ - echo "APK stored at: build/outputs/apk/$$BUILD_TYPE/Minetest-$$BUILD_TYPE.apk" && \ - echo "You can install it with \`make install_$$BUILD_TYPE\`" - -# These Intentionally doesn't depend on their respective build steps, -# because it takes a while to verify that everything's up-to-date. -install_debug: - ${ANDROID_SDK}/platform-tools/adb install -r build/outputs/apk/debug/Minetest-debug.apk - -install_release: - ${ANDROID_SDK}/platform-tools/adb install -r build/outputs/apk/release/Minetest-release.apk - -prep_srcdir : - @if [ ! -e ${ANDR_ROOT}/jni/src ]; then \ - ln -s ${PROJ_ROOT}/src ${ANDR_ROOT}/jni/src; \ - fi; \ - if [ ! -e ${ANDR_ROOT}/jni/lib ]; then \ - ln -s ${PROJ_ROOT}/lib ${ANDR_ROOT}/jni/lib; \ - fi - -clean_apk : - ./gradlew clean - -clean_all : - ./gradlew cleanAll - -$(ANDR_ROOT)/jni/src/android_version_githash.h : prep_srcdir - @export VERSION_FILE=${ANDR_ROOT}/jni/src/android_version_githash.h; \ - export VERSION_FILE_NEW=$${VERSION_FILE}.new; \ - { \ - echo "#ifndef ANDROID_MT_VERSION_GITHASH_H"; \ - echo "#define ANDROID_MT_VERSION_GITHASH_H"; \ - export GITHASH=$$(git rev-parse --short=8 HEAD); \ - export VERSION_STR="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}"; \ - echo "#define VERSION_GITHASH \"$$VERSION_STR-$$GITHASH-Android\""; \ - echo "#endif"; \ - } > "$${VERSION_FILE_NEW}"; \ - if ! cmp -s $${VERSION_FILE} $${VERSION_FILE_NEW}; then \ - echo "android_version_githash.h changed, updating..."; \ - mv "$${VERSION_FILE_NEW}" "$${VERSION_FILE}"; \ - else \ - rm "$${VERSION_FILE_NEW}"; \ - fi - - -$(ANDR_ROOT)/jni/src/android_version.h : prep_srcdir - @export VERSION_FILE=${ANDR_ROOT}/jni/src/android_version.h; \ - export VERSION_FILE_NEW=$${VERSION_FILE}.new; \ - { \ - echo "#ifndef ANDROID_MT_VERSION_H"; \ - echo "#define ANDROID_MT_VERSION_H"; \ - echo "#define VERSION_MAJOR ${VERSION_MAJOR}"; \ - echo "#define VERSION_MINOR ${VERSION_MINOR}"; \ - echo "#define VERSION_PATCH ${VERSION_PATCH}"; \ - echo "#define VERSION_STRING STR(VERSION_MAJOR) \".\" STR(VERSION_MINOR) \ - \".\" STR(VERSION_PATCH)"; \ - echo "#endif"; \ - } > $${VERSION_FILE_NEW}; \ - if ! cmp -s $${VERSION_FILE} $${VERSION_FILE_NEW}; then \ - echo "android_version.h changed, updating..."; \ - mv "$${VERSION_FILE_NEW}" "$${VERSION_FILE}"; \ - else \ - rm "$${VERSION_FILE_NEW}"; \ - fi - -clean : clean_apk clean_assets diff --git a/build/android/app/build.gradle b/build/android/app/build.gradle new file mode 100644 index 000000000..6a34a6d70 --- /dev/null +++ b/build/android/app/build.gradle @@ -0,0 +1,108 @@ +apply plugin: 'com.android.application' +android { + compileSdkVersion 29 + buildToolsVersion '29.0.3' + ndkVersion '21.0.6113669' + defaultConfig { + applicationId 'net.minetest.minetest' + minSdkVersion 16 + //noinspection OldTargetApi + targetSdkVersion 28 // Workaround for using `/sdcard` instead of the `data` patch for assets + versionName "${versionMajor}.${versionMinor}.${versionPatch}" + versionCode project.versionCode + } + + Properties props = new Properties() + props.load(new FileInputStream(file('../local.properties'))) + + if (props.getProperty('keystore') != null) { + signingConfigs { + release { + storeFile file(props['keystore']) + storePassword props['keystore.password'] + keyAlias props['key'] + keyPassword props['key.password'] + } + } + + buildTypes { + release { + minifyEnabled true + signingConfig signingConfigs.release + } + } + } + + // for multiple APKs + splits { + abi { + enable true + reset() + include 'armeabi-v7a', 'arm64-v8a' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +task prepareAssets() { + def assetsFolder = "build/assets" + def projRoot = "../../.." + def gameToCopy = "minetest_game" + + copy { + from "${projRoot}/minetest.conf.example", "${projRoot}/README.md" into assetsFolder + } + copy { + from "${projRoot}/doc/lgpl-2.1.txt" into "${assetsFolder}" + rename("lgpl-2.1.txt", "LICENSE.txt") + } + copy { + from "${projRoot}/builtin" into "${assetsFolder}/builtin" + } + copy { + from "${projRoot}/client/shaders" into "${assetsFolder}/client/shaders" + } + copy { + from "${projRoot}/fonts" include "*.ttf" into "${assetsFolder}/fonts" + } + copy { + from "${projRoot}/games/${gameToCopy}" into "${assetsFolder}/games/${gameToCopy}" + } + /*copy { + // locales broken right now + // ToDo: fix it! + from "${projRoot}/po" into "${assetsFolder}/po" + }*/ + copy { + from "${projRoot}/textures" into "${assetsFolder}/textures" + } + + task zipAssets(type: Zip) { + archiveName "Minetest.zip" + from "${assetsFolder}" + destinationDir file("src/main/assets") + } +} + +preBuild.dependsOn zipAssets + +// Map for the version code that gives each ABI a value. +import com.android.build.OutputFile + +def abiCodes = ['armeabi-v7a': 0, 'arm64-v8a': 1] +android.applicationVariants.all { variant -> + variant.outputs.each { + output -> + def abiName = output.getFilter(OutputFile.ABI) + output.versionCodeOverride = abiCodes.get(abiName, 0) + variant.versionCode + } +} + +dependencies { + implementation project(':native') + implementation 'androidx.appcompat:appcompat:1.1.0' +} diff --git a/build/android/app/src/main/AndroidManifest.xml b/build/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..3a5342751 --- /dev/null +++ b/build/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/android/app/src/main/java/net/minetest/minetest/CopyZipTask.java b/build/android/app/src/main/java/net/minetest/minetest/CopyZipTask.java new file mode 100644 index 000000000..770995502 --- /dev/null +++ b/build/android/app/src/main/java/net/minetest/minetest/CopyZipTask.java @@ -0,0 +1,82 @@ +/* +Minetest +Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik +Copyright (C) 2014-2020 ubulem, Bektur Mambetov + +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. +*/ + +package net.minetest.minetest; + +import android.content.Context; +import android.content.Intent; +import android.os.AsyncTask; +import android.util.Log; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.ref.WeakReference; + +public class CopyZipTask extends AsyncTask { + + private final WeakReference contextRef; + + CopyZipTask(Context context) { + contextRef = new WeakReference<>(context); + } + + protected String doInBackground(String... params) { + copyAssets(params); + return params[0]; + } + + @Override + protected void onPostExecute(String result) { + startUnzipService(result); + } + + private void copyAsset(String zipName) throws IOException { + String filename = zipName.substring(zipName.lastIndexOf("/") + 1); + try (InputStream in = contextRef.get().getAssets().open(filename); + OutputStream out = new FileOutputStream(zipName)) { + copyFile(in, out); + } + } + + private void copyAssets(String[] zips) { + try { + for (String zipName : zips) + copyAsset(zipName); + } catch (IOException e) { + Log.e("CopyZipTask", e.getLocalizedMessage()); + cancel(true); + } + } + + private void copyFile(InputStream in, OutputStream out) throws IOException { + byte[] buffer = new byte[1024]; + int read; + while ((read = in.read(buffer)) != -1) + out.write(buffer, 0, read); + } + + private void startUnzipService(String file) { + Intent intent = new Intent(contextRef.get(), UnzipService.class); + intent.putExtra(UnzipService.EXTRA_KEY_IN_FILE, file); + contextRef.get().startService(intent); + } +} diff --git a/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java b/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java new file mode 100644 index 000000000..02b61b598 --- /dev/null +++ b/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java @@ -0,0 +1,120 @@ +/* +Minetest +Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik +Copyright (C) 2014-2020 ubulem, Bektur Mambetov + +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. +*/ + +package net.minetest.minetest; + +import android.app.NativeActivity; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.view.WindowManager; + +public class GameActivity extends NativeActivity { + static { + System.loadLibrary("c++_shared"); + System.loadLibrary("Minetest"); + } + + private int messageReturnCode; + private String messageReturnValue; + + public static native void putMessageBoxResult(String text); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + messageReturnCode = -1; + messageReturnValue = ""; + } + + private void makeFullScreen() { + if (Build.VERSION.SDK_INT >= 19) + this.getWindow().getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + if (hasFocus) + makeFullScreen(); + } + + @Override + protected void onResume() { + super.onResume(); + makeFullScreen(); + } + + @Override + public void onBackPressed() { + // Ignore the back press so Minetest can handle it + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == 101) { + if (resultCode == RESULT_OK) { + String text = data.getStringExtra("text"); + messageReturnCode = 0; + messageReturnValue = text; + } else + messageReturnCode = 1; + } + } + + public void showDialog(String acceptButton, String hint, String current, int editType) { + Intent intent = new Intent(this, InputDialogActivity.class); + Bundle params = new Bundle(); + params.putString("acceptButton", acceptButton); + params.putString("hint", hint); + params.putString("current", current); + params.putInt("editType", editType); + intent.putExtras(params); + startActivityForResult(intent, 101); + messageReturnValue = ""; + messageReturnCode = -1; + } + + public int getDialogState() { + return messageReturnCode; + } + + public String getDialogValue() { + messageReturnCode = -1; + return messageReturnValue; + } + + public float getDensity() { + return getResources().getDisplayMetrics().density; + } + + public int getDisplayHeight() { + return getResources().getDisplayMetrics().heightPixels; + } + + public int getDisplayWidth() { + return getResources().getDisplayMetrics().widthPixels; + } +} diff --git a/build/android/app/src/main/java/net/minetest/minetest/InputDialogActivity.java b/build/android/app/src/main/java/net/minetest/minetest/InputDialogActivity.java new file mode 100644 index 000000000..7c6aa111d --- /dev/null +++ b/build/android/app/src/main/java/net/minetest/minetest/InputDialogActivity.java @@ -0,0 +1,98 @@ +/* +Minetest +Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik +Copyright (C) 2014-2020 ubulem, Bektur Mambetov + +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. +*/ + +package net.minetest.minetest; + +import android.app.Activity; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.text.InputType; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; + +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; + +import java.util.Objects; + +public class InputDialogActivity extends AppCompatActivity { + private AlertDialog alertDialog; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Bundle b = getIntent().getExtras(); + int editType = Objects.requireNonNull(b).getInt("editType"); + String hint = b.getString("hint"); + String current = b.getString("current"); + final AlertDialog.Builder builder = new AlertDialog.Builder(this); + EditText editText = new EditText(this); + builder.setView(editText); + editText.requestFocus(); + editText.setHint(hint); + editText.setText(current); + final InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); + Objects.requireNonNull(imm).toggleSoftInput(InputMethodManager.SHOW_FORCED, + InputMethodManager.HIDE_IMPLICIT_ONLY); + if (editType == 3) + editText.setInputType(InputType.TYPE_CLASS_TEXT | + InputType.TYPE_TEXT_VARIATION_PASSWORD); + else + editText.setInputType(InputType.TYPE_CLASS_TEXT); + editText.setOnKeyListener((view, KeyCode, event) -> { + if (KeyCode == KeyEvent.KEYCODE_ENTER) { + imm.hideSoftInputFromWindow(editText.getWindowToken(), 0); + pushResult(editText.getText().toString()); + return true; + } + return false; + }); + alertDialog = builder.create(); + if (!this.isFinishing()) + alertDialog.show(); + alertDialog.setOnCancelListener(dialog -> { + pushResult(editText.getText().toString()); + setResult(Activity.RESULT_CANCELED); + alertDialog.dismiss(); + makeFullScreen(); + finish(); + }); + } + + private void pushResult(String text) { + Intent resultData = new Intent(); + resultData.putExtra("text", text); + setResult(AppCompatActivity.RESULT_OK, resultData); + alertDialog.dismiss(); + makeFullScreen(); + finish(); + } + + private void makeFullScreen() { + if (Build.VERSION.SDK_INT >= 19) + this.getWindow().getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); + } +} diff --git a/build/android/app/src/main/java/net/minetest/minetest/MainActivity.java b/build/android/app/src/main/java/net/minetest/minetest/MainActivity.java new file mode 100644 index 000000000..f37ae6d4b --- /dev/null +++ b/build/android/app/src/main/java/net/minetest/minetest/MainActivity.java @@ -0,0 +1,139 @@ +/* +Minetest +Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik +Copyright (C) 2014-2020 ubulem, Bektur Mambetov + +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. +*/ + +package net.minetest.minetest; + +import android.Manifest; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class MainActivity extends AppCompatActivity { + private final static int versionCode = BuildConfig.VERSION_CODE; + private final static int PERMISSIONS = 1; + private static final String[] REQUIRED_SDK_PERMISSIONS = + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}; + private static final String SETTINGS = "MinetestSettings"; + private static final String TAG_VERSION_CODE = "versionCode"; + private ProgressBar mProgressBar; + private TextView mTextView; + private SharedPreferences sharedPreferences; + private final BroadcastReceiver myReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + int progress = 0; + if (intent != null) + progress = intent.getIntExtra(UnzipService.ACTION_PROGRESS, 0); + if (progress >= 0) { + if (mProgressBar != null) { + mProgressBar.setVisibility(View.VISIBLE); + mProgressBar.setProgress(progress); + } + mTextView.setVisibility(View.VISIBLE); + } else + startNative(); + } + }; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + IntentFilter filter = new IntentFilter(UnzipService.ACTION_UPDATE); + registerReceiver(myReceiver, filter); + mProgressBar = findViewById(R.id.progressBar); + mTextView = findViewById(R.id.textView); + sharedPreferences = getSharedPreferences(SETTINGS, Context.MODE_PRIVATE); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) + checkPermission(); + else + checkAppVersion(); + } + + private void checkPermission() { + final List missingPermissions = new ArrayList<>(); + for (final String permission : REQUIRED_SDK_PERMISSIONS) { + final int result = ContextCompat.checkSelfPermission(this, permission); + if (result != PackageManager.PERMISSION_GRANTED) + missingPermissions.add(permission); + } + if (!missingPermissions.isEmpty()) { + final String[] permissions = missingPermissions + .toArray(new String[0]); + ActivityCompat.requestPermissions(this, permissions, PERMISSIONS); + } else { + final int[] grantResults = new int[REQUIRED_SDK_PERMISSIONS.length]; + Arrays.fill(grantResults, PackageManager.PERMISSION_GRANTED); + onRequestPermissionsResult(PERMISSIONS, REQUIRED_SDK_PERMISSIONS, grantResults); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, + @NonNull String[] permissions, @NonNull int[] grantResults) { + if (requestCode == PERMISSIONS) { + for (int grantResult : grantResults) { + if (grantResult != PackageManager.PERMISSION_GRANTED) { + Toast.makeText(this, R.string.not_granted, Toast.LENGTH_LONG).show(); + finish(); + } + } + checkAppVersion(); + } + } + + private void checkAppVersion() { + if (sharedPreferences.getInt(TAG_VERSION_CODE, 0) == versionCode) + startNative(); + else + new CopyZipTask(this).execute(getCacheDir() + "/Minetest.zip"); + } + + private void startNative() { + sharedPreferences.edit().putInt(TAG_VERSION_CODE, versionCode).apply(); + Intent intent = new Intent(this, GameActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(myReceiver); + } +} diff --git a/build/android/app/src/main/java/net/minetest/minetest/UnzipService.java b/build/android/app/src/main/java/net/minetest/minetest/UnzipService.java new file mode 100644 index 000000000..ac9116994 --- /dev/null +++ b/build/android/app/src/main/java/net/minetest/minetest/UnzipService.java @@ -0,0 +1,153 @@ +/* +Minetest +Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik +Copyright (C) 2014-2020 ubulem, Bektur Mambetov + +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. +*/ + +package net.minetest.minetest; + +import android.app.IntentService; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Environment; +import android.util.Log; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; + +public class UnzipService extends IntentService { + public static final String ACTION_UPDATE = "net.minetest.minetest.UPDATE"; + public static final String ACTION_PROGRESS = "net.minetest.minetest.PROGRESS"; + public static final String EXTRA_KEY_IN_FILE = "file"; + private static final String TAG = "UnzipService"; + private final int id = 1; + private NotificationManager mNotifyManager; + + public UnzipService() { + super("net.minetest.minetest.UnzipService"); + } + + private void isDir(String dir, String location) { + File f = new File(location + dir); + if (!f.isDirectory()) + f.mkdirs(); + } + + @Override + protected void onHandleIntent(Intent intent) { + createNotification(); + unzip(intent); + } + + private void createNotification() { + String name = "net.minetest.minetest"; + String channelId = "Minetest channel"; + String description = "notifications from Minetest"; + Notification.Builder builder; + if (mNotifyManager == null) + mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + int importance = NotificationManager.IMPORTANCE_LOW; + NotificationChannel mChannel = null; + if (mNotifyManager != null) + mChannel = mNotifyManager.getNotificationChannel(channelId); + if (mChannel == null) { + mChannel = new NotificationChannel(channelId, name, importance); + mChannel.setDescription(description); + // Configure the notification channel, NO SOUND + mChannel.setSound(null, null); + mChannel.enableLights(false); + mChannel.enableVibration(false); + mNotifyManager.createNotificationChannel(mChannel); + } + builder = new Notification.Builder(this, channelId); + } else { + builder = new Notification.Builder(this); + } + builder.setContentTitle(getString(R.string.notification_title)) + .setSmallIcon(R.mipmap.ic_launcher) + .setContentText(getString(R.string.notification_description)); + mNotifyManager.notify(id, builder.build()); + } + + private void unzip(Intent intent) { + String zip = intent.getStringExtra(EXTRA_KEY_IN_FILE); + String location = Environment.getExternalStorageDirectory() + "/Minetest/"; + int per = 0; + int size = getSummarySize(zip); + File zipFile = new File(zip); + int readLen; + byte[] readBuffer = new byte[8192]; + try (FileInputStream fileInputStream = new FileInputStream(zipFile); + ZipInputStream zipInputStream = new ZipInputStream(fileInputStream)) { + ZipEntry ze; + while ((ze = zipInputStream.getNextEntry()) != null) { + if (ze.isDirectory()) { + ++per; + isDir(ze.getName(), location); + } else { + publishProgress(100 * ++per / size); + try (OutputStream outputStream = new FileOutputStream(location + ze.getName())) { + while ((readLen = zipInputStream.read(readBuffer)) != -1) { + outputStream.write(readBuffer, 0, readLen); + } + } + } + zipFile.delete(); + } + } catch (FileNotFoundException e) { + Log.e(TAG, e.getLocalizedMessage()); + } catch (IOException e) { + Log.e(TAG, e.getLocalizedMessage()); + } + } + + private void publishProgress(int progress) { + Intent intentUpdate = new Intent(ACTION_UPDATE); + intentUpdate.putExtra(ACTION_PROGRESS, progress); + sendBroadcast(intentUpdate); + } + + private int getSummarySize(String zip) { + int size = 0; + try { + ZipFile zipSize = new ZipFile(zip); + size += zipSize.size(); + } catch (IOException e) { + Log.e(TAG, e.getLocalizedMessage()); + } + return size; + } + + @Override + public void onDestroy() { + super.onDestroy(); + mNotifyManager.cancel(id); + publishProgress(-1); + } +} diff --git a/build/android/app/src/main/res/drawable/background.png b/build/android/app/src/main/res/drawable/background.png new file mode 100644 index 000000000..43bd6089e Binary files /dev/null and b/build/android/app/src/main/res/drawable/background.png differ diff --git a/build/android/app/src/main/res/drawable/bg.xml b/build/android/app/src/main/res/drawable/bg.xml new file mode 100644 index 000000000..903335ed9 --- /dev/null +++ b/build/android/app/src/main/res/drawable/bg.xml @@ -0,0 +1,4 @@ + + diff --git a/build/android/app/src/main/res/layout/activity_main.xml b/build/android/app/src/main/res/layout/activity_main.xml new file mode 100644 index 000000000..e6f461f14 --- /dev/null +++ b/build/android/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,30 @@ + + + + + + + diff --git a/build/android/app/src/main/res/mipmap/ic_launcher.png b/build/android/app/src/main/res/mipmap/ic_launcher.png new file mode 100644 index 000000000..88a83782c Binary files /dev/null and b/build/android/app/src/main/res/mipmap/ic_launcher.png differ diff --git a/build/android/app/src/main/res/values/strings.xml b/build/android/app/src/main/res/values/strings.xml new file mode 100644 index 000000000..a6fba70d5 --- /dev/null +++ b/build/android/app/src/main/res/values/strings.xml @@ -0,0 +1,10 @@ + + + + Minetest + Loading… + Required permission wasn\'t granted, Minetest can\'t run without it + Loading Minetest + Less than 1 minute… + + diff --git a/build/android/app/src/main/res/values/styles.xml b/build/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..618507e63 --- /dev/null +++ b/build/android/app/src/main/res/values/styles.xml @@ -0,0 +1,22 @@ + + + + + + + + + + diff --git a/build/android/build.gradle b/build/android/build.gradle index fa74cd497..b02e8c6df 100644 --- a/build/android/build.gradle +++ b/build/android/build.gradle @@ -1,10 +1,24 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +project.ext.set("versionMajor", 5) // Version Major +project.ext.set("versionMinor", 3) // Version Minor +project.ext.set("versionPatch", 0) // Version Patch +project.ext.set("versionExtra", "-dev") // Version Extra +project.ext.set("versionCode", 26) // Android Version Code +// NOTE: +2 after each release! +// +1 for ARM and +1 for ARM64 APK's, because +// each APK must have a larger `versionCode` than the previous + buildscript { repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.1' + classpath 'com.android.tools.build:gradle:3.6.2' + classpath 'org.ajoberstar.grgit:grgit-gradle:4.0.2' + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files } } @@ -15,161 +29,6 @@ allprojects { } } -def curl_version = "7.60.0" -def irrlicht_revision = "5150" -def openal_version = "1.18.2" -def openssl_version = "1.0.2n" -def sqlite3_version = "3240000" - -apply plugin: "com.android.application" - -android { - compileSdkVersion 29 - buildToolsVersion '29.0.2' - - defaultConfig { - versionCode 26 - versionName "${System.env.VERSION_STR}.${versionCode}" - minSdkVersion 14 - targetSdkVersion 29 - applicationId "net.minetest.minetest" - manifestPlaceholders = [package: "net.minetest.minetest", project: project.name] - ndk { - // Specifies the ABI configurations of your native - // libraries Gradle should build and package with your APK. - // abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' - abiFilters 'armeabi-v7a', 'x86', 'arm64-v8a' - } - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - lintOptions { - disable "OldTargetApi", "GoogleAppIndexingWarning" - } - - Properties props = new Properties() - props.load(new FileInputStream(file("local.properties"))) - - if (props.getProperty("keystore") != null) { - signingConfigs { - release { - storeFile file(props["keystore"]) - storePassword props["keystore.password"] - keyAlias props["key"] - keyPassword props["key.password"] - } - } - - buildTypes { - release { - signingConfig signingConfigs.release - } - } - } -} - -task cleanAssets(type: Delete) { - delete 'src/main/assets' -} - -task copyAssets { - dependsOn 'cleanAssets' - mkdir "src/main/assets" - - def mtAssetsFolder = "src/main/assets/Minetest" - def projRoot = "../.." - def gameToCopy = "minetest_game" - - doLast { - mkdir "${mtAssetsFolder}" - mkdir "${mtAssetsFolder}/client" - mkdir "${mtAssetsFolder}/fonts" - mkdir "${mtAssetsFolder}/games" - mkdir "${mtAssetsFolder}/media" - - copy { - from "${projRoot}/minetest.conf.example", "${projRoot}/README.md" into mtAssetsFolder - } - copy { - from "${projRoot}/doc/lgpl-2.1.txt" into "${mtAssetsFolder}/LICENSE.txt" - } - copy { - from "${projRoot}/builtin" into "${mtAssetsFolder}/builtin" - } - copy { - from "${projRoot}/client/shaders" into "${mtAssetsFolder}/client/shaders" - } - copy { - from "${projRoot}/fonts" include "*.ttf" into "${mtAssetsFolder}/fonts" - } - copy { - from "${projRoot}/games/${gameToCopy}" into "${mtAssetsFolder}/games/${gameToCopy}" - } - copy { - from "${projRoot}/po" into "${mtAssetsFolder}/po" - } - copy { - from "${projRoot}/textures" into "${mtAssetsFolder}/textures" - } - } -} - -task cleanIconv(type: Delete) { - delete 'deps/libiconv' -} - -task cleanIrrlicht(type: Delete) { - delete 'deps/irrlicht' -} - -task cleanLevelDB(type: Delete) { - delete 'deps/leveldb' -} - -task cleanCURL(type: Delete) { - delete 'deps/curl' - delete 'deps/curl-' + curl_version -} - -task cleanOpenSSL(type: Delete) { - delete 'deps/openssl' - delete 'deps/openssl-' + openssl_version - delete 'deps/openssl-' + openssl_version + '.tar.gz' -} - -task cleanOpenAL(type: Delete) { - delete 'deps/openal-soft' -} - -task cleanFreetype(type: Delete) { - delete 'deps/freetype2-android' -} - -task cleanOgg(type: Delete) { - delete 'deps/libvorbis-libogg-android' -} - -task cleanSQLite3(type: Delete) { - delete 'deps/sqlite-amalgamation-' + sqlite3_version - delete 'deps/sqlite-amalgamation-' + sqlite3_version + '.zip' -} - -task cleanAll(type: Delete, dependsOn: [clean, cleanAssets, cleanIconv, - cleanFreetype, cleanIrrlicht, cleanLevelDB, cleanSQLite3, cleanCURL, - cleanOpenSSL, cleanOpenAL, cleanOgg]) { - delete 'deps' - delete 'gen' - delete 'libs' - delete 'obj' - delete 'bin' - delete 'Debug' - delete 'and_env' -} - -dependencies { - implementation 'androidx.core:core:1.1.0' +task clean(type: Delete) { + delete rootProject.buildDir } diff --git a/build/android/gradle.properties b/build/android/gradle.properties index 5465fec0e..53b475cf9 100644 --- a/build/android/gradle.properties +++ b/build/android/gradle.properties @@ -1,2 +1,11 @@ +<#if isLowMemory> +org.gradle.jvmargs=-Xmx4G -XX:MaxPermSize=2G -XX:+HeapDumpOnOutOfMemoryError +<#else> +org.gradle.jvmargs=-Xmx16G -XX:MaxPermSize=8G -XX:+HeapDumpOnOutOfMemoryError + +org.gradle.daemon=true +org.gradle.parallel=true +org.gradle.parallel.threads=8 +org.gradle.configureondemand=true android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file +android.useAndroidX=true diff --git a/build/android/gradle/wrapper/gradle-wrapper.jar b/build/android/gradle/wrapper/gradle-wrapper.jar index 6b6ea3ab4..5c2d1cf01 100644 Binary files a/build/android/gradle/wrapper/gradle-wrapper.jar and b/build/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/build/android/gradle/wrapper/gradle-wrapper.properties b/build/android/gradle/wrapper/gradle-wrapper.properties index 22ac96460..d612cf333 100644 --- a/build/android/gradle/wrapper/gradle-wrapper.properties +++ b/build/android/gradle/wrapper/gradle-wrapper.properties @@ -1 +1,2 @@ -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip +#Mon Apr 06 00:06:16 CEST 2020 +distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip diff --git a/build/android/gradlew b/build/android/gradlew index cccdd3d51..83f2acfdc 100755 --- a/build/android/gradlew +++ b/build/android/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -109,8 +125,8 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` diff --git a/build/android/gradlew.bat b/build/android/gradlew.bat index f9553162f..9618d8d96 100644 --- a/build/android/gradlew.bat +++ b/build/android/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome diff --git a/build/android/jni/Android.mk b/build/android/jni/Android.mk deleted file mode 100644 index b67322d79..000000000 --- a/build/android/jni/Android.mk +++ /dev/null @@ -1,448 +0,0 @@ -LOCAL_PATH := $(call my-dir)/.. - -#LOCAL_ADDRESS_SANITIZER:=true - -include $(CLEAR_VARS) -LOCAL_MODULE := Irrlicht -LOCAL_SRC_FILES := deps/irrlicht/lib/Android/libIrrlicht.a -include $(PREBUILT_STATIC_LIBRARY) - -ifeq ($(HAVE_LEVELDB), 1) - include $(CLEAR_VARS) - LOCAL_MODULE := LevelDB - LOCAL_SRC_FILES := deps/leveldb/libleveldb.a - include $(PREBUILT_STATIC_LIBRARY) -endif - -include $(CLEAR_VARS) -LOCAL_MODULE := curl -LOCAL_SRC_FILES := deps/curl/lib/.libs/libcurl.a -include $(PREBUILT_STATIC_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_MODULE := freetype -LOCAL_SRC_FILES := deps/freetype2-android/Android/obj/local/$(TARGET_ARCH_ABI)/libfreetype2-static.a -include $(PREBUILT_STATIC_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_MODULE := iconv -LOCAL_SRC_FILES := deps/libiconv/lib/.libs/libiconv.so -include $(PREBUILT_SHARED_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_MODULE := openal -LOCAL_SRC_FILES := deps/openal-soft/libs/$(TARGET_LIBDIR)/libopenal.so -include $(PREBUILT_SHARED_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_MODULE := ogg -LOCAL_SRC_FILES := deps/libvorbis-libogg-android/libs/$(TARGET_LIBDIR)/libogg.so -include $(PREBUILT_SHARED_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_MODULE := vorbis -LOCAL_SRC_FILES := deps/libvorbis-libogg-android/libs/$(TARGET_LIBDIR)/libvorbis.so -include $(PREBUILT_SHARED_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_MODULE := ssl -LOCAL_SRC_FILES := deps/openssl/libssl.a -include $(PREBUILT_STATIC_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_MODULE := crypto -LOCAL_SRC_FILES := deps/openssl/libcrypto.a -include $(PREBUILT_STATIC_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_MODULE := minetest - -LOCAL_CPP_FEATURES += exceptions - -ifdef GPROF -GPROF_DEF=-DGPROF -endif - -LOCAL_CFLAGS := -D_IRR_ANDROID_PLATFORM_ \ - -DHAVE_TOUCHSCREENGUI \ - -DENABLE_GLES=1 \ - -DUSE_CURL=1 \ - -DUSE_SOUND=1 \ - -DUSE_FREETYPE=1 \ - -DUSE_LEVELDB=$(HAVE_LEVELDB) \ - $(GPROF_DEF) \ - -pipe -fstrict-aliasing - -ifndef NDEBUG -LOCAL_CFLAGS += -g -D_DEBUG -O0 -fno-omit-frame-pointer -else -LOCAL_CFLAGS += $(TARGET_CFLAGS_ADDON) -endif - -ifdef GPROF -PROFILER_LIBS := android-ndk-profiler -LOCAL_CFLAGS += -pg -endif - -# LOCAL_CFLAGS += -fsanitize=address -# LOCAL_LDFLAGS += -fsanitize=address - -ifeq ($(TARGET_ABI),x86) -LOCAL_CFLAGS += -fno-stack-protector -endif - -LOCAL_C_INCLUDES := \ - jni/src \ - jni/src/script \ - jni/lib/gmp \ - jni/lib/lua/src \ - jni/lib/jsoncpp \ - jni/src/cguittfont \ - deps/irrlicht/include \ - deps/libiconv/include \ - deps/freetype2-android/include \ - deps/curl/include \ - deps/openal-soft/jni/OpenAL/include \ - deps/libvorbis-libogg-android/jni/include \ - deps/leveldb/include \ - deps/sqlite/ - -LOCAL_SRC_FILES := \ - jni/src/ban.cpp \ - jni/src/chat.cpp \ - jni/src/client/activeobjectmgr.cpp \ - jni/src/client/camera.cpp \ - jni/src/client/client.cpp \ - jni/src/client/clientenvironment.cpp \ - jni/src/client/clientlauncher.cpp \ - jni/src/client/clientmap.cpp \ - jni/src/client/clientmedia.cpp \ - jni/src/client/clientobject.cpp \ - jni/src/client/clouds.cpp \ - jni/src/client/content_cao.cpp \ - jni/src/client/content_cso.cpp \ - jni/src/client/content_mapblock.cpp \ - jni/src/client/filecache.cpp \ - jni/src/client/fontengine.cpp \ - jni/src/client/game.cpp \ - jni/src/client/gameui.cpp \ - jni/src/client/guiscalingfilter.cpp \ - jni/src/client/hud.cpp \ - jni/src/clientiface.cpp \ - jni/src/client/imagefilters.cpp \ - jni/src/client/inputhandler.cpp \ - jni/src/client/joystick_controller.cpp \ - jni/src/client/keycode.cpp \ - jni/src/client/localplayer.cpp \ - jni/src/client/mapblock_mesh.cpp \ - jni/src/client/mesh.cpp \ - jni/src/client/meshgen/collector.cpp \ - jni/src/client/mesh_generator_thread.cpp \ - jni/src/client/minimap.cpp \ - jni/src/client/particles.cpp \ - jni/src/client/render/anaglyph.cpp \ - jni/src/client/render/core.cpp \ - jni/src/client/render/factory.cpp \ - jni/src/client/renderingengine.cpp \ - jni/src/client/render/interlaced.cpp \ - jni/src/client/render/pageflip.cpp \ - jni/src/client/render/plain.cpp \ - jni/src/client/render/sidebyside.cpp \ - jni/src/client/render/stereo.cpp \ - jni/src/client/shader.cpp \ - jni/src/client/sky.cpp \ - jni/src/client/sound.cpp \ - jni/src/client/sound_openal.cpp \ - jni/src/client/tile.cpp \ - jni/src/client/wieldmesh.cpp \ - jni/src/collision.cpp \ - jni/src/content/content.cpp \ - jni/src/content_mapnode.cpp \ - jni/src/content/mods.cpp \ - jni/src/content_nodemeta.cpp \ - jni/src/content/packages.cpp \ - jni/src/content/subgames.cpp \ - jni/src/convert_json.cpp \ - jni/src/craftdef.cpp \ - jni/src/database/database.cpp \ - jni/src/database/database-dummy.cpp \ - jni/src/database/database-files.cpp \ - jni/src/database/database-leveldb.cpp \ - jni/src/database/database-sqlite3.cpp \ - jni/src/debug.cpp \ - jni/src/defaultsettings.cpp \ - jni/src/emerge.cpp \ - jni/src/environment.cpp \ - jni/src/face_position_cache.cpp \ - jni/src/filesys.cpp \ - jni/src/gettext.cpp \ - jni/src/gui/guiAnimatedImage.cpp \ - jni/src/gui/guiBackgroundImage.cpp \ - jni/src/gui/guiBox.cpp \ - jni/src/gui/guiButton.cpp \ - jni/src/gui/guiButtonImage.cpp \ - jni/src/gui/guiButtonItemImage.cpp \ - jni/src/gui/guiChatConsole.cpp \ - jni/src/gui/guiConfirmRegistration.cpp \ - jni/src/gui/guiEditBoxWithScrollbar.cpp \ - jni/src/gui/guiEngine.cpp \ - jni/src/gui/guiFormSpecMenu.cpp \ - jni/src/gui/guiHyperText.cpp \ - jni/src/gui/guiInventoryList.cpp \ - jni/src/gui/guiItemImage.cpp \ - jni/src/gui/guiKeyChangeMenu.cpp \ - jni/src/gui/guiPasswordChange.cpp \ - jni/src/gui/guiPathSelectMenu.cpp \ - jni/src/gui/guiScrollBar.cpp \ - jni/src/gui/guiScrollContainer.cpp \ - jni/src/gui/guiSkin.cpp \ - jni/src/gui/guiTable.cpp \ - jni/src/gui/guiVolumeChange.cpp \ - jni/src/gui/intlGUIEditBox.cpp \ - jni/src/gui/modalMenu.cpp \ - jni/src/gui/profilergraph.cpp \ - jni/src/gui/touchscreengui.cpp \ - jni/src/httpfetch.cpp \ - jni/src/hud.cpp \ - jni/src/inventory.cpp \ - jni/src/inventorymanager.cpp \ - jni/src/irrlicht_changes/CGUITTFont.cpp \ - jni/src/irrlicht_changes/static_text.cpp \ - jni/src/itemdef.cpp \ - jni/src/itemstackmetadata.cpp \ - jni/src/light.cpp \ - jni/src/log.cpp \ - jni/src/main.cpp \ - jni/src/mapblock.cpp \ - jni/src/map.cpp \ - jni/src/mapgen/cavegen.cpp \ - jni/src/mapgen/dungeongen.cpp \ - jni/src/mapgen/mapgen_carpathian.cpp \ - jni/src/mapgen/mapgen.cpp \ - jni/src/mapgen/mapgen_flat.cpp \ - jni/src/mapgen/mapgen_fractal.cpp \ - jni/src/mapgen/mapgen_singlenode.cpp \ - jni/src/mapgen/mapgen_v5.cpp \ - jni/src/mapgen/mapgen_v6.cpp \ - jni/src/mapgen/mapgen_v7.cpp \ - jni/src/mapgen/mapgen_valleys.cpp \ - jni/src/mapgen/mg_biome.cpp \ - jni/src/mapgen/mg_decoration.cpp \ - jni/src/mapgen/mg_ore.cpp \ - jni/src/mapgen/mg_schematic.cpp \ - jni/src/mapgen/treegen.cpp \ - jni/src/mapnode.cpp \ - jni/src/mapsector.cpp \ - jni/src/map_settings_manager.cpp \ - jni/src/metadata.cpp \ - jni/src/modchannels.cpp \ - jni/src/nameidmapping.cpp \ - jni/src/nodedef.cpp \ - jni/src/nodemetadata.cpp \ - jni/src/nodetimer.cpp \ - jni/src/noise.cpp \ - jni/src/objdef.cpp \ - jni/src/object_properties.cpp \ - jni/src/pathfinder.cpp \ - jni/src/player.cpp \ - jni/src/porting_android.cpp \ - jni/src/porting.cpp \ - jni/src/profiler.cpp \ - jni/src/raycast.cpp \ - jni/src/reflowscan.cpp \ - jni/src/remoteplayer.cpp \ - jni/src/rollback.cpp \ - jni/src/rollback_interface.cpp \ - jni/src/serialization.cpp \ - jni/src/server/activeobjectmgr.cpp \ - jni/src/server.cpp \ - jni/src/serverenvironment.cpp \ - jni/src/serverlist.cpp \ - jni/src/server/luaentity_sao.cpp \ - jni/src/server/mods.cpp \ - jni/src/server/player_sao.cpp \ - jni/src/server/serveractiveobject.cpp \ - jni/src/server/unit_sao.cpp \ - jni/src/settings.cpp \ - jni/src/staticobject.cpp \ - jni/src/tileanimation.cpp \ - jni/src/tool.cpp \ - jni/src/translation.cpp \ - jni/src/unittest/test_authdatabase.cpp \ - jni/src/unittest/test_collision.cpp \ - jni/src/unittest/test_compression.cpp \ - jni/src/unittest/test_connection.cpp \ - jni/src/unittest/test.cpp \ - jni/src/unittest/test_filepath.cpp \ - jni/src/unittest/test_gameui.cpp \ - jni/src/unittest/test_inventory.cpp \ - jni/src/unittest/test_mapnode.cpp \ - jni/src/unittest/test_map_settings_manager.cpp \ - jni/src/unittest/test_nodedef.cpp \ - jni/src/unittest/test_noderesolver.cpp \ - jni/src/unittest/test_noise.cpp \ - jni/src/unittest/test_objdef.cpp \ - jni/src/unittest/test_profiler.cpp \ - jni/src/unittest/test_random.cpp \ - jni/src/unittest/test_schematic.cpp \ - jni/src/unittest/test_serialization.cpp \ - jni/src/unittest/test_settings.cpp \ - jni/src/unittest/test_socket.cpp \ - jni/src/unittest/test_utilities.cpp \ - jni/src/unittest/test_voxelalgorithms.cpp \ - jni/src/unittest/test_voxelmanipulator.cpp \ - jni/src/util/areastore.cpp \ - jni/src/util/auth.cpp \ - jni/src/util/base64.cpp \ - jni/src/util/directiontables.cpp \ - jni/src/util/enriched_string.cpp \ - jni/src/util/ieee_float.cpp \ - jni/src/util/numeric.cpp \ - jni/src/util/pointedthing.cpp \ - jni/src/util/quicktune.cpp \ - jni/src/util/serialize.cpp \ - jni/src/util/sha1.cpp \ - jni/src/util/srp.cpp \ - jni/src/util/string.cpp \ - jni/src/util/timetaker.cpp \ - jni/src/version.cpp \ - jni/src/voxelalgorithms.cpp \ - jni/src/voxel.cpp - - -# intentionally kept out (we already build openssl itself): jni/src/util/sha256.c - -# Network -LOCAL_SRC_FILES += \ - jni/src/network/address.cpp \ - jni/src/network/connection.cpp \ - jni/src/network/networkpacket.cpp \ - jni/src/network/clientopcodes.cpp \ - jni/src/network/clientpackethandler.cpp \ - jni/src/network/connectionthreads.cpp \ - jni/src/network/serveropcodes.cpp \ - jni/src/network/serverpackethandler.cpp \ - jni/src/network/socket.cpp \ - -# lua api -LOCAL_SRC_FILES += \ - jni/src/script/common/c_content.cpp \ - jni/src/script/common/c_converter.cpp \ - jni/src/script/common/c_internal.cpp \ - jni/src/script/common/c_types.cpp \ - jni/src/script/common/helper.cpp \ - jni/src/script/cpp_api/s_async.cpp \ - jni/src/script/cpp_api/s_base.cpp \ - jni/src/script/cpp_api/s_client.cpp \ - jni/src/script/cpp_api/s_entity.cpp \ - jni/src/script/cpp_api/s_env.cpp \ - jni/src/script/cpp_api/s_inventory.cpp \ - jni/src/script/cpp_api/s_item.cpp \ - jni/src/script/cpp_api/s_mainmenu.cpp \ - jni/src/script/cpp_api/s_modchannels.cpp \ - jni/src/script/cpp_api/s_node.cpp \ - jni/src/script/cpp_api/s_nodemeta.cpp \ - jni/src/script/cpp_api/s_player.cpp \ - jni/src/script/cpp_api/s_security.cpp \ - jni/src/script/cpp_api/s_server.cpp \ - jni/src/script/lua_api/l_areastore.cpp \ - jni/src/script/lua_api/l_auth.cpp \ - jni/src/script/lua_api/l_base.cpp \ - jni/src/script/lua_api/l_camera.cpp \ - jni/src/script/lua_api/l_client.cpp \ - jni/src/script/lua_api/l_craft.cpp \ - jni/src/script/lua_api/l_env.cpp \ - jni/src/script/lua_api/l_inventory.cpp \ - jni/src/script/lua_api/l_item.cpp \ - jni/src/script/lua_api/l_itemstackmeta.cpp\ - jni/src/script/lua_api/l_localplayer.cpp \ - jni/src/script/lua_api/l_mainmenu.cpp \ - jni/src/script/lua_api/l_mapgen.cpp \ - jni/src/script/lua_api/l_metadata.cpp \ - jni/src/script/lua_api/l_minimap.cpp \ - jni/src/script/lua_api/l_modchannels.cpp \ - jni/src/script/lua_api/l_nodemeta.cpp \ - jni/src/script/lua_api/l_nodetimer.cpp \ - jni/src/script/lua_api/l_noise.cpp \ - jni/src/script/lua_api/l_object.cpp \ - jni/src/script/lua_api/l_playermeta.cpp \ - jni/src/script/lua_api/l_particles.cpp \ - jni/src/script/lua_api/l_particles_local.cpp\ - jni/src/script/lua_api/l_rollback.cpp \ - jni/src/script/lua_api/l_server.cpp \ - jni/src/script/lua_api/l_settings.cpp \ - jni/src/script/lua_api/l_sound.cpp \ - jni/src/script/lua_api/l_http.cpp \ - jni/src/script/lua_api/l_storage.cpp \ - jni/src/script/lua_api/l_util.cpp \ - jni/src/script/lua_api/l_vmanip.cpp \ - jni/src/script/scripting_client.cpp \ - jni/src/script/scripting_server.cpp \ - jni/src/script/scripting_mainmenu.cpp - -#freetype2 support -#LOCAL_SRC_FILES += jni/src/cguittfont/xCGUITTFont.cpp - -# GMP -LOCAL_SRC_FILES += jni/lib/gmp/mini-gmp.c - -# Lua -LOCAL_SRC_FILES += \ - jni/lib/lua/src/lapi.c \ - jni/lib/lua/src/lauxlib.c \ - jni/lib/lua/src/lbaselib.c \ - jni/lib/lua/src/lcode.c \ - jni/lib/lua/src/ldblib.c \ - jni/lib/lua/src/ldebug.c \ - jni/lib/lua/src/ldo.c \ - jni/lib/lua/src/ldump.c \ - jni/lib/lua/src/lfunc.c \ - jni/lib/lua/src/lgc.c \ - jni/lib/lua/src/linit.c \ - jni/lib/lua/src/liolib.c \ - jni/lib/lua/src/llex.c \ - jni/lib/lua/src/lmathlib.c \ - jni/lib/lua/src/lmem.c \ - jni/lib/lua/src/loadlib.c \ - jni/lib/lua/src/lobject.c \ - jni/lib/lua/src/lopcodes.c \ - jni/lib/lua/src/loslib.c \ - jni/lib/lua/src/lparser.c \ - jni/lib/lua/src/lstate.c \ - jni/lib/lua/src/lstring.c \ - jni/lib/lua/src/lstrlib.c \ - jni/lib/lua/src/ltable.c \ - jni/lib/lua/src/ltablib.c \ - jni/lib/lua/src/ltm.c \ - jni/lib/lua/src/lundump.c \ - jni/lib/lua/src/lvm.c \ - jni/lib/lua/src/lzio.c \ - jni/lib/lua/src/print.c - -# SQLite3 -LOCAL_SRC_FILES += deps/sqlite/sqlite3.c - -# Threading -LOCAL_SRC_FILES += \ - jni/src/threading/event.cpp \ - jni/src/threading/semaphore.cpp \ - jni/src/threading/thread.cpp - -# JSONCPP -LOCAL_SRC_FILES += jni/lib/jsoncpp/jsoncpp.cpp - -LOCAL_SHARED_LIBRARIES := iconv openal ogg vorbis -LOCAL_STATIC_LIBRARIES := Irrlicht freetype curl ssl crypto android_native_app_glue $(PROFILER_LIBS) - -ifeq ($(HAVE_LEVELDB), 1) - LOCAL_STATIC_LIBRARIES += LevelDB -endif -LOCAL_LDLIBS := -lEGL -llog -lGLESv1_CM -lGLESv2 -lz -landroid - -include $(BUILD_SHARED_LIBRARY) - -# at the end of Android.mk -ifdef GPROF -$(call import-module,android-ndk-profiler) -endif -$(call import-module,android/native_app_glue) diff --git a/build/android/jni/Application.mk b/build/android/jni/Application.mk deleted file mode 100644 index f5eb96ed1..000000000 --- a/build/android/jni/Application.mk +++ /dev/null @@ -1,9 +0,0 @@ -APP_PLATFORM := ${APP_PLATFORM} -APP_ABI := ${TARGET_ABI} -APP_STL := c++_shared -APP_MODULES := minetest -ifndef NDEBUG -APP_OPTIM := debug -endif - -APP_CPPFLAGS += -fexceptions -std=c++11 -frtti diff --git a/build/android/jni/Deps.mk b/build/android/jni/Deps.mk deleted file mode 100644 index 73db2353f..000000000 --- a/build/android/jni/Deps.mk +++ /dev/null @@ -1,7 +0,0 @@ -APP_PLATFORM := ${APP_PLATFORM} -APP_ABI := ${TARGET_ABI} -APP_STL := c++_shared -APP_DEPRECATED_HEADERS := true - -APP_CFLAGS += ${TARGET_CFLAGS_ADDON} -APP_CPPFLAGS += ${TARGET_CXXFLAGS_ADDON} -fexceptions -std=c++11 diff --git a/build/android/jni/Irrlicht.mk b/build/android/jni/Irrlicht.mk deleted file mode 100644 index cedfe3139..000000000 --- a/build/android/jni/Irrlicht.mk +++ /dev/null @@ -1,8 +0,0 @@ -APP_PLATFORM := ${APP_PLATFORM} -APP_ABI := ${TARGET_ABI} -APP_STL := c++_shared -APP_DEPRECATED_HEADERS := true -APP_MODULES := Irrlicht - -APP_CLAFGS += ${TARGET_CFLAGS_ADDON} -APP_CPPFLAGS += ${TARGET_CXXFLAGS_ADDON} -fexceptions diff --git a/build/android/native/build.gradle b/build/android/native/build.gradle new file mode 100644 index 000000000..f06e4e3f0 --- /dev/null +++ b/build/android/native/build.gradle @@ -0,0 +1,59 @@ +apply plugin: 'com.android.library' +import org.ajoberstar.grgit.Grgit + +android { + compileSdkVersion 29 + buildToolsVersion '29.0.3' + ndkVersion '21.0.6113669' + defaultConfig { + minSdkVersion 16 + targetSdkVersion 29 + externalNativeBuild { + ndkBuild { + arguments '-j8', + "versionMajor=${versionMajor}", + "versionMinor=${versionMinor}", + "versionPatch=${versionPatch}", + "versionExtra=${versionExtra}" + } + } + } + + externalNativeBuild { + ndkBuild { + path file('jni/Android.mk') + } + } + + // supported architectures + splits { + abi { + enable true + reset() + include 'armeabi-v7a', 'arm64-v8a'//, 'x86' + } + } + + buildTypes { + release { + externalNativeBuild { + ndkBuild { + arguments 'NDEBUG=1' + } + } + } + } +} + +task cloneGitRepo() { + def destination = file('deps') + if(!destination.exists()) { + def grgit = Grgit.clone( + dir: destination, + uri: 'https://github.com/minetest/minetest_android_deps_binaries' + ) + grgit.close() + } +} + +preBuild.dependsOn cloneGitRepo diff --git a/build/android/native/jni/Android.mk b/build/android/native/jni/Android.mk new file mode 100644 index 000000000..a5cb099e6 --- /dev/null +++ b/build/android/native/jni/Android.mk @@ -0,0 +1,218 @@ +LOCAL_PATH := $(call my-dir)/.. + +#LOCAL_ADDRESS_SANITIZER:=true + +include $(CLEAR_VARS) +LOCAL_MODULE := Curl +LOCAL_SRC_FILES := deps/Android/Curl/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libcurl.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := Freetype +LOCAL_SRC_FILES := deps/Android/Freetype/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libfreetype.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := Irrlicht +LOCAL_SRC_FILES := deps/Android/Irrlicht/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libIrrlicht.a +include $(PREBUILT_STATIC_LIBRARY) + +#include $(CLEAR_VARS) +#LOCAL_MODULE := LevelDB +#LOCAL_SRC_FILES := deps/Android/LevelDB/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libleveldb.a +#include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := LuaJIT +LOCAL_SRC_FILES := deps/Android/LuaJIT/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libluajit.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := mbedTLS +LOCAL_SRC_FILES := deps/Android/mbedTLS/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libmbedtls.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := mbedx509 +LOCAL_SRC_FILES := deps/Android/mbedTLS/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libmbedx509.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := mbedcrypto +LOCAL_SRC_FILES := deps/Android/mbedTLS/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libmbedcrypto.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := OpenAL +LOCAL_SRC_FILES := deps/Android/OpenAL-Soft/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libopenal.a +include $(PREBUILT_STATIC_LIBRARY) + +# You can use `OpenSSL and Crypto` instead `mbedTLS mbedx509 mbedcrypto`, +#but it increase APK size on ~0.7MB +#include $(CLEAR_VARS) +#LOCAL_MODULE := OpenSSL +#LOCAL_SRC_FILES := deps/Android/OpenSSL/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libssl.a +#include $(PREBUILT_STATIC_LIBRARY) + +#include $(CLEAR_VARS) +#LOCAL_MODULE := Crypto +#LOCAL_SRC_FILES := deps/Android/OpenSSL/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libcrypto.a +#include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := Vorbis +LOCAL_SRC_FILES := deps/Android/Vorbis/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libvorbis.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := Minetest + +LOCAL_CFLAGS += \ + -DJSONCPP_NO_LOCALE_SUPPORT \ + -DHAVE_TOUCHSCREENGUI \ + -DENABLE_GLES=1 \ + -DUSE_CURL=1 \ + -DUSE_SOUND=1 \ + -DUSE_FREETYPE=1 \ + -DUSE_LEVELDB=0 \ + -DUSE_LUAJIT=1 \ + -DVERSION_MAJOR=${versionMajor} \ + -DVERSION_MINOR=${versionMinor} \ + -DVERSION_PATCH=${versionPatch} \ + -DVERSION_EXTRA=${versionExtra} \ + $(GPROF_DEF) + +ifdef NDEBUG + LOCAL_CFLAGS += -DNDEBUG=1 +endif + +ifdef GPROF + GPROF_DEF := -DGPROF + PROFILER_LIBS := android-ndk-profiler + LOCAL_CFLAGS += -pg +endif + +LOCAL_C_INCLUDES := \ + ../../../src \ + ../../../src/script \ + ../../../lib/gmp \ + ../../../lib/jsoncpp \ + deps/Android/Curl/include \ + deps/Android/Freetype/include \ + deps/Android/Irrlicht/include \ + deps/Android/LevelDB/include \ + deps/Android/libiconv/include \ + deps/Android/libiconv/libcharset/include \ + deps/Android/LuaJIT/src \ + deps/Android/OpenAL-Soft/include \ + deps/Android/sqlite \ + deps/Android/Vorbis/include + +LOCAL_SRC_FILES := \ + $(wildcard ../../../src/client/*.cpp) \ + $(wildcard ../../../src/client/*/*.cpp) \ + $(wildcard ../../../src/content/*.cpp) \ + ../../../src/database/database.cpp \ + ../../../src/database/database-dummy.cpp \ + ../../../src/database/database-files.cpp \ + ../../../src/database/database-sqlite3.cpp \ + $(wildcard ../../../src/gui/*.cpp) \ + $(wildcard ../../../src/irrlicht_changes/*.cpp) \ + $(wildcard ../../../src/mapgen/*.cpp) \ + $(wildcard ../../../src/network/*.cpp) \ + $(wildcard ../../../src/script/*.cpp) \ + $(wildcard ../../../src/script/*/*.cpp) \ + $(wildcard ../../../src/server/*.cpp) \ + $(wildcard ../../../src/threading/*.cpp) \ + $(wildcard ../../../src/util/*.c) \ + $(wildcard ../../../src/util/*.cpp) \ + ../../../src/ban.cpp \ + ../../../src/chat.cpp \ + ../../../src/clientiface.cpp \ + ../../../src/collision.cpp \ + ../../../src/content_mapnode.cpp \ + ../../../src/content_nodemeta.cpp \ + ../../../src/convert_json.cpp \ + ../../../src/craftdef.cpp \ + ../../../src/debug.cpp \ + ../../../src/defaultsettings.cpp \ + ../../../src/emerge.cpp \ + ../../../src/environment.cpp \ + ../../../src/face_position_cache.cpp \ + ../../../src/filesys.cpp \ + ../../../src/gettext.cpp \ + ../../../src/httpfetch.cpp \ + ../../../src/hud.cpp \ + ../../../src/inventory.cpp \ + ../../../src/inventorymanager.cpp \ + ../../../src/itemdef.cpp \ + ../../../src/itemstackmetadata.cpp \ + ../../../src/light.cpp \ + ../../../src/log.cpp \ + ../../../src/main.cpp \ + ../../../src/map.cpp \ + ../../../src/map_settings_manager.cpp \ + ../../../src/mapblock.cpp \ + ../../../src/mapnode.cpp \ + ../../../src/mapsector.cpp \ + ../../../src/metadata.cpp \ + ../../../src/modchannels.cpp \ + ../../../src/nameidmapping.cpp \ + ../../../src/nodedef.cpp \ + ../../../src/nodemetadata.cpp \ + ../../../src/nodetimer.cpp \ + ../../../src/noise.cpp \ + ../../../src/objdef.cpp \ + ../../../src/object_properties.cpp \ + ../../../src/pathfinder.cpp \ + ../../../src/player.cpp \ + ../../../src/porting.cpp \ + ../../../src/porting_android.cpp \ + ../../../src/profiler.cpp \ + ../../../src/raycast.cpp \ + ../../../src/reflowscan.cpp \ + ../../../src/remoteplayer.cpp \ + ../../../src/rollback.cpp \ + ../../../src/rollback_interface.cpp \ + ../../../src/serialization.cpp \ + ../../../src/server.cpp \ + ../../../src/serverenvironment.cpp \ + ../../../src/serverlist.cpp \ + ../../../src/settings.cpp \ + ../../../src/staticobject.cpp \ + ../../../src/texture_override.cpp \ + ../../../src/tileanimation.cpp \ + ../../../src/tool.cpp \ + ../../../src/translation.cpp \ + ../../../src/version.cpp \ + ../../../src/voxel.cpp \ + ../../../src/voxelalgorithms.cpp + +# LevelDB backend is disabled +# ../../../src/database/database-leveldb.cpp + +# GMP +LOCAL_SRC_FILES += ../../../lib/gmp/mini-gmp.c + +# JSONCPP +LOCAL_SRC_FILES += ../../../lib/jsoncpp/jsoncpp.cpp + +# iconv +LOCAL_SRC_FILES += \ + deps/Android/libiconv/lib/iconv.c \ + deps/Android/libiconv/libcharset/lib/localcharset.c + +# SQLite3 +LOCAL_SRC_FILES += deps/Android/sqlite/sqlite3.c + +LOCAL_STATIC_LIBRARIES += Curl Freetype Irrlicht OpenAL mbedTLS mbedx509 mbedcrypto Vorbis LuaJIT android_native_app_glue $(PROFILER_LIBS) #LevelDB +#OpenSSL Crypto + +LOCAL_LDLIBS := -lEGL -lGLESv1_CM -lGLESv2 -landroid -lOpenSLES + +include $(BUILD_SHARED_LIBRARY) + +ifdef GPROF +$(call import-module,android-ndk-profiler) +endif +$(call import-module,android/native_app_glue) diff --git a/build/android/native/jni/Application.mk b/build/android/native/jni/Application.mk new file mode 100644 index 000000000..82f0148f0 --- /dev/null +++ b/build/android/native/jni/Application.mk @@ -0,0 +1,32 @@ +APP_PLATFORM := ${APP_PLATFORM} +APP_ABI := ${TARGET_ABI} +APP_STL := c++_shared +NDK_TOOLCHAIN_VERSION := clang +APP_SHORT_COMMANDS := true +APP_MODULES := Minetest + +APP_CPPFLAGS := -Ofast -fvisibility=hidden -fexceptions -Wno-deprecated-declarations -Wno-extra-tokens + +ifeq ($(APP_ABI),armeabi-v7a) +APP_CPPFLAGS += -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb +endif + +#ifeq ($(APP_ABI),x86) +#APP_CPPFLAGS += -march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32 -funroll-loops +#endif + +ifndef NDEBUG +APP_CPPFLAGS := -g -D_DEBUG -O0 -fno-omit-frame-pointer -fexceptions +endif + +APP_CFLAGS := $(APP_CPPFLAGS) -Wno-parentheses-equality #-Werror=shorten-64-to-32 +APP_CXXFLAGS := $(APP_CPPFLAGS) -frtti -std=gnu++17 +APP_LDFLAGS := -Wl,--no-warn-mismatch,--gc-sections,--icf=safe + +ifeq ($(APP_ABI),arm64-v8a) +APP_LDFLAGS := -Wl,--no-warn-mismatch,--gc-sections +endif + +ifndef NDEBUG +APP_LDFLAGS := +endif diff --git a/build/android/native/src/main/AndroidManifest.xml b/build/android/native/src/main/AndroidManifest.xml new file mode 100644 index 000000000..19451c7fd --- /dev/null +++ b/build/android/native/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/build/android/patches/irrlicht-back_button.patch b/build/android/patches/irrlicht-back_button.patch deleted file mode 100644 index e17b81347..000000000 --- a/build/android/patches/irrlicht-back_button.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp.orig 2015-08-29 15:43:09.000000000 +0300 -+++ irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp 2016-05-13 21:36:22.880388505 +0300 -@@ -486,7 +486,7 @@ - event.KeyInput.Char = 0; - } - -- device->postEventFromUser(event); -+ status = device->postEventFromUser(event); - } - break; - default: -@@ -543,7 +543,7 @@ - KeyMap[1] = KEY_LBUTTON; // AKEYCODE_SOFT_LEFT - KeyMap[2] = KEY_RBUTTON; // AKEYCODE_SOFT_RIGHT - KeyMap[3] = KEY_HOME; // AKEYCODE_HOME -- KeyMap[4] = KEY_BACK; // AKEYCODE_BACK -+ KeyMap[4] = KEY_CANCEL; // AKEYCODE_BACK - KeyMap[5] = KEY_UNKNOWN; // AKEYCODE_CALL - KeyMap[6] = KEY_UNKNOWN; // AKEYCODE_ENDCALL - KeyMap[7] = KEY_KEY_0; // AKEYCODE_0 diff --git a/build/android/patches/irrlicht-native_activity.patch b/build/android/patches/irrlicht-native_activity.patch deleted file mode 100644 index a9d2610c3..000000000 --- a/build/android/patches/irrlicht-native_activity.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- irrlicht/source/Irrlicht/CEGLManager.cpp.orig 2018-09-11 18:19:51.453403631 +0300 -+++ irrlicht/source/Irrlicht/CEGLManager.cpp 2018-09-11 18:36:24.603471869 +0300 -@@ -9,6 +9,10 @@ - #include "irrString.h" - #include "os.h" - -+#if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) -+#include -+#endif -+ - namespace irr - { - namespace video diff --git a/build/android/patches/irrlicht-texturehack.patch b/build/android/patches/irrlicht-texturehack.patch deleted file mode 100644 index a458ede72..000000000 --- a/build/android/patches/irrlicht-texturehack.patch +++ /dev/null @@ -1,240 +0,0 @@ ---- irrlicht/source/Irrlicht/COGLESTexture.cpp.orig 2014-06-22 17:01:13.266568869 +0200 -+++ irrlicht/source/Irrlicht/COGLESTexture.cpp 2014-06-22 17:03:59.298572810 +0200 -@@ -366,112 +366,140 @@ - void(*convert)(const void*, s32, void*) = 0; - getFormatParameters(ColorFormat, InternalFormat, filtering, PixelFormat, PixelType, convert); - -- // make sure we don't change the internal format of existing images -- if (!newTexture) -- InternalFormat = oldInternalFormat; -- -- Driver->setActiveTexture(0, this); -- -- if (Driver->testGLError()) -- os::Printer::log("Could not bind Texture", ELL_ERROR); -- -- // mipmap handling for main texture -- if (!level && newTexture) -- { -- // auto generate if possible and no mipmap data is given -- if (!IsCompressed && HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) -- { -- if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) -- glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST); -- else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY)) -- glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); -- else -- glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); -+ bool retry = false; -+ -+ do { -+ if (retry) { -+ InternalFormat = GL_RGBA; -+ PixelFormat = GL_RGBA; -+ convert = CColorConverter::convert_A8R8G8B8toA8B8G8R8; -+ } -+ // make sure we don't change the internal format of existing images -+ if (!newTexture) -+ InternalFormat = oldInternalFormat; - -- glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); -- AutomaticMipmapUpdate=true; -- } -+ Driver->setActiveTexture(0, this); - -- // enable bilinear filter without mipmaps -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); -- } -+ if (Driver->testGLError()) -+ os::Printer::log("Could not bind Texture", ELL_ERROR); - -- // now get image data and upload to GPU -+ // mipmap handling for main texture -+ if (!level && newTexture) -+ { -+ // auto generate if possible and no mipmap data is given -+ if (!IsCompressed && HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) -+ { -+ if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) -+ glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST); -+ else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY)) -+ glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); -+ else -+ glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); -+ -+ glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); -+ AutomaticMipmapUpdate=true; -+ } -+ -+ // enable bilinear filter without mipmaps -+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); -+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); -+ } - -- u32 compressedImageSize = IImage::getCompressedImageSize(ColorFormat, image->getDimension().Width, image->getDimension().Height); -+ // now get image data and upload to GPU - -- void* source = image->lock(); -+ u32 compressedImageSize = IImage::getCompressedImageSize(ColorFormat, image->getDimension().Width, image->getDimension().Height); - -- IImage* tmpImage = 0; -+ void* source = image->lock(); - -- if (convert) -- { -- tmpImage = new CImage(image->getColorFormat(), image->getDimension()); -- void* dest = tmpImage->lock(); -- convert(source, image->getDimension().getArea(), dest); -- image->unlock(); -- source = dest; -- } -+ IImage* tmpImage = 0; - -- if (newTexture) -- { -- if (IsCompressed) -+ if (convert) - { -- glCompressedTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, image->getDimension().Width, -- image->getDimension().Height, 0, compressedImageSize, source); -+ tmpImage = new CImage(image->getColorFormat(), image->getDimension()); -+ void* dest = tmpImage->lock(); -+ convert(source, image->getDimension().getArea(), dest); -+ image->unlock(); -+ source = dest; - } -- else -- glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width, -- image->getDimension().Height, 0, PixelFormat, PixelType, source); -- } -- else -- { -- if (IsCompressed) -+ -+ if (newTexture) - { -- glCompressedTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width, -- image->getDimension().Height, PixelFormat, compressedImageSize, source); -+ if (IsCompressed) -+ { -+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, image->getDimension().Width, -+ image->getDimension().Height, 0, compressedImageSize, source); -+ } -+ else -+ glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width, -+ image->getDimension().Height, 0, PixelFormat, PixelType, source); - } - else -- glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width, -- image->getDimension().Height, PixelFormat, PixelType, source); -- } -- -- if (convert) -- { -- tmpImage->unlock(); -- tmpImage->drop(); -- } -- else -- image->unlock(); -- -- if (!level && newTexture) -- { -- if (IsCompressed && !mipmapData) - { -- if (image->hasMipMaps()) -- mipmapData = static_cast(image->lock())+compressedImageSize; -+ if (IsCompressed) -+ { -+ glCompressedTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width, -+ image->getDimension().Height, PixelFormat, compressedImageSize, source); -+ } - else -- HasMipMaps = false; -+ glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width, -+ image->getDimension().Height, PixelFormat, PixelType, source); - } - -- regenerateMipMapLevels(mipmapData); -- -- if (HasMipMaps) // might have changed in regenerateMipMapLevels -+ if (convert) - { -- // enable bilinear mipmap filter -- GLint filteringMipMaps = GL_LINEAR_MIPMAP_NEAREST; -- -- if (filtering != GL_LINEAR) -- filteringMipMaps = GL_NEAREST_MIPMAP_NEAREST; -+ tmpImage->unlock(); -+ tmpImage->drop(); -+ } -+ else -+ image->unlock(); -+ -+ if (glGetError() != GL_NO_ERROR) { -+ static bool warned = false; -+ if ((!retry) && (ColorFormat == ECF_A8R8G8B8)) { -+ -+ if (!warned) { -+ os::Printer::log("Your driver claims to support GL_BGRA but fails on trying to upload a texture, converting to GL_RGBA and trying again", ELL_ERROR); -+ warned = true; -+ } -+ } -+ else if (retry) { -+ os::Printer::log("Neither uploading texture as GL_BGRA nor, converted one using GL_RGBA succeeded", ELL_ERROR); -+ } -+ retry = !retry; -+ continue; -+ } else { -+ retry = false; -+ } - -- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filteringMipMaps); -- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); -+ if (!level && newTexture) -+ { -+ if (IsCompressed && !mipmapData) -+ { -+ if (image->hasMipMaps()) -+ mipmapData = static_cast(image->lock())+compressedImageSize; -+ else -+ HasMipMaps = false; -+ } -+ -+ regenerateMipMapLevels(mipmapData); -+ -+ if (HasMipMaps) // might have changed in regenerateMipMapLevels -+ { -+ // enable bilinear mipmap filter -+ GLint filteringMipMaps = GL_LINEAR_MIPMAP_NEAREST; -+ -+ if (filtering != GL_LINEAR) -+ filteringMipMaps = GL_NEAREST_MIPMAP_NEAREST; -+ -+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filteringMipMaps); -+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); -+ } - } -- } - -- if (Driver->testGLError()) -- os::Printer::log("Could not glTexImage2D", ELL_ERROR); -+ if (Driver->testGLError()) -+ os::Printer::log("Could not glTexImage2D", ELL_ERROR); -+ } -+ while(retry); - } - - ---- irrlicht/source/Irrlicht/COGLESTexture.cpp.orig 2014-06-25 00:28:50.820501856 +0200 -+++ irrlicht/source/Irrlicht/COGLESTexture.cpp 2014-06-25 00:08:37.712544692 +0200 -@@ -422,6 +422,9 @@ - source = dest; - } - -+ //clear old error -+ glGetError(); -+ - if (newTexture) - { - if (IsCompressed) diff --git a/build/android/patches/irrlicht-touchcount.patch b/build/android/patches/irrlicht-touchcount.patch deleted file mode 100644 index d4e4b9c3e..000000000 --- a/build/android/patches/irrlicht-touchcount.patch +++ /dev/null @@ -1,30 +0,0 @@ ---- irrlicht.orig/include/IEventReceiver.h 2014-06-03 19:43:50.433713133 +0200 -+++ irrlicht/include/IEventReceiver.h 2014-06-03 19:44:36.993711489 +0200 -@@ -375,6 +375,9 @@ - // Y position of simple touch. - s32 Y; - -+ // number of current touches -+ s32 touchedCount; -+ - //! Type of touch event. - ETOUCH_INPUT_EVENT Event; - }; ---- irrlicht.orig/source/Irrlicht/Android/CIrrDeviceAndroid.cpp 2014-06-03 19:43:50.505713130 +0200 -+++ irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp 2014-06-03 19:45:37.265709359 +0200 -@@ -315,6 +315,7 @@ - event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, i); - event.TouchInput.X = AMotionEvent_getX(androidEvent, i); - event.TouchInput.Y = AMotionEvent_getY(androidEvent, i); -+ event.TouchInput.touchedCount = AMotionEvent_getPointerCount(androidEvent); - - device->postEventFromUser(event); - } -@@ -326,6 +327,7 @@ - event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, pointerIndex); - event.TouchInput.X = AMotionEvent_getX(androidEvent, pointerIndex); - event.TouchInput.Y = AMotionEvent_getY(androidEvent, pointerIndex); -+ event.TouchInput.touchedCount = AMotionEvent_getPointerCount(androidEvent); - - device->postEventFromUser(event); - } diff --git a/build/android/patches/libvorbis-libogg-fpu.patch b/build/android/patches/libvorbis-libogg-fpu.patch deleted file mode 100644 index 52ab397ac..000000000 --- a/build/android/patches/libvorbis-libogg-fpu.patch +++ /dev/null @@ -1,37 +0,0 @@ ---- libvorbis-libogg-android/jni/libvorbis-jni/Android.mk.orig 2014-06-17 19:22:50.621559073 +0200 -+++ libvorbis-libogg-android/jni/libvorbis-jni/Android.mk 2014-06-17 19:38:20.641581140 +0200 -@@ -4,9 +4,6 @@ - - LOCAL_MODULE := vorbis-jni - LOCAL_CFLAGS += -I$(LOCAL_PATH)/../include -fsigned-char --ifeq ($(TARGET_ARCH),arm) -- LOCAL_CFLAGS += -march=armv6 -marm -mfloat-abi=softfp -mfpu=vfp --endif - - LOCAL_SHARED_LIBRARIES := libogg libvorbis - ---- libvorbis-libogg-android/jni/libvorbis/Android.mk.orig 2014-06-17 19:22:39.077558797 +0200 -+++ libvorbis-libogg-android/jni/libvorbis/Android.mk 2014-06-17 19:38:52.121581887 +0200 -@@ -4,9 +4,6 @@ - - LOCAL_MODULE := libvorbis - LOCAL_CFLAGS += -I$(LOCAL_PATH)/../include -ffast-math -fsigned-char --ifeq ($(TARGET_ARCH),arm) -- LOCAL_CFLAGS += -march=armv6 -marm -mfloat-abi=softfp -mfpu=vfp --endif - LOCAL_SHARED_LIBRARIES := libogg - - LOCAL_SRC_FILES := \ ---- libvorbis-libogg-android/jni/libogg/Android.mk.orig 2014-06-17 19:22:33.965558675 +0200 -+++ libvorbis-libogg-android/jni/libogg/Android.mk 2014-06-17 19:38:25.337581252 +0200 -@@ -4,10 +4,6 @@ - - LOCAL_MODULE := libogg - LOCAL_CFLAGS += -I$(LOCAL_PATH)/../include -ffast-math -fsigned-char --ifeq ($(TARGET_ARCH),arm) -- LOCAL_CFLAGS += -march=armv6 -marm -mfloat-abi=softfp -mfpu=vfp --endif -- - - LOCAL_SRC_FILES := \ - bitwise.c \ diff --git a/build/android/patches/openssl_arch.patch b/build/android/patches/openssl_arch.patch deleted file mode 100644 index d15e2b137..000000000 --- a/build/android/patches/openssl_arch.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- openssl-1.0.2e.orig/Configure 2015-12-03 15:04:23.000000000 +0100 -+++ openssl-1.0.2e/Configure 2015-12-14 21:01:40.351265968 +0100 -@@ -464,8 +464,10 @@ - # Android: linux-* but without pointers to headers and libs. - "android","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", - "android-x86","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-arm","gcc:-march=armv4 -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", - "android-armv7","gcc:-march=armv7-a -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", - "android-mips","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-mips32","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", - - #### *BSD [do see comment about ${BSDthreads} above!] - "BSD-generic32","gcc:-O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", diff --git a/build/android/settings.gradle b/build/android/settings.gradle index b0cee5dad..b048fca7c 100644 --- a/build/android/settings.gradle +++ b/build/android/settings.gradle @@ -1 +1,2 @@ rootProject.name = "Minetest" +include ':app', ':native' diff --git a/build/android/src/main/AndroidManifest.xml b/build/android/src/main/AndroidManifest.xml deleted file mode 100644 index fb1de9cf0..000000000 --- a/build/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/android/src/main/java/net.minetest.minetest/MainActivity.java b/build/android/src/main/java/net.minetest.minetest/MainActivity.java deleted file mode 100644 index 71b0ce144..000000000 --- a/build/android/src/main/java/net.minetest.minetest/MainActivity.java +++ /dev/null @@ -1,77 +0,0 @@ -package net.minetest.minetest; - -import android.Manifest; -import android.app.Activity; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.os.Build; -import android.os.Bundle; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class MainActivity extends Activity { - private final static int PERMISSIONS = 1; - private static final String[] REQUIRED_SDK_PERMISSIONS = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - checkPermission(); - } else { - next(); - } - } - - private void checkPermission() { - final List missingPermissions = new ArrayList<>(); - // check required permission - for (final String permission : REQUIRED_SDK_PERMISSIONS) { - final int result = ContextCompat.checkSelfPermission(this, permission); - if (result != PackageManager.PERMISSION_GRANTED) { - missingPermissions.add(permission); - } - } - if (!missingPermissions.isEmpty()) { - // request permission - final String[] permissions = missingPermissions - .toArray(new String[0]); - ActivityCompat.requestPermissions(this, permissions, PERMISSIONS); - } else { - final int[] grantResults = new int[REQUIRED_SDK_PERMISSIONS.length]; - Arrays.fill(grantResults, PackageManager.PERMISSION_GRANTED); - onRequestPermissionsResult(PERMISSIONS, REQUIRED_SDK_PERMISSIONS, - grantResults); - } - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, - @NonNull int[] grantResults) { - if (requestCode == PERMISSIONS) { - for (int index = 0; index < permissions.length; index++) { - if (grantResults[index] != PackageManager.PERMISSION_GRANTED) { - // permission not granted - toast and exit - Toast.makeText(this, R.string.not_granted, Toast.LENGTH_LONG).show(); - finish(); - return; - } - } - // permission were granted - run - next(); - } - } - - private void next() { - Intent intent = new Intent(this, MtNativeActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK); - startActivity(intent); - } -} diff --git a/build/android/src/main/java/net.minetest.minetest/MinetestAssetCopy.java b/build/android/src/main/java/net.minetest.minetest/MinetestAssetCopy.java deleted file mode 100644 index 84cfca796..000000000 --- a/build/android/src/main/java/net.minetest.minetest/MinetestAssetCopy.java +++ /dev/null @@ -1,371 +0,0 @@ -package net.minetest.minetest; - -import android.annotation.SuppressLint; -import android.app.Activity; -import android.content.res.AssetFileDescriptor; -import android.os.AsyncTask; -import android.os.Build; -import android.os.Bundle; -import android.os.Environment; -import android.util.Log; -import android.view.Display; -import android.view.View; -import android.widget.ProgressBar; -import android.widget.TextView; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.util.Vector; - -public class MinetestAssetCopy extends Activity { - private ProgressBar m_ProgressBar; - private TextView m_Filename; - private copyAssetTask m_AssetCopy; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.assetcopy); - m_ProgressBar = findViewById(R.id.progressBar1); - m_Filename = findViewById(R.id.textView1); - Display display = getWindowManager().getDefaultDisplay(); - m_ProgressBar.getLayoutParams().width = (int) (display.getWidth() * 0.8); - m_ProgressBar.invalidate(); - - /* check if there's already a copy in progress and reuse in case it is*/ - MinetestAssetCopy prevActivity = - (MinetestAssetCopy) getLastNonConfigurationInstance(); - if (prevActivity != null) { - m_AssetCopy = prevActivity.m_AssetCopy; - } else { - m_AssetCopy = new copyAssetTask(); - m_AssetCopy.execute(); - } - } - - @Override - protected void onResume() { - super.onResume(); - makeFullScreen(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - if (m_AssetCopy != null) { - m_AssetCopy.cancel(true); - } - } - - private void makeFullScreen() { - if (Build.VERSION.SDK_INT >= 19) - this.getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - if (hasFocus) - makeFullScreen(); - } - - /* preserve asset copy background task to prevent restart of copying */ - /* this way of doing it is not recommended for latest android version */ - /* but the recommended way isn't available on android 2.x */ - public Object onRetainNonConfigurationInstance() { - return this; - } - - @SuppressLint("StaticFieldLeak") - private class copyAssetTask extends AsyncTask { - boolean m_copy_started = false; - String m_Foldername = "media"; - Vector m_foldernames; - Vector m_filenames; - Vector m_tocopy; - Vector m_asset_size_unknown; - - private long getFullSize(String filename) { - long size = 0; - try { - InputStream src = getAssets().open(filename); - byte[] buf = new byte[4096]; - - int len; - while ((len = src.read(buf)) > 0) { - size += len; - } - } catch (IOException e) { - e.printStackTrace(); - } - return size; - } - - @Override - protected String doInBackground(String... files) { - m_foldernames = new Vector<>(); - m_filenames = new Vector<>(); - m_tocopy = new Vector<>(); - m_asset_size_unknown = new Vector<>(); - String baseDir = - Environment.getExternalStorageDirectory().getAbsolutePath() - + "/"; - - - // prepare temp folder - File TempFolder = new File(baseDir + "Minetest/tmp/"); - - if (!TempFolder.exists()) { - TempFolder.mkdir(); - } else { - File[] todel = TempFolder.listFiles(); - - for (File file : todel) { - Log.v("MinetestAssetCopy", "deleting: " + file.getAbsolutePath()); - file.delete(); - } - } - - // add a .nomedia file - try { - OutputStream dst = new FileOutputStream(baseDir + "Minetest/.nomedia"); - dst.close(); - } catch (IOException e) { - Log.e("MinetestAssetCopy", "Failed to create .nomedia file"); - e.printStackTrace(); - } - - - // build lists from prepared data - BuildFolderList(); - BuildFileList(); - - // scan filelist - ProcessFileList(); - - // doing work - m_copy_started = true; - m_ProgressBar.setMax(m_tocopy.size()); - - for (int i = 0; i < m_tocopy.size(); i++) { - try { - String filename = m_tocopy.get(i); - publishProgress(i); - - boolean asset_size_unknown = false; - long filesize = -1; - - if (m_asset_size_unknown.contains(filename)) { - File testme = new File(baseDir + "/" + filename); - - if (testme.exists()) - filesize = testme.length(); - - asset_size_unknown = true; - } - - InputStream src; - try { - src = getAssets().open(filename); - } catch (IOException e) { - Log.e("MinetestAssetCopy", "Copying file: " + filename + " FAILED (not in assets)"); - e.printStackTrace(); - continue; - } - - // Transfer bytes from in to out - byte[] buf = new byte[1024]; - int len = src.read(buf, 0, 1024); - - /* following handling is crazy but we need to deal with */ - /* compressed assets.Flash chips limited livetime due to */ - /* write operations, we can't allow large files to destroy */ - /* users flash. */ - if (asset_size_unknown) { - if ((len > 0) && (len < buf.length) && (len == filesize)) { - src.close(); - continue; - } - - if (len == buf.length) { - src.close(); - long size = getFullSize(filename); - if (size == filesize) { - continue; - } - src = getAssets().open(filename); - len = src.read(buf, 0, 1024); - } - } - if (len > 0) { - int total_filesize = 0; - OutputStream dst; - try { - dst = new FileOutputStream(baseDir + "/" + filename); - } catch (IOException e) { - Log.e("MinetestAssetCopy", "Copying file: " + baseDir + - "/" + filename + " FAILED (couldn't open output file)"); - e.printStackTrace(); - src.close(); - continue; - } - dst.write(buf, 0, len); - total_filesize += len; - - while ((len = src.read(buf)) > 0) { - dst.write(buf, 0, len); - total_filesize += len; - } - - dst.close(); - Log.v("MinetestAssetCopy", "Copied file: " + - m_tocopy.get(i) + " (" + total_filesize + - " bytes)"); - } else if (len < 0) { - Log.e("MinetestAssetCopy", "Copying file: " + - m_tocopy.get(i) + " failed, size < 0"); - } - src.close(); - } catch (IOException e) { - Log.e("MinetestAssetCopy", "Copying file: " + - m_tocopy.get(i) + " failed"); - e.printStackTrace(); - } - } - return ""; - } - - /** - * update progress bar - */ - protected void onProgressUpdate(Integer... progress) { - - if (m_copy_started) { - String todisplay = m_tocopy.get(progress[0]); - m_ProgressBar.setProgress(progress[0]); - m_Filename.setText(todisplay); - } else { - String todisplay = m_Foldername; - String full_text = "scanning " + todisplay + " ..."; - m_Filename.setText(full_text); - } - } - - /** - * check all files and folders in filelist - */ - void ProcessFileList() { - String FlashBaseDir = - Environment.getExternalStorageDirectory().getAbsolutePath(); - - for (String current_path : m_filenames) { - String FlashPath = FlashBaseDir + "/" + current_path; - - if (isAssetFolder(current_path)) { - /* store information and update gui */ - m_Foldername = current_path; - publishProgress(0); - - /* open file in order to check if it's a folder */ - File current_folder = new File(FlashPath); - if (!current_folder.exists()) { - if (!current_folder.mkdirs()) { - Log.e("MinetestAssetCopy", "\t failed create folder: " + - FlashPath); - } else { - Log.v("MinetestAssetCopy", "\t created folder: " + - FlashPath); - } - } - - continue; - } - - /* if it's not a folder it's most likely a file */ - boolean refresh = true; - - File testme = new File(FlashPath); - - long asset_filesize = -1; - long stored_filesize; - - if (testme.exists()) { - try { - AssetFileDescriptor fd = getAssets().openFd(current_path); - asset_filesize = fd.getLength(); - fd.close(); - } catch (IOException e) { - m_asset_size_unknown.add(current_path); - Log.e("MinetestAssetCopy", "Failed to open asset file \"" + - FlashPath + "\" for size check"); - } - - stored_filesize = testme.length(); - - if (asset_filesize == stored_filesize) - refresh = false; - - } - - if (refresh) - m_tocopy.add(current_path); - } - } - - /** - * read list of folders prepared on package build - */ - void BuildFolderList() { - try { - InputStream is = getAssets().open("index.txt"); - BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - - String line = reader.readLine(); - while (line != null) { - m_foldernames.add(line); - line = reader.readLine(); - } - is.close(); - } catch (IOException e1) { - Log.e("MinetestAssetCopy", "Error on processing index.txt"); - e1.printStackTrace(); - } - } - - /** - * read list of asset files prepared on package build - */ - void BuildFileList() { - long entrycount = 0; - try { - InputStream is = getAssets().open("filelist.txt"); - BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - - String line = reader.readLine(); - while (line != null) { - m_filenames.add(line); - line = reader.readLine(); - entrycount++; - } - is.close(); - } catch (IOException e1) { - Log.e("MinetestAssetCopy", "Error on processing filelist.txt"); - e1.printStackTrace(); - } - } - - protected void onPostExecute(String result) { - finish(); - } - - boolean isAssetFolder(String path) { - return m_foldernames.contains(path); - } - } -} diff --git a/build/android/src/main/java/net.minetest.minetest/MinetestTextEntry.java b/build/android/src/main/java/net.minetest.minetest/MinetestTextEntry.java deleted file mode 100644 index cb7ba8d3b..000000000 --- a/build/android/src/main/java/net.minetest.minetest/MinetestTextEntry.java +++ /dev/null @@ -1,87 +0,0 @@ -package net.minetest.minetest; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.os.Bundle; -import android.text.InputType; -import android.view.KeyEvent; -import android.view.View; -import android.view.View.OnKeyListener; -import android.widget.EditText; - -public class MinetestTextEntry extends Activity { - private final int MultiLineTextInput = 1; - private final int SingleLineTextInput = 2; - private final int SingleLinePasswordInput = 3; - private AlertDialog mTextInputDialog; - private EditText mTextInputWidget; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Bundle b = getIntent().getExtras(); - String acceptButton = b.getString("EnterButton"); - String hint = b.getString("hint"); - String current = b.getString("current"); - int editType = b.getInt("editType"); - - AlertDialog.Builder builder = new AlertDialog.Builder(this); - mTextInputWidget = new EditText(this); - mTextInputWidget.setHint(hint); - mTextInputWidget.setText(current); - mTextInputWidget.setMinWidth(300); - if (editType == SingleLinePasswordInput) { - mTextInputWidget.setInputType(InputType.TYPE_CLASS_TEXT | - InputType.TYPE_TEXT_VARIATION_PASSWORD); - } else { - mTextInputWidget.setInputType(InputType.TYPE_CLASS_TEXT); - } - - builder.setView(mTextInputWidget); - - if (editType == MultiLineTextInput) { - builder.setPositiveButton(acceptButton, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - pushResult(mTextInputWidget.getText().toString()); - } - }); - } - - builder.setOnCancelListener(new DialogInterface.OnCancelListener() { - public void onCancel(DialogInterface dialog) { - cancelDialog(); - } - }); - - mTextInputWidget.setOnKeyListener(new OnKeyListener() { - @Override - public boolean onKey(View view, int KeyCode, KeyEvent event) { - if (KeyCode == KeyEvent.KEYCODE_ENTER) { - - pushResult(mTextInputWidget.getText().toString()); - return true; - } - return false; - } - }); - - mTextInputDialog = builder.create(); - mTextInputDialog.show(); - } - - private void pushResult(String text) { - Intent resultData = new Intent(); - resultData.putExtra("text", text); - setResult(Activity.RESULT_OK, resultData); - mTextInputDialog.dismiss(); - finish(); - } - - private void cancelDialog() { - setResult(Activity.RESULT_CANCELED); - mTextInputDialog.dismiss(); - finish(); - } -} diff --git a/build/android/src/main/java/net.minetest.minetest/MtNativeActivity.java b/build/android/src/main/java/net.minetest.minetest/MtNativeActivity.java deleted file mode 100644 index f49d078fe..000000000 --- a/build/android/src/main/java/net.minetest.minetest/MtNativeActivity.java +++ /dev/null @@ -1,108 +0,0 @@ -package net.minetest.minetest; - -import android.app.NativeActivity; -import android.content.Intent; -import android.os.Build; -import android.os.Bundle; -import android.view.View; -import android.view.WindowManager; - -public class MtNativeActivity extends NativeActivity { - - static { - System.loadLibrary("c++_shared"); - System.loadLibrary("openal"); - System.loadLibrary("ogg"); - System.loadLibrary("vorbis"); - System.loadLibrary("iconv"); - System.loadLibrary("minetest"); - } - - private int m_MessagReturnCode; - private String m_MessageReturnValue; - - public static native void putMessageBoxResult(String text); - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - m_MessagReturnCode = -1; - m_MessageReturnValue = ""; - } - - @Override - protected void onResume() { - super.onResume(); - makeFullScreen(); - } - - private void makeFullScreen() { - if (Build.VERSION.SDK_INT >= 19) - this.getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - if (hasFocus) - makeFullScreen(); - } - - public void copyAssets() { - Intent intent = new Intent(this, MinetestAssetCopy.class); - startActivity(intent); - } - - public void showDialog(String acceptButton, String hint, String current, - int editType) { - - Intent intent = new Intent(this, MinetestTextEntry.class); - Bundle params = new Bundle(); - params.putString("acceptButton", acceptButton); - params.putString("hint", hint); - params.putString("current", current); - params.putInt("editType", editType); - intent.putExtras(params); - startActivityForResult(intent, 101); - m_MessageReturnValue = ""; - m_MessagReturnCode = -1; - } - - /* ugly code to workaround putMessageBoxResult not beeing found */ - public int getDialogState() { - return m_MessagReturnCode; - } - - public String getDialogValue() { - m_MessagReturnCode = -1; - return m_MessageReturnValue; - } - - public float getDensity() { - return getResources().getDisplayMetrics().density; - } - - public int getDisplayWidth() { - return getResources().getDisplayMetrics().widthPixels; - } - - public int getDisplayHeight() { - return getResources().getDisplayMetrics().heightPixels; - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, - Intent data) { - if (requestCode == 101) { - if (resultCode == RESULT_OK) { - String text = data.getStringExtra("text"); - m_MessagReturnCode = 0; - m_MessageReturnValue = text; - } else { - m_MessagReturnCode = 1; - } - } - } -} diff --git a/build/android/src/main/res/drawable/background.png b/build/android/src/main/res/drawable/background.png deleted file mode 100644 index 43bd6089e..000000000 Binary files a/build/android/src/main/res/drawable/background.png and /dev/null differ diff --git a/build/android/src/main/res/drawable/bg.xml b/build/android/src/main/res/drawable/bg.xml deleted file mode 100644 index c76ec372d..000000000 --- a/build/android/src/main/res/drawable/bg.xml +++ /dev/null @@ -1,4 +0,0 @@ - - \ No newline at end of file diff --git a/build/android/src/main/res/layout/assetcopy.xml b/build/android/src/main/res/layout/assetcopy.xml deleted file mode 100644 index b3da2f027..000000000 --- a/build/android/src/main/res/layout/assetcopy.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - diff --git a/build/android/src/main/res/mipmap/ic_launcher.png b/build/android/src/main/res/mipmap/ic_launcher.png deleted file mode 100644 index 88a83782c..000000000 Binary files a/build/android/src/main/res/mipmap/ic_launcher.png and /dev/null differ diff --git a/build/android/src/main/res/values-v21/styles.xml b/build/android/src/main/res/values-v21/styles.xml deleted file mode 100644 index 8b0777467..000000000 --- a/build/android/src/main/res/values-v21/styles.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - diff --git a/build/android/src/main/res/values/strings.xml b/build/android/src/main/res/values/strings.xml deleted file mode 100644 index a5eaef5d1..000000000 --- a/build/android/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - Preparing media… - Required permission wasn\'t granted, Minetest can\'t run without it - \ No newline at end of file diff --git a/build/android/src/main/res/values/styles.xml b/build/android/src/main/res/values/styles.xml deleted file mode 100644 index 1bd41ae76..000000000 --- a/build/android/src/main/res/values/styles.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - diff --git a/doc/README.android b/doc/README.android index c21279583..f6b67978f 100644 --- a/doc/README.android +++ b/doc/README.android @@ -1,6 +1,5 @@ -Minetest Android port -===================== -Date: 2014 06 28 +Minetest: Android version +========================= Controls -------- @@ -40,25 +39,6 @@ file can usually be found at /mnt/sdcard/Minetest. main menu is too big or small on your device, try changing this value. -Known issues ------------- -Not all issues are fixed by now: - -* Unable to exit from volume menu -- don't use the volume menu, use Android's - volume controls instead. -* 512 MB RAM seems to be inadequate -- this depends on the server you join. - Try to play on more lightweight servers. - -Versioning ----------- -Android version numbers are 4 digits instead of Minetest's 3 digits. The last -number of Android's version represents the Android internal version code. This -version code is strictly incremental. It's incremented for each official -Minetest Android build. - -E.g. prerelease Minetest Android builds have been 0.4.9.3, while the first -official version most likely will be 0.4.10.4 - Requirements ------------ @@ -69,9 +49,9 @@ following software packages. The version number in parenthesis denotes the version that was tested at the time this README was drafted; newer/older versions may or may not work. -* android SDK (api-26) -* android NDK (r17c) -* wget (1.13.4) +* Android SDK 29 +* Android NDK r21 +* Android Studio 3 [optional] Additionally, you'll need to have an Internet connection available on the build system, as the Android build will download some source packages. @@ -79,16 +59,15 @@ build system, as the Android build will download some source packages. Build ----- -Debug build: -* Enter "build/android" subdirectory -* Execute "make" -* Answer the questions about where SDK and NDK are located on your filesystem -* Wait for build to finish - -After the build is finished, the resulting apk can be fond in -build/android/bin/. It will be called Minetest-debug.apk +The new build system Minetest Android is fully functional and is designed to +speed up and simplify the work, as well as adding the possibility of +cross-platform build. +You can use `./gradlew assemblerelease` or `./gradlew assembledebug` from the +command line or use Android Studio and click the build button. -Release build: +When using gradlew, the newest NDK will be downloaded and installed +automatically. Or you can create a `local.properties` file and specify +`sdk.dir` and `ndk.dir` yourself. * In order to make a release build you'll have to have a keystore setup to sign the resulting apk package. How this is done is not part of this README. There @@ -97,32 +76,6 @@ Release build: * Once your keystore is setup, enter build/android subdirectory and create a new file "ant.properties" there. Add following lines to that file: - + > key.store= > key.alias=Minetest - -* Execute "make release" -* Enter your keystore as well as your Mintest key password once asked. Be - careful it's shown on console in clear text! -* The result can be found at "bin/Minetest-release.apk" - -Other things that may be nice to know ------------- -* The environment for Android development tools is saved within Android build - build folder. If you want direct access to it do: - - > make envpaths - > . and_env - - After you've done this you'll have your path and path variables set correct - to use adb and all other Android development tools - -* You can build a single dependency by calling make and the dependency's name, - e.g.: - - > make irrlicht - -* You can completely cleanup a dependency by calling make and the "clean" target, - e.g.: - - > make clean_irrlicht diff --git a/src/config.h b/src/config.h index 039100914..9d58a8cc1 100644 --- a/src/config.h +++ b/src/config.h @@ -11,12 +11,12 @@ #if defined USE_CMAKE_CONFIG_H #include "cmake_config.h" -#elif defined (__ANDROID__) || defined (ANDROID) +#elif defined (__ANDROID__) #define PROJECT_NAME "minetest" #define PROJECT_NAME_C "Minetest" #define STATIC_SHAREDIR "" - #include "android_version.h" - #ifdef NDEBUG + #define VERSION_STRING STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_PATCH) STR(VERSION_EXTRA) +#ifdef NDEBUG #define BUILD_TYPE "Release" #else #define BUILD_TYPE "Debug" diff --git a/src/main.cpp b/src/main.cpp index 8df2fe7d3..db020661a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -457,7 +457,6 @@ static bool create_userdata_path() } else { success = true; } - porting::copyAssets(); #else // Create user data directory success = fs::CreateDir(porting::path_user); diff --git a/src/porting_android.cpp b/src/porting_android.cpp index 7c74f7b5b..4130bdb6d 100644 --- a/src/porting_android.cpp +++ b/src/porting_android.cpp @@ -69,10 +69,10 @@ void android_main(android_app *app) /* TODO this doesn't work as expected, no idea why but there's a workaround */ /* for it right now */ extern "C" { - JNIEXPORT void JNICALL Java_net_minetest_MtNativeActivity_putMessageBoxResult( + JNIEXPORT void JNICALL Java_net_minetest_minetest_GameActivity_putMessageBoxResult( JNIEnv * env, jclass thiz, jstring text) { - errorstream << "Java_net_minetest_MtNativeActivity_putMessageBoxResult got: " + errorstream << "Java_net_minetest_minetest_GameActivity_putMessageBoxResult got: " << std::string((const char*)env->GetStringChars(text,0)) << std::endl; } @@ -107,17 +107,6 @@ jclass findClass(std::string classname) return (jclass) jnienv->CallObjectMethod(cls, findClass, strClassName); } -void copyAssets() -{ - jmethodID assetcopy = jnienv->GetMethodID(nativeActivity,"copyAssets","()V"); - - if (assetcopy == 0) { - assert("porting::copyAssets unable to find copy assets method" == 0); - } - - jnienv->CallVoidMethod(app_global->activity->clazz, assetcopy); -} - void initAndroid() { porting::jnienv = NULL; @@ -136,7 +125,7 @@ void initAndroid() exit(-1); } - nativeActivity = findClass("net/minetest/minetest/MtNativeActivity"); + nativeActivity = findClass("net/minetest/minetest/GameActivity"); if (nativeActivity == 0) { errorstream << "porting::initAndroid unable to find java native activity class" << diff --git a/src/porting_android.h b/src/porting_android.h index 0b3f2575e..60eb2a9c0 100644 --- a/src/porting_android.h +++ b/src/porting_android.h @@ -48,11 +48,6 @@ void cleanupAndroid(); */ void initializePathsAndroid(); -/** - * use java function to copy media from assets to external storage - */ -void copyAssets(); - /** * show text input dialog in java * @param acceptButton text to display on accept button diff --git a/src/version.cpp b/src/version.cpp index c0c59ee99..ae5ca3412 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -20,10 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "version.h" #include "config.h" -#if defined(__ANDROID__) - #include "android_version.h" - #include "android_version_githash.h" -#elif defined(USE_CMAKE_CONFIG_H) +#if USE_CMAKE_CONFIG_H #include "cmake_config_githash.h" #endif -- cgit v1.2.3 From 4e2473ec493689c3bc7d619fe17ee31c7f20945b Mon Sep 17 00:00:00 2001 From: Paramat Date: Fri, 17 Apr 2020 09:24:51 +0100 Subject: Document which noise APIs add world seed to noiseparams seed (#9693) --- doc/lua_api.txt | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index ccb605c8e..77f06682f 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -3250,9 +3250,9 @@ For this parameter you can randomly choose any whole number. Usually it is preferable for this to be different from other seeds, but sometimes it is useful to be able to create identical noise patterns. -When used in mapgen this is actually a 'seed offset', it is added to the -'world seed' to create the seed used by the noise, to ensure the noise has a -different pattern in different worlds. +In some noise APIs the world seed is added to the seed specified in noise +parameters. This is done to make the resulting noise pattern vary in different +worlds, and be 'world-specific'. ### `octaves` @@ -4649,8 +4649,11 @@ Environment access * Return value: Table with all node positions with a node air above * Area volume is limited to 4,096,000 nodes * `minetest.get_perlin(noiseparams)` + * Return world-specific perlin noise. + * The actual seed used is the noiseparams seed plus the world seed. * `minetest.get_perlin(seeddiff, octaves, persistence, spread)` - * Return world-specific perlin noise (`int(worldseed)+seeddiff`) + * Deprecated: use `minetest.get_perlin(noiseparams)` instead. + * Return world-specific perlin noise. * `minetest.get_voxel_manip([pos1, pos2])` * Return voxel manipulator object. * Loads the manipulator from the map if positions are passed. @@ -6207,10 +6210,15 @@ It can be created via `PcgRandom(seed)` or `PcgRandom(seed, sequence)`. ------------- A perlin noise generator. -It can be created via `PerlinNoise(seed, octaves, persistence, spread)` -or `PerlinNoise(noiseparams)`. -Alternatively with `minetest.get_perlin(seeddiff, octaves, persistence, spread)` -or `minetest.get_perlin(noiseparams)`. +It can be created via `PerlinNoise()` or `minetest.get_perlin()`. +For `minetest.get_perlin()`, the actual seed used is the noiseparams seed +plus the world seed, to create world-specific noise. + +`PerlinNoise(noiseparams)` +`PerlinNoise(seed, octaves, persistence, spread)` (Deprecated). + +`minetest.get_perlin(noiseparams)` +`minetest.get_perlin(seeddiff, octaves, persistence, spread)` (Deprecated). ### Methods @@ -6224,6 +6232,8 @@ A fast, bulk perlin noise generator. It can be created via `PerlinNoiseMap(noiseparams, size)` or `minetest.get_perlin_map(noiseparams, size)`. +For `minetest.get_perlin_map()`, the actual seed used is the noiseparams seed +plus the world seed, to create world-specific noise. Format of `size` is `{x=dimx, y=dimy, z=dimz}`. The `z` component is omitted for 2D noise, and it must be must be larger than 1 for 3D noise (otherwise -- cgit v1.2.3 From cee3c5e73d7af2a876aa76275234ee76e7cb1bbc Mon Sep 17 00:00:00 2001 From: EvidenceB Kidscode <49488517+EvidenceBKidscode@users.noreply.github.com> Date: Sat, 25 Apr 2020 07:20:00 +0200 Subject: Add server side translations capability (#9733) * Add server side translations capability --- doc/lua_api.txt | 15 ++++++++++++++ src/client/client.cpp | 2 +- src/client/game.cpp | 2 +- src/clientiface.h | 6 ++++++ src/network/serverpackethandler.cpp | 3 +++ src/script/lua_api/l_env.cpp | 16 +++++++++++++++ src/script/lua_api/l_env.h | 3 +++ src/script/lua_api/l_server.cpp | 7 ++++++- src/server.cpp | 22 +++++++++++++++++++- src/server.h | 5 ++++- src/translation.cpp | 13 ++++++++++-- src/translation.h | 5 ++++- src/util/string.cpp | 41 ++++++++++++++++++++++++++++--------- src/util/string.h | 4 ++++ 14 files changed, 126 insertions(+), 18 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 77f06682f..3ca32649a 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -3176,8 +3176,22 @@ Strings that need to be translated can contain several escapes, preceded by `@`. `minetest.translate`, but is in translation files. * `@n` acts as a literal newline as well. +Server side translations +------------------------ + +On some specific cases, server translation could be useful. For example, filter +a list on labels and send results to client. A method is supplied to achieve +that: + +`minetest.get_translated_string(lang_code, string)`: Translates `string` using +translations for `lang_code` language. It gives the same result as if the string +was translated by the client. +The `lang_code` to use for a given player can be retrieved from +the table returned by `minetest.get_player_information(name)`. +IMPORTANT: This functionality should only be used for sorting, filtering or similar purposes. +You do not need to use this to get translated strings to show up on the client. Perlin noise ============ @@ -4153,6 +4167,7 @@ Utilities connection_uptime = 200, -- seconds since client connected protocol_version = 32, -- protocol version used by client formspec_version = 2, -- supported formspec version + lang_code = "fr" -- Language code used for translation -- following information is available on debug build only!!! -- DO NOT USE IN MODS --ser_vers = 26, -- serialization version used by client diff --git a/src/client/client.cpp b/src/client/client.cpp index 8ee0869cd..941fc203d 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -736,7 +736,7 @@ bool Client::loadMedia(const std::string &data, const std::string &filename) if (!name.empty()) { TRACESTREAM(<< "Client: Loading translation: " << "\"" << filename << "\"" << std::endl); - g_translations->loadTranslation(data); + g_client_translations->loadTranslation(data); return true; } diff --git a/src/client/game.cpp b/src/client/game.cpp index 3429cc57b..610522dc2 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1055,7 +1055,7 @@ bool Game::startup(bool *kill, m_invert_mouse = g_settings->getBool("invert_mouse"); m_first_loop_after_window_activation = true; - g_translations->clear(); + g_client_translations->clear(); if (!init(map_dir, address, port, gamespec)) return false; diff --git a/src/clientiface.h b/src/clientiface.h index bf95df4a8..83fa6fe99 100644 --- a/src/clientiface.h +++ b/src/clientiface.h @@ -339,12 +339,18 @@ public: u8 getMinor() const { return m_version_minor; } u8 getPatch() const { return m_version_patch; } const std::string &getFull() const { return m_full_version; } + + void setLangCode(const std::string &code) { m_lang_code = code; } + const std::string &getLangCode() const { return m_lang_code; } private: // Version is stored in here after INIT before INIT2 u8 m_pending_serialization_version = SER_FMT_VER_INVALID; /* current state of client */ ClientState m_state = CS_Created; + + // Client sent language code + std::string m_lang_code; /* Blocks that have been sent to client. diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index c685500ce..5136eb0ec 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -311,6 +311,9 @@ void Server::handleCommand_Init2(NetworkPacket* pkt) RemoteClient *client = getClient(peer_id, CS_InitDone); + // Keep client language for server translations + client->setLangCode(lang); + // Send active objects { PlayerSAO *sao = getPlayerSAO(peer_id); diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 831464d3b..3fb58b8c8 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -40,6 +40,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "remoteplayer.h" #include "server/luaentity_sao.h" #include "server/player_sao.h" +#include "util/string.h" +#include "translation.h" #ifndef SERVER #include "client/client.h" #endif @@ -1302,6 +1304,19 @@ int ModApiEnvMod::l_forceload_free_block(lua_State *L) return 0; } +// get_translated_string(lang_code, string) +int ModApiEnvMod::l_get_translated_string(lua_State * L) +{ + GET_ENV_PTR; + std::string lang_code = luaL_checkstring(L, 1); + std::string string = luaL_checkstring(L, 2); + getServer(L)->loadTranslationLanguage(lang_code); + string = wide_to_utf8(translate_string(utf8_to_wide(string), + &(*g_server_translations)[lang_code])); + lua_pushstring(L, string.c_str()); + return 1; +} + void ModApiEnvMod::Initialize(lua_State *L, int top) { API_FCT(set_node); @@ -1349,6 +1364,7 @@ void ModApiEnvMod::Initialize(lua_State *L, int top) API_FCT(transforming_liquid_add); API_FCT(forceload_block); API_FCT(forceload_free_block); + API_FCT(get_translated_string); } void ModApiEnvMod::InitializeClient(lua_State *L, int top) diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h index ac2f8b588..9050b4306 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -187,6 +187,9 @@ private: // stops forceloading a position static int l_forceload_free_block(lua_State *L); + // Get a string translated server side + static int l_get_translated_string(lua_State * L); + public: static void Initialize(lua_State *L, int top); static void InitializeClient(lua_State *L, int top); diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index 00e849cdf..7137484e8 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -163,6 +163,7 @@ int ModApiServer::l_get_player_information(lua_State *L) u16 prot_vers; u8 ser_vers,major,minor,patch; std::string vers_string; + std::string lang_code; #define ERET(code) \ if (!(code)) { \ @@ -182,7 +183,7 @@ int ModApiServer::l_get_player_information(lua_State *L) &avg_jitter)) ERET(getServer(L)->getClientInfo(player->getPeerId(), &state, &uptime, &ser_vers, - &prot_vers, &major, &minor, &patch, &vers_string)) + &prot_vers, &major, &minor, &patch, &vers_string, &lang_code)) lua_newtable(L); int table = lua_gettop(L); @@ -237,6 +238,10 @@ int ModApiServer::l_get_player_information(lua_State *L) lua_pushnumber(L, player->formspec_version); lua_settable(L, table); + lua_pushstring(L, "lang_code"); + lua_pushstring(L, lang_code.c_str()); + lua_settable(L, table); + #ifndef NDEBUG lua_pushstring(L,"serialization_version"); lua_pushnumber(L, ser_vers); diff --git a/src/server.cpp b/src/server.cpp index c32aa5306..af6d3e40d 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -64,6 +64,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "chat_interface.h" #include "remoteplayer.h" #include "server/player_sao.h" +#include "translation.h" class ClientNotFoundException : public BaseException { @@ -1266,7 +1267,8 @@ bool Server::getClientInfo( u8* major, u8* minor, u8* patch, - std::string* vers_string + std::string* vers_string, + std::string* lang_code ) { *state = m_clients.getClientState(peer_id); @@ -1286,6 +1288,7 @@ bool Server::getClientInfo( *minor = client->getMinor(); *patch = client->getPatch(); *vers_string = client->getFull(); + *lang_code = client->getLangCode(); m_clients.unlock(); @@ -3937,3 +3940,20 @@ void Server::broadcastModChannelMessage(const std::string &channel, m_script->on_modchannel_message(channel, sender, message); } } + +void Server::loadTranslationLanguage(const std::string &lang_code) +{ + if (g_server_translations->count(lang_code)) + return; // Already loaded + + std::string suffix = "." + lang_code + ".tr"; + for (const auto &i : m_media) { + if (str_ends_with(i.first, suffix)) { + std::ifstream t(i.second.path); + std::string data((std::istreambuf_iterator(t)), + std::istreambuf_iterator()); + + (*g_server_translations)[lang_code].loadTranslation(data); + } + } +} diff --git a/src/server.h b/src/server.h index eecc2c0f0..b995aba28 100644 --- a/src/server.h +++ b/src/server.h @@ -334,7 +334,7 @@ public: bool getClientConInfo(session_t peer_id, con::rtt_stat_type type, float *retval); bool getClientInfo(session_t peer_id, ClientState *state, u32 *uptime, u8* ser_vers, u16* prot_vers, u8* major, u8* minor, u8* patch, - std::string* vers_string); + std::string* vers_string, std::string* lang_code); void printToConsoleOnly(const std::string &text); @@ -358,6 +358,9 @@ public: // Send block to specific player only bool SendBlock(session_t peer_id, const v3s16 &blockpos); + // Load translations for a language + void loadTranslationLanguage(const std::string &lang_code); + // Bind address Address m_bind_addr; diff --git a/src/translation.cpp b/src/translation.cpp index d17467ce7..8bbaee0a3 100644 --- a/src/translation.cpp +++ b/src/translation.cpp @@ -20,9 +20,18 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "translation.h" #include "log.h" #include "util/string.h" +#include -static Translations main_translations; -Translations *g_translations = &main_translations; + +#ifndef SERVER +// Client translations +Translations client_translations; +Translations *g_client_translations = &client_translations; +#endif + +// Per language server translations +std::unordered_map server_translations; +std::unordered_map *g_server_translations = &server_translations; Translations::~Translations() { diff --git a/src/translation.h b/src/translation.h index 18fc6c38f..71423b15e 100644 --- a/src/translation.h +++ b/src/translation.h @@ -23,7 +23,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include class Translations; -extern Translations *g_translations; +extern std::unordered_map *g_server_translations; +#ifndef SERVER +extern Translations *g_client_translations; +#endif class Translations { diff --git a/src/util/string.cpp b/src/util/string.cpp index 2ee3ec735..6e1db798c 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -693,10 +693,12 @@ void str_replace(std::string &str, char from, char to) * before filling it again. */ -void translate_all(const std::wstring &s, size_t &i, std::wstring &res); +void translate_all(const std::wstring &s, size_t &i, + Translations *translations, std::wstring &res); -void translate_string(const std::wstring &s, const std::wstring &textdomain, - size_t &i, std::wstring &res) { +void translate_string(const std::wstring &s, Translations *translations, + const std::wstring &textdomain, size_t &i, std::wstring &res) +{ std::wostringstream output; std::vector args; int arg_number = 1; @@ -750,7 +752,7 @@ void translate_string(const std::wstring &s, const std::wstring &textdomain, if (arg_number >= 10) { errorstream << "Ignoring too many arguments to translation" << std::endl; std::wstring arg; - translate_all(s, i, arg); + translate_all(s, i, translations, arg); args.push_back(arg); continue; } @@ -758,7 +760,7 @@ void translate_string(const std::wstring &s, const std::wstring &textdomain, output << arg_number; ++arg_number; std::wstring arg; - translate_all(s, i, arg); + translate_all(s, i, translations, arg); args.push_back(arg); } else { // This is an escape sequence *inside* the template string to translate itself. @@ -767,8 +769,13 @@ void translate_string(const std::wstring &s, const std::wstring &textdomain, } } + std::wstring toutput; // Translate the template. - std::wstring toutput = g_translations->getTranslation(textdomain, output.str()); + if (translations != nullptr) + toutput = translations->getTranslation( + textdomain, output.str()); + else + toutput = output.str(); // Put back the arguments in the translated template. std::wostringstream result; @@ -802,7 +809,9 @@ void translate_string(const std::wstring &s, const std::wstring &textdomain, res = result.str(); } -void translate_all(const std::wstring &s, size_t &i, std::wstring &res) { +void translate_all(const std::wstring &s, size_t &i, + Translations *translations, std::wstring &res) +{ std::wostringstream output; while (i < s.length()) { // Not an escape sequence: just add the character. @@ -851,7 +860,7 @@ void translate_all(const std::wstring &s, size_t &i, std::wstring &res) { if (parts.size() > 1) textdomain = parts[1]; std::wstring translated; - translate_string(s, textdomain, i, translated); + translate_string(s, translations, textdomain, i, translated); output << translated; } else { // Another escape sequence, such as colors. Preserve it. @@ -862,9 +871,21 @@ void translate_all(const std::wstring &s, size_t &i, std::wstring &res) { res = output.str(); } -std::wstring translate_string(const std::wstring &s) { +// Translate string server side +std::wstring translate_string(const std::wstring &s, Translations *translations) +{ size_t i = 0; std::wstring res; - translate_all(s, i, res); + translate_all(s, i, translations, res); return res; } + +// Translate string client side +std::wstring translate_string(const std::wstring &s) +{ +#ifdef SERVER + return translate_string(s, nullptr); +#else + return translate_string(s, g_client_translations); +#endif +} diff --git a/src/util/string.h b/src/util/string.h index 0d2a6bdb2..185fb55e2 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -31,6 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include +class Translations; + #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) @@ -650,6 +652,8 @@ std::vector > split(const std::basic_string &s, T delim) return tokens; } +std::wstring translate_string(const std::wstring &s, Translations *translations); + std::wstring translate_string(const std::wstring &s); inline std::wstring unescape_translate(const std::wstring &s) { -- cgit v1.2.3 From 3475759d1adbd4a64c6250fd87981f783e64f69c Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 14 Apr 2020 14:11:33 +0200 Subject: Expose collision information to LuaEntity on_step --- builtin/game/features.lua | 1 + doc/lua_api.txt | 25 ++++++++++++++++++- src/script/common/c_content.cpp | 54 +++++++++++++++++++++++++++++++++++++++++ src/script/common/c_content.h | 4 ++- src/script/cpp_api/s_entity.cpp | 12 ++++++--- src/script/cpp_api/s_entity.h | 4 ++- src/server/luaentity_sao.cpp | 8 +++--- 7 files changed, 98 insertions(+), 10 deletions(-) (limited to 'doc') diff --git a/builtin/game/features.lua b/builtin/game/features.lua index 623f8183b..a15475333 100644 --- a/builtin/game/features.lua +++ b/builtin/game/features.lua @@ -16,6 +16,7 @@ core.features = { formspec_version_element = true, area_store_persistent_ids = true, pathfinder_works = true, + object_step_has_moveresult = true, } function core.has_feature(arg) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 3ca32649a..5e4e18b62 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4147,6 +4147,8 @@ Utilities area_store_persistent_ids = true, -- Whether minetest.find_path is functional (5.2.0) pathfinder_works = true, + -- Whether Collision info is available to an objects' on_step (5.3.0) + object_step_has_moveresult = true, } * `minetest.has_feature(arg)`: returns `boolean, missing_features` @@ -6579,7 +6581,10 @@ Used by `minetest.register_entity`. on_activate = function(self, staticdata, dtime_s), - on_step = function(self, dtime), + on_step = function(self, dtime, moveresult), + -- Called every server step + -- dtime: Elapsed time + -- moveresult: Table with collision info (only available if physical=true) on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir), @@ -6594,6 +6599,24 @@ Used by `minetest.register_entity`. -- for more info) by using a '_' prefix } +Collision info passed to `on_step`: + + { + touching_ground = boolean, + collides = boolean, + standing_on_object = boolean, + collisions = { + { + type = string, -- "node" or "object", + axis = string, -- "x", "y" or "z" + node_pos = vector, -- if type is "node" + old_speed = vector, + new_speed = vector, + }, + ... + } + } + ABM (ActiveBlockModifier) definition ------------------------------------ diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 8335fccb5..6ff642738 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/c_types.h" #include "nodedef.h" #include "object_properties.h" +#include "collision.h" #include "cpp_api/s_node.h" #include "lua_api/l_object.h" #include "lua_api/l_item.h" @@ -2002,3 +2003,56 @@ HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value) } return stat; } + +/******************************************************************************/ + +// Indices must match values in `enum CollisionType` exactly!! +static const char *collision_type_str[] = { + "node", + "object", +}; + +// Indices must match values in `enum CollisionAxis` exactly!! +static const char *collision_axis_str[] = { + "x", + "y", + "z", +}; + +void push_collision_move_result(lua_State *L, const collisionMoveResult &res) +{ + lua_createtable(L, 0, 4); + + setboolfield(L, -1, "touching_ground", res.touching_ground); + setboolfield(L, -1, "collides", res.collides); + setboolfield(L, -1, "standing_on_object", res.standing_on_object); + + /* collisions */ + lua_createtable(L, res.collisions.size(), 0); + int i = 1; + for (const auto &c : res.collisions) { + lua_createtable(L, 0, 5); + + lua_pushstring(L, collision_type_str[c.type]); + lua_setfield(L, -2, "type"); + + assert(c.axis != COLLISION_AXIS_NONE); + lua_pushstring(L, collision_axis_str[c.axis]); + lua_setfield(L, -2, "axis"); + + if (c.type == COLLISION_NODE) { + push_v3s16(L, c.node_p); + lua_setfield(L, -2, "node_pos"); + } + + push_v3f(L, c.old_speed / BS); + lua_setfield(L, -2, "old_speed"); + + push_v3f(L, c.new_speed / BS); + lua_setfield(L, -2, "new_speed"); + + lua_rawseti(L, -2, i++); + } + lua_setfield(L, -2, "collisions"); + /**/ +} diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h index 9e755682f..8f32e58eb 100644 --- a/src/script/common/c_content.h +++ b/src/script/common/c_content.h @@ -63,7 +63,9 @@ struct EnumString; struct NoiseParams; class Schematic; class ServerActiveObject; +struct collisionMoveResult; +extern struct EnumString es_TileAnimationType[]; ContentFeatures read_content_features (lua_State *L, int index); void push_content_features (lua_State *L, @@ -196,4 +198,4 @@ void push_hud_element (lua_State *L, HudElement *elem); HudElementStat read_hud_change (lua_State *L, HudElement *elem, void **value); -extern struct EnumString es_TileAnimationType[]; +void push_collision_move_result(lua_State *L, const collisionMoveResult &res); diff --git a/src/script/cpp_api/s_entity.cpp b/src/script/cpp_api/s_entity.cpp index 26c7e8cd4..ea9320051 100644 --- a/src/script/cpp_api/s_entity.cpp +++ b/src/script/cpp_api/s_entity.cpp @@ -178,12 +178,11 @@ void ScriptApiEntity::luaentity_GetProperties(u16 id, lua_pop(L, 1); } -void ScriptApiEntity::luaentity_Step(u16 id, float dtime) +void ScriptApiEntity::luaentity_Step(u16 id, float dtime, + const collisionMoveResult *moveresult) { SCRIPTAPI_PRECHECKHEADER - //infostream<<"scriptapi_luaentity_step: id="<getScriptIface()->luaentity_Step(m_id, dtime); + if(m_registered) { + m_env->getScriptIface()->luaentity_Step(m_id, dtime, moveresult_p); } if (!send_recommended) -- cgit v1.2.3 From 74d9b6010fd42573d20cdbe78f7aaa07badfbf1b Mon Sep 17 00:00:00 2001 From: Lejo Date: Fri, 1 May 2020 16:47:17 +0200 Subject: Give the online lua mainmenu also the client_list and mods (#8691) --- doc/menu_lua_api.txt | 25 ++++++------ src/script/lua_api/l_mainmenu.cpp | 81 +++++++++++++++++++++++++++------------ 2 files changed, 70 insertions(+), 36 deletions(-) (limited to 'doc') diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index df6424ad7..8f5460acb 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -156,18 +156,21 @@ core.get_favorites(location) -> list of favorites (possible in async calls) ^ location: "local" or "online" ^ returns { [1] = { - clients = , - clients_max = , - version = , - password = , - creative = , - damage = , - pvp = , - description = , - name = , - address =
, - port = + clients = , + clients_max = , + version = , + password = , + creative = , + damage = , + pvp = , + description = , + name = , + address =
, + port = + clients_list = + mods = }, + ... } core.delete_favorite(id, location) -> success diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 867e84e13..a76e9f079 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -280,8 +280,8 @@ int ModApiMainMenu::l_get_favorites(lua_State *L) { std::string listtype = "local"; - if (!lua_isnone(L,1)) { - listtype = luaL_checkstring(L,1); + if (!lua_isnone(L, 1)) { + listtype = luaL_checkstring(L, 1); } std::vector servers; @@ -298,7 +298,7 @@ int ModApiMainMenu::l_get_favorites(lua_State *L) for (const Json::Value &server : servers) { - lua_pushnumber(L,index); + lua_pushnumber(L, index); lua_newtable(L); int top_lvl2 = lua_gettop(L); @@ -306,11 +306,11 @@ int ModApiMainMenu::l_get_favorites(lua_State *L) if (!server["clients"].asString().empty()) { std::string clients_raw = server["clients"].asString(); char* endptr = 0; - int numbervalue = strtol(clients_raw.c_str(),&endptr,10); + int numbervalue = strtol(clients_raw.c_str(), &endptr,10); if ((!clients_raw.empty()) && (*endptr == 0)) { - lua_pushstring(L,"clients"); - lua_pushnumber(L,numbervalue); + lua_pushstring(L, "clients"); + lua_pushnumber(L, numbervalue); lua_settable(L, top_lvl2); } } @@ -319,83 +319,83 @@ int ModApiMainMenu::l_get_favorites(lua_State *L) std::string clients_max_raw = server["clients_max"].asString(); char* endptr = 0; - int numbervalue = strtol(clients_max_raw.c_str(),&endptr,10); + int numbervalue = strtol(clients_max_raw.c_str(), &endptr,10); if ((!clients_max_raw.empty()) && (*endptr == 0)) { - lua_pushstring(L,"clients_max"); - lua_pushnumber(L,numbervalue); + lua_pushstring(L, "clients_max"); + lua_pushnumber(L, numbervalue); lua_settable(L, top_lvl2); } } if (!server["version"].asString().empty()) { - lua_pushstring(L,"version"); + lua_pushstring(L, "version"); std::string topush = server["version"].asString(); - lua_pushstring(L,topush.c_str()); + lua_pushstring(L, topush.c_str()); lua_settable(L, top_lvl2); } if (!server["proto_min"].asString().empty()) { - lua_pushstring(L,"proto_min"); + lua_pushstring(L, "proto_min"); lua_pushinteger(L, server["proto_min"].asInt()); lua_settable(L, top_lvl2); } if (!server["proto_max"].asString().empty()) { - lua_pushstring(L,"proto_max"); + lua_pushstring(L, "proto_max"); lua_pushinteger(L, server["proto_max"].asInt()); lua_settable(L, top_lvl2); } if (!server["password"].asString().empty()) { - lua_pushstring(L,"password"); + lua_pushstring(L, "password"); lua_pushboolean(L, server["password"].asBool()); lua_settable(L, top_lvl2); } if (!server["creative"].asString().empty()) { - lua_pushstring(L,"creative"); + lua_pushstring(L, "creative"); lua_pushboolean(L, server["creative"].asBool()); lua_settable(L, top_lvl2); } if (!server["damage"].asString().empty()) { - lua_pushstring(L,"damage"); + lua_pushstring(L, "damage"); lua_pushboolean(L, server["damage"].asBool()); lua_settable(L, top_lvl2); } if (!server["pvp"].asString().empty()) { - lua_pushstring(L,"pvp"); + lua_pushstring(L, "pvp"); lua_pushboolean(L, server["pvp"].asBool()); lua_settable(L, top_lvl2); } if (!server["description"].asString().empty()) { - lua_pushstring(L,"description"); + lua_pushstring(L, "description"); std::string topush = server["description"].asString(); - lua_pushstring(L,topush.c_str()); + lua_pushstring(L, topush.c_str()); lua_settable(L, top_lvl2); } if (!server["name"].asString().empty()) { - lua_pushstring(L,"name"); + lua_pushstring(L, "name"); std::string topush = server["name"].asString(); - lua_pushstring(L,topush.c_str()); + lua_pushstring(L, topush.c_str()); lua_settable(L, top_lvl2); } if (!server["address"].asString().empty()) { - lua_pushstring(L,"address"); + lua_pushstring(L, "address"); std::string topush = server["address"].asString(); - lua_pushstring(L,topush.c_str()); + lua_pushstring(L, topush.c_str()); lua_settable(L, top_lvl2); } if (!server["port"].asString().empty()) { - lua_pushstring(L,"port"); + lua_pushstring(L, "port"); std::string topush = server["port"].asString(); - lua_pushstring(L,topush.c_str()); + lua_pushstring(L, topush.c_str()); lua_settable(L, top_lvl2); } @@ -406,6 +406,37 @@ int ModApiMainMenu::l_get_favorites(lua_State *L) lua_settable(L, top_lvl2); } + if (server["clients_list"].isArray()) { + unsigned int index_lvl2 = 1; + lua_pushstring(L, "clients_list"); + lua_newtable(L); + int top_lvl3 = lua_gettop(L); + for (const Json::Value &client : server["clients_list"]) { + lua_pushnumber(L, index_lvl2); + std::string topush = client.asString(); + lua_pushstring(L, topush.c_str()); + lua_settable(L, top_lvl3); + index_lvl2++; + } + lua_settable(L, top_lvl2); + } + + if (server["mods"].isArray()) { + unsigned int index_lvl2 = 1; + lua_pushstring(L, "mods"); + lua_newtable(L); + int top_lvl3 = lua_gettop(L); + for (const Json::Value &mod : server["mods"]) { + + lua_pushnumber(L, index_lvl2); + std::string topush = mod.asString(); + lua_pushstring(L, topush.c_str()); + lua_settable(L, top_lvl3); + index_lvl2++; + } + lua_settable(L, top_lvl2); + } + lua_settable(L, top); index++; } -- cgit v1.2.3 From ac368af4fe27f61f5a4209cdfe90956ff745993c Mon Sep 17 00:00:00 2001 From: sfan5 Date: Fri, 1 May 2020 21:44:28 +0200 Subject: Allow connection info to be missing from minetest.get_player_information() (#9739) fixes #9352 This reverts commit 23c907befea02005e2c0c87fca0131b60aace18a. --- doc/lua_api.txt | 11 +++-- src/network/connection.h | 6 +-- src/script/lua_api/l_server.cpp | 102 ++++++++++++++++++++-------------------- 3 files changed, 61 insertions(+), 58 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 5e4e18b62..f9107b623 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4160,17 +4160,18 @@ Utilities { address = "127.0.0.1", -- IP address of client ip_version = 4, -- IPv4 / IPv6 + connection_uptime = 200, -- seconds since client connected + protocol_version = 32, -- protocol version used by client + formspec_version = 2, -- supported formspec version + lang_code = "fr" -- Language code used for translation + -- the following keys can be missing if no stats have been collected yet min_rtt = 0.01, -- minimum round trip time max_rtt = 0.2, -- maximum round trip time avg_rtt = 0.02, -- average round trip time min_jitter = 0.01, -- minimum packet time jitter max_jitter = 0.5, -- maximum packet time jitter avg_jitter = 0.03, -- average packet time jitter - connection_uptime = 200, -- seconds since client connected - protocol_version = 32, -- protocol version used by client - formspec_version = 2, -- supported formspec version - lang_code = "fr" -- Language code used for translation - -- following information is available on debug build only!!! + -- the following information is available in a debug build only!!! -- DO NOT USE IN MODS --ser_vers = 26, -- serialization version used by client --major = 0, -- major version number diff --git a/src/network/connection.h b/src/network/connection.h index 85f021c4c..47b0805ce 100644 --- a/src/network/connection.h +++ b/src/network/connection.h @@ -612,16 +612,16 @@ class Peer { struct rttstats { float jitter_min = FLT_MAX; float jitter_max = 0.0f; - float jitter_avg = -2.0f; + float jitter_avg = -1.0f; float min_rtt = FLT_MAX; float max_rtt = 0.0f; - float avg_rtt = -2.0f; + float avg_rtt = -1.0f; rttstats() = default; }; rttstats m_rtt; - float m_last_rtt = -2.0f; + float m_last_rtt = -1.0f; // current usage count unsigned int m_usage = 0; diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index 7137484e8..b6754938e 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -138,53 +138,54 @@ int ModApiServer::l_get_player_ip(lua_State *L) // get_player_information(name) int ModApiServer::l_get_player_information(lua_State *L) { - NO_MAP_LOCK_REQUIRED; - const char * name = luaL_checkstring(L, 1); - RemotePlayer *player = dynamic_cast(getEnv(L))->getPlayer(name); - if (player == NULL) { + + Server *server = getServer(L); + + const char *name = luaL_checkstring(L, 1); + RemotePlayer *player = server->getEnv().getPlayer(name); + if (!player) { lua_pushnil(L); // no such player return 1; } Address addr; - try - { - addr = getServer(L)->getPeerAddress(player->getPeerId()); - } catch(const con::PeerNotFoundException &) { + try { + addr = server->getPeerAddress(player->getPeerId()); + } catch (const con::PeerNotFoundException &) { dstream << FUNCTION_NAME << ": peer was not found" << std::endl; lua_pushnil(L); // error return 1; } - float min_rtt,max_rtt,avg_rtt,min_jitter,max_jitter,avg_jitter; + float min_rtt, max_rtt, avg_rtt, min_jitter, max_jitter, avg_jitter; ClientState state; u32 uptime; u16 prot_vers; - u8 ser_vers,major,minor,patch; - std::string vers_string; - std::string lang_code; - -#define ERET(code) \ - if (!(code)) { \ - dstream << FUNCTION_NAME << ": peer was not found" << std::endl; \ - lua_pushnil(L); /* error */ \ - return 1; \ + u8 ser_vers, major, minor, patch; + std::string vers_string, lang_code; + + auto getConInfo = [&] (con::rtt_stat_type type, float *value) -> bool { + return server->getClientConInfo(player->getPeerId(), type, value); + }; + + bool have_con_info = + getConInfo(con::MIN_RTT, &min_rtt) && + getConInfo(con::MAX_RTT, &max_rtt) && + getConInfo(con::AVG_RTT, &avg_rtt) && + getConInfo(con::MIN_JITTER, &min_jitter) && + getConInfo(con::MAX_JITTER, &max_jitter) && + getConInfo(con::AVG_JITTER, &avg_jitter); + + bool r = server->getClientInfo(player->getPeerId(), &state, &uptime, + &ser_vers, &prot_vers, &major, &minor, &patch, &vers_string, + &lang_code); + if (!r) { + dstream << FUNCTION_NAME << ": peer was not found" << std::endl; + lua_pushnil(L); // error + return 1; } - ERET(getServer(L)->getClientConInfo(player->getPeerId(), con::MIN_RTT, &min_rtt)) - ERET(getServer(L)->getClientConInfo(player->getPeerId(), con::MAX_RTT, &max_rtt)) - ERET(getServer(L)->getClientConInfo(player->getPeerId(), con::AVG_RTT, &avg_rtt)) - ERET(getServer(L)->getClientConInfo(player->getPeerId(), con::MIN_JITTER, - &min_jitter)) - ERET(getServer(L)->getClientConInfo(player->getPeerId(), con::MAX_JITTER, - &max_jitter)) - ERET(getServer(L)->getClientConInfo(player->getPeerId(), con::AVG_JITTER, - &avg_jitter)) - - ERET(getServer(L)->getClientInfo(player->getPeerId(), &state, &uptime, &ser_vers, - &prot_vers, &major, &minor, &patch, &vers_string, &lang_code)) - lua_newtable(L); int table = lua_gettop(L); @@ -202,29 +203,31 @@ int ModApiServer::l_get_player_information(lua_State *L) } lua_settable(L, table); - lua_pushstring(L,"min_rtt"); - lua_pushnumber(L, min_rtt); - lua_settable(L, table); + if (have_con_info) { // may be missing + lua_pushstring(L, "min_rtt"); + lua_pushnumber(L, min_rtt); + lua_settable(L, table); - lua_pushstring(L,"max_rtt"); - lua_pushnumber(L, max_rtt); - lua_settable(L, table); + lua_pushstring(L, "max_rtt"); + lua_pushnumber(L, max_rtt); + lua_settable(L, table); - lua_pushstring(L,"avg_rtt"); - lua_pushnumber(L, avg_rtt); - lua_settable(L, table); + lua_pushstring(L, "avg_rtt"); + lua_pushnumber(L, avg_rtt); + lua_settable(L, table); - lua_pushstring(L,"min_jitter"); - lua_pushnumber(L, min_jitter); - lua_settable(L, table); + lua_pushstring(L, "min_jitter"); + lua_pushnumber(L, min_jitter); + lua_settable(L, table); - lua_pushstring(L,"max_jitter"); - lua_pushnumber(L, max_jitter); - lua_settable(L, table); + lua_pushstring(L, "max_jitter"); + lua_pushnumber(L, max_jitter); + lua_settable(L, table); - lua_pushstring(L,"avg_jitter"); - lua_pushnumber(L, avg_jitter); - lua_settable(L, table); + lua_pushstring(L, "avg_jitter"); + lua_pushnumber(L, avg_jitter); + lua_settable(L, table); + } lua_pushstring(L,"connection_uptime"); lua_pushnumber(L, uptime); @@ -268,7 +271,6 @@ int ModApiServer::l_get_player_information(lua_State *L) lua_settable(L, table); #endif -#undef ERET return 1; } -- cgit v1.2.3 From e0ea87f1f32273dba2eb5421c2a8c890479ba078 Mon Sep 17 00:00:00 2001 From: ANAND Date: Sat, 2 May 2020 16:22:11 +0530 Subject: set_fov: Add support for time-based transitions (#9705) --- doc/lua_api.txt | 15 ++++--- src/client/camera.cpp | 84 +++++++++++++++++++++++++++++-------- src/client/camera.h | 15 ++++++- src/network/clientpackethandler.cpp | 15 ++++++- src/network/networkprotocol.h | 3 +- src/player.h | 12 ++++-- src/script/lua_api/l_object.cpp | 11 +++-- src/server.cpp | 4 +- 8 files changed, 124 insertions(+), 35 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index f9107b623..44f62f7a7 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -5998,15 +5998,18 @@ object you are working with still exists. * max: bubbles bar is not shown * See [Object properties] for more information * Is limited to range 0 ... 65535 (2^16 - 1) -* `set_fov(fov, is_multiplier)`: Sets player's FOV +* `set_fov(fov, is_multiplier, transition_time)`: Sets player's FOV * `fov`: FOV value. * `is_multiplier`: Set to `true` if the FOV value is a multiplier. Defaults to `false`. - * Set to 0 to clear FOV override. -* `get_fov()`: - * Returns player's FOV override in degrees, and a boolean depending on whether - the value is a multiplier. - * Returns 0 as first value if player's FOV hasn't been overridden. + * `transition_time`: If defined, enables smooth FOV transition. + Interpreted as the time (in seconds) to reach target FOV. + If set to 0, FOV change is instantaneous. Defaults to 0. + * Set `fov` to 0 to clear FOV override. +* `get_fov()`: Returns the following: + * Server-sent FOV value. Returns 0 if an FOV override doesn't exist. + * Boolean indicating whether the FOV value is a multiplier. + * Time (in seconds) taken for the FOV transition. Set by `set_fov`. * `set_attribute(attribute, value)`: DEPRECATED, use get_meta() instead * Sets an extra attribute with value on player. * `value` must be a string, or a number which will be converted to a diff --git a/src/client/camera.cpp b/src/client/camera.cpp index 69bd82a47..1a5253db4 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -86,6 +86,51 @@ Camera::~Camera() m_wieldmgr->drop(); } +void Camera::notifyFovChange() +{ + LocalPlayer *player = m_client->getEnv().getLocalPlayer(); + assert(player); + + PlayerFovSpec spec = player->getFov(); + + /* + * Update m_old_fov_degrees first - it serves as the starting point of the + * upcoming transition. + * + * If an FOV transition is already active, mark current FOV as the start of + * the new transition. If not, set it to the previous transition's target FOV. + */ + if (m_fov_transition_active) + m_old_fov_degrees = m_curr_fov_degrees; + else + m_old_fov_degrees = m_server_sent_fov ? m_target_fov_degrees : m_cache_fov; + + /* + * Update m_server_sent_fov next - it corresponds to the target FOV of the + * upcoming transition. + * + * Set it to m_cache_fov, if server-sent FOV is 0. Otherwise check if + * server-sent FOV is a multiplier, and multiply it with m_cache_fov instead + * of overriding. + */ + if (spec.fov == 0.0f) { + m_server_sent_fov = false; + m_target_fov_degrees = m_cache_fov; + } else { + m_server_sent_fov = true; + m_target_fov_degrees = spec.is_multiplier ? m_cache_fov * spec.fov : spec.fov; + } + + if (spec.transition_time > 0.0f) + m_fov_transition_active = true; + + // If FOV smooth transition is active, initialize required variables + if (m_fov_transition_active) { + m_transition_time = spec.transition_time; + m_fov_diff = m_target_fov_degrees - m_old_fov_degrees; + } +} + bool Camera::successfullyCreated(std::string &error_message) { if (!m_playernode) { @@ -462,33 +507,38 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, f32 tool_r m_camera_position = my_cp; /* - * Apply server-sent FOV. If server doesn't enforce FOV, - * check for zoom and set to zoom FOV. - * Otherwise, default to m_cache_fov + * Apply server-sent FOV, instantaneous or smooth transition. + * If not, check for zoom and set to zoom FOV. + * Otherwise, default to m_cache_fov. */ - - f32 fov_degrees; - PlayerFovSpec fov_spec = player->getFov(); - if (fov_spec.fov > 0.0f) { - // If server-sent FOV is a multiplier, multiply - // it with m_cache_fov instead of overriding - if (fov_spec.is_multiplier) - fov_degrees = m_cache_fov * fov_spec.fov; - else - fov_degrees = fov_spec.fov; + if (m_fov_transition_active) { + // Smooth FOV transition + // Dynamically calculate FOV delta based on frametimes + f32 delta = (frametime / m_transition_time) * m_fov_diff; + m_curr_fov_degrees += delta; + + // Mark transition as complete if target FOV has been reached + if ((m_fov_diff > 0.0f && m_curr_fov_degrees >= m_target_fov_degrees) || + (m_fov_diff < 0.0f && m_curr_fov_degrees <= m_target_fov_degrees)) { + m_fov_transition_active = false; + m_curr_fov_degrees = m_target_fov_degrees; + } + } else if (m_server_sent_fov) { + // Instantaneous FOV change + m_curr_fov_degrees = m_target_fov_degrees; } else if (player->getPlayerControl().zoom && player->getZoomFOV() > 0.001f) { // Player requests zoom, apply zoom FOV - fov_degrees = player->getZoomFOV(); + m_curr_fov_degrees = player->getZoomFOV(); } else { // Set to client's selected FOV - fov_degrees = m_cache_fov; + m_curr_fov_degrees = m_cache_fov; } - fov_degrees = rangelim(fov_degrees, 1.0f, 160.0f); + m_curr_fov_degrees = rangelim(m_curr_fov_degrees, 1.0f, 160.0f); // FOV and aspect ratio const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize(); m_aspect = (f32) window_size.X / (f32) window_size.Y; - m_fov_y = fov_degrees * M_PI / 180.0; + m_fov_y = m_curr_fov_degrees * M_PI / 180.0; // Increase vertical FOV on lower aspect ratios (<16:10) m_fov_y *= MYMAX(1.0, MYMIN(1.4, sqrt(16./10. / m_aspect))); m_fov_x = 2 * atan(m_aspect * tan(0.5 * m_fov_y)); diff --git a/src/client/camera.h b/src/client/camera.h index 6ec37fe10..3a59637bc 100644 --- a/src/client/camera.h +++ b/src/client/camera.h @@ -112,6 +112,9 @@ public: return MYMAX(m_fov_x, m_fov_y); } + // Notify about new server-sent FOV and initialize smooth FOV transition + void notifyFovChange(); + // Checks if the constructor was able to create the scene nodes bool successfullyCreated(std::string &error_message); @@ -186,6 +189,9 @@ private: Client *m_client; + // Default Client FOV (as defined by the "fov" setting) + f32 m_cache_fov; + // Absolute camera position v3f m_camera_position; // Absolute camera direction @@ -193,6 +199,14 @@ private: // Camera offset v3s16 m_camera_offset; + // Server-sent FOV variables + bool m_server_sent_fov = false; + f32 m_curr_fov_degrees, m_old_fov_degrees, m_target_fov_degrees; + + // FOV transition variables + bool m_fov_transition_active = false; + f32 m_fov_diff, m_transition_time; + v2f m_wieldmesh_offset = v2f(55.0f, -35.0f); v2f m_arm_dir; v2f m_cam_vel; @@ -230,7 +244,6 @@ private: f32 m_cache_fall_bobbing_amount; f32 m_cache_view_bobbing_amount; - f32 m_cache_fov; bool m_arm_inertia; std::list m_nametags; diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index d19dc3818..6428ed752 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/client.h" #include "util/base64.h" +#include "client/camera.h" #include "chatmessage.h" #include "client/clientmedia.h" #include "log.h" @@ -530,11 +531,21 @@ void Client::handleCommand_Movement(NetworkPacket* pkt) void Client::handleCommand_Fov(NetworkPacket *pkt) { f32 fov; - bool is_multiplier; + bool is_multiplier = false; + f32 transition_time = 0.0f; + *pkt >> fov >> is_multiplier; + // Wrap transition_time extraction within a + // try-catch to preserve backwards compat + try { + *pkt >> transition_time; + } catch (PacketError &e) {}; + LocalPlayer *player = m_env.getLocalPlayer(); - player->setFov({ fov, is_multiplier }); + assert(player); + player->setFov({ fov, is_multiplier, transition_time }); + m_camera->notifyFovChange(); } void Client::handleCommand_HP(NetworkPacket *pkt) diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 4b7345b15..73523ea42 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -384,8 +384,9 @@ enum ToClientCommand /* Sends an FOV override/multiplier to client. - float fov + f32 fov bool is_multiplier + f32 transition_time */ TOCLIENT_DEATHSCREEN = 0x37, diff --git a/src/player.h b/src/player.h index de7f427e9..3bc7762fa 100644 --- a/src/player.h +++ b/src/player.h @@ -35,7 +35,13 @@ with this program; if not, write to the Free Software Foundation, Inc., struct PlayerFovSpec { f32 fov; + + // Whether to multiply the client's FOV or to override it bool is_multiplier; + + // The time to be take to trasition to the new FOV value. + // Transition is instantaneous if omitted. Omitted by default. + f32 transition_time; }; struct PlayerControl @@ -186,12 +192,12 @@ public: void setFov(const PlayerFovSpec &spec) { - m_fov_spec = spec; + m_fov_override_spec = spec; } const PlayerFovSpec &getFov() const { - return m_fov_spec; + return m_fov_override_spec; } u32 keyPressed = 0; @@ -208,7 +214,7 @@ protected: char m_name[PLAYERNAME_SIZE]; v3f m_speed; u16 m_wield_index = 0; - PlayerFovSpec m_fov_spec = { 0.0f, false }; + PlayerFovSpec m_fov_override_spec = { 0.0f, false, 0.0f }; std::vector hud; private: diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 77e1e7dc2..dcaee10b2 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -1249,7 +1249,7 @@ int ObjectRef::l_set_look_yaw(lua_State *L) return 1; } -// set_fov(self, degrees[, is_multiplier]) +// set_fov(self, degrees[, is_multiplier, transition_time]) int ObjectRef::l_set_fov(lua_State *L) { NO_MAP_LOCK_REQUIRED; @@ -1258,7 +1258,11 @@ int ObjectRef::l_set_fov(lua_State *L) if (!player) return 0; - player->setFov({ static_cast(luaL_checknumber(L, 2)), readParam(L, 3) }); + player->setFov({ + static_cast(luaL_checknumber(L, 2)), + readParam(L, 3, false), + lua_isnumber(L, 4) ? static_cast(luaL_checknumber(L, 4)) : 0.0f + }); getServer(L)->SendPlayerFov(player->getPeerId()); return 0; @@ -1276,8 +1280,9 @@ int ObjectRef::l_get_fov(lua_State *L) PlayerFovSpec fov_spec = player->getFov(); lua_pushnumber(L, fov_spec.fov); lua_pushboolean(L, fov_spec.is_multiplier); + lua_pushnumber(L, fov_spec.transition_time); - return 2; + return 3; } // set_breath(self, breath) diff --git a/src/server.cpp b/src/server.cpp index a7eb52837..0346d197d 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1892,10 +1892,10 @@ void Server::SendMovePlayer(session_t peer_id) void Server::SendPlayerFov(session_t peer_id) { - NetworkPacket pkt(TOCLIENT_FOV, 4 + 1, peer_id); + NetworkPacket pkt(TOCLIENT_FOV, 4 + 1 + 4, peer_id); PlayerFovSpec fov_spec = m_env->getPlayer(peer_id)->getFov(); - pkt << fov_spec.fov << fov_spec.is_multiplier; + pkt << fov_spec.fov << fov_spec.is_multiplier << fov_spec.transition_time; Send(&pkt); } -- cgit v1.2.3 From 5c96f57782d967010f711c3806fdd18caa6e3e32 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Sat, 2 May 2020 13:12:02 +0200 Subject: Add a convention about z_index (#9701) --- doc/lua_api.txt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 44f62f7a7..988acde89 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1310,7 +1310,21 @@ factor! The `z_index` field specifies the order of HUD elements from back to front. Lower z-index elements are displayed behind higher z-index elements. Elements with same z-index are displayed in an arbitrary order. Default 0. -Supports negative values. +Supports negative values. By convention, the following values are recommended: + +* -400: Graphical effects, such as vignette +* -300: Name tags, waypoints +* -200: Wieldhand +* -100: Things that block the player's view, e.g. masks +* 0: Default. For standard in-game HUD elements like crosshair, hotbar, + minimap, builtin statbars, etc. +* 100: Temporary text messages or notification icons +* 1000: Full-screen effects such as full-black screen or credits. + This includes effects that cover the entire screen +* Other: If your HUD element doesn't fit into any category, pick a number + between the suggested values + + Below are the specific uses for fields in each type; fields not listed for that type are ignored. -- cgit v1.2.3 From cb9a44ef8998ff66c00187efc508bf8bd6cc2d67 Mon Sep 17 00:00:00 2001 From: Hugues Ross Date: Sat, 2 May 2020 07:32:02 -0400 Subject: Add 'content_offset' and 'padding' style properties for buttons (#9661) * Add padding and content_offset style properties to buttons --- doc/lua_api.txt | 6 +++- games/minimal/mods/test/formspec.lua | 3 +- src/gui/StyleSpec.h | 54 ++++++++++++++++++++++++++++++++++++ src/gui/guiButton.cpp | 44 ++++++++++++++++------------- src/gui/guiButton.h | 2 ++ 5 files changed, 88 insertions(+), 21 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 988acde89..1ffb5c39b 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2697,10 +2697,14 @@ Some types may inherit styles from parent types. * bgimg - standard background image. Defaults to none. * bgimg_hovered - background image when hovered. Defaults to bgimg when not provided. * bgimg_middle - Makes the bgimg textures render in 9-sliced mode and defines the middle rect. - See background9[] documentation for more details + See background9[] documentation for more details. This property also pads the + button's content when set. * bgimg_pressed - background image when pressed. Defaults to bgimg when not provided. * border - boolean, draw border. Set to false to hide the bevelled button pane. Default true. + * content_offset - 2d vector, shifts the position of the button's content without resizing it. * noclip - boolean, set to true to allow the element to exceed formspec bounds. + * padding - rect, adds space between the edges of the button and the content. This value is + relative to bgimg_middle. * textcolor - color, default white. * checkbox * noclip - boolean, set to true to allow the element to exceed formspec bounds. diff --git a/games/minimal/mods/test/formspec.lua b/games/minimal/mods/test/formspec.lua index 4ab4f2717..a5d3074cd 100644 --- a/games/minimal/mods/test/formspec.lua +++ b/games/minimal/mods/test/formspec.lua @@ -95,7 +95,7 @@ local style_fs = [[ style[one_btn13;border=false] item_image_button[1.25,8.35;1,1;default:sword_steel;one_btn13;NoBor] - style[one_btn14;border=false;bgimg=test_bg.png;fgimg=bubble.png] + style[one_btn14;border=false;bgimg=test_bg.png;fgimg=bubble.png;padding=8] style[one_btn14:hovered;bgimg=test_bg_hovered.png;fgimg=default_apple.png;textcolor=red] style[one_btn14:pressed;bgimg=test_bg_pressed.png;fgimg=heart.png;textcolor=green] style[one_btn14:hovered+pressed;textcolor=blue] @@ -105,6 +105,7 @@ local style_fs = [[ item_image_button[1.25,9.6;1,1;default:sword_steel;one_btn15;Bg] style[one_btn16;border=false;bgimg=test_bg_9slice.png;bgimg_hovered=test_bg_9slice_hovered.png;bgimg_pressed=test_bg_9slice_pressed.png;bgimg_middle=4,6] + style[one_btn16:pressed;content_offset=0,1] button[2.5,9.6;2,1;one_btn16;9-Slice Bg] diff --git a/src/gui/StyleSpec.h b/src/gui/StyleSpec.h index 799fbf46d..3e842e826 100644 --- a/src/gui/StyleSpec.h +++ b/src/gui/StyleSpec.h @@ -44,6 +44,8 @@ public: FGIMG_HOVERED, // Note: Deprecated property FGIMG_PRESSED, // Note: Deprecated property ALPHA, + CONTENT_OFFSET, + PADDING, NUM_PROPERTIES, NONE }; @@ -92,6 +94,10 @@ public: return FGIMG_PRESSED; } else if (name == "alpha") { return ALPHA; + } else if (name == "content_offset") { + return CONTENT_OFFSET; + } else if (name == "padding") { + return PADDING; } else { return NONE; } @@ -196,6 +202,29 @@ public: return rect; } + irr::core::vector2d getVector2i(Property prop, irr::core::vector2d def) const + { + const auto &val = properties[prop]; + if (val.empty()) + return def; + + irr::core::vector2d vec; + if (!parseVector2i(val, &vec)) + return def; + + return vec; + } + + irr::core::vector2d getVector2i(Property prop) const + { + const auto &val = properties[prop]; + FATAL_ERROR_IF(val.empty(), "Unexpected missing property"); + + irr::core::vector2d vec; + parseVector2i(val, &vec); + return vec; + } + video::ITexture *getTexture(Property prop, ISimpleTextureSource *tsrc, video::ITexture *def) const { @@ -286,4 +315,29 @@ private: return true; } + + bool parseVector2i(const std::string &value, irr::core::vector2d *parsed_vec) const + { + irr::core::vector2d vec; + std::vector v_vector = split(value, ','); + + if (v_vector.size() == 1) { + s32 x = stoi(v_vector[0]); + vec.X = x; + vec.Y = x; + } else if (v_vector.size() == 2) { + s32 x = stoi(v_vector[0]); + s32 y = stoi(v_vector[1]); + vec.X = x; + vec.Y = y; + } else { + warningstream << "Invalid vector2d string format: \"" << value + << "\"" << std::endl; + return false; + } + + *parsed_vec = vec; + + return true; + } }; diff --git a/src/gui/guiButton.cpp b/src/gui/guiButton.cpp index 9dfe36bc4..ff35958fd 100644 --- a/src/gui/guiButton.cpp +++ b/src/gui/guiButton.cpp @@ -592,25 +592,6 @@ void GUIButton::setPressed(bool pressed) { ClickTime = porting::getTimeMs(); Pressed = pressed; - - GUISkin* skin = dynamic_cast(Environment->getSkin()); - - for(IGUIElement *child : getChildren()) - { - core::rect originalRect = child->getRelativePosition(); - if (Pressed) { - child->setRelativePosition(originalRect + - core::dimension2d( - skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X), - skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y))); - } else { - child->setRelativePosition(originalRect - - core::dimension2d( - skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X), - skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y))); - } - } - setFromState(); } } @@ -819,7 +800,32 @@ void GUIButton::setFromStyle(const StyleSpec& style) } else { setImage(nullptr); } + BgMiddle = style.getRect(StyleSpec::BGIMG_MIDDLE, BgMiddle); + + // Child padding and offset + Padding = style.getRect(StyleSpec::PADDING, core::rect()); + Padding = core::rect( + Padding.UpperLeftCorner + BgMiddle.UpperLeftCorner, + Padding.LowerRightCorner + BgMiddle.LowerRightCorner); + + GUISkin* skin = dynamic_cast(Environment->getSkin()); + core::vector2d defaultPressOffset( + skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X), + skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y)); + ContentOffset = style.getVector2i(StyleSpec::CONTENT_OFFSET, isPressed() + ? defaultPressOffset + : core::vector2d(0)); + + core::rect childBounds( + Padding.UpperLeftCorner.X + ContentOffset.X, + Padding.UpperLeftCorner.Y + ContentOffset.Y, + AbsoluteRect.getWidth() + Padding.LowerRightCorner.X + ContentOffset.X, + AbsoluteRect.getHeight() + Padding.LowerRightCorner.Y + ContentOffset.Y); + + for (IGUIElement *child : getChildren()) { + child->setRelativePosition(childBounds); + } } //! Set the styles used for each state diff --git a/src/gui/guiButton.h b/src/gui/guiButton.h index ef10f926e..95fa1a2a1 100644 --- a/src/gui/guiButton.h +++ b/src/gui/guiButton.h @@ -336,5 +336,7 @@ private: gui::IGUIStaticText *StaticText; core::rect BgMiddle; + core::rect Padding; + core::vector2d ContentOffset; // END PATCH }; -- cgit v1.2.3 From 3ed5619d9a9e08031a749b8b4f5a3d1bc0e77608 Mon Sep 17 00:00:00 2001 From: oilboi <47129783+oilboi@users.noreply.github.com> Date: Tue, 5 May 2020 02:35:55 -0400 Subject: Fix small typo (#9813) --- doc/client_lua_api.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index 53ed680d0..53442d308 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -112,7 +112,7 @@ The main Lua script. Running this script should register everything it wants to register. Subsequent execution depends on minetest calling the registered callbacks. -**NOTE**: Client mods currently can't provide and textures, sounds or models by +**NOTE**: Client mods currently can't provide textures, sounds, or models by themselves. Any media referenced in function calls must already be loaded (provided by mods that exist on the server). -- cgit v1.2.3 From 1b6f40c35632ab5a2066822c8b5d4c09d469f49d Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Mon, 4 May 2020 20:02:33 +0200 Subject: Rename moveresult speed to velocity --- doc/lua_api.txt | 4 ++-- src/script/common/c_content.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 1ffb5c39b..b1099ec59 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6632,8 +6632,8 @@ Collision info passed to `on_step`: type = string, -- "node" or "object", axis = string, -- "x", "y" or "z" node_pos = vector, -- if type is "node" - old_speed = vector, - new_speed = vector, + old_velocity = vector, + new_velocity = vector, }, ... } diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 6ff642738..95364000c 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -2046,10 +2046,10 @@ void push_collision_move_result(lua_State *L, const collisionMoveResult &res) } push_v3f(L, c.old_speed / BS); - lua_setfield(L, -2, "old_speed"); + lua_setfield(L, -2, "old_velocity"); push_v3f(L, c.new_speed / BS); - lua_setfield(L, -2, "new_speed"); + lua_setfield(L, -2, "new_velocity"); lua_rawseti(L, -2, i++); } -- cgit v1.2.3 From b6b80f55c8a2bf4eae440108b3274f2f921e3a94 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sun, 26 Apr 2020 22:52:00 +0200 Subject: Expose collided objects in moveresult closes #9787 --- doc/lua_api.txt | 1 + src/collision.cpp | 40 ++++++++++++++++++++++++++-------------- src/collision.h | 1 + src/script/common/c_content.cpp | 3 +++ 4 files changed, 31 insertions(+), 14 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index b1099ec59..948e0f89e 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6632,6 +6632,7 @@ Collision info passed to `on_step`: type = string, -- "node" or "object", axis = string, -- "x", "y" or "z" node_pos = vector, -- if type is "node" + object = ObjectRef, -- if type is "object" old_velocity = vector, new_velocity = vector, }, diff --git a/src/collision.cpp b/src/collision.cpp index a089f3377..3b5e79a66 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -37,18 +37,30 @@ with this program; if not, write to the Free Software Foundation, Inc., #endif struct NearbyCollisionInfo { - NearbyCollisionInfo(bool is_ul, bool is_obj, int bouncy, - const v3s16 &pos, const aabb3f &box) : + // node + NearbyCollisionInfo(bool is_ul, int bouncy, const v3s16 &pos, + const aabb3f &box) : is_unloaded(is_ul), - is_object(is_obj), + obj(nullptr), bouncy(bouncy), position(pos), box(box) {} + // object + NearbyCollisionInfo(ActiveObject *obj, int bouncy, + const aabb3f &box) : + is_unloaded(false), + obj(obj), + bouncy(bouncy), + box(box) + {} + + inline bool isObject() const { return obj != nullptr; } + bool is_unloaded; bool is_step_up = false; - bool is_object; + ActiveObject *obj; int bouncy; v3s16 position; aabb3f box; @@ -312,13 +324,13 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, for (auto box : nodeboxes) { box.MinEdge += posf; box.MaxEdge += posf; - cinfo.emplace_back(false, false, n_bouncy_value, p, box); + cinfo.emplace_back(false, n_bouncy_value, p, box); } } else { // Collide with unloaded nodes (position invalid) and loaded // CONTENT_IGNORE nodes (position valid) aabb3f box = getNodeBox(p, BS); - cinfo.emplace_back(true, false, 0, p, box); + cinfo.emplace_back(true, 0, p, box); } } @@ -383,12 +395,10 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, iter != objects.end(); ++iter) { ActiveObject *object = *iter; - if (object) { + if (object && object->collideWithObjects()) { aabb3f object_collisionbox; - if (object->getCollisionBox(&object_collisionbox) && - object->collideWithObjects()) { - cinfo.emplace_back(false, true, 0, v3s16(), object_collisionbox); - } + if (object->getCollisionBox(&object_collisionbox)) + cinfo.emplace_back(object, 0, object_collisionbox); } } #ifndef SERVER @@ -399,7 +409,8 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, v3f lplayer_pos = lplayer->getPosition(); lplayer_collisionbox.MinEdge += lplayer_pos; lplayer_collisionbox.MaxEdge += lplayer_pos; - cinfo.emplace_back(false, true, 0, v3s16(), lplayer_collisionbox); + ActiveObject *obj = (ActiveObject*) lplayer->getCAO(); + cinfo.emplace_back(obj, 0, lplayer_collisionbox); } } #endif @@ -498,12 +509,13 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, is_collision = false; CollisionInfo info; - if (nearest_info.is_object) + if (nearest_info.isObject()) info.type = COLLISION_OBJECT; else info.type = COLLISION_NODE; info.node_p = nearest_info.position; + info.object = nearest_info.obj; info.old_speed = *speed_f; info.plane = nearest_collided; @@ -572,7 +584,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, if (std::fabs(cbox.MaxEdge.Y - box.MinEdge.Y) < 0.05f) { result.touching_ground = true; - if (box_info.is_object) + if (box_info.isObject()) result.standing_on_object = true; } } diff --git a/src/collision.h b/src/collision.h index fa47cccc1..87a502828 100644 --- a/src/collision.h +++ b/src/collision.h @@ -48,6 +48,7 @@ struct CollisionInfo CollisionType type = COLLISION_NODE; CollisionAxis axis = COLLISION_AXIS_NONE; v3s16 node_p = v3s16(-32768,-32768,-32768); // COLLISION_NODE + ActiveObject *object = nullptr; // COLLISION_OBJECT v3f old_speed; v3f new_speed; int plane = -1; diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 95364000c..dac828316 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -2043,6 +2043,9 @@ void push_collision_move_result(lua_State *L, const collisionMoveResult &res) if (c.type == COLLISION_NODE) { push_v3s16(L, c.node_p); lua_setfield(L, -2, "node_pos"); + } else if (c.type == COLLISION_OBJECT) { + push_objectRef(L, c.object->getId()); + lua_setfield(L, -2, "object"); } push_v3f(L, c.old_speed / BS); -- cgit v1.2.3 From 664800b2adda44039a85c3566b4ed958abff8b95 Mon Sep 17 00:00:00 2001 From: v-rob Date: Wed, 6 May 2020 10:36:02 -0700 Subject: FormSpec: Add universal style selector `*` (#9718) --- doc/lua_api.txt | 6 ++++-- src/gui/guiFormSpecMenu.cpp | 20 ++++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 948e0f89e..961e1ff37 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2567,7 +2567,7 @@ Elements * Set the style for the element(s) matching `selector` by name. * `selector` can be one of: - * `` - An element name. + * `` - An element name. Includes `*`, which represents every element. * `:` - An element name, a colon, and one or more states. * `state` is a list of states separated by the `+` character. * If a state is provided, the style will only take effect when the element is in that state. @@ -2580,7 +2580,7 @@ Elements * Set the style for the element(s) matching `selector` by type. * `selector` can be one of: - * `` - An element type. + * `` - An element type. Includes `*`, which represents every element. * `:` - An element type, a colon, and one or more states. * `state` is a list of states separated by the `+` character. * If a state is provided, the style will only take effect when the element is in that state. @@ -2647,6 +2647,8 @@ A name/type can optionally be a comma separated list of names/types, like so: world_delete,world_create,world_configure button,image_button +A `*` type can be used to select every element in the formspec. + Any name/type in the list can also be accompanied by a `+`-separated list of states, like so: world_delete:hovered+pressed diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 567f0ca7e..72095a86e 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -4609,20 +4609,32 @@ StyleSpec GUIFormSpecMenu::getDefaultStyleForElement(const std::string &type, return getStyleForElement(type, name, parent_type)[StyleSpec::STATE_DEFAULT]; } -std::array GUIFormSpecMenu::getStyleForElement(const std::string &type, - const std::string &name, const std::string &parent_type) +std::array GUIFormSpecMenu::getStyleForElement( + const std::string &type, const std::string &name, const std::string &parent_type) { std::array ret; + auto it = theme_by_type.find("*"); + if (it != theme_by_type.end()) { + for (const StyleSpec &spec : it->second) + ret[(u32)spec.getState()] |= spec; + } + + it = theme_by_name.find("*"); + if (it != theme_by_name.end()) { + for (const StyleSpec &spec : it->second) + ret[(u32)spec.getState()] |= spec; + } + if (!parent_type.empty()) { - auto it = theme_by_type.find(parent_type); + it = theme_by_type.find(parent_type); if (it != theme_by_type.end()) { for (const StyleSpec &spec : it->second) ret[(u32)spec.getState()] |= spec; } } - auto it = theme_by_type.find(type); + it = theme_by_type.find(type); if (it != theme_by_type.end()) { for (const StyleSpec &spec : it->second) ret[(u32)spec.getState()] |= spec; -- cgit v1.2.3 From 6e1372bd894d955300c40d69e5c882e9cc7d7523 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 11 May 2020 21:40:45 +0200 Subject: Add support for statbar “off state” icons (#9462) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds support for optional “off state” icons for statbars. “off state icons” can be used to denote the lack of something, like missing hearts or bubbles. Add "off state" textures to the builtin statbars. Co-authored-by: SmallJoker --- builtin/game/statbars.lua | 4 ++ doc/lua_api.txt | 16 ++++-- doc/texture_packs.txt | 4 ++ src/client/clientevent.h | 1 + src/client/game.cpp | 7 +++ src/client/hud.cpp | 96 ++++++++++++++++++++++++++++++------ src/client/hud.h | 5 +- src/hud.cpp | 1 + src/hud.h | 2 + src/network/clientpackethandler.cpp | 15 ++---- src/network/networkprotocol.h | 6 ++- src/script/common/c_content.cpp | 8 +++ src/server.cpp | 3 +- textures/base/pack/bubble_gone.png | Bin 0 -> 68 bytes textures/base/pack/heart_gone.png | Bin 0 -> 68 bytes 15 files changed, 132 insertions(+), 36 deletions(-) create mode 100644 textures/base/pack/bubble_gone.png create mode 100644 textures/base/pack/heart_gone.png (limited to 'doc') diff --git a/builtin/game/statbars.lua b/builtin/game/statbars.lua index 6b5b54428..d192029c5 100644 --- a/builtin/game/statbars.lua +++ b/builtin/game/statbars.lua @@ -5,7 +5,9 @@ local health_bar_definition = { hud_elem_type = "statbar", position = {x = 0.5, y = 1}, text = "heart.png", + text2 = "heart_gone.png", number = core.PLAYER_MAX_HP_DEFAULT, + item = core.PLAYER_MAX_HP_DEFAULT, direction = 0, size = {x = 24, y = 24}, offset = {x = (-10 * 24) - 25, y = -(48 + 24 + 16)}, @@ -15,7 +17,9 @@ local breath_bar_definition = { hud_elem_type = "statbar", position = {x = 0.5, y = 1}, text = "bubble.png", + text2 = "bubble_gone.png", number = core.PLAYER_MAX_BREATH_DEFAULT, + item = core.PLAYER_MAX_BREATH_DEFAULT * 2, direction = 0, size = {x = 24, y = 24}, offset = {x = 25, y= -(48 + 24 + 16)}, diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 961e1ff37..4078e21a1 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1289,9 +1289,9 @@ To account for differing resolutions, the position coordinates are the percentage of the screen, ranging in value from `0` to `1`. The name field is not yet used, but should contain a description of what the -HUD element represents. The direction field is the direction in which something -is drawn. +HUD element represents. +The `direction` field is the direction in which something is drawn. `0` draws from left to right, `1` draws from right to left, `2` draws from top to bottom, and `3` draws from bottom to top. @@ -1355,12 +1355,16 @@ Displays text on the HUD. ### `statbar` -Displays a horizontal bar made up of half-images. +Displays a horizontal bar made up of half-images with an optional background. -* `text`: The name of the texture that is used. +* `text`: The name of the texture to use. +* `text2`: Optional texture name to enable a background / "off state" + texture (useful to visualize the maximal value). Both textures + must have the same size. * `number`: The number of half-textures that are displayed. If odd, will end with a vertically center-split texture. -* `direction` +* `item`: Same as `number` but for the "off state" texture +* `direction`: To which direction the images will extend to * `offset`: offset in pixels from position. * `size`: If used, will force full-image size to this value (override texture pack image size) @@ -7772,6 +7776,8 @@ Used by `Player:hud_add`. Returned by `Player:hud_get`. text = "", + text2 = "", + number = 2, item = 3, diff --git a/doc/texture_packs.txt b/doc/texture_packs.txt index 4e7bc93c4..94151f1a4 100644 --- a/doc/texture_packs.txt +++ b/doc/texture_packs.txt @@ -64,6 +64,8 @@ by texture packs. All existing fallback textures can be found in the directory * `bubble.png`: the bubble texture when the player is drowning (default size: 12×12) +* `bubble_gone.png`: like `bubble.png`, but denotes lack of breath + (transparent by default, same size as bubble.png) * `crack_anylength.png`: node overlay texture when digging @@ -76,6 +78,8 @@ by texture packs. All existing fallback textures can be found in the directory * `heart.png`: used to display the health points of the player (default size: 12×12) +* `heart_gone.png`: like `heart.png`, but denotes lack of health points + (transparent by default, same size as heart.png) * `minimap_mask_round.png`: round minimap mask, white gets replaced by the map * `minimap_mask_square.png`: mask used for the square minimap diff --git a/src/client/clientevent.h b/src/client/clientevent.h index f5689c25b..7f3984b03 100644 --- a/src/client/clientevent.h +++ b/src/client/clientevent.h @@ -136,6 +136,7 @@ struct ClientEvent v3f *world_pos; v2s32 *size; s16 z_index; + std::string *text2; } hudadd; struct { diff --git a/src/client/game.cpp b/src/client/game.cpp index 4d7a85526..422e17d4f 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2672,6 +2672,7 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam) delete event->hudadd.offset; delete event->hudadd.world_pos; delete event->hudadd.size; + delete event->hudadd.text2; return; } @@ -2689,6 +2690,7 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam) e->world_pos = *event->hudadd.world_pos; e->size = *event->hudadd.size; e->z_index = event->hudadd.z_index; + e->text2 = *event->hudadd.text2; hud_server_to_client[server_id] = player->addHud(e); delete event->hudadd.pos; @@ -2699,6 +2701,7 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam) delete event->hudadd.offset; delete event->hudadd.world_pos; delete event->hudadd.size; + delete event->hudadd.text2; } void Game::handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam) @@ -2771,6 +2774,10 @@ void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *ca case HUD_STAT_Z_INDEX: e->z_index = event->hudchange.data; break; + + case HUD_STAT_TEXT2: + e->text2 = *event->hudchange.sdata; + break; } delete event->hudchange.v3fdata; diff --git a/src/client/hud.cpp b/src/client/hud.cpp index 56763e7e4..f8f712762 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -332,7 +332,8 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) break; } case HUD_ELEM_STATBAR: { v2s32 offs(e->offset.X, e->offset.Y); - drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs, e->size); + drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->text2, + e->number, e->item, offs, e->size); break; } case HUD_ELEM_INVENTORY: { InventoryList *inv = inventory->getList(e->text); @@ -401,8 +402,9 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) } -void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, const std::string &texture, - s32 count, v2s32 offset, v2s32 size) +void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, + const std::string &texture, const std::string &bgtexture, + s32 count, s32 maxcount, v2s32 offset, v2s32 size) { const video::SColor color(255, 255, 255, 255); const video::SColor colors[] = {color, color, color, color}; @@ -411,6 +413,11 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, const std::string &tex if (!stat_texture) return; + video::ITexture *stat_texture_bg = nullptr; + if (!bgtexture.empty()) { + stat_texture_bg = tsrc->getTexture(bgtexture); + } + core::dimension2di srcd(stat_texture->getOriginalSize()); core::dimension2di dstd; if (size == v2s32()) { @@ -430,43 +437,100 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, const std::string &tex p += offset; v2s32 steppos; - core::rect srchalfrect, dsthalfrect; switch (drawdir) { case HUD_DIR_RIGHT_LEFT: steppos = v2s32(-1, 0); - srchalfrect = core::rect(srcd.Width / 2, 0, srcd.Width, srcd.Height); - dsthalfrect = core::rect(dstd.Width / 2, 0, dstd.Width, dstd.Height); break; case HUD_DIR_TOP_BOTTOM: steppos = v2s32(0, 1); - srchalfrect = core::rect(0, 0, srcd.Width, srcd.Height / 2); - dsthalfrect = core::rect(0, 0, dstd.Width, dstd.Height / 2); break; case HUD_DIR_BOTTOM_TOP: steppos = v2s32(0, -1); - srchalfrect = core::rect(0, srcd.Height / 2, srcd.Width, srcd.Height); - dsthalfrect = core::rect(0, dstd.Height / 2, dstd.Width, dstd.Height); break; default: + // From left to right steppos = v2s32(1, 0); - srchalfrect = core::rect(0, 0, srcd.Width / 2, srcd.Height); - dsthalfrect = core::rect(0, 0, dstd.Width / 2, dstd.Height); + break; + } + + auto calculate_clipping_rect = [] (core::dimension2di src, + v2s32 steppos) -> core::rect { + + // Create basic rectangle + core::rect rect(0, 0, + src.Width - std::abs(steppos.X) * src.Width / 2, + src.Height - std::abs(steppos.Y) * src.Height / 2 + ); + // Move rectangle left or down + if (steppos.X == -1) + rect += v2s32(src.Width / 2, 0); + if (steppos.Y == -1) + rect += v2s32(0, src.Height / 2); + return rect; + }; + // Rectangles for 1/2 the actual value to display + core::rect srchalfrect, dsthalfrect; + // Rectangles for 1/2 the "off state" texture + core::rect srchalfrect2, dsthalfrect2; + + if (count % 2 == 1) { + // Need to draw halves: Calculate rectangles + srchalfrect = calculate_clipping_rect(srcd, steppos); + dsthalfrect = calculate_clipping_rect(dstd, steppos); + srchalfrect2 = calculate_clipping_rect(srcd, steppos * -1); + dsthalfrect2 = calculate_clipping_rect(dstd, steppos * -1); } + steppos.X *= dstd.Width; steppos.Y *= dstd.Height; + // Draw full textures for (s32 i = 0; i < count / 2; i++) { core::rect srcrect(0, 0, srcd.Width, srcd.Height); - core::rect dstrect(0,0, dstd.Width, dstd.Height); + core::rect dstrect(0, 0, dstd.Width, dstd.Height); dstrect += p; - draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true); + draw2DImageFilterScaled(driver, stat_texture, + dstrect, srcrect, NULL, colors, true); p += steppos; } if (count % 2 == 1) { - dsthalfrect += p; - draw2DImageFilterScaled(driver, stat_texture, dsthalfrect, srchalfrect, NULL, colors, true); + // Draw half a texture + draw2DImageFilterScaled(driver, stat_texture, + dsthalfrect + p, srchalfrect, NULL, colors, true); + + if (stat_texture_bg && maxcount > count) { + draw2DImageFilterScaled(driver, stat_texture_bg, + dsthalfrect2 + p, srchalfrect2, + NULL, colors, true); + p += steppos; + } + } + + if (stat_texture_bg && maxcount > count / 2) { + // Draw "off state" textures + s32 start_offset; + if (count % 2 == 1) + start_offset = count / 2 + 1; + else + start_offset = count / 2; + for (s32 i = start_offset; i < maxcount / 2; i++) { + core::rect srcrect(0, 0, srcd.Width, srcd.Height); + core::rect dstrect(0, 0, dstd.Width, dstd.Height); + + dstrect += p; + draw2DImageFilterScaled(driver, stat_texture_bg, + dstrect, srcrect, + NULL, colors, true); + p += steppos; + } + + if (maxcount % 2 == 1) { + draw2DImageFilterScaled(driver, stat_texture_bg, + dsthalfrect + p, srchalfrect, + NULL, colors, true); + } } } diff --git a/src/client/hud.h b/src/client/hud.h index cab115990..6274b1a83 100644 --- a/src/client/hud.h +++ b/src/client/hud.h @@ -82,8 +82,9 @@ public: private: bool calculateScreenPos(const v3s16 &camera_offset, HudElement *e, v2s32 *pos); - void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, const std::string &texture, - s32 count, v2s32 offset, v2s32 size = v2s32()); + void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, + const std::string &texture, const std::string& bgtexture, + s32 count, s32 maxcount, v2s32 offset, v2s32 size = v2s32()); void drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount, s32 inv_offset, InventoryList *mainlist, u16 selectitem, diff --git a/src/hud.cpp b/src/hud.cpp index 39625b5fd..3079b5cd8 100644 --- a/src/hud.cpp +++ b/src/hud.cpp @@ -46,6 +46,7 @@ const struct EnumString es_HudElementStat[] = {HUD_STAT_WORLD_POS, "world_pos"}, {HUD_STAT_SIZE, "size"}, {HUD_STAT_Z_INDEX, "z_index"}, + {HUD_STAT_TEXT2, "text2"}, {0, NULL}, }; diff --git a/src/hud.h b/src/hud.h index b0977c6a4..bab420ed2 100644 --- a/src/hud.h +++ b/src/hud.h @@ -77,6 +77,7 @@ enum HudElementStat { HUD_STAT_WORLD_POS, HUD_STAT_SIZE, HUD_STAT_Z_INDEX, + HUD_STAT_TEXT2, }; struct HudElement { @@ -93,6 +94,7 @@ struct HudElement { v3f world_pos; v2s32 size; s16 z_index = 0; + std::string text2; }; extern const EnumString es_HudElementType[]; diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 8d0225a3d..7b1b1368c 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1102,22 +1102,16 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt) v3f world_pos; v2s32 size; s16 z_index = 0; + std::string text2; *pkt >> server_id >> type >> pos >> name >> scale >> text >> number >> item >> dir >> align >> offset; try { *pkt >> world_pos; - } - catch(SerializationError &e) {}; - - try { *pkt >> size; - } catch(SerializationError &e) {}; - - try { *pkt >> z_index; - } - catch(PacketError &e) {} + *pkt >> text2; + } catch(PacketError &e) {}; ClientEvent *event = new ClientEvent(); event->type = CE_HUDADD; @@ -1135,6 +1129,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt) event->hudadd.world_pos = new v3f(world_pos); event->hudadd.size = new v2s32(size); event->hudadd.z_index = z_index; + event->hudadd.text2 = new std::string(text2); m_client_event_queue.push(event); } @@ -1171,7 +1166,7 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt) if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE || stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET) *pkt >> v2fdata; - else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT) + else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT || stat == HUD_STAT_TEXT2) *pkt >> sdata; else if (stat == HUD_STAT_WORLD_POS) *pkt >> v3fdata; diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 527ebba7c..ab924f1db 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -560,10 +560,10 @@ enum ToClientCommand u32 id u8 type v2f1000 pos - u32 len + u16 len u8[len] name v2f1000 scale - u32 len2 + u16 len2 u8[len2] text u32 number u32 item @@ -573,6 +573,8 @@ enum ToClientCommand v3f1000 world_pos v2s32 size s16 z_index + u16 len3 + u8[len3] text2 */ TOCLIENT_HUDRM = 0x4a, diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index dac828316..540b7222f 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -1871,6 +1871,7 @@ void read_hud_element(lua_State *L, HudElement *elem) elem->dir = getintfield_default(L, 2, "direction", 0); elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX, getintfield_default(L, 2, "z_index", 0))); + elem->text2 = getstringfield_default(L, 2, "text2", ""); // Deprecated, only for compatibility's sake if (elem->dir == 0) @@ -1939,6 +1940,9 @@ void push_hud_element(lua_State *L, HudElement *elem) lua_pushnumber(L, elem->z_index); lua_setfield(L, -2, "z_index"); + + lua_pushstring(L, elem->text2.c_str()); + lua_setfield(L, -2, "text2"); } HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value) @@ -2000,6 +2004,10 @@ HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value) elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX, luaL_checknumber(L, 4))); *value = &elem->z_index; break; + case HUD_STAT_TEXT2: + elem->text2 = luaL_checkstring(L, 4); + *value = &elem->text2; + break; } return stat; } diff --git a/src/server.cpp b/src/server.cpp index 16e026ce2..b28c30e1e 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1621,7 +1621,7 @@ void Server::SendHUDAdd(session_t peer_id, u32 id, HudElement *form) pkt << id << (u8) form->type << form->pos << form->name << form->scale << form->text << form->number << form->item << form->dir << form->align << form->offset << form->world_pos << form->size - << form->z_index; + << form->z_index << form->text2; Send(&pkt); } @@ -1647,6 +1647,7 @@ void Server::SendHUDChange(session_t peer_id, u32 id, HudElementStat stat, void break; case HUD_STAT_NAME: case HUD_STAT_TEXT: + case HUD_STAT_TEXT2: pkt << *(std::string *) value; break; case HUD_STAT_WORLD_POS: diff --git a/textures/base/pack/bubble_gone.png b/textures/base/pack/bubble_gone.png new file mode 100644 index 000000000..240ca4f8d Binary files /dev/null and b/textures/base/pack/bubble_gone.png differ diff --git a/textures/base/pack/heart_gone.png b/textures/base/pack/heart_gone.png new file mode 100644 index 000000000..240ca4f8d Binary files /dev/null and b/textures/base/pack/heart_gone.png differ -- cgit v1.2.3 From 9ba24f89f5846de6a8f0d7e01c89acfee1254704 Mon Sep 17 00:00:00 2001 From: Lars Müller <34514239+appgurueu@users.noreply.github.com> Date: Mon, 11 May 2020 21:41:36 +0200 Subject: Damage texture modifier (#9833) Adds a new object property "damage_texture_modifier" --- doc/lua_api.txt | 3 +++ src/client/content_cao.cpp | 14 +++++--------- src/object_properties.cpp | 5 +++++ src/object_properties.h | 1 + src/script/common/c_content.cpp | 4 ++++ 5 files changed, 18 insertions(+), 9 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 4078e21a1..db13f4224 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6589,6 +6589,9 @@ Player properties need to be saved manually. -- deleted when the block gets unloaded. -- The get_staticdata() callback is never called then. -- Defaults to 'true'. + + damage_texture_modifier = "^[brighten", + -- Texture modifier to be applied for a short duration when object is hit } Entity definition diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index aadd33bb9..eb1dad22b 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -1532,7 +1532,7 @@ void GenericCAO::processMessage(const std::string &data) } else if (cmd == AO_CMD_SET_TEXTURE_MOD) { std::string mod = deSerializeString(is); - // immediatly reset a engine issued texture modifier if a mod sends a different one + // immediately reset a engine issued texture modifier if a mod sends a different one if (m_reset_textures_timer > 0) { m_reset_textures_timer = -1; updateTextures(m_previous_texture_modifier); @@ -1646,13 +1646,11 @@ void GenericCAO::processMessage(const std::string &data) m_smgr, m_env, m_position, v2f(m_prop.visual_size.X, m_prop.visual_size.Y) * BS); m_env->addSimpleObject(simple); - } else if (m_reset_textures_timer < 0) { - // TODO: Execute defined fast response - // Flashing shall suffice as there is no definition + } else if (m_reset_textures_timer < 0 && !m_prop.damage_texture_modifier.empty()) { m_reset_textures_timer = 0.05; if(damage >= 2) m_reset_textures_timer += 0.05 * damage; - updateTextures(m_current_texture_modifier + "^[brighten"); + updateTextures(m_current_texture_modifier + m_prop.damage_texture_modifier); } } @@ -1723,13 +1721,11 @@ bool GenericCAO::directReportPunch(v3f dir, const ItemStack *punchitem, v2f(m_prop.visual_size.X, m_prop.visual_size.Y) * BS); m_env->addSimpleObject(simple); } - // TODO: Execute defined fast response - // Flashing shall suffice as there is no definition - if (m_reset_textures_timer < 0) { + if (m_reset_textures_timer < 0 && !m_prop.damage_texture_modifier.empty()) { m_reset_textures_timer = 0.05; if (result.damage >= 2) m_reset_textures_timer += 0.05 * result.damage; - updateTextures(m_current_texture_modifier + "^[brighten"); + updateTextures(m_current_texture_modifier + m_prop.damage_texture_modifier); } } diff --git a/src/object_properties.cpp b/src/object_properties.cpp index 4cf180b18..6ff344dce 100644 --- a/src/object_properties.cpp +++ b/src/object_properties.cpp @@ -68,6 +68,7 @@ std::string ObjectProperties::dump() os << ", eye_height=" << eye_height; os << ", zoom_fov=" << zoom_fov; os << ", use_texture_alpha=" << use_texture_alpha; + os << ", damage_texture_modifier=" << damage_texture_modifier; return os.str(); } @@ -114,6 +115,7 @@ void ObjectProperties::serialize(std::ostream &os) const writeF32(os, eye_height); writeF32(os, zoom_fov); writeU8(os, use_texture_alpha); + os << serializeString(damage_texture_modifier); // Add stuff only at the bottom. // Never remove anything, because we don't want new versions of this @@ -166,4 +168,7 @@ void ObjectProperties::deSerialize(std::istream &is) eye_height = readF32(is); zoom_fov = readF32(is); use_texture_alpha = readU8(is); + try { + damage_texture_modifier = deSerializeString(is); + } catch (SerializationError &e) {} } diff --git a/src/object_properties.h b/src/object_properties.h index 3895f3379..f7848f5a2 100644 --- a/src/object_properties.h +++ b/src/object_properties.h @@ -39,6 +39,7 @@ struct ObjectProperties std::string mesh = ""; v3f visual_size = v3f(1, 1, 1); std::vector textures; + std::string damage_texture_modifier = "^[brighten"; std::vector colors; v2s16 spritediv = v2s16(1, 1); v2s16 initial_sprite_basepos; diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 540b7222f..de9634c42 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -327,6 +327,8 @@ void read_object_properties(lua_State *L, int index, getfloatfield(L, -1, "zoom_fov", prop->zoom_fov); getboolfield(L, -1, "use_texture_alpha", prop->use_texture_alpha); + + getstringfield(L, -1, "damage_texture_modifier", prop->damage_texture_modifier); } /******************************************************************************/ @@ -409,6 +411,8 @@ void push_object_properties(lua_State *L, ObjectProperties *prop) lua_setfield(L, -2, "zoom_fov"); lua_pushboolean(L, prop->use_texture_alpha); lua_setfield(L, -2, "use_texture_alpha"); + lua_pushlstring(L, prop->damage_texture_modifier.c_str(), prop->damage_texture_modifier.size()); + lua_setfield(L, -2, "damage_texture_modifier"); } /******************************************************************************/ -- cgit v1.2.3 From 7ec76e530db9c3ed093e6edeca156e9311a6378a Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 12 May 2020 03:52:52 +0200 Subject: Add mapgen settings to world creation dialog (#9254) --- builtin/mainmenu/dlg_create_world.lua | 328 +++++++++++++++++++++++++++++++--- doc/lua_api.txt | 4 + 2 files changed, 310 insertions(+), 22 deletions(-) (limited to 'doc') diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua index f28ae6960..0d977a17c 100644 --- a/builtin/mainmenu/dlg_create_world.lua +++ b/builtin/mainmenu/dlg_create_world.lua @@ -17,13 +17,110 @@ local worldname = "" +local function table_to_flags(ftable) + -- Convert e.g. { jungles = true, caves = false } to "jungles,nocaves" + local str = {} + for flag, is_set in pairs(ftable) do + str[#str + 1] = is_set and flag or ("no" .. flag) + end + return table.concat(str, ",") +end + +-- Same as check_flag but returns a string +local function strflag(flags, flag) + return (flags[flag] == true) and "true" or "false" +end + +local cb_caverns = { "caverns", fgettext("Caverns"), "caverns", + fgettext("Very large caverns deep in the underground") } +local tt_sea_rivers = fgettext("Sea level rivers") + +local flag_checkboxes = { + v5 = { + cb_caverns, + }, + v7 = { + cb_caverns, + { "ridges", fgettext("Rivers"), "ridges", tt_sea_rivers }, + { "mountains", fgettext("Mountains"), "mountains" }, + { "floatlands", fgettext("Floatlands (experimental)"), "floatlands", + fgettext("Floating landmasses in the sky") }, + }, + carpathian = { + cb_caverns, + { "rivers", fgettext("Rivers"), "rivers", tt_sea_rivers }, + }, + valleys = { + { "altitude-chill", fgettext("Altitude chill"), "altitude_chill", + fgettext("Reduces heat with altitude") }, + { "altitude-dry", fgettext("Altitude dry"), "altitude_dry", + fgettext("Reduces humidity with altitude") }, + { "humid-rivers", fgettext("Humid rivers"), "humid_rivers", + fgettext("Increases humidity around rivers") }, + { "vary-river-depth", fgettext("Vary river depth"), "vary_river_depth", + fgettext("Low humidity and high heat causes shallow or dry rivers") }, + }, + flat = { + { "hills", fgettext("Hills"), "hills" }, + { "lakes", fgettext("Lakes"), "lakes" }, + }, + fractal = { + { "terrain", fgettext("Additional terrain"), "terrain", + fgettext("Generate non-fractal terrain: Oceans and underground") }, + }, + v6 = { + { "trees", fgettext("Trees and jungle grass"), "trees" }, + { "flat", fgettext("Flat terrain"), "flat" }, + { "mudflow", fgettext("Mud flow"), "mudflow", + fgettext("Terrain surface erosion") }, + -- Biome settings are in mgv6_biomes below + }, +} + +local mgv6_biomes = { + { + fgettext("Temperate, Desert, Jungle, Tundra, Taiga"), + {jungles = true, snowbiomes = true} + }, + { + fgettext("Temperate, Desert, Jungle"), + {jungles = true, snowbiomes = false} + }, + { + fgettext("Temperate, Desert"), + {jungles = false, snowbiomes = false} + }, +} + local function create_world_formspec(dialogdata) + + -- Error out when no games found + if #pkgmgr.games == 0 then + return "size[12.25,3,true]" .. + "box[0,0;12,2;#ff8800]" .. + "textarea[0.3,0;11.7,2;;;".. + fgettext("You have no games installed.") .. "\n" .. + fgettext("Download one from minetest.net") .. "]" .. + "button[4.75,2.5;3,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]" + end + local mapgens = core.get_mapgen_names() local current_seed = core.settings:get("fixed_map_seed") or "" local current_mg = core.settings:get("mg_name") local gameid = core.settings:get("menu_last_game") + local flags = { + main = core.settings:get_flags("mg_flags"), + v5 = core.settings:get_flags("mgv5_spflags"), + v6 = core.settings:get_flags("mgv6_spflags"), + v7 = core.settings:get_flags("mgv7_spflags"), + fractal = core.settings:get_flags("mgfractal_spflags"), + carpathian = core.settings:get_flags("mgcarpathian_spflags"), + valleys = core.settings:get_flags("mgvalleys_spflags"), + flat = core.settings:get_flags("mgflat_spflags"), + } + local gameidx = 0 if gameid ~= nil then local _ @@ -35,6 +132,7 @@ local function create_world_formspec(dialogdata) end local game_by_gameidx = core.get_game(gameidx) + local disallowed_mapgen_settings = {} if game_by_gameidx ~= nil then local gamepath = game_by_gameidx.path local gameconfig = Settings(gamepath.."/game.conf") @@ -64,49 +162,193 @@ local function create_world_formspec(dialogdata) end end end + + local ds = (gameconfig:get("disallowed_mapgen_settings") or ""):split() + for _, value in pairs(ds) do + disallowed_mapgen_settings[value:trim()] = true + end end local mglist = "" - local selindex = 1 + local selindex local i = 1 + local first_mg for k,v in pairs(mapgens) do + if not first_mg then + first_mg = v + end if current_mg == v then selindex = i end i = i + 1 mglist = mglist .. v .. "," end + if not selindex then + selindex = 1 + current_mg = first_mg + end mglist = mglist:sub(1, -2) - current_seed = core.formspec_escape(current_seed) - local retval = - "size[11.5,6.5,true]" .. - "label[2,0;" .. fgettext("World name") .. "]".. - "field[4.5,0.4;6,0.5;te_world_name;;" .. minetest.formspec_escape(worldname) .. "]" .. + local mg_main_flags = function(mapgen, y) + if mapgen == "singlenode" then + return "", y + end + if disallowed_mapgen_settings["mg_flags"] then + return "", y + end - "label[2,1;" .. fgettext("Seed") .. "]".. - "field[4.5,1.4;6,0.5;te_seed;;".. current_seed .. "]" .. + local form = "checkbox[0," .. y .. ";flag_mg_caves;" .. + fgettext("Caves") .. ";"..strflag(flags.main, "caves").."]" + y = y + 0.5 - "label[2,2;" .. fgettext("Mapgen") .. "]".. - "dropdown[4.2,2;6.3;dd_mapgen;" .. mglist .. ";" .. selindex .. "]" .. + form = form .. "checkbox[0,"..y..";flag_mg_dungeons;" .. + fgettext("Dungeons") .. ";"..strflag(flags.main, "dungeons").."]" + y = y + 0.5 - "label[2,3;" .. fgettext("Game") .. "]".. - "textlist[4.2,3;5.8,2.3;games;" .. pkgmgr.gamelist() .. - ";" .. gameidx .. ";true]" .. + local d_name = fgettext("Decorations") + local d_tt + if mapgen == "v6" then + d_tt = fgettext("Structures appearing on the terrain (no effect on trees and jungle grass created by v6)") + else + d_tt = fgettext("Structures appearing on the terrain, typically trees and plants") + end + form = form .. "checkbox[0,"..y..";flag_mg_decorations;" .. + d_name .. ";" .. + strflag(flags.main, "decorations").."]" .. + "tooltip[flag_mg_decorations;" .. + d_tt .. + "]" + y = y + 0.5 + + form = form .. "tooltip[flag_mg_caves;" .. + fgettext("Network of tunnels and caves") + .. "]" + return form, y + end - "button[3.25,6;2.5,0.5;world_create_confirm;" .. fgettext("Create") .. "]" .. - "button[5.75,6;2.5,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]" + local mg_specific_flags = function(mapgen, y) + if not flag_checkboxes[mapgen] then + return "", y + end + if disallowed_mapgen_settings["mg"..mapgen.."_spflags"] then + return "", y + end + local form = "" + for _,tab in pairs(flag_checkboxes[mapgen]) do + local id = "flag_mg"..mapgen.."_"..tab[1] + form = form .. ("checkbox[0,%f;%s;%s;%s]"): + format(y, id, tab[2], strflag(flags[mapgen], tab[3])) + + if tab[4] then + form = form .. "tooltip["..id..";"..tab[4].."]" + end + y = y + 0.5 + end - if #pkgmgr.games == 0 then - retval = retval .. "box[2,4;8,1;#ff8800]label[2.25,4;" .. - fgettext("You have no games installed.") .. "]label[2.25,4.4;" .. - fgettext("Download one from minetest.net") .. "]" - elseif #pkgmgr.games == 1 and pkgmgr.games[1].id == "minimal" then - retval = retval .. "box[1.75,4;8.7,1;#ff8800]label[2,4;" .. - fgettext("Warning: The minimal development test is meant for developers.") .. "]label[2,4.4;" .. + if mapgen ~= "v6" then + -- No special treatment + return form, y + end + -- Special treatment for v6 (add biome widgets) + + -- Biome type (jungles, snowbiomes) + local biometype + if flags.v6.snowbiomes == true then + biometype = 1 + elseif flags.v6.jungles == true then + biometype = 2 + else + biometype = 3 + end + y = y + 0.3 + + form = form .. "label[0,"..(y+0.1)..";" .. fgettext("Biomes") .. "]" + y = y + 0.6 + + form = form .. "dropdown[0,"..y..";6.3;mgv6_biomes;" + for b=1, #mgv6_biomes do + form = form .. mgv6_biomes[b][1] + if b < #mgv6_biomes then + form = form .. "," + end + end + form = form .. ";" .. biometype.. "]" + + -- biomeblend + y = y + 0.55 + form = form .. "checkbox[0,"..y..";flag_mgv6_biomeblend;" .. + fgettext("Biome blending") .. ";"..strflag(flags.v6, "biomeblend").."]" .. + "tooltip[flag_mgv6_biomeblend;" .. + fgettext("Smooth transition between biomes") .. "]" + + return form, y + end + + current_seed = core.formspec_escape(current_seed) + + local y_start = 0.0 + local y = y_start + local str_flags, str_spflags + local label_flags, label_spflags = "", "" + y = y + 0.3 + str_flags, y = mg_main_flags(current_mg, y) + if str_flags ~= "" then + label_flags = "label[0,"..y_start..";" .. fgettext("Mapgen flags") .. "]" + y_start = y + 0.4 + else + y_start = 0.0 + end + y = y_start + 0.3 + str_spflags = mg_specific_flags(current_mg, y) + if str_spflags ~= "" then + label_spflags = "label[0,"..y_start..";" .. fgettext("Mapgen-specific flags") .. "]" + end + + -- Warning if only minimal is installed + local minimal_only = "" + local gamelist_height = 2.3 + if #pkgmgr.games == 1 and pkgmgr.games[1].id == "minimal" then + minimal_only = "box[0,0;5.8,1.7;#ff8800]" .. + "textarea[0.3,0;6,1.8;;;".. + fgettext("Warning: The minimal development test is meant for developers.") .. "\n" .. fgettext("Download a game, such as Minetest Game, from minetest.net") .. "]" + gamelist_height = 0.5 end + local retval = + "size[12.25,7,true]" .. + + -- Left side + "container[0,0]".. + "field[0.3,0.6;6,0.5;te_world_name;" .. + fgettext("World name") .. + ";" .. core.formspec_escape(worldname) .. "]" .. + + "field[0.3,1.7;6,0.5;te_seed;" .. + fgettext("Seed") .. + ";".. current_seed .. "]" .. + + "label[0,2;" .. fgettext("Mapgen") .. "]".. + "dropdown[0,2.5;6.3;dd_mapgen;" .. mglist .. ";" .. selindex .. "]" .. + + "label[0,3.35;" .. fgettext("Game") .. "]".. + "textlist[0,3.85;5.8,"..gamelist_height..";games;" .. + pkgmgr.gamelist() .. ";" .. gameidx .. ";false]" .. + "container[0,4.5]" .. + minimal_only .. + "container_end[]" .. + "container_end[]" .. + + -- Right side + "container[6.2,0]".. + label_flags .. str_flags .. + label_spflags .. str_spflags .. + "container_end[]".. + + -- Menu buttons + "button[3.25,6.5;3,0.5;world_create_confirm;" .. fgettext("Create") .. "]" .. + "button[6.25,6.5;3,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]" + return retval end @@ -163,11 +405,53 @@ local function create_world_buttonhandler(this, fields) return true end + for k,v in pairs(fields) do + local split = string.split(k, "_", nil, 3) + if split and split[1] == "flag" then + local setting + if split[2] == "mg" then + setting = "mg_flags" + else + setting = split[2].."_spflags" + end + -- We replaced the underscore of flag names with a dash. + local flag = string.gsub(split[3], "-", "_") + local ftable = core.settings:get_flags(setting) + if v == "true" then + ftable[flag] = true + else + ftable[flag] = false + end + local flags = table_to_flags(ftable) + core.settings:set(setting, flags) + return true + end + end + if fields["world_create_cancel"] then this:delete() return true end + if fields["mgv6_biomes"] then + local entry = minetest.formspec_escape(fields["mgv6_biomes"]) + for b=1, #mgv6_biomes do + if entry == mgv6_biomes[b][1] then + local ftable = core.settings:get_flags("mgv6_spflags") + ftable.jungles = mgv6_biomes[b][2].jungles + ftable.snowbiomes = mgv6_biomes[b][2].snowbiomes + local flags = table_to_flags(ftable) + core.settings:set("mgv6_spflags", flags) + return true + end + end + end + + if fields["dd_mapgen"] then + core.settings:set("mg_name", fields["dd_mapgen"]) + return true + end + return false end diff --git a/doc/lua_api.txt b/doc/lua_api.txt index db13f4224..9685e8307 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -75,6 +75,10 @@ The game directory can contain the following files: When both `allowed_mapgens` and `disallowed_mapgens` are specified, `allowed_mapgens` is applied before `disallowed_mapgens`. + * `disallowed_mapgen_settings= ` + e.g. `disallowed_mapgen_settings = mgv5_spflags` + These settings are hidden for this game in the world creation + dialog and game start menu. * `minetest.conf`: Used to set default settings when running this game. * `settingtypes.txt`: -- cgit v1.2.3 From 36d35f2fe31a429c1510df680801940472416d45 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 14 May 2020 21:16:45 +0200 Subject: CSM: Bugfixes to camera:get_pos() and camera:get_fov() closes #9857 --- clientmods/preview/init.lua | 2 +- doc/client_lua_api.txt | 2 +- src/client/camera.cpp | 2 +- src/script/lua_api/l_camera.cpp | 59 +++++++++++++++++++++++++---------------- src/script/lua_api/l_env.cpp | 16 +++++------ 5 files changed, 47 insertions(+), 34 deletions(-) (limited to 'doc') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index d2440369a..089955d2f 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -79,7 +79,7 @@ core.register_on_item_use(function(itemstack, pointed_thing) return false end - local pos = vector.add(core.localplayer:get_pos(), core.camera:get_offset()) + 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) diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index 53442d308..c9cd8ac93 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -967,7 +967,7 @@ Please do not try to access the reference until the camera is initialized, other * `get_camera_mode()` * Returns 0, 1, or 2 as described above * `get_fov()` - * Returns: + * Returns a table with X, Y, maximum and actual FOV in degrees: ```lua { diff --git a/src/client/camera.cpp b/src/client/camera.cpp index 1a5253db4..9b311171a 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -540,7 +540,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, f32 tool_r m_aspect = (f32) window_size.X / (f32) window_size.Y; m_fov_y = m_curr_fov_degrees * M_PI / 180.0; // Increase vertical FOV on lower aspect ratios (<16:10) - m_fov_y *= MYMAX(1.0, MYMIN(1.4, sqrt(16./10. / m_aspect))); + m_fov_y *= core::clamp(sqrt(16./10. / m_aspect), 1.0, 1.4); m_fov_x = 2 * atan(m_aspect * tan(0.5 * m_fov_y)); m_cameranode->setAspectRatio(m_aspect); m_cameranode->setFOV(m_fov_y); diff --git a/src/script/lua_api/l_camera.cpp b/src/script/lua_api/l_camera.cpp index 9c1470284..bfa60be67 100644 --- a/src/script/lua_api/l_camera.cpp +++ b/src/script/lua_api/l_camera.cpp @@ -51,6 +51,7 @@ void LuaCamera::create(lua_State *L, Camera *m) lua_setfield(L, objectstable, "camera"); } +// set_camera_mode(self, mode) int LuaCamera::l_set_camera_mode(lua_State *L) { Camera *camera = getobject(L, 1); @@ -67,17 +68,19 @@ int LuaCamera::l_set_camera_mode(lua_State *L) return 0; } +// get_camera_mode(self) int LuaCamera::l_get_camera_mode(lua_State *L) { Camera *camera = getobject(L, 1); if (!camera) return 0; - lua_pushnumber(L, (int)camera->getCameraMode()); + lua_pushinteger(L, (int)camera->getCameraMode()); return 1; } +// get_fov(self) int LuaCamera::l_get_fov(lua_State *L) { Camera *camera = getobject(L, 1); @@ -85,9 +88,9 @@ int LuaCamera::l_get_fov(lua_State *L) return 0; lua_newtable(L); - lua_pushnumber(L, camera->getFovX() * core::DEGTORAD); + lua_pushnumber(L, camera->getFovX() * core::RADTODEG); lua_setfield(L, -2, "x"); - lua_pushnumber(L, camera->getFovY() * core::DEGTORAD); + lua_pushnumber(L, camera->getFovY() * core::RADTODEG); lua_setfield(L, -2, "y"); lua_pushnumber(L, camera->getCameraNode()->getFOV() * core::RADTODEG); lua_setfield(L, -2, "actual"); @@ -96,16 +99,18 @@ int LuaCamera::l_get_fov(lua_State *L) return 1; } +// get_pos(self) int LuaCamera::l_get_pos(lua_State *L) { Camera *camera = getobject(L, 1); if (!camera) return 0; - push_v3f(L, camera->getPosition()); + push_v3f(L, camera->getPosition() / BS); return 1; } +// get_offset(self) int LuaCamera::l_get_offset(lua_State *L) { LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer(); @@ -115,38 +120,40 @@ int LuaCamera::l_get_offset(lua_State *L) return 1; } +// get_look_dir(self) int LuaCamera::l_get_look_dir(lua_State *L) { - LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer(); - sanity_check(player); - - float pitch = -1.0 * player->getPitch() * core::DEGTORAD; - float yaw = (player->getYaw() + 90.) * core::DEGTORAD; - v3f v(std::cos(pitch) * std::cos(yaw), std::sin(pitch), - std::cos(pitch) * std::sin(yaw)); + Camera *camera = getobject(L, 1); + if (!camera) + return 0; - push_v3f(L, v); + push_v3f(L, camera->getDirection()); return 1; } +// get_look_horizontal(self) +// FIXME: wouldn't localplayer be a better place for this? int LuaCamera::l_get_look_horizontal(lua_State *L) { LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer(); sanity_check(player); - lua_pushnumber(L, (player->getYaw() + 90.) * core::DEGTORAD); + lua_pushnumber(L, (player->getYaw() + 90.f) * core::DEGTORAD); return 1; } +// get_look_vertical(self) +// FIXME: wouldn't localplayer be a better place for this? int LuaCamera::l_get_look_vertical(lua_State *L) { LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer(); sanity_check(player); - lua_pushnumber(L, -1.0 * player->getPitch() * core::DEGTORAD); + lua_pushnumber(L, -1.0f * player->getPitch() * core::DEGTORAD); return 1; } +// get_aspect_ratio(self) int LuaCamera::l_get_aspect_ratio(lua_State *L) { Camera *camera = getobject(L, 1); @@ -215,13 +222,19 @@ void LuaCamera::Register(lua_State *L) lua_pop(L, 1); } +// clang-format off const char LuaCamera::className[] = "Camera"; -const luaL_Reg LuaCamera::methods[] = {luamethod(LuaCamera, set_camera_mode), - luamethod(LuaCamera, get_camera_mode), luamethod(LuaCamera, get_fov), - luamethod(LuaCamera, get_pos), luamethod(LuaCamera, get_offset), - luamethod(LuaCamera, get_look_dir), - luamethod(LuaCamera, get_look_vertical), - luamethod(LuaCamera, get_look_horizontal), - luamethod(LuaCamera, get_aspect_ratio), - - {0, 0}}; +const luaL_Reg LuaCamera::methods[] = { + luamethod(LuaCamera, set_camera_mode), + luamethod(LuaCamera, get_camera_mode), + luamethod(LuaCamera, get_fov), + luamethod(LuaCamera, get_pos), + luamethod(LuaCamera, get_offset), + luamethod(LuaCamera, get_look_dir), + luamethod(LuaCamera, get_look_vertical), + luamethod(LuaCamera, get_look_horizontal), + luamethod(LuaCamera, get_aspect_ratio), + + {0, 0} +}; +// clang-format on diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index cabca124d..b8a8a5ce1 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -780,8 +780,8 @@ int ModApiEnvMod::l_find_node_near(lua_State *L) #ifndef SERVER // Client API limitations - if (getClient(L)) - radius = getClient(L)->CSMClampRadius(pos, radius); + if (Client *client = getClient(L)) + radius = client->CSMClampRadius(pos, radius); #endif for (int d = start_radius; d <= radius; d++) { @@ -811,9 +811,9 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) const NodeDefManager *ndef = env->getGameDef()->ndef(); #ifndef SERVER - if (getClient(L)) { - minp = getClient(L)->CSMClampPos(minp); - maxp = getClient(L)->CSMClampPos(maxp); + if (Client *client = getClient(L)) { + minp = client->CSMClampPos(minp); + maxp = client->CSMClampPos(maxp); } #endif @@ -887,9 +887,9 @@ int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L) const NodeDefManager *ndef = env->getGameDef()->ndef(); #ifndef SERVER - if (getClient(L)) { - minp = getClient(L)->CSMClampPos(minp); - maxp = getClient(L)->CSMClampPos(maxp); + if (Client *client = getClient(L)) { + minp = client->CSMClampPos(minp); + maxp = client->CSMClampPos(maxp); } #endif -- cgit v1.2.3 From c1ce4be756e2554051a27f244303377c0a7d69a6 Mon Sep 17 00:00:00 2001 From: ANAND Date: Sun, 17 May 2020 01:12:31 +0530 Subject: Make automatic_rotate relative, allow setting rotation (#8468) automatic_rotate does not make sense if it is absolute. Make it relative. To avoid bouncing, set_rotation did not update the client when automatic_rotate was set. That's no longer necessary because the new spinning method applies the rotation on top of the current one, and the updates are necessary for set_rotation to actually transform the object. Co-authored-by: ANAND Co-authored-by: Pedro Gimeno --- doc/lua_api.txt | 1 + src/client/content_cao.cpp | 15 +++++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 9685e8307..07758c237 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6555,6 +6555,7 @@ Player properties need to be saved manually. automatic_rotate = 0, -- Set constant rotation in radians per second, positive or negative. + -- Object rotates along the local Y-axis, and works with set_rotation. -- Set to 0 to disable constant rotation. stepheight = 0, diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index eb1dad22b..867bbf2c8 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -1077,10 +1077,13 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) updateTextures(m_previous_texture_modifier); } } + if (!getParent() && std::fabs(m_prop.automatic_rotate) > 0.001) { - m_rotation.Y += dtime * m_prop.automatic_rotate * 180 / M_PI; - rot_translator.val_current = m_rotation; - updateNodePos(); + // This is the child node's rotation. It is only used for automatic_rotate. + v3f local_rot = node->getRotation(); + local_rot.Y = modulo360f(local_rot.Y - dtime * core::RADTODEG * + m_prop.automatic_rotate); + node->setRotation(local_rot); } if (!getParent() && m_prop.automatic_face_movement_dir && @@ -1501,11 +1504,7 @@ void GenericCAO::processMessage(const std::string &data) m_position = readV3F32(is); m_velocity = readV3F32(is); m_acceleration = readV3F32(is); - - if (std::fabs(m_prop.automatic_rotate) < 0.001f) - m_rotation = readV3F32(is); - else - readV3F32(is); + m_rotation = readV3F32(is); m_rotation = wrapDegrees_0_360_v3f(m_rotation); bool do_interpolate = readU8(is); -- cgit v1.2.3 From a9c3a423231e26ea3edee51d5f0bf949ca8e529b Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Sun, 17 May 2020 19:09:10 +0100 Subject: Add core.open_url() to main menu API (#8592) --- .../java/net/minetest/minetest/GameActivity.java | 6 ++ builtin/mainmenu/dlg_contentstore.lua | 113 ++++----------------- builtin/mainmenu/tab_credits.lua | 11 +- doc/menu_lua_api.txt | 5 + src/porting.cpp | 30 +++++- src/porting.h | 3 + src/porting_android.cpp | 12 +++ src/porting_android.h | 2 + src/script/lua_api/l_mainmenu.cpp | 9 ++ src/script/lua_api/l_mainmenu.h | 3 + 10 files changed, 98 insertions(+), 96 deletions(-) (limited to 'doc') diff --git a/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java b/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java index 02b61b598..635512569 100644 --- a/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java +++ b/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java @@ -22,6 +22,7 @@ package net.minetest.minetest; import android.app.NativeActivity; import android.content.Intent; +import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.view.View; @@ -117,4 +118,9 @@ public class GameActivity extends NativeActivity { public int getDisplayWidth() { return getResources().getDisplayMetrics().widthPixels; } + + public void openURL(String url) { + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + startActivity(browserIntent); + } } diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index 3bc5f60bb..ce5c061c6 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -16,7 +16,6 @@ --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. local store = { packages = {}, packages_full = {} } -local package_dialog = {} -- Screenshot local screenshot_dir = core.get_cache_path() .. DIR_DELIM .. "cdb" @@ -44,8 +43,6 @@ local filter_types_type = { } - - local function download_package(param) if core.download_file(param.package.url, param.filename) then return { @@ -195,74 +192,6 @@ local function get_screenshot(package) return defaulttexturedir .. "loading_screenshot.png" end - - -function package_dialog.get_formspec() - local package = package_dialog.package - - store.update_paths() - - local formspec = { - "size[9,4;true]", - "image[0,1;4.5,3;", core.formspec_escape(get_screenshot(package)), ']', - "label[3.8,1;", - minetest.colorize(mt_color_green, core.formspec_escape(package.title)), "\n", - minetest.colorize('#BFBFBF', "by " .. core.formspec_escape(package.author)), "]", - "textarea[4,2;5.3,2;;;", core.formspec_escape(package.short_description), "]", - "button[0,0;2,1;back;", fgettext("Back"), "]", - } - - if not package.path then - formspec[#formspec + 1] = "button[7,0;2,1;install;" - formspec[#formspec + 1] = fgettext("Install") - formspec[#formspec + 1] = "]" - elseif package.installed_release < package.release then - -- The install_ action also handles updating - formspec[#formspec + 1] = "button[7,0;2,1;install;" - formspec[#formspec + 1] = fgettext("Update") - formspec[#formspec + 1] = "]" - formspec[#formspec + 1] = "button[5,0;2,1;uninstall;" - formspec[#formspec + 1] = fgettext("Uninstall") - formspec[#formspec + 1] = "]" - else - formspec[#formspec + 1] = "button[7,0;2,1;uninstall;" - formspec[#formspec + 1] = fgettext("Uninstall") - formspec[#formspec + 1] = "]" - end - - return table.concat(formspec, "") -end - -function package_dialog.handle_submit(this, fields) - if fields.back then - this:delete() - return true - end - - if fields.install then - start_install(this, package_dialog.package) - return true - end - - if fields.uninstall then - local dlg_delmod = create_delete_content_dlg(package_dialog.package) - dlg_delmod:set_parent(this) - this:hide() - dlg_delmod:show() - return true - end - - return false -end - -function package_dialog.create(package) - package_dialog.package = package - return dialog_create("package_view", - package_dialog.get_formspec, - package_dialog.handle_submit, - nil) -end - function store.load() local tmpdir = os.tempfolder() local target = tmpdir .. DIR_DELIM .. "packages.json" @@ -462,44 +391,45 @@ function store.get_formspec(dlgdata) minetest.colorize("#BFBFBF", " by " .. package.author)) formspec[#formspec + 1] = "]" - -- description - if package.path and package.installed_release < package.release then - formspec[#formspec + 1] = "textarea[1.25,0.3;7.5,1;;;" - else - formspec[#formspec + 1] = "textarea[1.25,0.3;9,1;;;" - end - formspec[#formspec + 1] = core.formspec_escape(package.short_description) - formspec[#formspec + 1] = "]" - -- buttons + local description_width = 7.5 if not package.path then - formspec[#formspec + 1] = "button[9.9,0;1.5,1;install_" + formspec[#formspec + 1] = "button[8.4,0;1.5,1;install_" formspec[#formspec + 1] = tostring(i) formspec[#formspec + 1] = ";" formspec[#formspec + 1] = fgettext("Install") formspec[#formspec + 1] = "]" else if package.installed_release < package.release then + description_width = 6 + -- The install_ action also handles updating - formspec[#formspec + 1] = "button[8.4,0;1.5,1;install_" + formspec[#formspec + 1] = "button[6.9,0;1.5,1;install_" formspec[#formspec + 1] = tostring(i) formspec[#formspec + 1] = ";" formspec[#formspec + 1] = fgettext("Update") formspec[#formspec + 1] = "]" end - formspec[#formspec + 1] = "button[9.9,0;1.5,1;uninstall_" + formspec[#formspec + 1] = "button[8.4,0;1.5,1;uninstall_" formspec[#formspec + 1] = tostring(i) formspec[#formspec + 1] = ";" formspec[#formspec + 1] = fgettext("Uninstall") formspec[#formspec + 1] = "]" end - --formspec[#formspec + 1] = "button[9.9,0;1.5,1;view_" - --formspec[#formspec + 1] = tostring(i) - --formspec[#formspec + 1] = ";" - --formspec[#formspec + 1] = fgettext("View") - --formspec[#formspec + 1] = "]" + formspec[#formspec + 1] = "button[9.9,0;1.5,1;view_" + formspec[#formspec + 1] = tostring(i) + formspec[#formspec + 1] = ";" + formspec[#formspec + 1] = fgettext("View") + formspec[#formspec + 1] = "]" + + -- description + formspec[#formspec + 1] = "textarea[1.25,0.3;" + formspec[#formspec + 1] = tostring(description_width) + formspec[#formspec + 1] = ",1;;;" + formspec[#formspec + 1] = core.formspec_escape(package.short_description) + formspec[#formspec + 1] = "]" formspec[#formspec + 1] = "container_end[]" end @@ -576,10 +506,9 @@ function store.handle_submit(this, fields) end if fields["view_" .. i] then - local dlg = package_dialog.create(package) - dlg:set_parent(this) - this:hide() - dlg:show() + local url = ("%s/packages/%s?protocol_version=%d"):format( + core.settings:get("contentdb_url"), package.id, core.get_max_supp_proto()) + core.open_url(url) return true end end diff --git a/builtin/mainmenu/tab_credits.lua b/builtin/mainmenu/tab_credits.lua index 962d2a3b4..c2b7e503a 100644 --- a/builtin/mainmenu/tab_credits.lua +++ b/builtin/mainmenu/tab_credits.lua @@ -101,8 +101,8 @@ return { local logofile = defaulttexturedir .. "logo.png" local version = core.get_version() return "image[0.5,1;" .. core.formspec_escape(logofile) .. "]" .. - "label[0.5,3.2;" .. version.project .. " " .. version.string .. "]" .. - "label[0.5,3.5;http://minetest.net]" .. + "label[0.5,2.8;" .. version.project .. " " .. version.string .. "]" .. + "button[0.5,3;2,2;homepage;minetest.net]" .. "tablecolumns[color;text]" .. "tableoptions[background=#00000000;highlight=#00000000;border=false]" .. "table[3.5,-0.25;8.5,6.05;list_credits;" .. @@ -115,5 +115,10 @@ return { "#FFFF00," .. fgettext("Previous Contributors") .. ",," .. buildCreditList(previous_contributors) .. "," .. ";1]" - end + end, + cbf_button_handler = function(this, fields, name, tabdata) + if fields.homepage then + core.open_url("https://www.minetest.net") + end + end, } diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index 8f5460acb..485c50110 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -234,6 +234,11 @@ core.get_min_supp_proto() core.get_max_supp_proto() ^ returns the maximum supported network protocol version +Other: +core.open_url(url) +^ opens the URL in a web browser, returns false on failure. +^ Must begin with http:// or https:// + Async: core.handle_async(async_job,parameters,finished) ^ execute a function asynchronously diff --git a/src/porting.cpp b/src/porting.cpp index c0381ad06..ef1640467 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -33,22 +33,28 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include + #include #endif #if !defined(_WIN32) #include #include + #if !defined(__ANDROID__) + #include + #endif #endif #if defined(__hpux) #define _PSTAT64 #include #endif +#if defined(__ANDROID__) + #include "porting_android.h" +#endif #include "config.h" #include "debug.h" #include "filesys.h" #include "log.h" #include "util/string.h" -#include "settings.h" #include #include #include @@ -697,6 +703,28 @@ int mt_snprintf(char *buf, const size_t buf_size, const char *fmt, ...) return c; } +bool openURL(const std::string &url) +{ + if ((url.substr(0, 7) != "http://" && url.substr(0, 8) != "https://") || + url.find_first_of("\r\n") != std::string::npos) { + errorstream << "Invalid url: " << url << std::endl; + return false; + } + +#if defined(_WIN32) + return (intptr_t)ShellExecuteA(NULL, NULL, url.c_str(), NULL, NULL, SW_SHOWNORMAL) > 32; +#elif defined(__ANDROID__) + openURLAndroid(url); + return true; +#elif defined(__APPLE__) + const char *argv[] = {"open", url.c_str(), NULL}; + return posix_spawnp(NULL, "open", NULL, NULL, (char**)argv, environ) == 0; +#else + const char *argv[] = {"xdg-open", url.c_str(), NULL}; + return posix_spawnp(NULL, "xdg-open", NULL, NULL, (char**)argv, environ) == 0; +#endif +} + // Load performance counter frequency only once at startup #ifdef _WIN32 diff --git a/src/porting.h b/src/porting.h index 4d30a5970..f50f0a950 100644 --- a/src/porting.h +++ b/src/porting.h @@ -329,6 +329,9 @@ bool secure_rand_fill_buf(void *buf, size_t len); void attachOrCreateConsole(); int mt_snprintf(char *buf, const size_t buf_size, const char *fmt, ...); + +bool openURL(const std::string &url); + } // namespace porting #ifdef __ANDROID__ diff --git a/src/porting_android.cpp b/src/porting_android.cpp index 2c91df235..41b521ec2 100644 --- a/src/porting_android.cpp +++ b/src/porting_android.cpp @@ -213,6 +213,18 @@ void showInputDialog(const std::string &acceptButton, const std::string &hint, jacceptButton, jhint, jcurrent, jeditType); } +void openURLAndroid(const std::string &url) +{ + jmethodID url_open = jnienv->GetMethodID(nativeActivity, "openURL", + "(Ljava/lang/String;)V"); + + FATAL_ERROR_IF(url_open == nullptr, + "porting::openURLAndroid unable to find java openURL method"); + + jstring jurl = jnienv->NewStringUTF(url.c_str()); + jnienv->CallVoidMethod(app_global->activity->clazz, url_open, jurl); +} + int getInputDialogState() { jmethodID dialogstate = jnienv->GetMethodID(nativeActivity, diff --git a/src/porting_android.h b/src/porting_android.h index 42f90b60b..6eb054041 100644 --- a/src/porting_android.h +++ b/src/porting_android.h @@ -58,6 +58,8 @@ void initializePathsAndroid(); void showInputDialog(const std::string &acceptButton, const std::string &hint, const std::string ¤t, int editType); +void openURLAndroid(const std::string &url); + /** * WORKAROUND for not working callbacks from java -> c++ * get current state of input dialog diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index a76e9f079..f32c477c2 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -1063,6 +1063,14 @@ int ModApiMainMenu::l_get_max_supp_proto(lua_State *L) return 1; } +/******************************************************************************/ +int ModApiMainMenu::l_open_url(lua_State *L) +{ + std::string url = luaL_checkstring(L, 1); + lua_pushboolean(L, porting::openURL(url)); + return 1; +} + /******************************************************************************/ int ModApiMainMenu::l_do_async_callback(lua_State *L) { @@ -1125,6 +1133,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top) API_FCT(get_screen_info); API_FCT(get_min_supp_proto); API_FCT(get_max_supp_proto); + API_FCT(open_url); API_FCT(do_async_callback); } diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h index b2ca49320..5a16b3bfe 100644 --- a/src/script/lua_api/l_mainmenu.h +++ b/src/script/lua_api/l_mainmenu.h @@ -145,6 +145,9 @@ private: static int l_get_max_supp_proto(lua_State *L); + // other + static int l_open_url(lua_State *L); + // async static int l_do_async_callback(lua_State *L); -- cgit v1.2.3 From 7d3972a5049324f776ab008894c34569641f0073 Mon Sep 17 00:00:00 2001 From: LoneWolfHT Date: Tue, 19 May 2020 10:10:39 -0700 Subject: Add ability to scale HUD text (#9814) Add 'size' property to HUD text elements that is used for relative font size calculations. --- doc/lua_api.txt | 2 ++ src/client/hud.cpp | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 07758c237..9c7c42436 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1356,6 +1356,8 @@ Displays text on the HUD. text. Specify `0xFFFFFF` for white text, `0xFF0000` for red, and so on. * `alignment`: The alignment of the text. * `offset`: offset in pixels from position. +* `size`: size of the text. + The player-set font size is multiplied by size.x (y value isn't used). ### `statbar` diff --git a/src/client/hud.cpp b/src/client/hud.cpp index f8f712762..4edc229b2 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -319,16 +319,21 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) floor(e->pos.Y * (float) m_screensize.Y + 0.5)); switch (e->type) { case HUD_ELEM_TEXT: { + irr::gui::IGUIFont *textfont = font; + if (e->size.X > 0) + textfont = g_fontengine->getFont( + e->size.X * g_fontengine->getDefaultFontSize()); + video::SColor color(255, (e->number >> 16) & 0xFF, (e->number >> 8) & 0xFF, (e->number >> 0) & 0xFF); core::rect size(0, 0, e->scale.X, text_height * e->scale.Y); std::wstring text = unescape_translate(utf8_to_wide(e->text)); - core::dimension2d textsize = font->getDimension(text.c_str()); + core::dimension2d textsize = textfont->getDimension(text.c_str()); v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2), (e->align.Y - 1.0) * (textsize.Height / 2)); v2s32 offs(e->offset.X, e->offset.Y); - font->draw(text.c_str(), size + pos + offset + offs, color); + textfont->draw(text.c_str(), size + pos + offset + offs, color); break; } case HUD_ELEM_STATBAR: { v2s32 offs(e->offset.X, e->offset.Y); -- cgit v1.2.3 From c94d37827dd3a8be9dcc59bb693032ba7ea07922 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 19 May 2020 21:08:37 +0200 Subject: Rework functionality of leveled nodes (#9852) Co-authored-by: sfan5 Co-authored-by: SmallJoker --- builtin/game/falling.lua | 58 ++++++++++++++++++++++++++++++----------- doc/lua_api.txt | 10 ++++--- src/mapnode.cpp | 21 ++++++++------- src/mapnode.h | 6 ++--- src/nodedef.cpp | 6 +++++ src/nodedef.h | 4 ++- src/script/common/c_content.cpp | 4 +++ src/script/lua_api/l_env.cpp | 4 +-- 8 files changed, 79 insertions(+), 34 deletions(-) (limited to 'doc') diff --git a/builtin/game/falling.lua b/builtin/game/falling.lua index 7037ae885..cdbb13acc 100644 --- a/builtin/game/falling.lua +++ b/builtin/game/falling.lua @@ -109,6 +109,7 @@ core.register_entity(":__builtin:falling_node", { if core.is_colored_paramtype(def.paramtype2) then itemstring = core.itemstring_with_palette(itemstring, node.param2) end + -- FIXME: solution needed for paramtype2 == "leveled" local vsize if def.visual_scale then local s = def.visual_scale * SCALE @@ -122,6 +123,24 @@ core.register_entity(":__builtin:falling_node", { }) end + -- Set collision box (certain nodeboxes only for now) + local nb_types = {fixed=true, leveled=true, connected=true} + if def.drawtype == "nodebox" and def.node_box and + nb_types[def.node_box.type] then + local box = table.copy(def.node_box.fixed) + if type(box[1]) == "table" then + box = #box == 1 and box[1] or nil -- We can only use a single box + end + if box then + if def.paramtype2 == "leveled" and (self.node.level or 0) > 0 then + box[5] = -0.5 + self.node.level / 64 + end + self.object:set_properties({ + collisionbox = box + }) + end + end + -- Rotate entity if def.drawtype == "torchlike" then self.object:set_yaw(math.pi*0.25) @@ -196,13 +215,16 @@ core.register_entity(":__builtin:falling_node", { try_place = function(self, bcp, bcn) local bcd = core.registered_nodes[bcn.name] -- Add levels if dropped on same leveled node - if bcd and bcd.leveled and + if bcd and bcd.paramtype2 == "leveled" and bcn.name == self.node.name then local addlevel = self.node.level - if not addlevel or addlevel <= 0 then + if (addlevel or 0) <= 0 then addlevel = bcd.leveled end - if core.add_node_level(bcp, addlevel) == 0 then + if core.add_node_level(bcp, addlevel) < addlevel then + return true + elseif bcd.buildable_to then + -- Node level has already reached max, don't place anything return true end end @@ -351,6 +373,7 @@ local function convert_to_falling_node(pos, node) if not obj then return false end + -- remember node level, the entities' set_node() uses this node.level = core.get_node_level(pos) local meta = core.get_meta(pos) local metatable = meta and meta:to_table() or {} @@ -436,18 +459,23 @@ function core.check_single_for_falling(p) -- Only spawn falling node if node below is loaded local n_bottom = core.get_node_or_nil(p_bottom) local d_bottom = n_bottom and core.registered_nodes[n_bottom.name] - if d_bottom and - - (core.get_item_group(n.name, "float") == 0 or - d_bottom.liquidtype == "none") and - - (n.name ~= n_bottom.name or (d_bottom.leveled and - core.get_node_level(p_bottom) < - core.get_node_max_level(p_bottom))) and - - (not d_bottom.walkable or d_bottom.buildable_to) then - convert_to_falling_node(p, n) - return true + if d_bottom then + local same = n.name == n_bottom.name + -- Let leveled nodes fall if it can merge with the bottom node + if same and d_bottom.paramtype2 == "leveled" and + core.get_node_level(p_bottom) < + core.get_node_max_level(p_bottom) then + convert_to_falling_node(p, n) + return true + end + -- Otherwise only if the bottom node is considered "fall through" + if not same and + (not d_bottom.walkable or d_bottom.buildable_to) and + (core.get_item_group(n.name, "float") == 0 or + d_bottom.liquidtype == "none") then + convert_to_falling_node(p, n) + return true + end end end diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 9c7c42436..8b7c412ab 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4882,7 +4882,7 @@ Environment access * `minetest.add_node_level(pos, level)` * increase level of leveled node by level, default `level` equals `1` * if `totallevel > maxlevel`, returns rest (`total-max`) - * can be negative for decreasing + * `level` must be between -127 and 127 * `minetest.fix_light(pos1, pos2)`: returns `true`/`false` * resets the light in a cuboid-shaped part of the map and removes lighting bugs. @@ -7012,11 +7012,15 @@ Used by `minetest.register_node`. -- If true, a new liquid source can be created by placing two or more -- sources nearby - leveled = 16, + leveled = 0, -- Only valid for "nodebox" drawtype with 'type = "leveled"'. -- Allows defining the nodebox height without using param2. -- The nodebox height is 'leveled' / 64 nodes. - -- The maximum value of 'leveled' is 127. + -- The maximum value of 'leveled' is `leveled_max`. + + leveled_max = 127, + -- Maximum value for `leveled` (0-127), enforced in + -- `minetest.set_node_level` and `minetest.add_node_level`. liquid_range = 8, -- Number of flowing nodes around source (max. 8) diff --git a/src/mapnode.cpp b/src/mapnode.cpp index bf7e79a71..24d62b504 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -584,7 +584,7 @@ u8 MapNode::getMaxLevel(const NodeDefManager *nodemgr) const if( f.liquid_type == LIQUID_FLOWING || f.param_type_2 == CPT2_FLOWINGLIQUID) return LIQUID_LEVEL_MAX; if(f.leveled || f.param_type_2 == CPT2_LEVELED) - return LEVELED_MAX; + return f.leveled_max; return 0; } @@ -603,14 +603,15 @@ u8 MapNode::getLevel(const NodeDefManager *nodemgr) const if (level) return level; } - if (f.leveled > LEVELED_MAX) - return LEVELED_MAX; + // Return static value from nodedef if param2 isn't used for level + if (f.leveled > f.leveled_max) + return f.leveled_max; return f.leveled; } -u8 MapNode::setLevel(const NodeDefManager *nodemgr, s8 level) +s8 MapNode::setLevel(const NodeDefManager *nodemgr, s16 level) { - u8 rest = 0; + s8 rest = 0; const ContentFeatures &f = nodemgr->get(*this); if (f.param_type_2 == CPT2_FLOWINGLIQUID || f.liquid_type == LIQUID_FLOWING @@ -631,18 +632,18 @@ u8 MapNode::setLevel(const NodeDefManager *nodemgr, s8 level) if (level < 0) { // zero means default for a leveled nodebox rest = level; level = 0; - } else if (level > LEVELED_MAX) { - rest = level - LEVELED_MAX; - level = LEVELED_MAX; + } else if (level > f.leveled_max) { + rest = level - f.leveled_max; + level = f.leveled_max; } setParam2((level & LEVELED_MASK) | (getParam2() & ~LEVELED_MASK)); } return rest; } -u8 MapNode::addLevel(const NodeDefManager *nodemgr, s8 add) +s8 MapNode::addLevel(const NodeDefManager *nodemgr, s16 add) { - s8 level = getLevel(nodemgr); + s16 level = getLevel(nodemgr); level += add; return setLevel(nodemgr, level); } diff --git a/src/mapnode.h b/src/mapnode.h index 7a3d30ddc..32ac1b4f6 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -268,12 +268,12 @@ struct MapNode std::vector *boxes, u8 neighbors = 0) const; /* - Liquid helpers + Liquid/leveled helpers */ u8 getMaxLevel(const NodeDefManager *nodemgr) const; u8 getLevel(const NodeDefManager *nodemgr) const; - u8 setLevel(const NodeDefManager *nodemgr, s8 level = 1); - u8 addLevel(const NodeDefManager *nodemgr, s8 add = 1); + s8 setLevel(const NodeDefManager *nodemgr, s16 level = 1); + s8 addLevel(const NodeDefManager *nodemgr, s16 add = 1); /* Serialization functions diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 65199830f..b8211fceb 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -368,6 +368,7 @@ void ContentFeatures::reset() floodable = false; rightclickable = true; leveled = 0; + leveled_max = LEVELED_MAX; liquid_type = LIQUID_NONE; liquid_alternative_flowing = ""; liquid_alternative_source = ""; @@ -478,6 +479,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const writeU8(os, legacy_wallmounted); os << serializeString(node_dig_prediction); + writeU8(os, leveled_max); } void ContentFeatures::correctAlpha(TileDef *tiles, int length) @@ -586,6 +588,10 @@ void ContentFeatures::deSerialize(std::istream &is) try { node_dig_prediction = deSerializeString(is); + u8 tmp_leveled_max = readU8(is); + if (is.eof()) /* readU8 doesn't throw exceptions so we have to do this */ + throw SerializationError(""); + leveled_max = tmp_leveled_max; } catch(SerializationError &e) {}; } diff --git a/src/nodedef.h b/src/nodedef.h index 0fce6eab1..497e7ee0e 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -326,8 +326,10 @@ struct ContentFeatures std::vector connects_to_ids; // Post effect color, drawn when the camera is inside the node. video::SColor post_effect_color; - // Flowing liquid or snow, value = default level + // Flowing liquid or leveled nodebox, value = default level u8 leveled; + // Maximum value for leveled nodes + u8 leveled_max; // --- LIGHTING-RELATED --- diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index de9634c42..116a59c09 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -694,6 +694,8 @@ ContentFeatures read_content_features(lua_State *L, int index) f.liquid_range = getintfield_default(L, index, "liquid_range", f.liquid_range); f.leveled = getintfield_default(L, index, "leveled", f.leveled); + f.leveled_max = getintfield_default(L, index, + "leveled_max", f.leveled_max); getboolfield(L, index, "liquid_renewable", f.liquid_renewable); f.drowning = getintfield_default(L, index, @@ -860,6 +862,8 @@ void push_content_features(lua_State *L, const ContentFeatures &c) lua_setfield(L, -2, "post_effect_color"); lua_pushnumber(L, c.leveled); lua_setfield(L, -2, "leveled"); + lua_pushnumber(L, c.leveled_max); + lua_setfield(L, -2, "leveled_max"); lua_pushboolean(L, c.sunlight_propagates); lua_setfield(L, -2, "sunlight_propagates"); lua_pushnumber(L, c.light_source); diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index b8a8a5ce1..89ec9dc7e 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -529,13 +529,13 @@ int ModApiEnvMod::l_set_node_level(lua_State *L) // add_node_level(pos, level) // pos = {x=num, y=num, z=num} -// level: 0..63 +// level: -127..127 int ModApiEnvMod::l_add_node_level(lua_State *L) { GET_ENV_PTR; v3s16 pos = read_v3s16(L, 1); - u8 level = 1; + s16 level = 1; if(lua_isnumber(L, 2)) level = lua_tonumber(L, 2); MapNode n = env->getMap().getNode(pos); -- cgit v1.2.3 From 42fcfb75e85523a2fa5d99a453c2fabc2c04c0f6 Mon Sep 17 00:00:00 2001 From: Paramat Date: Wed, 20 May 2020 22:16:14 +0100 Subject: Allow more than 255 biomes, document new maximum (#9855) Change biomemap data type from u8 to u16. New technical (not practical) maximum is 65535 biomes. --- doc/lua_api.txt | 4 ++++ src/mapgen/cavegen.cpp | 8 ++++---- src/mapgen/cavegen.h | 8 +++++--- src/mapgen/mapgen.h | 8 ++++---- src/mapgen/mg_biome.h | 6 +++--- src/mapgen/mg_decoration.cpp | 6 ++---- src/mapgen/mg_decoration.h | 4 +++- src/mapgen/mg_ore.cpp | 28 ++++++++++++++-------------- src/mapgen/mg_ore.h | 22 ++++++++++++---------- src/script/lua_api/l_mapgen.cpp | 4 ++-- src/script/lua_api/l_mapgen.h | 2 ++ 11 files changed, 55 insertions(+), 45 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 8b7c412ab..0101bd4cf 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -7443,6 +7443,10 @@ Biome definition Used by `minetest.register_biome`. +The maximum number of biomes that can be used is 65535. However, using an +excessive number of biomes will slow down map generation. Depending on desired +performance and computing power the practical limit is much lower. + { name = "tundra", diff --git a/src/mapgen/cavegen.cpp b/src/mapgen/cavegen.cpp index a9df4506f..340079821 100644 --- a/src/mapgen/cavegen.cpp +++ b/src/mapgen/cavegen.cpp @@ -1,8 +1,8 @@ /* Minetest -Copyright (C) 2010-2018 celeron55, Perttu Ahola -Copyright (C) 2010-2018 kwolekr, Ryan Kwolek -Copyright (C) 2015-2018 paramat +Copyright (C) 2010-2020 celeron55, Perttu Ahola +Copyright (C) 2015-2020 paramat +Copyright (C) 2010-2016 kwolekr, Ryan Kwolek 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 @@ -69,7 +69,7 @@ CavesNoiseIntersection::~CavesNoiseIntersection() void CavesNoiseIntersection::generateCaves(MMVManip *vm, - v3s16 nmin, v3s16 nmax, u8 *biomemap) + v3s16 nmin, v3s16 nmax, biome_t *biomemap) { assert(vm); assert(biomemap); diff --git a/src/mapgen/cavegen.h b/src/mapgen/cavegen.h index ff09f9423..d678d365b 100644 --- a/src/mapgen/cavegen.h +++ b/src/mapgen/cavegen.h @@ -1,7 +1,7 @@ /* Minetest -Copyright (C) 2010-2018 kwolekr, Ryan Kwolek -Copyright (C) 2015-2018 paramat +Copyright (C) 2015-2020 paramat +Copyright (C) 2010-2016 kwolekr, Ryan Kwolek 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 @@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #define VMANIP_FLAG_CAVE VOXELFLAG_CHECKED1 +typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include + class GenerateNotifier; /* @@ -44,7 +46,7 @@ public: NoiseParams *np_cave2, s32 seed, float cave_width); ~CavesNoiseIntersection(); - void generateCaves(MMVManip *vm, v3s16 nmin, v3s16 nmax, u8 *biomemap); + void generateCaves(MMVManip *vm, v3s16 nmin, v3s16 nmax, biome_t *biomemap); private: const NodeDefManager *m_ndef; diff --git a/src/mapgen/mapgen.h b/src/mapgen/mapgen.h index 7845c5349..a92b3b0d0 100644 --- a/src/mapgen/mapgen.h +++ b/src/mapgen/mapgen.h @@ -1,8 +1,8 @@ /* Minetest -Copyright (C) 2010-2018 celeron55, Perttu Ahola -Copyright (C) 2013-2018 kwolekr, Ryan Kwolek -Copyright (C) 2015-2018 paramat +Copyright (C) 2010-2020 celeron55, Perttu Ahola +Copyright (C) 2015-2020 paramat +Copyright (C) 2013-2016 kwolekr, Ryan Kwolek 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 @@ -38,7 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MG_DECORATIONS 0x20 #define MG_BIOMES 0x40 -typedef u8 biome_t; // copy from mg_biome.h to avoid an unnecessary include +typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include class Settings; class MMVManip; diff --git a/src/mapgen/mg_biome.h b/src/mapgen/mg_biome.h index 57f4aa20d..be4cfea4d 100644 --- a/src/mapgen/mg_biome.h +++ b/src/mapgen/mg_biome.h @@ -1,7 +1,7 @@ /* Minetest -Copyright (C) 2014-2018 kwolekr, Ryan Kwolek -Copyright (C) 2014-2018 paramat +Copyright (C) 2014-2020 paramat +Copyright (C) 2014-2016 kwolekr, Ryan Kwolek 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 @@ -32,7 +32,7 @@ class BiomeManager; //// Biome //// -typedef u8 biome_t; +typedef u16 biome_t; #define BIOME_NONE ((biome_t)0) diff --git a/src/mapgen/mg_decoration.cpp b/src/mapgen/mg_decoration.cpp index a9b67d239..a4cada396 100644 --- a/src/mapgen/mg_decoration.cpp +++ b/src/mapgen/mg_decoration.cpp @@ -206,8 +206,7 @@ size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) // All-surfaces decorations // Check biome of column if (mg->biomemap && !biomes.empty()) { - std::unordered_set::const_iterator iter = - biomes.find(mg->biomemap[mapindex]); + auto iter = biomes.find(mg->biomemap[mapindex]); if (iter == biomes.end()) continue; } @@ -259,8 +258,7 @@ size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) continue; if (mg->biomemap && !biomes.empty()) { - std::unordered_set::const_iterator iter = - biomes.find(mg->biomemap[mapindex]); + auto iter = biomes.find(mg->biomemap[mapindex]); if (iter == biomes.end()) continue; } diff --git a/src/mapgen/mg_decoration.h b/src/mapgen/mg_decoration.h index 1f9eb4510..1ea02a527 100644 --- a/src/mapgen/mg_decoration.h +++ b/src/mapgen/mg_decoration.h @@ -25,6 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "noise.h" #include "nodedef.h" +typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include + class Mapgen; class MMVManip; class PcgRandom; @@ -72,7 +74,7 @@ public: s16 nspawnby; s16 place_offset_y = 0; - std::unordered_set biomes; + std::unordered_set biomes; protected: void cloneTo(Decoration *def) const; diff --git a/src/mapgen/mg_ore.cpp b/src/mapgen/mg_ore.cpp index db647f82b..b50ed6a32 100644 --- a/src/mapgen/mg_ore.cpp +++ b/src/mapgen/mg_ore.cpp @@ -1,7 +1,7 @@ /* Minetest -Copyright (C) 2014-2018 kwolekr, Ryan Kwolek -Copyright (C) 2015-2018 paramat +Copyright (C) 2015-2020 paramat +Copyright (C) 2014-2016 kwolekr, Ryan Kwolek 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 @@ -146,7 +146,7 @@ ObjDef *OreScatter::clone() const void OreScatter::generate(MMVManip *vm, int mapseed, u32 blockseed, - v3s16 nmin, v3s16 nmax, u8 *biomemap) + v3s16 nmin, v3s16 nmax, biome_t *biomemap) { PcgRandom pr(blockseed); MapNode n_ore(c_ore, 0, ore_param2); @@ -170,7 +170,7 @@ void OreScatter::generate(MMVManip *vm, int mapseed, u32 blockseed, if (biomemap && !biomes.empty()) { u32 index = sizex * (z0 - nmin.Z) + (x0 - nmin.X); - std::unordered_set::const_iterator it = biomes.find(biomemap[index]); + auto it = biomes.find(biomemap[index]); if (it == biomes.end()) continue; } @@ -208,7 +208,7 @@ ObjDef *OreSheet::clone() const void OreSheet::generate(MMVManip *vm, int mapseed, u32 blockseed, - v3s16 nmin, v3s16 nmax, u8 *biomemap) + v3s16 nmin, v3s16 nmax, biome_t *biomemap) { PcgRandom pr(blockseed + 4234); MapNode n_ore(c_ore, 0, ore_param2); @@ -237,7 +237,7 @@ void OreSheet::generate(MMVManip *vm, int mapseed, u32 blockseed, continue; if (biomemap && !biomes.empty()) { - std::unordered_set::const_iterator it = biomes.find(biomemap[index]); + auto it = biomes.find(biomemap[index]); if (it == biomes.end()) continue; } @@ -285,7 +285,7 @@ ObjDef *OrePuff::clone() const void OrePuff::generate(MMVManip *vm, int mapseed, u32 blockseed, - v3s16 nmin, v3s16 nmax, u8 *biomemap) + v3s16 nmin, v3s16 nmax, biome_t *biomemap) { PcgRandom pr(blockseed + 4234); MapNode n_ore(c_ore, 0, ore_param2); @@ -312,7 +312,7 @@ void OrePuff::generate(MMVManip *vm, int mapseed, u32 blockseed, continue; if (biomemap && !biomes.empty()) { - std::unordered_set::const_iterator it = biomes.find(biomemap[index]); + auto it = biomes.find(biomemap[index]); if (it == biomes.end()) continue; } @@ -366,7 +366,7 @@ ObjDef *OreBlob::clone() const void OreBlob::generate(MMVManip *vm, int mapseed, u32 blockseed, - v3s16 nmin, v3s16 nmax, u8 *biomemap) + v3s16 nmin, v3s16 nmax, biome_t *biomemap) { PcgRandom pr(blockseed + 2404); MapNode n_ore(c_ore, 0, ore_param2); @@ -388,7 +388,7 @@ void OreBlob::generate(MMVManip *vm, int mapseed, u32 blockseed, if (biomemap && !biomes.empty()) { u32 bmapidx = sizex * (z0 - nmin.Z) + (x0 - nmin.X); - std::unordered_set::const_iterator it = biomes.find(biomemap[bmapidx]); + auto it = biomes.find(biomemap[bmapidx]); if (it == biomes.end()) continue; } @@ -451,7 +451,7 @@ ObjDef *OreVein::clone() const void OreVein::generate(MMVManip *vm, int mapseed, u32 blockseed, - v3s16 nmin, v3s16 nmax, u8 *biomemap) + v3s16 nmin, v3s16 nmax, biome_t *biomemap) { PcgRandom pr(blockseed + 520); MapNode n_ore(c_ore, 0, ore_param2); @@ -485,7 +485,7 @@ void OreVein::generate(MMVManip *vm, int mapseed, u32 blockseed, if (biomemap && !biomes.empty()) { u32 bmapidx = sizex * (z - nmin.Z) + (x - nmin.X); - std::unordered_set::const_iterator it = biomes.find(biomemap[bmapidx]); + auto it = biomes.find(biomemap[bmapidx]); if (it == biomes.end()) continue; } @@ -532,7 +532,7 @@ ObjDef *OreStratum::clone() const void OreStratum::generate(MMVManip *vm, int mapseed, u32 blockseed, - v3s16 nmin, v3s16 nmax, u8 *biomemap) + v3s16 nmin, v3s16 nmax, biome_t *biomemap) { PcgRandom pr(blockseed + 4234); MapNode n_ore(c_ore, 0, ore_param2); @@ -560,7 +560,7 @@ void OreStratum::generate(MMVManip *vm, int mapseed, u32 blockseed, for (int z = nmin.Z; z <= nmax.Z; z++) for (int x = nmin.X; x <= nmax.X; x++, index++) { if (biomemap && !biomes.empty()) { - std::unordered_set::const_iterator it = biomes.find(biomemap[index]); + auto it = biomes.find(biomemap[index]); if (it == biomes.end()) continue; } diff --git a/src/mapgen/mg_ore.h b/src/mapgen/mg_ore.h index 213bdc964..76420fab4 100644 --- a/src/mapgen/mg_ore.h +++ b/src/mapgen/mg_ore.h @@ -1,7 +1,7 @@ /* Minetest -Copyright (C) 2014-2018 kwolekr, Ryan Kwolek -Copyright (C) 2015-2018 paramat +Copyright (C) 2015-2020 paramat +Copyright (C) 2014-2016 kwolekr, Ryan Kwolek 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 @@ -25,6 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "noise.h" #include "nodedef.h" +typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include + class Noise; class Mapgen; class MMVManip; @@ -64,7 +66,7 @@ public: float nthresh; // threshold for noise at which an ore is placed NoiseParams np; // noise for distribution of clusters (NULL for uniform scattering) Noise *noise = nullptr; - std::unordered_set biomes; + std::unordered_set biomes; Ore() = default;; virtual ~Ore(); @@ -73,7 +75,7 @@ public: size_t placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, - v3s16 nmin, v3s16 nmax, u8 *biomemap) = 0; + v3s16 nmin, v3s16 nmax, biome_t *biomemap) = 0; protected: void cloneTo(Ore *def) const; @@ -86,7 +88,7 @@ public: ObjDef *clone() const; virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, - v3s16 nmin, v3s16 nmax, u8 *biomemap); + v3s16 nmin, v3s16 nmax, biome_t *biomemap); }; class OreSheet : public Ore { @@ -100,7 +102,7 @@ public: float column_midpoint_factor; virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, - v3s16 nmin, v3s16 nmax, u8 *biomemap); + v3s16 nmin, v3s16 nmax, biome_t *biomemap); }; class OrePuff : public Ore { @@ -118,7 +120,7 @@ public: virtual ~OrePuff(); virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, - v3s16 nmin, v3s16 nmax, u8 *biomemap); + v3s16 nmin, v3s16 nmax, biome_t *biomemap); }; class OreBlob : public Ore { @@ -128,7 +130,7 @@ public: ObjDef *clone() const; virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, - v3s16 nmin, v3s16 nmax, u8 *biomemap); + v3s16 nmin, v3s16 nmax, biome_t *biomemap); }; class OreVein : public Ore { @@ -145,7 +147,7 @@ public: virtual ~OreVein(); virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, - v3s16 nmin, v3s16 nmax, u8 *biomemap); + v3s16 nmin, v3s16 nmax, biome_t *biomemap); }; class OreStratum : public Ore { @@ -162,7 +164,7 @@ public: virtual ~OreStratum(); virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, - v3s16 nmin, v3s16 nmax, u8 *biomemap); + v3s16 nmin, v3s16 nmax, biome_t *biomemap); }; class OreManager : public ObjDefManager { diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index 584085428..834938e56 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -97,7 +97,7 @@ Biome *get_or_load_biome(lua_State *L, int index, BiomeManager *biomemgr); Biome *read_biome_def(lua_State *L, int index, const NodeDefManager *ndef); size_t get_biome_list(lua_State *L, int index, - BiomeManager *biomemgr, std::unordered_set *biome_id_list); + BiomeManager *biomemgr, std::unordered_set *biome_id_list); Schematic *get_or_load_schematic(lua_State *L, int index, SchematicManager *schemmgr, StringMap *replace_names); @@ -425,7 +425,7 @@ Biome *read_biome_def(lua_State *L, int index, const NodeDefManager *ndef) size_t get_biome_list(lua_State *L, int index, - BiomeManager *biomemgr, std::unordered_set *biome_id_list) + BiomeManager *biomemgr, std::unordered_set *biome_id_list) { if (index < 0) index = lua_gettop(L) + 1 + index; diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h index 4a6a9ccf4..0bdc56fc5 100644 --- a/src/script/lua_api/l_mapgen.h +++ b/src/script/lua_api/l_mapgen.h @@ -21,6 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_base.h" +typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include + class ModApiMapgen : public ModApiBase { private: -- cgit v1.2.3 From e79bc40c0a5312baf4e8c3e33048d50b41b4a2ff Mon Sep 17 00:00:00 2001 From: Lejo1 Date: Wed, 20 May 2020 21:54:52 +0200 Subject: Check for valid base64 before decoding (#9904) --- doc/lua_api.txt | 2 +- src/script/lua_api/l_util.cpp | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 0101bd4cf..bd0cb8acb 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -5449,7 +5449,7 @@ Misc. * Example: `minetest.rgba(10, 20, 30, 40)`, returns `"#0A141E28"` * `minetest.encode_base64(string)`: returns string encoded in base64 * Encodes a string in base64. -* `minetest.decode_base64(string)`: returns string +* `minetest.decode_base64(string)`: returns string or nil for invalid base64 * Decodes a string encoded in base64. * `minetest.is_protected(pos, name)`: returns boolean * Returning `true` restricts the player `name` from modifying (i.e. digging, diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp index 28ee39fc8..cd63e20c2 100644 --- a/src/script/lua_api/l_util.cpp +++ b/src/script/lua_api/l_util.cpp @@ -318,9 +318,13 @@ int ModApiUtil::l_decode_base64(lua_State *L) NO_MAP_LOCK_REQUIRED; size_t size; - const char *data = luaL_checklstring(L, 1, &size); + const char *d = luaL_checklstring(L, 1, &size); + const std::string data = std::string(d, size); + + if (!base64_is_valid(data)) + return 0; - std::string out = base64_decode(std::string(data, size)); + std::string out = base64_decode(data); lua_pushlstring(L, out.data(), out.size()); return 1; -- cgit v1.2.3 From 15ba75e4cf1d1b8ceaa9d8ce33dcfdd7dbe80741 Mon Sep 17 00:00:00 2001 From: sorcerykid Date: Sat, 23 May 2020 06:24:06 -0500 Subject: Add on_authplayer callback and 'last_login' to on_joinplayer (#9574) Replace on_auth_fail callback with more versatile on_authplayer Better clarify account login process in Lua API documentation Change initial timestamp for newly registered accounts to -1 --- builtin/game/auth.lua | 3 +-- builtin/game/chat.lua | 2 +- builtin/game/deprecated.lua | 16 ++++++++++++++ builtin/game/register.lua | 2 +- doc/lua_api.txt | 20 ++++++++++------- src/network/serverpackethandler.cpp | 44 +++++++++++++++++++------------------ src/script/cpp_api/s_player.cpp | 19 +++++++++++----- src/script/cpp_api/s_player.h | 4 ++-- src/script/cpp_api/s_server.cpp | 14 ++++++++---- src/script/cpp_api/s_server.h | 3 ++- 10 files changed, 81 insertions(+), 46 deletions(-) (limited to 'doc') diff --git a/builtin/game/auth.lua b/builtin/game/auth.lua index 7aedfc82e..fc061666c 100644 --- a/builtin/game/auth.lua +++ b/builtin/game/auth.lua @@ -41,7 +41,6 @@ core.builtin_auth_handler = { return { password = auth_entry.password, privileges = privileges, - -- Is set to nil if unknown last_login = auth_entry.last_login, } end, @@ -53,7 +52,7 @@ core.builtin_auth_handler = { name = name, password = password, privileges = core.string_to_privs(core.settings:get("default_privs")), - last_login = os.time(), + last_login = -1, -- Defer login time calculation until record_login (called by on_joinplayer) }) end, delete_auth = function(name) diff --git a/builtin/game/chat.lua b/builtin/game/chat.lua index b9f84e522..aae811794 100644 --- a/builtin/game/chat.lua +++ b/builtin/game/chat.lua @@ -1068,7 +1068,7 @@ core.register_chatcommand("last-login", { param = name end local pauth = core.get_auth_handler().get_auth(param) - if pauth and pauth.last_login then + if pauth and pauth.last_login and pauth.last_login ~= -1 then -- Time in UTC, ISO 8601 format return true, "Last login time was " .. os.date("!%Y-%m-%dT%H:%M:%SZ", pauth.last_login) diff --git a/builtin/game/deprecated.lua b/builtin/game/deprecated.lua index 73e105eb8..20f0482eb 100644 --- a/builtin/game/deprecated.lua +++ b/builtin/game/deprecated.lua @@ -70,3 +70,19 @@ core.setting_get = setting_proxy("get") core.setting_setbool = setting_proxy("set_bool") core.setting_getbool = setting_proxy("get_bool") core.setting_save = setting_proxy("write") + +-- +-- core.register_on_auth_fail +-- + +function core.register_on_auth_fail(func) + core.log("deprecated", "core.register_on_auth_fail " .. + "is obsolete and should be replaced by " .. + "core.register_on_authplayer instead.") + + core.register_on_authplayer(function (player_name, ip, is_success) + if not is_success then + func(player_name, ip) + end + end) +end diff --git a/builtin/game/register.lua b/builtin/game/register.lua index eb6c2897c..1034d4f2b 100644 --- a/builtin/game/register.lua +++ b/builtin/game/register.lua @@ -607,9 +607,9 @@ core.registered_on_item_eats, core.register_on_item_eat = make_registration() core.registered_on_punchplayers, core.register_on_punchplayer = make_registration() core.registered_on_priv_grant, core.register_on_priv_grant = make_registration() core.registered_on_priv_revoke, core.register_on_priv_revoke = make_registration() +core.registered_on_authplayers, core.register_on_authplayer = make_registration() core.registered_can_bypass_userlimit, core.register_can_bypass_userlimit = make_registration() core.registered_on_modchannel_message, core.register_on_modchannel_message = make_registration() -core.registered_on_auth_fail, core.register_on_auth_fail = make_registration() core.registered_on_player_inventory_actions, core.register_on_player_inventory_action = make_registration() core.registered_allow_player_inventory_actions, core.register_allow_player_inventory_action = make_registration() diff --git a/doc/lua_api.txt b/doc/lua_api.txt index bd0cb8acb..26061eccb 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4374,7 +4374,7 @@ Call these functions only at load time! * Called after generating a piece of world. Modifying nodes inside the area is a bit faster than usually. * `minetest.register_on_newplayer(function(ObjectRef))` - * Called after a new player has been created + * Called when a new player enters the world for the first time * `minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage))` * Called when a player is punched * Note: This callback is invoked even if the punched player is dead. @@ -4415,19 +4415,23 @@ Call these functions only at load time! * Called _before_ repositioning of player occurs * return true in func to disable regular player placement * `minetest.register_on_prejoinplayer(function(name, ip))` - * Called before a player joins the game - * If it returns a string, the player is disconnected with that string as + * Called when a client connects to the server, prior to authentication + * If it returns a string, the client is disconnected with that string as reason. -* `minetest.register_on_joinplayer(function(ObjectRef))` +* `minetest.register_on_joinplayer(function(ObjectRef, last_login))` * Called when a player joins the game + * `last_login`: The timestamp of the previous login, or nil if player is new * `minetest.register_on_leaveplayer(function(ObjectRef, timed_out))` * Called when a player leaves the game * `timed_out`: True for timeout, false for other reasons. +* `minetest.register_on_authplayer(function(name, ip, is_success))` + * Called when a client attempts to log into an account. + * `name`: The name of the account being authenticated. + * `ip`: The IP address of the client + * `is_success`: Whether the client was successfully authenticated + * For newly registered accounts, `is_success` will always be true * `minetest.register_on_auth_fail(function(name, ip))` - * Called when a client attempts to log into an account but supplies the - wrong password. - * `ip`: The IP address of the client. - * `name`: The account the client attempted to log into. + * Deprecated: use `minetest.register_on_authplayer(name, ip, is_success)` instead. * `minetest.register_on_cheat(function(ObjectRef, cheat))` * Called when a player cheats * `cheat`: `{type=}`, where `` is one of: diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index 2fa9d4196..fed3b6f85 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -409,9 +409,12 @@ void Server::handleCommand_ClientReady(NetworkPacket* pkt) // (u16) 1 + std::string represents a pseudo vector serialization representation notice_pkt << (u8) PLAYER_LIST_ADD << (u16) 1 << std::string(playersao->getPlayer()->getName()); m_clients.sendToAll(¬ice_pkt); - m_clients.event(peer_id, CSE_SetClientReady); - m_script->on_joinplayer(playersao); + + s64 last_login; + m_script->getAuth(playersao->getPlayer()->getName(), nullptr, nullptr, &last_login); + m_script->on_joinplayer(playersao, last_login); + // Send shutdown timer if shutdown has been scheduled if (m_shutdown_state.isTimerRunning()) { SendChatMessage(peer_id, m_shutdown_state.getShutdownTimerMessage()); @@ -1512,6 +1515,7 @@ void Server::handleCommand_FirstSrp(NetworkPacket* pkt) initial_ver_key = encode_srp_verifier(verification_key, salt); m_script->createAuth(playername, initial_ver_key); + m_script->on_authplayer(playername, addr_s, true); acceptAuth(peer_id, false); } else { @@ -1648,24 +1652,25 @@ void Server::handleCommand_SrpBytesM(NetworkPacket* pkt) session_t peer_id = pkt->getPeerId(); RemoteClient *client = getClient(peer_id, CS_Invalid); ClientState cstate = client->getState(); + std::string addr_s = getPeerAddress(pkt->getPeerId()).serializeString(); + std::string playername = client->getName(); bool wantSudo = (cstate == CS_Active); verbosestream << "Server: Received TOCLIENT_SRP_BYTES_M." << std::endl; if (!((cstate == CS_HelloSent) || (cstate == CS_Active))) { - actionstream << "Server: got SRP _M packet in wrong state " << cstate << - " from " << getPeerAddress(peer_id).serializeString() << - ". Ignoring." << std::endl; + actionstream << "Server: got SRP _M packet in wrong state " + << cstate << " from " << addr_s + << ". Ignoring." << std::endl; return; } if (client->chosen_mech != AUTH_MECHANISM_SRP && client->chosen_mech != AUTH_MECHANISM_LEGACY_PASSWORD) { - actionstream << "Server: got SRP _M packet, while auth is going on " - "with mech " << client->chosen_mech << " from " << - getPeerAddress(peer_id).serializeString() << - " (wantSudo=" << wantSudo << "). Denying." << std::endl; + actionstream << "Server: got SRP _M packet, while auth" + << "is going on with mech " << client->chosen_mech << " from " + << addr_s << " (wantSudo=" << wantSudo << "). Denying." << std::endl; if (wantSudo) { DenySudoAccess(peer_id); return; @@ -1680,9 +1685,8 @@ void Server::handleCommand_SrpBytesM(NetworkPacket* pkt) if (srp_verifier_get_session_key_length((SRPVerifier *) client->auth_data) != bytes_M.size()) { - actionstream << "Server: User " << client->getName() << " at " << - getPeerAddress(peer_id).serializeString() << - " sent bytes_M with invalid length " << bytes_M.size() << std::endl; + actionstream << "Server: User " << playername << " at " << addr_s + << " sent bytes_M with invalid length " << bytes_M.size() << std::endl; DenyAccess(peer_id, SERVER_ACCESSDENIED_UNEXPECTED_DATA); return; } @@ -1694,24 +1698,21 @@ void Server::handleCommand_SrpBytesM(NetworkPacket* pkt) if (!bytes_HAMK) { if (wantSudo) { - actionstream << "Server: User " << client->getName() << " at " << - getPeerAddress(peer_id).serializeString() << - " tried to change their password, but supplied wrong (SRP) " - "password for authentication." << std::endl; + actionstream << "Server: User " << playername << " at " << addr_s + << " tried to change their password, but supplied wrong" + << " (SRP) password for authentication." << std::endl; DenySudoAccess(peer_id); return; } - std::string ip = getPeerAddress(peer_id).serializeString(); - actionstream << "Server: User " << client->getName() << " at " << ip << - " supplied wrong password (auth mechanism: SRP)." << std::endl; - m_script->on_auth_failure(client->getName(), ip); + actionstream << "Server: User " << playername << " at " << addr_s + << " supplied wrong password (auth mechanism: SRP)." << std::endl; + m_script->on_authplayer(playername, addr_s, false); DenyAccess(peer_id, SERVER_ACCESSDENIED_WRONG_PASSWORD); return; } if (client->create_player_on_auth_success) { - std::string playername = client->getName(); m_script->createAuth(playername, client->enc_pwd); std::string checkpwd; // not used, but needed for passing something @@ -1725,6 +1726,7 @@ void Server::handleCommand_SrpBytesM(NetworkPacket* pkt) client->create_player_on_auth_success = false; } + m_script->on_authplayer(playername, addr_s, true); acceptAuth(peer_id, wantSudo); } diff --git a/src/script/cpp_api/s_player.cpp b/src/script/cpp_api/s_player.cpp index df67ea00c..712120c61 100644 --- a/src/script/cpp_api/s_player.cpp +++ b/src/script/cpp_api/s_player.cpp @@ -147,7 +147,7 @@ bool ScriptApiPlayer::can_bypass_userlimit(const std::string &name, const std::s return lua_toboolean(L, -1); } -void ScriptApiPlayer::on_joinplayer(ServerActiveObject *player) +void ScriptApiPlayer::on_joinplayer(ServerActiveObject *player, s64 last_login) { SCRIPTAPI_PRECHECKHEADER @@ -156,7 +156,11 @@ void ScriptApiPlayer::on_joinplayer(ServerActiveObject *player) lua_getfield(L, -1, "registered_on_joinplayers"); // Call callbacks objectrefGetOrCreate(L, player); - runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); + if (last_login != -1) + lua_pushinteger(L, last_login); + else + lua_pushnil(L); + runCallbacks(2, RUN_CALLBACKS_MODE_FIRST); } void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player, @@ -216,16 +220,19 @@ void ScriptApiPlayer::on_playerReceiveFields(ServerActiveObject *player, runCallbacks(3, RUN_CALLBACKS_MODE_OR_SC); } -void ScriptApiPlayer::on_auth_failure(const std::string &name, const std::string &ip) +void ScriptApiPlayer::on_authplayer(const std::string &name, const std::string &ip, bool is_success) { SCRIPTAPI_PRECHECKHEADER - // Get core.registered_on_auth_failure + // Get core.registered_on_authplayers lua_getglobal(L, "core"); - lua_getfield(L, -1, "registered_on_auth_fail"); + lua_getfield(L, -1, "registered_on_authplayers"); + + // Call callbacks lua_pushstring(L, name.c_str()); lua_pushstring(L, ip.c_str()); - runCallbacks(2, RUN_CALLBACKS_MODE_FIRST); + lua_pushboolean(L, is_success); + runCallbacks(3, RUN_CALLBACKS_MODE_FIRST); } void ScriptApiPlayer::pushMoveArguments( diff --git a/src/script/cpp_api/s_player.h b/src/script/cpp_api/s_player.h index 7ca3d8f30..a337f975b 100644 --- a/src/script/cpp_api/s_player.h +++ b/src/script/cpp_api/s_player.h @@ -41,7 +41,7 @@ public: bool on_prejoinplayer(const std::string &name, const std::string &ip, std::string *reason); bool can_bypass_userlimit(const std::string &name, const std::string &ip); - void on_joinplayer(ServerActiveObject *player); + void on_joinplayer(ServerActiveObject *player, s64 last_login); void on_leaveplayer(ServerActiveObject *player, bool timeout); void on_cheat(ServerActiveObject *player, const std::string &cheat_type); bool on_punchplayer(ServerActiveObject *player, ServerActiveObject *hitter, @@ -51,7 +51,7 @@ public: const PlayerHPChangeReason &reason); void on_playerReceiveFields(ServerActiveObject *player, const std::string &formname, const StringMap &fields); - void on_auth_failure(const std::string &name, const std::string &ip); + void on_authplayer(const std::string &name, const std::string &ip, bool is_success); // Player inventory callbacks // Return number of accepted items to be moved diff --git a/src/script/cpp_api/s_server.cpp b/src/script/cpp_api/s_server.cpp index 1ce2f9d45..96cb28b28 100644 --- a/src/script/cpp_api/s_server.cpp +++ b/src/script/cpp_api/s_server.cpp @@ -23,7 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc., bool ScriptApiServer::getAuth(const std::string &playername, std::string *dst_password, - std::set *dst_privs) + std::set *dst_privs, + s64 *dst_last_login) { SCRIPTAPI_PRECHECKHEADER @@ -43,8 +44,7 @@ bool ScriptApiServer::getAuth(const std::string &playername, luaL_checktype(L, -1, LUA_TTABLE); std::string password; - bool found = getstringfield(L, -1, "password", password); - if (!found) + if (!getstringfield(L, -1, "password", password)) throw LuaError("Authentication handler didn't return password"); if (dst_password) *dst_password = password; @@ -54,7 +54,13 @@ bool ScriptApiServer::getAuth(const std::string &playername, throw LuaError("Authentication handler didn't return privilege table"); if (dst_privs) readPrivileges(-1, *dst_privs); - lua_pop(L, 1); + lua_pop(L, 1); // Remove key from privs table + + s64 last_login; + if(!getintfield(L, -1, "last_login", last_login)) + throw LuaError("Authentication handler didn't return last_login"); + if (dst_last_login) + *dst_last_login = (s64)last_login; return true; } diff --git a/src/script/cpp_api/s_server.h b/src/script/cpp_api/s_server.h index a4cede84d..d8639cba7 100644 --- a/src/script/cpp_api/s_server.h +++ b/src/script/cpp_api/s_server.h @@ -43,7 +43,8 @@ public: /* auth */ bool getAuth(const std::string &playername, std::string *dst_password, - std::set *dst_privs); + std::set *dst_privs, + s64 *dst_last_login = nullptr); void createAuth(const std::string &playername, const std::string &password); bool setPassword(const std::string &playername, -- cgit v1.2.3 From 9d6e7e48d6fb1daff8fedcb2f111164bef61f1e7 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Fri, 22 May 2020 14:17:03 +0200 Subject: Implement spawning particles with node texture appearance --- build/android/native/jni/Android.mk | 1 + doc/lua_api.txt | 30 ++++++++++++- src/client/particles.cpp | 75 ++++++++++++++++++++++++-------- src/client/particles.h | 4 +- src/network/clientpackethandler.cpp | 10 +++++ src/particles.cpp | 10 +++++ src/particles.h | 6 +++ src/script/lua_api/l_particles.cpp | 14 ++++++ src/script/lua_api/l_particles_local.cpp | 14 ++++++ src/server.cpp | 1 + 10 files changed, 145 insertions(+), 20 deletions(-) (limited to 'doc') diff --git a/build/android/native/jni/Android.mk b/build/android/native/jni/Android.mk index a5cb099e6..140947e6a 100644 --- a/build/android/native/jni/Android.mk +++ b/build/android/native/jni/Android.mk @@ -164,6 +164,7 @@ LOCAL_SRC_FILES := \ ../../../src/noise.cpp \ ../../../src/objdef.cpp \ ../../../src/object_properties.cpp \ + ../../../src/particles.cpp \ ../../../src/pathfinder.cpp \ ../../../src/player.cpp \ ../../../src/porting.cpp \ diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 26061eccb..5b3f61c99 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -7835,6 +7835,8 @@ Used by `minetest.add_particle`. size = 1, -- Scales the visual size of the particle texture. + -- If `node` is set, size can be set to 0 to spawn a randomly-sized + -- particle (just like actual node dig particles). collisiondetection = false, -- If true collides with `walkable` nodes and, depending on the @@ -7853,6 +7855,7 @@ Used by `minetest.add_particle`. -- If true faces player using y axis only texture = "image.png", + -- The texture of the particle playername = "singleplayer", -- Optional, if specified spawns particle only on the player's client @@ -7863,6 +7866,17 @@ Used by `minetest.add_particle`. glow = 0 -- Optional, specify particle self-luminescence in darkness. -- Values 0-14. + + node = {name = "ignore", param2 = 0}, + -- Optional, if specified the particle will have the same appearance as + -- node dig particles for the given node. + -- `texture` and `animation` will be ignored if this is set. + + node_tile = 0, + -- Optional, only valid in combination with `node` + -- If set to a valid number 1-6, specifies the tile from which the + -- particle texture is picked. + -- Otherwise, the default behavior is used. (currently: any random tile) } @@ -7892,7 +7906,9 @@ Used by `minetest.add_particlespawner`. maxsize = 1, -- The particles' properties are random values between the min and max -- values. - -- pos, velocity, acceleration, expirationtime, size + -- applies to: pos, velocity, acceleration, expirationtime, size + -- If `node` is set, min and maxsize can be set to 0 to spawn + -- randomly-sized particles (just like actual node dig particles). collisiondetection = false, -- If true collide with `walkable` nodes and, depending on the @@ -7915,6 +7931,7 @@ Used by `minetest.add_particlespawner`. -- If true face player using y axis only texture = "image.png", + -- The texture of the particle playername = "singleplayer", -- Optional, if specified spawns particles only on the player's client @@ -7925,6 +7942,17 @@ Used by `minetest.add_particlespawner`. glow = 0 -- Optional, specify particle self-luminescence in darkness. -- Values 0-14. + + node = {name = "ignore", param2 = 0}, + -- Optional, if specified the particles will have the same appearance as + -- node dig particles for the given node. + -- `texture` and `animation` will be ignored if this is set. + + node_tile = 0, + -- Optional, only valid in combination with `node` + -- If set to a valid number 1-6, specifies the tile from which the + -- particle texture is picked. + -- Otherwise, the default behavior is used. (currently: any random tile) } `HTTPRequest` definition diff --git a/src/client/particles.cpp b/src/client/particles.cpp index c2e751b4f..c78a3e71a 100644 --- a/src/client/particles.cpp +++ b/src/client/particles.cpp @@ -304,18 +304,37 @@ void ParticleSpawner::spawnParticle(ClientEnvironment *env, float radius, } pp.expirationtime = random_f32(p.minexptime, p.maxexptime); - pp.size = random_f32(p.minsize, p.maxsize); - p.copyCommon(pp); + video::ITexture *texture; + v2f texpos, texsize; + video::SColor color(0xFFFFFFFF); + + if (p.node.getContent() != CONTENT_IGNORE) { + const ContentFeatures &f = + m_particlemanager->m_env->getGameDef()->ndef()->get(p.node); + if (!ParticleManager::getNodeParticleParams(p.node, f, pp, &texture, + texpos, texsize, &color, p.node_tile)) + return; + } else { + texture = m_texture; + texpos = v2f(0.0f, 0.0f); + texsize = v2f(1.0f, 1.0f); + } + + // Allow keeping default random size + if (p.maxsize > 0.0f) + pp.size = random_f32(p.minsize, p.maxsize); + m_particlemanager->addParticle(new Particle( m_gamedef, m_player, env, pp, - m_texture, - v2f(0.0, 0.0), - v2f(1.0, 1.0) + texture, + texpos, + texsize, + color )); } @@ -460,17 +479,35 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, Client *client, break; } case CE_SPAWN_PARTICLE: { - const ParticleParameters &p = *event->spawn_particle; - video::ITexture *texture = - client->tsrc()->getTextureForMesh(p.texture); + ParticleParameters &p = *event->spawn_particle; - Particle *toadd = new Particle(client, player, m_env, - p, - texture, - v2f(0.0, 0.0), - v2f(1.0, 1.0)); + video::ITexture *texture; + v2f texpos, texsize; + video::SColor color(0xFFFFFFFF); + + f32 oldsize = p.size; + + if (p.node.getContent() != CONTENT_IGNORE) { + const ContentFeatures &f = m_env->getGameDef()->ndef()->get(p.node); + if (!getNodeParticleParams(p.node, f, p, &texture, texpos, + texsize, &color, p.node_tile)) + texture = nullptr; + } else { + texture = client->tsrc()->getTextureForMesh(p.texture); + texpos = v2f(0.0f, 0.0f); + texsize = v2f(1.0f, 1.0f); + } + + // Allow keeping default random size + if (oldsize > 0.0f) + p.size = oldsize; - addParticle(toadd); + if (texture) { + Particle *toadd = new Particle(client, player, m_env, + p, texture, texpos, texsize, color); + + addParticle(toadd); + } delete event->spawn_particle; break; @@ -480,15 +517,19 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, Client *client, } bool ParticleManager::getNodeParticleParams(const MapNode &n, - const ContentFeatures &f, ParticleParameters &p, - video::ITexture **texture, v2f &texpos, v2f &texsize, video::SColor *color) + const ContentFeatures &f, ParticleParameters &p, video::ITexture **texture, + v2f &texpos, v2f &texsize, video::SColor *color, u8 tilenum) { // No particles for "airlike" nodes if (f.drawtype == NDT_AIRLIKE) return false; // Texture - u8 texid = rand() % 6; + u8 texid; + if (tilenum > 0 && tilenum <= 6) + texid = tilenum - 1; + else + texid = rand() % 6; const TileLayer &tile = f.tiles[texid].layers[0]; p.animation.type = TAT_NONE; diff --git a/src/client/particles.h b/src/client/particles.h index 7dda0e1b1..2011f0262 100644 --- a/src/client/particles.h +++ b/src/client/particles.h @@ -42,7 +42,7 @@ class Particle : public scene::ISceneNode video::ITexture *texture, v2f texpos, v2f texsize, - video::SColor color = video::SColor(0xFFFFFFFF) + video::SColor color ); ~Particle() = default; @@ -171,7 +171,7 @@ public: protected: static bool getNodeParticleParams(const MapNode &n, const ContentFeatures &f, ParticleParameters &p, video::ITexture **texture, v2f &texpos, - v2f &texsize, video::SColor *color); + v2f &texsize, video::SColor *color, u8 tilenum = 0); void addParticle(Particle* toadd); diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 054e60c3c..e000acc92 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1003,6 +1003,16 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt) p.glow = readU8(is); p.object_collision = readU8(is); + // This is kinda awful + do { + u16 tmp_param0 = readU16(is); + if (is.eof()) + break; + p.node.param0 = tmp_param0; + p.node.param2 = readU8(is); + p.node_tile = readU8(is); + } while (0); + auto event = new ClientEvent(); event->type = CE_ADD_PARTICLESPAWNER; event->add_particlespawner.p = new ParticleSpawnerParameters(p); diff --git a/src/particles.cpp b/src/particles.cpp index 711d189f6..fd81238dc 100644 --- a/src/particles.cpp +++ b/src/particles.cpp @@ -34,6 +34,9 @@ void ParticleParameters::serialize(std::ostream &os, u16 protocol_ver) const animation.serialize(os, 6); /* NOT the protocol ver */ writeU8(os, glow); writeU8(os, object_collision); + writeU16(os, node.param0); + writeU8(os, node.param2); + writeU8(os, node_tile); } void ParticleParameters::deSerialize(std::istream &is, u16 protocol_ver) @@ -50,4 +53,11 @@ void ParticleParameters::deSerialize(std::istream &is, u16 protocol_ver) animation.deSerialize(is, 6); /* NOT the protocol ver */ glow = readU8(is); object_collision = readU8(is); + // This is kinda awful + u16 tmp_param0 = readU16(is); + if (is.eof()) + return; + node.param0 = tmp_param0; + node.param2 = readU8(is); + node_tile = readU8(is); } diff --git a/src/particles.h b/src/particles.h index 659c1249f..6f518b771 100644 --- a/src/particles.h +++ b/src/particles.h @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "irrlichttypes_bloated.h" #include "tileanimation.h" +#include "mapnode.h" // This file defines the particle-related structures that both the server and // client need. The ParticleManager and rendering is in client/particles.h @@ -34,9 +35,12 @@ struct CommonParticleParams { std::string texture; struct TileAnimationParams animation; u8 glow = 0; + MapNode node; + u8 node_tile = 0; CommonParticleParams() { animation.type = TAT_NONE; + node.setContent(CONTENT_IGNORE); } /* This helper is useful for copying params from @@ -49,6 +53,8 @@ struct CommonParticleParams { to.texture = texture; to.animation = animation; to.glow = glow; + to.node = node; + to.node_tile = node_tile; } }; diff --git a/src/script/lua_api/l_particles.cpp b/src/script/lua_api/l_particles.cpp index 7680aa17b..a51c4fe20 100644 --- a/src/script/lua_api/l_particles.cpp +++ b/src/script/lua_api/l_particles.cpp @@ -111,6 +111,13 @@ int ModApiParticles::l_add_particle(lua_State *L) p.texture = getstringfield_default(L, 1, "texture", p.texture); p.glow = getintfield_default(L, 1, "glow", p.glow); + lua_getfield(L, 1, "node"); + if (lua_istable(L, -1)) + p.node = readnode(L, -1, getGameDef(L)->ndef()); + lua_pop(L, 1); + + p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile); + playername = getstringfield_default(L, 1, "playername", ""); } @@ -231,6 +238,13 @@ int ModApiParticles::l_add_particlespawner(lua_State *L) p.texture = getstringfield_default(L, 1, "texture", p.texture); playername = getstringfield_default(L, 1, "playername", ""); p.glow = getintfield_default(L, 1, "glow", p.glow); + + lua_getfield(L, 1, "node"); + if (lua_istable(L, -1)) + p.node = readnode(L, -1, getGameDef(L)->ndef()); + lua_pop(L, 1); + + p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile); } u32 id = getServer(L)->addParticleSpawner(p, attached, playername); diff --git a/src/script/lua_api/l_particles_local.cpp b/src/script/lua_api/l_particles_local.cpp index 9595b2fab..cc68b13a5 100644 --- a/src/script/lua_api/l_particles_local.cpp +++ b/src/script/lua_api/l_particles_local.cpp @@ -67,6 +67,13 @@ int ModApiParticlesLocal::l_add_particle(lua_State *L) p.texture = getstringfield_default(L, 1, "texture", p.texture); p.glow = getintfield_default(L, 1, "glow", p.glow); + lua_getfield(L, 1, "node"); + if (lua_istable(L, -1)) + p.node = readnode(L, -1, getGameDef(L)->ndef()); + lua_pop(L, 1); + + p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile); + ClientEvent *event = new ClientEvent(); event->type = CE_SPAWN_PARTICLE; event->spawn_particle = new ParticleParameters(p); @@ -134,6 +141,13 @@ int ModApiParticlesLocal::l_add_particlespawner(lua_State *L) p.texture = getstringfield_default(L, 1, "texture", p.texture); p.glow = getintfield_default(L, 1, "glow", p.glow); + lua_getfield(L, 1, "node"); + if (lua_istable(L, -1)) + p.node = readnode(L, -1, getGameDef(L)->ndef()); + lua_pop(L, 1); + + p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile); + u64 id = getClient(L)->getParticleManager()->generateSpawnerId(); auto event = new ClientEvent(); diff --git a/src/server.cpp b/src/server.cpp index 68b0131d4..d6e545498 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1577,6 +1577,7 @@ void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version, pkt.putRawString(os.str()); } pkt << p.glow << p.object_collision; + pkt << p.node.param0 << p.node.param2 << p.node_tile; Send(&pkt); } -- cgit v1.2.3 From 8ee2ece3c97d3beeab5b9930cfcf0d76aa1d39c4 Mon Sep 17 00:00:00 2001 From: ANAND Date: Sun, 24 May 2020 15:18:19 +0530 Subject: lua_api.txt: Fix minor typo (#9917) --- doc/lua_api.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 5b3f61c99..a77c7567e 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4494,7 +4494,7 @@ Call these functions only at load time! * The same as before, except that it is called before the player crafts, to make craft prediction, and it should not change anything. * `minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info))` - * Determinates how much of a stack may be taken, put or moved to a + * Determines how much of a stack may be taken, put or moved to a player inventory. * `player` (type `ObjectRef`) is the player who modified the inventory `inventory` (type `InvRef`). -- cgit v1.2.3 From 083b285f4319c470f307f0b52f03a2fb68facd38 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 26 May 2020 00:17:52 +0200 Subject: Rename “Minimal development test” to “Development Test” (#9928) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 6 +- README.md | 2 +- builtin/mainmenu/dlg_create_world.lua | 12 +- doc/lua_api.txt | 2 +- games/devtest/LICENSE.txt | 4 + games/devtest/README.md | 52 ++ games/devtest/game.conf | 2 + games/devtest/menu/background.png | Bin 0 -> 152 bytes games/devtest/menu/header.png | Bin 0 -> 404 bytes games/devtest/menu/icon.png | Bin 0 -> 217 bytes games/devtest/mods/basenodes/init.lua | 334 ++++++++++ games/devtest/mods/basenodes/mod.conf | 2 + .../textures/basenodes_dirt_with_grass_bottom.png | Bin 0 -> 187 bytes .../textures/basenodes_dirt_with_snow.png | Bin 0 -> 166 bytes .../textures/basenodes_dirt_with_snow_bottom.png | Bin 0 -> 177 bytes .../basenodes/textures/basenodes_snow_sheet.png | Bin 0 -> 166 bytes .../mods/basenodes/textures/default_apple.png | Bin 0 -> 102 bytes .../mods/basenodes/textures/default_cobble.png | Bin 0 -> 340 bytes .../basenodes/textures/default_desert_sand.png | Bin 0 -> 293 bytes .../basenodes/textures/default_desert_stone.png | Bin 0 -> 584 bytes .../mods/basenodes/textures/default_dirt.png | Bin 0 -> 790 bytes .../mods/basenodes/textures/default_grass.png | Bin 0 -> 697 bytes .../mods/basenodes/textures/default_grass_side.png | Bin 0 -> 796 bytes .../mods/basenodes/textures/default_gravel.png | Bin 0 -> 171 bytes .../mods/basenodes/textures/default_ice.png | Bin 0 -> 369 bytes .../basenodes/textures/default_junglegrass.png | Bin 0 -> 201 bytes .../basenodes/textures/default_jungleleaves.png | Bin 0 -> 399 bytes .../mods/basenodes/textures/default_jungletree.png | Bin 0 -> 730 bytes .../basenodes/textures/default_jungletree_top.png | Bin 0 -> 714 bytes .../mods/basenodes/textures/default_lava.png | Bin 0 -> 172 bytes .../basenodes/textures/default_lava_flowing.png | Bin 0 -> 91 bytes .../mods/basenodes/textures/default_leaves.png | Bin 0 -> 883 bytes .../basenodes/textures/default_mossycobble.png | Bin 0 -> 574 bytes .../basenodes/textures/default_pine_needles.png | Bin 0 -> 648 bytes .../mods/basenodes/textures/default_pine_tree.png | Bin 0 -> 604 bytes .../basenodes/textures/default_pine_tree_top.png | Bin 0 -> 174 bytes .../basenodes/textures/default_river_water.png | Bin 0 -> 496 bytes .../textures/default_river_water_flowing.png | Bin 0 -> 99 bytes .../mods/basenodes/textures/default_sand.png | Bin 0 -> 554 bytes .../mods/basenodes/textures/default_snow.png | Bin 0 -> 166 bytes .../mods/basenodes/textures/default_snow_side.png | Bin 0 -> 152 bytes .../mods/basenodes/textures/default_stone.png | Bin 0 -> 313 bytes .../mods/basenodes/textures/default_tree.png | Bin 0 -> 659 bytes .../mods/basenodes/textures/default_tree_top.png | Bin 0 -> 175 bytes .../mods/basenodes/textures/default_water.png | Bin 0 -> 302 bytes .../basenodes/textures/default_water_flowing.png | Bin 0 -> 115 bytes games/devtest/mods/basetools/init.lua | 295 +++++++++ games/devtest/mods/basetools/mod.conf | 2 + .../mods/basetools/textures/basetools_dirtpick.png | Bin 0 -> 307 bytes .../basetools/textures/basetools_firesword.png | Bin 0 -> 190 bytes .../mods/basetools/textures/basetools_icesword.png | Bin 0 -> 190 bytes .../mods/basetools/textures/basetools_mesepick.png | Bin 0 -> 155 bytes .../mods/basetools/textures/basetools_steelaxe.png | Bin 0 -> 131 bytes .../basetools/textures/basetools_steeldagger.png | Bin 0 -> 154 bytes .../basetools/textures/basetools_steelpick.png | Bin 0 -> 159 bytes .../basetools/textures/basetools_steelpick_l1.png | Bin 0 -> 190 bytes .../basetools/textures/basetools_steelpick_l2.png | Bin 0 -> 177 bytes .../basetools/textures/basetools_steelshears.png | Bin 0 -> 208 bytes .../basetools/textures/basetools_steelshovel.png | Bin 0 -> 140 bytes .../basetools/textures/basetools_steelsword.png | Bin 0 -> 163 bytes .../mods/basetools/textures/basetools_stoneaxe.png | Bin 0 -> 130 bytes .../basetools/textures/basetools_stonepick.png | Bin 0 -> 155 bytes .../basetools/textures/basetools_stoneshears.png | Bin 0 -> 224 bytes .../basetools/textures/basetools_stoneshovel.png | Bin 0 -> 134 bytes .../basetools/textures/basetools_stonesword.png | Bin 0 -> 159 bytes .../mods/basetools/textures/basetools_woodaxe.png | Bin 0 -> 121 bytes .../mods/basetools/textures/basetools_woodpick.png | Bin 0 -> 149 bytes .../basetools/textures/basetools_woodshears.png | Bin 0 -> 212 bytes .../basetools/textures/basetools_woodshovel.png | Bin 0 -> 133 bytes .../basetools/textures/basetools_woodsword.png | Bin 0 -> 139 bytes games/devtest/mods/bucket/init.lua | 26 + games/devtest/mods/bucket/mod.conf | 2 + games/devtest/mods/bucket/textures/bucket.png | Bin 0 -> 163 bytes games/devtest/mods/bucket/textures/bucket_lava.png | Bin 0 -> 168 bytes .../devtest/mods/bucket/textures/bucket_water.png | Bin 0 -> 168 bytes games/devtest/mods/chest/init.lua | 27 + games/devtest/mods/chest/mod.conf | 2 + games/devtest/mods/chest/textures/chest_chest.png | Bin 0 -> 163 bytes games/devtest/mods/chest_of_everything/init.lua | 135 ++++ games/devtest/mods/chest_of_everything/mod.conf | 2 + .../textures/chest_of_everything_chest.png | Bin 0 -> 210 bytes games/devtest/mods/dignodes/init.lua | 37 ++ games/devtest/mods/dignodes/mod.conf | 2 + .../mods/dignodes/textures/dignodes_choppy.png | Bin 0 -> 187 bytes .../mods/dignodes/textures/dignodes_cracky.png | Bin 0 -> 193 bytes .../mods/dignodes/textures/dignodes_crumbly.png | Bin 0 -> 172 bytes .../dignodes/textures/dignodes_dig_immediate.png | Bin 0 -> 170 bytes .../mods/dignodes/textures/dignodes_none.png | Bin 0 -> 201 bytes .../mods/dignodes/textures/dignodes_rating1.png | Bin 0 -> 94 bytes .../mods/dignodes/textures/dignodes_rating2.png | Bin 0 -> 92 bytes .../mods/dignodes/textures/dignodes_rating3.png | Bin 0 -> 93 bytes games/devtest/mods/experimental/commands.lua | 215 +++++++ games/devtest/mods/experimental/detached.lua | 29 + games/devtest/mods/experimental/init.lua | 23 + games/devtest/mods/experimental/items.lua | 103 +++ games/devtest/mods/experimental/mod.conf | 2 + .../textures/experimental_callback_node.png | Bin 0 -> 139 bytes .../textures/experimental_particle_sheet.png | Bin 0 -> 208 bytes .../textures/experimental_particle_vertical.png | Bin 0 -> 308 bytes .../textures/experimental_tester_tool_1.png | Bin 0 -> 138 bytes games/devtest/mods/give_initial_stuff/init.lua | 37 ++ games/devtest/mods/give_initial_stuff/mod.conf | 3 + games/devtest/mods/initial_message/init.lua | 9 + games/devtest/mods/initial_message/mod.conf | 2 + games/devtest/mods/mapgen/init.lua | 81 +++ games/devtest/mods/mapgen/mod.conf | 3 + games/devtest/mods/modchannels/init.lua | 14 + games/devtest/mods/modchannels/mod.conf | 2 + games/devtest/mods/soundstuff/init.lua | 170 +++++ games/devtest/mods/soundstuff/mod.conf | 2 + .../mods/soundstuff/sounds/soundstuff_mono.ogg | Bin 0 -> 4362 bytes .../mods/soundstuff/textures/soundstuff_eat.png | Bin 0 -> 113 bytes .../soundstuff/textures/soundstuff_node_blank.png | Bin 0 -> 83 bytes .../textures/soundstuff_node_climbable.png | Bin 0 -> 189 bytes .../soundstuff/textures/soundstuff_node_dig.png | Bin 0 -> 126 bytes .../soundstuff/textures/soundstuff_node_dug.png | Bin 0 -> 132 bytes .../soundstuff/textures/soundstuff_node_fall.png | Bin 0 -> 100 bytes .../textures/soundstuff_node_footstep.png | Bin 0 -> 120 bytes .../soundstuff/textures/soundstuff_node_place.png | Bin 0 -> 115 bytes .../textures/soundstuff_node_place_failed.png | Bin 0 -> 143 bytes .../soundstuff/textures/soundstuff_node_sound.png | Bin 0 -> 116 bytes games/devtest/mods/stairs/init.lua | 65 ++ games/devtest/mods/stairs/mod.conf | 3 + games/devtest/mods/testentities/armor.lua | 41 ++ games/devtest/mods/testentities/callbacks.lua | 75 +++ games/devtest/mods/testentities/init.lua | 3 + games/devtest/mods/testentities/mod.conf | 2 + .../textures/testentities_armorball.png | Bin 0 -> 561 bytes .../textures/testentities_callback.png | Bin 0 -> 156 bytes .../textures/testentities_callback_step.png | Bin 0 -> 166 bytes .../testentities/textures/testentities_cube1.png | Bin 0 -> 130 bytes .../testentities/textures/testentities_cube2.png | Bin 0 -> 128 bytes .../testentities/textures/testentities_cube3.png | Bin 0 -> 124 bytes .../testentities/textures/testentities_cube4.png | Bin 0 -> 126 bytes .../testentities/textures/testentities_cube5.png | Bin 0 -> 126 bytes .../testentities/textures/testentities_cube6.png | Bin 0 -> 126 bytes .../textures/testentities_dungeon_master.png | Bin 0 -> 2855 bytes .../testentities/textures/testentities_sprite.png | Bin 0 -> 120 bytes .../textures/testentities_upright_sprite1.png | Bin 0 -> 114 bytes .../textures/testentities_upright_sprite2.png | Bin 0 -> 119 bytes games/devtest/mods/testentities/visuals.lua | 74 +++ games/devtest/mods/testfood/init.lua | 24 + games/devtest/mods/testfood/mod.conf | 2 + .../mods/testfood/textures/testfood_bad.png | Bin 0 -> 126 bytes .../mods/testfood/textures/testfood_bad2.png | Bin 0 -> 133 bytes .../mods/testfood/textures/testfood_good.png | Bin 0 -> 129 bytes .../mods/testfood/textures/testfood_good2.png | Bin 0 -> 145 bytes games/devtest/mods/testformspec/callbacks.lua | 51 ++ games/devtest/mods/testformspec/dummy_items.lua | 14 + games/devtest/mods/testformspec/formspec.lua | 381 ++++++++++++ games/devtest/mods/testformspec/init.lua | 3 + games/devtest/mods/testformspec/mod.conf | 2 + .../textures/testformspec_animation.jpg | Bin 0 -> 4376 bytes .../textures/testformspec_animation.png | Bin 0 -> 214 bytes .../mods/testformspec/textures/testformspec_bg.png | Bin 0 -> 92 bytes .../textures/testformspec_bg_9slice.png | Bin 0 -> 146 bytes .../textures/testformspec_bg_9slice_hovered.png | Bin 0 -> 146 bytes .../textures/testformspec_bg_9slice_pressed.png | Bin 0 -> 146 bytes .../textures/testformspec_bg_hovered.png | Bin 0 -> 92 bytes .../textures/testformspec_bg_pressed.png | Bin 0 -> 91 bytes .../textures/testformspec_button_image.png | Bin 0 -> 146 bytes .../testformspec/textures/testformspec_hovered.png | Bin 0 -> 195 bytes .../testformspec/textures/testformspec_item.png | Bin 0 -> 182 bytes .../testformspec/textures/testformspec_node.png | Bin 0 -> 113 bytes .../testformspec/textures/testformspec_pressed.png | Bin 0 -> 165 bytes games/devtest/mods/testnodes/README.md | 11 + games/devtest/mods/testnodes/drawtypes.lua | 517 +++++++++++++++ games/devtest/mods/testnodes/init.lua | 10 + games/devtest/mods/testnodes/light.lua | 48 ++ games/devtest/mods/testnodes/liquids.lua | 91 +++ games/devtest/mods/testnodes/meshes.lua | 145 +++++ games/devtest/mods/testnodes/mod.conf | 2 + .../mods/testnodes/models/testnodes_ocorner.obj | 23 + .../mods/testnodes/models/testnodes_pyramid.obj | 24 + games/devtest/mods/testnodes/nodeboxes.lua | 80 +++ games/devtest/mods/testnodes/param2.lua | 168 +++++ games/devtest/mods/testnodes/properties.lua | 270 ++++++++ games/devtest/mods/testnodes/settingtypes.txt | 4 + games/devtest/mods/testnodes/textures.lua | 67 ++ .../mods/testnodes/textures/testnodes_1.png | Bin 0 -> 107 bytes .../mods/testnodes/textures/testnodes_1g.png | Bin 0 -> 104 bytes .../mods/testnodes/textures/testnodes_1w.png | Bin 0 -> 121 bytes .../mods/testnodes/textures/testnodes_1wg.png | Bin 0 -> 122 bytes .../mods/testnodes/textures/testnodes_2.png | Bin 0 -> 112 bytes .../mods/testnodes/textures/testnodes_2g.png | Bin 0 -> 110 bytes .../mods/testnodes/textures/testnodes_2w.png | Bin 0 -> 134 bytes .../mods/testnodes/textures/testnodes_2wg.png | Bin 0 -> 135 bytes .../mods/testnodes/textures/testnodes_3.png | Bin 0 -> 105 bytes .../mods/testnodes/textures/testnodes_3g.png | Bin 0 -> 103 bytes .../mods/testnodes/textures/testnodes_3w.png | Bin 0 -> 112 bytes .../mods/testnodes/textures/testnodes_3wg.png | Bin 0 -> 112 bytes .../mods/testnodes/textures/testnodes_4.png | Bin 0 -> 97 bytes .../mods/testnodes/textures/testnodes_4g.png | Bin 0 -> 95 bytes .../mods/testnodes/textures/testnodes_4w.png | Bin 0 -> 128 bytes .../mods/testnodes/textures/testnodes_4wg.png | Bin 0 -> 128 bytes .../mods/testnodes/textures/testnodes_5.png | Bin 0 -> 98 bytes .../mods/testnodes/textures/testnodes_5g.png | Bin 0 -> 98 bytes .../mods/testnodes/textures/testnodes_5w.png | Bin 0 -> 117 bytes .../mods/testnodes/textures/testnodes_5wg.png | Bin 0 -> 117 bytes .../mods/testnodes/textures/testnodes_6.png | Bin 0 -> 100 bytes .../mods/testnodes/textures/testnodes_6g.png | Bin 0 -> 98 bytes .../mods/testnodes/textures/testnodes_6w.png | Bin 0 -> 117 bytes .../mods/testnodes/textures/testnodes_6wg.png | Bin 0 -> 117 bytes .../mods/testnodes/textures/testnodes_airlike.png | Bin 0 -> 92 bytes .../mods/testnodes/textures/testnodes_allfaces.png | Bin 0 -> 150 bytes .../textures/testnodes_allfaces_optional.png | Bin 0 -> 150 bytes .../mods/testnodes/textures/testnodes_alpha.png | Bin 0 -> 96 bytes .../mods/testnodes/textures/testnodes_alpha128.png | Bin 0 -> 136 bytes .../mods/testnodes/textures/testnodes_alpha191.png | Bin 0 -> 132 bytes .../mods/testnodes/textures/testnodes_alpha64.png | Bin 0 -> 134 bytes .../mods/testnodes/textures/testnodes_anim.png | Bin 0 -> 274 bytes .../textures/testnodes_attached_bottom.png | Bin 0 -> 86 bytes .../testnodes/textures/testnodes_attached_side.png | Bin 0 -> 98 bytes .../testnodes/textures/testnodes_attached_top.png | Bin 0 -> 87 bytes .../textures/testnodes_attachedw_bottom.png | Bin 0 -> 130 bytes .../textures/testnodes_attachedw_side.png | Bin 0 -> 122 bytes .../testnodes/textures/testnodes_attachedw_top.png | Bin 0 -> 109 bytes .../mods/testnodes/textures/testnodes_bouncy.png | Bin 0 -> 106 bytes .../testnodes/textures/testnodes_buildable_to.png | Bin 0 -> 89 bytes .../textures/testnodes_climbable_nojump_side.png | Bin 0 -> 164 bytes .../textures/testnodes_climbable_side.png | Bin 0 -> 150 bytes .../mods/testnodes/textures/testnodes_damage.png | Bin 0 -> 108 bytes .../testnodes/textures/testnodes_damage_neg.png | Bin 0 -> 121 bytes .../mods/testnodes/textures/testnodes_drowning.png | Bin 0 -> 127 bytes .../textures/testnodes_fall_damage_minus.png | Bin 0 -> 116 bytes .../textures/testnodes_fall_damage_plus.png | Bin 0 -> 117 bytes .../testnodes/textures/testnodes_fencelike.png | Bin 0 -> 90 bytes .../mods/testnodes/textures/testnodes_firelike.png | Bin 0 -> 149 bytes .../testnodes/textures/testnodes_glasslike.png | Bin 0 -> 117 bytes .../textures/testnodes_glasslike_detail.png | Bin 0 -> 167 bytes .../textures/testnodes_glasslike_framed.png | Bin 0 -> 88 bytes .../textures/testnodes_glasslike_framed2.png | Bin 0 -> 118 bytes .../testnodes_glasslike_framed_optional.png | Bin 0 -> 128 bytes .../textures/testnodes_glasslikeliquid.png | Bin 0 -> 122 bytes .../mods/testnodes/textures/testnodes_light.png | Bin 0 -> 117 bytes .../mods/testnodes/textures/testnodes_light_1.png | Bin 0 -> 158 bytes .../mods/testnodes/textures/testnodes_light_10.png | Bin 0 -> 147 bytes .../mods/testnodes/textures/testnodes_light_11.png | Bin 0 -> 149 bytes .../mods/testnodes/textures/testnodes_light_12.png | Bin 0 -> 138 bytes .../mods/testnodes/textures/testnodes_light_13.png | Bin 0 -> 137 bytes .../mods/testnodes/textures/testnodes_light_14.png | Bin 0 -> 132 bytes .../mods/testnodes/textures/testnodes_light_2.png | Bin 0 -> 152 bytes .../mods/testnodes/textures/testnodes_light_3.png | Bin 0 -> 150 bytes .../mods/testnodes/textures/testnodes_light_4.png | Bin 0 -> 157 bytes .../mods/testnodes/textures/testnodes_light_5.png | Bin 0 -> 150 bytes .../mods/testnodes/textures/testnodes_light_6.png | Bin 0 -> 154 bytes .../mods/testnodes/textures/testnodes_light_7.png | Bin 0 -> 146 bytes .../mods/testnodes/textures/testnodes_light_8.png | Bin 0 -> 139 bytes .../mods/testnodes/textures/testnodes_light_9.png | Bin 0 -> 149 bytes .../testnodes/textures/testnodes_line_crossing.png | Bin 0 -> 130 bytes .../testnodes/textures/testnodes_line_curved.png | Bin 0 -> 123 bytes .../testnodes/textures/testnodes_line_straight.png | Bin 0 -> 115 bytes .../textures/testnodes_line_t_junction.png | Bin 0 -> 128 bytes .../mods/testnodes/textures/testnodes_liquid.png | Bin 0 -> 95 bytes .../testnodes/textures/testnodes_liquidflowing.png | Bin 0 -> 132 bytes .../textures/testnodes_liquidflowing_r0.png | Bin 0 -> 162 bytes .../textures/testnodes_liquidflowing_r1.png | Bin 0 -> 160 bytes .../textures/testnodes_liquidflowing_r2.png | Bin 0 -> 154 bytes .../textures/testnodes_liquidflowing_r3.png | Bin 0 -> 155 bytes .../textures/testnodes_liquidflowing_r4.png | Bin 0 -> 154 bytes .../textures/testnodes_liquidflowing_r5.png | Bin 0 -> 155 bytes .../textures/testnodes_liquidflowing_r6.png | Bin 0 -> 155 bytes .../textures/testnodes_liquidflowing_r7.png | Bin 0 -> 157 bytes .../textures/testnodes_liquidflowing_r8.png | Bin 0 -> 152 bytes .../testnodes/textures/testnodes_liquidsource.png | Bin 0 -> 128 bytes .../textures/testnodes_liquidsource_r0.png | Bin 0 -> 149 bytes .../textures/testnodes_liquidsource_r1.png | Bin 0 -> 152 bytes .../textures/testnodes_liquidsource_r2.png | Bin 0 -> 152 bytes .../textures/testnodes_liquidsource_r3.png | Bin 0 -> 152 bytes .../textures/testnodes_liquidsource_r4.png | Bin 0 -> 155 bytes .../textures/testnodes_liquidsource_r5.png | Bin 0 -> 150 bytes .../textures/testnodes_liquidsource_r6.png | Bin 0 -> 148 bytes .../textures/testnodes_liquidsource_r7.png | Bin 0 -> 154 bytes .../textures/testnodes_liquidsource_r8.png | Bin 0 -> 148 bytes .../testnodes/textures/testnodes_mesh_stripes.png | Bin 0 -> 150 bytes .../testnodes/textures/testnodes_mesh_stripes2.png | Bin 0 -> 144 bytes .../testnodes/textures/testnodes_mesh_stripes3.png | Bin 0 -> 85 bytes .../testnodes/textures/testnodes_mesh_stripes4.png | Bin 0 -> 93 bytes .../mods/testnodes/textures/testnodes_node.png | Bin 0 -> 89 bytes .../testnodes/textures/testnodes_node_falling.png | Bin 0 -> 112 bytes .../mods/testnodes/textures/testnodes_nodebox.png | Bin 0 -> 112 bytes .../testnodes/textures/testnodes_nojump_side.png | Bin 0 -> 94 bytes .../testnodes/textures/testnodes_nojump_top.png | Bin 0 -> 121 bytes .../mods/testnodes/textures/testnodes_normal.png | Bin 0 -> 92 bytes .../mods/testnodes/textures/testnodes_normal1.png | Bin 0 -> 114 bytes .../mods/testnodes/textures/testnodes_normal2.png | Bin 0 -> 122 bytes .../mods/testnodes/textures/testnodes_normal3.png | Bin 0 -> 114 bytes .../mods/testnodes/textures/testnodes_normal4.png | Bin 0 -> 106 bytes .../mods/testnodes/textures/testnodes_normal5.png | Bin 0 -> 109 bytes .../mods/testnodes/textures/testnodes_normal6.png | Bin 0 -> 111 bytes .../textures/testnodes_palette_facedir.png | Bin 0 -> 87 bytes .../testnodes/textures/testnodes_palette_full.png | Bin 0 -> 568 bytes .../textures/testnodes_palette_wallmounted.png | Bin 0 -> 136 bytes .../testnodes/textures/testnodes_plantlike.png | Bin 0 -> 183 bytes .../textures/testnodes_plantlike_degrotate.png | Bin 0 -> 176 bytes .../textures/testnodes_plantlike_leveled.png | Bin 0 -> 163 bytes .../textures/testnodes_plantlike_meshoptions.png | Bin 0 -> 164 bytes .../textures/testnodes_plantlike_rooted.png | Bin 0 -> 182 bytes .../textures/testnodes_plantlike_rooted_base.png | Bin 0 -> 101 bytes ...tnodes_plantlike_rooted_base_side_degrotate.png | Bin 0 -> 145 bytes ...estnodes_plantlike_rooted_base_side_leveled.png | Bin 0 -> 127 bytes ...odes_plantlike_rooted_base_side_meshoptions.png | Bin 0 -> 128 bytes ...testnodes_plantlike_rooted_base_side_waving.png | Bin 0 -> 126 bytes .../testnodes_plantlike_rooted_degrotate.png | Bin 0 -> 176 bytes .../testnodes_plantlike_rooted_leveled.png | Bin 0 -> 162 bytes .../testnodes_plantlike_rooted_meshoptions.png | Bin 0 -> 162 bytes .../textures/testnodes_plantlike_rooted_waving.png | Bin 0 -> 125 bytes .../textures/testnodes_plantlike_waving.png | Bin 0 -> 127 bytes .../textures/testnodes_rail2_crossing.png | Bin 0 -> 246 bytes .../testnodes/textures/testnodes_rail2_curved.png | Bin 0 -> 253 bytes .../textures/testnodes_rail2_straight.png | Bin 0 -> 246 bytes .../textures/testnodes_rail2_t_junction.png | Bin 0 -> 254 bytes .../testnodes/textures/testnodes_rail_crossing.png | Bin 0 -> 151 bytes .../testnodes/textures/testnodes_rail_curved.png | Bin 0 -> 164 bytes .../testnodes/textures/testnodes_rail_straight.png | Bin 0 -> 133 bytes .../textures/testnodes_rail_t_junction.png | Bin 0 -> 202 bytes .../mods/testnodes/textures/testnodes_signlike.png | Bin 0 -> 150 bytes .../mods/testnodes/textures/testnodes_slippery.png | Bin 0 -> 111 bytes .../textures/testnodes_street_crossing.png | Bin 0 -> 137 bytes .../testnodes/textures/testnodes_street_curved.png | Bin 0 -> 115 bytes .../textures/testnodes_street_straight.png | Bin 0 -> 101 bytes .../textures/testnodes_street_t_junction.png | Bin 0 -> 126 bytes .../textures/testnodes_sunlight_filter.png | Bin 0 -> 113 bytes .../textures/testnodes_torchlike_ceiling.png | Bin 0 -> 157 bytes .../textures/testnodes_torchlike_floor.png | Bin 0 -> 141 bytes .../textures/testnodes_torchlike_wall.png | Bin 0 -> 158 bytes games/devtest/mods/testpathfinder/README.md | 15 + games/devtest/mods/testpathfinder/init.lua | 132 ++++ games/devtest/mods/testpathfinder/mod.conf | 2 + .../textures/testpathfinder_testpathfinder.png | Bin 0 -> 159 bytes .../textures/testpathfinder_waypoint.png | Bin 0 -> 99 bytes .../textures/testpathfinder_waypoint_end.png | Bin 0 -> 147 bytes .../textures/testpathfinder_waypoint_start.png | Bin 0 -> 139 bytes games/devtest/mods/testtools/README.md | 99 +++ games/devtest/mods/testtools/init.lua | 691 +++++++++++++++++++++ games/devtest/mods/testtools/mod.conf | 2 + .../textures/testtools_entity_rotator.png | Bin 0 -> 151 bytes .../testtools/textures/testtools_entity_scaler.png | Bin 0 -> 182 bytes .../textures/testtools_entity_spawner.png | Bin 0 -> 189 bytes .../textures/testtools_falling_node_tool.png | Bin 0 -> 140 bytes .../testtools/textures/testtools_node_setter.png | Bin 0 -> 146 bytes .../textures/testtools_object_attacher.png | Bin 0 -> 173 bytes .../testtools/textures/testtools_object_editor.png | Bin 0 -> 180 bytes .../testtools/textures/testtools_object_mover.png | Bin 0 -> 175 bytes .../testtools/textures/testtools_param2tool.png | Bin 0 -> 127 bytes .../mods/testtools/textures/testtools_remover.png | Bin 0 -> 129 bytes games/devtest/mods/tiled/init.lua | 33 + games/devtest/mods/tiled/mod.conf | 3 + games/devtest/mods/tiled/textures/tiled_tiled.png | Bin 0 -> 410 bytes games/devtest/mods/unittests/crafting.lua | 120 ++++ games/devtest/mods/unittests/crafting_prepare.lua | 88 +++ games/devtest/mods/unittests/init.lua | 16 + games/devtest/mods/unittests/mod.conf | 2 + games/devtest/mods/unittests/player.lua | 73 +++ games/devtest/mods/unittests/random.lua | 10 + .../unittests/textures/unittests_coal_lump.png | Bin 0 -> 160 bytes .../unittests/textures/unittests_iron_lump.png | Bin 0 -> 154 bytes .../textures/unittests_repairable_tool.png | Bin 0 -> 160 bytes .../unittests/textures/unittests_steel_ingot.png | Bin 0 -> 159 bytes .../mods/unittests/textures/unittests_stick.png | Bin 0 -> 147 bytes .../mods/unittests/textures/unittests_torch.png | Bin 0 -> 155 bytes .../textures/unittests_unrepairable_tool.png | Bin 0 -> 157 bytes games/devtest/mods/util_commands/init.lua | 137 ++++ games/devtest/mods/util_commands/mod.conf | 2 + games/devtest/screenshot.png | Bin 0 -> 133364 bytes games/devtest/settingtypes.txt | 37 ++ games/minimal/LICENSE.txt | 4 - games/minimal/README.md | 52 -- games/minimal/game.conf | 2 - games/minimal/menu/background.png | Bin 152 -> 0 bytes games/minimal/menu/header.png | Bin 210 -> 0 bytes games/minimal/menu/icon.png | Bin 217 -> 0 bytes games/minimal/mods/basenodes/init.lua | 334 ---------- games/minimal/mods/basenodes/mod.conf | 2 - .../textures/basenodes_dirt_with_grass_bottom.png | Bin 187 -> 0 bytes .../textures/basenodes_dirt_with_snow.png | Bin 166 -> 0 bytes .../textures/basenodes_dirt_with_snow_bottom.png | Bin 177 -> 0 bytes .../basenodes/textures/basenodes_snow_sheet.png | Bin 166 -> 0 bytes .../mods/basenodes/textures/default_apple.png | Bin 102 -> 0 bytes .../mods/basenodes/textures/default_cobble.png | Bin 340 -> 0 bytes .../basenodes/textures/default_desert_sand.png | Bin 293 -> 0 bytes .../basenodes/textures/default_desert_stone.png | Bin 584 -> 0 bytes .../mods/basenodes/textures/default_dirt.png | Bin 790 -> 0 bytes .../mods/basenodes/textures/default_grass.png | Bin 697 -> 0 bytes .../mods/basenodes/textures/default_grass_side.png | Bin 796 -> 0 bytes .../mods/basenodes/textures/default_gravel.png | Bin 171 -> 0 bytes .../mods/basenodes/textures/default_ice.png | Bin 369 -> 0 bytes .../basenodes/textures/default_junglegrass.png | Bin 201 -> 0 bytes .../basenodes/textures/default_jungleleaves.png | Bin 399 -> 0 bytes .../mods/basenodes/textures/default_jungletree.png | Bin 730 -> 0 bytes .../basenodes/textures/default_jungletree_top.png | Bin 714 -> 0 bytes .../mods/basenodes/textures/default_lava.png | Bin 172 -> 0 bytes .../basenodes/textures/default_lava_flowing.png | Bin 91 -> 0 bytes .../mods/basenodes/textures/default_leaves.png | Bin 883 -> 0 bytes .../basenodes/textures/default_mossycobble.png | Bin 574 -> 0 bytes .../basenodes/textures/default_pine_needles.png | Bin 648 -> 0 bytes .../mods/basenodes/textures/default_pine_tree.png | Bin 604 -> 0 bytes .../basenodes/textures/default_pine_tree_top.png | Bin 174 -> 0 bytes .../basenodes/textures/default_river_water.png | Bin 496 -> 0 bytes .../textures/default_river_water_flowing.png | Bin 99 -> 0 bytes .../mods/basenodes/textures/default_sand.png | Bin 554 -> 0 bytes .../mods/basenodes/textures/default_snow.png | Bin 166 -> 0 bytes .../mods/basenodes/textures/default_snow_side.png | Bin 152 -> 0 bytes .../mods/basenodes/textures/default_stone.png | Bin 313 -> 0 bytes .../mods/basenodes/textures/default_tree.png | Bin 659 -> 0 bytes .../mods/basenodes/textures/default_tree_top.png | Bin 175 -> 0 bytes .../mods/basenodes/textures/default_water.png | Bin 302 -> 0 bytes .../basenodes/textures/default_water_flowing.png | Bin 115 -> 0 bytes games/minimal/mods/basetools/init.lua | 295 --------- games/minimal/mods/basetools/mod.conf | 2 - .../mods/basetools/textures/basetools_dirtpick.png | Bin 307 -> 0 bytes .../basetools/textures/basetools_firesword.png | Bin 190 -> 0 bytes .../mods/basetools/textures/basetools_icesword.png | Bin 190 -> 0 bytes .../mods/basetools/textures/basetools_mesepick.png | Bin 155 -> 0 bytes .../mods/basetools/textures/basetools_steelaxe.png | Bin 131 -> 0 bytes .../basetools/textures/basetools_steeldagger.png | Bin 154 -> 0 bytes .../basetools/textures/basetools_steelpick.png | Bin 159 -> 0 bytes .../basetools/textures/basetools_steelpick_l1.png | Bin 190 -> 0 bytes .../basetools/textures/basetools_steelpick_l2.png | Bin 177 -> 0 bytes .../basetools/textures/basetools_steelshears.png | Bin 208 -> 0 bytes .../basetools/textures/basetools_steelshovel.png | Bin 140 -> 0 bytes .../basetools/textures/basetools_steelsword.png | Bin 163 -> 0 bytes .../mods/basetools/textures/basetools_stoneaxe.png | Bin 130 -> 0 bytes .../basetools/textures/basetools_stonepick.png | Bin 155 -> 0 bytes .../basetools/textures/basetools_stoneshears.png | Bin 224 -> 0 bytes .../basetools/textures/basetools_stoneshovel.png | Bin 134 -> 0 bytes .../basetools/textures/basetools_stonesword.png | Bin 159 -> 0 bytes .../mods/basetools/textures/basetools_woodaxe.png | Bin 121 -> 0 bytes .../mods/basetools/textures/basetools_woodpick.png | Bin 149 -> 0 bytes .../basetools/textures/basetools_woodshears.png | Bin 212 -> 0 bytes .../basetools/textures/basetools_woodshovel.png | Bin 133 -> 0 bytes .../basetools/textures/basetools_woodsword.png | Bin 139 -> 0 bytes games/minimal/mods/bucket/init.lua | 26 - games/minimal/mods/bucket/mod.conf | 2 - games/minimal/mods/bucket/textures/bucket.png | Bin 163 -> 0 bytes games/minimal/mods/bucket/textures/bucket_lava.png | Bin 168 -> 0 bytes .../minimal/mods/bucket/textures/bucket_water.png | Bin 168 -> 0 bytes games/minimal/mods/chest/init.lua | 27 - games/minimal/mods/chest/mod.conf | 2 - games/minimal/mods/chest/textures/chest_chest.png | Bin 163 -> 0 bytes games/minimal/mods/chest_of_everything/init.lua | 135 ---- games/minimal/mods/chest_of_everything/mod.conf | 2 - .../textures/chest_of_everything_chest.png | Bin 210 -> 0 bytes games/minimal/mods/dignodes/init.lua | 37 -- games/minimal/mods/dignodes/mod.conf | 2 - .../mods/dignodes/textures/dignodes_choppy.png | Bin 187 -> 0 bytes .../mods/dignodes/textures/dignodes_cracky.png | Bin 193 -> 0 bytes .../mods/dignodes/textures/dignodes_crumbly.png | Bin 172 -> 0 bytes .../dignodes/textures/dignodes_dig_immediate.png | Bin 170 -> 0 bytes .../mods/dignodes/textures/dignodes_none.png | Bin 201 -> 0 bytes .../mods/dignodes/textures/dignodes_rating1.png | Bin 94 -> 0 bytes .../mods/dignodes/textures/dignodes_rating2.png | Bin 92 -> 0 bytes .../mods/dignodes/textures/dignodes_rating3.png | Bin 93 -> 0 bytes games/minimal/mods/experimental/commands.lua | 215 ------- games/minimal/mods/experimental/detached.lua | 29 - games/minimal/mods/experimental/init.lua | 23 - games/minimal/mods/experimental/items.lua | 103 --- games/minimal/mods/experimental/mod.conf | 2 - .../textures/experimental_callback_node.png | Bin 139 -> 0 bytes .../textures/experimental_particle_sheet.png | Bin 208 -> 0 bytes .../textures/experimental_particle_vertical.png | Bin 308 -> 0 bytes .../textures/experimental_tester_tool_1.png | Bin 138 -> 0 bytes games/minimal/mods/give_initial_stuff/init.lua | 37 -- games/minimal/mods/give_initial_stuff/mod.conf | 3 - games/minimal/mods/initial_message/init.lua | 9 - games/minimal/mods/initial_message/mod.conf | 2 - games/minimal/mods/mapgen/init.lua | 81 --- games/minimal/mods/mapgen/mod.conf | 3 - games/minimal/mods/modchannels/init.lua | 14 - games/minimal/mods/modchannels/mod.conf | 2 - games/minimal/mods/soundstuff/init.lua | 170 ----- games/minimal/mods/soundstuff/mod.conf | 2 - .../mods/soundstuff/sounds/soundstuff_mono.ogg | Bin 4362 -> 0 bytes .../mods/soundstuff/textures/soundstuff_eat.png | Bin 113 -> 0 bytes .../soundstuff/textures/soundstuff_node_blank.png | Bin 83 -> 0 bytes .../textures/soundstuff_node_climbable.png | Bin 189 -> 0 bytes .../soundstuff/textures/soundstuff_node_dig.png | Bin 126 -> 0 bytes .../soundstuff/textures/soundstuff_node_dug.png | Bin 132 -> 0 bytes .../soundstuff/textures/soundstuff_node_fall.png | Bin 100 -> 0 bytes .../textures/soundstuff_node_footstep.png | Bin 120 -> 0 bytes .../soundstuff/textures/soundstuff_node_place.png | Bin 115 -> 0 bytes .../textures/soundstuff_node_place_failed.png | Bin 143 -> 0 bytes .../soundstuff/textures/soundstuff_node_sound.png | Bin 116 -> 0 bytes games/minimal/mods/stairs/init.lua | 65 -- games/minimal/mods/stairs/mod.conf | 3 - games/minimal/mods/testentities/armor.lua | 41 -- games/minimal/mods/testentities/callbacks.lua | 75 --- games/minimal/mods/testentities/init.lua | 3 - games/minimal/mods/testentities/mod.conf | 2 - .../textures/testentities_armorball.png | Bin 561 -> 0 bytes .../textures/testentities_callback.png | Bin 156 -> 0 bytes .../textures/testentities_callback_step.png | Bin 166 -> 0 bytes .../testentities/textures/testentities_cube1.png | Bin 130 -> 0 bytes .../testentities/textures/testentities_cube2.png | Bin 128 -> 0 bytes .../testentities/textures/testentities_cube3.png | Bin 124 -> 0 bytes .../testentities/textures/testentities_cube4.png | Bin 126 -> 0 bytes .../testentities/textures/testentities_cube5.png | Bin 126 -> 0 bytes .../testentities/textures/testentities_cube6.png | Bin 126 -> 0 bytes .../textures/testentities_dungeon_master.png | Bin 2855 -> 0 bytes .../testentities/textures/testentities_sprite.png | Bin 120 -> 0 bytes .../textures/testentities_upright_sprite1.png | Bin 114 -> 0 bytes .../textures/testentities_upright_sprite2.png | Bin 119 -> 0 bytes games/minimal/mods/testentities/visuals.lua | 74 --- games/minimal/mods/testfood/init.lua | 24 - games/minimal/mods/testfood/mod.conf | 2 - .../mods/testfood/textures/testfood_bad.png | Bin 126 -> 0 bytes .../mods/testfood/textures/testfood_bad2.png | Bin 133 -> 0 bytes .../mods/testfood/textures/testfood_good.png | Bin 129 -> 0 bytes .../mods/testfood/textures/testfood_good2.png | Bin 145 -> 0 bytes games/minimal/mods/testformspec/callbacks.lua | 51 -- games/minimal/mods/testformspec/dummy_items.lua | 14 - games/minimal/mods/testformspec/formspec.lua | 381 ------------ games/minimal/mods/testformspec/init.lua | 3 - games/minimal/mods/testformspec/mod.conf | 2 - .../textures/testformspec_animation.jpg | Bin 4376 -> 0 bytes .../textures/testformspec_animation.png | Bin 214 -> 0 bytes .../mods/testformspec/textures/testformspec_bg.png | Bin 92 -> 0 bytes .../textures/testformspec_bg_9slice.png | Bin 146 -> 0 bytes .../textures/testformspec_bg_9slice_hovered.png | Bin 146 -> 0 bytes .../textures/testformspec_bg_9slice_pressed.png | Bin 146 -> 0 bytes .../textures/testformspec_bg_hovered.png | Bin 92 -> 0 bytes .../textures/testformspec_bg_pressed.png | Bin 91 -> 0 bytes .../textures/testformspec_button_image.png | Bin 146 -> 0 bytes .../testformspec/textures/testformspec_hovered.png | Bin 195 -> 0 bytes .../testformspec/textures/testformspec_item.png | Bin 182 -> 0 bytes .../testformspec/textures/testformspec_node.png | Bin 113 -> 0 bytes .../testformspec/textures/testformspec_pressed.png | Bin 165 -> 0 bytes games/minimal/mods/testnodes/README.md | 11 - games/minimal/mods/testnodes/drawtypes.lua | 517 --------------- games/minimal/mods/testnodes/init.lua | 10 - games/minimal/mods/testnodes/light.lua | 48 -- games/minimal/mods/testnodes/liquids.lua | 91 --- games/minimal/mods/testnodes/meshes.lua | 145 ----- games/minimal/mods/testnodes/mod.conf | 2 - .../mods/testnodes/models/testnodes_ocorner.obj | 23 - .../mods/testnodes/models/testnodes_pyramid.obj | 24 - games/minimal/mods/testnodes/nodeboxes.lua | 80 --- games/minimal/mods/testnodes/param2.lua | 168 ----- games/minimal/mods/testnodes/properties.lua | 270 -------- games/minimal/mods/testnodes/settingtypes.txt | 4 - games/minimal/mods/testnodes/textures.lua | 67 -- .../mods/testnodes/textures/testnodes_1.png | Bin 107 -> 0 bytes .../mods/testnodes/textures/testnodes_1g.png | Bin 104 -> 0 bytes .../mods/testnodes/textures/testnodes_1w.png | Bin 121 -> 0 bytes .../mods/testnodes/textures/testnodes_1wg.png | Bin 122 -> 0 bytes .../mods/testnodes/textures/testnodes_2.png | Bin 112 -> 0 bytes .../mods/testnodes/textures/testnodes_2g.png | Bin 110 -> 0 bytes .../mods/testnodes/textures/testnodes_2w.png | Bin 134 -> 0 bytes .../mods/testnodes/textures/testnodes_2wg.png | Bin 135 -> 0 bytes .../mods/testnodes/textures/testnodes_3.png | Bin 105 -> 0 bytes .../mods/testnodes/textures/testnodes_3g.png | Bin 103 -> 0 bytes .../mods/testnodes/textures/testnodes_3w.png | Bin 112 -> 0 bytes .../mods/testnodes/textures/testnodes_3wg.png | Bin 112 -> 0 bytes .../mods/testnodes/textures/testnodes_4.png | Bin 97 -> 0 bytes .../mods/testnodes/textures/testnodes_4g.png | Bin 95 -> 0 bytes .../mods/testnodes/textures/testnodes_4w.png | Bin 128 -> 0 bytes .../mods/testnodes/textures/testnodes_4wg.png | Bin 128 -> 0 bytes .../mods/testnodes/textures/testnodes_5.png | Bin 98 -> 0 bytes .../mods/testnodes/textures/testnodes_5g.png | Bin 98 -> 0 bytes .../mods/testnodes/textures/testnodes_5w.png | Bin 117 -> 0 bytes .../mods/testnodes/textures/testnodes_5wg.png | Bin 117 -> 0 bytes .../mods/testnodes/textures/testnodes_6.png | Bin 100 -> 0 bytes .../mods/testnodes/textures/testnodes_6g.png | Bin 98 -> 0 bytes .../mods/testnodes/textures/testnodes_6w.png | Bin 117 -> 0 bytes .../mods/testnodes/textures/testnodes_6wg.png | Bin 117 -> 0 bytes .../mods/testnodes/textures/testnodes_airlike.png | Bin 92 -> 0 bytes .../mods/testnodes/textures/testnodes_allfaces.png | Bin 150 -> 0 bytes .../textures/testnodes_allfaces_optional.png | Bin 150 -> 0 bytes .../mods/testnodes/textures/testnodes_alpha.png | Bin 96 -> 0 bytes .../mods/testnodes/textures/testnodes_alpha128.png | Bin 136 -> 0 bytes .../mods/testnodes/textures/testnodes_alpha191.png | Bin 132 -> 0 bytes .../mods/testnodes/textures/testnodes_alpha64.png | Bin 134 -> 0 bytes .../mods/testnodes/textures/testnodes_anim.png | Bin 274 -> 0 bytes .../textures/testnodes_attached_bottom.png | Bin 86 -> 0 bytes .../testnodes/textures/testnodes_attached_side.png | Bin 98 -> 0 bytes .../testnodes/textures/testnodes_attached_top.png | Bin 87 -> 0 bytes .../textures/testnodes_attachedw_bottom.png | Bin 130 -> 0 bytes .../textures/testnodes_attachedw_side.png | Bin 122 -> 0 bytes .../testnodes/textures/testnodes_attachedw_top.png | Bin 109 -> 0 bytes .../mods/testnodes/textures/testnodes_bouncy.png | Bin 106 -> 0 bytes .../testnodes/textures/testnodes_buildable_to.png | Bin 89 -> 0 bytes .../textures/testnodes_climbable_nojump_side.png | Bin 164 -> 0 bytes .../textures/testnodes_climbable_side.png | Bin 150 -> 0 bytes .../mods/testnodes/textures/testnodes_damage.png | Bin 108 -> 0 bytes .../testnodes/textures/testnodes_damage_neg.png | Bin 121 -> 0 bytes .../mods/testnodes/textures/testnodes_drowning.png | Bin 127 -> 0 bytes .../textures/testnodes_fall_damage_minus.png | Bin 116 -> 0 bytes .../textures/testnodes_fall_damage_plus.png | Bin 117 -> 0 bytes .../testnodes/textures/testnodes_fencelike.png | Bin 90 -> 0 bytes .../mods/testnodes/textures/testnodes_firelike.png | Bin 149 -> 0 bytes .../testnodes/textures/testnodes_glasslike.png | Bin 117 -> 0 bytes .../textures/testnodes_glasslike_detail.png | Bin 167 -> 0 bytes .../textures/testnodes_glasslike_framed.png | Bin 88 -> 0 bytes .../textures/testnodes_glasslike_framed2.png | Bin 118 -> 0 bytes .../testnodes_glasslike_framed_optional.png | Bin 128 -> 0 bytes .../textures/testnodes_glasslikeliquid.png | Bin 122 -> 0 bytes .../mods/testnodes/textures/testnodes_light.png | Bin 117 -> 0 bytes .../mods/testnodes/textures/testnodes_light_1.png | Bin 158 -> 0 bytes .../mods/testnodes/textures/testnodes_light_10.png | Bin 147 -> 0 bytes .../mods/testnodes/textures/testnodes_light_11.png | Bin 149 -> 0 bytes .../mods/testnodes/textures/testnodes_light_12.png | Bin 138 -> 0 bytes .../mods/testnodes/textures/testnodes_light_13.png | Bin 137 -> 0 bytes .../mods/testnodes/textures/testnodes_light_14.png | Bin 132 -> 0 bytes .../mods/testnodes/textures/testnodes_light_2.png | Bin 152 -> 0 bytes .../mods/testnodes/textures/testnodes_light_3.png | Bin 150 -> 0 bytes .../mods/testnodes/textures/testnodes_light_4.png | Bin 157 -> 0 bytes .../mods/testnodes/textures/testnodes_light_5.png | Bin 150 -> 0 bytes .../mods/testnodes/textures/testnodes_light_6.png | Bin 154 -> 0 bytes .../mods/testnodes/textures/testnodes_light_7.png | Bin 146 -> 0 bytes .../mods/testnodes/textures/testnodes_light_8.png | Bin 139 -> 0 bytes .../mods/testnodes/textures/testnodes_light_9.png | Bin 149 -> 0 bytes .../testnodes/textures/testnodes_line_crossing.png | Bin 130 -> 0 bytes .../testnodes/textures/testnodes_line_curved.png | Bin 123 -> 0 bytes .../testnodes/textures/testnodes_line_straight.png | Bin 115 -> 0 bytes .../textures/testnodes_line_t_junction.png | Bin 128 -> 0 bytes .../mods/testnodes/textures/testnodes_liquid.png | Bin 95 -> 0 bytes .../testnodes/textures/testnodes_liquidflowing.png | Bin 132 -> 0 bytes .../textures/testnodes_liquidflowing_r0.png | Bin 162 -> 0 bytes .../textures/testnodes_liquidflowing_r1.png | Bin 160 -> 0 bytes .../textures/testnodes_liquidflowing_r2.png | Bin 154 -> 0 bytes .../textures/testnodes_liquidflowing_r3.png | Bin 155 -> 0 bytes .../textures/testnodes_liquidflowing_r4.png | Bin 154 -> 0 bytes .../textures/testnodes_liquidflowing_r5.png | Bin 155 -> 0 bytes .../textures/testnodes_liquidflowing_r6.png | Bin 155 -> 0 bytes .../textures/testnodes_liquidflowing_r7.png | Bin 157 -> 0 bytes .../textures/testnodes_liquidflowing_r8.png | Bin 152 -> 0 bytes .../testnodes/textures/testnodes_liquidsource.png | Bin 128 -> 0 bytes .../textures/testnodes_liquidsource_r0.png | Bin 149 -> 0 bytes .../textures/testnodes_liquidsource_r1.png | Bin 152 -> 0 bytes .../textures/testnodes_liquidsource_r2.png | Bin 152 -> 0 bytes .../textures/testnodes_liquidsource_r3.png | Bin 152 -> 0 bytes .../textures/testnodes_liquidsource_r4.png | Bin 155 -> 0 bytes .../textures/testnodes_liquidsource_r5.png | Bin 150 -> 0 bytes .../textures/testnodes_liquidsource_r6.png | Bin 148 -> 0 bytes .../textures/testnodes_liquidsource_r7.png | Bin 154 -> 0 bytes .../textures/testnodes_liquidsource_r8.png | Bin 148 -> 0 bytes .../testnodes/textures/testnodes_mesh_stripes.png | Bin 150 -> 0 bytes .../testnodes/textures/testnodes_mesh_stripes2.png | Bin 144 -> 0 bytes .../testnodes/textures/testnodes_mesh_stripes3.png | Bin 85 -> 0 bytes .../testnodes/textures/testnodes_mesh_stripes4.png | Bin 93 -> 0 bytes .../mods/testnodes/textures/testnodes_node.png | Bin 89 -> 0 bytes .../testnodes/textures/testnodes_node_falling.png | Bin 112 -> 0 bytes .../mods/testnodes/textures/testnodes_nodebox.png | Bin 112 -> 0 bytes .../testnodes/textures/testnodes_nojump_side.png | Bin 94 -> 0 bytes .../testnodes/textures/testnodes_nojump_top.png | Bin 121 -> 0 bytes .../mods/testnodes/textures/testnodes_normal.png | Bin 92 -> 0 bytes .../mods/testnodes/textures/testnodes_normal1.png | Bin 114 -> 0 bytes .../mods/testnodes/textures/testnodes_normal2.png | Bin 122 -> 0 bytes .../mods/testnodes/textures/testnodes_normal3.png | Bin 114 -> 0 bytes .../mods/testnodes/textures/testnodes_normal4.png | Bin 106 -> 0 bytes .../mods/testnodes/textures/testnodes_normal5.png | Bin 109 -> 0 bytes .../mods/testnodes/textures/testnodes_normal6.png | Bin 111 -> 0 bytes .../textures/testnodes_palette_facedir.png | Bin 87 -> 0 bytes .../testnodes/textures/testnodes_palette_full.png | Bin 568 -> 0 bytes .../textures/testnodes_palette_wallmounted.png | Bin 136 -> 0 bytes .../testnodes/textures/testnodes_plantlike.png | Bin 183 -> 0 bytes .../textures/testnodes_plantlike_degrotate.png | Bin 176 -> 0 bytes .../textures/testnodes_plantlike_leveled.png | Bin 163 -> 0 bytes .../textures/testnodes_plantlike_meshoptions.png | Bin 164 -> 0 bytes .../textures/testnodes_plantlike_rooted.png | Bin 182 -> 0 bytes .../textures/testnodes_plantlike_rooted_base.png | Bin 101 -> 0 bytes ...tnodes_plantlike_rooted_base_side_degrotate.png | Bin 145 -> 0 bytes ...estnodes_plantlike_rooted_base_side_leveled.png | Bin 127 -> 0 bytes ...odes_plantlike_rooted_base_side_meshoptions.png | Bin 128 -> 0 bytes ...testnodes_plantlike_rooted_base_side_waving.png | Bin 126 -> 0 bytes .../testnodes_plantlike_rooted_degrotate.png | Bin 176 -> 0 bytes .../testnodes_plantlike_rooted_leveled.png | Bin 162 -> 0 bytes .../testnodes_plantlike_rooted_meshoptions.png | Bin 162 -> 0 bytes .../textures/testnodes_plantlike_rooted_waving.png | Bin 125 -> 0 bytes .../textures/testnodes_plantlike_waving.png | Bin 127 -> 0 bytes .../textures/testnodes_rail2_crossing.png | Bin 246 -> 0 bytes .../testnodes/textures/testnodes_rail2_curved.png | Bin 253 -> 0 bytes .../textures/testnodes_rail2_straight.png | Bin 246 -> 0 bytes .../textures/testnodes_rail2_t_junction.png | Bin 254 -> 0 bytes .../testnodes/textures/testnodes_rail_crossing.png | Bin 151 -> 0 bytes .../testnodes/textures/testnodes_rail_curved.png | Bin 164 -> 0 bytes .../testnodes/textures/testnodes_rail_straight.png | Bin 133 -> 0 bytes .../textures/testnodes_rail_t_junction.png | Bin 202 -> 0 bytes .../mods/testnodes/textures/testnodes_signlike.png | Bin 150 -> 0 bytes .../mods/testnodes/textures/testnodes_slippery.png | Bin 111 -> 0 bytes .../textures/testnodes_street_crossing.png | Bin 137 -> 0 bytes .../testnodes/textures/testnodes_street_curved.png | Bin 115 -> 0 bytes .../textures/testnodes_street_straight.png | Bin 101 -> 0 bytes .../textures/testnodes_street_t_junction.png | Bin 126 -> 0 bytes .../textures/testnodes_sunlight_filter.png | Bin 113 -> 0 bytes .../textures/testnodes_torchlike_ceiling.png | Bin 157 -> 0 bytes .../textures/testnodes_torchlike_floor.png | Bin 141 -> 0 bytes .../textures/testnodes_torchlike_wall.png | Bin 158 -> 0 bytes games/minimal/mods/testpathfinder/README.md | 15 - games/minimal/mods/testpathfinder/init.lua | 132 ---- games/minimal/mods/testpathfinder/mod.conf | 2 - .../textures/testpathfinder_testpathfinder.png | Bin 159 -> 0 bytes .../textures/testpathfinder_waypoint.png | Bin 99 -> 0 bytes .../textures/testpathfinder_waypoint_end.png | Bin 147 -> 0 bytes .../textures/testpathfinder_waypoint_start.png | Bin 139 -> 0 bytes games/minimal/mods/testtools/README.md | 99 --- games/minimal/mods/testtools/init.lua | 691 --------------------- games/minimal/mods/testtools/mod.conf | 2 - .../textures/testtools_entity_rotator.png | Bin 151 -> 0 bytes .../testtools/textures/testtools_entity_scaler.png | Bin 182 -> 0 bytes .../textures/testtools_entity_spawner.png | Bin 189 -> 0 bytes .../textures/testtools_falling_node_tool.png | Bin 140 -> 0 bytes .../testtools/textures/testtools_node_setter.png | Bin 146 -> 0 bytes .../textures/testtools_object_attacher.png | Bin 173 -> 0 bytes .../testtools/textures/testtools_object_editor.png | Bin 180 -> 0 bytes .../testtools/textures/testtools_object_mover.png | Bin 175 -> 0 bytes .../testtools/textures/testtools_param2tool.png | Bin 127 -> 0 bytes .../mods/testtools/textures/testtools_remover.png | Bin 129 -> 0 bytes games/minimal/mods/tiled/init.lua | 33 - games/minimal/mods/tiled/mod.conf | 3 - games/minimal/mods/tiled/textures/tiled_tiled.png | Bin 410 -> 0 bytes games/minimal/mods/unittests/crafting.lua | 120 ---- games/minimal/mods/unittests/crafting_prepare.lua | 88 --- games/minimal/mods/unittests/init.lua | 16 - games/minimal/mods/unittests/mod.conf | 2 - games/minimal/mods/unittests/player.lua | 73 --- games/minimal/mods/unittests/random.lua | 10 - .../unittests/textures/unittests_coal_lump.png | Bin 160 -> 0 bytes .../unittests/textures/unittests_iron_lump.png | Bin 154 -> 0 bytes .../textures/unittests_repairable_tool.png | Bin 160 -> 0 bytes .../unittests/textures/unittests_steel_ingot.png | Bin 159 -> 0 bytes .../mods/unittests/textures/unittests_stick.png | Bin 147 -> 0 bytes .../mods/unittests/textures/unittests_torch.png | Bin 155 -> 0 bytes .../textures/unittests_unrepairable_tool.png | Bin 157 -> 0 bytes games/minimal/mods/util_commands/init.lua | 137 ---- games/minimal/mods/util_commands/mod.conf | 2 - games/minimal/screenshot.png | Bin 133364 -> 0 bytes games/minimal/settingtypes.txt | 37 -- src/unittest/CMakeLists.txt | 2 +- src/unittest/test_servermodmanager.cpp | 10 +- util/test_multiplayer.sh | 2 +- 731 files changed, 5299 insertions(+), 5299 deletions(-) create mode 100644 games/devtest/LICENSE.txt create mode 100644 games/devtest/README.md create mode 100644 games/devtest/game.conf create mode 100644 games/devtest/menu/background.png create mode 100644 games/devtest/menu/header.png create mode 100644 games/devtest/menu/icon.png create mode 100644 games/devtest/mods/basenodes/init.lua create mode 100644 games/devtest/mods/basenodes/mod.conf create mode 100644 games/devtest/mods/basenodes/textures/basenodes_dirt_with_grass_bottom.png create mode 100644 games/devtest/mods/basenodes/textures/basenodes_dirt_with_snow.png create mode 100644 games/devtest/mods/basenodes/textures/basenodes_dirt_with_snow_bottom.png create mode 100644 games/devtest/mods/basenodes/textures/basenodes_snow_sheet.png create mode 100644 games/devtest/mods/basenodes/textures/default_apple.png create mode 100644 games/devtest/mods/basenodes/textures/default_cobble.png create mode 100644 games/devtest/mods/basenodes/textures/default_desert_sand.png create mode 100644 games/devtest/mods/basenodes/textures/default_desert_stone.png create mode 100644 games/devtest/mods/basenodes/textures/default_dirt.png create mode 100644 games/devtest/mods/basenodes/textures/default_grass.png create mode 100644 games/devtest/mods/basenodes/textures/default_grass_side.png create mode 100644 games/devtest/mods/basenodes/textures/default_gravel.png create mode 100644 games/devtest/mods/basenodes/textures/default_ice.png create mode 100644 games/devtest/mods/basenodes/textures/default_junglegrass.png create mode 100644 games/devtest/mods/basenodes/textures/default_jungleleaves.png create mode 100644 games/devtest/mods/basenodes/textures/default_jungletree.png create mode 100644 games/devtest/mods/basenodes/textures/default_jungletree_top.png create mode 100644 games/devtest/mods/basenodes/textures/default_lava.png create mode 100644 games/devtest/mods/basenodes/textures/default_lava_flowing.png create mode 100644 games/devtest/mods/basenodes/textures/default_leaves.png create mode 100644 games/devtest/mods/basenodes/textures/default_mossycobble.png create mode 100644 games/devtest/mods/basenodes/textures/default_pine_needles.png create mode 100644 games/devtest/mods/basenodes/textures/default_pine_tree.png create mode 100644 games/devtest/mods/basenodes/textures/default_pine_tree_top.png create mode 100644 games/devtest/mods/basenodes/textures/default_river_water.png create mode 100644 games/devtest/mods/basenodes/textures/default_river_water_flowing.png create mode 100644 games/devtest/mods/basenodes/textures/default_sand.png create mode 100644 games/devtest/mods/basenodes/textures/default_snow.png create mode 100644 games/devtest/mods/basenodes/textures/default_snow_side.png create mode 100644 games/devtest/mods/basenodes/textures/default_stone.png create mode 100644 games/devtest/mods/basenodes/textures/default_tree.png create mode 100644 games/devtest/mods/basenodes/textures/default_tree_top.png create mode 100644 games/devtest/mods/basenodes/textures/default_water.png create mode 100644 games/devtest/mods/basenodes/textures/default_water_flowing.png create mode 100644 games/devtest/mods/basetools/init.lua create mode 100644 games/devtest/mods/basetools/mod.conf create mode 100644 games/devtest/mods/basetools/textures/basetools_dirtpick.png create mode 100644 games/devtest/mods/basetools/textures/basetools_firesword.png create mode 100644 games/devtest/mods/basetools/textures/basetools_icesword.png create mode 100644 games/devtest/mods/basetools/textures/basetools_mesepick.png create mode 100644 games/devtest/mods/basetools/textures/basetools_steelaxe.png create mode 100644 games/devtest/mods/basetools/textures/basetools_steeldagger.png create mode 100644 games/devtest/mods/basetools/textures/basetools_steelpick.png create mode 100644 games/devtest/mods/basetools/textures/basetools_steelpick_l1.png create mode 100644 games/devtest/mods/basetools/textures/basetools_steelpick_l2.png create mode 100644 games/devtest/mods/basetools/textures/basetools_steelshears.png create mode 100644 games/devtest/mods/basetools/textures/basetools_steelshovel.png create mode 100644 games/devtest/mods/basetools/textures/basetools_steelsword.png create mode 100644 games/devtest/mods/basetools/textures/basetools_stoneaxe.png create mode 100644 games/devtest/mods/basetools/textures/basetools_stonepick.png create mode 100644 games/devtest/mods/basetools/textures/basetools_stoneshears.png create mode 100644 games/devtest/mods/basetools/textures/basetools_stoneshovel.png create mode 100644 games/devtest/mods/basetools/textures/basetools_stonesword.png create mode 100644 games/devtest/mods/basetools/textures/basetools_woodaxe.png create mode 100644 games/devtest/mods/basetools/textures/basetools_woodpick.png create mode 100644 games/devtest/mods/basetools/textures/basetools_woodshears.png create mode 100644 games/devtest/mods/basetools/textures/basetools_woodshovel.png create mode 100644 games/devtest/mods/basetools/textures/basetools_woodsword.png create mode 100644 games/devtest/mods/bucket/init.lua create mode 100644 games/devtest/mods/bucket/mod.conf create mode 100644 games/devtest/mods/bucket/textures/bucket.png create mode 100644 games/devtest/mods/bucket/textures/bucket_lava.png create mode 100644 games/devtest/mods/bucket/textures/bucket_water.png create mode 100644 games/devtest/mods/chest/init.lua create mode 100644 games/devtest/mods/chest/mod.conf create mode 100644 games/devtest/mods/chest/textures/chest_chest.png create mode 100644 games/devtest/mods/chest_of_everything/init.lua create mode 100644 games/devtest/mods/chest_of_everything/mod.conf create mode 100644 games/devtest/mods/chest_of_everything/textures/chest_of_everything_chest.png create mode 100644 games/devtest/mods/dignodes/init.lua create mode 100644 games/devtest/mods/dignodes/mod.conf create mode 100644 games/devtest/mods/dignodes/textures/dignodes_choppy.png create mode 100644 games/devtest/mods/dignodes/textures/dignodes_cracky.png create mode 100644 games/devtest/mods/dignodes/textures/dignodes_crumbly.png create mode 100644 games/devtest/mods/dignodes/textures/dignodes_dig_immediate.png create mode 100644 games/devtest/mods/dignodes/textures/dignodes_none.png create mode 100644 games/devtest/mods/dignodes/textures/dignodes_rating1.png create mode 100644 games/devtest/mods/dignodes/textures/dignodes_rating2.png create mode 100644 games/devtest/mods/dignodes/textures/dignodes_rating3.png create mode 100644 games/devtest/mods/experimental/commands.lua create mode 100644 games/devtest/mods/experimental/detached.lua create mode 100644 games/devtest/mods/experimental/init.lua create mode 100644 games/devtest/mods/experimental/items.lua create mode 100644 games/devtest/mods/experimental/mod.conf create mode 100644 games/devtest/mods/experimental/textures/experimental_callback_node.png create mode 100644 games/devtest/mods/experimental/textures/experimental_particle_sheet.png create mode 100644 games/devtest/mods/experimental/textures/experimental_particle_vertical.png create mode 100644 games/devtest/mods/experimental/textures/experimental_tester_tool_1.png create mode 100644 games/devtest/mods/give_initial_stuff/init.lua create mode 100644 games/devtest/mods/give_initial_stuff/mod.conf create mode 100644 games/devtest/mods/initial_message/init.lua create mode 100644 games/devtest/mods/initial_message/mod.conf create mode 100644 games/devtest/mods/mapgen/init.lua create mode 100644 games/devtest/mods/mapgen/mod.conf create mode 100644 games/devtest/mods/modchannels/init.lua create mode 100644 games/devtest/mods/modchannels/mod.conf create mode 100644 games/devtest/mods/soundstuff/init.lua create mode 100644 games/devtest/mods/soundstuff/mod.conf create mode 100644 games/devtest/mods/soundstuff/sounds/soundstuff_mono.ogg create mode 100644 games/devtest/mods/soundstuff/textures/soundstuff_eat.png create mode 100644 games/devtest/mods/soundstuff/textures/soundstuff_node_blank.png create mode 100644 games/devtest/mods/soundstuff/textures/soundstuff_node_climbable.png create mode 100644 games/devtest/mods/soundstuff/textures/soundstuff_node_dig.png create mode 100644 games/devtest/mods/soundstuff/textures/soundstuff_node_dug.png create mode 100644 games/devtest/mods/soundstuff/textures/soundstuff_node_fall.png create mode 100644 games/devtest/mods/soundstuff/textures/soundstuff_node_footstep.png create mode 100644 games/devtest/mods/soundstuff/textures/soundstuff_node_place.png create mode 100644 games/devtest/mods/soundstuff/textures/soundstuff_node_place_failed.png create mode 100644 games/devtest/mods/soundstuff/textures/soundstuff_node_sound.png create mode 100644 games/devtest/mods/stairs/init.lua create mode 100644 games/devtest/mods/stairs/mod.conf create mode 100644 games/devtest/mods/testentities/armor.lua create mode 100644 games/devtest/mods/testentities/callbacks.lua create mode 100644 games/devtest/mods/testentities/init.lua create mode 100644 games/devtest/mods/testentities/mod.conf create mode 100644 games/devtest/mods/testentities/textures/testentities_armorball.png create mode 100644 games/devtest/mods/testentities/textures/testentities_callback.png create mode 100644 games/devtest/mods/testentities/textures/testentities_callback_step.png create mode 100644 games/devtest/mods/testentities/textures/testentities_cube1.png create mode 100644 games/devtest/mods/testentities/textures/testentities_cube2.png create mode 100644 games/devtest/mods/testentities/textures/testentities_cube3.png create mode 100644 games/devtest/mods/testentities/textures/testentities_cube4.png create mode 100644 games/devtest/mods/testentities/textures/testentities_cube5.png create mode 100644 games/devtest/mods/testentities/textures/testentities_cube6.png create mode 100644 games/devtest/mods/testentities/textures/testentities_dungeon_master.png create mode 100644 games/devtest/mods/testentities/textures/testentities_sprite.png create mode 100644 games/devtest/mods/testentities/textures/testentities_upright_sprite1.png create mode 100644 games/devtest/mods/testentities/textures/testentities_upright_sprite2.png create mode 100644 games/devtest/mods/testentities/visuals.lua create mode 100644 games/devtest/mods/testfood/init.lua create mode 100644 games/devtest/mods/testfood/mod.conf create mode 100644 games/devtest/mods/testfood/textures/testfood_bad.png create mode 100644 games/devtest/mods/testfood/textures/testfood_bad2.png create mode 100644 games/devtest/mods/testfood/textures/testfood_good.png create mode 100644 games/devtest/mods/testfood/textures/testfood_good2.png create mode 100644 games/devtest/mods/testformspec/callbacks.lua create mode 100644 games/devtest/mods/testformspec/dummy_items.lua create mode 100644 games/devtest/mods/testformspec/formspec.lua create mode 100644 games/devtest/mods/testformspec/init.lua create mode 100644 games/devtest/mods/testformspec/mod.conf create mode 100644 games/devtest/mods/testformspec/textures/testformspec_animation.jpg create mode 100644 games/devtest/mods/testformspec/textures/testformspec_animation.png create mode 100644 games/devtest/mods/testformspec/textures/testformspec_bg.png create mode 100644 games/devtest/mods/testformspec/textures/testformspec_bg_9slice.png create mode 100644 games/devtest/mods/testformspec/textures/testformspec_bg_9slice_hovered.png create mode 100644 games/devtest/mods/testformspec/textures/testformspec_bg_9slice_pressed.png create mode 100644 games/devtest/mods/testformspec/textures/testformspec_bg_hovered.png create mode 100644 games/devtest/mods/testformspec/textures/testformspec_bg_pressed.png create mode 100644 games/devtest/mods/testformspec/textures/testformspec_button_image.png create mode 100644 games/devtest/mods/testformspec/textures/testformspec_hovered.png create mode 100644 games/devtest/mods/testformspec/textures/testformspec_item.png create mode 100644 games/devtest/mods/testformspec/textures/testformspec_node.png create mode 100644 games/devtest/mods/testformspec/textures/testformspec_pressed.png create mode 100644 games/devtest/mods/testnodes/README.md create mode 100644 games/devtest/mods/testnodes/drawtypes.lua create mode 100644 games/devtest/mods/testnodes/init.lua create mode 100644 games/devtest/mods/testnodes/light.lua create mode 100644 games/devtest/mods/testnodes/liquids.lua create mode 100644 games/devtest/mods/testnodes/meshes.lua create mode 100644 games/devtest/mods/testnodes/mod.conf create mode 100644 games/devtest/mods/testnodes/models/testnodes_ocorner.obj create mode 100644 games/devtest/mods/testnodes/models/testnodes_pyramid.obj create mode 100644 games/devtest/mods/testnodes/nodeboxes.lua create mode 100644 games/devtest/mods/testnodes/param2.lua create mode 100644 games/devtest/mods/testnodes/properties.lua create mode 100644 games/devtest/mods/testnodes/settingtypes.txt create mode 100644 games/devtest/mods/testnodes/textures.lua create mode 100644 games/devtest/mods/testnodes/textures/testnodes_1.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_1g.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_1w.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_1wg.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_2.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_2g.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_2w.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_2wg.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_3.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_3g.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_3w.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_3wg.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_4.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_4g.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_4w.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_4wg.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_5.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_5g.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_5w.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_5wg.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_6.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_6g.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_6w.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_6wg.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_airlike.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_allfaces.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_allfaces_optional.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_alpha.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_alpha128.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_alpha191.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_alpha64.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_anim.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_attached_bottom.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_attached_side.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_attached_top.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_attachedw_bottom.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_attachedw_side.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_attachedw_top.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_bouncy.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_buildable_to.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_climbable_nojump_side.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_climbable_side.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_damage.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_damage_neg.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_drowning.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_fall_damage_minus.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_fall_damage_plus.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_fencelike.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_firelike.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_glasslike.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_glasslike_detail.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_glasslike_framed.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_glasslike_framed2.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_glasslike_framed_optional.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_glasslikeliquid.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light_1.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light_10.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light_11.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light_12.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light_13.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light_14.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light_2.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light_3.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light_4.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light_5.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light_6.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light_7.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light_8.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_light_9.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_line_crossing.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_line_curved.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_line_straight.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_line_t_junction.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquid.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidflowing.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r0.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r1.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r2.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r3.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r4.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r5.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r6.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r7.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r8.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidsource.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidsource_r0.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidsource_r1.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidsource_r2.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidsource_r3.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidsource_r4.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidsource_r5.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidsource_r6.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidsource_r7.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_liquidsource_r8.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_mesh_stripes.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_mesh_stripes2.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_mesh_stripes3.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_mesh_stripes4.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_node.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_node_falling.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_nodebox.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_nojump_side.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_nojump_top.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_normal.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_normal1.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_normal2.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_normal3.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_normal4.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_normal5.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_normal6.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_palette_facedir.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_palette_full.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_palette_wallmounted.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike_degrotate.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike_leveled.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike_meshoptions.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_degrotate.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_leveled.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_meshoptions.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_waving.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_degrotate.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_leveled.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_meshoptions.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_waving.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_plantlike_waving.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_rail2_crossing.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_rail2_curved.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_rail2_straight.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_rail2_t_junction.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_rail_crossing.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_rail_curved.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_rail_straight.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_rail_t_junction.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_signlike.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_slippery.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_street_crossing.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_street_curved.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_street_straight.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_street_t_junction.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_sunlight_filter.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_torchlike_ceiling.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_torchlike_floor.png create mode 100644 games/devtest/mods/testnodes/textures/testnodes_torchlike_wall.png create mode 100644 games/devtest/mods/testpathfinder/README.md create mode 100644 games/devtest/mods/testpathfinder/init.lua create mode 100644 games/devtest/mods/testpathfinder/mod.conf create mode 100644 games/devtest/mods/testpathfinder/textures/testpathfinder_testpathfinder.png create mode 100644 games/devtest/mods/testpathfinder/textures/testpathfinder_waypoint.png create mode 100644 games/devtest/mods/testpathfinder/textures/testpathfinder_waypoint_end.png create mode 100644 games/devtest/mods/testpathfinder/textures/testpathfinder_waypoint_start.png create mode 100644 games/devtest/mods/testtools/README.md create mode 100644 games/devtest/mods/testtools/init.lua create mode 100644 games/devtest/mods/testtools/mod.conf create mode 100644 games/devtest/mods/testtools/textures/testtools_entity_rotator.png create mode 100644 games/devtest/mods/testtools/textures/testtools_entity_scaler.png create mode 100644 games/devtest/mods/testtools/textures/testtools_entity_spawner.png create mode 100644 games/devtest/mods/testtools/textures/testtools_falling_node_tool.png create mode 100644 games/devtest/mods/testtools/textures/testtools_node_setter.png create mode 100644 games/devtest/mods/testtools/textures/testtools_object_attacher.png create mode 100644 games/devtest/mods/testtools/textures/testtools_object_editor.png create mode 100644 games/devtest/mods/testtools/textures/testtools_object_mover.png create mode 100644 games/devtest/mods/testtools/textures/testtools_param2tool.png create mode 100644 games/devtest/mods/testtools/textures/testtools_remover.png create mode 100644 games/devtest/mods/tiled/init.lua create mode 100644 games/devtest/mods/tiled/mod.conf create mode 100644 games/devtest/mods/tiled/textures/tiled_tiled.png create mode 100644 games/devtest/mods/unittests/crafting.lua create mode 100644 games/devtest/mods/unittests/crafting_prepare.lua create mode 100644 games/devtest/mods/unittests/init.lua create mode 100644 games/devtest/mods/unittests/mod.conf create mode 100644 games/devtest/mods/unittests/player.lua create mode 100644 games/devtest/mods/unittests/random.lua create mode 100644 games/devtest/mods/unittests/textures/unittests_coal_lump.png create mode 100644 games/devtest/mods/unittests/textures/unittests_iron_lump.png create mode 100644 games/devtest/mods/unittests/textures/unittests_repairable_tool.png create mode 100644 games/devtest/mods/unittests/textures/unittests_steel_ingot.png create mode 100644 games/devtest/mods/unittests/textures/unittests_stick.png create mode 100644 games/devtest/mods/unittests/textures/unittests_torch.png create mode 100644 games/devtest/mods/unittests/textures/unittests_unrepairable_tool.png create mode 100644 games/devtest/mods/util_commands/init.lua create mode 100644 games/devtest/mods/util_commands/mod.conf create mode 100644 games/devtest/screenshot.png create mode 100644 games/devtest/settingtypes.txt delete mode 100644 games/minimal/LICENSE.txt delete mode 100644 games/minimal/README.md delete mode 100644 games/minimal/game.conf delete mode 100644 games/minimal/menu/background.png delete mode 100644 games/minimal/menu/header.png delete mode 100644 games/minimal/menu/icon.png delete mode 100644 games/minimal/mods/basenodes/init.lua delete mode 100644 games/minimal/mods/basenodes/mod.conf delete mode 100644 games/minimal/mods/basenodes/textures/basenodes_dirt_with_grass_bottom.png delete mode 100644 games/minimal/mods/basenodes/textures/basenodes_dirt_with_snow.png delete mode 100644 games/minimal/mods/basenodes/textures/basenodes_dirt_with_snow_bottom.png delete mode 100644 games/minimal/mods/basenodes/textures/basenodes_snow_sheet.png delete mode 100644 games/minimal/mods/basenodes/textures/default_apple.png delete mode 100644 games/minimal/mods/basenodes/textures/default_cobble.png delete mode 100644 games/minimal/mods/basenodes/textures/default_desert_sand.png delete mode 100644 games/minimal/mods/basenodes/textures/default_desert_stone.png delete mode 100644 games/minimal/mods/basenodes/textures/default_dirt.png delete mode 100644 games/minimal/mods/basenodes/textures/default_grass.png delete mode 100644 games/minimal/mods/basenodes/textures/default_grass_side.png delete mode 100644 games/minimal/mods/basenodes/textures/default_gravel.png delete mode 100644 games/minimal/mods/basenodes/textures/default_ice.png delete mode 100644 games/minimal/mods/basenodes/textures/default_junglegrass.png delete mode 100644 games/minimal/mods/basenodes/textures/default_jungleleaves.png delete mode 100644 games/minimal/mods/basenodes/textures/default_jungletree.png delete mode 100644 games/minimal/mods/basenodes/textures/default_jungletree_top.png delete mode 100644 games/minimal/mods/basenodes/textures/default_lava.png delete mode 100644 games/minimal/mods/basenodes/textures/default_lava_flowing.png delete mode 100644 games/minimal/mods/basenodes/textures/default_leaves.png delete mode 100644 games/minimal/mods/basenodes/textures/default_mossycobble.png delete mode 100644 games/minimal/mods/basenodes/textures/default_pine_needles.png delete mode 100644 games/minimal/mods/basenodes/textures/default_pine_tree.png delete mode 100644 games/minimal/mods/basenodes/textures/default_pine_tree_top.png delete mode 100644 games/minimal/mods/basenodes/textures/default_river_water.png delete mode 100644 games/minimal/mods/basenodes/textures/default_river_water_flowing.png delete mode 100644 games/minimal/mods/basenodes/textures/default_sand.png delete mode 100644 games/minimal/mods/basenodes/textures/default_snow.png delete mode 100644 games/minimal/mods/basenodes/textures/default_snow_side.png delete mode 100644 games/minimal/mods/basenodes/textures/default_stone.png delete mode 100644 games/minimal/mods/basenodes/textures/default_tree.png delete mode 100644 games/minimal/mods/basenodes/textures/default_tree_top.png delete mode 100644 games/minimal/mods/basenodes/textures/default_water.png delete mode 100644 games/minimal/mods/basenodes/textures/default_water_flowing.png delete mode 100644 games/minimal/mods/basetools/init.lua delete mode 100644 games/minimal/mods/basetools/mod.conf delete mode 100644 games/minimal/mods/basetools/textures/basetools_dirtpick.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_firesword.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_icesword.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_mesepick.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_steelaxe.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_steeldagger.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_steelpick.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_steelpick_l1.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_steelpick_l2.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_steelshears.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_steelshovel.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_steelsword.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_stoneaxe.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_stonepick.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_stoneshears.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_stoneshovel.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_stonesword.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_woodaxe.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_woodpick.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_woodshears.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_woodshovel.png delete mode 100644 games/minimal/mods/basetools/textures/basetools_woodsword.png delete mode 100644 games/minimal/mods/bucket/init.lua delete mode 100644 games/minimal/mods/bucket/mod.conf delete mode 100644 games/minimal/mods/bucket/textures/bucket.png delete mode 100644 games/minimal/mods/bucket/textures/bucket_lava.png delete mode 100644 games/minimal/mods/bucket/textures/bucket_water.png delete mode 100644 games/minimal/mods/chest/init.lua delete mode 100644 games/minimal/mods/chest/mod.conf delete mode 100644 games/minimal/mods/chest/textures/chest_chest.png delete mode 100644 games/minimal/mods/chest_of_everything/init.lua delete mode 100644 games/minimal/mods/chest_of_everything/mod.conf delete mode 100644 games/minimal/mods/chest_of_everything/textures/chest_of_everything_chest.png delete mode 100644 games/minimal/mods/dignodes/init.lua delete mode 100644 games/minimal/mods/dignodes/mod.conf delete mode 100644 games/minimal/mods/dignodes/textures/dignodes_choppy.png delete mode 100644 games/minimal/mods/dignodes/textures/dignodes_cracky.png delete mode 100644 games/minimal/mods/dignodes/textures/dignodes_crumbly.png delete mode 100644 games/minimal/mods/dignodes/textures/dignodes_dig_immediate.png delete mode 100644 games/minimal/mods/dignodes/textures/dignodes_none.png delete mode 100644 games/minimal/mods/dignodes/textures/dignodes_rating1.png delete mode 100644 games/minimal/mods/dignodes/textures/dignodes_rating2.png delete mode 100644 games/minimal/mods/dignodes/textures/dignodes_rating3.png delete mode 100644 games/minimal/mods/experimental/commands.lua delete mode 100644 games/minimal/mods/experimental/detached.lua delete mode 100644 games/minimal/mods/experimental/init.lua delete mode 100644 games/minimal/mods/experimental/items.lua delete mode 100644 games/minimal/mods/experimental/mod.conf delete mode 100644 games/minimal/mods/experimental/textures/experimental_callback_node.png delete mode 100644 games/minimal/mods/experimental/textures/experimental_particle_sheet.png delete mode 100644 games/minimal/mods/experimental/textures/experimental_particle_vertical.png delete mode 100644 games/minimal/mods/experimental/textures/experimental_tester_tool_1.png delete mode 100644 games/minimal/mods/give_initial_stuff/init.lua delete mode 100644 games/minimal/mods/give_initial_stuff/mod.conf delete mode 100644 games/minimal/mods/initial_message/init.lua delete mode 100644 games/minimal/mods/initial_message/mod.conf delete mode 100644 games/minimal/mods/mapgen/init.lua delete mode 100644 games/minimal/mods/mapgen/mod.conf delete mode 100644 games/minimal/mods/modchannels/init.lua delete mode 100644 games/minimal/mods/modchannels/mod.conf delete mode 100644 games/minimal/mods/soundstuff/init.lua delete mode 100644 games/minimal/mods/soundstuff/mod.conf delete mode 100644 games/minimal/mods/soundstuff/sounds/soundstuff_mono.ogg delete mode 100644 games/minimal/mods/soundstuff/textures/soundstuff_eat.png delete mode 100644 games/minimal/mods/soundstuff/textures/soundstuff_node_blank.png delete mode 100644 games/minimal/mods/soundstuff/textures/soundstuff_node_climbable.png delete mode 100644 games/minimal/mods/soundstuff/textures/soundstuff_node_dig.png delete mode 100644 games/minimal/mods/soundstuff/textures/soundstuff_node_dug.png delete mode 100644 games/minimal/mods/soundstuff/textures/soundstuff_node_fall.png delete mode 100644 games/minimal/mods/soundstuff/textures/soundstuff_node_footstep.png delete mode 100644 games/minimal/mods/soundstuff/textures/soundstuff_node_place.png delete mode 100644 games/minimal/mods/soundstuff/textures/soundstuff_node_place_failed.png delete mode 100644 games/minimal/mods/soundstuff/textures/soundstuff_node_sound.png delete mode 100644 games/minimal/mods/stairs/init.lua delete mode 100644 games/minimal/mods/stairs/mod.conf delete mode 100644 games/minimal/mods/testentities/armor.lua delete mode 100644 games/minimal/mods/testentities/callbacks.lua delete mode 100644 games/minimal/mods/testentities/init.lua delete mode 100644 games/minimal/mods/testentities/mod.conf delete mode 100644 games/minimal/mods/testentities/textures/testentities_armorball.png delete mode 100644 games/minimal/mods/testentities/textures/testentities_callback.png delete mode 100644 games/minimal/mods/testentities/textures/testentities_callback_step.png delete mode 100644 games/minimal/mods/testentities/textures/testentities_cube1.png delete mode 100644 games/minimal/mods/testentities/textures/testentities_cube2.png delete mode 100644 games/minimal/mods/testentities/textures/testentities_cube3.png delete mode 100644 games/minimal/mods/testentities/textures/testentities_cube4.png delete mode 100644 games/minimal/mods/testentities/textures/testentities_cube5.png delete mode 100644 games/minimal/mods/testentities/textures/testentities_cube6.png delete mode 100644 games/minimal/mods/testentities/textures/testentities_dungeon_master.png delete mode 100644 games/minimal/mods/testentities/textures/testentities_sprite.png delete mode 100644 games/minimal/mods/testentities/textures/testentities_upright_sprite1.png delete mode 100644 games/minimal/mods/testentities/textures/testentities_upright_sprite2.png delete mode 100644 games/minimal/mods/testentities/visuals.lua delete mode 100644 games/minimal/mods/testfood/init.lua delete mode 100644 games/minimal/mods/testfood/mod.conf delete mode 100644 games/minimal/mods/testfood/textures/testfood_bad.png delete mode 100644 games/minimal/mods/testfood/textures/testfood_bad2.png delete mode 100644 games/minimal/mods/testfood/textures/testfood_good.png delete mode 100644 games/minimal/mods/testfood/textures/testfood_good2.png delete mode 100644 games/minimal/mods/testformspec/callbacks.lua delete mode 100644 games/minimal/mods/testformspec/dummy_items.lua delete mode 100644 games/minimal/mods/testformspec/formspec.lua delete mode 100644 games/minimal/mods/testformspec/init.lua delete mode 100644 games/minimal/mods/testformspec/mod.conf delete mode 100644 games/minimal/mods/testformspec/textures/testformspec_animation.jpg delete mode 100644 games/minimal/mods/testformspec/textures/testformspec_animation.png delete mode 100644 games/minimal/mods/testformspec/textures/testformspec_bg.png delete mode 100644 games/minimal/mods/testformspec/textures/testformspec_bg_9slice.png delete mode 100644 games/minimal/mods/testformspec/textures/testformspec_bg_9slice_hovered.png delete mode 100644 games/minimal/mods/testformspec/textures/testformspec_bg_9slice_pressed.png delete mode 100644 games/minimal/mods/testformspec/textures/testformspec_bg_hovered.png delete mode 100644 games/minimal/mods/testformspec/textures/testformspec_bg_pressed.png delete mode 100644 games/minimal/mods/testformspec/textures/testformspec_button_image.png delete mode 100644 games/minimal/mods/testformspec/textures/testformspec_hovered.png delete mode 100644 games/minimal/mods/testformspec/textures/testformspec_item.png delete mode 100644 games/minimal/mods/testformspec/textures/testformspec_node.png delete mode 100644 games/minimal/mods/testformspec/textures/testformspec_pressed.png delete mode 100644 games/minimal/mods/testnodes/README.md delete mode 100644 games/minimal/mods/testnodes/drawtypes.lua delete mode 100644 games/minimal/mods/testnodes/init.lua delete mode 100644 games/minimal/mods/testnodes/light.lua delete mode 100644 games/minimal/mods/testnodes/liquids.lua delete mode 100644 games/minimal/mods/testnodes/meshes.lua delete mode 100644 games/minimal/mods/testnodes/mod.conf delete mode 100644 games/minimal/mods/testnodes/models/testnodes_ocorner.obj delete mode 100644 games/minimal/mods/testnodes/models/testnodes_pyramid.obj delete mode 100644 games/minimal/mods/testnodes/nodeboxes.lua delete mode 100644 games/minimal/mods/testnodes/param2.lua delete mode 100644 games/minimal/mods/testnodes/properties.lua delete mode 100644 games/minimal/mods/testnodes/settingtypes.txt delete mode 100644 games/minimal/mods/testnodes/textures.lua delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_1.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_1g.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_1w.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_1wg.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_2.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_2g.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_2w.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_2wg.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_3.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_3g.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_3w.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_3wg.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_4.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_4g.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_4w.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_4wg.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_5.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_5g.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_5w.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_5wg.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_6.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_6g.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_6w.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_6wg.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_airlike.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_allfaces.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_allfaces_optional.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_alpha.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_alpha128.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_alpha191.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_alpha64.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_anim.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_attached_bottom.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_attached_side.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_attached_top.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_attachedw_bottom.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_attachedw_side.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_attachedw_top.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_bouncy.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_buildable_to.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_climbable_nojump_side.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_climbable_side.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_damage.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_damage_neg.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_drowning.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_fall_damage_minus.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_fall_damage_plus.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_fencelike.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_firelike.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_glasslike.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_glasslike_detail.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_glasslike_framed.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_glasslike_framed2.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_glasslike_framed_optional.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_glasslikeliquid.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light_1.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light_10.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light_11.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light_12.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light_13.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light_14.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light_2.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light_3.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light_4.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light_5.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light_6.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light_7.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light_8.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_light_9.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_line_crossing.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_line_curved.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_line_straight.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_line_t_junction.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquid.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidflowing.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r0.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r1.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r2.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r3.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r4.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r5.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r6.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r7.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r8.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidsource.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidsource_r0.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidsource_r1.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidsource_r2.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidsource_r3.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidsource_r4.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidsource_r5.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidsource_r6.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidsource_r7.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_liquidsource_r8.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_mesh_stripes.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_mesh_stripes2.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_mesh_stripes3.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_mesh_stripes4.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_node.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_node_falling.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_nodebox.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_nojump_side.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_nojump_top.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_normal.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_normal1.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_normal2.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_normal3.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_normal4.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_normal5.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_normal6.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_palette_facedir.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_palette_full.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_palette_wallmounted.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike_degrotate.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike_leveled.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike_meshoptions.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_degrotate.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_leveled.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_meshoptions.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_waving.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_degrotate.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_leveled.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_meshoptions.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_waving.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_plantlike_waving.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_rail2_crossing.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_rail2_curved.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_rail2_straight.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_rail2_t_junction.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_rail_crossing.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_rail_curved.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_rail_straight.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_rail_t_junction.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_signlike.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_slippery.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_street_crossing.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_street_curved.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_street_straight.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_street_t_junction.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_sunlight_filter.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_torchlike_ceiling.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_torchlike_floor.png delete mode 100644 games/minimal/mods/testnodes/textures/testnodes_torchlike_wall.png delete mode 100644 games/minimal/mods/testpathfinder/README.md delete mode 100644 games/minimal/mods/testpathfinder/init.lua delete mode 100644 games/minimal/mods/testpathfinder/mod.conf delete mode 100644 games/minimal/mods/testpathfinder/textures/testpathfinder_testpathfinder.png delete mode 100644 games/minimal/mods/testpathfinder/textures/testpathfinder_waypoint.png delete mode 100644 games/minimal/mods/testpathfinder/textures/testpathfinder_waypoint_end.png delete mode 100644 games/minimal/mods/testpathfinder/textures/testpathfinder_waypoint_start.png delete mode 100644 games/minimal/mods/testtools/README.md delete mode 100644 games/minimal/mods/testtools/init.lua delete mode 100644 games/minimal/mods/testtools/mod.conf delete mode 100644 games/minimal/mods/testtools/textures/testtools_entity_rotator.png delete mode 100644 games/minimal/mods/testtools/textures/testtools_entity_scaler.png delete mode 100644 games/minimal/mods/testtools/textures/testtools_entity_spawner.png delete mode 100644 games/minimal/mods/testtools/textures/testtools_falling_node_tool.png delete mode 100644 games/minimal/mods/testtools/textures/testtools_node_setter.png delete mode 100644 games/minimal/mods/testtools/textures/testtools_object_attacher.png delete mode 100644 games/minimal/mods/testtools/textures/testtools_object_editor.png delete mode 100644 games/minimal/mods/testtools/textures/testtools_object_mover.png delete mode 100644 games/minimal/mods/testtools/textures/testtools_param2tool.png delete mode 100644 games/minimal/mods/testtools/textures/testtools_remover.png delete mode 100644 games/minimal/mods/tiled/init.lua delete mode 100644 games/minimal/mods/tiled/mod.conf delete mode 100644 games/minimal/mods/tiled/textures/tiled_tiled.png delete mode 100644 games/minimal/mods/unittests/crafting.lua delete mode 100644 games/minimal/mods/unittests/crafting_prepare.lua delete mode 100644 games/minimal/mods/unittests/init.lua delete mode 100644 games/minimal/mods/unittests/mod.conf delete mode 100644 games/minimal/mods/unittests/player.lua delete mode 100644 games/minimal/mods/unittests/random.lua delete mode 100644 games/minimal/mods/unittests/textures/unittests_coal_lump.png delete mode 100644 games/minimal/mods/unittests/textures/unittests_iron_lump.png delete mode 100644 games/minimal/mods/unittests/textures/unittests_repairable_tool.png delete mode 100644 games/minimal/mods/unittests/textures/unittests_steel_ingot.png delete mode 100644 games/minimal/mods/unittests/textures/unittests_stick.png delete mode 100644 games/minimal/mods/unittests/textures/unittests_torch.png delete mode 100644 games/minimal/mods/unittests/textures/unittests_unrepairable_tool.png delete mode 100644 games/minimal/mods/util_commands/init.lua delete mode 100644 games/minimal/mods/util_commands/mod.conf delete mode 100644 games/minimal/screenshot.png delete mode 100644 games/minimal/settingtypes.txt (limited to 'doc') diff --git a/CMakeLists.txt b/CMakeLists.txt index ae842918b..a5f644652 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -167,7 +167,7 @@ endif() install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/minetest_game" DESTINATION "${SHAREDIR}/games/" COMPONENT "SUBGAME_MINETEST_GAME" OPTIONAL PATTERN ".git*" EXCLUDE ) -install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/minimal" DESTINATION "${SHAREDIR}/games/" +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/devtest" DESTINATION "${SHAREDIR}/games/" COMPONENT "SUBGAME_MINIMAL" OPTIONAL PATTERN ".git*" EXCLUDE ) if(BUILD_CLIENT) @@ -254,8 +254,8 @@ cpack_add_component(SUBGAME_MINETEST_GAME ) cpack_add_component(SUBGAME_MINIMAL - DISPLAY_NAME "Minimal development test" - DESCRIPTION "A minimal subgame helping to develop the engine." + DISPLAY_NAME "Development Test" + DESCRIPTION "A minimal test game helping to develop the engine." DISABLED #DISABLED does not mean it is disabled, and is just not selected by default. GROUP "Subgames" ) diff --git a/README.md b/README.md index 202ba4fe2..6a3c11f40 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ Download source (this is the URL to the latest of source repository, which might git clone --depth 1 https://github.com/minetest/minetest.git cd minetest -Download minetest_game (otherwise only the "Minimal development test" game is available) using Git: +Download minetest_game (otherwise only the "Development Test" game is available) using Git: git clone --depth 1 https://github.com/minetest/minetest_game.git games/minetest_game diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua index 0d977a17c..36df23cce 100644 --- a/builtin/mainmenu/dlg_create_world.lua +++ b/builtin/mainmenu/dlg_create_world.lua @@ -304,13 +304,13 @@ local function create_world_formspec(dialogdata) label_spflags = "label[0,"..y_start..";" .. fgettext("Mapgen-specific flags") .. "]" end - -- Warning if only minimal is installed - local minimal_only = "" + -- Warning if only devtest is installed + local devtest_only = "" local gamelist_height = 2.3 - if #pkgmgr.games == 1 and pkgmgr.games[1].id == "minimal" then - minimal_only = "box[0,0;5.8,1.7;#ff8800]" .. + if #pkgmgr.games == 1 and pkgmgr.games[1].id == "devtest" then + devtest_only = "box[0,0;5.8,1.7;#ff8800]" .. "textarea[0.3,0;6,1.8;;;".. - fgettext("Warning: The minimal development test is meant for developers.") .. "\n" .. + fgettext("Warning: The Development Test is meant for developers.") .. "\n" .. fgettext("Download a game, such as Minetest Game, from minetest.net") .. "]" gamelist_height = 0.5 end @@ -335,7 +335,7 @@ local function create_world_formspec(dialogdata) "textlist[0,3.85;5.8,"..gamelist_height..";games;" .. pkgmgr.gamelist() .. ";" .. gameidx .. ";false]" .. "container[0,4.5]" .. - minimal_only .. + devtest_only .. "container_end[]" .. "container_end[]" .. diff --git a/doc/lua_api.txt b/doc/lua_api.txt index a77c7567e..c4310aa5b 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1069,7 +1069,7 @@ Node drawtypes There are a bunch of different looking node types. -Look for examples in `games/minimal` or `games/minetest_game`. +Look for examples in `games/devtest` or `games/minetest_game`. * `normal` * A node-sized cube. diff --git a/games/devtest/LICENSE.txt b/games/devtest/LICENSE.txt new file mode 100644 index 000000000..71bd0e596 --- /dev/null +++ b/games/devtest/LICENSE.txt @@ -0,0 +1,4 @@ +License information for Development Test +---------------------------------------- + +The same license as for Minetest applies. diff --git a/games/devtest/README.md b/games/devtest/README.md new file mode 100644 index 000000000..a7e93cf11 --- /dev/null +++ b/games/devtest/README.md @@ -0,0 +1,52 @@ +# Development Test (devtest) + +This is a basic testing environment that contains a bunch of things to test the engine, but it could also be used as a minimal testbed for testing out mods. + +## Features + +* Basic nodes for mapgen +* Basic, minimal map generator +* Lots of example nodes for testing drawtypes, param2, light level, and many other node properties +* Example entities +* Other example items +* Formspec test (via `/test_formspec` command) +* Automated unit tests (disabled by default) +* Tools for manipulating nodes and entities, like the "Param2 Tool" + +## Getting started + +Basically, just create a world and start. A few important things to note: + +* Items are gotten from the “Chest of Everything” (`chest_of_everything:chest`) +* When you lost your initial items, type in `/stuff` command to get them back +* By default, Creative Mode activates infinite node placement. This behavior can be changed with the `devtest_infplace` setting +* Use the `/infplace` command to toggle infinite node placement in-game +* Use the Param2 Tool to change the param2 of nodes; it's useful to experiment with the various drawtype test nodes +* Check out the game settings and server commands for additional tests and features +* Creative Mode does nothing (apart from default engine behavior) + +Confused by a certain node or item? Check out for inline code comments. + +### Example tests + +* You can use this to test what happens if a player is simultaneously in 2 nodes with `damage_per_second` but with a different value. +* Or use the Falling Node Tool on various test nodes to see how they behave when falling. +* You could also use this as a testbed for dependency-free mods, e.g. to test out how your formspecs behave without theming. + +## Random notes + +* Experimental/strange/unstructured tests can be found in the `experimental` mod +* Textures of drawtype test nodes have a red dot at the top left corner. This is to see whether the textures are oriented properly + +## Design philosophy + +This should loosely follow the following principles: + +* Engine testing: The main focus of this is to aid testing of *engine* features, such as mapgen or node drawtypes +* Mod testing: The secondary focus is to help modders as well, either as a minimal testbed for mods or even as a code example +* Minimal interference: Under default settings, it shall not interfere with APIs except on explicit user wish. Non-trivial tests and features need to be enabled by a setting first +* Convenience: Have various tools to make usage easier and more convenient +* Reproducing engine bugs: When an engine bug was found, consider creating a test case +* Clarity: Textures and names need to be designed to keep different things clearly visually apart at a glance +* Low loading time: It must load blazing-fast so stuff can be tested quickly + diff --git a/games/devtest/game.conf b/games/devtest/game.conf new file mode 100644 index 000000000..d6e382ad7 --- /dev/null +++ b/games/devtest/game.conf @@ -0,0 +1,2 @@ +name = Development Test +description = Testing environment to help with testing the engine features of Minetest. It can also be helpful in mod development. diff --git a/games/devtest/menu/background.png b/games/devtest/menu/background.png new file mode 100644 index 000000000..415bb3d14 Binary files /dev/null and b/games/devtest/menu/background.png differ diff --git a/games/devtest/menu/header.png b/games/devtest/menu/header.png new file mode 100644 index 000000000..c80ed71f1 Binary files /dev/null and b/games/devtest/menu/header.png differ diff --git a/games/devtest/menu/icon.png b/games/devtest/menu/icon.png new file mode 100644 index 000000000..f854b9c31 Binary files /dev/null and b/games/devtest/menu/icon.png differ diff --git a/games/devtest/mods/basenodes/init.lua b/games/devtest/mods/basenodes/init.lua new file mode 100644 index 000000000..8156c4bec --- /dev/null +++ b/games/devtest/mods/basenodes/init.lua @@ -0,0 +1,334 @@ +local WATER_ALPHA = 160 +local WATER_VISC = 1 +local LAVA_VISC = 7 + +-- +-- Node definitions +-- + +-- Register nodes + +minetest.register_node("basenodes:stone", { + description = "Stone", + tiles = {"default_stone.png"}, + groups = {cracky=3}, +}) + +minetest.register_node("basenodes:desert_stone", { + description = "Desert Stone", + tiles = {"default_desert_stone.png"}, + groups = {cracky=3}, +}) + +minetest.register_node("basenodes:dirt_with_grass", { + description = "Dirt with Grass", + tiles ={"default_grass.png", + -- a little dot on the bottom to distinguish it from dirt + "default_dirt.png^basenodes_dirt_with_grass_bottom.png", + {name = "default_dirt.png^default_grass_side.png", + tileable_vertical = false}}, + groups = {crumbly=3, soil=1}, +}) + +minetest.register_node("basenodes:dirt_with_snow", { + description = "Dirt with Snow", + tiles ={"basenodes_dirt_with_snow.png", + -- a little dot on the bottom to distinguish it from dirt + "default_dirt.png^basenodes_dirt_with_snow_bottom.png", + {name = "default_dirt.png^default_snow_side.png", + tileable_vertical = false}}, + groups = {crumbly=3, soil=1}, +}) + +minetest.register_node("basenodes:dirt", { + description = "Dirt", + tiles ={"default_dirt.png"}, + groups = {crumbly=3, soil=1}, +}) + +minetest.register_node("basenodes:sand", { + description = "Sand", + tiles ={"default_sand.png"}, + groups = {crumbly=3}, +}) + +minetest.register_node("basenodes:desert_sand", { + description = "Desert Sand", + tiles ={"default_desert_sand.png"}, + groups = {crumbly=3}, +}) + +minetest.register_node("basenodes:gravel", { + description = "Gravel", + tiles ={"default_gravel.png"}, + groups = {crumbly=2}, +}) + +minetest.register_node("basenodes:junglegrass", { + description = "Jungle Grass", + drawtype = "plantlike", + tiles ={"default_junglegrass.png"}, + inventory_image = "default_junglegrass.png", + wield_image = "default_junglegrass.png", + paramtype = "light", + walkable = false, + groups = {snappy=3}, +}) + +minetest.register_node("basenodes:tree", { + description = "Normal Tree Trunk", + tiles = {"default_tree_top.png", "default_tree_top.png", "default_tree.png"}, + is_ground_content = false, + groups = {choppy=2,oddly_breakable_by_hand=1}, +}) + +minetest.register_node("basenodes:leaves", { + description = "Normal Leaves", + drawtype = "allfaces_optional", + tiles = {"default_leaves.png"}, + paramtype = "light", + is_ground_content = false, + groups = {snappy=3}, +}) + +minetest.register_node("basenodes:jungletree", { + description = "Jungle Tree Trunk", + tiles = {"default_jungletree_top.png", "default_jungletree_top.png", "default_jungletree.png"}, + is_ground_content = false, + groups = {choppy=2,oddly_breakable_by_hand=1}, +}) + +minetest.register_node("basenodes:jungleleaves", { + description = "Jungle Leaves", + drawtype = "allfaces_optional", + tiles = {"default_jungleleaves.png"}, + paramtype = "light", + is_ground_content = false, + groups = {snappy=3}, +}) + +minetest.register_node("basenodes:pine_tree", { + description = "Pine Tree Trunk", + tiles = {"default_pine_tree_top.png", "default_pine_tree_top.png", "default_pine_tree.png"}, + is_ground_content = false, + groups = {choppy=2,oddly_breakable_by_hand=1}, +}) + +minetest.register_node("basenodes:pine_needles", { + description = "Pine Needles", + drawtype = "allfaces_optional", + tiles = {"default_pine_needles.png"}, + paramtype = "light", + is_ground_content = false, + groups = {snappy=3}, +}) + +minetest.register_node("basenodes:water_source", { + description = "Water Source", + drawtype = "liquid", + tiles = {"default_water.png"}, + special_tiles = { + {name = "default_water.png", backface_culling = false}, + {name = "default_water.png", backface_culling = true}, + }, + alpha = WATER_ALPHA, + paramtype = "light", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drowning = 1, + liquidtype = "source", + liquid_alternative_flowing = "basenodes:water_flowing", + liquid_alternative_source = "basenodes:water_source", + liquid_viscosity = WATER_VISC, + post_effect_color = {a = 64, r = 100, g = 100, b = 200}, + groups = {water = 3, liquid = 3}, +}) + +minetest.register_node("basenodes:water_flowing", { + description = "Flowing Water", + drawtype = "flowingliquid", + tiles = {"default_water_flowing.png"}, + special_tiles = { + {name = "default_water_flowing.png", backface_culling = false}, + {name = "default_water_flowing.png", backface_culling = false}, + }, + alpha = WATER_ALPHA, + paramtype = "light", + paramtype2 = "flowingliquid", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drowning = 1, + liquidtype = "flowing", + liquid_alternative_flowing = "basenodes:water_flowing", + liquid_alternative_source = "basenodes:water_source", + liquid_viscosity = WATER_VISC, + post_effect_color = {a = 64, r = 100, g = 100, b = 200}, + groups = {water = 3, liquid = 3}, +}) + +minetest.register_node("basenodes:river_water_source", { + description = "River Water Source", + drawtype = "liquid", + tiles = { "default_river_water.png" }, + special_tiles = { + {name = "default_river_water.png", backface_culling = false}, + {name = "default_river_water.png", backface_culling = true}, + }, + alpha = WATER_ALPHA, + paramtype = "light", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drowning = 1, + liquidtype = "source", + liquid_alternative_flowing = "basenodes:river_water_flowing", + liquid_alternative_source = "basenodes:river_water_source", + liquid_viscosity = 1, + liquid_renewable = false, + liquid_range = 2, + post_effect_color = {a = 103, r = 30, g = 76, b = 90}, + groups = {water = 3, liquid = 3, }, +}) + +minetest.register_node("basenodes:river_water_flowing", { + description = "Flowing River Water", + drawtype = "flowingliquid", + tiles = {"default_river_water_flowing.png"}, + special_tiles = { + {name = "default_river_water_flowing.png", backface_culling = false}, + {name = "default_river_water_flowing.png", backface_culling = false}, + }, + alpha = WATER_ALPHA, + paramtype = "light", + paramtype2 = "flowingliquid", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drowning = 1, + liquidtype = "flowing", + liquid_alternative_flowing = "basenodes:river_water_flowing", + liquid_alternative_source = "basenodes:river_water_source", + liquid_viscosity = 1, + liquid_renewable = false, + liquid_range = 2, + post_effect_color = {a = 103, r = 30, g = 76, b = 90}, + groups = {water = 3, liquid = 3, }, +}) + +minetest.register_node("basenodes:lava_flowing", { + description = "Flowing Lava", + drawtype = "flowingliquid", + tiles = {"default_lava_flowing.png"}, + special_tiles = { + {name="default_lava_flowing.png", backface_culling = false}, + {name="default_lava_flowing.png", backface_culling = false}, + }, + paramtype = "light", + light_source = minetest.LIGHT_MAX, + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drowning = 1, + damage_per_second = 4, + liquidtype = "flowing", + liquid_alternative_flowing = "basenodes:lava_flowing", + liquid_alternative_source = "basenodes:lava_source", + liquid_viscosity = LAVA_VISC, + post_effect_color = {a=192, r=255, g=64, b=0}, + groups = {lava=3, liquid=1}, +}) + +minetest.register_node("basenodes:lava_source", { + description = "Lava Source", + drawtype = "liquid", + tiles = { "default_lava.png" }, + special_tiles = { + {name = "default_lava.png", backface_culling = false}, + {name = "default_lava.png", backface_culling = true}, + }, + paramtype = "light", + light_source = minetest.LIGHT_MAX, + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drowning = 1, + damage_per_second = 4, + liquidtype = "source", + liquid_alternative_flowing = "basenodes:lava_flowing", + liquid_alternative_source = "basenodes:lava_source", + liquid_viscosity = LAVA_VISC, + post_effect_color = {a=192, r=255, g=64, b=0}, + groups = {lava=3, liquid=1}, +}) + +minetest.register_node("basenodes:cobble", { + description = "Cobblestone", + tiles ={"default_cobble.png"}, + is_ground_content = false, + groups = {cracky=3}, +}) + +minetest.register_node("basenodes:mossycobble", { + description = "Mossy Cobblestone", + tiles ={"default_mossycobble.png"}, + is_ground_content = false, + groups = {cracky=3}, +}) + +minetest.register_node("basenodes:apple", { + description = "Apple", + drawtype = "plantlike", + tiles ={"default_apple.png"}, + inventory_image = "default_apple.png", + paramtype = "light", + is_ground_content = false, + sunlight_propagates = true, + walkable = false, + groups = {dig_immediate=3}, + + -- Make eatable because why not? + on_use = minetest.item_eat(2), +}) + +minetest.register_node("basenodes:ice", { + description = "Ice", + tiles ={"default_ice.png"}, + groups = {cracky=3}, +}) + +-- The snow nodes intentionally have different tints to make them more +-- distinguishable +minetest.register_node("basenodes:snow", { + description = "Snow Sheet", + tiles = {"basenodes_snow_sheet.png"}, + groups = {crumbly=3}, + walkable = false, + paramtype = "light", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -0.25, 0.5}, + }, +}) + +minetest.register_node("basenodes:snowblock", { + description = "Snow Block", + tiles ={"default_snow.png"}, + groups = {crumbly=3}, +}) + + diff --git a/games/devtest/mods/basenodes/mod.conf b/games/devtest/mods/basenodes/mod.conf new file mode 100644 index 000000000..25024dc63 --- /dev/null +++ b/games/devtest/mods/basenodes/mod.conf @@ -0,0 +1,2 @@ +name = basenodes +description = Contains basic nodes for mapgen diff --git a/games/devtest/mods/basenodes/textures/basenodes_dirt_with_grass_bottom.png b/games/devtest/mods/basenodes/textures/basenodes_dirt_with_grass_bottom.png new file mode 100644 index 000000000..5e8fc41a9 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/basenodes_dirt_with_grass_bottom.png differ diff --git a/games/devtest/mods/basenodes/textures/basenodes_dirt_with_snow.png b/games/devtest/mods/basenodes/textures/basenodes_dirt_with_snow.png new file mode 100644 index 000000000..7ea2d8d31 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/basenodes_dirt_with_snow.png differ diff --git a/games/devtest/mods/basenodes/textures/basenodes_dirt_with_snow_bottom.png b/games/devtest/mods/basenodes/textures/basenodes_dirt_with_snow_bottom.png new file mode 100644 index 000000000..447c94e98 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/basenodes_dirt_with_snow_bottom.png differ diff --git a/games/devtest/mods/basenodes/textures/basenodes_snow_sheet.png b/games/devtest/mods/basenodes/textures/basenodes_snow_sheet.png new file mode 100644 index 000000000..455332093 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/basenodes_snow_sheet.png differ diff --git a/games/devtest/mods/basenodes/textures/default_apple.png b/games/devtest/mods/basenodes/textures/default_apple.png new file mode 100644 index 000000000..9c115dae4 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_apple.png differ diff --git a/games/devtest/mods/basenodes/textures/default_cobble.png b/games/devtest/mods/basenodes/textures/default_cobble.png new file mode 100644 index 000000000..5b859e9c2 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_cobble.png differ diff --git a/games/devtest/mods/basenodes/textures/default_desert_sand.png b/games/devtest/mods/basenodes/textures/default_desert_sand.png new file mode 100644 index 000000000..19ec87dc0 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_desert_sand.png differ diff --git a/games/devtest/mods/basenodes/textures/default_desert_stone.png b/games/devtest/mods/basenodes/textures/default_desert_stone.png new file mode 100644 index 000000000..5126fb61c Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_desert_stone.png differ diff --git a/games/devtest/mods/basenodes/textures/default_dirt.png b/games/devtest/mods/basenodes/textures/default_dirt.png new file mode 100644 index 000000000..58670305d Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_dirt.png differ diff --git a/games/devtest/mods/basenodes/textures/default_grass.png b/games/devtest/mods/basenodes/textures/default_grass.png new file mode 100644 index 000000000..3d6397186 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_grass.png differ diff --git a/games/devtest/mods/basenodes/textures/default_grass_side.png b/games/devtest/mods/basenodes/textures/default_grass_side.png new file mode 100644 index 000000000..04770b6f6 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_grass_side.png differ diff --git a/games/devtest/mods/basenodes/textures/default_gravel.png b/games/devtest/mods/basenodes/textures/default_gravel.png new file mode 100644 index 000000000..7e5ff616f Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_gravel.png differ diff --git a/games/devtest/mods/basenodes/textures/default_ice.png b/games/devtest/mods/basenodes/textures/default_ice.png new file mode 100644 index 000000000..c4bddd223 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_ice.png differ diff --git a/games/devtest/mods/basenodes/textures/default_junglegrass.png b/games/devtest/mods/basenodes/textures/default_junglegrass.png new file mode 100644 index 000000000..d64e33abc Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_junglegrass.png differ diff --git a/games/devtest/mods/basenodes/textures/default_jungleleaves.png b/games/devtest/mods/basenodes/textures/default_jungleleaves.png new file mode 100644 index 000000000..1fa67e83a Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_jungleleaves.png differ diff --git a/games/devtest/mods/basenodes/textures/default_jungletree.png b/games/devtest/mods/basenodes/textures/default_jungletree.png new file mode 100644 index 000000000..053850fa7 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_jungletree.png differ diff --git a/games/devtest/mods/basenodes/textures/default_jungletree_top.png b/games/devtest/mods/basenodes/textures/default_jungletree_top.png new file mode 100644 index 000000000..e80de8a69 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_jungletree_top.png differ diff --git a/games/devtest/mods/basenodes/textures/default_lava.png b/games/devtest/mods/basenodes/textures/default_lava.png new file mode 100644 index 000000000..a4cf649f1 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_lava.png differ diff --git a/games/devtest/mods/basenodes/textures/default_lava_flowing.png b/games/devtest/mods/basenodes/textures/default_lava_flowing.png new file mode 100644 index 000000000..07066a6e3 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_lava_flowing.png differ diff --git a/games/devtest/mods/basenodes/textures/default_leaves.png b/games/devtest/mods/basenodes/textures/default_leaves.png new file mode 100644 index 000000000..c0475d4d2 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_leaves.png differ diff --git a/games/devtest/mods/basenodes/textures/default_mossycobble.png b/games/devtest/mods/basenodes/textures/default_mossycobble.png new file mode 100644 index 000000000..69585e37b Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_mossycobble.png differ diff --git a/games/devtest/mods/basenodes/textures/default_pine_needles.png b/games/devtest/mods/basenodes/textures/default_pine_needles.png new file mode 100644 index 000000000..137caa2a3 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_pine_needles.png differ diff --git a/games/devtest/mods/basenodes/textures/default_pine_tree.png b/games/devtest/mods/basenodes/textures/default_pine_tree.png new file mode 100644 index 000000000..5743183c0 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_pine_tree.png differ diff --git a/games/devtest/mods/basenodes/textures/default_pine_tree_top.png b/games/devtest/mods/basenodes/textures/default_pine_tree_top.png new file mode 100644 index 000000000..cc18f3462 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_pine_tree_top.png differ diff --git a/games/devtest/mods/basenodes/textures/default_river_water.png b/games/devtest/mods/basenodes/textures/default_river_water.png new file mode 100644 index 000000000..e1074d2ef Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_river_water.png differ diff --git a/games/devtest/mods/basenodes/textures/default_river_water_flowing.png b/games/devtest/mods/basenodes/textures/default_river_water_flowing.png new file mode 100644 index 000000000..4a756b2bd Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_river_water_flowing.png differ diff --git a/games/devtest/mods/basenodes/textures/default_sand.png b/games/devtest/mods/basenodes/textures/default_sand.png new file mode 100644 index 000000000..0ed0e4ceb Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_sand.png differ diff --git a/games/devtest/mods/basenodes/textures/default_snow.png b/games/devtest/mods/basenodes/textures/default_snow.png new file mode 100644 index 000000000..c42e0eecb Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_snow.png differ diff --git a/games/devtest/mods/basenodes/textures/default_snow_side.png b/games/devtest/mods/basenodes/textures/default_snow_side.png new file mode 100644 index 000000000..f34d10991 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_snow_side.png differ diff --git a/games/devtest/mods/basenodes/textures/default_stone.png b/games/devtest/mods/basenodes/textures/default_stone.png new file mode 100644 index 000000000..763b4396a Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_stone.png differ diff --git a/games/devtest/mods/basenodes/textures/default_tree.png b/games/devtest/mods/basenodes/textures/default_tree.png new file mode 100644 index 000000000..189ec1593 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_tree.png differ diff --git a/games/devtest/mods/basenodes/textures/default_tree_top.png b/games/devtest/mods/basenodes/textures/default_tree_top.png new file mode 100644 index 000000000..d1a4fa704 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_tree_top.png differ diff --git a/games/devtest/mods/basenodes/textures/default_water.png b/games/devtest/mods/basenodes/textures/default_water.png new file mode 100644 index 000000000..3e385ae8b Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_water.png differ diff --git a/games/devtest/mods/basenodes/textures/default_water_flowing.png b/games/devtest/mods/basenodes/textures/default_water_flowing.png new file mode 100644 index 000000000..7cdafd51d Binary files /dev/null and b/games/devtest/mods/basenodes/textures/default_water_flowing.png differ diff --git a/games/devtest/mods/basetools/init.lua b/games/devtest/mods/basetools/init.lua new file mode 100644 index 000000000..d9d9afb07 --- /dev/null +++ b/games/devtest/mods/basetools/init.lua @@ -0,0 +1,295 @@ +-- +-- Tool definitions +-- + +--[[ TOOLS SUMMARY: + +Tool types: + +* Hand: basic tool/weapon (just for convenience, not optimized for testing) +* Pickaxe: dig cracky +* Axe: dig choppy +* Shovel: dig crumbly +* Shears: dig snappy +* Sword: deal damage +* Dagger: deal damage, but faster + +Tool materials: + +* Dirt: dig nodes of rating 3, one use only +* Wood: dig nodes of rating 3 +* Stone: dig nodes of rating 3 or 2 +* Steel: dig nodes of rating 3, 2 or 1 +* Mese: dig "everything" instantly +]] + +-- The hand +minetest.register_item(":", { + type = "none", + wield_image = "wieldhand.png", + wield_scale = {x=1,y=1,z=2.5}, + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level = 0, + groupcaps = { + crumbly = {times={[3]=1.50}, uses=0, maxlevel=0}, + snappy = {times={[3]=1.50}, uses=0, maxlevel=0}, + oddly_breakable_by_hand = {times={[1]=7.00,[2]=4.00,[3]=2.00}, uses=0, maxlevel=0}, + }, + damage_groups = {fleshy=1}, + } +}) + +-- Mese Pickaxe: special tool that digs "everything" instantly +minetest.register_tool("basetools:pick_mese", { + description = "Mese Pickaxe", + inventory_image = "basetools_mesepick.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=3, + groupcaps={ + cracky={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255}, + crumbly={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255}, + snappy={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255}, + choppy={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255}, + dig_immediate={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255}, + }, + }, +}) + + +-- +-- Pickaxes: Dig cracky +-- + +-- This should break after only 1 use +minetest.register_tool("basetools:pick_dirt", { + description = "Dirt Pickaxe", + inventory_image = "basetools_dirtpick.png", + tool_capabilities = { + max_drop_level=0, + groupcaps={ + cracky={times={[3]=2.00}, uses=1, maxlevel=0} + }, + }, +}) + +minetest.register_tool("basetools:pick_wood", { + description = "Wooden Pickaxe", + inventory_image = "basetools_woodpick.png", + tool_capabilities = { + max_drop_level=0, + groupcaps={ + cracky={times={[3]=2.00}, uses=30, maxlevel=0} + }, + }, +}) +minetest.register_tool("basetools:pick_stone", { + description = "Stone Pickaxe", + inventory_image = "basetools_stonepick.png", + tool_capabilities = { + max_drop_level=0, + groupcaps={ + cracky={times={[2]=1.20, [3]=0.80}, uses=60, maxlevel=0} + }, + }, +}) +minetest.register_tool("basetools:pick_steel", { + description = "Steel Pickaxe", + inventory_image = "basetools_steelpick.png", + tool_capabilities = { + max_drop_level=1, + groupcaps={ + cracky={times={[1]=4.00, [2]=1.60, [3]=1.00}, uses=90, maxlevel=0} + }, + }, +}) +minetest.register_tool("basetools:pick_steel_l1", { + description = "Steel Pickaxe Level 1", + inventory_image = "basetools_steelpick_l1.png", + tool_capabilities = { + max_drop_level=1, + groupcaps={ + cracky={times={[1]=4.00, [2]=1.60, [3]=1.00}, uses=90, maxlevel=1} + }, + }, +}) +minetest.register_tool("basetools:pick_steel_l2", { + description = "Steel Pickaxe Level 2", + inventory_image = "basetools_steelpick_l2.png", + tool_capabilities = { + max_drop_level=1, + groupcaps={ + cracky={times={[1]=4.00, [2]=1.60, [3]=1.00}, uses=90, maxlevel=2} + }, + }, +}) + +-- +-- Shovels (dig crumbly) +-- + +minetest.register_tool("basetools:shovel_wood", { + description = "Wooden Shovel", + inventory_image = "basetools_woodshovel.png", + tool_capabilities = { + max_drop_level=0, + groupcaps={ + crumbly={times={[3]=0.50}, uses=30, maxlevel=0} + }, + }, +}) +minetest.register_tool("basetools:shovel_stone", { + description = "Stone Shovel", + inventory_image = "basetools_stoneshovel.png", + tool_capabilities = { + max_drop_level=0, + groupcaps={ + crumbly={times={[2]=0.50, [3]=0.30}, uses=60, maxlevel=0} + }, + }, +}) +minetest.register_tool("basetools:shovel_steel", { + description = "Steel Shovel", + inventory_image = "basetools_steelshovel.png", + tool_capabilities = { + max_drop_level=1, + groupcaps={ + crumbly={times={[1]=1.00, [2]=0.70, [3]=0.60}, uses=90, maxlevel=0} + }, + }, +}) + +-- +-- Axes (dig choppy) +-- + +minetest.register_tool("basetools:axe_wood", { + description = "Wooden Axe", + inventory_image = "basetools_woodaxe.png", + tool_capabilities = { + max_drop_level=0, + groupcaps={ + choppy={times={[3]=0.80}, uses=30, maxlevel=0}, + }, + }, +}) +minetest.register_tool("basetools:axe_stone", { + description = "Stone Axe", + inventory_image = "basetools_stoneaxe.png", + tool_capabilities = { + max_drop_level=0, + groupcaps={ + choppy={times={[2]=1.00, [3]=0.60}, uses=60, maxlevel=0}, + }, + }, +}) +minetest.register_tool("basetools:axe_steel", { + description = "Steel Axe", + inventory_image = "basetools_steelaxe.png", + tool_capabilities = { + max_drop_level=1, + groupcaps={ + choppy={times={[1]=2.00, [2]=0.80, [3]=0.40}, uses=90, maxlevel=0}, + }, + }, +}) + +-- +-- Shears (dig snappy) +-- + +minetest.register_tool("basetools:shears_wood", { + description = "Wooden Shears", + inventory_image = "basetools_woodshears.png", + tool_capabilities = { + max_drop_level=0, + groupcaps={ + snappy={times={[3]=1.00}, uses=30, maxlevel=0}, + }, + }, +}) +minetest.register_tool("basetools:shears_stone", { + description = "Stone Shears", + inventory_image = "basetools_stoneshears.png", + tool_capabilities = { + max_drop_level=0, + groupcaps={ + snappy={times={[2]=1.00, [3]=0.50}, uses=60, maxlevel=0}, + }, + }, +}) +minetest.register_tool("basetools:shears_steel", { + description = "Steel Shears", + inventory_image = "basetools_steelshears.png", + tool_capabilities = { + max_drop_level=1, + groupcaps={ + snappy={times={[1]=1.00, [2]=0.50, [3]=0.25}, uses=90, maxlevel=0}, + }, + }, +}) + +-- +-- Swords (deal damage) +-- + +minetest.register_tool("basetools:sword_wood", { + description = "Wooden Sword", + inventory_image = "basetools_woodsword.png", + tool_capabilities = { + full_punch_interval = 1.0, + damage_groups = {fleshy=2}, + } +}) +minetest.register_tool("basetools:sword_stone", { + description = "Stone Sword", + inventory_image = "basetools_stonesword.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=0, + damage_groups = {fleshy=4}, + } +}) +minetest.register_tool("basetools:sword_steel", { + description = "Steel Sword", + inventory_image = "basetools_steelsword.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=1, + damage_groups = {fleshy=6}, + } +}) + +-- Fire/Ice sword: Deal damage to non-fleshy damage groups +minetest.register_tool("basetools:sword_fire", { + description = "Fire Sword", + inventory_image = "basetools_firesword.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=0, + damage_groups = {icy=6}, + } +}) +minetest.register_tool("basetools:sword_ice", { + description = "Ice Sword", + inventory_image = "basetools_icesword.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=0, + damage_groups = {firy=6}, + } +}) + +-- +-- Dagger: Low damage, fast punch interval +-- +minetest.register_tool("basetools:dagger_steel", { + description = "Steel Dagger", + inventory_image = "basetools_steeldagger.png", + tool_capabilities = { + full_punch_interval = 0.5, + max_drop_level=0, + damage_groups = {fleshy=2}, + } +}) diff --git a/games/devtest/mods/basetools/mod.conf b/games/devtest/mods/basetools/mod.conf new file mode 100644 index 000000000..f0d9f657d --- /dev/null +++ b/games/devtest/mods/basetools/mod.conf @@ -0,0 +1,2 @@ +name = basetools +description = Contains basic digging tools diff --git a/games/devtest/mods/basetools/textures/basetools_dirtpick.png b/games/devtest/mods/basetools/textures/basetools_dirtpick.png new file mode 100644 index 000000000..20a021d72 Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_dirtpick.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_firesword.png b/games/devtest/mods/basetools/textures/basetools_firesword.png new file mode 100644 index 000000000..ee2809ab7 Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_firesword.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_icesword.png b/games/devtest/mods/basetools/textures/basetools_icesword.png new file mode 100644 index 000000000..35ba8214b Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_icesword.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_mesepick.png b/games/devtest/mods/basetools/textures/basetools_mesepick.png new file mode 100644 index 000000000..2b5e12cdb Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_mesepick.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_steelaxe.png b/games/devtest/mods/basetools/textures/basetools_steelaxe.png new file mode 100644 index 000000000..aac594d84 Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_steelaxe.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_steeldagger.png b/games/devtest/mods/basetools/textures/basetools_steeldagger.png new file mode 100644 index 000000000..4c9173094 Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_steeldagger.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_steelpick.png b/games/devtest/mods/basetools/textures/basetools_steelpick.png new file mode 100644 index 000000000..bc02aac3e Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_steelpick.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_steelpick_l1.png b/games/devtest/mods/basetools/textures/basetools_steelpick_l1.png new file mode 100644 index 000000000..dc03f3f65 Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_steelpick_l1.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_steelpick_l2.png b/games/devtest/mods/basetools/textures/basetools_steelpick_l2.png new file mode 100644 index 000000000..011df4584 Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_steelpick_l2.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_steelshears.png b/games/devtest/mods/basetools/textures/basetools_steelshears.png new file mode 100644 index 000000000..04c86c370 Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_steelshears.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_steelshovel.png b/games/devtest/mods/basetools/textures/basetools_steelshovel.png new file mode 100644 index 000000000..8cab60784 Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_steelshovel.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_steelsword.png b/games/devtest/mods/basetools/textures/basetools_steelsword.png new file mode 100644 index 000000000..9909365c3 Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_steelsword.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_stoneaxe.png b/games/devtest/mods/basetools/textures/basetools_stoneaxe.png new file mode 100644 index 000000000..a374c547d Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_stoneaxe.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_stonepick.png b/games/devtest/mods/basetools/textures/basetools_stonepick.png new file mode 100644 index 000000000..d9156ee3a Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_stonepick.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_stoneshears.png b/games/devtest/mods/basetools/textures/basetools_stoneshears.png new file mode 100644 index 000000000..0b4bd3b74 Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_stoneshears.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_stoneshovel.png b/games/devtest/mods/basetools/textures/basetools_stoneshovel.png new file mode 100644 index 000000000..3c1bb48cb Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_stoneshovel.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_stonesword.png b/games/devtest/mods/basetools/textures/basetools_stonesword.png new file mode 100644 index 000000000..6f3e94cda Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_stonesword.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_woodaxe.png b/games/devtest/mods/basetools/textures/basetools_woodaxe.png new file mode 100644 index 000000000..4015e910f Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_woodaxe.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_woodpick.png b/games/devtest/mods/basetools/textures/basetools_woodpick.png new file mode 100644 index 000000000..15c61f408 Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_woodpick.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_woodshears.png b/games/devtest/mods/basetools/textures/basetools_woodshears.png new file mode 100644 index 000000000..4ff92fd7c Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_woodshears.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_woodshovel.png b/games/devtest/mods/basetools/textures/basetools_woodshovel.png new file mode 100644 index 000000000..6cc52f8a1 Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_woodshovel.png differ diff --git a/games/devtest/mods/basetools/textures/basetools_woodsword.png b/games/devtest/mods/basetools/textures/basetools_woodsword.png new file mode 100644 index 000000000..364016ed6 Binary files /dev/null and b/games/devtest/mods/basetools/textures/basetools_woodsword.png differ diff --git a/games/devtest/mods/bucket/init.lua b/games/devtest/mods/bucket/init.lua new file mode 100644 index 000000000..3189d4aa6 --- /dev/null +++ b/games/devtest/mods/bucket/init.lua @@ -0,0 +1,26 @@ +-- Bucket: Punch liquid source or flowing liquid to collect it + +minetest.register_tool("bucket:bucket", { + description = "Bucket", + inventory_image = "bucket.png", + stack_max = 1, + liquids_pointable = true, + groups = { disable_repair = 1 }, + on_use = function(itemstack, user, pointed_thing) + -- Must be pointing to node + if pointed_thing.type ~= "node" then + return + end + -- Check if pointing to a liquid + local n = minetest.get_node(pointed_thing.under) + local def = minetest.registered_nodes[n.name] + if def ~= nil and (def.liquidtype == "source" or def.liquidtype == "flowing") then + minetest.add_node(pointed_thing.under, {name="air"}) + local inv = user:get_inventory() + if inv then + inv:add_item("main", ItemStack(n.name)) + end + end + end, +}) + diff --git a/games/devtest/mods/bucket/mod.conf b/games/devtest/mods/bucket/mod.conf new file mode 100644 index 000000000..d14deb4ea --- /dev/null +++ b/games/devtest/mods/bucket/mod.conf @@ -0,0 +1,2 @@ +name = bucket +description = Minimal bucket to pick up liquids diff --git a/games/devtest/mods/bucket/textures/bucket.png b/games/devtest/mods/bucket/textures/bucket.png new file mode 100644 index 000000000..677952875 Binary files /dev/null and b/games/devtest/mods/bucket/textures/bucket.png differ diff --git a/games/devtest/mods/bucket/textures/bucket_lava.png b/games/devtest/mods/bucket/textures/bucket_lava.png new file mode 100644 index 000000000..dfcae65fb Binary files /dev/null and b/games/devtest/mods/bucket/textures/bucket_lava.png differ diff --git a/games/devtest/mods/bucket/textures/bucket_water.png b/games/devtest/mods/bucket/textures/bucket_water.png new file mode 100644 index 000000000..e164b0a50 Binary files /dev/null and b/games/devtest/mods/bucket/textures/bucket_water.png differ diff --git a/games/devtest/mods/chest/init.lua b/games/devtest/mods/chest/init.lua new file mode 100644 index 000000000..c44522cb9 --- /dev/null +++ b/games/devtest/mods/chest/init.lua @@ -0,0 +1,27 @@ +minetest.register_node("chest:chest", { + description = "Chest", + tiles ={"chest_chest.png^[sheet:2x2:0,0", "chest_chest.png^[sheet:2x2:0,0", + "chest_chest.png^[sheet:2x2:1,0", "chest_chest.png^[sheet:2x2:1,0", + "chest_chest.png^[sheet:2x2:1,0", "chest_chest.png^[sheet:2x2:0,1"}, + paramtype2 = "facedir", + groups = {dig_immediate=2,choppy=3}, + is_ground_content = false, + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", + "size[8,9]".. + "list[current_name;main;0,0;8,4;]".. + "list[current_player;main;0,5;8,4;]" .. + "listring[]") + meta:set_string("infotext", "Chest") + local inv = meta:get_inventory() + inv:set_size("main", 8*4) + end, + can_dig = function(pos,player) + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory() + return inv:is_empty("main") + end, +}) + + diff --git a/games/devtest/mods/chest/mod.conf b/games/devtest/mods/chest/mod.conf new file mode 100644 index 000000000..0d7500164 --- /dev/null +++ b/games/devtest/mods/chest/mod.conf @@ -0,0 +1,2 @@ +name = chest +description = A simple chest to store items diff --git a/games/devtest/mods/chest/textures/chest_chest.png b/games/devtest/mods/chest/textures/chest_chest.png new file mode 100644 index 000000000..824b4d502 Binary files /dev/null and b/games/devtest/mods/chest/textures/chest_chest.png differ diff --git a/games/devtest/mods/chest_of_everything/init.lua b/games/devtest/mods/chest_of_everything/init.lua new file mode 100644 index 000000000..7d61abebf --- /dev/null +++ b/games/devtest/mods/chest_of_everything/init.lua @@ -0,0 +1,135 @@ +local F = minetest.formspec_escape + +-- Create a detached inventory +local inv_everything = minetest.create_detached_inventory("everything", { + allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) + return 0 + end, + allow_put = function(inv, listname, index, stack, player) + return 0 + end, + allow_take = function(inv, listname, index, stack, player) + return -1 + end, +}) +local inv_trash = minetest.create_detached_inventory("trash", { + allow_take = function(inv, listname, index, stack, player) + return 0 + end, + allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) + return 0 + end, + on_put = function(inv, listname, index, stack, player) + inv:set_list("main", {}) + end, +}) +inv_trash:set_size("main", 1) + +local max_page = 1 + +local function get_chest_formspec(page) + local start = 0 + (page-1)*32 + return "size[8,9]".. + "list[detached:everything;main;0,0;8,4;"..start.."]".. + "list[current_player;main;0,5;8,4;]" .. + "label[6,4;Trash:]" .. + "list[detached:trash;main;7,4;1,1]" .. + "button[0,4;1,1;chest_of_everything_prev;"..F("<").."]".. + "button[1,4;1,1;chest_of_everything_next;"..F(">").."]".. + "label[2,4;"..F("Page: "..page).."]".. + "listring[detached:everything;main]".. + "listring[current_player;main]".. + "listring[detached:trash;main]" +end + +minetest.register_node("chest_of_everything:chest", { + description = "Chest of Everything", + tiles ={"chest_of_everything_chest.png^[sheet:2x2:0,0", "chest_of_everything_chest.png^[sheet:2x2:0,0", + "chest_of_everything_chest.png^[sheet:2x2:1,0", "chest_of_everything_chest.png^[sheet:2x2:1,0", + "chest_of_everything_chest.png^[sheet:2x2:1,0", "chest_of_everything_chest.png^[sheet:2x2:0,1"}, + paramtype2 = "facedir", + groups = {dig_immediate=2,choppy=3}, + is_ground_content = false, + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", "Chest of Everything") + meta:set_int("page", 1) + meta:set_string("formspec", get_chest_formspec(1)) + end, + on_receive_fields = function(pos, formname, fields, sender) + if formname == "" then + local meta = minetest.get_meta(pos) + local page = meta:get_int("page") + if fields.chest_of_everything_prev then + page = page - 1 + elseif fields.chest_of_everything_next then + page = page + 1 + end + if page < 1 then + page = 1 + end + if page > max_page then + page = max_page + end + meta:set_int("page", page) + meta:set_string("formspec", get_chest_formspec(page)) + end + end, +}) + +minetest.register_on_mods_loaded(function() + local items = {} + for itemstring,_ in pairs(minetest.registered_items) do + if itemstring ~= "" and itemstring ~= "unknown" and itemstring ~= "ignore" then + table.insert(items, itemstring) + end + end + --[[ Sort items in this order: + * Chest of Everything + * Test tools + * Other tools + * Craftitems + * Other items + * Dummy items ]] + local function compare(item1, item2) + local def1 = minetest.registered_items[item1] + local def2 = minetest.registered_items[item2] + local tool1 = def1.type == "tool" + local tool2 = def2.type == "tool" + local testtool1 = minetest.get_item_group(item1, "testtool") == 1 + local testtool2 = minetest.get_item_group(item2, "testtool") == 1 + local dummy1 = minetest.get_item_group(item1, "dummy") == 1 + local dummy2 = minetest.get_item_group(item2, "dummy") == 1 + local craftitem1 = def1.type == "craft" + local craftitem2 = def2.type == "craft" + if item1 == "chest_of_everything:chest" then + return true + elseif item2 == "chest_of_everything:chest" then + return false + elseif dummy1 and not dummy2 then + return false + elseif not dummy1 and dummy2 then + return true + elseif testtool1 and not testtool2 then + return true + elseif not testtool1 and testtool2 then + return false + elseif tool1 and not tool2 then + return true + elseif not tool1 and tool2 then + return false + elseif craftitem1 and not craftitem2 then + return true + elseif not craftitem1 and craftitem2 then + return false + else + return item1 < item2 + end + end + table.sort(items, compare) + inv_everything:set_size("main", #items) + max_page = math.ceil(#items / 32) + for i=1, #items do + inv_everything:add_item("main", items[i]) + end +end) diff --git a/games/devtest/mods/chest_of_everything/mod.conf b/games/devtest/mods/chest_of_everything/mod.conf new file mode 100644 index 000000000..4a4425e05 --- /dev/null +++ b/games/devtest/mods/chest_of_everything/mod.conf @@ -0,0 +1,2 @@ +name = chest_of_everything +description = Adds the chest of everything from which you can take all items diff --git a/games/devtest/mods/chest_of_everything/textures/chest_of_everything_chest.png b/games/devtest/mods/chest_of_everything/textures/chest_of_everything_chest.png new file mode 100644 index 000000000..6b2fd58d5 Binary files /dev/null and b/games/devtest/mods/chest_of_everything/textures/chest_of_everything_chest.png differ diff --git a/games/devtest/mods/dignodes/init.lua b/games/devtest/mods/dignodes/init.lua new file mode 100644 index 000000000..833150873 --- /dev/null +++ b/games/devtest/mods/dignodes/init.lua @@ -0,0 +1,37 @@ +local groups = { + "cracky", "dig_immediate" +} + +-- Register dig nodes with 1 digging group, a rating between 1-3 and a level between 0-2 +for g=1, #groups do + local gr = groups[g] + for r=1, 3 do + for l=0, 2 do + if not (gr=="dig_immediate" and (l>0 or r==1)) then + local d + if l > 0 then + d = string.format("Dig Test Node: %s=%d, level=%d", gr, r, l) + else + d = string.format("Dig Test Node: %s=%d", gr, r) + end + local tile = "dignodes_"..gr..".png^dignodes_rating"..r..".png" + if l==1 then + tile = tile .. "^[colorize:#FFFF00:127" + elseif l==2 then + tile = tile .. "^[colorize:#FF0000:127" + end + minetest.register_node("dignodes:"..gr.."_"..r.."_"..l, { + description = d, + tiles = { tile }, + groups = { [gr] = r, level = l }, + }) + end + end + end +end + +-- Node without any digging groups +minetest.register_node("dignodes:none", { + description = "Dig Test Node: groupless", + tiles = {"dignodes_none.png"}, +}) diff --git a/games/devtest/mods/dignodes/mod.conf b/games/devtest/mods/dignodes/mod.conf new file mode 100644 index 000000000..52a80d66e --- /dev/null +++ b/games/devtest/mods/dignodes/mod.conf @@ -0,0 +1,2 @@ +name = dignodes +description = Nodes with different digging groups diff --git a/games/devtest/mods/dignodes/textures/dignodes_choppy.png b/games/devtest/mods/dignodes/textures/dignodes_choppy.png new file mode 100644 index 000000000..a73fc2424 Binary files /dev/null and b/games/devtest/mods/dignodes/textures/dignodes_choppy.png differ diff --git a/games/devtest/mods/dignodes/textures/dignodes_cracky.png b/games/devtest/mods/dignodes/textures/dignodes_cracky.png new file mode 100644 index 000000000..eb84e3079 Binary files /dev/null and b/games/devtest/mods/dignodes/textures/dignodes_cracky.png differ diff --git a/games/devtest/mods/dignodes/textures/dignodes_crumbly.png b/games/devtest/mods/dignodes/textures/dignodes_crumbly.png new file mode 100644 index 000000000..23f2f7c71 Binary files /dev/null and b/games/devtest/mods/dignodes/textures/dignodes_crumbly.png differ diff --git a/games/devtest/mods/dignodes/textures/dignodes_dig_immediate.png b/games/devtest/mods/dignodes/textures/dignodes_dig_immediate.png new file mode 100644 index 000000000..a532ad90b Binary files /dev/null and b/games/devtest/mods/dignodes/textures/dignodes_dig_immediate.png differ diff --git a/games/devtest/mods/dignodes/textures/dignodes_none.png b/games/devtest/mods/dignodes/textures/dignodes_none.png new file mode 100644 index 000000000..60f13650b Binary files /dev/null and b/games/devtest/mods/dignodes/textures/dignodes_none.png differ diff --git a/games/devtest/mods/dignodes/textures/dignodes_rating1.png b/games/devtest/mods/dignodes/textures/dignodes_rating1.png new file mode 100644 index 000000000..d2fee3a23 Binary files /dev/null and b/games/devtest/mods/dignodes/textures/dignodes_rating1.png differ diff --git a/games/devtest/mods/dignodes/textures/dignodes_rating2.png b/games/devtest/mods/dignodes/textures/dignodes_rating2.png new file mode 100644 index 000000000..15329b93f Binary files /dev/null and b/games/devtest/mods/dignodes/textures/dignodes_rating2.png differ diff --git a/games/devtest/mods/dignodes/textures/dignodes_rating3.png b/games/devtest/mods/dignodes/textures/dignodes_rating3.png new file mode 100644 index 000000000..37216bfd1 Binary files /dev/null and b/games/devtest/mods/dignodes/textures/dignodes_rating3.png differ diff --git a/games/devtest/mods/experimental/commands.lua b/games/devtest/mods/experimental/commands.lua new file mode 100644 index 000000000..96f8cbe39 --- /dev/null +++ b/games/devtest/mods/experimental/commands.lua @@ -0,0 +1,215 @@ +minetest.register_chatcommand("test_inv", { + params = "", + description = "Test: Modify player's inventory formspec", + func = function(name, param) + local player = minetest.get_player_by_name(name) + if not player then + return false, "No player." + end + player:set_inventory_formspec( + "size[13,7.5]".. + "image[6,0.6;1,2;player.png]".. + "list[current_player;main;5,3.5;8,4;]".. + "list[current_player;craft;8,0;3,3;]".. + "list[current_player;craftpreview;12,1;1,1;]".. + "list[detached:test_inventory;main;0,0;4,6;0]".. + "button[0.5,7;2,1;button1;Button 1]".. + "button_exit[2.5,7;2,1;button2;Exit Button]") + return true, "Done." + end, +}) + +minetest.register_chatcommand("test_bulk_set_node", { + params = "", + description = "Test: Bulk-set 9×9×9 stone nodes", + func = function(name, param) + local player = minetest.get_player_by_name(name) + if not player then + return false, "No player." + end + local pos_list = {} + local ppos = player:get_pos() + local i = 1 + for x=2,10 do + for y=2,10 do + for z=2,10 do + pos_list[i] = {x=ppos.x + x,y = ppos.y + y,z = ppos.z + z} + i = i + 1 + end + end + end + minetest.bulk_set_node(pos_list, {name = "mapgen_stone"}) + return true, "Done." + end, +}) + +minetest.register_chatcommand("bench_bulk_set_node", { + params = "", + description = "Benchmark: Bulk-set 99×99×99 stone nodes", + func = function(name, param) + local player = minetest.get_player_by_name(name) + if not player then + return false, "No player." + end + local pos_list = {} + local ppos = player:get_pos() + local i = 1 + for x=2,100 do + for y=2,100 do + for z=2,100 do + pos_list[i] = {x=ppos.x + x,y = ppos.y + y,z = ppos.z + z} + i = i + 1 + end + end + end + + minetest.chat_send_player(name, "Benchmarking minetest.bulk_set_node. Warming up ..."); + + -- warm up with stone to prevent having different callbacks + -- due to different node topology + minetest.bulk_set_node(pos_list, {name = "mapgen_stone"}) + + minetest.chat_send_player(name, "Warming up finished, now benchmarking ..."); + + local start_time = minetest.get_us_time() + for i=1,#pos_list do + minetest.set_node(pos_list[i], {name = "mapgen_stone"}) + end + local middle_time = minetest.get_us_time() + minetest.bulk_set_node(pos_list, {name = "mapgen_stone"}) + local end_time = minetest.get_us_time() + local msg = string.format("Benchmark results: minetest.set_node loop: %.2f ms; minetest.bulk_set_node: %.2f ms", + ((middle_time - start_time)) / 1000, + ((end_time - middle_time)) / 1000 + ) + return true, msg + end, +}) + +local function advance_pos(pos, start_pos, advance_z) + if advance_z then + pos.z = pos.z + 2 + pos.x = start_pos.x + else + pos.x = pos.x + 2 + end + if pos.x > 30900 or pos.x - start_pos.x > 46 then + pos.x = start_pos.x + pos.z = pos.z + 2 + end + if pos.z > 30900 then + -- We ran out of space! Aborting + aborted = true + return false + end + return pos +end + +local function place_nodes(param) + local nodes = param.nodes + local name = param.name + local pos = param.pos + local start_pos = param.start_pos + table.sort(nodes) + minetest.chat_send_player(name, "Placing nodes …") + local nodes_placed = 0 + for n=1, #nodes do + local itemstring = nodes[n] + local def = minetest.registered_nodes[itemstring] + local p2_max = 0 + if param.param ~= "no_param2" then + -- Also test the param2 values of the nodes + -- ... but we only use permissible param2 values + if def.paramtype2 == "wallmounted" then + p2_max = 5 + elseif def.paramtype2 == "facedir" then + p2_max = 23 + elseif def.paramtype2 == "glasslikeliquidlevel" then + p2_max = 63 + elseif def.paramtype2 == "meshoptions" and def.drawtype == "plantlike" then + p2_max = 63 + elseif def.paramtype2 == "leveled" then + p2_max = 127 + elseif def.paramtype2 == "degrotate" and def.drawtype == "plantlike" then + p2_max = 179 + elseif def.paramtype2 == "colorfacedir" or + def.paramtype2 == "colorwallmounted" or + def.paramtype2 == "color" then + p2_max = 255 + end + end + for p2 = 0, p2_max do + -- Skip undefined param2 values + if not ((def.paramtype2 == "meshoptions" and p2 % 8 > 4) or + (def.paramtype2 == "colorwallmounted" and p2 % 8 > 5) or + (def.paramtype2 == "colorfacedir" and p2 % 32 > 23)) then + + minetest.set_node(pos, { name = itemstring, param2 = p2 }) + nodes_placed = nodes_placed + 1 + pos = advance_pos(pos, start_pos) + if not pos then + aborted = true + break + end + end + end + if aborted then + break + end + end + if aborted then + minetest.chat_send_player(name, "Not all nodes could be placed, please move further away from the world boundary. Nodes placed: "..nodes_placed) + end + minetest.chat_send_player(name, "Nodes placed: "..nodes_placed..".") +end + +local function after_emerge(blockpos, action, calls_remaining, param) + if calls_remaining == 0 then + place_nodes(param) + end +end + +minetest.register_chatcommand("test_place_nodes", { + params = "[ no_param2 ]", + description = "Test: Place all non-experimental nodes and optionally their permissible param2 variants", + func = function(name, param) + local player = minetest.get_player_by_name(name) + if not player then + return false, "No player." + end + local pos = vector.floor(player:get_pos()) + pos.x = math.ceil(pos.x + 3) + pos.z = math.ceil(pos.z + 3) + pos.y = math.ceil(pos.y + 1) + local start_pos = table.copy(pos) + if pos.x > 30800 then + return false, "Too close to world boundary (+X). Please move to X < 30800." + end + if pos.z > 30800 then + return false, "Too close to world boundary (+Z). Please move to Z < 30800." + end + + local aborted = false + local nodes = {} + local emerge_estimate = 0 + for itemstring, def in pairs(minetest.registered_nodes) do + if itemstring ~= "ignore" and string.sub(itemstring, 1, 13) ~= "experimental:" then + table.insert(nodes, itemstring) + if def.paramtype2 == 0 then + emerge_estimate = emerge_estimate + 1 + else + emerge_estimate = emerge_estimate + 255 + end + end + end + -- Emerge area to make sure that all nodes are being placed. + -- Note we will emerge much more than we need to (overestimation), + -- the estimation code could be improved performance-wise … + local length = 16 + math.ceil(emerge_estimate / 24) * 2 + minetest.emerge_area(start_pos, + { x = start_pos.x + 46, y = start_pos.y, z = start_pos.z + length }, + after_emerge, { nodes = nodes, name = name, pos = pos, start_pos = start_pos, param = param }) + return true, "Emerging area …" + end, +}) + diff --git a/games/devtest/mods/experimental/detached.lua b/games/devtest/mods/experimental/detached.lua new file mode 100644 index 000000000..673adfdd4 --- /dev/null +++ b/games/devtest/mods/experimental/detached.lua @@ -0,0 +1,29 @@ +-- Create a detached inventory +local inv = minetest.create_detached_inventory("test_inventory", { + allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) + experimental.print_to_everything("allow move asked") + return count -- Allow all + end, + allow_put = function(inv, listname, index, stack, player) + experimental.print_to_everything("allow put asked") + return 1 -- Allow only 1 + end, + allow_take = function(inv, listname, index, stack, player) + experimental.print_to_everything("allow take asked") + return 4 -- Allow 4 at max + end, + on_move = function(inv, from_list, from_index, to_list, to_index, count, player) + experimental.print_to_everything(player:get_player_name().." moved items") + end, + on_put = function(inv, listname, index, stack, player) + experimental.print_to_everything(player:get_player_name().." put items") + end, + on_take = function(inv, listname, index, stack, player) + experimental.print_to_everything(player:get_player_name().." took items") + end, +}) +inv:set_size("main", 4*6) +inv:add_item("main", "experimental:callback_node") +inv:add_item("main", "experimental:particle_spawner") + + diff --git a/games/devtest/mods/experimental/init.lua b/games/devtest/mods/experimental/init.lua new file mode 100644 index 000000000..b292f792e --- /dev/null +++ b/games/devtest/mods/experimental/init.lua @@ -0,0 +1,23 @@ +-- +-- Experimental things +-- + +experimental = {} + +dofile(minetest.get_modpath("experimental").."/detached.lua") +dofile(minetest.get_modpath("experimental").."/items.lua") +dofile(minetest.get_modpath("experimental").."/commands.lua") + +function experimental.print_to_everything(msg) + minetest.log("action", msg) + minetest.chat_send_all(msg) +end + +minetest.log("info", "[experimental] modname="..dump(minetest.get_current_modname())) +minetest.log("info", "[experimental] modpath="..dump(minetest.get_modpath("experimental"))) +minetest.log("info", "[experimental] worldpath="..dump(minetest.get_worldpath())) + + +minetest.register_on_mods_loaded(function() + minetest.log("action", "[experimental] on_mods_loaded()") +end) diff --git a/games/devtest/mods/experimental/items.lua b/games/devtest/mods/experimental/items.lua new file mode 100644 index 000000000..51b063ba2 --- /dev/null +++ b/games/devtest/mods/experimental/items.lua @@ -0,0 +1,103 @@ +minetest.register_node("experimental:callback_node", { + description = "Callback Test Node (construct/destruct/timer)", + tiles = {"experimental_callback_node.png"}, + groups = {dig_immediate=3}, + -- This was known to cause a bug in minetest.item_place_node() when used + -- via minetest.place_node(), causing a placer with no position + paramtype2 = "facedir", + drop = "", + + on_construct = function(pos) + experimental.print_to_everything("experimental:callback_node:on_construct("..minetest.pos_to_string(pos)..")") + local meta = minetest.get_meta(pos) + meta:set_string("mine", "test") + local timer = minetest.get_node_timer(pos) + timer:start(4, 3) + end, + + after_place_node = function(pos, placer) + experimental.print_to_everything("experimental:callback_node:after_place_node("..minetest.pos_to_string(pos)..")") + local meta = minetest.get_meta(pos) + if meta:get_string("mine") == "test" then + experimental.print_to_everything("correct metadata found") + else + experimental.print_to_everything("incorrect metadata found") + end + end, + + on_destruct = function(pos) + experimental.print_to_everything("experimental:callback_node:on_destruct("..minetest.pos_to_string(pos)..")") + end, + + after_destruct = function(pos) + experimental.print_to_everything("experimental:callback_node:after_destruct("..minetest.pos_to_string(pos)..")") + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + experimental.print_to_everything("experimental:callback_node:after_dig_node("..minetest.pos_to_string(pos)..")") + end, + + on_timer = function(pos, elapsed) + experimental.print_to_everything("on_timer(): elapsed="..dump(elapsed)) + return true + end, +}) + +minetest.register_tool("experimental:privatizer", { + description = "Node Meta Privatizer", + inventory_image = "experimental_tester_tool_1.png", + groups = { testtool = 1, disable_repair = 1 }, + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type == "node" then + local node = minetest.get_node(pointed_thing.under) + if node.name == "chest:chest" then + local p = pointed_thing.under + minetest.log("action", "Privatizer used at "..minetest.pos_to_string(p)) + minetest.get_meta(p):mark_as_private({"infotext", "formspec"}) + if user and user:is_player() then + minetest.chat_send_player(user:get_player_name(), "Chest metadata (infotext, formspec) set private!") + end + return + end + end + if user and user:is_player() then + minetest.chat_send_player(user:get_player_name(), "Privatizer can only be used on chest!") + end + end, +}) + +minetest.register_tool("experimental:particle_spawner", { + description = "Particle Spawner", + inventory_image = "experimental_tester_tool_1.png^[invert:g", + groups = { testtool = 1, disable_repair = 1 }, + on_use = function(itemstack, user, pointed_thing) + local pos = minetest.get_pointed_thing_position(pointed_thing, true) + if pos == nil then + if user then + pos = user:get_pos() + end + end + pos = vector.add(pos, {x=0, y=0.5, z=0}) + local tex, anim + if math.random(0, 1) == 0 then + tex = "experimental_particle_sheet.png" + anim = {type="sheet_2d", frames_w=3, frames_h=2, frame_length=0.5} + else + tex = "experimental_particle_vertical.png" + anim = {type="vertical_frames", aspect_w=16, aspect_h=16, length=3.3} + end + + minetest.add_particle({ + pos = pos, + velocity = {x=0, y=0, z=0}, + acceleration = {x=0, y=0.04, z=0}, + expirationtime = 6, + collisiondetection = true, + texture = tex, + animation = anim, + size = 4, + glow = math.random(0, 5), + }) + end, +}) + diff --git a/games/devtest/mods/experimental/mod.conf b/games/devtest/mods/experimental/mod.conf new file mode 100644 index 000000000..cf0f9cb42 --- /dev/null +++ b/games/devtest/mods/experimental/mod.conf @@ -0,0 +1,2 @@ +name = experimental +description = Chaotic mod containing unstructured tests for testing out engine features. The features in this mod should be moved to other mods. diff --git a/games/devtest/mods/experimental/textures/experimental_callback_node.png b/games/devtest/mods/experimental/textures/experimental_callback_node.png new file mode 100644 index 000000000..e9d87434c Binary files /dev/null and b/games/devtest/mods/experimental/textures/experimental_callback_node.png differ diff --git a/games/devtest/mods/experimental/textures/experimental_particle_sheet.png b/games/devtest/mods/experimental/textures/experimental_particle_sheet.png new file mode 100644 index 000000000..6d70394e4 Binary files /dev/null and b/games/devtest/mods/experimental/textures/experimental_particle_sheet.png differ diff --git a/games/devtest/mods/experimental/textures/experimental_particle_vertical.png b/games/devtest/mods/experimental/textures/experimental_particle_vertical.png new file mode 100644 index 000000000..0320b7545 Binary files /dev/null and b/games/devtest/mods/experimental/textures/experimental_particle_vertical.png differ diff --git a/games/devtest/mods/experimental/textures/experimental_tester_tool_1.png b/games/devtest/mods/experimental/textures/experimental_tester_tool_1.png new file mode 100644 index 000000000..5df416a58 Binary files /dev/null and b/games/devtest/mods/experimental/textures/experimental_tester_tool_1.png differ diff --git a/games/devtest/mods/give_initial_stuff/init.lua b/games/devtest/mods/give_initial_stuff/init.lua new file mode 100644 index 000000000..491a531e4 --- /dev/null +++ b/games/devtest/mods/give_initial_stuff/init.lua @@ -0,0 +1,37 @@ +local give_if_not_gotten_already = function(inv, list, item) + if not inv:contains_item(list, item) then + inv:add_item(list, item) + end +end + +local give_initial_stuff = function(player) + local inv = player:get_inventory() + give_if_not_gotten_already(inv, "main", "basetools:pick_mese") + give_if_not_gotten_already(inv, "main", "basetools:axe_steel") + give_if_not_gotten_already(inv, "main", "basetools:shovel_steel") + give_if_not_gotten_already(inv, "main", "bucket:bucket") + give_if_not_gotten_already(inv, "main", "testnodes:light14") + give_if_not_gotten_already(inv, "main", "chest_of_everything:chest") + minetest.log("action", "[give_initial_stuff] Giving initial stuff to "..player:get_player_name()) +end + +minetest.register_on_newplayer(function(player) + if minetest.settings:get_bool("give_initial_stuff", true) then + give_initial_stuff(player) + end +end) + +minetest.register_chatcommand("stuff", { + params = "", + privs = { give = true }, + description = "Give yourself initial items", + func = function(name, param) + local player = minetest.get_player_by_name(name) + if not player or not player:is_player() then + return false, "No player." + end + give_initial_stuff(player) + return true + end, +}) + diff --git a/games/devtest/mods/give_initial_stuff/mod.conf b/games/devtest/mods/give_initial_stuff/mod.conf new file mode 100644 index 000000000..1ba49f52a --- /dev/null +++ b/games/devtest/mods/give_initial_stuff/mod.conf @@ -0,0 +1,3 @@ +name = give_initial_stuff +description = Gives items to players on join +depends = basetools, bucket, chest_of_everything, testnodes diff --git a/games/devtest/mods/initial_message/init.lua b/games/devtest/mods/initial_message/init.lua new file mode 100644 index 000000000..59e9f5f4b --- /dev/null +++ b/games/devtest/mods/initial_message/init.lua @@ -0,0 +1,9 @@ +minetest.register_on_joinplayer(function(player) + local cb = function(player) + if not player or not player:is_player() then + return + end + minetest.chat_send_player(player:get_player_name(), "This is the \"Development Test\" [devtest], meant only for testing and development. Use Minetest Game for the real thing.") + end + minetest.after(2.0, cb, player) +end) diff --git a/games/devtest/mods/initial_message/mod.conf b/games/devtest/mods/initial_message/mod.conf new file mode 100644 index 000000000..32aa2ac4e --- /dev/null +++ b/games/devtest/mods/initial_message/mod.conf @@ -0,0 +1,2 @@ +name = initial_message +description = Show message to joining players explaining what this testing game is about diff --git a/games/devtest/mods/mapgen/init.lua b/games/devtest/mods/mapgen/init.lua new file mode 100644 index 000000000..13a186a50 --- /dev/null +++ b/games/devtest/mods/mapgen/init.lua @@ -0,0 +1,81 @@ +-- +-- Aliases for map generator outputs +-- + +-- ESSENTIAL node aliases +-- Basic nodes +minetest.register_alias("mapgen_stone", "basenodes:stone") +minetest.register_alias("mapgen_water_source", "basenodes:water_source") +minetest.register_alias("mapgen_river_water_source", "basenodes:river_water_source") + +-- Additional essential aliases for v6 +minetest.register_alias("mapgen_lava_source", "basenodes:lava_source") +minetest.register_alias("mapgen_dirt", "basenodes:dirt") +minetest.register_alias("mapgen_dirt_with_grass", "basenodes:dirt_with_grass") +minetest.register_alias("mapgen_sand", "basenodes:sand") +minetest.register_alias("mapgen_tree", "basenodes:tree") +minetest.register_alias("mapgen_leaves", "basenodes:leaves") +minetest.register_alias("mapgen_apple", "basenodes:apple") + +-- Essential alias for dungeons +minetest.register_alias("mapgen_cobble", "basenodes:cobble") + +-- Optional aliases for v6 (they all have fallback values in the engine) +if minetest.settings:get_bool("devtest_v6_mapgen_aliases", false) then + minetest.register_alias("mapgen_gravel", "basenodes:gravel") + minetest.register_alias("mapgen_desert_stone", "basenodes:desert_stone") + minetest.register_alias("mapgen_desert_sand", "basenodes:desert_sand") + minetest.register_alias("mapgen_dirt_with_snow", "basenodes:dirt_with_snow") + minetest.register_alias("mapgen_snowblock", "basenodes:snowblock") + minetest.register_alias("mapgen_snow", "basenodes:snow") + minetest.register_alias("mapgen_ice", "basenodes:ice") + minetest.register_alias("mapgen_junglegrass", "basenodes:junglegrass") + minetest.register_alias("mapgen_jungletree", "basenodes:jungletree") + minetest.register_alias("mapgen_jungleleaves", "basenodes:jungleleaves") + minetest.register_alias("mapgen_pine_tree", "basenodes:pine_tree") + minetest.register_alias("mapgen_pine_needles", "basenodes:pine_needles") +end +-- Optional alias for mossycobble (should fall back to cobble) +if minetest.settings:get_bool("devtest_dungeon_mossycobble", false) then + minetest.register_alias("mapgen_mossycobble", "basenodes:mossycobble") +end +-- Optional aliases for dungeon stairs (should fall back to full nodes) +if minetest.settings:get_bool("devtest_dungeon_stairs", false) then + minetest.register_alias("mapgen_stair_cobble", "stairs:stair_cobble") + if minetest.settings:get_bool("devtest_v6_mapgen_aliases", false) then + minetest.register_alias("mapgen_stair_desert_stone", "stairs:stair_desert_stone") + end +end + +-- +-- Register biomes for biome API +-- + +minetest.clear_registered_biomes() +minetest.clear_registered_decorations() + +if minetest.settings:get_bool("devtest_register_biomes", true) then + minetest.register_biome({ + name = "mapgen:grassland", + node_top = "basenodes:dirt_with_grass", + depth_top = 1, + node_filler = "basenodes:dirt", + depth_filler = 1, + y_min = 5, + y_max = 31000, + heat_point = 50, + humidity_point = 50, + }) + + minetest.register_biome({ + name = "mapgen:grassland_ocean", + node_top = "basenodes:sand", + depth_top = 1, + node_filler = "basenodes:sand", + depth_filler = 2, + y_min = -31000, + y_max = 4, + heat_point = 50, + humidity_point = 50, + }) +end diff --git a/games/devtest/mods/mapgen/mod.conf b/games/devtest/mods/mapgen/mod.conf new file mode 100644 index 000000000..15750ccbe --- /dev/null +++ b/games/devtest/mods/mapgen/mod.conf @@ -0,0 +1,3 @@ +name = mapgen +description = Minimal map generator +depends = basenodes diff --git a/games/devtest/mods/modchannels/init.lua b/games/devtest/mods/modchannels/init.lua new file mode 100644 index 000000000..ee925f09b --- /dev/null +++ b/games/devtest/mods/modchannels/init.lua @@ -0,0 +1,14 @@ +-- +-- Mod channels experimental handlers +-- +local mod_channel = minetest.mod_channel_join("experimental_preview") + +minetest.register_on_modchannel_message(function(channel, sender, message) + minetest.log("action", "[modchannels] Server received message `" .. message + .. "` on channel `" .. channel .. "` from sender `" .. sender .. "`") + + if mod_channel:is_writeable() then + mod_channel:send_all("experimental answers to preview") + mod_channel:leave() + end +end) diff --git a/games/devtest/mods/modchannels/mod.conf b/games/devtest/mods/modchannels/mod.conf new file mode 100644 index 000000000..7c13aadfb --- /dev/null +++ b/games/devtest/mods/modchannels/mod.conf @@ -0,0 +1,2 @@ +name = modchannels +description = Add experimental mod channel handlers diff --git a/games/devtest/mods/soundstuff/init.lua b/games/devtest/mods/soundstuff/init.lua new file mode 100644 index 000000000..22012ba14 --- /dev/null +++ b/games/devtest/mods/soundstuff/init.lua @@ -0,0 +1,170 @@ +local simple_nodes = { + footstep = { "Footstep Sound Node", "soundstuff_node_footstep.png" }, + dig = { "Dig Sound Node", "soundstuff_node_dig.png" }, + dug = { "Dug Sound Node", "soundstuff_node_dug.png" }, + place = { "Place Sound Node", "soundstuff_node_place.png" }, + place_failed = { "Place Failed Sound Node", "soundstuff_node_place_failed.png" }, +} + +for k,v in pairs(simple_nodes) do + minetest.register_node("soundstuff:"..k, { + description = v[1], + tiles = {"soundstuff_node_sound.png","soundstuff_node_sound.png",v[2]}, + groups = {dig_immediate=2}, + sounds = { + [k] = { name = "soundstuff_mono", gain = 1.0 }, + } + }) +end + +minetest.register_node("soundstuff:place_failed_attached", { + description = "Attached Place Failed Sound Node", + tiles = {"soundstuff_node_sound.png", "soundstuff_node_sound.png", "soundstuff_node_place_failed.png"}, + groups = {dig_immediate=2, attached_node=1}, + drawtype = "nodebox", + paramtype = "light", + node_box = { type = "fixed", fixed = { + { -7/16, -7/16, -7/16, 7/16, 7/16, 7/16 }, + { -0.5, -0.5, -0.5, 0.5, -7/16, 0.5 }, + }}, + sounds = { + place_failed = { name = "soundstuff_mono", gain = 1.0 }, + }, +}) + +minetest.register_node("soundstuff:fall", { + description = "Fall Sound Node", + tiles = {"soundstuff_node_sound.png", "soundstuff_node_sound.png", "soundstuff_node_fall.png"}, + groups = {dig_immediate=2, falling_node=1}, + sounds = { + fall = { name = "soundstuff_mono", gain = 1.0 }, + } +}) + +minetest.register_node("soundstuff:fall_attached", { + description = "Attached Fall Sound Node", + tiles = {"soundstuff_node_sound.png", "soundstuff_node_sound.png", "soundstuff_node_fall.png"}, + groups = {dig_immediate=2, attached_node=1}, + drawtype = "nodebox", + paramtype = "light", + node_box = { type = "fixed", fixed = { + { -7/16, -7/16, -7/16, 7/16, 7/16, 7/16 }, + { -0.5, -0.5, -0.5, 0.5, -7/16, 0.5 }, + }}, + sounds = { + fall = { name = "soundstuff_mono", gain = 1.0 }, + } +}) + +minetest.register_node("soundstuff:footstep_liquid", { + description = "Liquid Footstep Sound Node", + drawtype = "liquid", + tiles = { + "soundstuff_node_sound.png^[colorize:#0000FF:127", + }, + special_tiles = { + {name = "soundstuff_node_sound.png^[colorize:#0000FF:127", backface_culling = false}, + {name = "soundstuff_node_sound.png^[colorize:#0000FF:127", backface_culling = true}, + }, + liquids_pointable = true, + liquidtype = "source", + liquid_alternative_flowing = "soundstuff:footstep_liquid", + liquid_alternative_source = "soundstuff:footstep_liquid", + liquid_renewable = false, + liquid_range = 0, + liquid_viscosity = 0, + alpha = 190, + paramtype = "light", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + post_effect_color = {a = 64, r = 0, g = 0, b = 200}, + sounds = { + footstep = { name = "soundstuff_mono", gain = 1.0 }, + } +}) + +minetest.register_node("soundstuff:footstep_climbable", { + description = "Climbable Footstep Sound Node", + drawtype = "allfaces", + tiles = { + "soundstuff_node_climbable.png", + }, + alpha = 120, + paramtype = "light", + sunlight_propagates = true, + walkable = false, + climbable = true, + is_ground_content = false, + groups = { dig_immediate = 2 }, + sounds = { + footstep = { name = "soundstuff_mono", gain = 1.0 }, + } +}) + + + +minetest.register_craftitem("soundstuff:eat", { + description = "Eat Sound Item", + inventory_image = "soundstuff_eat.png", + on_use = minetest.item_eat(0), + sound = { + eat = { name = "soundstuff_mono", gain = 1.0 }, + } +}) + +minetest.register_tool("soundstuff:breaks", { + description = "Break Sound Tool", + inventory_image = "soundstuff_node_dug.png", + sound = { + breaks = { name = "soundstuff_mono", gain = 1.0 }, + }, + tool_capabilities = { + max_drop_level=0, + groupcaps={ + cracky={times={[2]=2.00, [3]=1.20}, uses=1, maxlevel=0}, + choppy={times={[2]=2.00, [3]=1.20}, uses=1, maxlevel=0}, + snappy={times={[2]=2.00, [3]=1.20}, uses=1, maxlevel=0}, + crumbly={times={[2]=2.00, [3]=1.20}, uses=1, maxlevel=0}, + }, + }, +}) + +-- Plays sound repeatedly +minetest.register_node("soundstuff:positional", { + description = "Positional Sound Node", + on_construct = function(pos) + local timer = minetest.get_node_timer(pos) + timer:start(0) + end, + on_timer = function(pos, elapsed) + local node = minetest.get_node(pos) + local dist = node.param2 + if dist == 0 then + dist = nil + end + minetest.sound_play("soundstuff_mono", { pos = pos, max_hear_distance = dist }) + local timer = minetest.get_node_timer(pos) + timer:start(0.7) + end, + on_rightclick = function(pos, node, clicker) + node.param2 = (node.param2 + 1) % 64 + minetest.set_node(pos, node) + if clicker and clicker:is_player() then + local dist = node.param2 + local diststr + if dist == 0 then + diststr = "" + else + diststr = tostring(dist) + end + minetest.chat_send_player(clicker:get_player_name(), "max_hear_distance = " .. diststr) + end + end, + + groups = { dig_immediate = 2 }, + tiles = { "soundstuff_node_sound.png" }, +}) + diff --git a/games/devtest/mods/soundstuff/mod.conf b/games/devtest/mods/soundstuff/mod.conf new file mode 100644 index 000000000..2c631e2da --- /dev/null +++ b/games/devtest/mods/soundstuff/mod.conf @@ -0,0 +1,2 @@ +name = soundstuff +description = Example items and nodes for testing sound effects diff --git a/games/devtest/mods/soundstuff/sounds/soundstuff_mono.ogg b/games/devtest/mods/soundstuff/sounds/soundstuff_mono.ogg new file mode 100644 index 000000000..43428d566 Binary files /dev/null and b/games/devtest/mods/soundstuff/sounds/soundstuff_mono.ogg differ diff --git a/games/devtest/mods/soundstuff/textures/soundstuff_eat.png b/games/devtest/mods/soundstuff/textures/soundstuff_eat.png new file mode 100644 index 000000000..aed205422 Binary files /dev/null and b/games/devtest/mods/soundstuff/textures/soundstuff_eat.png differ diff --git a/games/devtest/mods/soundstuff/textures/soundstuff_node_blank.png b/games/devtest/mods/soundstuff/textures/soundstuff_node_blank.png new file mode 100644 index 000000000..4dffacc4c Binary files /dev/null and b/games/devtest/mods/soundstuff/textures/soundstuff_node_blank.png differ diff --git a/games/devtest/mods/soundstuff/textures/soundstuff_node_climbable.png b/games/devtest/mods/soundstuff/textures/soundstuff_node_climbable.png new file mode 100644 index 000000000..3888f793c Binary files /dev/null and b/games/devtest/mods/soundstuff/textures/soundstuff_node_climbable.png differ diff --git a/games/devtest/mods/soundstuff/textures/soundstuff_node_dig.png b/games/devtest/mods/soundstuff/textures/soundstuff_node_dig.png new file mode 100644 index 000000000..67ba111d8 Binary files /dev/null and b/games/devtest/mods/soundstuff/textures/soundstuff_node_dig.png differ diff --git a/games/devtest/mods/soundstuff/textures/soundstuff_node_dug.png b/games/devtest/mods/soundstuff/textures/soundstuff_node_dug.png new file mode 100644 index 000000000..bab5fbe51 Binary files /dev/null and b/games/devtest/mods/soundstuff/textures/soundstuff_node_dug.png differ diff --git a/games/devtest/mods/soundstuff/textures/soundstuff_node_fall.png b/games/devtest/mods/soundstuff/textures/soundstuff_node_fall.png new file mode 100644 index 000000000..17b14f1e4 Binary files /dev/null and b/games/devtest/mods/soundstuff/textures/soundstuff_node_fall.png differ diff --git a/games/devtest/mods/soundstuff/textures/soundstuff_node_footstep.png b/games/devtest/mods/soundstuff/textures/soundstuff_node_footstep.png new file mode 100644 index 000000000..6367ae909 Binary files /dev/null and b/games/devtest/mods/soundstuff/textures/soundstuff_node_footstep.png differ diff --git a/games/devtest/mods/soundstuff/textures/soundstuff_node_place.png b/games/devtest/mods/soundstuff/textures/soundstuff_node_place.png new file mode 100644 index 000000000..d159ad533 Binary files /dev/null and b/games/devtest/mods/soundstuff/textures/soundstuff_node_place.png differ diff --git a/games/devtest/mods/soundstuff/textures/soundstuff_node_place_failed.png b/games/devtest/mods/soundstuff/textures/soundstuff_node_place_failed.png new file mode 100644 index 000000000..780ba946d Binary files /dev/null and b/games/devtest/mods/soundstuff/textures/soundstuff_node_place_failed.png differ diff --git a/games/devtest/mods/soundstuff/textures/soundstuff_node_sound.png b/games/devtest/mods/soundstuff/textures/soundstuff_node_sound.png new file mode 100644 index 000000000..0592a0299 Binary files /dev/null and b/games/devtest/mods/soundstuff/textures/soundstuff_node_sound.png differ diff --git a/games/devtest/mods/stairs/init.lua b/games/devtest/mods/stairs/init.lua new file mode 100644 index 000000000..2701cabab --- /dev/null +++ b/games/devtest/mods/stairs/init.lua @@ -0,0 +1,65 @@ +stairs = {} + +-- Node will be called stairs:stair_ +function stairs.register_stair(subname, recipeitem, groups, images, description) + minetest.register_node(":stairs:stair_" .. subname, { + description = description, + drawtype = "nodebox", + tiles = images, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + {-0.5, 0, 0, 0.5, 0.5, 0.5}, + }, + }, + }) +end + +-- Node will be called stairs:slab_ +function stairs.register_slab(subname, recipeitem, groups, images, description) + minetest.register_node(":stairs:slab_" .. subname, { + description = description, + drawtype = "nodebox", + tiles = images, + paramtype = "light", + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + }, + }) +end + +-- Nodes will be called stairs:{stair,slab}_ +function stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab) + stairs.register_stair(subname, recipeitem, groups, images, desc_stair) + stairs.register_slab(subname, recipeitem, groups, images, desc_slab) +end + +stairs.register_stair_and_slab("stone", "basenodes:stone", + {cracky=3}, + {"default_stone.png"}, + "Stone Stair", + "Stone Slab") + +stairs.register_stair_and_slab("desert_stone", "basenodes:desert_stone", + {cracky=3}, + {"default_desert_stone.png"}, + "Desert Stone Stair", + "Desert Stone Slab") + +stairs.register_stair_and_slab("cobble", "basenodes:cobble", + {cracky=3}, + {"default_cobble.png"}, + "Cobblestone Stair", + "Cobblestone Slab") diff --git a/games/devtest/mods/stairs/mod.conf b/games/devtest/mods/stairs/mod.conf new file mode 100644 index 000000000..724bff881 --- /dev/null +++ b/games/devtest/mods/stairs/mod.conf @@ -0,0 +1,3 @@ +name = stairs +description = Adds stairs and slabs +depends = basenodes diff --git a/games/devtest/mods/testentities/armor.lua b/games/devtest/mods/testentities/armor.lua new file mode 100644 index 000000000..4c30cec8d --- /dev/null +++ b/games/devtest/mods/testentities/armor.lua @@ -0,0 +1,41 @@ +-- Armorball: Test entity for testing armor groups +-- Rightclick to change armor group + +local phasearmor = { + [0]={icy=100}, + [1]={firy=100}, + [2]={fleshy=100}, + [3]={immortal=1}, + [4]={punch_operable=1}, +} + +minetest.register_entity("testentities:armorball", { + initial_properties = { + hp_max = 20, + physical = false, + collisionbox = {-0.4,-0.4,-0.4, 0.4,0.4,0.4}, + visual = "sprite", + visual_size = {x=1, y=1}, + textures = {"testentities_armorball.png"}, + spritediv = {x=1, y=5}, + initial_sprite_basepos = {x=0, y=0}, + }, + + _phase = 2, + + on_activate = function(self, staticdata) + minetest.log("action", "[testentities] armorball.on_activate") + self.object:set_armor_groups(phasearmor[self._phase]) + self.object:set_sprite({x=0, y=self._phase}) + end, + + on_rightclick = function(self, clicker) + -- Change armor group and sprite + self._phase = self._phase + 1 + if self._phase >= 5 then + self._phase = 0 + end + self.object:set_sprite({x=0, y=self._phase}) + self.object:set_armor_groups(phasearmor[self._phase]) + end, +}) diff --git a/games/devtest/mods/testentities/callbacks.lua b/games/devtest/mods/testentities/callbacks.lua new file mode 100644 index 000000000..711079f87 --- /dev/null +++ b/games/devtest/mods/testentities/callbacks.lua @@ -0,0 +1,75 @@ +-- Entities that test their callbacks + +local message = function(msg) + minetest.log("action", msg) + minetest.chat_send_all(msg) +end + +local get_object_name = function(obj) + local name = "" + if obj then + if obj:is_player() then + name = obj:get_player_name() + else + name = "" + end + end + return name +end + +local spos = function(self) + return minetest.pos_to_string(vector.round(self.object:get_pos())) +end + +-- Callback test entity (all callbacks except on_step) +minetest.register_entity("testentities:callback", { + initial_properties = { + visual = "upright_sprite", + textures = { "testentities_callback.png" }, + }, + + on_activate = function(self, staticdata, dtime_s) + message("Callback entity: on_activate! pos="..spos(self).."; dtime_s="..dtime_s) + end, + on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage) + local name = get_object_name(puncher) + message( + "Callback entity: on_punch! ".. + "pos="..spos(self).."; puncher="..name.."; ".. + "time_from_last_punch="..time_from_last_punch.."; ".. + "tool_capabilities="..tostring(dump(tool_capabilities)).."; ".. + "dir="..tostring(dump(dir)).."; damage="..damage) + end, + on_rightclick = function(self, clicker) + local name = get_object_name(clicker) + message("Callback entity: on_rightclick! pos="..spos(self).."; clicker="..name) + end, + on_death = function(self, killer) + local name = get_object_name(killer) + message("Callback entity: on_death! pos="..spos(self).."; killer="..name) + end, + on_attach_child = function(self, child) + local name = get_object_name(child) + message("Callback entity: on_attach_child! pos="..spos(self).."; child="..name) + end, + on_detach_child = function(self, child) + local name = get_object_name(child) + message("Callback entity: on_detach_child! pos="..spos(self).."; child="..name) + end, + on_detach = function(self, parent) + local name = get_object_name(parent) + message("Callback entity: on_detach! pos="..spos(self).."; parent="..name) + end, + get_staticdata = function(self) + message("Callback entity: get_staticdata! pos="..spos(self)) + end, +}) + +-- Only test on_step callback +minetest.register_entity("testentities:callback_step", { + visual = "upright_sprite", + textures = { "testentities_callback_step.png" }, + on_step = function(self, dtime) + message("on_step callback entity: on_step! pos="..spos(self).."; dtime="..dtime) + end, +}) diff --git a/games/devtest/mods/testentities/init.lua b/games/devtest/mods/testentities/init.lua new file mode 100644 index 000000000..df8c72ea7 --- /dev/null +++ b/games/devtest/mods/testentities/init.lua @@ -0,0 +1,3 @@ +dofile(minetest.get_modpath("testentities").."/visuals.lua") +dofile(minetest.get_modpath("testentities").."/armor.lua") +dofile(minetest.get_modpath("testentities").."/callbacks.lua") diff --git a/games/devtest/mods/testentities/mod.conf b/games/devtest/mods/testentities/mod.conf new file mode 100644 index 000000000..7a8cb5a3e --- /dev/null +++ b/games/devtest/mods/testentities/mod.conf @@ -0,0 +1,2 @@ +name = testentities +description = Example entities for testing diff --git a/games/devtest/mods/testentities/textures/testentities_armorball.png b/games/devtest/mods/testentities/textures/testentities_armorball.png new file mode 100644 index 000000000..88147bd1f Binary files /dev/null and b/games/devtest/mods/testentities/textures/testentities_armorball.png differ diff --git a/games/devtest/mods/testentities/textures/testentities_callback.png b/games/devtest/mods/testentities/textures/testentities_callback.png new file mode 100644 index 000000000..c4c9066d1 Binary files /dev/null and b/games/devtest/mods/testentities/textures/testentities_callback.png differ diff --git a/games/devtest/mods/testentities/textures/testentities_callback_step.png b/games/devtest/mods/testentities/textures/testentities_callback_step.png new file mode 100644 index 000000000..b67506a97 Binary files /dev/null and b/games/devtest/mods/testentities/textures/testentities_callback_step.png differ diff --git a/games/devtest/mods/testentities/textures/testentities_cube1.png b/games/devtest/mods/testentities/textures/testentities_cube1.png new file mode 100644 index 000000000..c667e425f Binary files /dev/null and b/games/devtest/mods/testentities/textures/testentities_cube1.png differ diff --git a/games/devtest/mods/testentities/textures/testentities_cube2.png b/games/devtest/mods/testentities/textures/testentities_cube2.png new file mode 100644 index 000000000..481823420 Binary files /dev/null and b/games/devtest/mods/testentities/textures/testentities_cube2.png differ diff --git a/games/devtest/mods/testentities/textures/testentities_cube3.png b/games/devtest/mods/testentities/textures/testentities_cube3.png new file mode 100644 index 000000000..03b5daa15 Binary files /dev/null and b/games/devtest/mods/testentities/textures/testentities_cube3.png differ diff --git a/games/devtest/mods/testentities/textures/testentities_cube4.png b/games/devtest/mods/testentities/textures/testentities_cube4.png new file mode 100644 index 000000000..639204896 Binary files /dev/null and b/games/devtest/mods/testentities/textures/testentities_cube4.png differ diff --git a/games/devtest/mods/testentities/textures/testentities_cube5.png b/games/devtest/mods/testentities/textures/testentities_cube5.png new file mode 100644 index 000000000..d8acdf0b6 Binary files /dev/null and b/games/devtest/mods/testentities/textures/testentities_cube5.png differ diff --git a/games/devtest/mods/testentities/textures/testentities_cube6.png b/games/devtest/mods/testentities/textures/testentities_cube6.png new file mode 100644 index 000000000..5f81a64d9 Binary files /dev/null and b/games/devtest/mods/testentities/textures/testentities_cube6.png differ diff --git a/games/devtest/mods/testentities/textures/testentities_dungeon_master.png b/games/devtest/mods/testentities/textures/testentities_dungeon_master.png new file mode 100644 index 000000000..1e3107746 Binary files /dev/null and b/games/devtest/mods/testentities/textures/testentities_dungeon_master.png differ diff --git a/games/devtest/mods/testentities/textures/testentities_sprite.png b/games/devtest/mods/testentities/textures/testentities_sprite.png new file mode 100644 index 000000000..a4b019699 Binary files /dev/null and b/games/devtest/mods/testentities/textures/testentities_sprite.png differ diff --git a/games/devtest/mods/testentities/textures/testentities_upright_sprite1.png b/games/devtest/mods/testentities/textures/testentities_upright_sprite1.png new file mode 100644 index 000000000..6242511df Binary files /dev/null and b/games/devtest/mods/testentities/textures/testentities_upright_sprite1.png differ diff --git a/games/devtest/mods/testentities/textures/testentities_upright_sprite2.png b/games/devtest/mods/testentities/textures/testentities_upright_sprite2.png new file mode 100644 index 000000000..a79a760e3 Binary files /dev/null and b/games/devtest/mods/testentities/textures/testentities_upright_sprite2.png differ diff --git a/games/devtest/mods/testentities/visuals.lua b/games/devtest/mods/testentities/visuals.lua new file mode 100644 index 000000000..de346fd68 --- /dev/null +++ b/games/devtest/mods/testentities/visuals.lua @@ -0,0 +1,74 @@ +-- Minimal test entities to test visuals + +minetest.register_entity("testentities:sprite", { + initial_properties = { + visual = "sprite", + textures = { "testentities_sprite.png" }, + }, +}) + +minetest.register_entity("testentities:upright_sprite", { + initial_properties = { + visual = "upright_sprite", + textures = { + "testentities_upright_sprite1.png", + "testentities_upright_sprite2.png", + }, + }, +}) + +minetest.register_entity("testentities:cube", { + initial_properties = { + visual = "cube", + textures = { + "testentities_cube1.png", + "testentities_cube2.png", + "testentities_cube3.png", + "testentities_cube4.png", + "testentities_cube5.png", + "testentities_cube6.png", + }, + }, +}) + +minetest.register_entity("testentities:item", { + initial_properties = { + visual = "item", + wield_item = "testnodes:normal", + }, +}) + +minetest.register_entity("testentities:wielditem", { + initial_properties = { + visual = "wielditem", + wield_item = "testnodes:normal", + }, +}) + +minetest.register_entity("testentities:mesh", { + initial_properties = { + visual = "mesh", + mesh = "testnodes_pyramid.obj", + textures = { + "testnodes_mesh_stripes2.png" + }, + }, +}) + +-- Advanced visual tests + +-- A test entity for testing animated and yaw-modulated sprites +minetest.register_entity("testentities:yawsprite", { + initial_properties = { + selectionbox = {-0.3, -0.5, -0.3, 0.3, 0.3, 0.3}, + visual = "sprite", + visual_size = {x=0.6666, y=1}, + textures = {"testentities_dungeon_master.png^[makealpha:128,0,0^[makealpha:128,128,0"}, + spritediv = {x=6, y=5}, + initial_sprite_basepos = {x=0, y=0}, + on_activate = function(self, staticdata) + self.object:set_sprite({x=0, y=0}, 1, 0, true) + end, + }, +}) + diff --git a/games/devtest/mods/testfood/init.lua b/games/devtest/mods/testfood/init.lua new file mode 100644 index 000000000..a6236ff68 --- /dev/null +++ b/games/devtest/mods/testfood/init.lua @@ -0,0 +1,24 @@ +local S = minetest.get_translator("testfood") + +minetest.register_craftitem("testfood:good1", { + description = S("Good Food (+1)"), + inventory_image = "testfood_good.png", + on_use = minetest.item_eat(1), +}) +minetest.register_craftitem("testfood:good5", { + description = S("Good Food (+5)"), + inventory_image = "testfood_good2.png", + on_use = minetest.item_eat(5), +}) + +minetest.register_craftitem("testfood:bad1", { + description = S("Bad Food (-1)"), + inventory_image = "testfood_bad.png", + on_use = minetest.item_eat(-1), +}) +minetest.register_craftitem("testfood:bad5", { + description = S("Bad Food (-5)"), + inventory_image = "testfood_bad2.png", + on_use = minetest.item_eat(-5), +}) + diff --git a/games/devtest/mods/testfood/mod.conf b/games/devtest/mods/testfood/mod.conf new file mode 100644 index 000000000..7bff21b6e --- /dev/null +++ b/games/devtest/mods/testfood/mod.conf @@ -0,0 +1,2 @@ +name = testfood +description = For testing food items diff --git a/games/devtest/mods/testfood/textures/testfood_bad.png b/games/devtest/mods/testfood/textures/testfood_bad.png new file mode 100644 index 000000000..6e9251440 Binary files /dev/null and b/games/devtest/mods/testfood/textures/testfood_bad.png differ diff --git a/games/devtest/mods/testfood/textures/testfood_bad2.png b/games/devtest/mods/testfood/textures/testfood_bad2.png new file mode 100644 index 000000000..22b567890 Binary files /dev/null and b/games/devtest/mods/testfood/textures/testfood_bad2.png differ diff --git a/games/devtest/mods/testfood/textures/testfood_good.png b/games/devtest/mods/testfood/textures/testfood_good.png new file mode 100644 index 000000000..31df7f5dd Binary files /dev/null and b/games/devtest/mods/testfood/textures/testfood_good.png differ diff --git a/games/devtest/mods/testfood/textures/testfood_good2.png b/games/devtest/mods/testfood/textures/testfood_good2.png new file mode 100644 index 000000000..e43dda209 Binary files /dev/null and b/games/devtest/mods/testfood/textures/testfood_good2.png differ diff --git a/games/devtest/mods/testformspec/callbacks.lua b/games/devtest/mods/testformspec/callbacks.lua new file mode 100644 index 000000000..559380580 --- /dev/null +++ b/games/devtest/mods/testformspec/callbacks.lua @@ -0,0 +1,51 @@ +local callback_test = 0 + +local out = function(player, formname, fields, number) + local snum = "" + if number then + snum = " "..number + end + local msg = "Formspec callback"..snum..": player="..player:get_player_name()..", formname=\""..tostring(formname).."\", fields="..dump(fields) + minetest.chat_send_player(player:get_player_name(), msg) + minetest.log("action", msg) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if callback_test == 1 then + out(player, formname, fields) + elseif callback_test == 2 then + out(player, formname, fields, 1) + end +end) +minetest.register_on_player_receive_fields(function(player, formname, fields) + if callback_test == 2 then + out(player, formname, fields, 2) + return true -- Disable the first callback + end +end) +minetest.register_on_player_receive_fields(function(player, formname, fields) + if callback_test == 2 then + out(player, formname, fields, 3) + end +end) + +minetest.register_chatcommand("test_formspec_callbacks", { + params = "[ 0 | 1 | 2 ]", + description = "Test: Change formspec callbacks testing mode", + func = function(name, param) + local mode = tonumber(param) + if not mode then + callback_test = (callback_test + 1 % 3) + else + callback_test = mode + end + if callback_test == 1 then + minetest.chat_send_player(name, "Formspec callback test mode 1 enabled: Logging only") + elseif callback_test == 2 then + minetest.chat_send_player(name, "Formspec callback test mode 2 enabled: Three callbacks, disable pre-registered callbacks") + else + callback_test = 0 + minetest.chat_send_player(name, "Formspec callback test disabled!") + end + end +}) diff --git a/games/devtest/mods/testformspec/dummy_items.lua b/games/devtest/mods/testformspec/dummy_items.lua new file mode 100644 index 000000000..2037ae9cf --- /dev/null +++ b/games/devtest/mods/testformspec/dummy_items.lua @@ -0,0 +1,14 @@ +-- This code adds dummy items that are supposed to be used in formspecs +-- for testing item_image formspec elements. + +minetest.register_node("testformspec:node", { + description = "Formspec Test Node", + tiles = { "testformspec_node.png" }, + groups = { dig_immediate = 3, dummy = 1 }, +}) + +minetest.register_craftitem("testformspec:item", { + description = "Formspec Test Item", + inventory_image = "testformspec_item.png", + groups = { dummy = 1 }, +}) diff --git a/games/devtest/mods/testformspec/formspec.lua b/games/devtest/mods/testformspec/formspec.lua new file mode 100644 index 000000000..08c1b6dc0 --- /dev/null +++ b/games/devtest/mods/testformspec/formspec.lua @@ -0,0 +1,381 @@ +local color = minetest.colorize + +local clip_fs = [[ + style_type[label,button,image_button,item_image_button, + tabheader,scrollbar,table,animated_image + ,field,textarea,checkbox,dropdown;noclip=%c] + + label[0,0;A clipping test] + button[0,1;3,0.8;clip_button;A clipping test] + image_button[0,2;3,0.8;testformspec_button_image.png;clip_image_button;A clipping test] + item_image_button[0,3;3,0.8;testformspec:item;clip_item_image_button;A clipping test] + tabheader[0,4.7;3,0.63;clip_tabheader;Clip,Test,Text,Tabs;1;false;false] + field[0,5;3,0.8;clip_field;Title;] + textarea[0,6;3,1;clip_textarea;Title;] + checkbox[0,7.5;clip_checkbox;This is a test;true] + dropdown[0,8;3,0.8;clip_dropdown;Select An Item,One,Two,Three,Four,Five;1] + scrollbar[0,9;3,0.8;horizontal;clip_scrollbar;3] + tablecolumns[text;text] + table[0,10;3,1;clip_table;one,two,three,four;1] + animated_image[-0.5,11;4.5,1;clip_animated_image;testformspec_animation.png;4;100] +]] + +local tabheaders_fs = [[ + tabheader[0,0;10,0.63;tabs_opaque;Opaque,Without,Border;1;false;false] + tabheader[0,1;10,0.63;tabs_opaque_border;Opaque,With,Border;1;false;true] + tabheader[0,2;10,0.63;tabs_transparent;Transparent,Without,Border;1;true;false] + tabheader[0,3;10,0.63;tabs_transparent_border;Transparent,With,Border;1;true;true] + tabheader[0,4;tabs_default;Default,Tabs;1] + tabheader[0,6;10,0.5;tabs_size1;Height=0.5;1;false;false] + tabheader[2,6;10,0.75;tabs_size1;Height=0.75;1;false;false] + tabheader[4,6;10,1;tabs_size2;Height=1;1;false;false] + tabheader[6,6;10,1.25;tabs_size2;Height=1.25;1;false;false] + tabheader[8,6;10,1.5;tabs_size2;Height=1.5;1;false;false] +]] + +local hypertext_basic = [[ +Normal test +This is a normal text. + +style test + + . + + +Tag test +normal +mono +bold +italic +underlined +big +bigger +left +
center
+right +justify. Here comes a blind text: Lorem testum dolor sit amet consecutor celeron fiftifahivus e shadoninia e smalus jokus anrus relsocutoti rubenwardus. Erasputinus hara holisti dominus wusi. Grumarinsti erltusmuate ol fortitusti fla flo, blani burki e sfani fahif. Ultae ratii, e megus gigae don anonimus. Grinus dimondus krockus e nore. Endus finalus nowus comus endus o blindus tekstus. + +Custom tag test + + + + + +color=green +Action: color=green +Action: hovercolor=yellow +size=24 +font=mono +color=green font=mono size=24 + +action test +action + +img test +Normal: + +width=48 height=48: + +float=left: + +float=right: + + +item test +Normal: + +width=48 height=48 + +angle=30,0,0: + +angle=0,30,0: + +angle=0,0,30: + +rotate=yes: + +rotate=100,0,0: + +rotate=0,100,0: + +rotate=0,0,100: + +rotate=50,75,100: + +angle=-30,-45,90 rotate=100,150,-50: +]] + +local hypertext_global = [[ + +This is a test of the global tag. The parameters are: +background=gray margin=20 valign=bottom halign=right color=pink hovercolor=purple size=12 font=mono +action]] + +local hypertext_fs = "hypertext[0,0;11,9;hypertext;"..minetest.formspec_escape(hypertext_basic).."]".. + "hypertext[0,9.5;11,2.5;hypertext;"..minetest.formspec_escape(hypertext_global).."]" + +local style_fs = [[ + style[one_btn1;bgcolor=red;textcolor=yellow;bgcolor_hovered=orange; + bgcolor_pressed=purple] + button[0,0;2.5,0.8;one_btn1;Button] + + style[one_btn2;border=false;textcolor=cyan] ]].. + "button[0,1.05;2.5,0.8;one_btn2;Text " .. color("#FF0", "Yellow") .. [[] + + style[one_btn3;bgimg=testformspec_button_image.png;bgimg_hovered=testformspec_hovered.png; + bgimg_pressed=testformspec_pressed.png] + button[0,2.1;1,1;one_btn3;Border] + + style[one_btn4;bgimg=testformspec_button_image.png;bgimg_hovered=testformspec_hovered.png; + bgimg_pressed=testformspec_pressed.png;border=false] + button[1.25,2.1;1,1;one_btn4;NoBor] + + style[one_btn5;bgimg=testformspec_button_image.png;bgimg_hovered=testformspec_hovered.png; + bgimg_pressed=testformspec_pressed.png;border=false;alpha=false] + button[0,3.35;1,1;one_btn5;Alph] + + style[one_btn6;border=true] + image_button[0,4.6;1,1;testformspec_button_image.png;one_btn6;Border] + + style[one_btn7;border=false] + image_button[1.25,4.6;1,1;testformspec_button_image.png;one_btn7;NoBor] + + style[one_btn8;border=false] + image_button[0,5.85;1,1;testformspec_button_image.png;one_btn8;Border;false;true;testformspec_pressed.png] + + style[one_btn9;border=true] + image_button[1.25,5.85;1,1;testformspec_button_image.png;one_btn9;NoBor;false;false;testformspec_pressed.png] + + style[one_btn10;alpha=false] + image_button[0,7.1;1,1;testformspec_button_image.png;one_btn10;NoAlpha] + + style[one_btn11;alpha=true] + image_button[1.25,7.1;1,1;testformspec_button_image.png;one_btn11;Alpha] + + style[one_btn12;border=true] + item_image_button[0,8.35;1,1;testformspec:item;one_btn12;Border] + + style[one_btn13;border=false] + item_image_button[1.25,8.35;1,1;testformspec:item;one_btn13;NoBor] + + style[one_btn14;border=false;bgimg=testformspec_bg.png;fgimg=testformspec_button_image.png] + style[one_btn14:hovered;bgimg=testformspec_bg_hovered.png;fgimg=testformspec_hovered.png;textcolor=yellow] + style[one_btn14:pressed;bgimg=testformspec_bg_pressed.png;fgimg=testformspec_pressed.png;textcolor=blue] + style[one_btn14:hovered+pressed;textcolor=purple] + image_button[0,9.6;1,1;testformspec_button_image.png;one_btn14;Bg] + + style[one_btn15;border=false;bgimg=testformspec_bg.png;bgimg_hovered=testformspec_bg_hovered.png;bgimg_pressed=testformspec_bg_pressed.png] + item_image_button[1.25,9.6;1,1;testformspec:item;one_btn15;Bg] + + style[one_btn16;border=false;bgimg=testformspec_bg_9slice.png;bgimg_hovered=testformspec_bg_9slice_hovered.png;bgimg_pressed=testformspec_bg_9slice_pressed.png;bgimg_middle=4,6] + button[2.5,9.6;2,1;one_btn16;9-Slice Bg] + + + + container[2.75,0] + + style[one_tb1;textcolor=Yellow] + tabheader[0,3;2.5,0.63;one_tb1;Yellow,Text,Tabs;1;false;false] + + style[one_f1;textcolor=yellow] + field[0,4.25;2.5,0.8;one_f1;Field One;Yellow Text] + + style[one_f2;border=false;textcolor=cyan] + field[0,5.75;2.5,0.8;one_f2;Field Two;Borderless Cyan Text] + + style[one_f3;textcolor=yellow] + textarea[0,7.025;2.5,0.8;one_f3;Label;]] .. + minetest.formspec_escape("Yellow Text\nLine two") .. [[ ] + + style[one_f4;border=false;textcolor=cyan] + textarea[0,8.324999999999999;2.5,0.8;one_f4;Label;]] .. + minetest.formspec_escape("Borderless Cyan Text\nLine two") .. [[ ] + + container_end[] +]] + +local scroll_fs = + "button[8.5,1;4,1;outside;Outside of container]".. + "box[1,1;8,6;#00aa]".. + "scroll_container[1,1;8,6;scrbar;vertical]".. + "button[0,1;1,1;lorem;Lorem]".. + "button[0,10;1,1;ipsum;Ipsum]".. + "pwdfield[2,2;1,1;lorem2;Lorem]".. + "list[current_player;main;4,4;1,5;]".. + "box[2,5;3,2;#ffff00]".. + "image[1,10;3,2;testformspec_item.png]".. + "image[3,1;testformspec_item.png]".. + "item_image[2,6;3,2;testformspec:node]".. + "label[2,15;bla Bli\nfoo bar]".. + "item_image_button[2,3;1,1;testformspec:node;itemimagebutton;ItemImageButton]".. + "tooltip[0,11;3,2;Buz;#f00;#000]".. + "box[0,11;3,2;#00ff00]".. + "hypertext[3,13;3,3;;" .. hypertext_basic .. "]" .. + "container[0,18]".. + "box[1,2;3,2;#0a0a]".. + "scroll_container[1,2;3,2;scrbar2;horizontal;0.06]".. + "button[0,0;6,1;butnest;Nest]".. + "label[10,0.5;nest]".. + "scroll_container_end[]".. + "scrollbar[1,0;3.5,0.3;horizontal;scrbar2;0]".. + "container_end[]".. + "dropdown[0,6;2;hmdrpdwn;apple,bulb;1]".. + "image_button[0,4;2,2;testformspec_button_image.png;imagebutton;bbbbtt;false;true;testformspec_pressed.png]".. + "box[1,22.5;4,1;#a00a]".. + "scroll_container_end[]".. + "scrollbaroptions[max=170]".. -- lowest seen pos is: 0.1*170+6=23 (factor*max+height) + "scrollbar[7.5,0;0.3,4;vertical;scrbar;0]".. + "scrollbar[8,0;0.3,4;vertical;scrbarhmmm;0]".. + "dropdown[0,6;2;hmdrpdwnnn;Outside,of,container;1]" + +--style_type[label;textcolor=green] +--label[0,0;Green] +--style_type[label;textcolor=blue] +--label[0,1;Blue] +--style_type[label;textcolor=;border=true] +--label[1.2,0;Border] +--style_type[label;border=true;bgcolor=red] +--label[1.2,1;Background] +--style_type[label;border=;bgcolor=] +--label[0.75,2;Reset] + + +local pages = { + -- Real Coordinates + [[ + formspec_version[3] + size[12,13] + image_button[0,0;1,1;logo.png;rc_image_button_1x1;1x1] + image_button[1,0;2,2;logo.png;rc_image_button_2x2;2x2] + button[0,2;1,1;rc_button_1x1;1x1] + button[1,2;2,2;rc_button_2x2;2x2] + item_image[0,4;1,1;air] + item_image[1,4;2,2;air] + item_image_button[0,6;1,1;testformspec:node;rc_item_image_button_1x1;1x1] + item_image_button[1,6;2,2;testformspec:node;rc_item_image_button_2x2;2x2] + field[3,.5;3,.5;rc_field;Field;text] + pwdfield[6,.5;3,1;rc_pwdfield;Password Field] + field[3,1;3,1;;Read-Only Field;text] + textarea[3,2;3,.5;rc_textarea_small;Textarea;text] + textarea[6,2;3,2;rc_textarea_big;Textarea;text\nmore text] + textarea[3,3;3,1;;Read-Only Textarea;text\nmore text] + textlist[3,4;3,2;rc_textlist;Textlist,Perfect Coordinates;1;false] + tableoptions[highlight=#ABCDEF75;background=#00000055;border=false] + table[6,4;3,2;rc_table;Table,Cool Stuff,Foo,Bar;2] + dropdown[3,6;3,1;rc_dropdown_small;This,is,a,dropdown;1] + dropdown[6,6;3,2;rc_dropdown_big;I,am,a,bigger,dropdown;5] + image[0,8;3,2;ignore.png] + box[3,7;3,1;#00A3FF] + checkbox[3,8;rc_checkbox_1;Check me!;false] + checkbox[3,9;rc_checkbox_2;Uncheck me now!;true] + scrollbar[0,11.5;11.5,.5;horizontal;rc_scrollbar_horizontal;500] + scrollbar[11.5,0;.5,11.5;vertical;rc_scrollbar_vertical;0] + list[current_player;main;6,8;3,2;1] + button[9,0;2.5,1;rc_empty_button_1;] + button[9,1;2.5,1;rc_empty_button_2;] + button[9,2;2.5,1;rc_empty_button_3;] ]].. + "label[9,0.5;This is a label.\nLine\nLine\nLine\nEnd]".. + [[button[9,3;1,1;rc_empty_button_4;] + vertlabel[9,4;VERT] + label[10,3;HORIZ] + tabheader[8,0;6,0.65;rc_tabheader;Tab 1,Tab 2,Tab 3,Secrets;1;false;false] + ]], + -- Style + + "formspec_version[3]size[12,13]" .. + ("label[0.375,0.375;Styled - %s %s]"):format( + color("#F00", "red text"), + color("#77FF00CC", "green text")) .. + "label[6.375,0.375;Unstyled]" .. + "box[0,0.75;12,0.1;#999]" .. + "box[6,0.85;0.1,11.15;#999]" .. + "container[0.375,1.225]" .. + style_fs .. + "container_end[]container[6.375,1.225]" .. + style_fs:gsub("one_", "two_"):gsub("style%[[^%]]+%]", ""):gsub("style_type%[[^%]]+%]", "") .. + "container_end[]", + + -- Noclip + "formspec_version[3]size[12,13]" .. + "label[0.1,0.5;Clip]" .. + "container[-2.5,1]" .. clip_fs:gsub("%%c", "false") .. "container_end[]" .. + "label[11,0.5;Noclip]" .. + "container[11.5,1]" .. clip_fs:gsub("%%c", "true") .. "container_end[]", + + -- Hypertext + "size[12,13]real_coordinates[true]" .. + "container[0.5,0.5]" .. hypertext_fs .. "container_end[]", + + -- Tabheaders + "size[12,13]real_coordinates[true]" .. + "container[0.5,1.5]" .. tabheaders_fs .. "container_end[]", + + -- Animation + [[ + formspec_version[3] + size[12,13] + animated_image[0.5,0.5;1,1;;testformspec_animation.png;4;100] + animated_image[0.5,1.75;1,1;;testformspec_animation.jpg;4;100] + animated_image[1.75,0.5;1,1;;testformspec_animation.png;100;100] + animated_image[3,0.5;1,1;ani_img_1;testformspec_animation.png;4;1000] + button[4.25,0.5;1,1;ani_btn_1;Current +Number] + animated_image[3,1.75;1,1;ani_img_2;testformspec_animation.png;4;1000;2] + button[4.25,1.75;1,1;ani_btn_2;Current +Number] + animated_image[3,3;1,1;;testformspec_animation.png;4;0] + animated_image[3,4.25;1,1;;testformspec_animation.png;4;0;3] + animated_image[5.5,0.5;5,2;;testformspec_animation.png;4;100] + animated_image[5.5,2.75;5,2;;testformspec_animation.jpg;4;100] + ]], + + -- Scroll containers + "formspec_version[3]size[12,13]" .. + scroll_fs, +} + +local function show_test_formspec(pname, page_id) + page_id = page_id or 2 + + local fs = pages[page_id] .. "tabheader[0,0;8,0.65;maintabs;Real Coord,Styles,Noclip,Hypertext,Tabs,Anim,ScrollC;" .. page_id .. ";false;false]" + + minetest.show_formspec(pname, "testformspec:formspec", fs) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "testformspec:formspec" then + return false + end + + + if fields.maintabs then + show_test_formspec(player:get_player_name(), tonumber(fields.maintabs)) + return true + end + + if fields.ani_img_1 and fields.ani_btn_1 then + minetest.chat_send_player(player:get_player_name(), "ani_img_1 = " .. tostring(fields.ani_img_1)) + return true + elseif fields.ani_img_2 and fields.ani_btn_2 then + minetest.chat_send_player(player:get_player_name(), "ani_img_2 = " .. tostring(fields.ani_img_2)) + return true + end + + if fields.hypertext then + minetest.chat_send_player(player:get_player_name(), "Hypertext action received: " .. tostring(fields.hypertext)) + return true + end +end) + +minetest.register_chatcommand("test_formspec", { + params = "", + description = "Open the test formspec", + func = function(name) + if not minetest.get_player_by_name(name) then + return false, "You need to be online!" + end + + show_test_formspec(name) + return true + end, +}) diff --git a/games/devtest/mods/testformspec/init.lua b/games/devtest/mods/testformspec/init.lua new file mode 100644 index 000000000..23b565f08 --- /dev/null +++ b/games/devtest/mods/testformspec/init.lua @@ -0,0 +1,3 @@ +dofile(minetest.get_modpath("testformspec").."/dummy_items.lua") +dofile(minetest.get_modpath("testformspec").."/formspec.lua") +dofile(minetest.get_modpath("testformspec").."/callbacks.lua") diff --git a/games/devtest/mods/testformspec/mod.conf b/games/devtest/mods/testformspec/mod.conf new file mode 100644 index 000000000..00eac307a --- /dev/null +++ b/games/devtest/mods/testformspec/mod.conf @@ -0,0 +1,2 @@ +name = testformspec +description = Contains an example formspec to test all the features of formspecs diff --git a/games/devtest/mods/testformspec/textures/testformspec_animation.jpg b/games/devtest/mods/testformspec/textures/testformspec_animation.jpg new file mode 100644 index 000000000..b98ca2677 Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_animation.jpg differ diff --git a/games/devtest/mods/testformspec/textures/testformspec_animation.png b/games/devtest/mods/testformspec/textures/testformspec_animation.png new file mode 100644 index 000000000..b972e5dbb Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_animation.png differ diff --git a/games/devtest/mods/testformspec/textures/testformspec_bg.png b/games/devtest/mods/testformspec/textures/testformspec_bg.png new file mode 100644 index 000000000..cd1e50900 Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_bg.png differ diff --git a/games/devtest/mods/testformspec/textures/testformspec_bg_9slice.png b/games/devtest/mods/testformspec/textures/testformspec_bg_9slice.png new file mode 100644 index 000000000..34433ac82 Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_bg_9slice.png differ diff --git a/games/devtest/mods/testformspec/textures/testformspec_bg_9slice_hovered.png b/games/devtest/mods/testformspec/textures/testformspec_bg_9slice_hovered.png new file mode 100644 index 000000000..01c2dc777 Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_bg_9slice_hovered.png differ diff --git a/games/devtest/mods/testformspec/textures/testformspec_bg_9slice_pressed.png b/games/devtest/mods/testformspec/textures/testformspec_bg_9slice_pressed.png new file mode 100644 index 000000000..0cbac7536 Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_bg_9slice_pressed.png differ diff --git a/games/devtest/mods/testformspec/textures/testformspec_bg_hovered.png b/games/devtest/mods/testformspec/textures/testformspec_bg_hovered.png new file mode 100644 index 000000000..3ebbb988c Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_bg_hovered.png differ diff --git a/games/devtest/mods/testformspec/textures/testformspec_bg_pressed.png b/games/devtest/mods/testformspec/textures/testformspec_bg_pressed.png new file mode 100644 index 000000000..2fb5fc21e Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_bg_pressed.png differ diff --git a/games/devtest/mods/testformspec/textures/testformspec_button_image.png b/games/devtest/mods/testformspec/textures/testformspec_button_image.png new file mode 100644 index 000000000..75c438a9a Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_button_image.png differ diff --git a/games/devtest/mods/testformspec/textures/testformspec_hovered.png b/games/devtest/mods/testformspec/textures/testformspec_hovered.png new file mode 100644 index 000000000..3ccad30a2 Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_hovered.png differ diff --git a/games/devtest/mods/testformspec/textures/testformspec_item.png b/games/devtest/mods/testformspec/textures/testformspec_item.png new file mode 100644 index 000000000..4fd823b55 Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_item.png differ diff --git a/games/devtest/mods/testformspec/textures/testformspec_node.png b/games/devtest/mods/testformspec/textures/testformspec_node.png new file mode 100644 index 000000000..c107f28a3 Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_node.png differ diff --git a/games/devtest/mods/testformspec/textures/testformspec_pressed.png b/games/devtest/mods/testformspec/textures/testformspec_pressed.png new file mode 100644 index 000000000..45c504f27 Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_pressed.png differ diff --git a/games/devtest/mods/testnodes/README.md b/games/devtest/mods/testnodes/README.md new file mode 100644 index 000000000..13ed972c0 --- /dev/null +++ b/games/devtest/mods/testnodes/README.md @@ -0,0 +1,11 @@ +# Test Nodes + +This mod contains a bunch of basic nodes to test development stuff. +Most nodes are kept as minimal as possible in order to show off one particular feature of the engine, to make testing stuff easier. + +This mod includes tests for: + +* drawtypes +* paramtype2's +* node properties such as damage, drowning, falling, etc. +* other random stuff diff --git a/games/devtest/mods/testnodes/drawtypes.lua b/games/devtest/mods/testnodes/drawtypes.lua new file mode 100644 index 000000000..35fda960f --- /dev/null +++ b/games/devtest/mods/testnodes/drawtypes.lua @@ -0,0 +1,517 @@ +--[[ Drawtype Test: This file tests out and provides examples for +all drawtypes in Minetest. It is attempted to keep the node +definitions as simple and minimal as possible to keep +side-effects to a minimum. + +How to read the node definitions: +There are two parts which are separated by 2 newlines: +The first part contains the things that are more or less essential +for defining the drawtype (except description, which is +at the top for readability). +The second part (after the 2 newlines) contains stuff that are +unrelated to the drawtype, stuff that is mostly there to make +testing this node easier and more convenient. +]] + +local S = minetest.get_translator("testnodes") + +-- If set to true, will show an inventory image for nodes that have no inventory image as of Minetest 5.1.0. +-- This is due to . +-- This is only added to make the items more visible to avoid confusion, but you will no longer see +-- the default inventory images for these items. When you want to test the default inventory image of drawtypes, +-- this should be turned off. +-- TODO: Remove support for fallback inventory image as soon #9209 is fixed. +local SHOW_FALLBACK_IMAGE = minetest.settings:get_bool("testnodes_show_fallback_image", false) + +local fallback_image = function(img) + if SHOW_FALLBACK_IMAGE then + return img + else + return nil + end +end + +-- A regular cube +minetest.register_node("testnodes:normal", { + description = S("Normal Drawtype Test Node"), + drawtype = "normal", + tiles = { "testnodes_normal.png" }, + + groups = { dig_immediate = 3 }, +}) + +-- Standard glasslike node +minetest.register_node("testnodes:glasslike", { + description = S("Glasslike Drawtype Test Node"), + drawtype = "glasslike", + paramtype = "light", + tiles = { "testnodes_glasslike.png" }, + + groups = { dig_immediate = 3 }, +}) + +-- Glasslike framed with the two textures (normal and "detail") +minetest.register_node("testnodes:glasslike_framed", { + description = S("Glasslike Framed Drawtype Test Node"), + drawtype = "glasslike_framed", + paramtype = "light", + tiles = { + "testnodes_glasslike_framed.png", + "testnodes_glasslike_detail.png", + }, + + + sunlight_propagates = true, + groups = { dig_immediate = 3 }, +}) + +-- Like the one above, but without the "detail" texture (texture 2). +-- This node was added to see how the engine behaves when the "detail" texture +-- is missing. +minetest.register_node("testnodes:glasslike_framed_no_detail", { + description = S("Glasslike Framed without Detail Drawtype Test Node"), + drawtype = "glasslike_framed", + paramtype = "light", + tiles = { "testnodes_glasslike_framed2.png" }, + + + sunlight_propagates = true, + groups = { dig_immediate = 3 }, +}) + + +minetest.register_node("testnodes:glasslike_framed_optional", { + description = S("Glasslike Framed Optional Drawtype Test Node"), + drawtype = "glasslike_framed_optional", + paramtype = "light", + tiles = { + "testnodes_glasslike_framed_optional.png", + "testnodes_glasslike_detail.png", + }, + + + sunlight_propagates = true, + groups = { dig_immediate = 3 }, +}) + + + +minetest.register_node("testnodes:allfaces", { + description = S("Allfaces Drawtype Test Node"), + drawtype = "allfaces", + paramtype = "light", + tiles = { "testnodes_allfaces.png" }, + + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:allfaces_optional", { + description = S("Allfaces Optional Drawtype Test Node"), + drawtype = "allfaces_optional", + paramtype = "light", + tiles = { "testnodes_allfaces_optional.png" }, + + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:allfaces_optional_waving", { + description = S("Waving Allfaces Optional Drawtype Test Node"), + drawtype = "allfaces_optional", + paramtype = "light", + tiles = { "testnodes_allfaces_optional.png^[brighten" }, + waving = 2, + + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:firelike", { + description = S("Firelike Drawtype Test Node"), + drawtype = "firelike", + paramtype = "light", + tiles = { "testnodes_firelike.png" }, + + + walkable = false, + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:fencelike", { + description = S("Fencelike Drawtype Test Node"), + drawtype = "fencelike", + paramtype = "light", + tiles = { "testnodes_fencelike.png" }, + + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:torchlike", { + description = S("Wallmounted Torchlike Drawtype Test Node"), + drawtype = "torchlike", + paramtype = "light", + paramtype2 = "wallmounted", + tiles = { + "testnodes_torchlike_floor.png", + "testnodes_torchlike_ceiling.png", + "testnodes_torchlike_wall.png", + }, + + + walkable = false, + sunlight_propagates = true, + groups = { dig_immediate = 3 }, + inventory_image = fallback_image("testnodes_torchlike_floor.png"), +}) + +minetest.register_node("testnodes:signlike", { + description = S("Wallmounted Signlike Drawtype Test Node"), + drawtype = "signlike", + paramtype = "light", + paramtype2 = "wallmounted", + tiles = { "testnodes_signlike.png" }, + + + walkable = false, + groups = { dig_immediate = 3 }, + sunlight_propagates = true, + inventory_image = fallback_image("testnodes_signlike.png"), +}) + +minetest.register_node("testnodes:plantlike", { + description = S("Plantlike Drawtype Test Node"), + drawtype = "plantlike", + paramtype = "light", + tiles = { "testnodes_plantlike.png" }, + + + walkable = false, + sunlight_propagates = true, + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:plantlike_waving", { + description = S("Waving Plantlike Drawtype Test Node"), + drawtype = "plantlike", + paramtype = "light", + tiles = { "testnodes_plantlike_waving.png" }, + waving = 1, + + + walkable = false, + sunlight_propagates = true, + groups = { dig_immediate = 3 }, +}) + + + +-- param2 will rotate +minetest.register_node("testnodes:plantlike_degrotate", { + description = S("Degrotate Plantlike Drawtype Test Node"), + drawtype = "plantlike", + paramtype = "light", + paramtype2 = "degrotate", + tiles = { "testnodes_plantlike_degrotate.png" }, + + + walkable = false, + sunlight_propagates = true, + groups = { dig_immediate = 3 }, +}) + +-- param2 will change height +minetest.register_node("testnodes:plantlike_leveled", { + description = S("Leveled Plantlike Drawtype Test Node"), + drawtype = "plantlike", + paramtype = "light", + paramtype2 = "leveled", + tiles = { + { name = "testnodes_plantlike_leveled.png", tileable_vertical = true }, + }, + + + -- We set a default param2 here only for convenience, to make the "plant" visible after placement + place_param2 = 8, + walkable = false, + sunlight_propagates = true, + groups = { dig_immediate = 3 }, +}) + +-- param2 changes shape +minetest.register_node("testnodes:plantlike_meshoptions", { + description = S("Meshoptions Plantlike Drawtype Test Node"), + drawtype = "plantlike", + paramtype = "light", + paramtype2 = "meshoptions", + tiles = { "testnodes_plantlike_meshoptions.png" }, + + + walkable = false, + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:plantlike_rooted", { + description = S("Rooted Plantlike Drawtype Test Node"), + drawtype = "plantlike_rooted", + paramtype = "light", + tiles = { "testnodes_plantlike_rooted_base.png" }, + special_tiles = { "testnodes_plantlike_rooted.png" }, + + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:plantlike_rooted_waving", { + description = S("Waving Rooted Plantlike Drawtype Test Node"), + drawtype = "plantlike_rooted", + paramtype = "light", + tiles = { + "testnodes_plantlike_rooted_base.png", + "testnodes_plantlike_rooted_base.png", + "testnodes_plantlike_rooted_base_side_waving.png", + }, + special_tiles = { "testnodes_plantlike_rooted_waving.png" }, + waving = 1, + + groups = { dig_immediate = 3 }, +}) + +-- param2 changes height +minetest.register_node("testnodes:plantlike_rooted_leveled", { + description = S("Leveled Rooted Plantlike Drawtype Test Node"), + drawtype = "plantlike_rooted", + paramtype = "light", + paramtype2 = "leveled", + tiles = { + "testnodes_plantlike_rooted_base.png", + "testnodes_plantlike_rooted_base.png", + "testnodes_plantlike_rooted_base_side_leveled.png", + }, + special_tiles = { + { name = "testnodes_plantlike_rooted_leveled.png", tileable_vertical = true }, + }, + + + -- We set a default param2 here only for convenience, to make the "plant" visible after placement + place_param2 = 8, + groups = { dig_immediate = 3 }, +}) + +-- param2 changes shape +minetest.register_node("testnodes:plantlike_rooted_meshoptions", { + description = S("Meshoptions Rooted Plantlike Drawtype Test Node"), + drawtype = "plantlike_rooted", + paramtype = "light", + paramtype2 = "meshoptions", + tiles = { + "testnodes_plantlike_rooted_base.png", + "testnodes_plantlike_rooted_base.png", + "testnodes_plantlike_rooted_base_side_meshoptions.png", + }, + special_tiles = { + "testnodes_plantlike_rooted_meshoptions.png", + }, + + groups = { dig_immediate = 3 }, +}) + +-- param2 changes rotation +minetest.register_node("testnodes:plantlike_rooted_degrotate", { + description = S("Degrotate Rooted Plantlike Drawtype Test Node"), + drawtype = "plantlike_rooted", + paramtype = "light", + paramtype2 = "degrotate", + tiles = { + "testnodes_plantlike_rooted_base.png", + "testnodes_plantlike_rooted_base.png", + "testnodes_plantlike_rooted_base_side_degrotate.png", + }, + special_tiles = { + "testnodes_plantlike_rooted_degrotate.png", + }, + + groups = { dig_immediate = 3 }, +}) + +-- Demonstrative liquid nodes, source and flowing form. This is only the +-- drawtype, no physical liquid properties are used +minetest.register_node("testnodes:liquid", { + description = S("Source Liquid Drawtype Test Node"), + drawtype = "liquid", + paramtype = "light", + tiles = { + "testnodes_liquidsource.png", + }, + special_tiles = { + {name="testnodes_liquidsource.png", backface_culling=false}, + {name="testnodes_liquidsource.png", backface_culling=true}, + }, + use_texture_alpha = true, + + + walkable = false, + liquid_alternative_flowing = "testnodes:liquid_flowing", + liquid_alternative_source = "testnodes:liquid", + groups = { dig_immediate = 3 }, +}) +minetest.register_node("testnodes:liquid_flowing", { + description = S("Flowing Liquid Drawtype Test Node"), + drawtype = "flowingliquid", + paramtype = "light", + paramtype2 = "flowingliquid", + tiles = { + "testnodes_liquidflowing.png", + }, + special_tiles = { + {name="testnodes_liquidflowing.png", backface_culling=false}, + {name="testnodes_liquidflowing.png", backface_culling=false}, + }, + use_texture_alpha = true, + + + walkable = false, + liquid_alternative_flowing = "testnodes:liquid_flowing", + liquid_alternative_source = "testnodes:liquid", + groups = { dig_immediate = 3 }, +}) +minetest.register_node("testnodes:liquid_waving", { + description = S("Waving Source Liquid Drawtype Test Node"), + drawtype = "liquid", + paramtype = "light", + tiles = { + "testnodes_liquidsource.png^[brighten", + }, + special_tiles = { + {name="testnodes_liquidsource.png^[brighten", backface_culling=false}, + {name="testnodes_liquidsource.png^[brighten", backface_culling=true}, + }, + use_texture_alpha = true, + waving = 3, + + + walkable = false, + liquid_alternative_flowing = "testnodes:liquid_flowing", + liquid_alternative_source = "testnodes:liquid", + groups = { dig_immediate = 3 }, +}) +minetest.register_node("testnodes:liquid_flowing_waving", { + description = S("Waving Flowing Liquid Drawtype Test Node"), + drawtype = "flowingliquid", + paramtype = "light", + paramtype2 = "flowingliquid", + tiles = { + "testnodes_liquidflowing.png^[brighten", + }, + special_tiles = { + {name="testnodes_liquidflowing.png^[brighten", backface_culling=false}, + {name="testnodes_liquidflowing.png^[brighten", backface_culling=false}, + }, + use_texture_alpha = true, + waving = 3, + + + walkable = false, + liquid_alternative_flowing = "testnodes:liquid_flowing", + liquid_alternative_source = "testnodes:liquid", + groups = { dig_immediate = 3 }, +}) + + + +-- Invisible node +minetest.register_node("testnodes:airlike", { + description = S("Airlike Drawtype Test Node"), + drawtype = "airlike", + paramtype = "light", + + + walkable = false, + groups = { dig_immediate = 3 }, + sunlight_propagates = true, + inventory_image = fallback_image("testnodes_airlike.png"), +}) + +-- param2 changes liquid height +minetest.register_node("testnodes:glassliquid", { + description = S("Glasslike Liquid Level Drawtype Test Node"), + drawtype = "glasslike_framed", + paramtype = "light", + paramtype2 = "glasslikeliquidlevel", + tiles = { + "testnodes_glasslikeliquid.png", + }, + special_tiles = { + "testnodes_liquid.png", + }, + + groups = { dig_immediate = 3 }, +}) + +-- Adding many raillike examples, primarily to demonstrate the behavior of +-- "raillike groups". Nodes of the same type (rail, groupless, line, street) +-- should connect to nodes of the same "rail type" (=same shape, different +-- color) only. +local rails = { + { "rail", {"testnodes_rail_straight.png", "testnodes_rail_curved.png", "testnodes_rail_t_junction.png", "testnodes_rail_crossing.png"} }, + { "line", {"testnodes_line_straight.png", "testnodes_line_curved.png", "testnodes_line_t_junction.png", "testnodes_line_crossing.png"}, }, + { "street", {"testnodes_street_straight.png", "testnodes_street_curved.png", "testnodes_street_t_junction.png", "testnodes_street_crossing.png"}, }, + -- the "groupless" nodes are nodes in which the "connect_to_raillike" group is not set + { "groupless", {"testnodes_rail2_straight.png", "testnodes_rail2_curved.png", "testnodes_rail2_t_junction.png", "testnodes_rail2_crossing.png"} }, +} +local colors = { "", "cyan", "red" } + +for r=1, #rails do + local id = rails[r][1] + local tiles = rails[r][2] + local raillike_group + if id ~= "groupless" then + raillike_group = minetest.raillike_group(id) + end + for c=1, #colors do + local color + if colors[c] ~= "" then + color = colors[c] + end + minetest.register_node("testnodes:raillike_"..id..c, { + description = S("Raillike Drawtype Test Node: @1 @2", id, c), + drawtype = "raillike", + paramtype = "light", + tiles = tiles, + groups = { connect_to_raillike = raillike_group, dig_immediate = 3 }, + + + color = color, + selection_box = { + type = "fixed", + fixed = {{-0.5, -0.5, -0.5, 0.5, -0.4, 0.5}}, + }, + sunlight_propagates = true, + walkable = false, + }) + end +end + + + +-- Add visual_scale variants of previous nodes for half and double size +local scale = function(subname, desc_double, desc_half) + local original = "testnodes:"..subname + local def = table.copy(minetest.registered_items[original]) + def.visual_scale = 2.0 + def.description = desc_double + minetest.register_node("testnodes:"..subname.."_double", def) + def = table.copy(minetest.registered_items[original]) + def.visual_scale = 0.5 + def.description = desc_half + minetest.register_node("testnodes:"..subname.."_half", def) +end + +scale("plantlike", + S("Double-sized Plantlike Drawtype Test Node"), + S("Half-sized Plantlike Drawtype Test Node")) +scale("torchlike", + S("Double-sized Wallmounted Torchlike Drawtype Test Node"), + S("Half-sized Wallmounted Torchlike Drawtype Test Node")) +scale("signlike", + S("Double-sized Wallmounted Signlike Drawtype Test Node"), + S("Half-sized Wallmounted Signlike Drawtype Test Node")) +scale("firelike", + S("Double-sized Firelike Drawtype Test Node"), + S("Half-sized Firelike Drawtype Test Node")) diff --git a/games/devtest/mods/testnodes/init.lua b/games/devtest/mods/testnodes/init.lua new file mode 100644 index 000000000..92e2c5630 --- /dev/null +++ b/games/devtest/mods/testnodes/init.lua @@ -0,0 +1,10 @@ +local path = minetest.get_modpath(minetest.get_current_modname()) + +dofile(path.."/drawtypes.lua") +dofile(path.."/meshes.lua") +dofile(path.."/nodeboxes.lua") +dofile(path.."/param2.lua") +dofile(path.."/properties.lua") +dofile(path.."/liquids.lua") +dofile(path.."/light.lua") +dofile(path.."/textures.lua") diff --git a/games/devtest/mods/testnodes/light.lua b/games/devtest/mods/testnodes/light.lua new file mode 100644 index 000000000..94409e83f --- /dev/null +++ b/games/devtest/mods/testnodes/light.lua @@ -0,0 +1,48 @@ +-- Test Nodes: Light test + +local S = minetest.get_translator("testnodes") + +-- All possible light levels +for i=1, minetest.LIGHT_MAX do + minetest.register_node("testnodes:light"..i, { + description = S("Light Source (@1)", i), + paramtype = "light", + light_source = i, + + + tiles ={"testnodes_light_"..i..".png"}, + drawtype = "glasslike", + walkable = false, + sunlight_propagates = true, + is_ground_content = false, + groups = {dig_immediate=3}, + }) +end + +-- Lets light through, but not sunlight, leading to a +-- reduction in light level when light passes through +minetest.register_node("testnodes:sunlight_filter", { + description = S("Sunlight Filter"), + paramtype = "light", + + + drawtype = "glasslike", + tiles = { + "testnodes_sunlight_filter.png", + }, + groups = { dig_immediate = 3 }, +}) + +-- Lets light and sunlight through without obstruction +minetest.register_node("testnodes:sunlight_propagator", { + description = S("Sunlight Propagator"), + paramtype = "light", + sunlight_propagates = true, + + + drawtype = "glasslike", + tiles = { + "testnodes_sunlight_filter.png^[brighten", + }, + groups = { dig_immediate = 3 }, +}) diff --git a/games/devtest/mods/testnodes/liquids.lua b/games/devtest/mods/testnodes/liquids.lua new file mode 100644 index 000000000..e316782ad --- /dev/null +++ b/games/devtest/mods/testnodes/liquids.lua @@ -0,0 +1,91 @@ +-- Add liquids for ranges and viscosity levels 0-8 + +for d=0, 8 do + minetest.register_node("testnodes:rliquid_"..d, { + description = "Test Liquid Source, Range "..d, + drawtype = "liquid", + tiles = {"testnodes_liquidsource_r"..d..".png"}, + special_tiles = { + {name = "testnodes_liquidsource_r"..d..".png", backface_culling = false}, + {name = "testnodes_liquidsource_r"..d..".png", backface_culling = true}, + }, + alpha = 192, + paramtype = "light", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + liquidtype = "source", + liquid_alternative_flowing = "testnodes:rliquid_flowing_"..d, + liquid_alternative_source = "testnodes:rliquid_"..d, + liquid_range = d, + }) + + minetest.register_node("testnodes:rliquid_flowing_"..d, { + description = "Flowing Test Liquid, Range "..d, + drawtype = "flowingliquid", + tiles = {"testnodes_liquidflowing_r"..d..".png"}, + special_tiles = { + {name = "testnodes_liquidflowing_r"..d..".png", backface_culling = false}, + {name = "testnodes_liquidflowing_r"..d..".png", backface_culling = false}, + }, + alpha = 192, + paramtype = "light", + paramtype2 = "flowingliquid", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + liquidtype = "flowing", + liquid_alternative_flowing = "testnodes:rliquid_flowing_"..d, + liquid_alternative_source = "testnodes:rliquid_"..d, + liquid_range = d, + }) + + local mod = "^[colorize:#000000:127" + minetest.register_node("testnodes:vliquid_"..d, { + description = "Test Liquid Source, Viscosity "..d, + drawtype = "liquid", + tiles = {"testnodes_liquidsource_r"..d..".png"..mod}, + special_tiles = { + {name = "testnodes_liquidsource_r"..d..".png"..mod, backface_culling = false}, + {name = "testnodes_liquidsource_r"..d..".png"..mod, backface_culling = true}, + }, + alpha = 192, + paramtype = "light", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + liquidtype = "source", + liquid_alternative_flowing = "testnodes:vliquid_flowing_"..d, + liquid_alternative_source = "testnodes:vliquid_"..d, + liquid_viscosity = d, + }) + + minetest.register_node("testnodes:vliquid_flowing_"..d, { + description = "Flowing Test Liquid, Viscosity "..d, + drawtype = "flowingliquid", + tiles = {"testnodes_liquidflowing_r"..d..".png"..mod}, + special_tiles = { + {name = "testnodes_liquidflowing_r"..d..".png"..mod, backface_culling = false}, + {name = "testnodes_liquidflowing_r"..d..".png"..mod, backface_culling = false}, + }, + alpha = 192, + paramtype = "light", + paramtype2 = "flowingliquid", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + liquidtype = "flowing", + liquid_alternative_flowing = "testnodes:vliquid_flowing_"..d, + liquid_alternative_source = "testnodes:vliquid_"..d, + liquid_viscosity = d, + }) + +end diff --git a/games/devtest/mods/testnodes/meshes.lua b/games/devtest/mods/testnodes/meshes.lua new file mode 100644 index 000000000..900abc180 --- /dev/null +++ b/games/devtest/mods/testnodes/meshes.lua @@ -0,0 +1,145 @@ +-- Meshes + +local S = minetest.get_translator("testnodes") + +local ocorner_cbox = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, -0.25, 0.5}, + {-0.5, -0.25, -0.25, 0.25, 0, 0.5}, + {-0.5, 0, 0, 0, 0.25, 0.5}, + {-0.5, 0.25, 0.25, -0.25, 0.5, 0.5} + } +} + +local tall_pyr_cbox = { + type = "fixed", + fixed = { + { -0.5, -0.5, -0.5, 0.5, -0.25, 0.5 }, + { -0.375, -0.25, -0.375, 0.375, 0, 0.375}, + { -0.25, 0, -0.25, 0.25, 0.25, 0.25}, + { -0.125, 0.25, -0.125, 0.125, 0.5, 0.125} + } +} + +-- Normal mesh +minetest.register_node("testnodes:mesh", { + description = S("Mesh Test Node"), + drawtype = "mesh", + mesh = "testnodes_pyramid.obj", + tiles = {"testnodes_mesh_stripes2.png"}, + paramtype = "light", + collision_box = tall_pyr_cbox, + + groups = {dig_immediate=3}, +}) + +-- Facedir mesh: outer corner slope +minetest.register_node("testnodes:mesh_facedir", { + description = S("Facedir Mesh Test Node"), + drawtype = "mesh", + mesh = "testnodes_ocorner.obj", + tiles = {"testnodes_mesh_stripes.png"}, + paramtype = "light", + paramtype2 = "facedir", + collision_box = ocorner_cbox, + + groups = {dig_immediate=3}, +}) + +minetest.register_node("testnodes:mesh_colorfacedir", { + description = S("Color Facedir Mesh Test Node"), + drawtype = "mesh", + mesh = "testnodes_ocorner.obj", + tiles = {"testnodes_mesh_stripes3.png"}, + paramtype = "light", + paramtype2 = "colorfacedir", + palette = "testnodes_palette_facedir.png", + collision_box = ocorner_cbox, + + groups = {dig_immediate=3}, +}) + +-- Wallmounted mesh: pyramid +minetest.register_node("testnodes:mesh_wallmounted", { + description = S("Wallmounted Mesh Test Node"), + drawtype = "mesh", + mesh = "testnodes_pyramid.obj", + tiles = {"testnodes_mesh_stripes2.png"}, + paramtype = "light", + paramtype2 = "wallmounted", + collision_box = tall_pyr_cbox, + + groups = {dig_immediate=3}, +}) + +minetest.register_node("testnodes:mesh_colorwallmounted", { + description = S("Color Wallmounted Mesh Test Node"), + drawtype = "mesh", + mesh = "testnodes_pyramid.obj", + tiles = {"testnodes_mesh_stripes3.png"}, + paramtype = "light", + paramtype2 = "colorwallmounted", + palette = "testnodes_palette_wallmounted.png", + collision_box = tall_pyr_cbox, + + groups = {dig_immediate=3}, +}) + + +minetest.register_node("testnodes:mesh_double", { + description = S("Double-sized Mesh Test Node"), + drawtype = "mesh", + mesh = "testnodes_pyramid.obj", + tiles = {"testnodes_mesh_stripes2.png"}, + paramtype = "light", + collision_box = tall_pyr_cbox, + visual_scale = 2, + + groups = {dig_immediate=3}, +}) +minetest.register_node("testnodes:mesh_half", { + description = S("Half-sized Mesh Test Node"), + drawtype = "mesh", + mesh = "testnodes_pyramid.obj", + tiles = {"testnodes_mesh_stripes2.png"}, + paramtype = "light", + collision_box = tall_pyr_cbox, + visual_scale = 0.5, + + groups = {dig_immediate=3}, +}) + +minetest.register_node("testnodes:mesh_waving1", { + description = S("Plantlike-waving Mesh Test Node"), + drawtype = "mesh", + mesh = "testnodes_pyramid.obj", + tiles = {"testnodes_mesh_stripes4.png^[multiply:#B0FFB0"}, + paramtype = "light", + collision_box = tall_pyr_cbox, + waving = 1, + + groups = {dig_immediate=3}, +}) +minetest.register_node("testnodes:mesh_waving2", { + description = S("Leaflike-waving Mesh Test Node"), + drawtype = "mesh", + mesh = "testnodes_pyramid.obj", + tiles = {"testnodes_mesh_stripes4.png^[multiply:#FFFFB0"}, + paramtype = "light", + collision_box = tall_pyr_cbox, + waving = 2, + + groups = {dig_immediate=3}, +}) +minetest.register_node("testnodes:mesh_waving3", { + description = S("Liquidlike-waving Mesh Test Node"), + drawtype = "mesh", + mesh = "testnodes_pyramid.obj", + tiles = {"testnodes_mesh_stripes4.png^[multiply:#B0B0FF"}, + paramtype = "light", + collision_box = tall_pyr_cbox, + waving = 3, + + groups = {dig_immediate=3}, +}) diff --git a/games/devtest/mods/testnodes/mod.conf b/games/devtest/mods/testnodes/mod.conf new file mode 100644 index 000000000..4824c6ed0 --- /dev/null +++ b/games/devtest/mods/testnodes/mod.conf @@ -0,0 +1,2 @@ +name = testnodes +description = Contains a bunch of basic example nodes for demonstrative purposes, development and testing diff --git a/games/devtest/mods/testnodes/models/testnodes_ocorner.obj b/games/devtest/mods/testnodes/models/testnodes_ocorner.obj new file mode 100644 index 000000000..231d7056b --- /dev/null +++ b/games/devtest/mods/testnodes/models/testnodes_ocorner.obj @@ -0,0 +1,23 @@ +# Blender v2.73 (sub 0) OBJ File: 'slope_test_ocorner_onetexture.blend' +# www.blender.org +o Cube_Cube.002 +v 0.500000 0.500000 0.500000 +v -0.500000 -0.500000 0.500000 +v 0.500000 -0.500000 0.500000 +v -0.500000 -0.500000 -0.500000 +v 0.500000 -0.500000 -0.500000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 -0.000000 1.000000 +vn -0.707100 0.707100 0.000000 +vn 0.000000 0.707100 -0.707100 +s off +f 3/1/1 2/2/1 4/3/1 5/4/1 +f 1/2/2 3/3/2 5/4/2 +f 1/1/3 2/3/3 3/4/3 +f 1/1/4 4/3/4 2/4/4 +f 1/2/5 5/3/5 4/4/5 diff --git a/games/devtest/mods/testnodes/models/testnodes_pyramid.obj b/games/devtest/mods/testnodes/models/testnodes_pyramid.obj new file mode 100644 index 000000000..b305af2f8 --- /dev/null +++ b/games/devtest/mods/testnodes/models/testnodes_pyramid.obj @@ -0,0 +1,24 @@ +# Blender v2.73 (sub 0) OBJ File: 'slope_test_pyramid_onetexture.blend' +# www.blender.org +o Cube +v 0.500000 -0.500000 -0.500000 +v 0.500000 -0.500000 0.500000 +v -0.500000 -0.500000 0.500000 +v -0.500000 -0.500000 -0.500000 +v -0.000000 0.500000 -0.000000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 0.000000 +vt 0.500000 1.000000 +vn 0.000000 -1.000000 0.000000 +vn -0.894400 0.447200 -0.000000 +vn 0.000000 0.447200 -0.894400 +vn 0.894400 0.447200 0.000000 +vn -0.000000 0.447200 0.894400 +s off +f 1/1/1 2/2/1 3/3/1 4/4/1 +f 3/4/2 5/5/2 4/3/2 +f 5/5/3 1/3/3 4/4/3 +f 1/4/4 5/5/4 2/3/4 +f 2/4/5 5/5/5 3/3/5 diff --git a/games/devtest/mods/testnodes/nodeboxes.lua b/games/devtest/mods/testnodes/nodeboxes.lua new file mode 100644 index 000000000..ebd858337 --- /dev/null +++ b/games/devtest/mods/testnodes/nodeboxes.lua @@ -0,0 +1,80 @@ +local S = minetest.get_translator("testnodes") + +-- Nodebox examples and tests. + +-- An simple example nodebox with one centered box +minetest.register_node("testnodes:nodebox_fixed", { + description = S("Fixed Nodebox Test Node"), + tiles = {"testnodes_nodebox.png"}, + drawtype = "nodebox", + paramtype = "light", + node_box = { + type = "fixed", + fixed = {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25}, + }, + + groups = {dig_immediate=3}, +}) + +-- 50% higher than a regular node +minetest.register_node("testnodes:nodebox_overhigh", { + description = S("Overhigh Nodebox Test Node"), + tiles = {"testnodes_nodebox.png"}, + drawtype = "nodebox", + paramtype = "light", + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 1, 0.5}, + }, + + groups = {dig_immediate=3}, +}) + +-- 100% higher than a regular node +minetest.register_node("testnodes:nodebox_overhigh2", { + description = S("Double-height Nodebox Test Node"), + tiles = {"testnodes_nodebox.png"}, + drawtype = "nodebox", + paramtype = "light", + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 1.5, 0.5}, + }, + + groups = {dig_immediate=3}, +}) + +-- Height of nodebox changes with its param2 value +minetest.register_node("testnodes:nodebox_leveled", { + description = S("Leveled Nodebox Test Node"), + tiles = {"testnodes_nodebox.png"}, + drawtype = "nodebox", + paramtype = "light", + paramtype2 = "leveled", + node_box = { + type = "leveled", + fixed = {-0.5, 0.0, -0.5, 0.5, -0.499, 0.5}, + }, + + groups = {dig_immediate=3}, +}) + +-- Wall-like nodebox that connects to neighbors +minetest.register_node("testnodes:nodebox_connected", { + description = S("Connected Nodebox Test Node"), + tiles = {"testnodes_nodebox.png"}, + groups = {connected_nodebox=1, dig_immediate=3}, + drawtype = "nodebox", + paramtype = "light", + connects_to = {"group:connected_nodebox"}, + connect_sides = {"front", "back", "left", "right"}, + node_box = { + type = "connected", + fixed = {-0.125, -0.500, -0.125, 0.125, 0.500, 0.125}, + connect_front = {-0.125, -0.500, -0.500, 0.125, 0.400, -0.125}, + connect_back = {-0.125, -0.500, 0.125, 0.125, 0.400, 0.500}, + connect_left = {-0.500, -0.500, -0.125, -0.125, 0.400, 0.125}, + connect_right = {0.125, -0.500, -0.125, 0.500, 0.400, 0.125}, + }, +}) + diff --git a/games/devtest/mods/testnodes/param2.lua b/games/devtest/mods/testnodes/param2.lua new file mode 100644 index 000000000..5d64376fa --- /dev/null +++ b/games/devtest/mods/testnodes/param2.lua @@ -0,0 +1,168 @@ +-- This file is for misc. param2 tests that aren't covered in drawtypes.lua already. + +local S = minetest.get_translator("testnodes") + +minetest.register_node("testnodes:facedir", { + description = S("Facedir Test Node"), + paramtype2 = "facedir", + tiles = { + "testnodes_1.png", + "testnodes_2.png", + "testnodes_3.png", + "testnodes_4.png", + "testnodes_5.png", + "testnodes_6.png", + }, + + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:facedir_nodebox", { + description = S("Facedir Nodebox Test Node"), + tiles = { + "testnodes_1.png", + "testnodes_2.png", + "testnodes_3.png", + "testnodes_4.png", + "testnodes_5.png", + "testnodes_6.png", + }, + drawtype = "nodebox", + paramtype = "light", + paramtype2 = "facedir", + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.2, 0.2, 0.2}, + }, + + groups = {dig_immediate=3}, +}) + +minetest.register_node("testnodes:wallmounted", { + description = S("Wallmounted Test Node"), + paramtype2 = "wallmounted", + tiles = { + "testnodes_1w.png", + "testnodes_2w.png", + "testnodes_3w.png", + "testnodes_4w.png", + "testnodes_5w.png", + "testnodes_6w.png", + }, + + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:wallmounted_nodebox", { + description = S("Wallmounted Nodebox Test Node"), + paramtype2 = "wallmounted", + paramtype = "light", + tiles = { + "testnodes_1w.png", + "testnodes_2w.png", + "testnodes_3w.png", + "testnodes_4w.png", + "testnodes_5w.png", + "testnodes_6w.png", + }, + drawtype = "nodebox", + node_box = { + type = "wallmounted", + wall_top = { -0.5, 0, -0.5, 0.5, 0.5, 0.5 }, + wall_bottom = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }, + wall_side = { -0.5, -0.5, -0.5, 0, 0.5, 0.5 }, + }, + + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:color", { + description = S("Color Test Node"), + paramtype2 = "color", + palette = "testnodes_palette_full.png", + tiles = { + "testnodes_node.png", + }, + + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:colorfacedir", { + description = S("Color Facedir Test Node"), + paramtype2 = "colorfacedir", + palette = "testnodes_palette_facedir.png", + tiles = { + "testnodes_1g.png", + "testnodes_2g.png", + "testnodes_3g.png", + "testnodes_4g.png", + "testnodes_5g.png", + "testnodes_6g.png", + }, + + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:colorfacedir_nodebox", { + description = S("Color Facedir Nodebox Test Node"), + tiles = { + "testnodes_1g.png", + "testnodes_2g.png", + "testnodes_3g.png", + "testnodes_4g.png", + "testnodes_5g.png", + "testnodes_6g.png", + }, + drawtype = "nodebox", + paramtype = "light", + paramtype2 = "colorfacedir", + palette = "testnodes_palette_facedir.png", + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.2, 0.2, 0.2}, + }, + + groups = {dig_immediate=3}, +}) + +minetest.register_node("testnodes:colorwallmounted", { + description = S("Color Wallmounted Test Node"), + paramtype2 = "colorwallmounted", + paramtype = "light", + palette = "testnodes_palette_wallmounted.png", + tiles = { + "testnodes_1wg.png", + "testnodes_2wg.png", + "testnodes_3wg.png", + "testnodes_4wg.png", + "testnodes_5wg.png", + "testnodes_6wg.png", + }, + + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:colorwallmounted_nodebox", { + description = S("Color Wallmounted Nodebox Test Node"), + paramtype2 = "colorwallmounted", + paramtype = "light", + palette = "testnodes_palette_wallmounted.png", + tiles = { + "testnodes_1wg.png", + "testnodes_2wg.png", + "testnodes_3wg.png", + "testnodes_4wg.png", + "testnodes_5wg.png", + "testnodes_6wg.png", + }, + drawtype = "nodebox", + node_box = { + type = "wallmounted", + wall_top = { -0.5, 0, -0.5, 0.5, 0.5, 0.5 }, + wall_bottom = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }, + wall_side = { -0.5, -0.5, -0.5, 0, 0.5, 0.5 }, + }, + + groups = { dig_immediate = 3 }, +}) + diff --git a/games/devtest/mods/testnodes/properties.lua b/games/devtest/mods/testnodes/properties.lua new file mode 100644 index 000000000..e169d4b08 --- /dev/null +++ b/games/devtest/mods/testnodes/properties.lua @@ -0,0 +1,270 @@ +-- Test Nodes: Node property tests + +local S = minetest.get_translator("testnodes") + +-- Is supposed to fall when it doesn't rest on solid ground +minetest.register_node("testnodes:falling", { + description = S("Falling Node"), + tiles = { + "testnodes_node.png", + "testnodes_node.png", + "testnodes_node_falling.png", + }, + groups = { falling_node = 1, dig_immediate = 3 }, +}) + +-- Same as falling node, but will stop falling on top of liquids +minetest.register_node("testnodes:falling_float", { + description = S("Falling+Floating Node"), + groups = { falling_node = 1, float = 1, dig_immediate = 3 }, + + + tiles = { + "testnodes_node.png", + "testnodes_node.png", + "testnodes_node_falling.png", + }, + color = "cyan", +}) + +-- This node attaches to the floor and drops as item +-- when the floor is gone. +minetest.register_node("testnodes:attached", { + description = S("Floor-Attached Node"), + tiles = { + "testnodes_attached_top.png", + "testnodes_attached_bottom.png", + "testnodes_attached_side.png", + }, + groups = { attached_node = 1, dig_immediate = 3 }, +}) + +-- This node attaches to the side of a node and drops as item +-- when the node it attaches to is gone. +minetest.register_node("testnodes:attached_wallmounted", { + description = S("Wallmounted Attached Node"), + paramtype2 = "wallmounted", + tiles = { + "testnodes_attachedw_top.png", + "testnodes_attachedw_bottom.png", + "testnodes_attachedw_side.png", + }, + groups = { attached_node = 1, dig_immediate = 3 }, +}) + +-- Jump disabled +minetest.register_node("testnodes:nojump", { + description = S("Non-jumping Node"), + groups = {disable_jump=1, dig_immediate=3}, + + + tiles = {"testnodes_nojump_top.png", "testnodes_nojump_side.png"}, +}) + +-- Climbable up and down with jump and sneak keys +minetest.register_node("testnodes:climbable", { + description = S("Climbable Node"), + climbable = true, + walkable = false, + + + paramtype = "light", + sunlight_propagates = true, + is_ground_content = false, + tiles ={"testnodes_climbable_side.png"}, + drawtype = "glasslike", + groups = {dig_immediate=3}, +}) + +-- Climbable only downwards with sneak key +minetest.register_node("testnodes:climbable_nojump", { + description = S("Downwards-climbable Node"), + climbable = true, + walkable = false, + + groups = {disable_jump=1, dig_immediate=3}, + drawtype = "glasslike", + tiles ={"testnodes_climbable_nojump_side.png"}, + paramtype = "light", + sunlight_propagates = true, +}) + +-- A liquid in which you can't rise +minetest.register_node("testnodes:liquid_nojump", { + description = S("Non-jumping Liquid Source Node"), + liquidtype = "source", + liquid_range = 1, + liquid_viscosity = 0, + liquid_alternative_flowing = "testnodes:liquidflowing_nojump", + liquid_alternative_source = "testnodes:liquid_nojump", + liquid_renewable = false, + groups = {disable_jump=1, dig_immediate=3}, + walkable = false, + + drawtype = "liquid", + tiles = {"testnodes_liquidsource.png^[colorize:#FF0000:127"}, + special_tiles = { + {name = "testnodes_liquidsource.png^[colorize:#FF0000:127", backface_culling = false}, + {name = "testnodes_liquidsource.png^[colorize:#FF0000:127", backface_culling = true}, + }, + use_texture_alpha = true, + paramtype = "light", + pointable = false, + liquids_pointable = true, + diggable = false, + buildable_to = true, + is_ground_content = false, + post_effect_color = {a = 70, r = 255, g = 0, b = 200}, +}) + +-- A liquid in which you can't rise (flowing variant) +minetest.register_node("testnodes:liquidflowing_nojump", { + description = S("Non-jumping Flowing Liquid Node"), + liquidtype = "flowing", + liquid_range = 1, + liquid_viscosity = 0, + liquid_alternative_flowing = "testnodes:liquidflowing_nojump", + liquid_alternative_source = "testnodes:liquid_nojump", + liquid_renewable = false, + groups = {disable_jump=1, dig_immediate=3}, + walkable = false, + + + drawtype = "flowingliquid", + tiles = {"testnodes_liquidflowing.png^[colorize:#FF0000:127"}, + special_tiles = { + {name = "testnodes_liquidflowing.png^[colorize:#FF0000:127", backface_culling = false}, + {name = "testnodes_liquidflowing.png^[colorize:#FF0000:127", backface_culling = false}, + }, + use_texture_alpha = true, + paramtype = "light", + paramtype2 = "flowingliquid", + pointable = false, + liquids_pointable = true, + diggable = false, + buildable_to = true, + is_ground_content = false, + post_effect_color = {a = 70, r = 255, g = 0, b = 200}, +}) + +-- Nodes that modify fall damage (various damage modifiers) +for i=-100, 100, 25 do + if i ~= 0 then + local subname, descnum + if i < 0 then + subname = "m"..math.abs(i) + descnum = tostring(i) + else + subname = tostring(i) + descnum = S("+@1", i) + end + local tex, color, desc + if i > 0 then + local val = math.floor((i/100)*255) + tex = "testnodes_fall_damage_plus.png" + color = { b=0, g=255-val, r=255, a=255 } + desc = S("Fall Damage Node (+@1%)", i) + else + tex = "testnodes_fall_damage_minus.png" + if i == -100 then + color = { r=0, b=0, g=255, a=255 } + else + local val = math.floor((math.abs(i)/100)*255) + color = { r=0, b=255, g=255-val, a=255 } + end + desc = S("Fall Damage Node (-@1%)", math.abs(i)) + end + minetest.register_node("testnodes:damage"..subname, { + description = desc, + groups = {fall_damage_add_percent=i, dig_immediate=3}, + + + tiles = { tex }, + is_ground_content = false, + color = color, + }) + end +end + +-- Bouncy nodes (various bounce levels) +for i=20, 180, 20 do + local val = math.floor(((i-20)/200)*255) + minetest.register_node("testnodes:bouncy"..i, { + description = S("Bouncy Node (@1%)", i), + groups = {bouncy=i, dig_immediate=3}, + + + tiles ={"testnodes_bouncy.png"}, + is_ground_content = false, + color = { r=255, g=255-val, b=val, a=255 }, + }) +end + +-- Slippery nodes (various slippery levels) +for i=1, 5 do + minetest.register_node("testnodes:slippery"..i, { + description = S("Slippery Node (@1)", i), + tiles ={"testnodes_slippery.png"}, + is_ground_content = false, + groups = {slippery=i, dig_immediate=3}, + color = { r=0, g=255, b=math.floor((i/5)*255), a=255 }, + }) +end + +-- By placing something on the node, the node itself will be replaced +minetest.register_node("testnodes:buildable_to", { + description = S("Replacable Node"), + buildable_to = true, + tiles = {"testnodes_buildable_to.png"}, + is_ground_content = false, + groups = {dig_immediate=3}, +}) + +-- Nodes that deal damage to players that are inside them. +-- Negative damage nodes should heal. +for d=-3,3 do + if d ~= 0 then + local sub, tile + if d > 0 then + sub = tostring(d) + tile = "testnodes_damage.png" + else + sub = "m" .. tostring(math.abs(d)) + tile = "testnodes_damage_neg.png" + end + if math.abs(d) == 2 then + tile = tile .. "^[colorize:#000000:70" + elseif math.abs(d) == 3 then + tile = tile .. "^[colorize:#000000:140" + end + minetest.register_node("testnodes:damage_"..sub, { + description = S("Damage Node (@1 damage per second)", d), + damage_per_second = d, + + + walkable = false, + is_ground_content = false, + drawtype = "allfaces", + paramtype = "light", + sunlight_propagates = true, + tiles = { tile }, + groups = {dig_immediate=3}, + }) + end +end + +-- Causes drowning damage +minetest.register_node("testnodes:drowning_1", { + description = S("Drowning Node (@1 damage)", 1), + drowning = 1, + + + walkable = false, + is_ground_content = false, + drawtype = "allfaces", + paramtype = "light", + sunlight_propagates = true, + tiles = { "testnodes_drowning.png" }, + groups = {dig_immediate=3}, +}) + diff --git a/games/devtest/mods/testnodes/settingtypes.txt b/games/devtest/mods/testnodes/settingtypes.txt new file mode 100644 index 000000000..7f753bf3e --- /dev/null +++ b/games/devtest/mods/testnodes/settingtypes.txt @@ -0,0 +1,4 @@ +# If set to true, will show an inventory image for nodes that have no inventory image as of Minetest 5.1.0. +# This is due to . +# This is only added to make the items more visible to avoid confusion, but you will no longer see the default inventory images for these items. When you want to test the default inventory image of drawtypes, this should be turned off. +testnodes_show_fallback_image (Use fallback inventory images) bool false diff --git a/games/devtest/mods/testnodes/textures.lua b/games/devtest/mods/testnodes/textures.lua new file mode 100644 index 000000000..f5db9ccbf --- /dev/null +++ b/games/devtest/mods/testnodes/textures.lua @@ -0,0 +1,67 @@ +-- Node texture tests + +local S = minetest.get_translator("testnodes") + +minetest.register_node("testnodes:6sides", { + description = S("Six Textures Test Node"), + tiles = { + "testnodes_normal1.png", + "testnodes_normal2.png", + "testnodes_normal3.png", + "testnodes_normal4.png", + "testnodes_normal5.png", + "testnodes_normal6.png", + }, + + groups = { dig_immediate = 2 }, +}) + +minetest.register_node("testnodes:anim", { + description = S("Animated Test Node"), + tiles = { + { name = "testnodes_anim.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 4.0, + }, }, + }, + + groups = { dig_immediate = 2 }, +}) + +-- Node texture transparency test + +local alphas = { 64, 128, 191 } + +for a=1,#alphas do + local alpha = alphas[a] + + -- Transparency taken from texture + minetest.register_node("testnodes:alpha_texture_"..alpha, { + description = S("Texture Alpha Test Node (@1)", alpha), + drawtype = "glasslike", + paramtype = "light", + tiles = { + "testnodes_alpha"..alpha..".png", + }, + use_texture_alpha = true, + + groups = { dig_immediate = 3 }, + }) + + -- Transparency set via "alpha" parameter + minetest.register_node("testnodes:alpha_"..alpha, { + description = S("Alpha Test Node (@1)", alpha), + -- It seems that only the liquid drawtype supports the alpha parameter + drawtype = "liquid", + paramtype = "light", + tiles = { + "testnodes_alpha.png", + }, + alpha = alpha, + + groups = { dig_immediate = 3 }, + }) +end diff --git a/games/devtest/mods/testnodes/textures/testnodes_1.png b/games/devtest/mods/testnodes/textures/testnodes_1.png new file mode 100644 index 000000000..6730997e2 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_1.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_1g.png b/games/devtest/mods/testnodes/textures/testnodes_1g.png new file mode 100644 index 000000000..529298ece Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_1g.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_1w.png b/games/devtest/mods/testnodes/textures/testnodes_1w.png new file mode 100644 index 000000000..d24e571cc Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_1w.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_1wg.png b/games/devtest/mods/testnodes/textures/testnodes_1wg.png new file mode 100644 index 000000000..b2eba0e9a Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_1wg.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_2.png b/games/devtest/mods/testnodes/textures/testnodes_2.png new file mode 100644 index 000000000..6c87c868d Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_2.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_2g.png b/games/devtest/mods/testnodes/textures/testnodes_2g.png new file mode 100644 index 000000000..cb9060f7b Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_2g.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_2w.png b/games/devtest/mods/testnodes/textures/testnodes_2w.png new file mode 100644 index 000000000..b56874ee1 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_2w.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_2wg.png b/games/devtest/mods/testnodes/textures/testnodes_2wg.png new file mode 100644 index 000000000..108dc87bb Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_2wg.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_3.png b/games/devtest/mods/testnodes/textures/testnodes_3.png new file mode 100644 index 000000000..05b45629a Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_3.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_3g.png b/games/devtest/mods/testnodes/textures/testnodes_3g.png new file mode 100644 index 000000000..5c84f5882 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_3g.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_3w.png b/games/devtest/mods/testnodes/textures/testnodes_3w.png new file mode 100644 index 000000000..8b435cf01 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_3w.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_3wg.png b/games/devtest/mods/testnodes/textures/testnodes_3wg.png new file mode 100644 index 000000000..9ee900667 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_3wg.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_4.png b/games/devtest/mods/testnodes/textures/testnodes_4.png new file mode 100644 index 000000000..15e6ffec7 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_4.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_4g.png b/games/devtest/mods/testnodes/textures/testnodes_4g.png new file mode 100644 index 000000000..8f144fae0 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_4g.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_4w.png b/games/devtest/mods/testnodes/textures/testnodes_4w.png new file mode 100644 index 000000000..214e0df9d Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_4w.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_4wg.png b/games/devtest/mods/testnodes/textures/testnodes_4wg.png new file mode 100644 index 000000000..888b3d482 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_4wg.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_5.png b/games/devtest/mods/testnodes/textures/testnodes_5.png new file mode 100644 index 000000000..1ef1c728c Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_5.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_5g.png b/games/devtest/mods/testnodes/textures/testnodes_5g.png new file mode 100644 index 000000000..30da4793a Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_5g.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_5w.png b/games/devtest/mods/testnodes/textures/testnodes_5w.png new file mode 100644 index 000000000..b4cb42426 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_5w.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_5wg.png b/games/devtest/mods/testnodes/textures/testnodes_5wg.png new file mode 100644 index 000000000..fac9db28e Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_5wg.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_6.png b/games/devtest/mods/testnodes/textures/testnodes_6.png new file mode 100644 index 000000000..805813e57 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_6.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_6g.png b/games/devtest/mods/testnodes/textures/testnodes_6g.png new file mode 100644 index 000000000..a88f4c9f8 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_6g.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_6w.png b/games/devtest/mods/testnodes/textures/testnodes_6w.png new file mode 100644 index 000000000..e6bbf97d9 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_6w.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_6wg.png b/games/devtest/mods/testnodes/textures/testnodes_6wg.png new file mode 100644 index 000000000..29ca933e0 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_6wg.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_airlike.png b/games/devtest/mods/testnodes/textures/testnodes_airlike.png new file mode 100644 index 000000000..5a5664a2a Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_airlike.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_allfaces.png b/games/devtest/mods/testnodes/textures/testnodes_allfaces.png new file mode 100644 index 000000000..c0a7dc550 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_allfaces.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_allfaces_optional.png b/games/devtest/mods/testnodes/textures/testnodes_allfaces_optional.png new file mode 100644 index 000000000..1f6a17313 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_allfaces_optional.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_alpha.png b/games/devtest/mods/testnodes/textures/testnodes_alpha.png new file mode 100644 index 000000000..157fa7386 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_alpha.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_alpha128.png b/games/devtest/mods/testnodes/textures/testnodes_alpha128.png new file mode 100644 index 000000000..16babf6c7 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_alpha128.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_alpha191.png b/games/devtest/mods/testnodes/textures/testnodes_alpha191.png new file mode 100644 index 000000000..f165d2887 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_alpha191.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_alpha64.png b/games/devtest/mods/testnodes/textures/testnodes_alpha64.png new file mode 100644 index 000000000..c343c32c3 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_alpha64.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_anim.png b/games/devtest/mods/testnodes/textures/testnodes_anim.png new file mode 100644 index 000000000..d321fe857 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_anim.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_attached_bottom.png b/games/devtest/mods/testnodes/textures/testnodes_attached_bottom.png new file mode 100644 index 000000000..e01ae576f Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_attached_bottom.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_attached_side.png b/games/devtest/mods/testnodes/textures/testnodes_attached_side.png new file mode 100644 index 000000000..9459cbb05 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_attached_side.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_attached_top.png b/games/devtest/mods/testnodes/textures/testnodes_attached_top.png new file mode 100644 index 000000000..0148b41e0 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_attached_top.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_attachedw_bottom.png b/games/devtest/mods/testnodes/textures/testnodes_attachedw_bottom.png new file mode 100644 index 000000000..488ad23a9 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_attachedw_bottom.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_attachedw_side.png b/games/devtest/mods/testnodes/textures/testnodes_attachedw_side.png new file mode 100644 index 000000000..a02facbc7 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_attachedw_side.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_attachedw_top.png b/games/devtest/mods/testnodes/textures/testnodes_attachedw_top.png new file mode 100644 index 000000000..1f4fc7b85 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_attachedw_top.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_bouncy.png b/games/devtest/mods/testnodes/textures/testnodes_bouncy.png new file mode 100644 index 000000000..eabbbdfe4 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_bouncy.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_buildable_to.png b/games/devtest/mods/testnodes/textures/testnodes_buildable_to.png new file mode 100644 index 000000000..23b5e54d2 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_buildable_to.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_climbable_nojump_side.png b/games/devtest/mods/testnodes/textures/testnodes_climbable_nojump_side.png new file mode 100644 index 000000000..d5ca13033 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_climbable_nojump_side.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_climbable_side.png b/games/devtest/mods/testnodes/textures/testnodes_climbable_side.png new file mode 100644 index 000000000..c56ea90d7 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_climbable_side.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_damage.png b/games/devtest/mods/testnodes/textures/testnodes_damage.png new file mode 100644 index 000000000..9de2ab5e8 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_damage.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_damage_neg.png b/games/devtest/mods/testnodes/textures/testnodes_damage_neg.png new file mode 100644 index 000000000..85811bc8e Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_damage_neg.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_drowning.png b/games/devtest/mods/testnodes/textures/testnodes_drowning.png new file mode 100644 index 000000000..57ffc8fcf Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_drowning.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_fall_damage_minus.png b/games/devtest/mods/testnodes/textures/testnodes_fall_damage_minus.png new file mode 100644 index 000000000..88d3bdf58 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_fall_damage_minus.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_fall_damage_plus.png b/games/devtest/mods/testnodes/textures/testnodes_fall_damage_plus.png new file mode 100644 index 000000000..61fdec2e3 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_fall_damage_plus.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_fencelike.png b/games/devtest/mods/testnodes/textures/testnodes_fencelike.png new file mode 100644 index 000000000..84dea1b7c Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_fencelike.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_firelike.png b/games/devtest/mods/testnodes/textures/testnodes_firelike.png new file mode 100644 index 000000000..ee59b0db1 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_firelike.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_glasslike.png b/games/devtest/mods/testnodes/textures/testnodes_glasslike.png new file mode 100644 index 000000000..cf3e35414 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_glasslike.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_glasslike_detail.png b/games/devtest/mods/testnodes/textures/testnodes_glasslike_detail.png new file mode 100644 index 000000000..30c9586e8 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_glasslike_detail.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_glasslike_framed.png b/games/devtest/mods/testnodes/textures/testnodes_glasslike_framed.png new file mode 100644 index 000000000..8a513f21c Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_glasslike_framed.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_glasslike_framed2.png b/games/devtest/mods/testnodes/textures/testnodes_glasslike_framed2.png new file mode 100644 index 000000000..4ea839c8b Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_glasslike_framed2.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_glasslike_framed_optional.png b/games/devtest/mods/testnodes/textures/testnodes_glasslike_framed_optional.png new file mode 100644 index 000000000..37de77dd1 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_glasslike_framed_optional.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_glasslikeliquid.png b/games/devtest/mods/testnodes/textures/testnodes_glasslikeliquid.png new file mode 100644 index 000000000..e1e96ffb9 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_glasslikeliquid.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light.png b/games/devtest/mods/testnodes/textures/testnodes_light.png new file mode 100644 index 000000000..4ba0081c3 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light_1.png b/games/devtest/mods/testnodes/textures/testnodes_light_1.png new file mode 100644 index 000000000..57adf5a4a Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light_1.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light_10.png b/games/devtest/mods/testnodes/textures/testnodes_light_10.png new file mode 100644 index 000000000..483834770 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light_10.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light_11.png b/games/devtest/mods/testnodes/textures/testnodes_light_11.png new file mode 100644 index 000000000..4c423d9b4 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light_11.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light_12.png b/games/devtest/mods/testnodes/textures/testnodes_light_12.png new file mode 100644 index 000000000..bc7946d09 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light_12.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light_13.png b/games/devtest/mods/testnodes/textures/testnodes_light_13.png new file mode 100644 index 000000000..0b63c84a6 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light_13.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light_14.png b/games/devtest/mods/testnodes/textures/testnodes_light_14.png new file mode 100644 index 000000000..a817bd394 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light_14.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light_2.png b/games/devtest/mods/testnodes/textures/testnodes_light_2.png new file mode 100644 index 000000000..852eaeff1 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light_2.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light_3.png b/games/devtest/mods/testnodes/textures/testnodes_light_3.png new file mode 100644 index 000000000..79fc834cc Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light_3.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light_4.png b/games/devtest/mods/testnodes/textures/testnodes_light_4.png new file mode 100644 index 000000000..75f8c6136 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light_4.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light_5.png b/games/devtest/mods/testnodes/textures/testnodes_light_5.png new file mode 100644 index 000000000..b6eede0ae Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light_5.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light_6.png b/games/devtest/mods/testnodes/textures/testnodes_light_6.png new file mode 100644 index 000000000..ef54addec Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light_6.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light_7.png b/games/devtest/mods/testnodes/textures/testnodes_light_7.png new file mode 100644 index 000000000..4a885b0f6 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light_7.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light_8.png b/games/devtest/mods/testnodes/textures/testnodes_light_8.png new file mode 100644 index 000000000..b283301e3 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light_8.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_light_9.png b/games/devtest/mods/testnodes/textures/testnodes_light_9.png new file mode 100644 index 000000000..2aa902358 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_light_9.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_line_crossing.png b/games/devtest/mods/testnodes/textures/testnodes_line_crossing.png new file mode 100644 index 000000000..e566f2793 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_line_crossing.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_line_curved.png b/games/devtest/mods/testnodes/textures/testnodes_line_curved.png new file mode 100644 index 000000000..ab9f8e720 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_line_curved.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_line_straight.png b/games/devtest/mods/testnodes/textures/testnodes_line_straight.png new file mode 100644 index 000000000..4f33d9c6d Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_line_straight.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_line_t_junction.png b/games/devtest/mods/testnodes/textures/testnodes_line_t_junction.png new file mode 100644 index 000000000..5668f6ea3 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_line_t_junction.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquid.png b/games/devtest/mods/testnodes/textures/testnodes_liquid.png new file mode 100644 index 000000000..98ab270c2 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquid.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidflowing.png b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing.png new file mode 100644 index 000000000..1736b89ba Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r0.png b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r0.png new file mode 100644 index 000000000..e8a61039d Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r0.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r1.png b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r1.png new file mode 100644 index 000000000..b4e45b42f Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r1.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r2.png b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r2.png new file mode 100644 index 000000000..e064b8f2d Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r2.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r3.png b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r3.png new file mode 100644 index 000000000..bef773968 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r3.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r4.png b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r4.png new file mode 100644 index 000000000..de1001b2d Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r4.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r5.png b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r5.png new file mode 100644 index 000000000..97b422e9a Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r5.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r6.png b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r6.png new file mode 100644 index 000000000..4cd8e4e8e Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r6.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r7.png b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r7.png new file mode 100644 index 000000000..711dd961c Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r7.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r8.png b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r8.png new file mode 100644 index 000000000..9cf22b8ca Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidflowing_r8.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidsource.png b/games/devtest/mods/testnodes/textures/testnodes_liquidsource.png new file mode 100644 index 000000000..b3f29b702 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidsource.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r0.png b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r0.png new file mode 100644 index 000000000..da0a99623 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r0.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r1.png b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r1.png new file mode 100644 index 000000000..66bf2be8f Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r1.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r2.png b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r2.png new file mode 100644 index 000000000..fc5f65cb6 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r2.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r3.png b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r3.png new file mode 100644 index 000000000..0f46e291e Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r3.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r4.png b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r4.png new file mode 100644 index 000000000..0693a04d7 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r4.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r5.png b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r5.png new file mode 100644 index 000000000..cc9d03992 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r5.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r6.png b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r6.png new file mode 100644 index 000000000..e276a07ae Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r6.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r7.png b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r7.png new file mode 100644 index 000000000..3534a4b15 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r7.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r8.png b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r8.png new file mode 100644 index 000000000..ee1a8b169 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_liquidsource_r8.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_mesh_stripes.png b/games/devtest/mods/testnodes/textures/testnodes_mesh_stripes.png new file mode 100644 index 000000000..51b8e0025 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_mesh_stripes.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_mesh_stripes2.png b/games/devtest/mods/testnodes/textures/testnodes_mesh_stripes2.png new file mode 100644 index 000000000..9ea65c1ec Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_mesh_stripes2.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_mesh_stripes3.png b/games/devtest/mods/testnodes/textures/testnodes_mesh_stripes3.png new file mode 100644 index 000000000..96bc55ac5 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_mesh_stripes3.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_mesh_stripes4.png b/games/devtest/mods/testnodes/textures/testnodes_mesh_stripes4.png new file mode 100644 index 000000000..fca33727d Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_mesh_stripes4.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_node.png b/games/devtest/mods/testnodes/textures/testnodes_node.png new file mode 100644 index 000000000..145099b3a Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_node.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_node_falling.png b/games/devtest/mods/testnodes/textures/testnodes_node_falling.png new file mode 100644 index 000000000..44153185c Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_node_falling.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_nodebox.png b/games/devtest/mods/testnodes/textures/testnodes_nodebox.png new file mode 100644 index 000000000..66e8dd663 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_nodebox.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_nojump_side.png b/games/devtest/mods/testnodes/textures/testnodes_nojump_side.png new file mode 100644 index 000000000..6a64cfff0 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_nojump_side.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_nojump_top.png b/games/devtest/mods/testnodes/textures/testnodes_nojump_top.png new file mode 100644 index 000000000..fe770838f Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_nojump_top.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_normal.png b/games/devtest/mods/testnodes/textures/testnodes_normal.png new file mode 100644 index 000000000..a1acfd9fd Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_normal.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_normal1.png b/games/devtest/mods/testnodes/textures/testnodes_normal1.png new file mode 100644 index 000000000..edaba77e4 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_normal1.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_normal2.png b/games/devtest/mods/testnodes/textures/testnodes_normal2.png new file mode 100644 index 000000000..0080a9ee7 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_normal2.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_normal3.png b/games/devtest/mods/testnodes/textures/testnodes_normal3.png new file mode 100644 index 000000000..0426ab216 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_normal3.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_normal4.png b/games/devtest/mods/testnodes/textures/testnodes_normal4.png new file mode 100644 index 000000000..0d1922eb6 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_normal4.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_normal5.png b/games/devtest/mods/testnodes/textures/testnodes_normal5.png new file mode 100644 index 000000000..0b7dcd2da Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_normal5.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_normal6.png b/games/devtest/mods/testnodes/textures/testnodes_normal6.png new file mode 100644 index 000000000..f34a67d71 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_normal6.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_palette_facedir.png b/games/devtest/mods/testnodes/textures/testnodes_palette_facedir.png new file mode 100644 index 000000000..8cf47bbbe Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_palette_facedir.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_palette_full.png b/games/devtest/mods/testnodes/textures/testnodes_palette_full.png new file mode 100644 index 000000000..e0a5f8b34 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_palette_full.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_palette_wallmounted.png b/games/devtest/mods/testnodes/textures/testnodes_palette_wallmounted.png new file mode 100644 index 000000000..682f3ac84 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_palette_wallmounted.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike.png new file mode 100644 index 000000000..cc464444d Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike_degrotate.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike_degrotate.png new file mode 100644 index 000000000..01c81da8e Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike_degrotate.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike_leveled.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike_leveled.png new file mode 100644 index 000000000..53504dbcd Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike_leveled.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike_meshoptions.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike_meshoptions.png new file mode 100644 index 000000000..d504d459f Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike_meshoptions.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted.png new file mode 100644 index 000000000..79cf2125e Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base.png new file mode 100644 index 000000000..b9ee9e5be Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_degrotate.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_degrotate.png new file mode 100644 index 000000000..85311cb2c Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_degrotate.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_leveled.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_leveled.png new file mode 100644 index 000000000..bc602bafe Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_leveled.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_meshoptions.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_meshoptions.png new file mode 100644 index 000000000..d10002375 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_meshoptions.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_waving.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_waving.png new file mode 100644 index 000000000..527817bc1 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_waving.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_degrotate.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_degrotate.png new file mode 100644 index 000000000..45e75bdd3 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_degrotate.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_leveled.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_leveled.png new file mode 100644 index 000000000..8954b2c34 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_leveled.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_meshoptions.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_meshoptions.png new file mode 100644 index 000000000..a782d4874 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_meshoptions.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_waving.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_waving.png new file mode 100644 index 000000000..112a0540f Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike_rooted_waving.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_plantlike_waving.png b/games/devtest/mods/testnodes/textures/testnodes_plantlike_waving.png new file mode 100644 index 000000000..b584a8dc9 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_plantlike_waving.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_rail2_crossing.png b/games/devtest/mods/testnodes/textures/testnodes_rail2_crossing.png new file mode 100644 index 000000000..530bbba7a Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_rail2_crossing.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_rail2_curved.png b/games/devtest/mods/testnodes/textures/testnodes_rail2_curved.png new file mode 100644 index 000000000..4ed1ca00f Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_rail2_curved.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_rail2_straight.png b/games/devtest/mods/testnodes/textures/testnodes_rail2_straight.png new file mode 100644 index 000000000..8749330d8 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_rail2_straight.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_rail2_t_junction.png b/games/devtest/mods/testnodes/textures/testnodes_rail2_t_junction.png new file mode 100644 index 000000000..0517f6570 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_rail2_t_junction.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_rail_crossing.png b/games/devtest/mods/testnodes/textures/testnodes_rail_crossing.png new file mode 100644 index 000000000..3916ce1ef Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_rail_crossing.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_rail_curved.png b/games/devtest/mods/testnodes/textures/testnodes_rail_curved.png new file mode 100644 index 000000000..e44419848 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_rail_curved.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_rail_straight.png b/games/devtest/mods/testnodes/textures/testnodes_rail_straight.png new file mode 100644 index 000000000..872d04fb9 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_rail_straight.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_rail_t_junction.png b/games/devtest/mods/testnodes/textures/testnodes_rail_t_junction.png new file mode 100644 index 000000000..7e4af5182 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_rail_t_junction.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_signlike.png b/games/devtest/mods/testnodes/textures/testnodes_signlike.png new file mode 100644 index 000000000..33ffcba6c Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_signlike.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_slippery.png b/games/devtest/mods/testnodes/textures/testnodes_slippery.png new file mode 100644 index 000000000..b990468a1 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_slippery.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_street_crossing.png b/games/devtest/mods/testnodes/textures/testnodes_street_crossing.png new file mode 100644 index 000000000..d6e35ad7a Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_street_crossing.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_street_curved.png b/games/devtest/mods/testnodes/textures/testnodes_street_curved.png new file mode 100644 index 000000000..251b7fb71 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_street_curved.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_street_straight.png b/games/devtest/mods/testnodes/textures/testnodes_street_straight.png new file mode 100644 index 000000000..639e24b93 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_street_straight.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_street_t_junction.png b/games/devtest/mods/testnodes/textures/testnodes_street_t_junction.png new file mode 100644 index 000000000..713621e06 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_street_t_junction.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_sunlight_filter.png b/games/devtest/mods/testnodes/textures/testnodes_sunlight_filter.png new file mode 100644 index 000000000..b38ea4072 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_sunlight_filter.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_torchlike_ceiling.png b/games/devtest/mods/testnodes/textures/testnodes_torchlike_ceiling.png new file mode 100644 index 000000000..5d9862cc9 Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_torchlike_ceiling.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_torchlike_floor.png b/games/devtest/mods/testnodes/textures/testnodes_torchlike_floor.png new file mode 100644 index 000000000..adf1e002d Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_torchlike_floor.png differ diff --git a/games/devtest/mods/testnodes/textures/testnodes_torchlike_wall.png b/games/devtest/mods/testnodes/textures/testnodes_torchlike_wall.png new file mode 100644 index 000000000..cb442b22d Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_torchlike_wall.png differ diff --git a/games/devtest/mods/testpathfinder/README.md b/games/devtest/mods/testpathfinder/README.md new file mode 100644 index 000000000..2b9d46e70 --- /dev/null +++ b/games/devtest/mods/testpathfinder/README.md @@ -0,0 +1,15 @@ +# Pathfinder Tester + +Usage: + +Use the Pathfinder Tester tool (`testpathfinder:testpathfinder`). +Here's how it works: + +* Place on node: Set destination position +* Punch: Find path +* Sneak+punch: Select pathfinding algorithm + +Information will be shown in chat. If a path was found, all waypoints +will be shown for a few seconds. + +See `init.lua` for config variables. diff --git a/games/devtest/mods/testpathfinder/init.lua b/games/devtest/mods/testpathfinder/init.lua new file mode 100644 index 000000000..f94848236 --- /dev/null +++ b/games/devtest/mods/testpathfinder/init.lua @@ -0,0 +1,132 @@ +local S = minetest.get_translator("testpathfinder") + +-- Config parameters + +-- Maximum direct distance between start and end +local MAX_DIRECT_DISTANCE = 64 +-- Maximum search distance +local MAX_SEARCH_DISTANCE = 32 +-- Maximum permitted jump height +local MAX_JUMP = 1 +-- Maximum permitted drop height +local MAX_DROP = 5 +-- If true, mod won't refuse to run pathfinder even at long distances +local IGNORE_MAX_DISTANCE_SAFEGUARD = false + +-- End of config parameters + +local timer = 0 +local algorithms = { + "A*_noprefetch", + "A*", + "Dijkstra", +} + +local function find_path_for_player(player, itemstack) + local meta = itemstack:get_meta() + if not meta then + return + end + local x = meta:get_int("pos_x") + local y = meta:get_int("pos_y") + local z = meta:get_int("pos_z") + local algo = meta:get_int("algorithm") + if x and y and z then + local pos2 = {x=x, y=y, z=z} + algo = algorithms[algo+1] + local pos1 = vector.round(player:get_pos()) + -- Don't bother calling pathfinder for high distance to avoid freezing + if (not IGNORE_MAX_DISTANCE_SAFEGUARD) and (vector.distance(pos1, pos2) > MAX_DIRECT_DISTANCE) then + minetest.chat_send_player(player:get_player_name(), S("Destination too far away! Set a destination (via placing) within a distance of @1 and try again!", MAX_DIRECT_DISTANCE)) + return + end + local str = S("Path from @1 to @2:", + minetest.pos_to_string(pos1), + minetest.pos_to_string(pos2)) + + minetest.chat_send_player(player:get_player_name(), str) + local time_start = minetest.get_us_time() + local path = minetest.find_path(pos1, pos2, MAX_SEARCH_DISTANCE, MAX_JUMP, MAX_DROP, algo) + local time_end = minetest.get_us_time() + local time_diff = time_end - time_start + str = "" + if not path then + minetest.chat_send_player(player:get_player_name(), S("No path!")) + minetest.chat_send_player(player:get_player_name(), S("Time: @1 ms", time_diff/1000)) + return + end + for s=1, #path do + str = str .. minetest.pos_to_string(path[s]) .. "\n" + local t + if s == #path then + t = "testpathfinder_waypoint_end.png" + elseif s == 1 then + t = "testpathfinder_waypoint_start.png" + else + local c = math.floor(((#path-s)/#path)*255) + t = string.format("testpathfinder_waypoint.png^[multiply:#%02x%02x00", 0xFF-c, c) + end + minetest.add_particle({ + pos = path[s], + expirationtime = 5 + 0.2 * s, + playername = player:get_player_name(), + glow = minetest.LIGHT_MAX, + texture = t, + size = 3, + }) + end + minetest.chat_send_player(player:get_player_name(), str) + minetest.chat_send_player(player:get_player_name(), S("Path length: @1", #path)) + minetest.chat_send_player(player:get_player_name(), S("Time: @1 ms", time_diff/1000)) + end +end + +local function set_destination(itemstack, user, pointed_thing) + if not (user and user:is_player()) then + return + end + local name = user:get_player_name() + local obj + local meta = itemstack:get_meta() + if pointed_thing.type == "node" then + local pos = pointed_thing.above + meta:set_int("pos_x", pos.x) + meta:set_int("pos_y", pos.y) + meta:set_int("pos_z", pos.z) + minetest.chat_send_player(user:get_player_name(), S("Destination set to @1", minetest.pos_to_string(pos))) + return itemstack + end +end + +local function find_path_or_set_algorithm(itemstack, user, pointed_thing) + if not (user and user:is_player()) then + return + end + local ctrl = user:get_player_control() + -- No sneak: Find path + if not ctrl.sneak then + find_path_for_player(user, itemstack) + else + -- Sneak: Set algorithm + local meta = itemstack:get_meta() + local algo = meta:get_int("algorithm") + algo = (algo + 1) % #algorithms + meta:set_int("algorithm", algo) + minetest.chat_send_player(user:get_player_name(), S("Algorithm: @1", algorithms[algo+1])) + return itemstack + end +end + +-- Punch: Find path +-- Sneak+punch: Select pathfinding algorithm +-- Place: Select destination node +minetest.register_tool("testpathfinder:testpathfinder", { + description = S("Pathfinder Tester"), + inventory_image = "testpathfinder_testpathfinder.png", + groups = { testtool = 1, disable_repair = 1 }, + on_use = find_path_or_set_algorithm, + on_secondary_use = set_destination, + on_place = set_destination, +}) + + diff --git a/games/devtest/mods/testpathfinder/mod.conf b/games/devtest/mods/testpathfinder/mod.conf new file mode 100644 index 000000000..e6034ae8c --- /dev/null +++ b/games/devtest/mods/testpathfinder/mod.conf @@ -0,0 +1,2 @@ +name = testpathfinder +description = Tool to test Minetest's pathfinder function diff --git a/games/devtest/mods/testpathfinder/textures/testpathfinder_testpathfinder.png b/games/devtest/mods/testpathfinder/textures/testpathfinder_testpathfinder.png new file mode 100644 index 000000000..37eef0565 Binary files /dev/null and b/games/devtest/mods/testpathfinder/textures/testpathfinder_testpathfinder.png differ diff --git a/games/devtest/mods/testpathfinder/textures/testpathfinder_waypoint.png b/games/devtest/mods/testpathfinder/textures/testpathfinder_waypoint.png new file mode 100644 index 000000000..661dcf906 Binary files /dev/null and b/games/devtest/mods/testpathfinder/textures/testpathfinder_waypoint.png differ diff --git a/games/devtest/mods/testpathfinder/textures/testpathfinder_waypoint_end.png b/games/devtest/mods/testpathfinder/textures/testpathfinder_waypoint_end.png new file mode 100644 index 000000000..41a1cc549 Binary files /dev/null and b/games/devtest/mods/testpathfinder/textures/testpathfinder_waypoint_end.png differ diff --git a/games/devtest/mods/testpathfinder/textures/testpathfinder_waypoint_start.png b/games/devtest/mods/testpathfinder/textures/testpathfinder_waypoint_start.png new file mode 100644 index 000000000..a22e31c3b Binary files /dev/null and b/games/devtest/mods/testpathfinder/textures/testpathfinder_waypoint_start.png differ diff --git a/games/devtest/mods/testtools/README.md b/games/devtest/mods/testtools/README.md new file mode 100644 index 000000000..9cfe29ea4 --- /dev/null +++ b/games/devtest/mods/testtools/README.md @@ -0,0 +1,99 @@ +# Test Tools readme + +Test Tools is a mod for developers that adds a bunch of tools to directly manipulate nodes and entities. This is great for quickly testing out stuff. + +Here's the list of tools: + +## Remover +Removes nodes and non-player entities that you punch. + +## Node Setter +Replace a node with another one. + +First, punch a node you want to remember. +Then rightclick any other node to replace it with the node you remembered. + +If you rightclick while pointing nothing, you can manually enter the node and param2. + +## Param2 Tool +Change the value param2 of nodes. + +* Punch: Add 1 to param2 +* Sneak+Punch: Add 8 to param2 +* Place: Subtract 1 from param2 +* Sneak+Place: Subtract 8 from param2 + +Note: Use the debug screen (F5) to see the param2 of the pointed node. + +## Falling Node Tool +Turns nodes into falling nodes. + +Usage: + +* Punch node: Make it fall +* Place: Try to teleport up to 2 units upwards, then make it fall + +## Entity Rotator +Changes the entity rotation (with `set_rotation`). + +Usage: + +* Punch entity: Rotate yaw +* Punch entity while holding down “Sneak” key: Rotate pitch +* Punch entity while holding down “Special” key (aka “Aux”): Rotate roll + +Each usage rotates the entity by 22.5°. + +## Entity Spawner +Spawns entities. + +Usage: + +* Punch to select entity or spawn one directly +* Place to place selected entity + +## Object Property Editor +Edits properties of objects. + +Usage: + +* Punch object to open a formspec that allows you to view and edit properties +* Punch air to edit properties of your own player object + +To edit a property, select it in the list, enter a new value (in Lua syntax) +and hit “Submit”. + +## Object Attacher +Allows you to attach an object to another one. + +Basic usage: +* First select the parent object, then the child object that should be attached +* Selecting an object is done by punching it +* Sneak+punch to detach selected object +* If you punch air, you select yourself + +Configuration: +* Place: Increase attachment Y position +* Sneak+place: decrease attachment Y position +* Aux+place: Increase attachment X rotation +* Aux+Sneak+Rightclick: Decrease attachment X rotation + +Hint: To detach all objects nearby you (including on yourself), use the +`/detach` server command. + +## Object Mover +Move an object by a given distance. + +Usage: +* Punch object into the direction you want to move it +* Sneak+punch: Move object towards you +* Place: Increase move distance +* Sneak+place: Decrease move distance + +## Entity Visual Scaler +Change visual size of entities + +Usage: + +* Punch entity to increase visual size +* Sneak+punch entity to decrease visual size diff --git a/games/devtest/mods/testtools/init.lua b/games/devtest/mods/testtools/init.lua new file mode 100644 index 000000000..a63c98377 --- /dev/null +++ b/games/devtest/mods/testtools/init.lua @@ -0,0 +1,691 @@ +local S = minetest.get_translator("testtools") +local F = minetest.formspec_escape + +-- TODO: Add a Node Metadata tool + +-- Param 2 Tool: Set param2 value of tools +-- Punch: +1 +-- Punch+Shift: +8 +-- Place: -1 +-- Place+Shift: -8 +minetest.register_tool("testtools:param2tool", { + description = S("Param2 Tool"), + inventory_image = "testtools_param2tool.png", + groups = { testtool = 1, disable_repair = 1 }, + on_use = function(itemstack, user, pointed_thing) + local pos = minetest.get_pointed_thing_position(pointed_thing) + if pointed_thing.type ~= "node" or (not pos) then + return + end + local add = 1 + if user then + local ctrl = user:get_player_control() + if ctrl.sneak then + add = 8 + end + end + local node = minetest.get_node(pos) + node.param2 = node.param2 + add + minetest.swap_node(pos, node) + end, + on_place = function(itemstack, user, pointed_thing) + local pos = minetest.get_pointed_thing_position(pointed_thing) + if pointed_thing.type ~= "node" or (not pos) then + return + end + local add = -1 + if user then + local ctrl = user:get_player_control() + if ctrl.sneak then + add = -8 + end + end + local node = minetest.get_node(pos) + node.param2 = node.param2 + add + minetest.swap_node(pos, node) + end, +}) + +minetest.register_tool("testtools:node_setter", { + description = S("Node Setter"), + inventory_image = "testtools_node_setter.png", + groups = { testtool = 1, disable_repair = 1 }, + on_use = function(itemstack, user, pointed_thing) + local pos = minetest.get_pointed_thing_position(pointed_thing) + if pointed_thing.type == "nothing" then + local meta = itemstack:get_meta() + meta:set_string("node", "air") + meta:set_int("node_param2", 0) + if user and user:is_player() then + minetest.chat_send_player(user:get_player_name(), S("Now placing: @1 (param2=@2)", "air", 0)) + end + return itemstack + elseif pointed_thing.type ~= "node" or (not pos) then + return + end + local node = minetest.get_node(pos) + local meta = itemstack:get_meta() + meta:set_string("node", node.name) + meta:set_int("node_param2", node.param2) + if user and user:is_player() then + minetest.chat_send_player(user:get_player_name(), S("Now placing: @1 (param2=@2)", node.name, node.param2)) + end + return itemstack + end, + on_secondary_use = function(itemstack, user, pointed_thing) + local meta = itemstack:get_meta() + local nodename = meta:get_string("node") or "" + local param2 = meta:get_int("node_param2") or 0 + + minetest.show_formspec(user:get_player_name(), "testtools:node_setter", + "size[4,4]".. + "field[0.5,1;3,1;nodename;"..F(S("Node name (itemstring):"))..";"..F(nodename).."]".. + "field[0.5,2;3,1;param2;"..F(S("param2:"))..";"..F(tostring(param2)).."]".. + "button_exit[0.5,3;3,1;submit;"..F(S("Submit")).."]" + ) + end, + on_place = function(itemstack, user, pointed_thing) + local pos = minetest.get_pointed_thing_position(pointed_thing) + local meta = itemstack:get_meta() + local nodename = meta:get_string("node") + if nodename == "" and user and user:is_player() then + minetest.chat_send_player(user:get_player_name(), S("Punch a node first!")) + return + end + local param2 = meta:get_int("node_param2") + if not param2 then + param2 = 0 + end + local node = { name = nodename, param2 = param2 } + if not minetest.registered_nodes[nodename] then + minetest.chat_send_player(user:get_player_name(), S("Cannot set unknown node: @1", nodename)) + return + end + minetest.set_node(pos, node) + end, +}) + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname == "testtools:node_setter" then + local playername = player:get_player_name() + local witem = player:get_wielded_item() + if witem:get_name() == "testtools:node_setter" then + if fields.nodename and fields.param2 then + local param2 = tonumber(fields.param2) + if not param2 then + return + end + local meta = witem:get_meta() + meta:set_string("node", fields.nodename) + meta:set_int("node_param2", param2) + player:set_wielded_item(witem) + end + end + end +end) + +minetest.register_tool("testtools:remover", { + description = S("Remover"), + inventory_image = "testtools_remover.png", + groups = { testtool = 1, disable_repair = 1 }, + on_use = function(itemstack, user, pointed_thing) + local pos = minetest.get_pointed_thing_position(pointed_thing) + if pointed_thing.type == "node" and pos ~= nil then + minetest.remove_node(pos) + elseif pointed_thing.type == "object" then + local obj = pointed_thing.ref + if not obj:is_player() then + obj:remove() + end + end + end, +}) + +minetest.register_tool("testtools:falling_node_tool", { + description = S("Falling Node Tool"), + inventory_image = "testtools_falling_node_tool.png", + groups = { testtool = 1, disable_repair = 1 }, + on_place = function(itemstack, user, pointed_thing) + -- Teleport node 1-2 units upwards (if possible) and make it fall + local pos = minetest.get_pointed_thing_position(pointed_thing) + if pointed_thing.type ~= "node" or (not pos) then + return + end + local ok = false + local highest + for i=1,2 do + local above = {x=pos.x,y=pos.y+i,z=pos.z} + local n2 = minetest.get_node(above) + local def2 = minetest.registered_nodes[n2.name] + if def2 and (not def2.walkable) then + highest = above + else + break + end + end + if highest then + local node = minetest.get_node(pos) + local metatable = minetest.get_meta(pos):to_table() + minetest.remove_node(pos) + minetest.set_node(highest, node) + local meta_highest = minetest.get_meta(highest) + meta_highest:from_table(metatable) + ok = minetest.spawn_falling_node(highest) + else + ok = minetest.spawn_falling_node(pos) + end + if not ok and user and user:is_player() then + minetest.chat_send_player(user:get_player_name(), S("Falling node could not be spawned!")) + end + end, + on_use = function(itemstack, user, pointed_thing) + local pos = minetest.get_pointed_thing_position(pointed_thing) + if pointed_thing.type ~= "node" or (not pos) then + return + end + local ok = minetest.spawn_falling_node(pos) + if not ok and user and user:is_player() then + minetest.chat_send_player(user:get_player_name(), S("Falling node could not be spawned!")) + end + end, +}) + +minetest.register_tool("testtools:rotator", { + description = S("Entity Rotator"), + inventory_image = "testtools_entity_rotator.png", + groups = { testtool = 1, disable_repair = 1 }, + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type ~= "object" then + return + end + local obj = pointed_thing.ref + if obj:is_player() then + -- No player rotation + return + else + local axis = "y" + if user and user:is_player() then + local ctrl = user:get_player_control() + if ctrl.sneak then + axis = "x" + elseif ctrl.aux1 then + axis = "z" + end + end + local rot = obj:get_rotation() + rot[axis] = rot[axis] + math.pi/8 + if rot[axis] > math.pi*2 then + rot[axis] = rot[axis] - math.pi*2 + end + obj:set_rotation(rot) + end + end, +}) + +local mover_config = function(itemstack, user, pointed_thing) + if not (user and user:is_player()) then + return + end + local name = user:get_player_name() + local ctrl = user:get_player_control() + local meta = itemstack:get_meta() + local dist = 1.0 + if meta:contains("distance") then + dist = meta:get_int("distance") + end + if ctrl.sneak then + dist = dist - 1 + else + dist = dist + 1 + end + meta:set_int("distance", dist) + minetest.chat_send_player(user:get_player_name(), S("distance=@1/10", dist*2)) + return itemstack +end + +minetest.register_tool("testtools:object_mover", { + description = S("Object Mover"), + inventory_image = "testtools_object_mover.png", + groups = { testtool = 1, disable_repair = 1 }, + on_place = mover_config, + on_secondary_use = mover_config, + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type ~= "object" then + return + end + local obj = pointed_thing.ref + if not (user and user:is_player()) then + return + end + local yaw = user:get_look_horizontal() + local dir = minetest.yaw_to_dir(yaw) + local pos = obj:get_pos() + local pitch = user:get_look_vertical() + if pitch > 0.25 * math.pi then + dir.y = -1 + dir.x = 0 + dir.z = 0 + elseif pitch < -0.25 * math.pi then + dir.y = 1 + dir.x = 0 + dir.z = 0 + end + local ctrl = user:get_player_control() + if ctrl.sneak then + dir = vector.multiply(dir, -1) + end + local meta = itemstack:get_meta() + if meta:contains("distance") then + local dist = meta:get_int("distance") + dir = vector.multiply(dir, dist*0.2) + end + pos = vector.add(pos, dir) + obj:set_pos(pos) + end, +}) + + + +minetest.register_tool("testtools:entity_scaler", { + description = S("Entity Visual Scaler"), + inventory_image = "testtools_entity_scaler.png", + groups = { testtool = 1, disable_repair = 1 }, + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type ~= "object" then + return + end + local obj = pointed_thing.ref + if obj:is_player() then + -- No player scaling + return + else + local diff = 0.1 + if user and user:is_player() then + local ctrl = user:get_player_control() + if ctrl.sneak then + diff = -0.1 + end + end + local prop = obj:get_properties() + if not prop.visual_size then + prop.visual_size = { x=1, y=1, z=1 } + else + prop.visual_size = { x=prop.visual_size.x+diff, y=prop.visual_size.y+diff, z=prop.visual_size.z+diff } + if prop.visual_size.x <= 0.1 then + prop.visual_size.x = 0.1 + end + if prop.visual_size.y <= 0.1 then + prop.visual_size.y = 0.1 + end + if prop.visual_size.z <= 0.1 then + prop.visual_size.z = 0.1 + end + end + obj:set_properties(prop) + end + end, +}) + +local selections = {} +local entity_list +local function get_entity_list() + if entity_list then + return entity_list + end + local ents = minetest.registered_entities + local list = {} + for k,_ in pairs(ents) do + table.insert(list, k) + end + table.sort(list) + entity_list = list + return entity_list +end +minetest.register_tool("testtools:entity_spawner", { + description = S("Entity Spawner"), + inventory_image = "testtools_entity_spawner.png", + groups = { testtool = 1, disable_repair = 1 }, + on_place = function(itemstack, user, pointed_thing) + local name = user:get_player_name() + if selections[name] and pointed_thing.type == "node" then + local pos = pointed_thing.above + minetest.add_entity(pos, get_entity_list()[selections[name]]) + end + end, + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type == "object" then + return + end + if user and user:is_player() then + local list = table.concat(get_entity_list(), ",") + local name = user:get_player_name() + local sel = selections[name] or "" + minetest.show_formspec(name, "testtools:entity_list", + "size[9,9]".. + "textlist[0,0;9,8;entity_list;"..list..";"..sel..";false]".. + "button[0,8;4,1;spawn;Spawn entity]" + ) + end + end, +}) + +local function prop_to_string(property) + if type(property) == "string" then + return "\"" .. property .. "\"" + elseif type(property) == "table" then + return tostring(dump(property)):gsub("\n", "") + else + return tostring(property) + end +end + +local property_formspec_data = {} +local property_formspec_index = {} +local selected_objects = {} +local function get_object_properties_form(obj, playername) + if not playername then return "" end + local props = obj:get_properties() + local str = "" + property_formspec_data[playername] = {} + local proplist = {} + for k,_ in pairs(props) do + table.insert(proplist, k) + end + table.sort(proplist) + for p=1, #proplist do + local k = proplist[p] + local v = props[k] + local newline = "" + newline = k .. " = " + newline = newline .. prop_to_string(v) + str = str .. F(newline) + if p < #proplist then + str = str .. "," + end + table.insert(property_formspec_data[playername], k) + end + return str +end + +local editor_formspec_selindex = {} + +local editor_formspec = function(playername, obj, value, sel) + if not value then + value = "" + end + if not sel then + sel = "" + end + local list = get_object_properties_form(obj, playername) + local title + if obj:is_player() then + title = S("Object properties of player “@1”", obj:get_player_name()) + else + local ent = obj:get_luaentity() + title = S("Object properties of @1", ent.name) + end + minetest.show_formspec(playername, "testtools:object_editor", + "size[9,9]".. + "label[0,0;"..F(title).."]".. + "textlist[0,0.5;9,7.5;object_props;"..list..";"..sel..";false]".. + "field[0.2,8.75;8,1;value;"..F(S("Value"))..";"..F(value).."]".. + "button[8,8.5;1,1;submit;"..F(S("Submit")).."]" + ) +end + +minetest.register_tool("testtools:object_editor", { + description = S("Object Property Editor"), + inventory_image = "testtools_object_editor.png", + groups = { testtool = 1, disable_repair = 1 }, + on_use = function(itemstack, user, pointed_thing) + if user and user:is_player() then + local name = user:get_player_name() + + if pointed_thing.type == "object" then + selected_objects[name] = pointed_thing.ref + elseif pointed_thing.type == "nothing" then + -- Use on yourself if pointing nothing + selected_objects[name] = user + else + -- Unsupported pointed thing + return + end + + local sel = editor_formspec_selindex[name] + local val + if selected_objects[name] and selected_objects[name]:get_properties() then + local props = selected_objects[name]:get_properties() + local keys = property_formspec_data[name] + if property_formspec_index[name] and props then + local key = keys[property_formspec_index[name]] + val = prop_to_string(props[key]) + end + end + + editor_formspec(name, selected_objects[name], val, sel) + end + end, +}) + +local ent_parent = {} +local ent_child = {} +local DEFAULT_ATTACH_OFFSET_Y = 11 + +local attacher_config = function(itemstack, user, pointed_thing) + if not (user and user:is_player()) then + return + end + if pointed_thing.type == "object" then + return + end + local name = user:get_player_name() + local ctrl = user:get_player_control() + local meta = itemstack:get_meta() + if ctrl.aux1 then + local rot_x = meta:get_float("rot_x") + if ctrl.sneak then + rot_x = rot_x - math.pi/8 + else + rot_x = rot_x + math.pi/8 + end + if rot_x > 6.2 then + rot_x = 0 + elseif rot_x < 0 then + rot_x = math.pi * (15/8) + end + minetest.chat_send_player(name, S("rotation=@1", minetest.pos_to_string({x=rot_x,y=0,z=0}))) + meta:set_float("rot_x", rot_x) + else + local pos_y + if meta:contains("pos_y") then + pos_y = meta:get_int("pos_y") + else + pos_y = DEFAULT_ATTACH_OFFSET_Y + end + if ctrl.sneak then + pos_y = pos_y - 1 + else + pos_y = pos_y + 1 + end + minetest.chat_send_player(name, S("position=@1", minetest.pos_to_string({x=0,y=pos_y,z=0}))) + meta:set_int("pos_y", pos_y) + end + return itemstack +end + +minetest.register_tool("testtools:object_attacher", { + description = S("Object Attacher"), + inventory_image = "testtools_object_attacher.png", + groups = { testtool = 1, disable_repair = 1 }, + on_place = attacher_config, + on_secondary_use = attacher_config, + on_use = function(itemstack, user, pointed_thing) + if user and user:is_player() then + local name = user:get_player_name() + local selected_object + if pointed_thing.type == "object" then + selected_object = pointed_thing.ref + elseif pointed_thing.type == "nothing" then + selected_object = user + else + return + end + local ctrl = user:get_player_control() + if ctrl.sneak then + if selected_object:get_attach() then + selected_object:set_detach() + minetest.chat_send_player(name, S("Object detached!")) + else + minetest.chat_send_player(name, S("Object is not attached!")) + end + return + end + local parent = ent_parent[name] + local child = ent_child[name] + local ename = S("") + if not parent then + parent = selected_object + ent_parent[name] = parent + elseif not child then + child = selected_object + ent_child[name] = child + end + local entity = selected_object:get_luaentity() + if entity then + ename = entity.name + elseif selected_object:is_player() then + ename = selected_object:get_player_name() + end + if selected_object == parent then + minetest.chat_send_player(name, S("Parent object selected: @1", ename)) + elseif selected_object == child then + minetest.chat_send_player(name, S("Child object selected: @1", ename)) + end + if parent and child then + if parent == child then + minetest.chat_send_player(name, S("Can't attach an object to itself!")) + ent_parent[name] = nil + ent_child[name] = nil + return + end + local meta = itemstack:get_meta() + local y + if meta:contains("pos_y") then + y = meta:get_int("pos_y") + else + y = DEFAULT_ATTACH_OFFSET_Y + end + local rx = meta:get_float("rot_x") or 0 + local offset = {x=0,y=y,z=0} + local angle = {x=rx,y=0,z=0} + child:set_attach(parent, "", offset, angle) + local check_parent = child:get_attach() + if check_parent then + minetest.chat_send_player(name, S("Object attached! position=@1, rotation=@2", + minetest.pos_to_string(offset), minetest.pos_to_string(angle))) + else + minetest.chat_send_player(name, S("Attachment failed!")) + end + ent_parent[name] = nil + ent_child[name] = nil + end + end + end, +}) + +-- Use loadstring to parse param as a Lua value +local function use_loadstring(param, player) + -- For security reasons, require 'server' priv, just in case + -- someone is actually crazy enough to run this on a public server. + local privs = minetest.get_player_privs(player:get_player_name()) + if not privs.server then + return false, "You need 'server' privilege to change object properties!" + end + if not param then + return false, "Failed: parameter is nil" + end + --[[ DANGER ZONE ]] + -- Interpret string as Lua value + local func, errormsg = loadstring("return (" .. param .. ")") + if not func then + return false, "Failed: " .. errormsg + end + + -- Apply sandbox here using setfenv + setfenv(func, {}) + + -- Run it + local good, errOrResult = pcall(func) + if not good then + -- A Lua error was thrown + return false, "Failed: " .. errOrResult + end + + -- errOrResult will be the value + return true, errOrResult +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if not (player and player:is_player()) then + return + end + if formname == "testtools:entity_list" then + local name = player:get_player_name() + if fields.entity_list then + local expl = minetest.explode_textlist_event(fields.entity_list) + if expl.type == "DCL" then + local pos = vector.add(player:get_pos(), {x=0,y=1,z=0}) + selections[name] = expl.index + minetest.add_entity(pos, get_entity_list()[expl.index]) + return + elseif expl.type == "CHG" then + selections[name] = expl.index + return + end + elseif fields.spawn and selections[name] then + local pos = vector.add(player:get_pos(), {x=0,y=1,z=0}) + minetest.add_entity(pos, get_entity_list()[selections[name]]) + return + end + elseif formname == "testtools:object_editor" then + local name = player:get_player_name() + if fields.object_props then + local expl = minetest.explode_textlist_event(fields.object_props) + if expl.type == "DCL" or expl.type == "CHG" then + property_formspec_index[name] = expl.index + + local props = selected_objects[name]:get_properties() + local keys = property_formspec_data[name] + if (not property_formspec_index[name]) or (not props) then + return + end + local key = keys[property_formspec_index[name]] + editor_formspec_selindex[name] = expl.index + editor_formspec(name, selected_objects[name], prop_to_string(props[key]), expl.index) + return + end + end + if fields.submit then + local props = selected_objects[name]:get_properties() + local keys = property_formspec_data[name] + if (not property_formspec_index[name]) or (not props) then + return + end + local key = keys[property_formspec_index[name]] + if not key then + return + end + local success, str = use_loadstring(fields.value, player) + if success then + props[key] = str + else + minetest.chat_send_player(name, str) + return + end + selected_objects[name]:set_properties(props) + local sel = editor_formspec_selindex[name] + editor_formspec(name, selected_objects[name], prop_to_string(props[key]), sel) + return + end + end +end) diff --git a/games/devtest/mods/testtools/mod.conf b/games/devtest/mods/testtools/mod.conf new file mode 100644 index 000000000..cde1b2685 --- /dev/null +++ b/games/devtest/mods/testtools/mod.conf @@ -0,0 +1,2 @@ +name = testtools +description = Some tools to directly manipulate nodes and entities. Great for development and testing diff --git a/games/devtest/mods/testtools/textures/testtools_entity_rotator.png b/games/devtest/mods/testtools/textures/testtools_entity_rotator.png new file mode 100644 index 000000000..17ebb2d35 Binary files /dev/null and b/games/devtest/mods/testtools/textures/testtools_entity_rotator.png differ diff --git a/games/devtest/mods/testtools/textures/testtools_entity_scaler.png b/games/devtest/mods/testtools/textures/testtools_entity_scaler.png new file mode 100644 index 000000000..4909c25b0 Binary files /dev/null and b/games/devtest/mods/testtools/textures/testtools_entity_scaler.png differ diff --git a/games/devtest/mods/testtools/textures/testtools_entity_spawner.png b/games/devtest/mods/testtools/textures/testtools_entity_spawner.png new file mode 100644 index 000000000..6199e0145 Binary files /dev/null and b/games/devtest/mods/testtools/textures/testtools_entity_spawner.png differ diff --git a/games/devtest/mods/testtools/textures/testtools_falling_node_tool.png b/games/devtest/mods/testtools/textures/testtools_falling_node_tool.png new file mode 100644 index 000000000..30099a7ef Binary files /dev/null and b/games/devtest/mods/testtools/textures/testtools_falling_node_tool.png differ diff --git a/games/devtest/mods/testtools/textures/testtools_node_setter.png b/games/devtest/mods/testtools/textures/testtools_node_setter.png new file mode 100644 index 000000000..8599438de Binary files /dev/null and b/games/devtest/mods/testtools/textures/testtools_node_setter.png differ diff --git a/games/devtest/mods/testtools/textures/testtools_object_attacher.png b/games/devtest/mods/testtools/textures/testtools_object_attacher.png new file mode 100644 index 000000000..4d9bf6fd1 Binary files /dev/null and b/games/devtest/mods/testtools/textures/testtools_object_attacher.png differ diff --git a/games/devtest/mods/testtools/textures/testtools_object_editor.png b/games/devtest/mods/testtools/textures/testtools_object_editor.png new file mode 100644 index 000000000..d1ce9cecd Binary files /dev/null and b/games/devtest/mods/testtools/textures/testtools_object_editor.png differ diff --git a/games/devtest/mods/testtools/textures/testtools_object_mover.png b/games/devtest/mods/testtools/textures/testtools_object_mover.png new file mode 100644 index 000000000..8b14e9fb2 Binary files /dev/null and b/games/devtest/mods/testtools/textures/testtools_object_mover.png differ diff --git a/games/devtest/mods/testtools/textures/testtools_param2tool.png b/games/devtest/mods/testtools/textures/testtools_param2tool.png new file mode 100644 index 000000000..dbc663575 Binary files /dev/null and b/games/devtest/mods/testtools/textures/testtools_param2tool.png differ diff --git a/games/devtest/mods/testtools/textures/testtools_remover.png b/games/devtest/mods/testtools/textures/testtools_remover.png new file mode 100644 index 000000000..73f14cd54 Binary files /dev/null and b/games/devtest/mods/testtools/textures/testtools_remover.png differ diff --git a/games/devtest/mods/tiled/init.lua b/games/devtest/mods/tiled/init.lua new file mode 100644 index 000000000..68ead8e3a --- /dev/null +++ b/games/devtest/mods/tiled/init.lua @@ -0,0 +1,33 @@ +minetest.register_node("tiled:tiled", { + description = "Tiled Node (world-aligned)", + tiles = {{ + name = "tiled_tiled.png", + align_style = "world", + scale = 8, + }}, + groups = {cracky=3}, +}) + +minetest.register_node("tiled:tiled_n", { + description = "Tiled Node (node-aligned)", + tiles = {{ + name = "tiled_tiled.png", + align_style = "node", + scale = 8, + }}, + groups = {cracky=3}, +}) + +stairs.register_stair_and_slab("tiled_n", "tiled:tiled", + {cracky=3}, + {{name="tiled_tiled.png", align_style="node", scale=8}}, + "Tiled Stair (node-aligned)", + "Tiled Slab (node-aligned)") + +stairs.register_stair_and_slab("tiled", "tiled:tiled", + {cracky=3}, + {{name="tiled_tiled.png", align_style="world", scale=8}}, + "Tiled Stair (world-aligned)", + "Tiled Slab (world-aligned)") + + diff --git a/games/devtest/mods/tiled/mod.conf b/games/devtest/mods/tiled/mod.conf new file mode 100644 index 000000000..78b19f93b --- /dev/null +++ b/games/devtest/mods/tiled/mod.conf @@ -0,0 +1,3 @@ +name = tiled +description = Add nodes with a special texture that spans multiple nodes (aka "world-aligned") +depends = stairs diff --git a/games/devtest/mods/tiled/textures/tiled_tiled.png b/games/devtest/mods/tiled/textures/tiled_tiled.png new file mode 100644 index 000000000..363a26487 Binary files /dev/null and b/games/devtest/mods/tiled/textures/tiled_tiled.png differ diff --git a/games/devtest/mods/unittests/crafting.lua b/games/devtest/mods/unittests/crafting.lua new file mode 100644 index 000000000..eff13ce09 --- /dev/null +++ b/games/devtest/mods/unittests/crafting.lua @@ -0,0 +1,120 @@ +-- Test minetest.clear_craft function +local function test_clear_craft() + minetest.log("info", "[unittests] Testing minetest.clear_craft") + -- Clearing by output + minetest.register_craft({ + output = "foo", + recipe = {{"bar"}} + }) + minetest.register_craft({ + output = "foo 4", + recipe = {{"foo", "bar"}} + }) + assert(#minetest.get_all_craft_recipes("foo") == 2) + minetest.clear_craft({output="foo"}) + assert(minetest.get_all_craft_recipes("foo") == nil) + -- Clearing by input + minetest.register_craft({ + output = "foo 4", + recipe = {{"foo", "bar"}} + }) + assert(#minetest.get_all_craft_recipes("foo") == 1) + minetest.clear_craft({recipe={{"foo", "bar"}}}) + assert(minetest.get_all_craft_recipes("foo") == nil) +end + +-- Test minetest.get_craft_result function +local function test_get_craft_result() + minetest.log("info", "[unittests] Testing minetest.get_craft_result") + + -- normal + local input = { + method = "normal", + width = 2, + items = {"", "unittests:coal_lump", "", "unittests:stick"} + } + minetest.log("info", "[unittests] torch crafting input: "..dump(input)) + local output, decremented_input = minetest.get_craft_result(input) + minetest.log("info", "[unittests] torch crafting output: "..dump(output)) + minetest.log("info", "[unittests] torch crafting decremented input: "..dump(decremented_input)) + assert(output.item) + minetest.log("info", "[unittests] torch crafting output.item:to_table(): "..dump(output.item:to_table())) + assert(output.item:get_name() == "unittests:torch") + assert(output.item:get_count() == 4) + + -- fuel + input = { + method = "fuel", + width = 1, + items = {"unittests:coal_lump"} + } + minetest.log("info", "[unittests] coal fuel input: "..dump(input)) + output, decremented_input = minetest.get_craft_result(input) + minetest.log("info", "[unittests] coal fuel output: "..dump(output)) + minetest.log("info", "[unittests] coal fuel decremented input: "..dump(decremented_input)) + assert(output.time) + assert(output.time > 0) + + -- cooking + input = { + method = "cooking", + width = 1, + items = {"unittests:iron_lump"} + } + minetest.log("info", "[unittests] iron lump cooking input: "..dump(output)) + output, decremented_input = minetest.get_craft_result(input) + minetest.log("info", "[unittests] iron lump cooking output: "..dump(output)) + minetest.log("info", "[unittests] iron lump cooking decremented input: "..dump(decremented_input)) + assert(output.time) + assert(output.time > 0) + assert(output.item) + minetest.log("info", "[unittests] iron lump cooking output.item:to_table(): "..dump(output.item:to_table())) + assert(output.item:get_name() == "unittests:steel_ingot") + assert(output.item:get_count() == 1) + + -- tool repair (repairable) + input = { + method = "normal", + width = 2, + -- Using a wear of 60000 + items = {"unittests:repairable_tool 1 60000", "unittests:repairable_tool 1 60000"} + } + minetest.log("info", "[unittests] repairable tool crafting input: "..dump(input)) + output, decremented_input = minetest.get_craft_result(input) + minetest.log("info", "[unittests] repairable tool crafting output: "..dump(output)) + minetest.log("info", "[unittests] repairable tool crafting decremented input: "..dump(decremented_input)) + assert(output.item) + minetest.log("info", "[unittests] repairable tool crafting output.item:to_table(): "..dump(output.item:to_table())) + assert(output.item:get_name() == "unittests:repairable_tool") + -- Test the wear value. + -- See src/craftdef.cpp in Minetest source code for the formula. The formula to calculate + -- the value 51187 is: + -- 65536 - ((65536-60000)+(65536-60000)) + floor(additonal_wear * 65536 + 0.5) = 51187 + -- where additional_wear = 0.05 + assert(output.item:get_wear() == 51187) + assert(output.item:get_count() == 1) + + -- failing tool repair (unrepairable) + input = { + method = "normal", + width = 2, + items = {"unittests:unrepairable_tool 1 60000", "unittests:unrepairable_tool 1 60000"} + } + minetest.log("info", "[unittests] unrepairable tool crafting input: "..dump(input)) + output, decremented_input = minetest.get_craft_result(input) + minetest.log("info", "[unittests] unrepairable tool crafting output: "..dump(output)) + minetest.log("info", "[unittests] unrepairable tool crafting decremented input: "..dump(decremented_input)) + assert(output.item) + minetest.log("info", "[unittests] unrepairable tool crafting output.item:to_table(): "..dump(output.item:to_table())) + -- unrepairable tool must not yield any output + assert(output.item:get_name() == "") + +end + +function unittests.test_crafting() + test_clear_craft() + test_get_craft_result() + minetest.log("action", "[unittests] Crafting tests passed!") + return true +end + diff --git a/games/devtest/mods/unittests/crafting_prepare.lua b/games/devtest/mods/unittests/crafting_prepare.lua new file mode 100644 index 000000000..a09734827 --- /dev/null +++ b/games/devtest/mods/unittests/crafting_prepare.lua @@ -0,0 +1,88 @@ +-- Registering some dummy items and recipes for the crafting tests + +minetest.register_craftitem("unittests:torch", { + description = "Crafting Test Item: Torch", + inventory_image = "unittests_torch.png", + + groups = { dummy = 1 }, +}) +minetest.register_craftitem("unittests:coal_lump", { + description = "Crafting Test Item: Coal Lump", + inventory_image = "unittests_coal_lump.png", + + groups = { dummy = 1 }, +}) +minetest.register_craftitem("unittests:stick", { + description = "Crafting Test Item: Stick", + inventory_image = "unittests_stick.png", + + groups = { dummy = 1 }, +}) +minetest.register_craftitem("unittests:iron_lump", { + description = "Crafting Test Item: Iron Lump", + inventory_image = "unittests_iron_lump.png", + + groups = { dummy = 1 }, +}) +minetest.register_craftitem("unittests:steel_ingot", { + description = "Crafting Test Item: Steel Ingot", + inventory_image = "unittests_steel_ingot.png", + + groups = { dummy = 1 }, +}) + +-- Recipes for tests: Normal crafting, cooking and fuel + +minetest.register_craft({ + output = 'unittests:torch 4', + recipe = { + {'unittests:coal_lump'}, + {'unittests:stick'}, + } +}) + +minetest.register_craft({ + type = "cooking", + output = "unittests:steel_ingot", + recipe = "unittests:iron_lump", +}) + +minetest.register_craft({ + type = "fuel", + recipe = "unittests:coal_lump", + burntime = 40, +}) + +-- Test tool repair +minetest.register_craft({ + type = "toolrepair", + additional_wear = -0.05, +}) + +-- Test the disable_repair=1 group +minetest.register_tool("unittests:unrepairable_tool", { + description = "Crafting Test Item: Unrepairable Tool", + inventory_image = "unittests_unrepairable_tool.png", + tool_capabilities = { + groupcaps = { + cracky = { + times = {3, 2, 1}, + } + } + }, + groups = { disable_repair = 1, dummy = 1 } +}) + +minetest.register_tool("unittests:repairable_tool", { + description = "Crafting Test Item: Repairable Tool", + inventory_image = "unittests_repairable_tool.png", + tool_capabilities = { + groupcaps = { + cracky = { + times = {3, 2, 1}, + } + } + }, + + groups = { dummy = 1 }, +}) diff --git a/games/devtest/mods/unittests/init.lua b/games/devtest/mods/unittests/init.lua new file mode 100644 index 000000000..6c1728420 --- /dev/null +++ b/games/devtest/mods/unittests/init.lua @@ -0,0 +1,16 @@ +unittests = {} + +local modpath = minetest.get_modpath("unittests") +dofile(modpath .. "/random.lua") +dofile(modpath .. "/player.lua") +dofile(modpath .. "/crafting_prepare.lua") +dofile(modpath .. "/crafting.lua") + +if minetest.settings:get_bool("devtest_unittests_autostart", false) then + unittests.test_random() + unittests.test_crafting() + minetest.register_on_joinplayer(function(player) + unittests.test_player(player) + end) +end + diff --git a/games/devtest/mods/unittests/mod.conf b/games/devtest/mods/unittests/mod.conf new file mode 100644 index 000000000..0d5e3c959 --- /dev/null +++ b/games/devtest/mods/unittests/mod.conf @@ -0,0 +1,2 @@ +name = unittests +description = Adds automated unit tests for the engine diff --git a/games/devtest/mods/unittests/player.lua b/games/devtest/mods/unittests/player.lua new file mode 100644 index 000000000..10781a95f --- /dev/null +++ b/games/devtest/mods/unittests/player.lua @@ -0,0 +1,73 @@ +-- +-- HP Change Reasons +-- +local expect = nil +local function run_hpchangereason_tests(player) + expect = { type = "set_hp", from = "mod" } + player:set_hp(3) + assert(expect == nil) + + expect = { a = 234, type = "set_hp", from = "mod" } + player:set_hp(7, { a= 234 }) + assert(expect == nil) + + expect = { df = 3458973454, type = "fall", from = "mod" } + player:set_hp(10, { type = "fall", df = 3458973454 }) + assert(expect == nil) + + player:set_hp(20) +end + +local function run_player_meta_tests(player) + local meta = player:get_meta() + meta:set_string("foo", "bar") + assert(meta:contains("foo")) + assert(meta:get_string("foo") == "bar") + assert(meta:get("foo") == "bar") + + local meta2 = player:get_meta() + assert(meta2:get_string("foo") == "bar") + assert(meta2:get("foo") == "bar") + assert(meta:equals(meta2)) + + meta:set_string("bob", "dillan") + assert(meta:get_string("foo") == "bar") + assert(meta:get_string("bob") == "dillan") + assert(meta:get("bob") == "dillan") + assert(meta2:get_string("foo") == "bar") + assert(meta2:get_string("bob") == "dillan") + assert(meta2:get("bob") == "dillan") + assert(meta:equals(meta2)) + + meta:set_string("foo", "") + assert(not meta:contains("foo")) + assert(meta:get("foo") == nil) + assert(meta:get_string("foo") == "") + assert(meta:equals(meta2)) +end + +function unittests.test_player(player) + minetest.register_on_player_hpchange(function(player, hp, reason) + if not expect then + return + end + + for key, value in pairs(reason) do + assert(expect[key] == value) + end + + for key, value in pairs(expect) do + assert(reason[key] == value) + end + + expect = nil + end) + + run_hpchangereason_tests(player) + run_player_meta_tests(player) + local msg = "Player tests passed for player '"..player:get_player_name().."'!" + minetest.chat_send_all(msg) + minetest.log("action", "[unittests] "..msg) + return true +end + diff --git a/games/devtest/mods/unittests/random.lua b/games/devtest/mods/unittests/random.lua new file mode 100644 index 000000000..f94f0a88e --- /dev/null +++ b/games/devtest/mods/unittests/random.lua @@ -0,0 +1,10 @@ +function unittests.test_random() + -- Try out PseudoRandom + minetest.log("action", "[unittests] Testing PseudoRandom ...") + local pseudo = PseudoRandom(13) + assert(pseudo:next() == 22290) + assert(pseudo:next() == 13854) + minetest.log("action", "[unittests] PseudoRandom test passed!") + return true +end + diff --git a/games/devtest/mods/unittests/textures/unittests_coal_lump.png b/games/devtest/mods/unittests/textures/unittests_coal_lump.png new file mode 100644 index 000000000..f460d909e Binary files /dev/null and b/games/devtest/mods/unittests/textures/unittests_coal_lump.png differ diff --git a/games/devtest/mods/unittests/textures/unittests_iron_lump.png b/games/devtest/mods/unittests/textures/unittests_iron_lump.png new file mode 100644 index 000000000..22f43e9cc Binary files /dev/null and b/games/devtest/mods/unittests/textures/unittests_iron_lump.png differ diff --git a/games/devtest/mods/unittests/textures/unittests_repairable_tool.png b/games/devtest/mods/unittests/textures/unittests_repairable_tool.png new file mode 100644 index 000000000..46fbbaa74 Binary files /dev/null and b/games/devtest/mods/unittests/textures/unittests_repairable_tool.png differ diff --git a/games/devtest/mods/unittests/textures/unittests_steel_ingot.png b/games/devtest/mods/unittests/textures/unittests_steel_ingot.png new file mode 100644 index 000000000..6977696a2 Binary files /dev/null and b/games/devtest/mods/unittests/textures/unittests_steel_ingot.png differ diff --git a/games/devtest/mods/unittests/textures/unittests_stick.png b/games/devtest/mods/unittests/textures/unittests_stick.png new file mode 100644 index 000000000..ffdce70d4 Binary files /dev/null and b/games/devtest/mods/unittests/textures/unittests_stick.png differ diff --git a/games/devtest/mods/unittests/textures/unittests_torch.png b/games/devtest/mods/unittests/textures/unittests_torch.png new file mode 100644 index 000000000..ba5eebef0 Binary files /dev/null and b/games/devtest/mods/unittests/textures/unittests_torch.png differ diff --git a/games/devtest/mods/unittests/textures/unittests_unrepairable_tool.png b/games/devtest/mods/unittests/textures/unittests_unrepairable_tool.png new file mode 100644 index 000000000..c676213a5 Binary files /dev/null and b/games/devtest/mods/unittests/textures/unittests_unrepairable_tool.png differ diff --git a/games/devtest/mods/util_commands/init.lua b/games/devtest/mods/util_commands/init.lua new file mode 100644 index 000000000..ad8d3f9ba --- /dev/null +++ b/games/devtest/mods/util_commands/init.lua @@ -0,0 +1,137 @@ +minetest.register_chatcommand("hotbar", { + params = "", + description = "Set hotbar size", + func = function(name, param) + local player = minetest.get_player_by_name(name) + if not player then + return false, "No player." + end + local size = tonumber(param) + if not size then + return false, "Missing or incorrect size parameter!" + end + local ok = player:hud_set_hotbar_itemcount(size) + if ok then + return true + else + return false, "Invalid item count!" + end + end, +}) + +minetest.register_chatcommand("hp", { + params = "", + description = "Set your health", + func = function(name, param) + local player = minetest.get_player_by_name(name) + if not player then + return false, "No player." + end + local hp = tonumber(param) + if not hp then + return false, "Missing or incorrect hp parameter!" + end + player:set_hp(hp) + return true + end, +}) + +minetest.register_chatcommand("zoom", { + params = "[]", + description = "Set or display your zoom_fov", + func = function(name, param) + local player = minetest.get_player_by_name(name) + if not player then + return false, "No player." + end + if param == "" then + local fov = player:get_properties().zoom_fov + return true, "zoom_fov = "..tostring(fov) + end + local fov = tonumber(param) + if not fov then + return false, "Missing or incorrect zoom_fov parameter!" + end + player:set_properties({zoom_fov = fov}) + fov = player:get_properties().zoom_fov + return true, "zoom_fov = "..tostring(fov) + end, +}) + + + +local s_infplace = minetest.settings:get("devtest_infplace") +if s_infplace == "true" then + infplace = true +elseif s_infplace == "false" then + infplace = false +else + infplace = minetest.settings:get_bool("creative_mode", false) +end + +minetest.register_chatcommand("infplace", { + params = "", + description = "Toggle infinite node placement", + func = function(name, param) + infplace = not infplace + if infplace then + minetest.chat_send_all("Infinite node placement enabled!") + minetest.log("action", "Infinite node placement enabled") + else + minetest.chat_send_all("Infinite node placement disabled!") + minetest.log("action", "Infinite node placement disabled") + end + return true + end, +}) + +minetest.register_chatcommand("detach", { + params = "[]", + description = "Detach all objects nearby", + func = function(name, param) + local radius = tonumber(param) + if type(radius) ~= "number" then + radius = 8 + end + if radius < 1 then + radius = 1 + end + local player = minetest.get_player_by_name(name) + if not player then + return false, "No player." + end + local objs = minetest.get_objects_inside_radius(player:get_pos(), radius) + local num = 0 + for o=1, #objs do + if objs[o]:get_attach() then + objs[o]:set_detach() + num = num + 1 + end + end + return true, string.format("%d object(s) detached.", num) + end, +}) + + +-- Unlimited node placement +minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) + if placer and placer:is_player() then + return infplace + end +end) + +-- Don't pick up if the item is already in the inventory +local old_handle_node_drops = minetest.handle_node_drops +function minetest.handle_node_drops(pos, drops, digger) + if not digger or not digger:is_player() or not infplace then + return old_handle_node_drops(pos, drops, digger) + end + local inv = digger:get_inventory() + if inv then + for _, item in ipairs(drops) do + if not inv:contains_item("main", item, true) then + inv:add_item("main", item) + end + end + end +end diff --git a/games/devtest/mods/util_commands/mod.conf b/games/devtest/mods/util_commands/mod.conf new file mode 100644 index 000000000..fea6dd3e9 --- /dev/null +++ b/games/devtest/mods/util_commands/mod.conf @@ -0,0 +1,2 @@ +name = util_commands +description = Random server commands to make testing easier and more convenient diff --git a/games/devtest/screenshot.png b/games/devtest/screenshot.png new file mode 100644 index 000000000..7324883f6 Binary files /dev/null and b/games/devtest/screenshot.png differ diff --git a/games/devtest/settingtypes.txt b/games/devtest/settingtypes.txt new file mode 100644 index 000000000..40ee5845b --- /dev/null +++ b/games/devtest/settingtypes.txt @@ -0,0 +1,37 @@ +# If enabled, nodes won't be used up when placed. +# Note: This behavior can also be toggled in-game with the /infplace command. +# +# - true: enabled +# - false: disabled +# - auto: only enabled when Creative Mode is enabled (default) +devtest_infplace (Infinite node placement) enum auto true,false,auto + +# If enabled, new players receive some initial items when joining for the first time. +give_initial_stuff (Give initial stuff) bool true + +# If enabled, automated tests of the Lua API such as player health, crafting and PseudoRandom will be performed on startup. +devtest_unittests_autostart (Perform unit tests) bool false + +# If enabled, the game will use all mapgen aliases for the v6 mapgen. +# If disabled, it will only use a minimal set of mapgen aliases. +# If enabled, there should be biome-specific tree, leaves and ground nodes. If disabled, stuff should use fallback nodes (like stone instead of desert stone). +# +# Many mapgen aliases have fallback values when no value is provided. Having this setting disabled can be useful to test whether those fallback values are functional. +devtest_v6_mapgen_aliases (Use all v6 mapgen aliases) bool false + +# If enabled, the game will use dungeon stairs by enabling the corresponding mapgen aliases. +# +# Disabling this setting can be useful to test whether dungeons still work when stairs are not defined. +devtest_dungeon_stairs (Generate dungeon stairs) bool false + +# If enabled, the mapgen alias 'mapgen_mossycobble' will be used. This should enable random mossy cobblestone in dungeons. +# If disabled, it won't be used. The engine should fall back to cobble instead. +devtest_dungeon_mossycobble (Generate mossy cobblestone) bool false + +# If enabled, some very basic biomes will be registered. +devtest_register_biomes (Register biomes) bool true + +# If set to true, will show an inventory image for nodes that have no inventory image as of Minetest 5.1.0. +# This is due to . +# This is only added to make the items more visible to avoid confusion, but you will no longer see the default inventory images for these items. When you want to test the default inventory image of drawtypes, this should be turned off. +testnodes_show_fallback_image (Use fallback inventory images) bool false diff --git a/games/minimal/LICENSE.txt b/games/minimal/LICENSE.txt deleted file mode 100644 index 108c66abf..000000000 --- a/games/minimal/LICENSE.txt +++ /dev/null @@ -1,4 +0,0 @@ -License information for Developer Test --------------------------------------- - -The same license as for Minetest applies. diff --git a/games/minimal/README.md b/games/minimal/README.md deleted file mode 100644 index a94530498..000000000 --- a/games/minimal/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# Minimal development test - -This is a basic testing environment that contains a bunch of things to test the engine, but it could also be used as a minimal testbed for testing out mods. - -## Features - -* Basic nodes for mapgen -* Basic, minimal map generator -* Lots of example nodes for testing drawtypes, param2, light level, and many other node properties -* Example entities -* Other example items -* Formspec test (via `/test_formspec` command) -* Automated unit tests (disabled by default) -* Tools for manipulating nodes and entities, like the "Param2 Tool" - -## Getting started - -Basically, just create a world and start. A few important things to note: - -* Items are gotten from the “Chest of Everything” (`chest_of_everything:chest`) -* When you lost your initial items, type in `/stuff` command to get them back -* By default, Creative Mode activates infinite node placement. This behavior can be changed with the `devtest_infplace` setting -* Use the `/infplace` command to toggle infinite node placement in-game -* Use the Param2 Tool to change the param2 of nodes; it's useful to experiment with the various drawtype test nodes -* Check out the game settings and server commands for additional tests and features -* Creative Mode does nothing (apart from default engine behavior) - -Confused by a certain node or item? Check out for inline code comments. - -### Example tests - -* You can use this to test what happens if a player is simultaneously in 2 nodes with `damage_per_second` but with a different value. -* Or use the Falling Node Tool on various test nodes to see how they behave when falling. -* You could also use this as a testbed for dependency-free mods, e.g. to test out how your formspecs behave without theming. - -## Random notes - -* Experimental/strange/unstructured tests can be found in the `experimental` mod -* Textures of drawtype test nodes have a red dot at the top left corner. This is to see whether the textures are oriented properly - -## Design philosophy - -This should loosely follow the following principles: - -* Engine testing: The main focus of this is to aid testing of *engine* features, such as mapgen or node drawtypes -* Mod testing: The secondary focus is to help modders as well, either as a minimal testbed for mods or even as a code example -* Minimal interference: Under default settings, it shall not interfere with APIs except on explicit user wish. Non-trivial tests and features need to be enabled by a setting first -* Convenience: Have various tools to make usage easier and more convenient -* Reproducing engine bugs: When an engine bug was found, consider creating a test case -* Clarity: Textures and names need to be designed to keep different things clearly visually apart at a glance -* Low loading time: It must load blazing-fast so stuff can be tested quickly - diff --git a/games/minimal/game.conf b/games/minimal/game.conf deleted file mode 100644 index ae76cf7ad..000000000 --- a/games/minimal/game.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = Minimal development test -description = Testing environment to help with testing the engine features of Minetest. It can also be helpful in mod development. diff --git a/games/minimal/menu/background.png b/games/minimal/menu/background.png deleted file mode 100644 index 415bb3d14..000000000 Binary files a/games/minimal/menu/background.png and /dev/null differ diff --git a/games/minimal/menu/header.png b/games/minimal/menu/header.png deleted file mode 100644 index db864d6b7..000000000 Binary files a/games/minimal/menu/header.png and /dev/null differ diff --git a/games/minimal/menu/icon.png b/games/minimal/menu/icon.png deleted file mode 100644 index f854b9c31..000000000 Binary files a/games/minimal/menu/icon.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/init.lua b/games/minimal/mods/basenodes/init.lua deleted file mode 100644 index 8156c4bec..000000000 --- a/games/minimal/mods/basenodes/init.lua +++ /dev/null @@ -1,334 +0,0 @@ -local WATER_ALPHA = 160 -local WATER_VISC = 1 -local LAVA_VISC = 7 - --- --- Node definitions --- - --- Register nodes - -minetest.register_node("basenodes:stone", { - description = "Stone", - tiles = {"default_stone.png"}, - groups = {cracky=3}, -}) - -minetest.register_node("basenodes:desert_stone", { - description = "Desert Stone", - tiles = {"default_desert_stone.png"}, - groups = {cracky=3}, -}) - -minetest.register_node("basenodes:dirt_with_grass", { - description = "Dirt with Grass", - tiles ={"default_grass.png", - -- a little dot on the bottom to distinguish it from dirt - "default_dirt.png^basenodes_dirt_with_grass_bottom.png", - {name = "default_dirt.png^default_grass_side.png", - tileable_vertical = false}}, - groups = {crumbly=3, soil=1}, -}) - -minetest.register_node("basenodes:dirt_with_snow", { - description = "Dirt with Snow", - tiles ={"basenodes_dirt_with_snow.png", - -- a little dot on the bottom to distinguish it from dirt - "default_dirt.png^basenodes_dirt_with_snow_bottom.png", - {name = "default_dirt.png^default_snow_side.png", - tileable_vertical = false}}, - groups = {crumbly=3, soil=1}, -}) - -minetest.register_node("basenodes:dirt", { - description = "Dirt", - tiles ={"default_dirt.png"}, - groups = {crumbly=3, soil=1}, -}) - -minetest.register_node("basenodes:sand", { - description = "Sand", - tiles ={"default_sand.png"}, - groups = {crumbly=3}, -}) - -minetest.register_node("basenodes:desert_sand", { - description = "Desert Sand", - tiles ={"default_desert_sand.png"}, - groups = {crumbly=3}, -}) - -minetest.register_node("basenodes:gravel", { - description = "Gravel", - tiles ={"default_gravel.png"}, - groups = {crumbly=2}, -}) - -minetest.register_node("basenodes:junglegrass", { - description = "Jungle Grass", - drawtype = "plantlike", - tiles ={"default_junglegrass.png"}, - inventory_image = "default_junglegrass.png", - wield_image = "default_junglegrass.png", - paramtype = "light", - walkable = false, - groups = {snappy=3}, -}) - -minetest.register_node("basenodes:tree", { - description = "Normal Tree Trunk", - tiles = {"default_tree_top.png", "default_tree_top.png", "default_tree.png"}, - is_ground_content = false, - groups = {choppy=2,oddly_breakable_by_hand=1}, -}) - -minetest.register_node("basenodes:leaves", { - description = "Normal Leaves", - drawtype = "allfaces_optional", - tiles = {"default_leaves.png"}, - paramtype = "light", - is_ground_content = false, - groups = {snappy=3}, -}) - -minetest.register_node("basenodes:jungletree", { - description = "Jungle Tree Trunk", - tiles = {"default_jungletree_top.png", "default_jungletree_top.png", "default_jungletree.png"}, - is_ground_content = false, - groups = {choppy=2,oddly_breakable_by_hand=1}, -}) - -minetest.register_node("basenodes:jungleleaves", { - description = "Jungle Leaves", - drawtype = "allfaces_optional", - tiles = {"default_jungleleaves.png"}, - paramtype = "light", - is_ground_content = false, - groups = {snappy=3}, -}) - -minetest.register_node("basenodes:pine_tree", { - description = "Pine Tree Trunk", - tiles = {"default_pine_tree_top.png", "default_pine_tree_top.png", "default_pine_tree.png"}, - is_ground_content = false, - groups = {choppy=2,oddly_breakable_by_hand=1}, -}) - -minetest.register_node("basenodes:pine_needles", { - description = "Pine Needles", - drawtype = "allfaces_optional", - tiles = {"default_pine_needles.png"}, - paramtype = "light", - is_ground_content = false, - groups = {snappy=3}, -}) - -minetest.register_node("basenodes:water_source", { - description = "Water Source", - drawtype = "liquid", - tiles = {"default_water.png"}, - special_tiles = { - {name = "default_water.png", backface_culling = false}, - {name = "default_water.png", backface_culling = true}, - }, - alpha = WATER_ALPHA, - paramtype = "light", - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, - is_ground_content = false, - drowning = 1, - liquidtype = "source", - liquid_alternative_flowing = "basenodes:water_flowing", - liquid_alternative_source = "basenodes:water_source", - liquid_viscosity = WATER_VISC, - post_effect_color = {a = 64, r = 100, g = 100, b = 200}, - groups = {water = 3, liquid = 3}, -}) - -minetest.register_node("basenodes:water_flowing", { - description = "Flowing Water", - drawtype = "flowingliquid", - tiles = {"default_water_flowing.png"}, - special_tiles = { - {name = "default_water_flowing.png", backface_culling = false}, - {name = "default_water_flowing.png", backface_culling = false}, - }, - alpha = WATER_ALPHA, - paramtype = "light", - paramtype2 = "flowingliquid", - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, - is_ground_content = false, - drowning = 1, - liquidtype = "flowing", - liquid_alternative_flowing = "basenodes:water_flowing", - liquid_alternative_source = "basenodes:water_source", - liquid_viscosity = WATER_VISC, - post_effect_color = {a = 64, r = 100, g = 100, b = 200}, - groups = {water = 3, liquid = 3}, -}) - -minetest.register_node("basenodes:river_water_source", { - description = "River Water Source", - drawtype = "liquid", - tiles = { "default_river_water.png" }, - special_tiles = { - {name = "default_river_water.png", backface_culling = false}, - {name = "default_river_water.png", backface_culling = true}, - }, - alpha = WATER_ALPHA, - paramtype = "light", - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, - is_ground_content = false, - drowning = 1, - liquidtype = "source", - liquid_alternative_flowing = "basenodes:river_water_flowing", - liquid_alternative_source = "basenodes:river_water_source", - liquid_viscosity = 1, - liquid_renewable = false, - liquid_range = 2, - post_effect_color = {a = 103, r = 30, g = 76, b = 90}, - groups = {water = 3, liquid = 3, }, -}) - -minetest.register_node("basenodes:river_water_flowing", { - description = "Flowing River Water", - drawtype = "flowingliquid", - tiles = {"default_river_water_flowing.png"}, - special_tiles = { - {name = "default_river_water_flowing.png", backface_culling = false}, - {name = "default_river_water_flowing.png", backface_culling = false}, - }, - alpha = WATER_ALPHA, - paramtype = "light", - paramtype2 = "flowingliquid", - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, - is_ground_content = false, - drowning = 1, - liquidtype = "flowing", - liquid_alternative_flowing = "basenodes:river_water_flowing", - liquid_alternative_source = "basenodes:river_water_source", - liquid_viscosity = 1, - liquid_renewable = false, - liquid_range = 2, - post_effect_color = {a = 103, r = 30, g = 76, b = 90}, - groups = {water = 3, liquid = 3, }, -}) - -minetest.register_node("basenodes:lava_flowing", { - description = "Flowing Lava", - drawtype = "flowingliquid", - tiles = {"default_lava_flowing.png"}, - special_tiles = { - {name="default_lava_flowing.png", backface_culling = false}, - {name="default_lava_flowing.png", backface_culling = false}, - }, - paramtype = "light", - light_source = minetest.LIGHT_MAX, - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, - is_ground_content = false, - drowning = 1, - damage_per_second = 4, - liquidtype = "flowing", - liquid_alternative_flowing = "basenodes:lava_flowing", - liquid_alternative_source = "basenodes:lava_source", - liquid_viscosity = LAVA_VISC, - post_effect_color = {a=192, r=255, g=64, b=0}, - groups = {lava=3, liquid=1}, -}) - -minetest.register_node("basenodes:lava_source", { - description = "Lava Source", - drawtype = "liquid", - tiles = { "default_lava.png" }, - special_tiles = { - {name = "default_lava.png", backface_culling = false}, - {name = "default_lava.png", backface_culling = true}, - }, - paramtype = "light", - light_source = minetest.LIGHT_MAX, - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, - is_ground_content = false, - drowning = 1, - damage_per_second = 4, - liquidtype = "source", - liquid_alternative_flowing = "basenodes:lava_flowing", - liquid_alternative_source = "basenodes:lava_source", - liquid_viscosity = LAVA_VISC, - post_effect_color = {a=192, r=255, g=64, b=0}, - groups = {lava=3, liquid=1}, -}) - -minetest.register_node("basenodes:cobble", { - description = "Cobblestone", - tiles ={"default_cobble.png"}, - is_ground_content = false, - groups = {cracky=3}, -}) - -minetest.register_node("basenodes:mossycobble", { - description = "Mossy Cobblestone", - tiles ={"default_mossycobble.png"}, - is_ground_content = false, - groups = {cracky=3}, -}) - -minetest.register_node("basenodes:apple", { - description = "Apple", - drawtype = "plantlike", - tiles ={"default_apple.png"}, - inventory_image = "default_apple.png", - paramtype = "light", - is_ground_content = false, - sunlight_propagates = true, - walkable = false, - groups = {dig_immediate=3}, - - -- Make eatable because why not? - on_use = minetest.item_eat(2), -}) - -minetest.register_node("basenodes:ice", { - description = "Ice", - tiles ={"default_ice.png"}, - groups = {cracky=3}, -}) - --- The snow nodes intentionally have different tints to make them more --- distinguishable -minetest.register_node("basenodes:snow", { - description = "Snow Sheet", - tiles = {"basenodes_snow_sheet.png"}, - groups = {crumbly=3}, - walkable = false, - paramtype = "light", - drawtype = "nodebox", - node_box = { - type = "fixed", - fixed = {-0.5, -0.5, -0.5, 0.5, -0.25, 0.5}, - }, -}) - -minetest.register_node("basenodes:snowblock", { - description = "Snow Block", - tiles ={"default_snow.png"}, - groups = {crumbly=3}, -}) - - diff --git a/games/minimal/mods/basenodes/mod.conf b/games/minimal/mods/basenodes/mod.conf deleted file mode 100644 index 25024dc63..000000000 --- a/games/minimal/mods/basenodes/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = basenodes -description = Contains basic nodes for mapgen diff --git a/games/minimal/mods/basenodes/textures/basenodes_dirt_with_grass_bottom.png b/games/minimal/mods/basenodes/textures/basenodes_dirt_with_grass_bottom.png deleted file mode 100644 index 5e8fc41a9..000000000 Binary files a/games/minimal/mods/basenodes/textures/basenodes_dirt_with_grass_bottom.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/basenodes_dirt_with_snow.png b/games/minimal/mods/basenodes/textures/basenodes_dirt_with_snow.png deleted file mode 100644 index 7ea2d8d31..000000000 Binary files a/games/minimal/mods/basenodes/textures/basenodes_dirt_with_snow.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/basenodes_dirt_with_snow_bottom.png b/games/minimal/mods/basenodes/textures/basenodes_dirt_with_snow_bottom.png deleted file mode 100644 index 447c94e98..000000000 Binary files a/games/minimal/mods/basenodes/textures/basenodes_dirt_with_snow_bottom.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/basenodes_snow_sheet.png b/games/minimal/mods/basenodes/textures/basenodes_snow_sheet.png deleted file mode 100644 index 455332093..000000000 Binary files a/games/minimal/mods/basenodes/textures/basenodes_snow_sheet.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_apple.png b/games/minimal/mods/basenodes/textures/default_apple.png deleted file mode 100644 index 9c115dae4..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_apple.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_cobble.png b/games/minimal/mods/basenodes/textures/default_cobble.png deleted file mode 100644 index 5b859e9c2..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_cobble.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_desert_sand.png b/games/minimal/mods/basenodes/textures/default_desert_sand.png deleted file mode 100644 index 19ec87dc0..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_desert_sand.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_desert_stone.png b/games/minimal/mods/basenodes/textures/default_desert_stone.png deleted file mode 100644 index 5126fb61c..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_desert_stone.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_dirt.png b/games/minimal/mods/basenodes/textures/default_dirt.png deleted file mode 100644 index 58670305d..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_dirt.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_grass.png b/games/minimal/mods/basenodes/textures/default_grass.png deleted file mode 100644 index 3d6397186..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_grass.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_grass_side.png b/games/minimal/mods/basenodes/textures/default_grass_side.png deleted file mode 100644 index 04770b6f6..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_grass_side.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_gravel.png b/games/minimal/mods/basenodes/textures/default_gravel.png deleted file mode 100644 index 7e5ff616f..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_gravel.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_ice.png b/games/minimal/mods/basenodes/textures/default_ice.png deleted file mode 100644 index c4bddd223..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_ice.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_junglegrass.png b/games/minimal/mods/basenodes/textures/default_junglegrass.png deleted file mode 100644 index d64e33abc..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_junglegrass.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_jungleleaves.png b/games/minimal/mods/basenodes/textures/default_jungleleaves.png deleted file mode 100644 index 1fa67e83a..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_jungleleaves.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_jungletree.png b/games/minimal/mods/basenodes/textures/default_jungletree.png deleted file mode 100644 index 053850fa7..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_jungletree.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_jungletree_top.png b/games/minimal/mods/basenodes/textures/default_jungletree_top.png deleted file mode 100644 index e80de8a69..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_jungletree_top.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_lava.png b/games/minimal/mods/basenodes/textures/default_lava.png deleted file mode 100644 index a4cf649f1..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_lava.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_lava_flowing.png b/games/minimal/mods/basenodes/textures/default_lava_flowing.png deleted file mode 100644 index 07066a6e3..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_lava_flowing.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_leaves.png b/games/minimal/mods/basenodes/textures/default_leaves.png deleted file mode 100644 index c0475d4d2..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_leaves.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_mossycobble.png b/games/minimal/mods/basenodes/textures/default_mossycobble.png deleted file mode 100644 index 69585e37b..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_mossycobble.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_pine_needles.png b/games/minimal/mods/basenodes/textures/default_pine_needles.png deleted file mode 100644 index 137caa2a3..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_pine_needles.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_pine_tree.png b/games/minimal/mods/basenodes/textures/default_pine_tree.png deleted file mode 100644 index 5743183c0..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_pine_tree.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_pine_tree_top.png b/games/minimal/mods/basenodes/textures/default_pine_tree_top.png deleted file mode 100644 index cc18f3462..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_pine_tree_top.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_river_water.png b/games/minimal/mods/basenodes/textures/default_river_water.png deleted file mode 100644 index e1074d2ef..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_river_water.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_river_water_flowing.png b/games/minimal/mods/basenodes/textures/default_river_water_flowing.png deleted file mode 100644 index 4a756b2bd..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_river_water_flowing.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_sand.png b/games/minimal/mods/basenodes/textures/default_sand.png deleted file mode 100644 index 0ed0e4ceb..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_sand.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_snow.png b/games/minimal/mods/basenodes/textures/default_snow.png deleted file mode 100644 index c42e0eecb..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_snow.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_snow_side.png b/games/minimal/mods/basenodes/textures/default_snow_side.png deleted file mode 100644 index f34d10991..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_snow_side.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_stone.png b/games/minimal/mods/basenodes/textures/default_stone.png deleted file mode 100644 index 763b4396a..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_stone.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_tree.png b/games/minimal/mods/basenodes/textures/default_tree.png deleted file mode 100644 index 189ec1593..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_tree.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_tree_top.png b/games/minimal/mods/basenodes/textures/default_tree_top.png deleted file mode 100644 index d1a4fa704..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_tree_top.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_water.png b/games/minimal/mods/basenodes/textures/default_water.png deleted file mode 100644 index 3e385ae8b..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_water.png and /dev/null differ diff --git a/games/minimal/mods/basenodes/textures/default_water_flowing.png b/games/minimal/mods/basenodes/textures/default_water_flowing.png deleted file mode 100644 index 7cdafd51d..000000000 Binary files a/games/minimal/mods/basenodes/textures/default_water_flowing.png and /dev/null differ diff --git a/games/minimal/mods/basetools/init.lua b/games/minimal/mods/basetools/init.lua deleted file mode 100644 index d9d9afb07..000000000 --- a/games/minimal/mods/basetools/init.lua +++ /dev/null @@ -1,295 +0,0 @@ --- --- Tool definitions --- - ---[[ TOOLS SUMMARY: - -Tool types: - -* Hand: basic tool/weapon (just for convenience, not optimized for testing) -* Pickaxe: dig cracky -* Axe: dig choppy -* Shovel: dig crumbly -* Shears: dig snappy -* Sword: deal damage -* Dagger: deal damage, but faster - -Tool materials: - -* Dirt: dig nodes of rating 3, one use only -* Wood: dig nodes of rating 3 -* Stone: dig nodes of rating 3 or 2 -* Steel: dig nodes of rating 3, 2 or 1 -* Mese: dig "everything" instantly -]] - --- The hand -minetest.register_item(":", { - type = "none", - wield_image = "wieldhand.png", - wield_scale = {x=1,y=1,z=2.5}, - tool_capabilities = { - full_punch_interval = 1.0, - max_drop_level = 0, - groupcaps = { - crumbly = {times={[3]=1.50}, uses=0, maxlevel=0}, - snappy = {times={[3]=1.50}, uses=0, maxlevel=0}, - oddly_breakable_by_hand = {times={[1]=7.00,[2]=4.00,[3]=2.00}, uses=0, maxlevel=0}, - }, - damage_groups = {fleshy=1}, - } -}) - --- Mese Pickaxe: special tool that digs "everything" instantly -minetest.register_tool("basetools:pick_mese", { - description = "Mese Pickaxe", - inventory_image = "basetools_mesepick.png", - tool_capabilities = { - full_punch_interval = 1.0, - max_drop_level=3, - groupcaps={ - cracky={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255}, - crumbly={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255}, - snappy={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255}, - choppy={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255}, - dig_immediate={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255}, - }, - }, -}) - - --- --- Pickaxes: Dig cracky --- - --- This should break after only 1 use -minetest.register_tool("basetools:pick_dirt", { - description = "Dirt Pickaxe", - inventory_image = "basetools_dirtpick.png", - tool_capabilities = { - max_drop_level=0, - groupcaps={ - cracky={times={[3]=2.00}, uses=1, maxlevel=0} - }, - }, -}) - -minetest.register_tool("basetools:pick_wood", { - description = "Wooden Pickaxe", - inventory_image = "basetools_woodpick.png", - tool_capabilities = { - max_drop_level=0, - groupcaps={ - cracky={times={[3]=2.00}, uses=30, maxlevel=0} - }, - }, -}) -minetest.register_tool("basetools:pick_stone", { - description = "Stone Pickaxe", - inventory_image = "basetools_stonepick.png", - tool_capabilities = { - max_drop_level=0, - groupcaps={ - cracky={times={[2]=1.20, [3]=0.80}, uses=60, maxlevel=0} - }, - }, -}) -minetest.register_tool("basetools:pick_steel", { - description = "Steel Pickaxe", - inventory_image = "basetools_steelpick.png", - tool_capabilities = { - max_drop_level=1, - groupcaps={ - cracky={times={[1]=4.00, [2]=1.60, [3]=1.00}, uses=90, maxlevel=0} - }, - }, -}) -minetest.register_tool("basetools:pick_steel_l1", { - description = "Steel Pickaxe Level 1", - inventory_image = "basetools_steelpick_l1.png", - tool_capabilities = { - max_drop_level=1, - groupcaps={ - cracky={times={[1]=4.00, [2]=1.60, [3]=1.00}, uses=90, maxlevel=1} - }, - }, -}) -minetest.register_tool("basetools:pick_steel_l2", { - description = "Steel Pickaxe Level 2", - inventory_image = "basetools_steelpick_l2.png", - tool_capabilities = { - max_drop_level=1, - groupcaps={ - cracky={times={[1]=4.00, [2]=1.60, [3]=1.00}, uses=90, maxlevel=2} - }, - }, -}) - --- --- Shovels (dig crumbly) --- - -minetest.register_tool("basetools:shovel_wood", { - description = "Wooden Shovel", - inventory_image = "basetools_woodshovel.png", - tool_capabilities = { - max_drop_level=0, - groupcaps={ - crumbly={times={[3]=0.50}, uses=30, maxlevel=0} - }, - }, -}) -minetest.register_tool("basetools:shovel_stone", { - description = "Stone Shovel", - inventory_image = "basetools_stoneshovel.png", - tool_capabilities = { - max_drop_level=0, - groupcaps={ - crumbly={times={[2]=0.50, [3]=0.30}, uses=60, maxlevel=0} - }, - }, -}) -minetest.register_tool("basetools:shovel_steel", { - description = "Steel Shovel", - inventory_image = "basetools_steelshovel.png", - tool_capabilities = { - max_drop_level=1, - groupcaps={ - crumbly={times={[1]=1.00, [2]=0.70, [3]=0.60}, uses=90, maxlevel=0} - }, - }, -}) - --- --- Axes (dig choppy) --- - -minetest.register_tool("basetools:axe_wood", { - description = "Wooden Axe", - inventory_image = "basetools_woodaxe.png", - tool_capabilities = { - max_drop_level=0, - groupcaps={ - choppy={times={[3]=0.80}, uses=30, maxlevel=0}, - }, - }, -}) -minetest.register_tool("basetools:axe_stone", { - description = "Stone Axe", - inventory_image = "basetools_stoneaxe.png", - tool_capabilities = { - max_drop_level=0, - groupcaps={ - choppy={times={[2]=1.00, [3]=0.60}, uses=60, maxlevel=0}, - }, - }, -}) -minetest.register_tool("basetools:axe_steel", { - description = "Steel Axe", - inventory_image = "basetools_steelaxe.png", - tool_capabilities = { - max_drop_level=1, - groupcaps={ - choppy={times={[1]=2.00, [2]=0.80, [3]=0.40}, uses=90, maxlevel=0}, - }, - }, -}) - --- --- Shears (dig snappy) --- - -minetest.register_tool("basetools:shears_wood", { - description = "Wooden Shears", - inventory_image = "basetools_woodshears.png", - tool_capabilities = { - max_drop_level=0, - groupcaps={ - snappy={times={[3]=1.00}, uses=30, maxlevel=0}, - }, - }, -}) -minetest.register_tool("basetools:shears_stone", { - description = "Stone Shears", - inventory_image = "basetools_stoneshears.png", - tool_capabilities = { - max_drop_level=0, - groupcaps={ - snappy={times={[2]=1.00, [3]=0.50}, uses=60, maxlevel=0}, - }, - }, -}) -minetest.register_tool("basetools:shears_steel", { - description = "Steel Shears", - inventory_image = "basetools_steelshears.png", - tool_capabilities = { - max_drop_level=1, - groupcaps={ - snappy={times={[1]=1.00, [2]=0.50, [3]=0.25}, uses=90, maxlevel=0}, - }, - }, -}) - --- --- Swords (deal damage) --- - -minetest.register_tool("basetools:sword_wood", { - description = "Wooden Sword", - inventory_image = "basetools_woodsword.png", - tool_capabilities = { - full_punch_interval = 1.0, - damage_groups = {fleshy=2}, - } -}) -minetest.register_tool("basetools:sword_stone", { - description = "Stone Sword", - inventory_image = "basetools_stonesword.png", - tool_capabilities = { - full_punch_interval = 1.0, - max_drop_level=0, - damage_groups = {fleshy=4}, - } -}) -minetest.register_tool("basetools:sword_steel", { - description = "Steel Sword", - inventory_image = "basetools_steelsword.png", - tool_capabilities = { - full_punch_interval = 1.0, - max_drop_level=1, - damage_groups = {fleshy=6}, - } -}) - --- Fire/Ice sword: Deal damage to non-fleshy damage groups -minetest.register_tool("basetools:sword_fire", { - description = "Fire Sword", - inventory_image = "basetools_firesword.png", - tool_capabilities = { - full_punch_interval = 1.0, - max_drop_level=0, - damage_groups = {icy=6}, - } -}) -minetest.register_tool("basetools:sword_ice", { - description = "Ice Sword", - inventory_image = "basetools_icesword.png", - tool_capabilities = { - full_punch_interval = 1.0, - max_drop_level=0, - damage_groups = {firy=6}, - } -}) - --- --- Dagger: Low damage, fast punch interval --- -minetest.register_tool("basetools:dagger_steel", { - description = "Steel Dagger", - inventory_image = "basetools_steeldagger.png", - tool_capabilities = { - full_punch_interval = 0.5, - max_drop_level=0, - damage_groups = {fleshy=2}, - } -}) diff --git a/games/minimal/mods/basetools/mod.conf b/games/minimal/mods/basetools/mod.conf deleted file mode 100644 index f0d9f657d..000000000 --- a/games/minimal/mods/basetools/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = basetools -description = Contains basic digging tools diff --git a/games/minimal/mods/basetools/textures/basetools_dirtpick.png b/games/minimal/mods/basetools/textures/basetools_dirtpick.png deleted file mode 100644 index 20a021d72..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_dirtpick.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_firesword.png b/games/minimal/mods/basetools/textures/basetools_firesword.png deleted file mode 100644 index ee2809ab7..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_firesword.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_icesword.png b/games/minimal/mods/basetools/textures/basetools_icesword.png deleted file mode 100644 index 35ba8214b..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_icesword.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_mesepick.png b/games/minimal/mods/basetools/textures/basetools_mesepick.png deleted file mode 100644 index 2b5e12cdb..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_mesepick.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_steelaxe.png b/games/minimal/mods/basetools/textures/basetools_steelaxe.png deleted file mode 100644 index aac594d84..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_steelaxe.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_steeldagger.png b/games/minimal/mods/basetools/textures/basetools_steeldagger.png deleted file mode 100644 index 4c9173094..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_steeldagger.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_steelpick.png b/games/minimal/mods/basetools/textures/basetools_steelpick.png deleted file mode 100644 index bc02aac3e..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_steelpick.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_steelpick_l1.png b/games/minimal/mods/basetools/textures/basetools_steelpick_l1.png deleted file mode 100644 index dc03f3f65..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_steelpick_l1.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_steelpick_l2.png b/games/minimal/mods/basetools/textures/basetools_steelpick_l2.png deleted file mode 100644 index 011df4584..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_steelpick_l2.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_steelshears.png b/games/minimal/mods/basetools/textures/basetools_steelshears.png deleted file mode 100644 index 04c86c370..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_steelshears.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_steelshovel.png b/games/minimal/mods/basetools/textures/basetools_steelshovel.png deleted file mode 100644 index 8cab60784..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_steelshovel.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_steelsword.png b/games/minimal/mods/basetools/textures/basetools_steelsword.png deleted file mode 100644 index 9909365c3..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_steelsword.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_stoneaxe.png b/games/minimal/mods/basetools/textures/basetools_stoneaxe.png deleted file mode 100644 index a374c547d..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_stoneaxe.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_stonepick.png b/games/minimal/mods/basetools/textures/basetools_stonepick.png deleted file mode 100644 index d9156ee3a..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_stonepick.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_stoneshears.png b/games/minimal/mods/basetools/textures/basetools_stoneshears.png deleted file mode 100644 index 0b4bd3b74..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_stoneshears.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_stoneshovel.png b/games/minimal/mods/basetools/textures/basetools_stoneshovel.png deleted file mode 100644 index 3c1bb48cb..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_stoneshovel.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_stonesword.png b/games/minimal/mods/basetools/textures/basetools_stonesword.png deleted file mode 100644 index 6f3e94cda..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_stonesword.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_woodaxe.png b/games/minimal/mods/basetools/textures/basetools_woodaxe.png deleted file mode 100644 index 4015e910f..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_woodaxe.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_woodpick.png b/games/minimal/mods/basetools/textures/basetools_woodpick.png deleted file mode 100644 index 15c61f408..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_woodpick.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_woodshears.png b/games/minimal/mods/basetools/textures/basetools_woodshears.png deleted file mode 100644 index 4ff92fd7c..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_woodshears.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_woodshovel.png b/games/minimal/mods/basetools/textures/basetools_woodshovel.png deleted file mode 100644 index 6cc52f8a1..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_woodshovel.png and /dev/null differ diff --git a/games/minimal/mods/basetools/textures/basetools_woodsword.png b/games/minimal/mods/basetools/textures/basetools_woodsword.png deleted file mode 100644 index 364016ed6..000000000 Binary files a/games/minimal/mods/basetools/textures/basetools_woodsword.png and /dev/null differ diff --git a/games/minimal/mods/bucket/init.lua b/games/minimal/mods/bucket/init.lua deleted file mode 100644 index 3189d4aa6..000000000 --- a/games/minimal/mods/bucket/init.lua +++ /dev/null @@ -1,26 +0,0 @@ --- Bucket: Punch liquid source or flowing liquid to collect it - -minetest.register_tool("bucket:bucket", { - description = "Bucket", - inventory_image = "bucket.png", - stack_max = 1, - liquids_pointable = true, - groups = { disable_repair = 1 }, - on_use = function(itemstack, user, pointed_thing) - -- Must be pointing to node - if pointed_thing.type ~= "node" then - return - end - -- Check if pointing to a liquid - local n = minetest.get_node(pointed_thing.under) - local def = minetest.registered_nodes[n.name] - if def ~= nil and (def.liquidtype == "source" or def.liquidtype == "flowing") then - minetest.add_node(pointed_thing.under, {name="air"}) - local inv = user:get_inventory() - if inv then - inv:add_item("main", ItemStack(n.name)) - end - end - end, -}) - diff --git a/games/minimal/mods/bucket/mod.conf b/games/minimal/mods/bucket/mod.conf deleted file mode 100644 index d14deb4ea..000000000 --- a/games/minimal/mods/bucket/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = bucket -description = Minimal bucket to pick up liquids diff --git a/games/minimal/mods/bucket/textures/bucket.png b/games/minimal/mods/bucket/textures/bucket.png deleted file mode 100644 index 677952875..000000000 Binary files a/games/minimal/mods/bucket/textures/bucket.png and /dev/null differ diff --git a/games/minimal/mods/bucket/textures/bucket_lava.png b/games/minimal/mods/bucket/textures/bucket_lava.png deleted file mode 100644 index dfcae65fb..000000000 Binary files a/games/minimal/mods/bucket/textures/bucket_lava.png and /dev/null differ diff --git a/games/minimal/mods/bucket/textures/bucket_water.png b/games/minimal/mods/bucket/textures/bucket_water.png deleted file mode 100644 index e164b0a50..000000000 Binary files a/games/minimal/mods/bucket/textures/bucket_water.png and /dev/null differ diff --git a/games/minimal/mods/chest/init.lua b/games/minimal/mods/chest/init.lua deleted file mode 100644 index c44522cb9..000000000 --- a/games/minimal/mods/chest/init.lua +++ /dev/null @@ -1,27 +0,0 @@ -minetest.register_node("chest:chest", { - description = "Chest", - tiles ={"chest_chest.png^[sheet:2x2:0,0", "chest_chest.png^[sheet:2x2:0,0", - "chest_chest.png^[sheet:2x2:1,0", "chest_chest.png^[sheet:2x2:1,0", - "chest_chest.png^[sheet:2x2:1,0", "chest_chest.png^[sheet:2x2:0,1"}, - paramtype2 = "facedir", - groups = {dig_immediate=2,choppy=3}, - is_ground_content = false, - on_construct = function(pos) - local meta = minetest.get_meta(pos) - meta:set_string("formspec", - "size[8,9]".. - "list[current_name;main;0,0;8,4;]".. - "list[current_player;main;0,5;8,4;]" .. - "listring[]") - meta:set_string("infotext", "Chest") - local inv = meta:get_inventory() - inv:set_size("main", 8*4) - end, - can_dig = function(pos,player) - local meta = minetest.get_meta(pos); - local inv = meta:get_inventory() - return inv:is_empty("main") - end, -}) - - diff --git a/games/minimal/mods/chest/mod.conf b/games/minimal/mods/chest/mod.conf deleted file mode 100644 index 0d7500164..000000000 --- a/games/minimal/mods/chest/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = chest -description = A simple chest to store items diff --git a/games/minimal/mods/chest/textures/chest_chest.png b/games/minimal/mods/chest/textures/chest_chest.png deleted file mode 100644 index 824b4d502..000000000 Binary files a/games/minimal/mods/chest/textures/chest_chest.png and /dev/null differ diff --git a/games/minimal/mods/chest_of_everything/init.lua b/games/minimal/mods/chest_of_everything/init.lua deleted file mode 100644 index 7d61abebf..000000000 --- a/games/minimal/mods/chest_of_everything/init.lua +++ /dev/null @@ -1,135 +0,0 @@ -local F = minetest.formspec_escape - --- Create a detached inventory -local inv_everything = minetest.create_detached_inventory("everything", { - allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) - return 0 - end, - allow_put = function(inv, listname, index, stack, player) - return 0 - end, - allow_take = function(inv, listname, index, stack, player) - return -1 - end, -}) -local inv_trash = minetest.create_detached_inventory("trash", { - allow_take = function(inv, listname, index, stack, player) - return 0 - end, - allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) - return 0 - end, - on_put = function(inv, listname, index, stack, player) - inv:set_list("main", {}) - end, -}) -inv_trash:set_size("main", 1) - -local max_page = 1 - -local function get_chest_formspec(page) - local start = 0 + (page-1)*32 - return "size[8,9]".. - "list[detached:everything;main;0,0;8,4;"..start.."]".. - "list[current_player;main;0,5;8,4;]" .. - "label[6,4;Trash:]" .. - "list[detached:trash;main;7,4;1,1]" .. - "button[0,4;1,1;chest_of_everything_prev;"..F("<").."]".. - "button[1,4;1,1;chest_of_everything_next;"..F(">").."]".. - "label[2,4;"..F("Page: "..page).."]".. - "listring[detached:everything;main]".. - "listring[current_player;main]".. - "listring[detached:trash;main]" -end - -minetest.register_node("chest_of_everything:chest", { - description = "Chest of Everything", - tiles ={"chest_of_everything_chest.png^[sheet:2x2:0,0", "chest_of_everything_chest.png^[sheet:2x2:0,0", - "chest_of_everything_chest.png^[sheet:2x2:1,0", "chest_of_everything_chest.png^[sheet:2x2:1,0", - "chest_of_everything_chest.png^[sheet:2x2:1,0", "chest_of_everything_chest.png^[sheet:2x2:0,1"}, - paramtype2 = "facedir", - groups = {dig_immediate=2,choppy=3}, - is_ground_content = false, - on_construct = function(pos) - local meta = minetest.get_meta(pos) - meta:set_string("infotext", "Chest of Everything") - meta:set_int("page", 1) - meta:set_string("formspec", get_chest_formspec(1)) - end, - on_receive_fields = function(pos, formname, fields, sender) - if formname == "" then - local meta = minetest.get_meta(pos) - local page = meta:get_int("page") - if fields.chest_of_everything_prev then - page = page - 1 - elseif fields.chest_of_everything_next then - page = page + 1 - end - if page < 1 then - page = 1 - end - if page > max_page then - page = max_page - end - meta:set_int("page", page) - meta:set_string("formspec", get_chest_formspec(page)) - end - end, -}) - -minetest.register_on_mods_loaded(function() - local items = {} - for itemstring,_ in pairs(minetest.registered_items) do - if itemstring ~= "" and itemstring ~= "unknown" and itemstring ~= "ignore" then - table.insert(items, itemstring) - end - end - --[[ Sort items in this order: - * Chest of Everything - * Test tools - * Other tools - * Craftitems - * Other items - * Dummy items ]] - local function compare(item1, item2) - local def1 = minetest.registered_items[item1] - local def2 = minetest.registered_items[item2] - local tool1 = def1.type == "tool" - local tool2 = def2.type == "tool" - local testtool1 = minetest.get_item_group(item1, "testtool") == 1 - local testtool2 = minetest.get_item_group(item2, "testtool") == 1 - local dummy1 = minetest.get_item_group(item1, "dummy") == 1 - local dummy2 = minetest.get_item_group(item2, "dummy") == 1 - local craftitem1 = def1.type == "craft" - local craftitem2 = def2.type == "craft" - if item1 == "chest_of_everything:chest" then - return true - elseif item2 == "chest_of_everything:chest" then - return false - elseif dummy1 and not dummy2 then - return false - elseif not dummy1 and dummy2 then - return true - elseif testtool1 and not testtool2 then - return true - elseif not testtool1 and testtool2 then - return false - elseif tool1 and not tool2 then - return true - elseif not tool1 and tool2 then - return false - elseif craftitem1 and not craftitem2 then - return true - elseif not craftitem1 and craftitem2 then - return false - else - return item1 < item2 - end - end - table.sort(items, compare) - inv_everything:set_size("main", #items) - max_page = math.ceil(#items / 32) - for i=1, #items do - inv_everything:add_item("main", items[i]) - end -end) diff --git a/games/minimal/mods/chest_of_everything/mod.conf b/games/minimal/mods/chest_of_everything/mod.conf deleted file mode 100644 index 4a4425e05..000000000 --- a/games/minimal/mods/chest_of_everything/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = chest_of_everything -description = Adds the chest of everything from which you can take all items diff --git a/games/minimal/mods/chest_of_everything/textures/chest_of_everything_chest.png b/games/minimal/mods/chest_of_everything/textures/chest_of_everything_chest.png deleted file mode 100644 index 6b2fd58d5..000000000 Binary files a/games/minimal/mods/chest_of_everything/textures/chest_of_everything_chest.png and /dev/null differ diff --git a/games/minimal/mods/dignodes/init.lua b/games/minimal/mods/dignodes/init.lua deleted file mode 100644 index 833150873..000000000 --- a/games/minimal/mods/dignodes/init.lua +++ /dev/null @@ -1,37 +0,0 @@ -local groups = { - "cracky", "dig_immediate" -} - --- Register dig nodes with 1 digging group, a rating between 1-3 and a level between 0-2 -for g=1, #groups do - local gr = groups[g] - for r=1, 3 do - for l=0, 2 do - if not (gr=="dig_immediate" and (l>0 or r==1)) then - local d - if l > 0 then - d = string.format("Dig Test Node: %s=%d, level=%d", gr, r, l) - else - d = string.format("Dig Test Node: %s=%d", gr, r) - end - local tile = "dignodes_"..gr..".png^dignodes_rating"..r..".png" - if l==1 then - tile = tile .. "^[colorize:#FFFF00:127" - elseif l==2 then - tile = tile .. "^[colorize:#FF0000:127" - end - minetest.register_node("dignodes:"..gr.."_"..r.."_"..l, { - description = d, - tiles = { tile }, - groups = { [gr] = r, level = l }, - }) - end - end - end -end - --- Node without any digging groups -minetest.register_node("dignodes:none", { - description = "Dig Test Node: groupless", - tiles = {"dignodes_none.png"}, -}) diff --git a/games/minimal/mods/dignodes/mod.conf b/games/minimal/mods/dignodes/mod.conf deleted file mode 100644 index 52a80d66e..000000000 --- a/games/minimal/mods/dignodes/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = dignodes -description = Nodes with different digging groups diff --git a/games/minimal/mods/dignodes/textures/dignodes_choppy.png b/games/minimal/mods/dignodes/textures/dignodes_choppy.png deleted file mode 100644 index a73fc2424..000000000 Binary files a/games/minimal/mods/dignodes/textures/dignodes_choppy.png and /dev/null differ diff --git a/games/minimal/mods/dignodes/textures/dignodes_cracky.png b/games/minimal/mods/dignodes/textures/dignodes_cracky.png deleted file mode 100644 index eb84e3079..000000000 Binary files a/games/minimal/mods/dignodes/textures/dignodes_cracky.png and /dev/null differ diff --git a/games/minimal/mods/dignodes/textures/dignodes_crumbly.png b/games/minimal/mods/dignodes/textures/dignodes_crumbly.png deleted file mode 100644 index 23f2f7c71..000000000 Binary files a/games/minimal/mods/dignodes/textures/dignodes_crumbly.png and /dev/null differ diff --git a/games/minimal/mods/dignodes/textures/dignodes_dig_immediate.png b/games/minimal/mods/dignodes/textures/dignodes_dig_immediate.png deleted file mode 100644 index a532ad90b..000000000 Binary files a/games/minimal/mods/dignodes/textures/dignodes_dig_immediate.png and /dev/null differ diff --git a/games/minimal/mods/dignodes/textures/dignodes_none.png b/games/minimal/mods/dignodes/textures/dignodes_none.png deleted file mode 100644 index 60f13650b..000000000 Binary files a/games/minimal/mods/dignodes/textures/dignodes_none.png and /dev/null differ diff --git a/games/minimal/mods/dignodes/textures/dignodes_rating1.png b/games/minimal/mods/dignodes/textures/dignodes_rating1.png deleted file mode 100644 index d2fee3a23..000000000 Binary files a/games/minimal/mods/dignodes/textures/dignodes_rating1.png and /dev/null differ diff --git a/games/minimal/mods/dignodes/textures/dignodes_rating2.png b/games/minimal/mods/dignodes/textures/dignodes_rating2.png deleted file mode 100644 index 15329b93f..000000000 Binary files a/games/minimal/mods/dignodes/textures/dignodes_rating2.png and /dev/null differ diff --git a/games/minimal/mods/dignodes/textures/dignodes_rating3.png b/games/minimal/mods/dignodes/textures/dignodes_rating3.png deleted file mode 100644 index 37216bfd1..000000000 Binary files a/games/minimal/mods/dignodes/textures/dignodes_rating3.png and /dev/null differ diff --git a/games/minimal/mods/experimental/commands.lua b/games/minimal/mods/experimental/commands.lua deleted file mode 100644 index 96f8cbe39..000000000 --- a/games/minimal/mods/experimental/commands.lua +++ /dev/null @@ -1,215 +0,0 @@ -minetest.register_chatcommand("test_inv", { - params = "", - description = "Test: Modify player's inventory formspec", - func = function(name, param) - local player = minetest.get_player_by_name(name) - if not player then - return false, "No player." - end - player:set_inventory_formspec( - "size[13,7.5]".. - "image[6,0.6;1,2;player.png]".. - "list[current_player;main;5,3.5;8,4;]".. - "list[current_player;craft;8,0;3,3;]".. - "list[current_player;craftpreview;12,1;1,1;]".. - "list[detached:test_inventory;main;0,0;4,6;0]".. - "button[0.5,7;2,1;button1;Button 1]".. - "button_exit[2.5,7;2,1;button2;Exit Button]") - return true, "Done." - end, -}) - -minetest.register_chatcommand("test_bulk_set_node", { - params = "", - description = "Test: Bulk-set 9×9×9 stone nodes", - func = function(name, param) - local player = minetest.get_player_by_name(name) - if not player then - return false, "No player." - end - local pos_list = {} - local ppos = player:get_pos() - local i = 1 - for x=2,10 do - for y=2,10 do - for z=2,10 do - pos_list[i] = {x=ppos.x + x,y = ppos.y + y,z = ppos.z + z} - i = i + 1 - end - end - end - minetest.bulk_set_node(pos_list, {name = "mapgen_stone"}) - return true, "Done." - end, -}) - -minetest.register_chatcommand("bench_bulk_set_node", { - params = "", - description = "Benchmark: Bulk-set 99×99×99 stone nodes", - func = function(name, param) - local player = minetest.get_player_by_name(name) - if not player then - return false, "No player." - end - local pos_list = {} - local ppos = player:get_pos() - local i = 1 - for x=2,100 do - for y=2,100 do - for z=2,100 do - pos_list[i] = {x=ppos.x + x,y = ppos.y + y,z = ppos.z + z} - i = i + 1 - end - end - end - - minetest.chat_send_player(name, "Benchmarking minetest.bulk_set_node. Warming up ..."); - - -- warm up with stone to prevent having different callbacks - -- due to different node topology - minetest.bulk_set_node(pos_list, {name = "mapgen_stone"}) - - minetest.chat_send_player(name, "Warming up finished, now benchmarking ..."); - - local start_time = minetest.get_us_time() - for i=1,#pos_list do - minetest.set_node(pos_list[i], {name = "mapgen_stone"}) - end - local middle_time = minetest.get_us_time() - minetest.bulk_set_node(pos_list, {name = "mapgen_stone"}) - local end_time = minetest.get_us_time() - local msg = string.format("Benchmark results: minetest.set_node loop: %.2f ms; minetest.bulk_set_node: %.2f ms", - ((middle_time - start_time)) / 1000, - ((end_time - middle_time)) / 1000 - ) - return true, msg - end, -}) - -local function advance_pos(pos, start_pos, advance_z) - if advance_z then - pos.z = pos.z + 2 - pos.x = start_pos.x - else - pos.x = pos.x + 2 - end - if pos.x > 30900 or pos.x - start_pos.x > 46 then - pos.x = start_pos.x - pos.z = pos.z + 2 - end - if pos.z > 30900 then - -- We ran out of space! Aborting - aborted = true - return false - end - return pos -end - -local function place_nodes(param) - local nodes = param.nodes - local name = param.name - local pos = param.pos - local start_pos = param.start_pos - table.sort(nodes) - minetest.chat_send_player(name, "Placing nodes …") - local nodes_placed = 0 - for n=1, #nodes do - local itemstring = nodes[n] - local def = minetest.registered_nodes[itemstring] - local p2_max = 0 - if param.param ~= "no_param2" then - -- Also test the param2 values of the nodes - -- ... but we only use permissible param2 values - if def.paramtype2 == "wallmounted" then - p2_max = 5 - elseif def.paramtype2 == "facedir" then - p2_max = 23 - elseif def.paramtype2 == "glasslikeliquidlevel" then - p2_max = 63 - elseif def.paramtype2 == "meshoptions" and def.drawtype == "plantlike" then - p2_max = 63 - elseif def.paramtype2 == "leveled" then - p2_max = 127 - elseif def.paramtype2 == "degrotate" and def.drawtype == "plantlike" then - p2_max = 179 - elseif def.paramtype2 == "colorfacedir" or - def.paramtype2 == "colorwallmounted" or - def.paramtype2 == "color" then - p2_max = 255 - end - end - for p2 = 0, p2_max do - -- Skip undefined param2 values - if not ((def.paramtype2 == "meshoptions" and p2 % 8 > 4) or - (def.paramtype2 == "colorwallmounted" and p2 % 8 > 5) or - (def.paramtype2 == "colorfacedir" and p2 % 32 > 23)) then - - minetest.set_node(pos, { name = itemstring, param2 = p2 }) - nodes_placed = nodes_placed + 1 - pos = advance_pos(pos, start_pos) - if not pos then - aborted = true - break - end - end - end - if aborted then - break - end - end - if aborted then - minetest.chat_send_player(name, "Not all nodes could be placed, please move further away from the world boundary. Nodes placed: "..nodes_placed) - end - minetest.chat_send_player(name, "Nodes placed: "..nodes_placed..".") -end - -local function after_emerge(blockpos, action, calls_remaining, param) - if calls_remaining == 0 then - place_nodes(param) - end -end - -minetest.register_chatcommand("test_place_nodes", { - params = "[ no_param2 ]", - description = "Test: Place all non-experimental nodes and optionally their permissible param2 variants", - func = function(name, param) - local player = minetest.get_player_by_name(name) - if not player then - return false, "No player." - end - local pos = vector.floor(player:get_pos()) - pos.x = math.ceil(pos.x + 3) - pos.z = math.ceil(pos.z + 3) - pos.y = math.ceil(pos.y + 1) - local start_pos = table.copy(pos) - if pos.x > 30800 then - return false, "Too close to world boundary (+X). Please move to X < 30800." - end - if pos.z > 30800 then - return false, "Too close to world boundary (+Z). Please move to Z < 30800." - end - - local aborted = false - local nodes = {} - local emerge_estimate = 0 - for itemstring, def in pairs(minetest.registered_nodes) do - if itemstring ~= "ignore" and string.sub(itemstring, 1, 13) ~= "experimental:" then - table.insert(nodes, itemstring) - if def.paramtype2 == 0 then - emerge_estimate = emerge_estimate + 1 - else - emerge_estimate = emerge_estimate + 255 - end - end - end - -- Emerge area to make sure that all nodes are being placed. - -- Note we will emerge much more than we need to (overestimation), - -- the estimation code could be improved performance-wise … - local length = 16 + math.ceil(emerge_estimate / 24) * 2 - minetest.emerge_area(start_pos, - { x = start_pos.x + 46, y = start_pos.y, z = start_pos.z + length }, - after_emerge, { nodes = nodes, name = name, pos = pos, start_pos = start_pos, param = param }) - return true, "Emerging area …" - end, -}) - diff --git a/games/minimal/mods/experimental/detached.lua b/games/minimal/mods/experimental/detached.lua deleted file mode 100644 index 673adfdd4..000000000 --- a/games/minimal/mods/experimental/detached.lua +++ /dev/null @@ -1,29 +0,0 @@ --- Create a detached inventory -local inv = minetest.create_detached_inventory("test_inventory", { - allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) - experimental.print_to_everything("allow move asked") - return count -- Allow all - end, - allow_put = function(inv, listname, index, stack, player) - experimental.print_to_everything("allow put asked") - return 1 -- Allow only 1 - end, - allow_take = function(inv, listname, index, stack, player) - experimental.print_to_everything("allow take asked") - return 4 -- Allow 4 at max - end, - on_move = function(inv, from_list, from_index, to_list, to_index, count, player) - experimental.print_to_everything(player:get_player_name().." moved items") - end, - on_put = function(inv, listname, index, stack, player) - experimental.print_to_everything(player:get_player_name().." put items") - end, - on_take = function(inv, listname, index, stack, player) - experimental.print_to_everything(player:get_player_name().." took items") - end, -}) -inv:set_size("main", 4*6) -inv:add_item("main", "experimental:callback_node") -inv:add_item("main", "experimental:particle_spawner") - - diff --git a/games/minimal/mods/experimental/init.lua b/games/minimal/mods/experimental/init.lua deleted file mode 100644 index b292f792e..000000000 --- a/games/minimal/mods/experimental/init.lua +++ /dev/null @@ -1,23 +0,0 @@ --- --- Experimental things --- - -experimental = {} - -dofile(minetest.get_modpath("experimental").."/detached.lua") -dofile(minetest.get_modpath("experimental").."/items.lua") -dofile(minetest.get_modpath("experimental").."/commands.lua") - -function experimental.print_to_everything(msg) - minetest.log("action", msg) - minetest.chat_send_all(msg) -end - -minetest.log("info", "[experimental] modname="..dump(minetest.get_current_modname())) -minetest.log("info", "[experimental] modpath="..dump(minetest.get_modpath("experimental"))) -minetest.log("info", "[experimental] worldpath="..dump(minetest.get_worldpath())) - - -minetest.register_on_mods_loaded(function() - minetest.log("action", "[experimental] on_mods_loaded()") -end) diff --git a/games/minimal/mods/experimental/items.lua b/games/minimal/mods/experimental/items.lua deleted file mode 100644 index 51b063ba2..000000000 --- a/games/minimal/mods/experimental/items.lua +++ /dev/null @@ -1,103 +0,0 @@ -minetest.register_node("experimental:callback_node", { - description = "Callback Test Node (construct/destruct/timer)", - tiles = {"experimental_callback_node.png"}, - groups = {dig_immediate=3}, - -- This was known to cause a bug in minetest.item_place_node() when used - -- via minetest.place_node(), causing a placer with no position - paramtype2 = "facedir", - drop = "", - - on_construct = function(pos) - experimental.print_to_everything("experimental:callback_node:on_construct("..minetest.pos_to_string(pos)..")") - local meta = minetest.get_meta(pos) - meta:set_string("mine", "test") - local timer = minetest.get_node_timer(pos) - timer:start(4, 3) - end, - - after_place_node = function(pos, placer) - experimental.print_to_everything("experimental:callback_node:after_place_node("..minetest.pos_to_string(pos)..")") - local meta = minetest.get_meta(pos) - if meta:get_string("mine") == "test" then - experimental.print_to_everything("correct metadata found") - else - experimental.print_to_everything("incorrect metadata found") - end - end, - - on_destruct = function(pos) - experimental.print_to_everything("experimental:callback_node:on_destruct("..minetest.pos_to_string(pos)..")") - end, - - after_destruct = function(pos) - experimental.print_to_everything("experimental:callback_node:after_destruct("..minetest.pos_to_string(pos)..")") - end, - - after_dig_node = function(pos, oldnode, oldmetadata, digger) - experimental.print_to_everything("experimental:callback_node:after_dig_node("..minetest.pos_to_string(pos)..")") - end, - - on_timer = function(pos, elapsed) - experimental.print_to_everything("on_timer(): elapsed="..dump(elapsed)) - return true - end, -}) - -minetest.register_tool("experimental:privatizer", { - description = "Node Meta Privatizer", - inventory_image = "experimental_tester_tool_1.png", - groups = { testtool = 1, disable_repair = 1 }, - on_use = function(itemstack, user, pointed_thing) - if pointed_thing.type == "node" then - local node = minetest.get_node(pointed_thing.under) - if node.name == "chest:chest" then - local p = pointed_thing.under - minetest.log("action", "Privatizer used at "..minetest.pos_to_string(p)) - minetest.get_meta(p):mark_as_private({"infotext", "formspec"}) - if user and user:is_player() then - minetest.chat_send_player(user:get_player_name(), "Chest metadata (infotext, formspec) set private!") - end - return - end - end - if user and user:is_player() then - minetest.chat_send_player(user:get_player_name(), "Privatizer can only be used on chest!") - end - end, -}) - -minetest.register_tool("experimental:particle_spawner", { - description = "Particle Spawner", - inventory_image = "experimental_tester_tool_1.png^[invert:g", - groups = { testtool = 1, disable_repair = 1 }, - on_use = function(itemstack, user, pointed_thing) - local pos = minetest.get_pointed_thing_position(pointed_thing, true) - if pos == nil then - if user then - pos = user:get_pos() - end - end - pos = vector.add(pos, {x=0, y=0.5, z=0}) - local tex, anim - if math.random(0, 1) == 0 then - tex = "experimental_particle_sheet.png" - anim = {type="sheet_2d", frames_w=3, frames_h=2, frame_length=0.5} - else - tex = "experimental_particle_vertical.png" - anim = {type="vertical_frames", aspect_w=16, aspect_h=16, length=3.3} - end - - minetest.add_particle({ - pos = pos, - velocity = {x=0, y=0, z=0}, - acceleration = {x=0, y=0.04, z=0}, - expirationtime = 6, - collisiondetection = true, - texture = tex, - animation = anim, - size = 4, - glow = math.random(0, 5), - }) - end, -}) - diff --git a/games/minimal/mods/experimental/mod.conf b/games/minimal/mods/experimental/mod.conf deleted file mode 100644 index cf0f9cb42..000000000 --- a/games/minimal/mods/experimental/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = experimental -description = Chaotic mod containing unstructured tests for testing out engine features. The features in this mod should be moved to other mods. diff --git a/games/minimal/mods/experimental/textures/experimental_callback_node.png b/games/minimal/mods/experimental/textures/experimental_callback_node.png deleted file mode 100644 index e9d87434c..000000000 Binary files a/games/minimal/mods/experimental/textures/experimental_callback_node.png and /dev/null differ diff --git a/games/minimal/mods/experimental/textures/experimental_particle_sheet.png b/games/minimal/mods/experimental/textures/experimental_particle_sheet.png deleted file mode 100644 index 6d70394e4..000000000 Binary files a/games/minimal/mods/experimental/textures/experimental_particle_sheet.png and /dev/null differ diff --git a/games/minimal/mods/experimental/textures/experimental_particle_vertical.png b/games/minimal/mods/experimental/textures/experimental_particle_vertical.png deleted file mode 100644 index 0320b7545..000000000 Binary files a/games/minimal/mods/experimental/textures/experimental_particle_vertical.png and /dev/null differ diff --git a/games/minimal/mods/experimental/textures/experimental_tester_tool_1.png b/games/minimal/mods/experimental/textures/experimental_tester_tool_1.png deleted file mode 100644 index 5df416a58..000000000 Binary files a/games/minimal/mods/experimental/textures/experimental_tester_tool_1.png and /dev/null differ diff --git a/games/minimal/mods/give_initial_stuff/init.lua b/games/minimal/mods/give_initial_stuff/init.lua deleted file mode 100644 index 491a531e4..000000000 --- a/games/minimal/mods/give_initial_stuff/init.lua +++ /dev/null @@ -1,37 +0,0 @@ -local give_if_not_gotten_already = function(inv, list, item) - if not inv:contains_item(list, item) then - inv:add_item(list, item) - end -end - -local give_initial_stuff = function(player) - local inv = player:get_inventory() - give_if_not_gotten_already(inv, "main", "basetools:pick_mese") - give_if_not_gotten_already(inv, "main", "basetools:axe_steel") - give_if_not_gotten_already(inv, "main", "basetools:shovel_steel") - give_if_not_gotten_already(inv, "main", "bucket:bucket") - give_if_not_gotten_already(inv, "main", "testnodes:light14") - give_if_not_gotten_already(inv, "main", "chest_of_everything:chest") - minetest.log("action", "[give_initial_stuff] Giving initial stuff to "..player:get_player_name()) -end - -minetest.register_on_newplayer(function(player) - if minetest.settings:get_bool("give_initial_stuff", true) then - give_initial_stuff(player) - end -end) - -minetest.register_chatcommand("stuff", { - params = "", - privs = { give = true }, - description = "Give yourself initial items", - func = function(name, param) - local player = minetest.get_player_by_name(name) - if not player or not player:is_player() then - return false, "No player." - end - give_initial_stuff(player) - return true - end, -}) - diff --git a/games/minimal/mods/give_initial_stuff/mod.conf b/games/minimal/mods/give_initial_stuff/mod.conf deleted file mode 100644 index 1ba49f52a..000000000 --- a/games/minimal/mods/give_initial_stuff/mod.conf +++ /dev/null @@ -1,3 +0,0 @@ -name = give_initial_stuff -description = Gives items to players on join -depends = basetools, bucket, chest_of_everything, testnodes diff --git a/games/minimal/mods/initial_message/init.lua b/games/minimal/mods/initial_message/init.lua deleted file mode 100644 index f92f4d3cf..000000000 --- a/games/minimal/mods/initial_message/init.lua +++ /dev/null @@ -1,9 +0,0 @@ -minetest.register_on_joinplayer(function(player) - local cb = function(player) - if not player or not player:is_player() then - return - end - minetest.chat_send_player(player:get_player_name(), "This is the \"Minimal development Test\" [minimal], meant only for testing and development. Use Minetest Game for the real thing.") - end - minetest.after(2.0, cb, player) -end) diff --git a/games/minimal/mods/initial_message/mod.conf b/games/minimal/mods/initial_message/mod.conf deleted file mode 100644 index 32aa2ac4e..000000000 --- a/games/minimal/mods/initial_message/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = initial_message -description = Show message to joining players explaining what this testing game is about diff --git a/games/minimal/mods/mapgen/init.lua b/games/minimal/mods/mapgen/init.lua deleted file mode 100644 index 13a186a50..000000000 --- a/games/minimal/mods/mapgen/init.lua +++ /dev/null @@ -1,81 +0,0 @@ --- --- Aliases for map generator outputs --- - --- ESSENTIAL node aliases --- Basic nodes -minetest.register_alias("mapgen_stone", "basenodes:stone") -minetest.register_alias("mapgen_water_source", "basenodes:water_source") -minetest.register_alias("mapgen_river_water_source", "basenodes:river_water_source") - --- Additional essential aliases for v6 -minetest.register_alias("mapgen_lava_source", "basenodes:lava_source") -minetest.register_alias("mapgen_dirt", "basenodes:dirt") -minetest.register_alias("mapgen_dirt_with_grass", "basenodes:dirt_with_grass") -minetest.register_alias("mapgen_sand", "basenodes:sand") -minetest.register_alias("mapgen_tree", "basenodes:tree") -minetest.register_alias("mapgen_leaves", "basenodes:leaves") -minetest.register_alias("mapgen_apple", "basenodes:apple") - --- Essential alias for dungeons -minetest.register_alias("mapgen_cobble", "basenodes:cobble") - --- Optional aliases for v6 (they all have fallback values in the engine) -if minetest.settings:get_bool("devtest_v6_mapgen_aliases", false) then - minetest.register_alias("mapgen_gravel", "basenodes:gravel") - minetest.register_alias("mapgen_desert_stone", "basenodes:desert_stone") - minetest.register_alias("mapgen_desert_sand", "basenodes:desert_sand") - minetest.register_alias("mapgen_dirt_with_snow", "basenodes:dirt_with_snow") - minetest.register_alias("mapgen_snowblock", "basenodes:snowblock") - minetest.register_alias("mapgen_snow", "basenodes:snow") - minetest.register_alias("mapgen_ice", "basenodes:ice") - minetest.register_alias("mapgen_junglegrass", "basenodes:junglegrass") - minetest.register_alias("mapgen_jungletree", "basenodes:jungletree") - minetest.register_alias("mapgen_jungleleaves", "basenodes:jungleleaves") - minetest.register_alias("mapgen_pine_tree", "basenodes:pine_tree") - minetest.register_alias("mapgen_pine_needles", "basenodes:pine_needles") -end --- Optional alias for mossycobble (should fall back to cobble) -if minetest.settings:get_bool("devtest_dungeon_mossycobble", false) then - minetest.register_alias("mapgen_mossycobble", "basenodes:mossycobble") -end --- Optional aliases for dungeon stairs (should fall back to full nodes) -if minetest.settings:get_bool("devtest_dungeon_stairs", false) then - minetest.register_alias("mapgen_stair_cobble", "stairs:stair_cobble") - if minetest.settings:get_bool("devtest_v6_mapgen_aliases", false) then - minetest.register_alias("mapgen_stair_desert_stone", "stairs:stair_desert_stone") - end -end - --- --- Register biomes for biome API --- - -minetest.clear_registered_biomes() -minetest.clear_registered_decorations() - -if minetest.settings:get_bool("devtest_register_biomes", true) then - minetest.register_biome({ - name = "mapgen:grassland", - node_top = "basenodes:dirt_with_grass", - depth_top = 1, - node_filler = "basenodes:dirt", - depth_filler = 1, - y_min = 5, - y_max = 31000, - heat_point = 50, - humidity_point = 50, - }) - - minetest.register_biome({ - name = "mapgen:grassland_ocean", - node_top = "basenodes:sand", - depth_top = 1, - node_filler = "basenodes:sand", - depth_filler = 2, - y_min = -31000, - y_max = 4, - heat_point = 50, - humidity_point = 50, - }) -end diff --git a/games/minimal/mods/mapgen/mod.conf b/games/minimal/mods/mapgen/mod.conf deleted file mode 100644 index 15750ccbe..000000000 --- a/games/minimal/mods/mapgen/mod.conf +++ /dev/null @@ -1,3 +0,0 @@ -name = mapgen -description = Minimal map generator -depends = basenodes diff --git a/games/minimal/mods/modchannels/init.lua b/games/minimal/mods/modchannels/init.lua deleted file mode 100644 index ee925f09b..000000000 --- a/games/minimal/mods/modchannels/init.lua +++ /dev/null @@ -1,14 +0,0 @@ --- --- Mod channels experimental handlers --- -local mod_channel = minetest.mod_channel_join("experimental_preview") - -minetest.register_on_modchannel_message(function(channel, sender, message) - minetest.log("action", "[modchannels] Server received message `" .. message - .. "` on channel `" .. channel .. "` from sender `" .. sender .. "`") - - if mod_channel:is_writeable() then - mod_channel:send_all("experimental answers to preview") - mod_channel:leave() - end -end) diff --git a/games/minimal/mods/modchannels/mod.conf b/games/minimal/mods/modchannels/mod.conf deleted file mode 100644 index 7c13aadfb..000000000 --- a/games/minimal/mods/modchannels/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = modchannels -description = Add experimental mod channel handlers diff --git a/games/minimal/mods/soundstuff/init.lua b/games/minimal/mods/soundstuff/init.lua deleted file mode 100644 index 22012ba14..000000000 --- a/games/minimal/mods/soundstuff/init.lua +++ /dev/null @@ -1,170 +0,0 @@ -local simple_nodes = { - footstep = { "Footstep Sound Node", "soundstuff_node_footstep.png" }, - dig = { "Dig Sound Node", "soundstuff_node_dig.png" }, - dug = { "Dug Sound Node", "soundstuff_node_dug.png" }, - place = { "Place Sound Node", "soundstuff_node_place.png" }, - place_failed = { "Place Failed Sound Node", "soundstuff_node_place_failed.png" }, -} - -for k,v in pairs(simple_nodes) do - minetest.register_node("soundstuff:"..k, { - description = v[1], - tiles = {"soundstuff_node_sound.png","soundstuff_node_sound.png",v[2]}, - groups = {dig_immediate=2}, - sounds = { - [k] = { name = "soundstuff_mono", gain = 1.0 }, - } - }) -end - -minetest.register_node("soundstuff:place_failed_attached", { - description = "Attached Place Failed Sound Node", - tiles = {"soundstuff_node_sound.png", "soundstuff_node_sound.png", "soundstuff_node_place_failed.png"}, - groups = {dig_immediate=2, attached_node=1}, - drawtype = "nodebox", - paramtype = "light", - node_box = { type = "fixed", fixed = { - { -7/16, -7/16, -7/16, 7/16, 7/16, 7/16 }, - { -0.5, -0.5, -0.5, 0.5, -7/16, 0.5 }, - }}, - sounds = { - place_failed = { name = "soundstuff_mono", gain = 1.0 }, - }, -}) - -minetest.register_node("soundstuff:fall", { - description = "Fall Sound Node", - tiles = {"soundstuff_node_sound.png", "soundstuff_node_sound.png", "soundstuff_node_fall.png"}, - groups = {dig_immediate=2, falling_node=1}, - sounds = { - fall = { name = "soundstuff_mono", gain = 1.0 }, - } -}) - -minetest.register_node("soundstuff:fall_attached", { - description = "Attached Fall Sound Node", - tiles = {"soundstuff_node_sound.png", "soundstuff_node_sound.png", "soundstuff_node_fall.png"}, - groups = {dig_immediate=2, attached_node=1}, - drawtype = "nodebox", - paramtype = "light", - node_box = { type = "fixed", fixed = { - { -7/16, -7/16, -7/16, 7/16, 7/16, 7/16 }, - { -0.5, -0.5, -0.5, 0.5, -7/16, 0.5 }, - }}, - sounds = { - fall = { name = "soundstuff_mono", gain = 1.0 }, - } -}) - -minetest.register_node("soundstuff:footstep_liquid", { - description = "Liquid Footstep Sound Node", - drawtype = "liquid", - tiles = { - "soundstuff_node_sound.png^[colorize:#0000FF:127", - }, - special_tiles = { - {name = "soundstuff_node_sound.png^[colorize:#0000FF:127", backface_culling = false}, - {name = "soundstuff_node_sound.png^[colorize:#0000FF:127", backface_culling = true}, - }, - liquids_pointable = true, - liquidtype = "source", - liquid_alternative_flowing = "soundstuff:footstep_liquid", - liquid_alternative_source = "soundstuff:footstep_liquid", - liquid_renewable = false, - liquid_range = 0, - liquid_viscosity = 0, - alpha = 190, - paramtype = "light", - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, - is_ground_content = false, - post_effect_color = {a = 64, r = 0, g = 0, b = 200}, - sounds = { - footstep = { name = "soundstuff_mono", gain = 1.0 }, - } -}) - -minetest.register_node("soundstuff:footstep_climbable", { - description = "Climbable Footstep Sound Node", - drawtype = "allfaces", - tiles = { - "soundstuff_node_climbable.png", - }, - alpha = 120, - paramtype = "light", - sunlight_propagates = true, - walkable = false, - climbable = true, - is_ground_content = false, - groups = { dig_immediate = 2 }, - sounds = { - footstep = { name = "soundstuff_mono", gain = 1.0 }, - } -}) - - - -minetest.register_craftitem("soundstuff:eat", { - description = "Eat Sound Item", - inventory_image = "soundstuff_eat.png", - on_use = minetest.item_eat(0), - sound = { - eat = { name = "soundstuff_mono", gain = 1.0 }, - } -}) - -minetest.register_tool("soundstuff:breaks", { - description = "Break Sound Tool", - inventory_image = "soundstuff_node_dug.png", - sound = { - breaks = { name = "soundstuff_mono", gain = 1.0 }, - }, - tool_capabilities = { - max_drop_level=0, - groupcaps={ - cracky={times={[2]=2.00, [3]=1.20}, uses=1, maxlevel=0}, - choppy={times={[2]=2.00, [3]=1.20}, uses=1, maxlevel=0}, - snappy={times={[2]=2.00, [3]=1.20}, uses=1, maxlevel=0}, - crumbly={times={[2]=2.00, [3]=1.20}, uses=1, maxlevel=0}, - }, - }, -}) - --- Plays sound repeatedly -minetest.register_node("soundstuff:positional", { - description = "Positional Sound Node", - on_construct = function(pos) - local timer = minetest.get_node_timer(pos) - timer:start(0) - end, - on_timer = function(pos, elapsed) - local node = minetest.get_node(pos) - local dist = node.param2 - if dist == 0 then - dist = nil - end - minetest.sound_play("soundstuff_mono", { pos = pos, max_hear_distance = dist }) - local timer = minetest.get_node_timer(pos) - timer:start(0.7) - end, - on_rightclick = function(pos, node, clicker) - node.param2 = (node.param2 + 1) % 64 - minetest.set_node(pos, node) - if clicker and clicker:is_player() then - local dist = node.param2 - local diststr - if dist == 0 then - diststr = "" - else - diststr = tostring(dist) - end - minetest.chat_send_player(clicker:get_player_name(), "max_hear_distance = " .. diststr) - end - end, - - groups = { dig_immediate = 2 }, - tiles = { "soundstuff_node_sound.png" }, -}) - diff --git a/games/minimal/mods/soundstuff/mod.conf b/games/minimal/mods/soundstuff/mod.conf deleted file mode 100644 index 2c631e2da..000000000 --- a/games/minimal/mods/soundstuff/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = soundstuff -description = Example items and nodes for testing sound effects diff --git a/games/minimal/mods/soundstuff/sounds/soundstuff_mono.ogg b/games/minimal/mods/soundstuff/sounds/soundstuff_mono.ogg deleted file mode 100644 index 43428d566..000000000 Binary files a/games/minimal/mods/soundstuff/sounds/soundstuff_mono.ogg and /dev/null differ diff --git a/games/minimal/mods/soundstuff/textures/soundstuff_eat.png b/games/minimal/mods/soundstuff/textures/soundstuff_eat.png deleted file mode 100644 index aed205422..000000000 Binary files a/games/minimal/mods/soundstuff/textures/soundstuff_eat.png and /dev/null differ diff --git a/games/minimal/mods/soundstuff/textures/soundstuff_node_blank.png b/games/minimal/mods/soundstuff/textures/soundstuff_node_blank.png deleted file mode 100644 index 4dffacc4c..000000000 Binary files a/games/minimal/mods/soundstuff/textures/soundstuff_node_blank.png and /dev/null differ diff --git a/games/minimal/mods/soundstuff/textures/soundstuff_node_climbable.png b/games/minimal/mods/soundstuff/textures/soundstuff_node_climbable.png deleted file mode 100644 index 3888f793c..000000000 Binary files a/games/minimal/mods/soundstuff/textures/soundstuff_node_climbable.png and /dev/null differ diff --git a/games/minimal/mods/soundstuff/textures/soundstuff_node_dig.png b/games/minimal/mods/soundstuff/textures/soundstuff_node_dig.png deleted file mode 100644 index 67ba111d8..000000000 Binary files a/games/minimal/mods/soundstuff/textures/soundstuff_node_dig.png and /dev/null differ diff --git a/games/minimal/mods/soundstuff/textures/soundstuff_node_dug.png b/games/minimal/mods/soundstuff/textures/soundstuff_node_dug.png deleted file mode 100644 index bab5fbe51..000000000 Binary files a/games/minimal/mods/soundstuff/textures/soundstuff_node_dug.png and /dev/null differ diff --git a/games/minimal/mods/soundstuff/textures/soundstuff_node_fall.png b/games/minimal/mods/soundstuff/textures/soundstuff_node_fall.png deleted file mode 100644 index 17b14f1e4..000000000 Binary files a/games/minimal/mods/soundstuff/textures/soundstuff_node_fall.png and /dev/null differ diff --git a/games/minimal/mods/soundstuff/textures/soundstuff_node_footstep.png b/games/minimal/mods/soundstuff/textures/soundstuff_node_footstep.png deleted file mode 100644 index 6367ae909..000000000 Binary files a/games/minimal/mods/soundstuff/textures/soundstuff_node_footstep.png and /dev/null differ diff --git a/games/minimal/mods/soundstuff/textures/soundstuff_node_place.png b/games/minimal/mods/soundstuff/textures/soundstuff_node_place.png deleted file mode 100644 index d159ad533..000000000 Binary files a/games/minimal/mods/soundstuff/textures/soundstuff_node_place.png and /dev/null differ diff --git a/games/minimal/mods/soundstuff/textures/soundstuff_node_place_failed.png b/games/minimal/mods/soundstuff/textures/soundstuff_node_place_failed.png deleted file mode 100644 index 780ba946d..000000000 Binary files a/games/minimal/mods/soundstuff/textures/soundstuff_node_place_failed.png and /dev/null differ diff --git a/games/minimal/mods/soundstuff/textures/soundstuff_node_sound.png b/games/minimal/mods/soundstuff/textures/soundstuff_node_sound.png deleted file mode 100644 index 0592a0299..000000000 Binary files a/games/minimal/mods/soundstuff/textures/soundstuff_node_sound.png and /dev/null differ diff --git a/games/minimal/mods/stairs/init.lua b/games/minimal/mods/stairs/init.lua deleted file mode 100644 index 2701cabab..000000000 --- a/games/minimal/mods/stairs/init.lua +++ /dev/null @@ -1,65 +0,0 @@ -stairs = {} - --- Node will be called stairs:stair_ -function stairs.register_stair(subname, recipeitem, groups, images, description) - minetest.register_node(":stairs:stair_" .. subname, { - description = description, - drawtype = "nodebox", - tiles = images, - paramtype = "light", - paramtype2 = "facedir", - is_ground_content = true, - groups = groups, - node_box = { - type = "fixed", - fixed = { - {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, - {-0.5, 0, 0, 0.5, 0.5, 0.5}, - }, - }, - }) -end - --- Node will be called stairs:slab_ -function stairs.register_slab(subname, recipeitem, groups, images, description) - minetest.register_node(":stairs:slab_" .. subname, { - description = description, - drawtype = "nodebox", - tiles = images, - paramtype = "light", - is_ground_content = true, - groups = groups, - node_box = { - type = "fixed", - fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, - }, - selection_box = { - type = "fixed", - fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, - }, - }) -end - --- Nodes will be called stairs:{stair,slab}_ -function stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab) - stairs.register_stair(subname, recipeitem, groups, images, desc_stair) - stairs.register_slab(subname, recipeitem, groups, images, desc_slab) -end - -stairs.register_stair_and_slab("stone", "basenodes:stone", - {cracky=3}, - {"default_stone.png"}, - "Stone Stair", - "Stone Slab") - -stairs.register_stair_and_slab("desert_stone", "basenodes:desert_stone", - {cracky=3}, - {"default_desert_stone.png"}, - "Desert Stone Stair", - "Desert Stone Slab") - -stairs.register_stair_and_slab("cobble", "basenodes:cobble", - {cracky=3}, - {"default_cobble.png"}, - "Cobblestone Stair", - "Cobblestone Slab") diff --git a/games/minimal/mods/stairs/mod.conf b/games/minimal/mods/stairs/mod.conf deleted file mode 100644 index 724bff881..000000000 --- a/games/minimal/mods/stairs/mod.conf +++ /dev/null @@ -1,3 +0,0 @@ -name = stairs -description = Adds stairs and slabs -depends = basenodes diff --git a/games/minimal/mods/testentities/armor.lua b/games/minimal/mods/testentities/armor.lua deleted file mode 100644 index 4c30cec8d..000000000 --- a/games/minimal/mods/testentities/armor.lua +++ /dev/null @@ -1,41 +0,0 @@ --- Armorball: Test entity for testing armor groups --- Rightclick to change armor group - -local phasearmor = { - [0]={icy=100}, - [1]={firy=100}, - [2]={fleshy=100}, - [3]={immortal=1}, - [4]={punch_operable=1}, -} - -minetest.register_entity("testentities:armorball", { - initial_properties = { - hp_max = 20, - physical = false, - collisionbox = {-0.4,-0.4,-0.4, 0.4,0.4,0.4}, - visual = "sprite", - visual_size = {x=1, y=1}, - textures = {"testentities_armorball.png"}, - spritediv = {x=1, y=5}, - initial_sprite_basepos = {x=0, y=0}, - }, - - _phase = 2, - - on_activate = function(self, staticdata) - minetest.log("action", "[testentities] armorball.on_activate") - self.object:set_armor_groups(phasearmor[self._phase]) - self.object:set_sprite({x=0, y=self._phase}) - end, - - on_rightclick = function(self, clicker) - -- Change armor group and sprite - self._phase = self._phase + 1 - if self._phase >= 5 then - self._phase = 0 - end - self.object:set_sprite({x=0, y=self._phase}) - self.object:set_armor_groups(phasearmor[self._phase]) - end, -}) diff --git a/games/minimal/mods/testentities/callbacks.lua b/games/minimal/mods/testentities/callbacks.lua deleted file mode 100644 index 711079f87..000000000 --- a/games/minimal/mods/testentities/callbacks.lua +++ /dev/null @@ -1,75 +0,0 @@ --- Entities that test their callbacks - -local message = function(msg) - minetest.log("action", msg) - minetest.chat_send_all(msg) -end - -local get_object_name = function(obj) - local name = "" - if obj then - if obj:is_player() then - name = obj:get_player_name() - else - name = "" - end - end - return name -end - -local spos = function(self) - return minetest.pos_to_string(vector.round(self.object:get_pos())) -end - --- Callback test entity (all callbacks except on_step) -minetest.register_entity("testentities:callback", { - initial_properties = { - visual = "upright_sprite", - textures = { "testentities_callback.png" }, - }, - - on_activate = function(self, staticdata, dtime_s) - message("Callback entity: on_activate! pos="..spos(self).."; dtime_s="..dtime_s) - end, - on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage) - local name = get_object_name(puncher) - message( - "Callback entity: on_punch! ".. - "pos="..spos(self).."; puncher="..name.."; ".. - "time_from_last_punch="..time_from_last_punch.."; ".. - "tool_capabilities="..tostring(dump(tool_capabilities)).."; ".. - "dir="..tostring(dump(dir)).."; damage="..damage) - end, - on_rightclick = function(self, clicker) - local name = get_object_name(clicker) - message("Callback entity: on_rightclick! pos="..spos(self).."; clicker="..name) - end, - on_death = function(self, killer) - local name = get_object_name(killer) - message("Callback entity: on_death! pos="..spos(self).."; killer="..name) - end, - on_attach_child = function(self, child) - local name = get_object_name(child) - message("Callback entity: on_attach_child! pos="..spos(self).."; child="..name) - end, - on_detach_child = function(self, child) - local name = get_object_name(child) - message("Callback entity: on_detach_child! pos="..spos(self).."; child="..name) - end, - on_detach = function(self, parent) - local name = get_object_name(parent) - message("Callback entity: on_detach! pos="..spos(self).."; parent="..name) - end, - get_staticdata = function(self) - message("Callback entity: get_staticdata! pos="..spos(self)) - end, -}) - --- Only test on_step callback -minetest.register_entity("testentities:callback_step", { - visual = "upright_sprite", - textures = { "testentities_callback_step.png" }, - on_step = function(self, dtime) - message("on_step callback entity: on_step! pos="..spos(self).."; dtime="..dtime) - end, -}) diff --git a/games/minimal/mods/testentities/init.lua b/games/minimal/mods/testentities/init.lua deleted file mode 100644 index df8c72ea7..000000000 --- a/games/minimal/mods/testentities/init.lua +++ /dev/null @@ -1,3 +0,0 @@ -dofile(minetest.get_modpath("testentities").."/visuals.lua") -dofile(minetest.get_modpath("testentities").."/armor.lua") -dofile(minetest.get_modpath("testentities").."/callbacks.lua") diff --git a/games/minimal/mods/testentities/mod.conf b/games/minimal/mods/testentities/mod.conf deleted file mode 100644 index 7a8cb5a3e..000000000 --- a/games/minimal/mods/testentities/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = testentities -description = Example entities for testing diff --git a/games/minimal/mods/testentities/textures/testentities_armorball.png b/games/minimal/mods/testentities/textures/testentities_armorball.png deleted file mode 100644 index 88147bd1f..000000000 Binary files a/games/minimal/mods/testentities/textures/testentities_armorball.png and /dev/null differ diff --git a/games/minimal/mods/testentities/textures/testentities_callback.png b/games/minimal/mods/testentities/textures/testentities_callback.png deleted file mode 100644 index c4c9066d1..000000000 Binary files a/games/minimal/mods/testentities/textures/testentities_callback.png and /dev/null differ diff --git a/games/minimal/mods/testentities/textures/testentities_callback_step.png b/games/minimal/mods/testentities/textures/testentities_callback_step.png deleted file mode 100644 index b67506a97..000000000 Binary files a/games/minimal/mods/testentities/textures/testentities_callback_step.png and /dev/null differ diff --git a/games/minimal/mods/testentities/textures/testentities_cube1.png b/games/minimal/mods/testentities/textures/testentities_cube1.png deleted file mode 100644 index c667e425f..000000000 Binary files a/games/minimal/mods/testentities/textures/testentities_cube1.png and /dev/null differ diff --git a/games/minimal/mods/testentities/textures/testentities_cube2.png b/games/minimal/mods/testentities/textures/testentities_cube2.png deleted file mode 100644 index 481823420..000000000 Binary files a/games/minimal/mods/testentities/textures/testentities_cube2.png and /dev/null differ diff --git a/games/minimal/mods/testentities/textures/testentities_cube3.png b/games/minimal/mods/testentities/textures/testentities_cube3.png deleted file mode 100644 index 03b5daa15..000000000 Binary files a/games/minimal/mods/testentities/textures/testentities_cube3.png and /dev/null differ diff --git a/games/minimal/mods/testentities/textures/testentities_cube4.png b/games/minimal/mods/testentities/textures/testentities_cube4.png deleted file mode 100644 index 639204896..000000000 Binary files a/games/minimal/mods/testentities/textures/testentities_cube4.png and /dev/null differ diff --git a/games/minimal/mods/testentities/textures/testentities_cube5.png b/games/minimal/mods/testentities/textures/testentities_cube5.png deleted file mode 100644 index d8acdf0b6..000000000 Binary files a/games/minimal/mods/testentities/textures/testentities_cube5.png and /dev/null differ diff --git a/games/minimal/mods/testentities/textures/testentities_cube6.png b/games/minimal/mods/testentities/textures/testentities_cube6.png deleted file mode 100644 index 5f81a64d9..000000000 Binary files a/games/minimal/mods/testentities/textures/testentities_cube6.png and /dev/null differ diff --git a/games/minimal/mods/testentities/textures/testentities_dungeon_master.png b/games/minimal/mods/testentities/textures/testentities_dungeon_master.png deleted file mode 100644 index 1e3107746..000000000 Binary files a/games/minimal/mods/testentities/textures/testentities_dungeon_master.png and /dev/null differ diff --git a/games/minimal/mods/testentities/textures/testentities_sprite.png b/games/minimal/mods/testentities/textures/testentities_sprite.png deleted file mode 100644 index a4b019699..000000000 Binary files a/games/minimal/mods/testentities/textures/testentities_sprite.png and /dev/null differ diff --git a/games/minimal/mods/testentities/textures/testentities_upright_sprite1.png b/games/minimal/mods/testentities/textures/testentities_upright_sprite1.png deleted file mode 100644 index 6242511df..000000000 Binary files a/games/minimal/mods/testentities/textures/testentities_upright_sprite1.png and /dev/null differ diff --git a/games/minimal/mods/testentities/textures/testentities_upright_sprite2.png b/games/minimal/mods/testentities/textures/testentities_upright_sprite2.png deleted file mode 100644 index a79a760e3..000000000 Binary files a/games/minimal/mods/testentities/textures/testentities_upright_sprite2.png and /dev/null differ diff --git a/games/minimal/mods/testentities/visuals.lua b/games/minimal/mods/testentities/visuals.lua deleted file mode 100644 index de346fd68..000000000 --- a/games/minimal/mods/testentities/visuals.lua +++ /dev/null @@ -1,74 +0,0 @@ --- Minimal test entities to test visuals - -minetest.register_entity("testentities:sprite", { - initial_properties = { - visual = "sprite", - textures = { "testentities_sprite.png" }, - }, -}) - -minetest.register_entity("testentities:upright_sprite", { - initial_properties = { - visual = "upright_sprite", - textures = { - "testentities_upright_sprite1.png", - "testentities_upright_sprite2.png", - }, - }, -}) - -minetest.register_entity("testentities:cube", { - initial_properties = { - visual = "cube", - textures = { - "testentities_cube1.png", - "testentities_cube2.png", - "testentities_cube3.png", - "testentities_cube4.png", - "testentities_cube5.png", - "testentities_cube6.png", - }, - }, -}) - -minetest.register_entity("testentities:item", { - initial_properties = { - visual = "item", - wield_item = "testnodes:normal", - }, -}) - -minetest.register_entity("testentities:wielditem", { - initial_properties = { - visual = "wielditem", - wield_item = "testnodes:normal", - }, -}) - -minetest.register_entity("testentities:mesh", { - initial_properties = { - visual = "mesh", - mesh = "testnodes_pyramid.obj", - textures = { - "testnodes_mesh_stripes2.png" - }, - }, -}) - --- Advanced visual tests - --- A test entity for testing animated and yaw-modulated sprites -minetest.register_entity("testentities:yawsprite", { - initial_properties = { - selectionbox = {-0.3, -0.5, -0.3, 0.3, 0.3, 0.3}, - visual = "sprite", - visual_size = {x=0.6666, y=1}, - textures = {"testentities_dungeon_master.png^[makealpha:128,0,0^[makealpha:128,128,0"}, - spritediv = {x=6, y=5}, - initial_sprite_basepos = {x=0, y=0}, - on_activate = function(self, staticdata) - self.object:set_sprite({x=0, y=0}, 1, 0, true) - end, - }, -}) - diff --git a/games/minimal/mods/testfood/init.lua b/games/minimal/mods/testfood/init.lua deleted file mode 100644 index a6236ff68..000000000 --- a/games/minimal/mods/testfood/init.lua +++ /dev/null @@ -1,24 +0,0 @@ -local S = minetest.get_translator("testfood") - -minetest.register_craftitem("testfood:good1", { - description = S("Good Food (+1)"), - inventory_image = "testfood_good.png", - on_use = minetest.item_eat(1), -}) -minetest.register_craftitem("testfood:good5", { - description = S("Good Food (+5)"), - inventory_image = "testfood_good2.png", - on_use = minetest.item_eat(5), -}) - -minetest.register_craftitem("testfood:bad1", { - description = S("Bad Food (-1)"), - inventory_image = "testfood_bad.png", - on_use = minetest.item_eat(-1), -}) -minetest.register_craftitem("testfood:bad5", { - description = S("Bad Food (-5)"), - inventory_image = "testfood_bad2.png", - on_use = minetest.item_eat(-5), -}) - diff --git a/games/minimal/mods/testfood/mod.conf b/games/minimal/mods/testfood/mod.conf deleted file mode 100644 index 7bff21b6e..000000000 --- a/games/minimal/mods/testfood/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = testfood -description = For testing food items diff --git a/games/minimal/mods/testfood/textures/testfood_bad.png b/games/minimal/mods/testfood/textures/testfood_bad.png deleted file mode 100644 index 6e9251440..000000000 Binary files a/games/minimal/mods/testfood/textures/testfood_bad.png and /dev/null differ diff --git a/games/minimal/mods/testfood/textures/testfood_bad2.png b/games/minimal/mods/testfood/textures/testfood_bad2.png deleted file mode 100644 index 22b567890..000000000 Binary files a/games/minimal/mods/testfood/textures/testfood_bad2.png and /dev/null differ diff --git a/games/minimal/mods/testfood/textures/testfood_good.png b/games/minimal/mods/testfood/textures/testfood_good.png deleted file mode 100644 index 31df7f5dd..000000000 Binary files a/games/minimal/mods/testfood/textures/testfood_good.png and /dev/null differ diff --git a/games/minimal/mods/testfood/textures/testfood_good2.png b/games/minimal/mods/testfood/textures/testfood_good2.png deleted file mode 100644 index e43dda209..000000000 Binary files a/games/minimal/mods/testfood/textures/testfood_good2.png and /dev/null differ diff --git a/games/minimal/mods/testformspec/callbacks.lua b/games/minimal/mods/testformspec/callbacks.lua deleted file mode 100644 index 559380580..000000000 --- a/games/minimal/mods/testformspec/callbacks.lua +++ /dev/null @@ -1,51 +0,0 @@ -local callback_test = 0 - -local out = function(player, formname, fields, number) - local snum = "" - if number then - snum = " "..number - end - local msg = "Formspec callback"..snum..": player="..player:get_player_name()..", formname=\""..tostring(formname).."\", fields="..dump(fields) - minetest.chat_send_player(player:get_player_name(), msg) - minetest.log("action", msg) -end - -minetest.register_on_player_receive_fields(function(player, formname, fields) - if callback_test == 1 then - out(player, formname, fields) - elseif callback_test == 2 then - out(player, formname, fields, 1) - end -end) -minetest.register_on_player_receive_fields(function(player, formname, fields) - if callback_test == 2 then - out(player, formname, fields, 2) - return true -- Disable the first callback - end -end) -minetest.register_on_player_receive_fields(function(player, formname, fields) - if callback_test == 2 then - out(player, formname, fields, 3) - end -end) - -minetest.register_chatcommand("test_formspec_callbacks", { - params = "[ 0 | 1 | 2 ]", - description = "Test: Change formspec callbacks testing mode", - func = function(name, param) - local mode = tonumber(param) - if not mode then - callback_test = (callback_test + 1 % 3) - else - callback_test = mode - end - if callback_test == 1 then - minetest.chat_send_player(name, "Formspec callback test mode 1 enabled: Logging only") - elseif callback_test == 2 then - minetest.chat_send_player(name, "Formspec callback test mode 2 enabled: Three callbacks, disable pre-registered callbacks") - else - callback_test = 0 - minetest.chat_send_player(name, "Formspec callback test disabled!") - end - end -}) diff --git a/games/minimal/mods/testformspec/dummy_items.lua b/games/minimal/mods/testformspec/dummy_items.lua deleted file mode 100644 index 2037ae9cf..000000000 --- a/games/minimal/mods/testformspec/dummy_items.lua +++ /dev/null @@ -1,14 +0,0 @@ --- This code adds dummy items that are supposed to be used in formspecs --- for testing item_image formspec elements. - -minetest.register_node("testformspec:node", { - description = "Formspec Test Node", - tiles = { "testformspec_node.png" }, - groups = { dig_immediate = 3, dummy = 1 }, -}) - -minetest.register_craftitem("testformspec:item", { - description = "Formspec Test Item", - inventory_image = "testformspec_item.png", - groups = { dummy = 1 }, -}) diff --git a/games/minimal/mods/testformspec/formspec.lua b/games/minimal/mods/testformspec/formspec.lua deleted file mode 100644 index 08c1b6dc0..000000000 --- a/games/minimal/mods/testformspec/formspec.lua +++ /dev/null @@ -1,381 +0,0 @@ -local color = minetest.colorize - -local clip_fs = [[ - style_type[label,button,image_button,item_image_button, - tabheader,scrollbar,table,animated_image - ,field,textarea,checkbox,dropdown;noclip=%c] - - label[0,0;A clipping test] - button[0,1;3,0.8;clip_button;A clipping test] - image_button[0,2;3,0.8;testformspec_button_image.png;clip_image_button;A clipping test] - item_image_button[0,3;3,0.8;testformspec:item;clip_item_image_button;A clipping test] - tabheader[0,4.7;3,0.63;clip_tabheader;Clip,Test,Text,Tabs;1;false;false] - field[0,5;3,0.8;clip_field;Title;] - textarea[0,6;3,1;clip_textarea;Title;] - checkbox[0,7.5;clip_checkbox;This is a test;true] - dropdown[0,8;3,0.8;clip_dropdown;Select An Item,One,Two,Three,Four,Five;1] - scrollbar[0,9;3,0.8;horizontal;clip_scrollbar;3] - tablecolumns[text;text] - table[0,10;3,1;clip_table;one,two,three,four;1] - animated_image[-0.5,11;4.5,1;clip_animated_image;testformspec_animation.png;4;100] -]] - -local tabheaders_fs = [[ - tabheader[0,0;10,0.63;tabs_opaque;Opaque,Without,Border;1;false;false] - tabheader[0,1;10,0.63;tabs_opaque_border;Opaque,With,Border;1;false;true] - tabheader[0,2;10,0.63;tabs_transparent;Transparent,Without,Border;1;true;false] - tabheader[0,3;10,0.63;tabs_transparent_border;Transparent,With,Border;1;true;true] - tabheader[0,4;tabs_default;Default,Tabs;1] - tabheader[0,6;10,0.5;tabs_size1;Height=0.5;1;false;false] - tabheader[2,6;10,0.75;tabs_size1;Height=0.75;1;false;false] - tabheader[4,6;10,1;tabs_size2;Height=1;1;false;false] - tabheader[6,6;10,1.25;tabs_size2;Height=1.25;1;false;false] - tabheader[8,6;10,1.5;tabs_size2;Height=1.5;1;false;false] -]] - -local hypertext_basic = [[ -Normal test -This is a normal text. - -style test - - . - - -Tag test -normal -mono -bold -italic -underlined -big -bigger -left -
center
-right -justify. Here comes a blind text: Lorem testum dolor sit amet consecutor celeron fiftifahivus e shadoninia e smalus jokus anrus relsocutoti rubenwardus. Erasputinus hara holisti dominus wusi. Grumarinsti erltusmuate ol fortitusti fla flo, blani burki e sfani fahif. Ultae ratii, e megus gigae don anonimus. Grinus dimondus krockus e nore. Endus finalus nowus comus endus o blindus tekstus. - -Custom tag test - - - - - -color=green -Action: color=green -Action: hovercolor=yellow -size=24 -font=mono -color=green font=mono size=24 - -action test -action - -img test -Normal: - -width=48 height=48: - -float=left: - -float=right: - - -item test -Normal: - -width=48 height=48 - -angle=30,0,0: - -angle=0,30,0: - -angle=0,0,30: - -rotate=yes: - -rotate=100,0,0: - -rotate=0,100,0: - -rotate=0,0,100: - -rotate=50,75,100: - -angle=-30,-45,90 rotate=100,150,-50: -]] - -local hypertext_global = [[ - -This is a test of the global tag. The parameters are: -background=gray margin=20 valign=bottom halign=right color=pink hovercolor=purple size=12 font=mono -action]] - -local hypertext_fs = "hypertext[0,0;11,9;hypertext;"..minetest.formspec_escape(hypertext_basic).."]".. - "hypertext[0,9.5;11,2.5;hypertext;"..minetest.formspec_escape(hypertext_global).."]" - -local style_fs = [[ - style[one_btn1;bgcolor=red;textcolor=yellow;bgcolor_hovered=orange; - bgcolor_pressed=purple] - button[0,0;2.5,0.8;one_btn1;Button] - - style[one_btn2;border=false;textcolor=cyan] ]].. - "button[0,1.05;2.5,0.8;one_btn2;Text " .. color("#FF0", "Yellow") .. [[] - - style[one_btn3;bgimg=testformspec_button_image.png;bgimg_hovered=testformspec_hovered.png; - bgimg_pressed=testformspec_pressed.png] - button[0,2.1;1,1;one_btn3;Border] - - style[one_btn4;bgimg=testformspec_button_image.png;bgimg_hovered=testformspec_hovered.png; - bgimg_pressed=testformspec_pressed.png;border=false] - button[1.25,2.1;1,1;one_btn4;NoBor] - - style[one_btn5;bgimg=testformspec_button_image.png;bgimg_hovered=testformspec_hovered.png; - bgimg_pressed=testformspec_pressed.png;border=false;alpha=false] - button[0,3.35;1,1;one_btn5;Alph] - - style[one_btn6;border=true] - image_button[0,4.6;1,1;testformspec_button_image.png;one_btn6;Border] - - style[one_btn7;border=false] - image_button[1.25,4.6;1,1;testformspec_button_image.png;one_btn7;NoBor] - - style[one_btn8;border=false] - image_button[0,5.85;1,1;testformspec_button_image.png;one_btn8;Border;false;true;testformspec_pressed.png] - - style[one_btn9;border=true] - image_button[1.25,5.85;1,1;testformspec_button_image.png;one_btn9;NoBor;false;false;testformspec_pressed.png] - - style[one_btn10;alpha=false] - image_button[0,7.1;1,1;testformspec_button_image.png;one_btn10;NoAlpha] - - style[one_btn11;alpha=true] - image_button[1.25,7.1;1,1;testformspec_button_image.png;one_btn11;Alpha] - - style[one_btn12;border=true] - item_image_button[0,8.35;1,1;testformspec:item;one_btn12;Border] - - style[one_btn13;border=false] - item_image_button[1.25,8.35;1,1;testformspec:item;one_btn13;NoBor] - - style[one_btn14;border=false;bgimg=testformspec_bg.png;fgimg=testformspec_button_image.png] - style[one_btn14:hovered;bgimg=testformspec_bg_hovered.png;fgimg=testformspec_hovered.png;textcolor=yellow] - style[one_btn14:pressed;bgimg=testformspec_bg_pressed.png;fgimg=testformspec_pressed.png;textcolor=blue] - style[one_btn14:hovered+pressed;textcolor=purple] - image_button[0,9.6;1,1;testformspec_button_image.png;one_btn14;Bg] - - style[one_btn15;border=false;bgimg=testformspec_bg.png;bgimg_hovered=testformspec_bg_hovered.png;bgimg_pressed=testformspec_bg_pressed.png] - item_image_button[1.25,9.6;1,1;testformspec:item;one_btn15;Bg] - - style[one_btn16;border=false;bgimg=testformspec_bg_9slice.png;bgimg_hovered=testformspec_bg_9slice_hovered.png;bgimg_pressed=testformspec_bg_9slice_pressed.png;bgimg_middle=4,6] - button[2.5,9.6;2,1;one_btn16;9-Slice Bg] - - - - container[2.75,0] - - style[one_tb1;textcolor=Yellow] - tabheader[0,3;2.5,0.63;one_tb1;Yellow,Text,Tabs;1;false;false] - - style[one_f1;textcolor=yellow] - field[0,4.25;2.5,0.8;one_f1;Field One;Yellow Text] - - style[one_f2;border=false;textcolor=cyan] - field[0,5.75;2.5,0.8;one_f2;Field Two;Borderless Cyan Text] - - style[one_f3;textcolor=yellow] - textarea[0,7.025;2.5,0.8;one_f3;Label;]] .. - minetest.formspec_escape("Yellow Text\nLine two") .. [[ ] - - style[one_f4;border=false;textcolor=cyan] - textarea[0,8.324999999999999;2.5,0.8;one_f4;Label;]] .. - minetest.formspec_escape("Borderless Cyan Text\nLine two") .. [[ ] - - container_end[] -]] - -local scroll_fs = - "button[8.5,1;4,1;outside;Outside of container]".. - "box[1,1;8,6;#00aa]".. - "scroll_container[1,1;8,6;scrbar;vertical]".. - "button[0,1;1,1;lorem;Lorem]".. - "button[0,10;1,1;ipsum;Ipsum]".. - "pwdfield[2,2;1,1;lorem2;Lorem]".. - "list[current_player;main;4,4;1,5;]".. - "box[2,5;3,2;#ffff00]".. - "image[1,10;3,2;testformspec_item.png]".. - "image[3,1;testformspec_item.png]".. - "item_image[2,6;3,2;testformspec:node]".. - "label[2,15;bla Bli\nfoo bar]".. - "item_image_button[2,3;1,1;testformspec:node;itemimagebutton;ItemImageButton]".. - "tooltip[0,11;3,2;Buz;#f00;#000]".. - "box[0,11;3,2;#00ff00]".. - "hypertext[3,13;3,3;;" .. hypertext_basic .. "]" .. - "container[0,18]".. - "box[1,2;3,2;#0a0a]".. - "scroll_container[1,2;3,2;scrbar2;horizontal;0.06]".. - "button[0,0;6,1;butnest;Nest]".. - "label[10,0.5;nest]".. - "scroll_container_end[]".. - "scrollbar[1,0;3.5,0.3;horizontal;scrbar2;0]".. - "container_end[]".. - "dropdown[0,6;2;hmdrpdwn;apple,bulb;1]".. - "image_button[0,4;2,2;testformspec_button_image.png;imagebutton;bbbbtt;false;true;testformspec_pressed.png]".. - "box[1,22.5;4,1;#a00a]".. - "scroll_container_end[]".. - "scrollbaroptions[max=170]".. -- lowest seen pos is: 0.1*170+6=23 (factor*max+height) - "scrollbar[7.5,0;0.3,4;vertical;scrbar;0]".. - "scrollbar[8,0;0.3,4;vertical;scrbarhmmm;0]".. - "dropdown[0,6;2;hmdrpdwnnn;Outside,of,container;1]" - ---style_type[label;textcolor=green] ---label[0,0;Green] ---style_type[label;textcolor=blue] ---label[0,1;Blue] ---style_type[label;textcolor=;border=true] ---label[1.2,0;Border] ---style_type[label;border=true;bgcolor=red] ---label[1.2,1;Background] ---style_type[label;border=;bgcolor=] ---label[0.75,2;Reset] - - -local pages = { - -- Real Coordinates - [[ - formspec_version[3] - size[12,13] - image_button[0,0;1,1;logo.png;rc_image_button_1x1;1x1] - image_button[1,0;2,2;logo.png;rc_image_button_2x2;2x2] - button[0,2;1,1;rc_button_1x1;1x1] - button[1,2;2,2;rc_button_2x2;2x2] - item_image[0,4;1,1;air] - item_image[1,4;2,2;air] - item_image_button[0,6;1,1;testformspec:node;rc_item_image_button_1x1;1x1] - item_image_button[1,6;2,2;testformspec:node;rc_item_image_button_2x2;2x2] - field[3,.5;3,.5;rc_field;Field;text] - pwdfield[6,.5;3,1;rc_pwdfield;Password Field] - field[3,1;3,1;;Read-Only Field;text] - textarea[3,2;3,.5;rc_textarea_small;Textarea;text] - textarea[6,2;3,2;rc_textarea_big;Textarea;text\nmore text] - textarea[3,3;3,1;;Read-Only Textarea;text\nmore text] - textlist[3,4;3,2;rc_textlist;Textlist,Perfect Coordinates;1;false] - tableoptions[highlight=#ABCDEF75;background=#00000055;border=false] - table[6,4;3,2;rc_table;Table,Cool Stuff,Foo,Bar;2] - dropdown[3,6;3,1;rc_dropdown_small;This,is,a,dropdown;1] - dropdown[6,6;3,2;rc_dropdown_big;I,am,a,bigger,dropdown;5] - image[0,8;3,2;ignore.png] - box[3,7;3,1;#00A3FF] - checkbox[3,8;rc_checkbox_1;Check me!;false] - checkbox[3,9;rc_checkbox_2;Uncheck me now!;true] - scrollbar[0,11.5;11.5,.5;horizontal;rc_scrollbar_horizontal;500] - scrollbar[11.5,0;.5,11.5;vertical;rc_scrollbar_vertical;0] - list[current_player;main;6,8;3,2;1] - button[9,0;2.5,1;rc_empty_button_1;] - button[9,1;2.5,1;rc_empty_button_2;] - button[9,2;2.5,1;rc_empty_button_3;] ]].. - "label[9,0.5;This is a label.\nLine\nLine\nLine\nEnd]".. - [[button[9,3;1,1;rc_empty_button_4;] - vertlabel[9,4;VERT] - label[10,3;HORIZ] - tabheader[8,0;6,0.65;rc_tabheader;Tab 1,Tab 2,Tab 3,Secrets;1;false;false] - ]], - -- Style - - "formspec_version[3]size[12,13]" .. - ("label[0.375,0.375;Styled - %s %s]"):format( - color("#F00", "red text"), - color("#77FF00CC", "green text")) .. - "label[6.375,0.375;Unstyled]" .. - "box[0,0.75;12,0.1;#999]" .. - "box[6,0.85;0.1,11.15;#999]" .. - "container[0.375,1.225]" .. - style_fs .. - "container_end[]container[6.375,1.225]" .. - style_fs:gsub("one_", "two_"):gsub("style%[[^%]]+%]", ""):gsub("style_type%[[^%]]+%]", "") .. - "container_end[]", - - -- Noclip - "formspec_version[3]size[12,13]" .. - "label[0.1,0.5;Clip]" .. - "container[-2.5,1]" .. clip_fs:gsub("%%c", "false") .. "container_end[]" .. - "label[11,0.5;Noclip]" .. - "container[11.5,1]" .. clip_fs:gsub("%%c", "true") .. "container_end[]", - - -- Hypertext - "size[12,13]real_coordinates[true]" .. - "container[0.5,0.5]" .. hypertext_fs .. "container_end[]", - - -- Tabheaders - "size[12,13]real_coordinates[true]" .. - "container[0.5,1.5]" .. tabheaders_fs .. "container_end[]", - - -- Animation - [[ - formspec_version[3] - size[12,13] - animated_image[0.5,0.5;1,1;;testformspec_animation.png;4;100] - animated_image[0.5,1.75;1,1;;testformspec_animation.jpg;4;100] - animated_image[1.75,0.5;1,1;;testformspec_animation.png;100;100] - animated_image[3,0.5;1,1;ani_img_1;testformspec_animation.png;4;1000] - button[4.25,0.5;1,1;ani_btn_1;Current -Number] - animated_image[3,1.75;1,1;ani_img_2;testformspec_animation.png;4;1000;2] - button[4.25,1.75;1,1;ani_btn_2;Current -Number] - animated_image[3,3;1,1;;testformspec_animation.png;4;0] - animated_image[3,4.25;1,1;;testformspec_animation.png;4;0;3] - animated_image[5.5,0.5;5,2;;testformspec_animation.png;4;100] - animated_image[5.5,2.75;5,2;;testformspec_animation.jpg;4;100] - ]], - - -- Scroll containers - "formspec_version[3]size[12,13]" .. - scroll_fs, -} - -local function show_test_formspec(pname, page_id) - page_id = page_id or 2 - - local fs = pages[page_id] .. "tabheader[0,0;8,0.65;maintabs;Real Coord,Styles,Noclip,Hypertext,Tabs,Anim,ScrollC;" .. page_id .. ";false;false]" - - minetest.show_formspec(pname, "testformspec:formspec", fs) -end - -minetest.register_on_player_receive_fields(function(player, formname, fields) - if formname ~= "testformspec:formspec" then - return false - end - - - if fields.maintabs then - show_test_formspec(player:get_player_name(), tonumber(fields.maintabs)) - return true - end - - if fields.ani_img_1 and fields.ani_btn_1 then - minetest.chat_send_player(player:get_player_name(), "ani_img_1 = " .. tostring(fields.ani_img_1)) - return true - elseif fields.ani_img_2 and fields.ani_btn_2 then - minetest.chat_send_player(player:get_player_name(), "ani_img_2 = " .. tostring(fields.ani_img_2)) - return true - end - - if fields.hypertext then - minetest.chat_send_player(player:get_player_name(), "Hypertext action received: " .. tostring(fields.hypertext)) - return true - end -end) - -minetest.register_chatcommand("test_formspec", { - params = "", - description = "Open the test formspec", - func = function(name) - if not minetest.get_player_by_name(name) then - return false, "You need to be online!" - end - - show_test_formspec(name) - return true - end, -}) diff --git a/games/minimal/mods/testformspec/init.lua b/games/minimal/mods/testformspec/init.lua deleted file mode 100644 index 23b565f08..000000000 --- a/games/minimal/mods/testformspec/init.lua +++ /dev/null @@ -1,3 +0,0 @@ -dofile(minetest.get_modpath("testformspec").."/dummy_items.lua") -dofile(minetest.get_modpath("testformspec").."/formspec.lua") -dofile(minetest.get_modpath("testformspec").."/callbacks.lua") diff --git a/games/minimal/mods/testformspec/mod.conf b/games/minimal/mods/testformspec/mod.conf deleted file mode 100644 index 00eac307a..000000000 --- a/games/minimal/mods/testformspec/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = testformspec -description = Contains an example formspec to test all the features of formspecs diff --git a/games/minimal/mods/testformspec/textures/testformspec_animation.jpg b/games/minimal/mods/testformspec/textures/testformspec_animation.jpg deleted file mode 100644 index b98ca2677..000000000 Binary files a/games/minimal/mods/testformspec/textures/testformspec_animation.jpg and /dev/null differ diff --git a/games/minimal/mods/testformspec/textures/testformspec_animation.png b/games/minimal/mods/testformspec/textures/testformspec_animation.png deleted file mode 100644 index b972e5dbb..000000000 Binary files a/games/minimal/mods/testformspec/textures/testformspec_animation.png and /dev/null differ diff --git a/games/minimal/mods/testformspec/textures/testformspec_bg.png b/games/minimal/mods/testformspec/textures/testformspec_bg.png deleted file mode 100644 index cd1e50900..000000000 Binary files a/games/minimal/mods/testformspec/textures/testformspec_bg.png and /dev/null differ diff --git a/games/minimal/mods/testformspec/textures/testformspec_bg_9slice.png b/games/minimal/mods/testformspec/textures/testformspec_bg_9slice.png deleted file mode 100644 index 34433ac82..000000000 Binary files a/games/minimal/mods/testformspec/textures/testformspec_bg_9slice.png and /dev/null differ diff --git a/games/minimal/mods/testformspec/textures/testformspec_bg_9slice_hovered.png b/games/minimal/mods/testformspec/textures/testformspec_bg_9slice_hovered.png deleted file mode 100644 index 01c2dc777..000000000 Binary files a/games/minimal/mods/testformspec/textures/testformspec_bg_9slice_hovered.png and /dev/null differ diff --git a/games/minimal/mods/testformspec/textures/testformspec_bg_9slice_pressed.png b/games/minimal/mods/testformspec/textures/testformspec_bg_9slice_pressed.png deleted file mode 100644 index 0cbac7536..000000000 Binary files a/games/minimal/mods/testformspec/textures/testformspec_bg_9slice_pressed.png and /dev/null differ diff --git a/games/minimal/mods/testformspec/textures/testformspec_bg_hovered.png b/games/minimal/mods/testformspec/textures/testformspec_bg_hovered.png deleted file mode 100644 index 3ebbb988c..000000000 Binary files a/games/minimal/mods/testformspec/textures/testformspec_bg_hovered.png and /dev/null differ diff --git a/games/minimal/mods/testformspec/textures/testformspec_bg_pressed.png b/games/minimal/mods/testformspec/textures/testformspec_bg_pressed.png deleted file mode 100644 index 2fb5fc21e..000000000 Binary files a/games/minimal/mods/testformspec/textures/testformspec_bg_pressed.png and /dev/null differ diff --git a/games/minimal/mods/testformspec/textures/testformspec_button_image.png b/games/minimal/mods/testformspec/textures/testformspec_button_image.png deleted file mode 100644 index 75c438a9a..000000000 Binary files a/games/minimal/mods/testformspec/textures/testformspec_button_image.png and /dev/null differ diff --git a/games/minimal/mods/testformspec/textures/testformspec_hovered.png b/games/minimal/mods/testformspec/textures/testformspec_hovered.png deleted file mode 100644 index 3ccad30a2..000000000 Binary files a/games/minimal/mods/testformspec/textures/testformspec_hovered.png and /dev/null differ diff --git a/games/minimal/mods/testformspec/textures/testformspec_item.png b/games/minimal/mods/testformspec/textures/testformspec_item.png deleted file mode 100644 index 4fd823b55..000000000 Binary files a/games/minimal/mods/testformspec/textures/testformspec_item.png and /dev/null differ diff --git a/games/minimal/mods/testformspec/textures/testformspec_node.png b/games/minimal/mods/testformspec/textures/testformspec_node.png deleted file mode 100644 index c107f28a3..000000000 Binary files a/games/minimal/mods/testformspec/textures/testformspec_node.png and /dev/null differ diff --git a/games/minimal/mods/testformspec/textures/testformspec_pressed.png b/games/minimal/mods/testformspec/textures/testformspec_pressed.png deleted file mode 100644 index 45c504f27..000000000 Binary files a/games/minimal/mods/testformspec/textures/testformspec_pressed.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/README.md b/games/minimal/mods/testnodes/README.md deleted file mode 100644 index 13ed972c0..000000000 --- a/games/minimal/mods/testnodes/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Test Nodes - -This mod contains a bunch of basic nodes to test development stuff. -Most nodes are kept as minimal as possible in order to show off one particular feature of the engine, to make testing stuff easier. - -This mod includes tests for: - -* drawtypes -* paramtype2's -* node properties such as damage, drowning, falling, etc. -* other random stuff diff --git a/games/minimal/mods/testnodes/drawtypes.lua b/games/minimal/mods/testnodes/drawtypes.lua deleted file mode 100644 index 35fda960f..000000000 --- a/games/minimal/mods/testnodes/drawtypes.lua +++ /dev/null @@ -1,517 +0,0 @@ ---[[ Drawtype Test: This file tests out and provides examples for -all drawtypes in Minetest. It is attempted to keep the node -definitions as simple and minimal as possible to keep -side-effects to a minimum. - -How to read the node definitions: -There are two parts which are separated by 2 newlines: -The first part contains the things that are more or less essential -for defining the drawtype (except description, which is -at the top for readability). -The second part (after the 2 newlines) contains stuff that are -unrelated to the drawtype, stuff that is mostly there to make -testing this node easier and more convenient. -]] - -local S = minetest.get_translator("testnodes") - --- If set to true, will show an inventory image for nodes that have no inventory image as of Minetest 5.1.0. --- This is due to . --- This is only added to make the items more visible to avoid confusion, but you will no longer see --- the default inventory images for these items. When you want to test the default inventory image of drawtypes, --- this should be turned off. --- TODO: Remove support for fallback inventory image as soon #9209 is fixed. -local SHOW_FALLBACK_IMAGE = minetest.settings:get_bool("testnodes_show_fallback_image", false) - -local fallback_image = function(img) - if SHOW_FALLBACK_IMAGE then - return img - else - return nil - end -end - --- A regular cube -minetest.register_node("testnodes:normal", { - description = S("Normal Drawtype Test Node"), - drawtype = "normal", - tiles = { "testnodes_normal.png" }, - - groups = { dig_immediate = 3 }, -}) - --- Standard glasslike node -minetest.register_node("testnodes:glasslike", { - description = S("Glasslike Drawtype Test Node"), - drawtype = "glasslike", - paramtype = "light", - tiles = { "testnodes_glasslike.png" }, - - groups = { dig_immediate = 3 }, -}) - --- Glasslike framed with the two textures (normal and "detail") -minetest.register_node("testnodes:glasslike_framed", { - description = S("Glasslike Framed Drawtype Test Node"), - drawtype = "glasslike_framed", - paramtype = "light", - tiles = { - "testnodes_glasslike_framed.png", - "testnodes_glasslike_detail.png", - }, - - - sunlight_propagates = true, - groups = { dig_immediate = 3 }, -}) - --- Like the one above, but without the "detail" texture (texture 2). --- This node was added to see how the engine behaves when the "detail" texture --- is missing. -minetest.register_node("testnodes:glasslike_framed_no_detail", { - description = S("Glasslike Framed without Detail Drawtype Test Node"), - drawtype = "glasslike_framed", - paramtype = "light", - tiles = { "testnodes_glasslike_framed2.png" }, - - - sunlight_propagates = true, - groups = { dig_immediate = 3 }, -}) - - -minetest.register_node("testnodes:glasslike_framed_optional", { - description = S("Glasslike Framed Optional Drawtype Test Node"), - drawtype = "glasslike_framed_optional", - paramtype = "light", - tiles = { - "testnodes_glasslike_framed_optional.png", - "testnodes_glasslike_detail.png", - }, - - - sunlight_propagates = true, - groups = { dig_immediate = 3 }, -}) - - - -minetest.register_node("testnodes:allfaces", { - description = S("Allfaces Drawtype Test Node"), - drawtype = "allfaces", - paramtype = "light", - tiles = { "testnodes_allfaces.png" }, - - groups = { dig_immediate = 3 }, -}) - -minetest.register_node("testnodes:allfaces_optional", { - description = S("Allfaces Optional Drawtype Test Node"), - drawtype = "allfaces_optional", - paramtype = "light", - tiles = { "testnodes_allfaces_optional.png" }, - - groups = { dig_immediate = 3 }, -}) - -minetest.register_node("testnodes:allfaces_optional_waving", { - description = S("Waving Allfaces Optional Drawtype Test Node"), - drawtype = "allfaces_optional", - paramtype = "light", - tiles = { "testnodes_allfaces_optional.png^[brighten" }, - waving = 2, - - groups = { dig_immediate = 3 }, -}) - -minetest.register_node("testnodes:firelike", { - description = S("Firelike Drawtype Test Node"), - drawtype = "firelike", - paramtype = "light", - tiles = { "testnodes_firelike.png" }, - - - walkable = false, - groups = { dig_immediate = 3 }, -}) - -minetest.register_node("testnodes:fencelike", { - description = S("Fencelike Drawtype Test Node"), - drawtype = "fencelike", - paramtype = "light", - tiles = { "testnodes_fencelike.png" }, - - groups = { dig_immediate = 3 }, -}) - -minetest.register_node("testnodes:torchlike", { - description = S("Wallmounted Torchlike Drawtype Test Node"), - drawtype = "torchlike", - paramtype = "light", - paramtype2 = "wallmounted", - tiles = { - "testnodes_torchlike_floor.png", - "testnodes_torchlike_ceiling.png", - "testnodes_torchlike_wall.png", - }, - - - walkable = false, - sunlight_propagates = true, - groups = { dig_immediate = 3 }, - inventory_image = fallback_image("testnodes_torchlike_floor.png"), -}) - -minetest.register_node("testnodes:signlike", { - description = S("Wallmounted Signlike Drawtype Test Node"), - drawtype = "signlike", - paramtype = "light", - paramtype2 = "wallmounted", - tiles = { "testnodes_signlike.png" }, - - - walkable = false, - groups = { dig_immediate = 3 }, - sunlight_propagates = true, - inventory_image = fallback_image("testnodes_signlike.png"), -}) - -minetest.register_node("testnodes:plantlike", { - description = S("Plantlike Drawtype Test Node"), - drawtype = "plantlike", - paramtype = "light", - tiles = { "testnodes_plantlike.png" }, - - - walkable = false, - sunlight_propagates = true, - groups = { dig_immediate = 3 }, -}) - -minetest.register_node("testnodes:plantlike_waving", { - description = S("Waving Plantlike Drawtype Test Node"), - drawtype = "plantlike", - paramtype = "light", - tiles = { "testnodes_plantlike_waving.png" }, - waving = 1, - - - walkable = false, - sunlight_propagates = true, - groups = { dig_immediate = 3 }, -}) - - - --- param2 will rotate -minetest.register_node("testnodes:plantlike_degrotate", { - description = S("Degrotate Plantlike Drawtype Test Node"), - drawtype = "plantlike", - paramtype = "light", - paramtype2 = "degrotate", - tiles = { "testnodes_plantlike_degrotate.png" }, - - - walkable = false, - sunlight_propagates = true, - groups = { dig_immediate = 3 }, -}) - --- param2 will change height -minetest.register_node("testnodes:plantlike_leveled", { - description = S("Leveled Plantlike Drawtype Test Node"), - drawtype = "plantlike", - paramtype = "light", - paramtype2 = "leveled", - tiles = { - { name = "testnodes_plantlike_leveled.png", tileable_vertical = true }, - }, - - - -- We set a default param2 here only for convenience, to make the "plant" visible after placement - place_param2 = 8, - walkable = false, - sunlight_propagates = true, - groups = { dig_immediate = 3 }, -}) - --- param2 changes shape -minetest.register_node("testnodes:plantlike_meshoptions", { - description = S("Meshoptions Plantlike Drawtype Test Node"), - drawtype = "plantlike", - paramtype = "light", - paramtype2 = "meshoptions", - tiles = { "testnodes_plantlike_meshoptions.png" }, - - - walkable = false, - groups = { dig_immediate = 3 }, -}) - -minetest.register_node("testnodes:plantlike_rooted", { - description = S("Rooted Plantlike Drawtype Test Node"), - drawtype = "plantlike_rooted", - paramtype = "light", - tiles = { "testnodes_plantlike_rooted_base.png" }, - special_tiles = { "testnodes_plantlike_rooted.png" }, - - groups = { dig_immediate = 3 }, -}) - -minetest.register_node("testnodes:plantlike_rooted_waving", { - description = S("Waving Rooted Plantlike Drawtype Test Node"), - drawtype = "plantlike_rooted", - paramtype = "light", - tiles = { - "testnodes_plantlike_rooted_base.png", - "testnodes_plantlike_rooted_base.png", - "testnodes_plantlike_rooted_base_side_waving.png", - }, - special_tiles = { "testnodes_plantlike_rooted_waving.png" }, - waving = 1, - - groups = { dig_immediate = 3 }, -}) - --- param2 changes height -minetest.register_node("testnodes:plantlike_rooted_leveled", { - description = S("Leveled Rooted Plantlike Drawtype Test Node"), - drawtype = "plantlike_rooted", - paramtype = "light", - paramtype2 = "leveled", - tiles = { - "testnodes_plantlike_rooted_base.png", - "testnodes_plantlike_rooted_base.png", - "testnodes_plantlike_rooted_base_side_leveled.png", - }, - special_tiles = { - { name = "testnodes_plantlike_rooted_leveled.png", tileable_vertical = true }, - }, - - - -- We set a default param2 here only for convenience, to make the "plant" visible after placement - place_param2 = 8, - groups = { dig_immediate = 3 }, -}) - --- param2 changes shape -minetest.register_node("testnodes:plantlike_rooted_meshoptions", { - description = S("Meshoptions Rooted Plantlike Drawtype Test Node"), - drawtype = "plantlike_rooted", - paramtype = "light", - paramtype2 = "meshoptions", - tiles = { - "testnodes_plantlike_rooted_base.png", - "testnodes_plantlike_rooted_base.png", - "testnodes_plantlike_rooted_base_side_meshoptions.png", - }, - special_tiles = { - "testnodes_plantlike_rooted_meshoptions.png", - }, - - groups = { dig_immediate = 3 }, -}) - --- param2 changes rotation -minetest.register_node("testnodes:plantlike_rooted_degrotate", { - description = S("Degrotate Rooted Plantlike Drawtype Test Node"), - drawtype = "plantlike_rooted", - paramtype = "light", - paramtype2 = "degrotate", - tiles = { - "testnodes_plantlike_rooted_base.png", - "testnodes_plantlike_rooted_base.png", - "testnodes_plantlike_rooted_base_side_degrotate.png", - }, - special_tiles = { - "testnodes_plantlike_rooted_degrotate.png", - }, - - groups = { dig_immediate = 3 }, -}) - --- Demonstrative liquid nodes, source and flowing form. This is only the --- drawtype, no physical liquid properties are used -minetest.register_node("testnodes:liquid", { - description = S("Source Liquid Drawtype Test Node"), - drawtype = "liquid", - paramtype = "light", - tiles = { - "testnodes_liquidsource.png", - }, - special_tiles = { - {name="testnodes_liquidsource.png", backface_culling=false}, - {name="testnodes_liquidsource.png", backface_culling=true}, - }, - use_texture_alpha = true, - - - walkable = false, - liquid_alternative_flowing = "testnodes:liquid_flowing", - liquid_alternative_source = "testnodes:liquid", - groups = { dig_immediate = 3 }, -}) -minetest.register_node("testnodes:liquid_flowing", { - description = S("Flowing Liquid Drawtype Test Node"), - drawtype = "flowingliquid", - paramtype = "light", - paramtype2 = "flowingliquid", - tiles = { - "testnodes_liquidflowing.png", - }, - special_tiles = { - {name="testnodes_liquidflowing.png", backface_culling=false}, - {name="testnodes_liquidflowing.png", backface_culling=false}, - }, - use_texture_alpha = true, - - - walkable = false, - liquid_alternative_flowing = "testnodes:liquid_flowing", - liquid_alternative_source = "testnodes:liquid", - groups = { dig_immediate = 3 }, -}) -minetest.register_node("testnodes:liquid_waving", { - description = S("Waving Source Liquid Drawtype Test Node"), - drawtype = "liquid", - paramtype = "light", - tiles = { - "testnodes_liquidsource.png^[brighten", - }, - special_tiles = { - {name="testnodes_liquidsource.png^[brighten", backface_culling=false}, - {name="testnodes_liquidsource.png^[brighten", backface_culling=true}, - }, - use_texture_alpha = true, - waving = 3, - - - walkable = false, - liquid_alternative_flowing = "testnodes:liquid_flowing", - liquid_alternative_source = "testnodes:liquid", - groups = { dig_immediate = 3 }, -}) -minetest.register_node("testnodes:liquid_flowing_waving", { - description = S("Waving Flowing Liquid Drawtype Test Node"), - drawtype = "flowingliquid", - paramtype = "light", - paramtype2 = "flowingliquid", - tiles = { - "testnodes_liquidflowing.png^[brighten", - }, - special_tiles = { - {name="testnodes_liquidflowing.png^[brighten", backface_culling=false}, - {name="testnodes_liquidflowing.png^[brighten", backface_culling=false}, - }, - use_texture_alpha = true, - waving = 3, - - - walkable = false, - liquid_alternative_flowing = "testnodes:liquid_flowing", - liquid_alternative_source = "testnodes:liquid", - groups = { dig_immediate = 3 }, -}) - - - --- Invisible node -minetest.register_node("testnodes:airlike", { - description = S("Airlike Drawtype Test Node"), - drawtype = "airlike", - paramtype = "light", - - - walkable = false, - groups = { dig_immediate = 3 }, - sunlight_propagates = true, - inventory_image = fallback_image("testnodes_airlike.png"), -}) - --- param2 changes liquid height -minetest.register_node("testnodes:glassliquid", { - description = S("Glasslike Liquid Level Drawtype Test Node"), - drawtype = "glasslike_framed", - paramtype = "light", - paramtype2 = "glasslikeliquidlevel", - tiles = { - "testnodes_glasslikeliquid.png", - }, - special_tiles = { - "testnodes_liquid.png", - }, - - groups = { dig_immediate = 3 }, -}) - --- Adding many raillike examples, primarily to demonstrate the behavior of --- "raillike groups". Nodes of the same type (rail, groupless, line, street) --- should connect to nodes of the same "rail type" (=same shape, different --- color) only. -local rails = { - { "rail", {"testnodes_rail_straight.png", "testnodes_rail_curved.png", "testnodes_rail_t_junction.png", "testnodes_rail_crossing.png"} }, - { "line", {"testnodes_line_straight.png", "testnodes_line_curved.png", "testnodes_line_t_junction.png", "testnodes_line_crossing.png"}, }, - { "street", {"testnodes_street_straight.png", "testnodes_street_curved.png", "testnodes_street_t_junction.png", "testnodes_street_crossing.png"}, }, - -- the "groupless" nodes are nodes in which the "connect_to_raillike" group is not set - { "groupless", {"testnodes_rail2_straight.png", "testnodes_rail2_curved.png", "testnodes_rail2_t_junction.png", "testnodes_rail2_crossing.png"} }, -} -local colors = { "", "cyan", "red" } - -for r=1, #rails do - local id = rails[r][1] - local tiles = rails[r][2] - local raillike_group - if id ~= "groupless" then - raillike_group = minetest.raillike_group(id) - end - for c=1, #colors do - local color - if colors[c] ~= "" then - color = colors[c] - end - minetest.register_node("testnodes:raillike_"..id..c, { - description = S("Raillike Drawtype Test Node: @1 @2", id, c), - drawtype = "raillike", - paramtype = "light", - tiles = tiles, - groups = { connect_to_raillike = raillike_group, dig_immediate = 3 }, - - - color = color, - selection_box = { - type = "fixed", - fixed = {{-0.5, -0.5, -0.5, 0.5, -0.4, 0.5}}, - }, - sunlight_propagates = true, - walkable = false, - }) - end -end - - - --- Add visual_scale variants of previous nodes for half and double size -local scale = function(subname, desc_double, desc_half) - local original = "testnodes:"..subname - local def = table.copy(minetest.registered_items[original]) - def.visual_scale = 2.0 - def.description = desc_double - minetest.register_node("testnodes:"..subname.."_double", def) - def = table.copy(minetest.registered_items[original]) - def.visual_scale = 0.5 - def.description = desc_half - minetest.register_node("testnodes:"..subname.."_half", def) -end - -scale("plantlike", - S("Double-sized Plantlike Drawtype Test Node"), - S("Half-sized Plantlike Drawtype Test Node")) -scale("torchlike", - S("Double-sized Wallmounted Torchlike Drawtype Test Node"), - S("Half-sized Wallmounted Torchlike Drawtype Test Node")) -scale("signlike", - S("Double-sized Wallmounted Signlike Drawtype Test Node"), - S("Half-sized Wallmounted Signlike Drawtype Test Node")) -scale("firelike", - S("Double-sized Firelike Drawtype Test Node"), - S("Half-sized Firelike Drawtype Test Node")) diff --git a/games/minimal/mods/testnodes/init.lua b/games/minimal/mods/testnodes/init.lua deleted file mode 100644 index 92e2c5630..000000000 --- a/games/minimal/mods/testnodes/init.lua +++ /dev/null @@ -1,10 +0,0 @@ -local path = minetest.get_modpath(minetest.get_current_modname()) - -dofile(path.."/drawtypes.lua") -dofile(path.."/meshes.lua") -dofile(path.."/nodeboxes.lua") -dofile(path.."/param2.lua") -dofile(path.."/properties.lua") -dofile(path.."/liquids.lua") -dofile(path.."/light.lua") -dofile(path.."/textures.lua") diff --git a/games/minimal/mods/testnodes/light.lua b/games/minimal/mods/testnodes/light.lua deleted file mode 100644 index 94409e83f..000000000 --- a/games/minimal/mods/testnodes/light.lua +++ /dev/null @@ -1,48 +0,0 @@ --- Test Nodes: Light test - -local S = minetest.get_translator("testnodes") - --- All possible light levels -for i=1, minetest.LIGHT_MAX do - minetest.register_node("testnodes:light"..i, { - description = S("Light Source (@1)", i), - paramtype = "light", - light_source = i, - - - tiles ={"testnodes_light_"..i..".png"}, - drawtype = "glasslike", - walkable = false, - sunlight_propagates = true, - is_ground_content = false, - groups = {dig_immediate=3}, - }) -end - --- Lets light through, but not sunlight, leading to a --- reduction in light level when light passes through -minetest.register_node("testnodes:sunlight_filter", { - description = S("Sunlight Filter"), - paramtype = "light", - - - drawtype = "glasslike", - tiles = { - "testnodes_sunlight_filter.png", - }, - groups = { dig_immediate = 3 }, -}) - --- Lets light and sunlight through without obstruction -minetest.register_node("testnodes:sunlight_propagator", { - description = S("Sunlight Propagator"), - paramtype = "light", - sunlight_propagates = true, - - - drawtype = "glasslike", - tiles = { - "testnodes_sunlight_filter.png^[brighten", - }, - groups = { dig_immediate = 3 }, -}) diff --git a/games/minimal/mods/testnodes/liquids.lua b/games/minimal/mods/testnodes/liquids.lua deleted file mode 100644 index e316782ad..000000000 --- a/games/minimal/mods/testnodes/liquids.lua +++ /dev/null @@ -1,91 +0,0 @@ --- Add liquids for ranges and viscosity levels 0-8 - -for d=0, 8 do - minetest.register_node("testnodes:rliquid_"..d, { - description = "Test Liquid Source, Range "..d, - drawtype = "liquid", - tiles = {"testnodes_liquidsource_r"..d..".png"}, - special_tiles = { - {name = "testnodes_liquidsource_r"..d..".png", backface_culling = false}, - {name = "testnodes_liquidsource_r"..d..".png", backface_culling = true}, - }, - alpha = 192, - paramtype = "light", - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, - is_ground_content = false, - liquidtype = "source", - liquid_alternative_flowing = "testnodes:rliquid_flowing_"..d, - liquid_alternative_source = "testnodes:rliquid_"..d, - liquid_range = d, - }) - - minetest.register_node("testnodes:rliquid_flowing_"..d, { - description = "Flowing Test Liquid, Range "..d, - drawtype = "flowingliquid", - tiles = {"testnodes_liquidflowing_r"..d..".png"}, - special_tiles = { - {name = "testnodes_liquidflowing_r"..d..".png", backface_culling = false}, - {name = "testnodes_liquidflowing_r"..d..".png", backface_culling = false}, - }, - alpha = 192, - paramtype = "light", - paramtype2 = "flowingliquid", - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, - is_ground_content = false, - liquidtype = "flowing", - liquid_alternative_flowing = "testnodes:rliquid_flowing_"..d, - liquid_alternative_source = "testnodes:rliquid_"..d, - liquid_range = d, - }) - - local mod = "^[colorize:#000000:127" - minetest.register_node("testnodes:vliquid_"..d, { - description = "Test Liquid Source, Viscosity "..d, - drawtype = "liquid", - tiles = {"testnodes_liquidsource_r"..d..".png"..mod}, - special_tiles = { - {name = "testnodes_liquidsource_r"..d..".png"..mod, backface_culling = false}, - {name = "testnodes_liquidsource_r"..d..".png"..mod, backface_culling = true}, - }, - alpha = 192, - paramtype = "light", - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, - is_ground_content = false, - liquidtype = "source", - liquid_alternative_flowing = "testnodes:vliquid_flowing_"..d, - liquid_alternative_source = "testnodes:vliquid_"..d, - liquid_viscosity = d, - }) - - minetest.register_node("testnodes:vliquid_flowing_"..d, { - description = "Flowing Test Liquid, Viscosity "..d, - drawtype = "flowingliquid", - tiles = {"testnodes_liquidflowing_r"..d..".png"..mod}, - special_tiles = { - {name = "testnodes_liquidflowing_r"..d..".png"..mod, backface_culling = false}, - {name = "testnodes_liquidflowing_r"..d..".png"..mod, backface_culling = false}, - }, - alpha = 192, - paramtype = "light", - paramtype2 = "flowingliquid", - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, - is_ground_content = false, - liquidtype = "flowing", - liquid_alternative_flowing = "testnodes:vliquid_flowing_"..d, - liquid_alternative_source = "testnodes:vliquid_"..d, - liquid_viscosity = d, - }) - -end diff --git a/games/minimal/mods/testnodes/meshes.lua b/games/minimal/mods/testnodes/meshes.lua deleted file mode 100644 index 900abc180..000000000 --- a/games/minimal/mods/testnodes/meshes.lua +++ /dev/null @@ -1,145 +0,0 @@ --- Meshes - -local S = minetest.get_translator("testnodes") - -local ocorner_cbox = { - type = "fixed", - fixed = { - {-0.5, -0.5, -0.5, 0.5, -0.25, 0.5}, - {-0.5, -0.25, -0.25, 0.25, 0, 0.5}, - {-0.5, 0, 0, 0, 0.25, 0.5}, - {-0.5, 0.25, 0.25, -0.25, 0.5, 0.5} - } -} - -local tall_pyr_cbox = { - type = "fixed", - fixed = { - { -0.5, -0.5, -0.5, 0.5, -0.25, 0.5 }, - { -0.375, -0.25, -0.375, 0.375, 0, 0.375}, - { -0.25, 0, -0.25, 0.25, 0.25, 0.25}, - { -0.125, 0.25, -0.125, 0.125, 0.5, 0.125} - } -} - --- Normal mesh -minetest.register_node("testnodes:mesh", { - description = S("Mesh Test Node"), - drawtype = "mesh", - mesh = "testnodes_pyramid.obj", - tiles = {"testnodes_mesh_stripes2.png"}, - paramtype = "light", - collision_box = tall_pyr_cbox, - - groups = {dig_immediate=3}, -}) - --- Facedir mesh: outer corner slope -minetest.register_node("testnodes:mesh_facedir", { - description = S("Facedir Mesh Test Node"), - drawtype = "mesh", - mesh = "testnodes_ocorner.obj", - tiles = {"testnodes_mesh_stripes.png"}, - paramtype = "light", - paramtype2 = "facedir", - collision_box = ocorner_cbox, - - groups = {dig_immediate=3}, -}) - -minetest.register_node("testnodes:mesh_colorfacedir", { - description = S("Color Facedir Mesh Test Node"), - drawtype = "mesh", - mesh = "testnodes_ocorner.obj", - tiles = {"testnodes_mesh_stripes3.png"}, - paramtype = "light", - paramtype2 = "colorfacedir", - palette = "testnodes_palette_facedir.png", - collision_box = ocorner_cbox, - - groups = {dig_immediate=3}, -}) - --- Wallmounted mesh: pyramid -minetest.register_node("testnodes:mesh_wallmounted", { - description = S("Wallmounted Mesh Test Node"), - drawtype = "mesh", - mesh = "testnodes_pyramid.obj", - tiles = {"testnodes_mesh_stripes2.png"}, - paramtype = "light", - paramtype2 = "wallmounted", - collision_box = tall_pyr_cbox, - - groups = {dig_immediate=3}, -}) - -minetest.register_node("testnodes:mesh_colorwallmounted", { - description = S("Color Wallmounted Mesh Test Node"), - drawtype = "mesh", - mesh = "testnodes_pyramid.obj", - tiles = {"testnodes_mesh_stripes3.png"}, - paramtype = "light", - paramtype2 = "colorwallmounted", - palette = "testnodes_palette_wallmounted.png", - collision_box = tall_pyr_cbox, - - groups = {dig_immediate=3}, -}) - - -minetest.register_node("testnodes:mesh_double", { - description = S("Double-sized Mesh Test Node"), - drawtype = "mesh", - mesh = "testnodes_pyramid.obj", - tiles = {"testnodes_mesh_stripes2.png"}, - paramtype = "light", - collision_box = tall_pyr_cbox, - visual_scale = 2, - - groups = {dig_immediate=3}, -}) -minetest.register_node("testnodes:mesh_half", { - description = S("Half-sized Mesh Test Node"), - drawtype = "mesh", - mesh = "testnodes_pyramid.obj", - tiles = {"testnodes_mesh_stripes2.png"}, - paramtype = "light", - collision_box = tall_pyr_cbox, - visual_scale = 0.5, - - groups = {dig_immediate=3}, -}) - -minetest.register_node("testnodes:mesh_waving1", { - description = S("Plantlike-waving Mesh Test Node"), - drawtype = "mesh", - mesh = "testnodes_pyramid.obj", - tiles = {"testnodes_mesh_stripes4.png^[multiply:#B0FFB0"}, - paramtype = "light", - collision_box = tall_pyr_cbox, - waving = 1, - - groups = {dig_immediate=3}, -}) -minetest.register_node("testnodes:mesh_waving2", { - description = S("Leaflike-waving Mesh Test Node"), - drawtype = "mesh", - mesh = "testnodes_pyramid.obj", - tiles = {"testnodes_mesh_stripes4.png^[multiply:#FFFFB0"}, - paramtype = "light", - collision_box = tall_pyr_cbox, - waving = 2, - - groups = {dig_immediate=3}, -}) -minetest.register_node("testnodes:mesh_waving3", { - description = S("Liquidlike-waving Mesh Test Node"), - drawtype = "mesh", - mesh = "testnodes_pyramid.obj", - tiles = {"testnodes_mesh_stripes4.png^[multiply:#B0B0FF"}, - paramtype = "light", - collision_box = tall_pyr_cbox, - waving = 3, - - groups = {dig_immediate=3}, -}) diff --git a/games/minimal/mods/testnodes/mod.conf b/games/minimal/mods/testnodes/mod.conf deleted file mode 100644 index 4824c6ed0..000000000 --- a/games/minimal/mods/testnodes/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = testnodes -description = Contains a bunch of basic example nodes for demonstrative purposes, development and testing diff --git a/games/minimal/mods/testnodes/models/testnodes_ocorner.obj b/games/minimal/mods/testnodes/models/testnodes_ocorner.obj deleted file mode 100644 index 231d7056b..000000000 --- a/games/minimal/mods/testnodes/models/testnodes_ocorner.obj +++ /dev/null @@ -1,23 +0,0 @@ -# Blender v2.73 (sub 0) OBJ File: 'slope_test_ocorner_onetexture.blend' -# www.blender.org -o Cube_Cube.002 -v 0.500000 0.500000 0.500000 -v -0.500000 -0.500000 0.500000 -v 0.500000 -0.500000 0.500000 -v -0.500000 -0.500000 -0.500000 -v 0.500000 -0.500000 -0.500000 -vt 1.000000 1.000000 -vt 0.000000 1.000000 -vt 0.000000 0.000000 -vt 1.000000 0.000000 -vn 0.000000 -1.000000 -0.000000 -vn 1.000000 0.000000 0.000000 -vn 0.000000 -0.000000 1.000000 -vn -0.707100 0.707100 0.000000 -vn 0.000000 0.707100 -0.707100 -s off -f 3/1/1 2/2/1 4/3/1 5/4/1 -f 1/2/2 3/3/2 5/4/2 -f 1/1/3 2/3/3 3/4/3 -f 1/1/4 4/3/4 2/4/4 -f 1/2/5 5/3/5 4/4/5 diff --git a/games/minimal/mods/testnodes/models/testnodes_pyramid.obj b/games/minimal/mods/testnodes/models/testnodes_pyramid.obj deleted file mode 100644 index b305af2f8..000000000 --- a/games/minimal/mods/testnodes/models/testnodes_pyramid.obj +++ /dev/null @@ -1,24 +0,0 @@ -# Blender v2.73 (sub 0) OBJ File: 'slope_test_pyramid_onetexture.blend' -# www.blender.org -o Cube -v 0.500000 -0.500000 -0.500000 -v 0.500000 -0.500000 0.500000 -v -0.500000 -0.500000 0.500000 -v -0.500000 -0.500000 -0.500000 -v -0.000000 0.500000 -0.000000 -vt 1.000000 1.000000 -vt 0.000000 1.000000 -vt 0.000000 0.000000 -vt 1.000000 0.000000 -vt 0.500000 1.000000 -vn 0.000000 -1.000000 0.000000 -vn -0.894400 0.447200 -0.000000 -vn 0.000000 0.447200 -0.894400 -vn 0.894400 0.447200 0.000000 -vn -0.000000 0.447200 0.894400 -s off -f 1/1/1 2/2/1 3/3/1 4/4/1 -f 3/4/2 5/5/2 4/3/2 -f 5/5/3 1/3/3 4/4/3 -f 1/4/4 5/5/4 2/3/4 -f 2/4/5 5/5/5 3/3/5 diff --git a/games/minimal/mods/testnodes/nodeboxes.lua b/games/minimal/mods/testnodes/nodeboxes.lua deleted file mode 100644 index ebd858337..000000000 --- a/games/minimal/mods/testnodes/nodeboxes.lua +++ /dev/null @@ -1,80 +0,0 @@ -local S = minetest.get_translator("testnodes") - --- Nodebox examples and tests. - --- An simple example nodebox with one centered box -minetest.register_node("testnodes:nodebox_fixed", { - description = S("Fixed Nodebox Test Node"), - tiles = {"testnodes_nodebox.png"}, - drawtype = "nodebox", - paramtype = "light", - node_box = { - type = "fixed", - fixed = {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25}, - }, - - groups = {dig_immediate=3}, -}) - --- 50% higher than a regular node -minetest.register_node("testnodes:nodebox_overhigh", { - description = S("Overhigh Nodebox Test Node"), - tiles = {"testnodes_nodebox.png"}, - drawtype = "nodebox", - paramtype = "light", - node_box = { - type = "fixed", - fixed = {-0.5, -0.5, -0.5, 0.5, 1, 0.5}, - }, - - groups = {dig_immediate=3}, -}) - --- 100% higher than a regular node -minetest.register_node("testnodes:nodebox_overhigh2", { - description = S("Double-height Nodebox Test Node"), - tiles = {"testnodes_nodebox.png"}, - drawtype = "nodebox", - paramtype = "light", - node_box = { - type = "fixed", - fixed = {-0.5, -0.5, -0.5, 0.5, 1.5, 0.5}, - }, - - groups = {dig_immediate=3}, -}) - --- Height of nodebox changes with its param2 value -minetest.register_node("testnodes:nodebox_leveled", { - description = S("Leveled Nodebox Test Node"), - tiles = {"testnodes_nodebox.png"}, - drawtype = "nodebox", - paramtype = "light", - paramtype2 = "leveled", - node_box = { - type = "leveled", - fixed = {-0.5, 0.0, -0.5, 0.5, -0.499, 0.5}, - }, - - groups = {dig_immediate=3}, -}) - --- Wall-like nodebox that connects to neighbors -minetest.register_node("testnodes:nodebox_connected", { - description = S("Connected Nodebox Test Node"), - tiles = {"testnodes_nodebox.png"}, - groups = {connected_nodebox=1, dig_immediate=3}, - drawtype = "nodebox", - paramtype = "light", - connects_to = {"group:connected_nodebox"}, - connect_sides = {"front", "back", "left", "right"}, - node_box = { - type = "connected", - fixed = {-0.125, -0.500, -0.125, 0.125, 0.500, 0.125}, - connect_front = {-0.125, -0.500, -0.500, 0.125, 0.400, -0.125}, - connect_back = {-0.125, -0.500, 0.125, 0.125, 0.400, 0.500}, - connect_left = {-0.500, -0.500, -0.125, -0.125, 0.400, 0.125}, - connect_right = {0.125, -0.500, -0.125, 0.500, 0.400, 0.125}, - }, -}) - diff --git a/games/minimal/mods/testnodes/param2.lua b/games/minimal/mods/testnodes/param2.lua deleted file mode 100644 index 5d64376fa..000000000 --- a/games/minimal/mods/testnodes/param2.lua +++ /dev/null @@ -1,168 +0,0 @@ --- This file is for misc. param2 tests that aren't covered in drawtypes.lua already. - -local S = minetest.get_translator("testnodes") - -minetest.register_node("testnodes:facedir", { - description = S("Facedir Test Node"), - paramtype2 = "facedir", - tiles = { - "testnodes_1.png", - "testnodes_2.png", - "testnodes_3.png", - "testnodes_4.png", - "testnodes_5.png", - "testnodes_6.png", - }, - - groups = { dig_immediate = 3 }, -}) - -minetest.register_node("testnodes:facedir_nodebox", { - description = S("Facedir Nodebox Test Node"), - tiles = { - "testnodes_1.png", - "testnodes_2.png", - "testnodes_3.png", - "testnodes_4.png", - "testnodes_5.png", - "testnodes_6.png", - }, - drawtype = "nodebox", - paramtype = "light", - paramtype2 = "facedir", - node_box = { - type = "fixed", - fixed = {-0.5, -0.5, -0.5, 0.2, 0.2, 0.2}, - }, - - groups = {dig_immediate=3}, -}) - -minetest.register_node("testnodes:wallmounted", { - description = S("Wallmounted Test Node"), - paramtype2 = "wallmounted", - tiles = { - "testnodes_1w.png", - "testnodes_2w.png", - "testnodes_3w.png", - "testnodes_4w.png", - "testnodes_5w.png", - "testnodes_6w.png", - }, - - groups = { dig_immediate = 3 }, -}) - -minetest.register_node("testnodes:wallmounted_nodebox", { - description = S("Wallmounted Nodebox Test Node"), - paramtype2 = "wallmounted", - paramtype = "light", - tiles = { - "testnodes_1w.png", - "testnodes_2w.png", - "testnodes_3w.png", - "testnodes_4w.png", - "testnodes_5w.png", - "testnodes_6w.png", - }, - drawtype = "nodebox", - node_box = { - type = "wallmounted", - wall_top = { -0.5, 0, -0.5, 0.5, 0.5, 0.5 }, - wall_bottom = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }, - wall_side = { -0.5, -0.5, -0.5, 0, 0.5, 0.5 }, - }, - - groups = { dig_immediate = 3 }, -}) - -minetest.register_node("testnodes:color", { - description = S("Color Test Node"), - paramtype2 = "color", - palette = "testnodes_palette_full.png", - tiles = { - "testnodes_node.png", - }, - - groups = { dig_immediate = 3 }, -}) - -minetest.register_node("testnodes:colorfacedir", { - description = S("Color Facedir Test Node"), - paramtype2 = "colorfacedir", - palette = "testnodes_palette_facedir.png", - tiles = { - "testnodes_1g.png", - "testnodes_2g.png", - "testnodes_3g.png", - "testnodes_4g.png", - "testnodes_5g.png", - "testnodes_6g.png", - }, - - groups = { dig_immediate = 3 }, -}) - -minetest.register_node("testnodes:colorfacedir_nodebox", { - description = S("Color Facedir Nodebox Test Node"), - tiles = { - "testnodes_1g.png", - "testnodes_2g.png", - "testnodes_3g.png", - "testnodes_4g.png", - "testnodes_5g.png", - "testnodes_6g.png", - }, - drawtype = "nodebox", - paramtype = "light", - paramtype2 = "colorfacedir", - palette = "testnodes_palette_facedir.png", - node_box = { - type = "fixed", - fixed = {-0.5, -0.5, -0.5, 0.2, 0.2, 0.2}, - }, - - groups = {dig_immediate=3}, -}) - -minetest.register_node("testnodes:colorwallmounted", { - description = S("Color Wallmounted Test Node"), - paramtype2 = "colorwallmounted", - paramtype = "light", - palette = "testnodes_palette_wallmounted.png", - tiles = { - "testnodes_1wg.png", - "testnodes_2wg.png", - "testnodes_3wg.png", - "testnodes_4wg.png", - "testnodes_5wg.png", - "testnodes_6wg.png", - }, - - groups = { dig_immediate = 3 }, -}) - -minetest.register_node("testnodes:colorwallmounted_nodebox", { - description = S("Color Wallmounted Nodebox Test Node"), - paramtype2 = "colorwallmounted", - paramtype = "light", - palette = "testnodes_palette_wallmounted.png", - tiles = { - "testnodes_1wg.png", - "testnodes_2wg.png", - "testnodes_3wg.png", - "testnodes_4wg.png", - "testnodes_5wg.png", - "testnodes_6wg.png", - }, - drawtype = "nodebox", - node_box = { - type = "wallmounted", - wall_top = { -0.5, 0, -0.5, 0.5, 0.5, 0.5 }, - wall_bottom = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }, - wall_side = { -0.5, -0.5, -0.5, 0, 0.5, 0.5 }, - }, - - groups = { dig_immediate = 3 }, -}) - diff --git a/games/minimal/mods/testnodes/properties.lua b/games/minimal/mods/testnodes/properties.lua deleted file mode 100644 index e169d4b08..000000000 --- a/games/minimal/mods/testnodes/properties.lua +++ /dev/null @@ -1,270 +0,0 @@ --- Test Nodes: Node property tests - -local S = minetest.get_translator("testnodes") - --- Is supposed to fall when it doesn't rest on solid ground -minetest.register_node("testnodes:falling", { - description = S("Falling Node"), - tiles = { - "testnodes_node.png", - "testnodes_node.png", - "testnodes_node_falling.png", - }, - groups = { falling_node = 1, dig_immediate = 3 }, -}) - --- Same as falling node, but will stop falling on top of liquids -minetest.register_node("testnodes:falling_float", { - description = S("Falling+Floating Node"), - groups = { falling_node = 1, float = 1, dig_immediate = 3 }, - - - tiles = { - "testnodes_node.png", - "testnodes_node.png", - "testnodes_node_falling.png", - }, - color = "cyan", -}) - --- This node attaches to the floor and drops as item --- when the floor is gone. -minetest.register_node("testnodes:attached", { - description = S("Floor-Attached Node"), - tiles = { - "testnodes_attached_top.png", - "testnodes_attached_bottom.png", - "testnodes_attached_side.png", - }, - groups = { attached_node = 1, dig_immediate = 3 }, -}) - --- This node attaches to the side of a node and drops as item --- when the node it attaches to is gone. -minetest.register_node("testnodes:attached_wallmounted", { - description = S("Wallmounted Attached Node"), - paramtype2 = "wallmounted", - tiles = { - "testnodes_attachedw_top.png", - "testnodes_attachedw_bottom.png", - "testnodes_attachedw_side.png", - }, - groups = { attached_node = 1, dig_immediate = 3 }, -}) - --- Jump disabled -minetest.register_node("testnodes:nojump", { - description = S("Non-jumping Node"), - groups = {disable_jump=1, dig_immediate=3}, - - - tiles = {"testnodes_nojump_top.png", "testnodes_nojump_side.png"}, -}) - --- Climbable up and down with jump and sneak keys -minetest.register_node("testnodes:climbable", { - description = S("Climbable Node"), - climbable = true, - walkable = false, - - - paramtype = "light", - sunlight_propagates = true, - is_ground_content = false, - tiles ={"testnodes_climbable_side.png"}, - drawtype = "glasslike", - groups = {dig_immediate=3}, -}) - --- Climbable only downwards with sneak key -minetest.register_node("testnodes:climbable_nojump", { - description = S("Downwards-climbable Node"), - climbable = true, - walkable = false, - - groups = {disable_jump=1, dig_immediate=3}, - drawtype = "glasslike", - tiles ={"testnodes_climbable_nojump_side.png"}, - paramtype = "light", - sunlight_propagates = true, -}) - --- A liquid in which you can't rise -minetest.register_node("testnodes:liquid_nojump", { - description = S("Non-jumping Liquid Source Node"), - liquidtype = "source", - liquid_range = 1, - liquid_viscosity = 0, - liquid_alternative_flowing = "testnodes:liquidflowing_nojump", - liquid_alternative_source = "testnodes:liquid_nojump", - liquid_renewable = false, - groups = {disable_jump=1, dig_immediate=3}, - walkable = false, - - drawtype = "liquid", - tiles = {"testnodes_liquidsource.png^[colorize:#FF0000:127"}, - special_tiles = { - {name = "testnodes_liquidsource.png^[colorize:#FF0000:127", backface_culling = false}, - {name = "testnodes_liquidsource.png^[colorize:#FF0000:127", backface_culling = true}, - }, - use_texture_alpha = true, - paramtype = "light", - pointable = false, - liquids_pointable = true, - diggable = false, - buildable_to = true, - is_ground_content = false, - post_effect_color = {a = 70, r = 255, g = 0, b = 200}, -}) - --- A liquid in which you can't rise (flowing variant) -minetest.register_node("testnodes:liquidflowing_nojump", { - description = S("Non-jumping Flowing Liquid Node"), - liquidtype = "flowing", - liquid_range = 1, - liquid_viscosity = 0, - liquid_alternative_flowing = "testnodes:liquidflowing_nojump", - liquid_alternative_source = "testnodes:liquid_nojump", - liquid_renewable = false, - groups = {disable_jump=1, dig_immediate=3}, - walkable = false, - - - drawtype = "flowingliquid", - tiles = {"testnodes_liquidflowing.png^[colorize:#FF0000:127"}, - special_tiles = { - {name = "testnodes_liquidflowing.png^[colorize:#FF0000:127", backface_culling = false}, - {name = "testnodes_liquidflowing.png^[colorize:#FF0000:127", backface_culling = false}, - }, - use_texture_alpha = true, - paramtype = "light", - paramtype2 = "flowingliquid", - pointable = false, - liquids_pointable = true, - diggable = false, - buildable_to = true, - is_ground_content = false, - post_effect_color = {a = 70, r = 255, g = 0, b = 200}, -}) - --- Nodes that modify fall damage (various damage modifiers) -for i=-100, 100, 25 do - if i ~= 0 then - local subname, descnum - if i < 0 then - subname = "m"..math.abs(i) - descnum = tostring(i) - else - subname = tostring(i) - descnum = S("+@1", i) - end - local tex, color, desc - if i > 0 then - local val = math.floor((i/100)*255) - tex = "testnodes_fall_damage_plus.png" - color = { b=0, g=255-val, r=255, a=255 } - desc = S("Fall Damage Node (+@1%)", i) - else - tex = "testnodes_fall_damage_minus.png" - if i == -100 then - color = { r=0, b=0, g=255, a=255 } - else - local val = math.floor((math.abs(i)/100)*255) - color = { r=0, b=255, g=255-val, a=255 } - end - desc = S("Fall Damage Node (-@1%)", math.abs(i)) - end - minetest.register_node("testnodes:damage"..subname, { - description = desc, - groups = {fall_damage_add_percent=i, dig_immediate=3}, - - - tiles = { tex }, - is_ground_content = false, - color = color, - }) - end -end - --- Bouncy nodes (various bounce levels) -for i=20, 180, 20 do - local val = math.floor(((i-20)/200)*255) - minetest.register_node("testnodes:bouncy"..i, { - description = S("Bouncy Node (@1%)", i), - groups = {bouncy=i, dig_immediate=3}, - - - tiles ={"testnodes_bouncy.png"}, - is_ground_content = false, - color = { r=255, g=255-val, b=val, a=255 }, - }) -end - --- Slippery nodes (various slippery levels) -for i=1, 5 do - minetest.register_node("testnodes:slippery"..i, { - description = S("Slippery Node (@1)", i), - tiles ={"testnodes_slippery.png"}, - is_ground_content = false, - groups = {slippery=i, dig_immediate=3}, - color = { r=0, g=255, b=math.floor((i/5)*255), a=255 }, - }) -end - --- By placing something on the node, the node itself will be replaced -minetest.register_node("testnodes:buildable_to", { - description = S("Replacable Node"), - buildable_to = true, - tiles = {"testnodes_buildable_to.png"}, - is_ground_content = false, - groups = {dig_immediate=3}, -}) - --- Nodes that deal damage to players that are inside them. --- Negative damage nodes should heal. -for d=-3,3 do - if d ~= 0 then - local sub, tile - if d > 0 then - sub = tostring(d) - tile = "testnodes_damage.png" - else - sub = "m" .. tostring(math.abs(d)) - tile = "testnodes_damage_neg.png" - end - if math.abs(d) == 2 then - tile = tile .. "^[colorize:#000000:70" - elseif math.abs(d) == 3 then - tile = tile .. "^[colorize:#000000:140" - end - minetest.register_node("testnodes:damage_"..sub, { - description = S("Damage Node (@1 damage per second)", d), - damage_per_second = d, - - - walkable = false, - is_ground_content = false, - drawtype = "allfaces", - paramtype = "light", - sunlight_propagates = true, - tiles = { tile }, - groups = {dig_immediate=3}, - }) - end -end - --- Causes drowning damage -minetest.register_node("testnodes:drowning_1", { - description = S("Drowning Node (@1 damage)", 1), - drowning = 1, - - - walkable = false, - is_ground_content = false, - drawtype = "allfaces", - paramtype = "light", - sunlight_propagates = true, - tiles = { "testnodes_drowning.png" }, - groups = {dig_immediate=3}, -}) - diff --git a/games/minimal/mods/testnodes/settingtypes.txt b/games/minimal/mods/testnodes/settingtypes.txt deleted file mode 100644 index 7f753bf3e..000000000 --- a/games/minimal/mods/testnodes/settingtypes.txt +++ /dev/null @@ -1,4 +0,0 @@ -# If set to true, will show an inventory image for nodes that have no inventory image as of Minetest 5.1.0. -# This is due to . -# This is only added to make the items more visible to avoid confusion, but you will no longer see the default inventory images for these items. When you want to test the default inventory image of drawtypes, this should be turned off. -testnodes_show_fallback_image (Use fallback inventory images) bool false diff --git a/games/minimal/mods/testnodes/textures.lua b/games/minimal/mods/testnodes/textures.lua deleted file mode 100644 index f5db9ccbf..000000000 --- a/games/minimal/mods/testnodes/textures.lua +++ /dev/null @@ -1,67 +0,0 @@ --- Node texture tests - -local S = minetest.get_translator("testnodes") - -minetest.register_node("testnodes:6sides", { - description = S("Six Textures Test Node"), - tiles = { - "testnodes_normal1.png", - "testnodes_normal2.png", - "testnodes_normal3.png", - "testnodes_normal4.png", - "testnodes_normal5.png", - "testnodes_normal6.png", - }, - - groups = { dig_immediate = 2 }, -}) - -minetest.register_node("testnodes:anim", { - description = S("Animated Test Node"), - tiles = { - { name = "testnodes_anim.png", - animation = { - type = "vertical_frames", - aspect_w = 16, - aspect_h = 16, - length = 4.0, - }, }, - }, - - groups = { dig_immediate = 2 }, -}) - --- Node texture transparency test - -local alphas = { 64, 128, 191 } - -for a=1,#alphas do - local alpha = alphas[a] - - -- Transparency taken from texture - minetest.register_node("testnodes:alpha_texture_"..alpha, { - description = S("Texture Alpha Test Node (@1)", alpha), - drawtype = "glasslike", - paramtype = "light", - tiles = { - "testnodes_alpha"..alpha..".png", - }, - use_texture_alpha = true, - - groups = { dig_immediate = 3 }, - }) - - -- Transparency set via "alpha" parameter - minetest.register_node("testnodes:alpha_"..alpha, { - description = S("Alpha Test Node (@1)", alpha), - -- It seems that only the liquid drawtype supports the alpha parameter - drawtype = "liquid", - paramtype = "light", - tiles = { - "testnodes_alpha.png", - }, - alpha = alpha, - - groups = { dig_immediate = 3 }, - }) -end diff --git a/games/minimal/mods/testnodes/textures/testnodes_1.png b/games/minimal/mods/testnodes/textures/testnodes_1.png deleted file mode 100644 index 6730997e2..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_1.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_1g.png b/games/minimal/mods/testnodes/textures/testnodes_1g.png deleted file mode 100644 index 529298ece..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_1g.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_1w.png b/games/minimal/mods/testnodes/textures/testnodes_1w.png deleted file mode 100644 index d24e571cc..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_1w.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_1wg.png b/games/minimal/mods/testnodes/textures/testnodes_1wg.png deleted file mode 100644 index b2eba0e9a..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_1wg.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_2.png b/games/minimal/mods/testnodes/textures/testnodes_2.png deleted file mode 100644 index 6c87c868d..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_2.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_2g.png b/games/minimal/mods/testnodes/textures/testnodes_2g.png deleted file mode 100644 index cb9060f7b..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_2g.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_2w.png b/games/minimal/mods/testnodes/textures/testnodes_2w.png deleted file mode 100644 index b56874ee1..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_2w.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_2wg.png b/games/minimal/mods/testnodes/textures/testnodes_2wg.png deleted file mode 100644 index 108dc87bb..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_2wg.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_3.png b/games/minimal/mods/testnodes/textures/testnodes_3.png deleted file mode 100644 index 05b45629a..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_3.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_3g.png b/games/minimal/mods/testnodes/textures/testnodes_3g.png deleted file mode 100644 index 5c84f5882..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_3g.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_3w.png b/games/minimal/mods/testnodes/textures/testnodes_3w.png deleted file mode 100644 index 8b435cf01..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_3w.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_3wg.png b/games/minimal/mods/testnodes/textures/testnodes_3wg.png deleted file mode 100644 index 9ee900667..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_3wg.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_4.png b/games/minimal/mods/testnodes/textures/testnodes_4.png deleted file mode 100644 index 15e6ffec7..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_4.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_4g.png b/games/minimal/mods/testnodes/textures/testnodes_4g.png deleted file mode 100644 index 8f144fae0..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_4g.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_4w.png b/games/minimal/mods/testnodes/textures/testnodes_4w.png deleted file mode 100644 index 214e0df9d..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_4w.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_4wg.png b/games/minimal/mods/testnodes/textures/testnodes_4wg.png deleted file mode 100644 index 888b3d482..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_4wg.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_5.png b/games/minimal/mods/testnodes/textures/testnodes_5.png deleted file mode 100644 index 1ef1c728c..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_5.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_5g.png b/games/minimal/mods/testnodes/textures/testnodes_5g.png deleted file mode 100644 index 30da4793a..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_5g.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_5w.png b/games/minimal/mods/testnodes/textures/testnodes_5w.png deleted file mode 100644 index b4cb42426..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_5w.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_5wg.png b/games/minimal/mods/testnodes/textures/testnodes_5wg.png deleted file mode 100644 index fac9db28e..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_5wg.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_6.png b/games/minimal/mods/testnodes/textures/testnodes_6.png deleted file mode 100644 index 805813e57..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_6.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_6g.png b/games/minimal/mods/testnodes/textures/testnodes_6g.png deleted file mode 100644 index a88f4c9f8..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_6g.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_6w.png b/games/minimal/mods/testnodes/textures/testnodes_6w.png deleted file mode 100644 index e6bbf97d9..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_6w.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_6wg.png b/games/minimal/mods/testnodes/textures/testnodes_6wg.png deleted file mode 100644 index 29ca933e0..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_6wg.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_airlike.png b/games/minimal/mods/testnodes/textures/testnodes_airlike.png deleted file mode 100644 index 5a5664a2a..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_airlike.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_allfaces.png b/games/minimal/mods/testnodes/textures/testnodes_allfaces.png deleted file mode 100644 index c0a7dc550..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_allfaces.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_allfaces_optional.png b/games/minimal/mods/testnodes/textures/testnodes_allfaces_optional.png deleted file mode 100644 index 1f6a17313..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_allfaces_optional.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_alpha.png b/games/minimal/mods/testnodes/textures/testnodes_alpha.png deleted file mode 100644 index 157fa7386..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_alpha.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_alpha128.png b/games/minimal/mods/testnodes/textures/testnodes_alpha128.png deleted file mode 100644 index 16babf6c7..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_alpha128.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_alpha191.png b/games/minimal/mods/testnodes/textures/testnodes_alpha191.png deleted file mode 100644 index f165d2887..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_alpha191.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_alpha64.png b/games/minimal/mods/testnodes/textures/testnodes_alpha64.png deleted file mode 100644 index c343c32c3..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_alpha64.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_anim.png b/games/minimal/mods/testnodes/textures/testnodes_anim.png deleted file mode 100644 index d321fe857..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_anim.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_attached_bottom.png b/games/minimal/mods/testnodes/textures/testnodes_attached_bottom.png deleted file mode 100644 index e01ae576f..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_attached_bottom.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_attached_side.png b/games/minimal/mods/testnodes/textures/testnodes_attached_side.png deleted file mode 100644 index 9459cbb05..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_attached_side.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_attached_top.png b/games/minimal/mods/testnodes/textures/testnodes_attached_top.png deleted file mode 100644 index 0148b41e0..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_attached_top.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_attachedw_bottom.png b/games/minimal/mods/testnodes/textures/testnodes_attachedw_bottom.png deleted file mode 100644 index 488ad23a9..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_attachedw_bottom.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_attachedw_side.png b/games/minimal/mods/testnodes/textures/testnodes_attachedw_side.png deleted file mode 100644 index a02facbc7..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_attachedw_side.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_attachedw_top.png b/games/minimal/mods/testnodes/textures/testnodes_attachedw_top.png deleted file mode 100644 index 1f4fc7b85..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_attachedw_top.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_bouncy.png b/games/minimal/mods/testnodes/textures/testnodes_bouncy.png deleted file mode 100644 index eabbbdfe4..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_bouncy.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_buildable_to.png b/games/minimal/mods/testnodes/textures/testnodes_buildable_to.png deleted file mode 100644 index 23b5e54d2..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_buildable_to.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_climbable_nojump_side.png b/games/minimal/mods/testnodes/textures/testnodes_climbable_nojump_side.png deleted file mode 100644 index d5ca13033..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_climbable_nojump_side.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_climbable_side.png b/games/minimal/mods/testnodes/textures/testnodes_climbable_side.png deleted file mode 100644 index c56ea90d7..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_climbable_side.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_damage.png b/games/minimal/mods/testnodes/textures/testnodes_damage.png deleted file mode 100644 index 9de2ab5e8..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_damage.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_damage_neg.png b/games/minimal/mods/testnodes/textures/testnodes_damage_neg.png deleted file mode 100644 index 85811bc8e..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_damage_neg.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_drowning.png b/games/minimal/mods/testnodes/textures/testnodes_drowning.png deleted file mode 100644 index 57ffc8fcf..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_drowning.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_fall_damage_minus.png b/games/minimal/mods/testnodes/textures/testnodes_fall_damage_minus.png deleted file mode 100644 index 88d3bdf58..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_fall_damage_minus.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_fall_damage_plus.png b/games/minimal/mods/testnodes/textures/testnodes_fall_damage_plus.png deleted file mode 100644 index 61fdec2e3..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_fall_damage_plus.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_fencelike.png b/games/minimal/mods/testnodes/textures/testnodes_fencelike.png deleted file mode 100644 index 84dea1b7c..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_fencelike.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_firelike.png b/games/minimal/mods/testnodes/textures/testnodes_firelike.png deleted file mode 100644 index ee59b0db1..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_firelike.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_glasslike.png b/games/minimal/mods/testnodes/textures/testnodes_glasslike.png deleted file mode 100644 index cf3e35414..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_glasslike.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_glasslike_detail.png b/games/minimal/mods/testnodes/textures/testnodes_glasslike_detail.png deleted file mode 100644 index 30c9586e8..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_glasslike_detail.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_glasslike_framed.png b/games/minimal/mods/testnodes/textures/testnodes_glasslike_framed.png deleted file mode 100644 index 8a513f21c..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_glasslike_framed.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_glasslike_framed2.png b/games/minimal/mods/testnodes/textures/testnodes_glasslike_framed2.png deleted file mode 100644 index 4ea839c8b..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_glasslike_framed2.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_glasslike_framed_optional.png b/games/minimal/mods/testnodes/textures/testnodes_glasslike_framed_optional.png deleted file mode 100644 index 37de77dd1..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_glasslike_framed_optional.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_glasslikeliquid.png b/games/minimal/mods/testnodes/textures/testnodes_glasslikeliquid.png deleted file mode 100644 index e1e96ffb9..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_glasslikeliquid.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light.png b/games/minimal/mods/testnodes/textures/testnodes_light.png deleted file mode 100644 index 4ba0081c3..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light_1.png b/games/minimal/mods/testnodes/textures/testnodes_light_1.png deleted file mode 100644 index 57adf5a4a..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light_1.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light_10.png b/games/minimal/mods/testnodes/textures/testnodes_light_10.png deleted file mode 100644 index 483834770..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light_10.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light_11.png b/games/minimal/mods/testnodes/textures/testnodes_light_11.png deleted file mode 100644 index 4c423d9b4..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light_11.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light_12.png b/games/minimal/mods/testnodes/textures/testnodes_light_12.png deleted file mode 100644 index bc7946d09..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light_12.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light_13.png b/games/minimal/mods/testnodes/textures/testnodes_light_13.png deleted file mode 100644 index 0b63c84a6..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light_13.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light_14.png b/games/minimal/mods/testnodes/textures/testnodes_light_14.png deleted file mode 100644 index a817bd394..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light_14.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light_2.png b/games/minimal/mods/testnodes/textures/testnodes_light_2.png deleted file mode 100644 index 852eaeff1..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light_2.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light_3.png b/games/minimal/mods/testnodes/textures/testnodes_light_3.png deleted file mode 100644 index 79fc834cc..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light_3.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light_4.png b/games/minimal/mods/testnodes/textures/testnodes_light_4.png deleted file mode 100644 index 75f8c6136..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light_4.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light_5.png b/games/minimal/mods/testnodes/textures/testnodes_light_5.png deleted file mode 100644 index b6eede0ae..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light_5.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light_6.png b/games/minimal/mods/testnodes/textures/testnodes_light_6.png deleted file mode 100644 index ef54addec..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light_6.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light_7.png b/games/minimal/mods/testnodes/textures/testnodes_light_7.png deleted file mode 100644 index 4a885b0f6..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light_7.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light_8.png b/games/minimal/mods/testnodes/textures/testnodes_light_8.png deleted file mode 100644 index b283301e3..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light_8.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_light_9.png b/games/minimal/mods/testnodes/textures/testnodes_light_9.png deleted file mode 100644 index 2aa902358..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_light_9.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_line_crossing.png b/games/minimal/mods/testnodes/textures/testnodes_line_crossing.png deleted file mode 100644 index e566f2793..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_line_crossing.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_line_curved.png b/games/minimal/mods/testnodes/textures/testnodes_line_curved.png deleted file mode 100644 index ab9f8e720..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_line_curved.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_line_straight.png b/games/minimal/mods/testnodes/textures/testnodes_line_straight.png deleted file mode 100644 index 4f33d9c6d..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_line_straight.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_line_t_junction.png b/games/minimal/mods/testnodes/textures/testnodes_line_t_junction.png deleted file mode 100644 index 5668f6ea3..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_line_t_junction.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquid.png b/games/minimal/mods/testnodes/textures/testnodes_liquid.png deleted file mode 100644 index 98ab270c2..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquid.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing.png b/games/minimal/mods/testnodes/textures/testnodes_liquidflowing.png deleted file mode 100644 index 1736b89ba..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r0.png b/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r0.png deleted file mode 100644 index e8a61039d..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r0.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r1.png b/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r1.png deleted file mode 100644 index b4e45b42f..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r1.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r2.png b/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r2.png deleted file mode 100644 index e064b8f2d..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r2.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r3.png b/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r3.png deleted file mode 100644 index bef773968..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r3.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r4.png b/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r4.png deleted file mode 100644 index de1001b2d..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r4.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r5.png b/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r5.png deleted file mode 100644 index 97b422e9a..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r5.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r6.png b/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r6.png deleted file mode 100644 index 4cd8e4e8e..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r6.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r7.png b/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r7.png deleted file mode 100644 index 711dd961c..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r7.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r8.png b/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r8.png deleted file mode 100644 index 9cf22b8ca..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidflowing_r8.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidsource.png b/games/minimal/mods/testnodes/textures/testnodes_liquidsource.png deleted file mode 100644 index b3f29b702..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidsource.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r0.png b/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r0.png deleted file mode 100644 index da0a99623..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r0.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r1.png b/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r1.png deleted file mode 100644 index 66bf2be8f..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r1.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r2.png b/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r2.png deleted file mode 100644 index fc5f65cb6..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r2.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r3.png b/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r3.png deleted file mode 100644 index 0f46e291e..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r3.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r4.png b/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r4.png deleted file mode 100644 index 0693a04d7..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r4.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r5.png b/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r5.png deleted file mode 100644 index cc9d03992..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r5.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r6.png b/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r6.png deleted file mode 100644 index e276a07ae..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r6.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r7.png b/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r7.png deleted file mode 100644 index 3534a4b15..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r7.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r8.png b/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r8.png deleted file mode 100644 index ee1a8b169..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_liquidsource_r8.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_mesh_stripes.png b/games/minimal/mods/testnodes/textures/testnodes_mesh_stripes.png deleted file mode 100644 index 51b8e0025..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_mesh_stripes.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_mesh_stripes2.png b/games/minimal/mods/testnodes/textures/testnodes_mesh_stripes2.png deleted file mode 100644 index 9ea65c1ec..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_mesh_stripes2.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_mesh_stripes3.png b/games/minimal/mods/testnodes/textures/testnodes_mesh_stripes3.png deleted file mode 100644 index 96bc55ac5..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_mesh_stripes3.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_mesh_stripes4.png b/games/minimal/mods/testnodes/textures/testnodes_mesh_stripes4.png deleted file mode 100644 index fca33727d..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_mesh_stripes4.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_node.png b/games/minimal/mods/testnodes/textures/testnodes_node.png deleted file mode 100644 index 145099b3a..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_node.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_node_falling.png b/games/minimal/mods/testnodes/textures/testnodes_node_falling.png deleted file mode 100644 index 44153185c..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_node_falling.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_nodebox.png b/games/minimal/mods/testnodes/textures/testnodes_nodebox.png deleted file mode 100644 index 66e8dd663..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_nodebox.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_nojump_side.png b/games/minimal/mods/testnodes/textures/testnodes_nojump_side.png deleted file mode 100644 index 6a64cfff0..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_nojump_side.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_nojump_top.png b/games/minimal/mods/testnodes/textures/testnodes_nojump_top.png deleted file mode 100644 index fe770838f..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_nojump_top.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_normal.png b/games/minimal/mods/testnodes/textures/testnodes_normal.png deleted file mode 100644 index a1acfd9fd..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_normal.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_normal1.png b/games/minimal/mods/testnodes/textures/testnodes_normal1.png deleted file mode 100644 index edaba77e4..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_normal1.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_normal2.png b/games/minimal/mods/testnodes/textures/testnodes_normal2.png deleted file mode 100644 index 0080a9ee7..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_normal2.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_normal3.png b/games/minimal/mods/testnodes/textures/testnodes_normal3.png deleted file mode 100644 index 0426ab216..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_normal3.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_normal4.png b/games/minimal/mods/testnodes/textures/testnodes_normal4.png deleted file mode 100644 index 0d1922eb6..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_normal4.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_normal5.png b/games/minimal/mods/testnodes/textures/testnodes_normal5.png deleted file mode 100644 index 0b7dcd2da..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_normal5.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_normal6.png b/games/minimal/mods/testnodes/textures/testnodes_normal6.png deleted file mode 100644 index f34a67d71..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_normal6.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_palette_facedir.png b/games/minimal/mods/testnodes/textures/testnodes_palette_facedir.png deleted file mode 100644 index 8cf47bbbe..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_palette_facedir.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_palette_full.png b/games/minimal/mods/testnodes/textures/testnodes_palette_full.png deleted file mode 100644 index e0a5f8b34..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_palette_full.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_palette_wallmounted.png b/games/minimal/mods/testnodes/textures/testnodes_palette_wallmounted.png deleted file mode 100644 index 682f3ac84..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_palette_wallmounted.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike.png deleted file mode 100644 index cc464444d..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike_degrotate.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike_degrotate.png deleted file mode 100644 index 01c81da8e..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike_degrotate.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike_leveled.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike_leveled.png deleted file mode 100644 index 53504dbcd..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike_leveled.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike_meshoptions.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike_meshoptions.png deleted file mode 100644 index d504d459f..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike_meshoptions.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted.png deleted file mode 100644 index 79cf2125e..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base.png deleted file mode 100644 index b9ee9e5be..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_degrotate.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_degrotate.png deleted file mode 100644 index 85311cb2c..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_degrotate.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_leveled.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_leveled.png deleted file mode 100644 index bc602bafe..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_leveled.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_meshoptions.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_meshoptions.png deleted file mode 100644 index d10002375..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_meshoptions.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_waving.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_waving.png deleted file mode 100644 index 527817bc1..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_base_side_waving.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_degrotate.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_degrotate.png deleted file mode 100644 index 45e75bdd3..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_degrotate.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_leveled.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_leveled.png deleted file mode 100644 index 8954b2c34..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_leveled.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_meshoptions.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_meshoptions.png deleted file mode 100644 index a782d4874..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_meshoptions.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_waving.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_waving.png deleted file mode 100644 index 112a0540f..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike_rooted_waving.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_plantlike_waving.png b/games/minimal/mods/testnodes/textures/testnodes_plantlike_waving.png deleted file mode 100644 index b584a8dc9..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_plantlike_waving.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_rail2_crossing.png b/games/minimal/mods/testnodes/textures/testnodes_rail2_crossing.png deleted file mode 100644 index 530bbba7a..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_rail2_crossing.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_rail2_curved.png b/games/minimal/mods/testnodes/textures/testnodes_rail2_curved.png deleted file mode 100644 index 4ed1ca00f..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_rail2_curved.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_rail2_straight.png b/games/minimal/mods/testnodes/textures/testnodes_rail2_straight.png deleted file mode 100644 index 8749330d8..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_rail2_straight.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_rail2_t_junction.png b/games/minimal/mods/testnodes/textures/testnodes_rail2_t_junction.png deleted file mode 100644 index 0517f6570..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_rail2_t_junction.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_rail_crossing.png b/games/minimal/mods/testnodes/textures/testnodes_rail_crossing.png deleted file mode 100644 index 3916ce1ef..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_rail_crossing.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_rail_curved.png b/games/minimal/mods/testnodes/textures/testnodes_rail_curved.png deleted file mode 100644 index e44419848..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_rail_curved.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_rail_straight.png b/games/minimal/mods/testnodes/textures/testnodes_rail_straight.png deleted file mode 100644 index 872d04fb9..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_rail_straight.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_rail_t_junction.png b/games/minimal/mods/testnodes/textures/testnodes_rail_t_junction.png deleted file mode 100644 index 7e4af5182..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_rail_t_junction.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_signlike.png b/games/minimal/mods/testnodes/textures/testnodes_signlike.png deleted file mode 100644 index 33ffcba6c..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_signlike.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_slippery.png b/games/minimal/mods/testnodes/textures/testnodes_slippery.png deleted file mode 100644 index b990468a1..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_slippery.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_street_crossing.png b/games/minimal/mods/testnodes/textures/testnodes_street_crossing.png deleted file mode 100644 index d6e35ad7a..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_street_crossing.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_street_curved.png b/games/minimal/mods/testnodes/textures/testnodes_street_curved.png deleted file mode 100644 index 251b7fb71..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_street_curved.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_street_straight.png b/games/minimal/mods/testnodes/textures/testnodes_street_straight.png deleted file mode 100644 index 639e24b93..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_street_straight.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_street_t_junction.png b/games/minimal/mods/testnodes/textures/testnodes_street_t_junction.png deleted file mode 100644 index 713621e06..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_street_t_junction.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_sunlight_filter.png b/games/minimal/mods/testnodes/textures/testnodes_sunlight_filter.png deleted file mode 100644 index b38ea4072..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_sunlight_filter.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_torchlike_ceiling.png b/games/minimal/mods/testnodes/textures/testnodes_torchlike_ceiling.png deleted file mode 100644 index 5d9862cc9..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_torchlike_ceiling.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_torchlike_floor.png b/games/minimal/mods/testnodes/textures/testnodes_torchlike_floor.png deleted file mode 100644 index adf1e002d..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_torchlike_floor.png and /dev/null differ diff --git a/games/minimal/mods/testnodes/textures/testnodes_torchlike_wall.png b/games/minimal/mods/testnodes/textures/testnodes_torchlike_wall.png deleted file mode 100644 index cb442b22d..000000000 Binary files a/games/minimal/mods/testnodes/textures/testnodes_torchlike_wall.png and /dev/null differ diff --git a/games/minimal/mods/testpathfinder/README.md b/games/minimal/mods/testpathfinder/README.md deleted file mode 100644 index 2b9d46e70..000000000 --- a/games/minimal/mods/testpathfinder/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Pathfinder Tester - -Usage: - -Use the Pathfinder Tester tool (`testpathfinder:testpathfinder`). -Here's how it works: - -* Place on node: Set destination position -* Punch: Find path -* Sneak+punch: Select pathfinding algorithm - -Information will be shown in chat. If a path was found, all waypoints -will be shown for a few seconds. - -See `init.lua` for config variables. diff --git a/games/minimal/mods/testpathfinder/init.lua b/games/minimal/mods/testpathfinder/init.lua deleted file mode 100644 index f94848236..000000000 --- a/games/minimal/mods/testpathfinder/init.lua +++ /dev/null @@ -1,132 +0,0 @@ -local S = minetest.get_translator("testpathfinder") - --- Config parameters - --- Maximum direct distance between start and end -local MAX_DIRECT_DISTANCE = 64 --- Maximum search distance -local MAX_SEARCH_DISTANCE = 32 --- Maximum permitted jump height -local MAX_JUMP = 1 --- Maximum permitted drop height -local MAX_DROP = 5 --- If true, mod won't refuse to run pathfinder even at long distances -local IGNORE_MAX_DISTANCE_SAFEGUARD = false - --- End of config parameters - -local timer = 0 -local algorithms = { - "A*_noprefetch", - "A*", - "Dijkstra", -} - -local function find_path_for_player(player, itemstack) - local meta = itemstack:get_meta() - if not meta then - return - end - local x = meta:get_int("pos_x") - local y = meta:get_int("pos_y") - local z = meta:get_int("pos_z") - local algo = meta:get_int("algorithm") - if x and y and z then - local pos2 = {x=x, y=y, z=z} - algo = algorithms[algo+1] - local pos1 = vector.round(player:get_pos()) - -- Don't bother calling pathfinder for high distance to avoid freezing - if (not IGNORE_MAX_DISTANCE_SAFEGUARD) and (vector.distance(pos1, pos2) > MAX_DIRECT_DISTANCE) then - minetest.chat_send_player(player:get_player_name(), S("Destination too far away! Set a destination (via placing) within a distance of @1 and try again!", MAX_DIRECT_DISTANCE)) - return - end - local str = S("Path from @1 to @2:", - minetest.pos_to_string(pos1), - minetest.pos_to_string(pos2)) - - minetest.chat_send_player(player:get_player_name(), str) - local time_start = minetest.get_us_time() - local path = minetest.find_path(pos1, pos2, MAX_SEARCH_DISTANCE, MAX_JUMP, MAX_DROP, algo) - local time_end = minetest.get_us_time() - local time_diff = time_end - time_start - str = "" - if not path then - minetest.chat_send_player(player:get_player_name(), S("No path!")) - minetest.chat_send_player(player:get_player_name(), S("Time: @1 ms", time_diff/1000)) - return - end - for s=1, #path do - str = str .. minetest.pos_to_string(path[s]) .. "\n" - local t - if s == #path then - t = "testpathfinder_waypoint_end.png" - elseif s == 1 then - t = "testpathfinder_waypoint_start.png" - else - local c = math.floor(((#path-s)/#path)*255) - t = string.format("testpathfinder_waypoint.png^[multiply:#%02x%02x00", 0xFF-c, c) - end - minetest.add_particle({ - pos = path[s], - expirationtime = 5 + 0.2 * s, - playername = player:get_player_name(), - glow = minetest.LIGHT_MAX, - texture = t, - size = 3, - }) - end - minetest.chat_send_player(player:get_player_name(), str) - minetest.chat_send_player(player:get_player_name(), S("Path length: @1", #path)) - minetest.chat_send_player(player:get_player_name(), S("Time: @1 ms", time_diff/1000)) - end -end - -local function set_destination(itemstack, user, pointed_thing) - if not (user and user:is_player()) then - return - end - local name = user:get_player_name() - local obj - local meta = itemstack:get_meta() - if pointed_thing.type == "node" then - local pos = pointed_thing.above - meta:set_int("pos_x", pos.x) - meta:set_int("pos_y", pos.y) - meta:set_int("pos_z", pos.z) - minetest.chat_send_player(user:get_player_name(), S("Destination set to @1", minetest.pos_to_string(pos))) - return itemstack - end -end - -local function find_path_or_set_algorithm(itemstack, user, pointed_thing) - if not (user and user:is_player()) then - return - end - local ctrl = user:get_player_control() - -- No sneak: Find path - if not ctrl.sneak then - find_path_for_player(user, itemstack) - else - -- Sneak: Set algorithm - local meta = itemstack:get_meta() - local algo = meta:get_int("algorithm") - algo = (algo + 1) % #algorithms - meta:set_int("algorithm", algo) - minetest.chat_send_player(user:get_player_name(), S("Algorithm: @1", algorithms[algo+1])) - return itemstack - end -end - --- Punch: Find path --- Sneak+punch: Select pathfinding algorithm --- Place: Select destination node -minetest.register_tool("testpathfinder:testpathfinder", { - description = S("Pathfinder Tester"), - inventory_image = "testpathfinder_testpathfinder.png", - groups = { testtool = 1, disable_repair = 1 }, - on_use = find_path_or_set_algorithm, - on_secondary_use = set_destination, - on_place = set_destination, -}) - - diff --git a/games/minimal/mods/testpathfinder/mod.conf b/games/minimal/mods/testpathfinder/mod.conf deleted file mode 100644 index e6034ae8c..000000000 --- a/games/minimal/mods/testpathfinder/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = testpathfinder -description = Tool to test Minetest's pathfinder function diff --git a/games/minimal/mods/testpathfinder/textures/testpathfinder_testpathfinder.png b/games/minimal/mods/testpathfinder/textures/testpathfinder_testpathfinder.png deleted file mode 100644 index 37eef0565..000000000 Binary files a/games/minimal/mods/testpathfinder/textures/testpathfinder_testpathfinder.png and /dev/null differ diff --git a/games/minimal/mods/testpathfinder/textures/testpathfinder_waypoint.png b/games/minimal/mods/testpathfinder/textures/testpathfinder_waypoint.png deleted file mode 100644 index 661dcf906..000000000 Binary files a/games/minimal/mods/testpathfinder/textures/testpathfinder_waypoint.png and /dev/null differ diff --git a/games/minimal/mods/testpathfinder/textures/testpathfinder_waypoint_end.png b/games/minimal/mods/testpathfinder/textures/testpathfinder_waypoint_end.png deleted file mode 100644 index 41a1cc549..000000000 Binary files a/games/minimal/mods/testpathfinder/textures/testpathfinder_waypoint_end.png and /dev/null differ diff --git a/games/minimal/mods/testpathfinder/textures/testpathfinder_waypoint_start.png b/games/minimal/mods/testpathfinder/textures/testpathfinder_waypoint_start.png deleted file mode 100644 index a22e31c3b..000000000 Binary files a/games/minimal/mods/testpathfinder/textures/testpathfinder_waypoint_start.png and /dev/null differ diff --git a/games/minimal/mods/testtools/README.md b/games/minimal/mods/testtools/README.md deleted file mode 100644 index 9cfe29ea4..000000000 --- a/games/minimal/mods/testtools/README.md +++ /dev/null @@ -1,99 +0,0 @@ -# Test Tools readme - -Test Tools is a mod for developers that adds a bunch of tools to directly manipulate nodes and entities. This is great for quickly testing out stuff. - -Here's the list of tools: - -## Remover -Removes nodes and non-player entities that you punch. - -## Node Setter -Replace a node with another one. - -First, punch a node you want to remember. -Then rightclick any other node to replace it with the node you remembered. - -If you rightclick while pointing nothing, you can manually enter the node and param2. - -## Param2 Tool -Change the value param2 of nodes. - -* Punch: Add 1 to param2 -* Sneak+Punch: Add 8 to param2 -* Place: Subtract 1 from param2 -* Sneak+Place: Subtract 8 from param2 - -Note: Use the debug screen (F5) to see the param2 of the pointed node. - -## Falling Node Tool -Turns nodes into falling nodes. - -Usage: - -* Punch node: Make it fall -* Place: Try to teleport up to 2 units upwards, then make it fall - -## Entity Rotator -Changes the entity rotation (with `set_rotation`). - -Usage: - -* Punch entity: Rotate yaw -* Punch entity while holding down “Sneak” key: Rotate pitch -* Punch entity while holding down “Special” key (aka “Aux”): Rotate roll - -Each usage rotates the entity by 22.5°. - -## Entity Spawner -Spawns entities. - -Usage: - -* Punch to select entity or spawn one directly -* Place to place selected entity - -## Object Property Editor -Edits properties of objects. - -Usage: - -* Punch object to open a formspec that allows you to view and edit properties -* Punch air to edit properties of your own player object - -To edit a property, select it in the list, enter a new value (in Lua syntax) -and hit “Submit”. - -## Object Attacher -Allows you to attach an object to another one. - -Basic usage: -* First select the parent object, then the child object that should be attached -* Selecting an object is done by punching it -* Sneak+punch to detach selected object -* If you punch air, you select yourself - -Configuration: -* Place: Increase attachment Y position -* Sneak+place: decrease attachment Y position -* Aux+place: Increase attachment X rotation -* Aux+Sneak+Rightclick: Decrease attachment X rotation - -Hint: To detach all objects nearby you (including on yourself), use the -`/detach` server command. - -## Object Mover -Move an object by a given distance. - -Usage: -* Punch object into the direction you want to move it -* Sneak+punch: Move object towards you -* Place: Increase move distance -* Sneak+place: Decrease move distance - -## Entity Visual Scaler -Change visual size of entities - -Usage: - -* Punch entity to increase visual size -* Sneak+punch entity to decrease visual size diff --git a/games/minimal/mods/testtools/init.lua b/games/minimal/mods/testtools/init.lua deleted file mode 100644 index a63c98377..000000000 --- a/games/minimal/mods/testtools/init.lua +++ /dev/null @@ -1,691 +0,0 @@ -local S = minetest.get_translator("testtools") -local F = minetest.formspec_escape - --- TODO: Add a Node Metadata tool - --- Param 2 Tool: Set param2 value of tools --- Punch: +1 --- Punch+Shift: +8 --- Place: -1 --- Place+Shift: -8 -minetest.register_tool("testtools:param2tool", { - description = S("Param2 Tool"), - inventory_image = "testtools_param2tool.png", - groups = { testtool = 1, disable_repair = 1 }, - on_use = function(itemstack, user, pointed_thing) - local pos = minetest.get_pointed_thing_position(pointed_thing) - if pointed_thing.type ~= "node" or (not pos) then - return - end - local add = 1 - if user then - local ctrl = user:get_player_control() - if ctrl.sneak then - add = 8 - end - end - local node = minetest.get_node(pos) - node.param2 = node.param2 + add - minetest.swap_node(pos, node) - end, - on_place = function(itemstack, user, pointed_thing) - local pos = minetest.get_pointed_thing_position(pointed_thing) - if pointed_thing.type ~= "node" or (not pos) then - return - end - local add = -1 - if user then - local ctrl = user:get_player_control() - if ctrl.sneak then - add = -8 - end - end - local node = minetest.get_node(pos) - node.param2 = node.param2 + add - minetest.swap_node(pos, node) - end, -}) - -minetest.register_tool("testtools:node_setter", { - description = S("Node Setter"), - inventory_image = "testtools_node_setter.png", - groups = { testtool = 1, disable_repair = 1 }, - on_use = function(itemstack, user, pointed_thing) - local pos = minetest.get_pointed_thing_position(pointed_thing) - if pointed_thing.type == "nothing" then - local meta = itemstack:get_meta() - meta:set_string("node", "air") - meta:set_int("node_param2", 0) - if user and user:is_player() then - minetest.chat_send_player(user:get_player_name(), S("Now placing: @1 (param2=@2)", "air", 0)) - end - return itemstack - elseif pointed_thing.type ~= "node" or (not pos) then - return - end - local node = minetest.get_node(pos) - local meta = itemstack:get_meta() - meta:set_string("node", node.name) - meta:set_int("node_param2", node.param2) - if user and user:is_player() then - minetest.chat_send_player(user:get_player_name(), S("Now placing: @1 (param2=@2)", node.name, node.param2)) - end - return itemstack - end, - on_secondary_use = function(itemstack, user, pointed_thing) - local meta = itemstack:get_meta() - local nodename = meta:get_string("node") or "" - local param2 = meta:get_int("node_param2") or 0 - - minetest.show_formspec(user:get_player_name(), "testtools:node_setter", - "size[4,4]".. - "field[0.5,1;3,1;nodename;"..F(S("Node name (itemstring):"))..";"..F(nodename).."]".. - "field[0.5,2;3,1;param2;"..F(S("param2:"))..";"..F(tostring(param2)).."]".. - "button_exit[0.5,3;3,1;submit;"..F(S("Submit")).."]" - ) - end, - on_place = function(itemstack, user, pointed_thing) - local pos = minetest.get_pointed_thing_position(pointed_thing) - local meta = itemstack:get_meta() - local nodename = meta:get_string("node") - if nodename == "" and user and user:is_player() then - minetest.chat_send_player(user:get_player_name(), S("Punch a node first!")) - return - end - local param2 = meta:get_int("node_param2") - if not param2 then - param2 = 0 - end - local node = { name = nodename, param2 = param2 } - if not minetest.registered_nodes[nodename] then - minetest.chat_send_player(user:get_player_name(), S("Cannot set unknown node: @1", nodename)) - return - end - minetest.set_node(pos, node) - end, -}) - -minetest.register_on_player_receive_fields(function(player, formname, fields) - if formname == "testtools:node_setter" then - local playername = player:get_player_name() - local witem = player:get_wielded_item() - if witem:get_name() == "testtools:node_setter" then - if fields.nodename and fields.param2 then - local param2 = tonumber(fields.param2) - if not param2 then - return - end - local meta = witem:get_meta() - meta:set_string("node", fields.nodename) - meta:set_int("node_param2", param2) - player:set_wielded_item(witem) - end - end - end -end) - -minetest.register_tool("testtools:remover", { - description = S("Remover"), - inventory_image = "testtools_remover.png", - groups = { testtool = 1, disable_repair = 1 }, - on_use = function(itemstack, user, pointed_thing) - local pos = minetest.get_pointed_thing_position(pointed_thing) - if pointed_thing.type == "node" and pos ~= nil then - minetest.remove_node(pos) - elseif pointed_thing.type == "object" then - local obj = pointed_thing.ref - if not obj:is_player() then - obj:remove() - end - end - end, -}) - -minetest.register_tool("testtools:falling_node_tool", { - description = S("Falling Node Tool"), - inventory_image = "testtools_falling_node_tool.png", - groups = { testtool = 1, disable_repair = 1 }, - on_place = function(itemstack, user, pointed_thing) - -- Teleport node 1-2 units upwards (if possible) and make it fall - local pos = minetest.get_pointed_thing_position(pointed_thing) - if pointed_thing.type ~= "node" or (not pos) then - return - end - local ok = false - local highest - for i=1,2 do - local above = {x=pos.x,y=pos.y+i,z=pos.z} - local n2 = minetest.get_node(above) - local def2 = minetest.registered_nodes[n2.name] - if def2 and (not def2.walkable) then - highest = above - else - break - end - end - if highest then - local node = minetest.get_node(pos) - local metatable = minetest.get_meta(pos):to_table() - minetest.remove_node(pos) - minetest.set_node(highest, node) - local meta_highest = minetest.get_meta(highest) - meta_highest:from_table(metatable) - ok = minetest.spawn_falling_node(highest) - else - ok = minetest.spawn_falling_node(pos) - end - if not ok and user and user:is_player() then - minetest.chat_send_player(user:get_player_name(), S("Falling node could not be spawned!")) - end - end, - on_use = function(itemstack, user, pointed_thing) - local pos = minetest.get_pointed_thing_position(pointed_thing) - if pointed_thing.type ~= "node" or (not pos) then - return - end - local ok = minetest.spawn_falling_node(pos) - if not ok and user and user:is_player() then - minetest.chat_send_player(user:get_player_name(), S("Falling node could not be spawned!")) - end - end, -}) - -minetest.register_tool("testtools:rotator", { - description = S("Entity Rotator"), - inventory_image = "testtools_entity_rotator.png", - groups = { testtool = 1, disable_repair = 1 }, - on_use = function(itemstack, user, pointed_thing) - if pointed_thing.type ~= "object" then - return - end - local obj = pointed_thing.ref - if obj:is_player() then - -- No player rotation - return - else - local axis = "y" - if user and user:is_player() then - local ctrl = user:get_player_control() - if ctrl.sneak then - axis = "x" - elseif ctrl.aux1 then - axis = "z" - end - end - local rot = obj:get_rotation() - rot[axis] = rot[axis] + math.pi/8 - if rot[axis] > math.pi*2 then - rot[axis] = rot[axis] - math.pi*2 - end - obj:set_rotation(rot) - end - end, -}) - -local mover_config = function(itemstack, user, pointed_thing) - if not (user and user:is_player()) then - return - end - local name = user:get_player_name() - local ctrl = user:get_player_control() - local meta = itemstack:get_meta() - local dist = 1.0 - if meta:contains("distance") then - dist = meta:get_int("distance") - end - if ctrl.sneak then - dist = dist - 1 - else - dist = dist + 1 - end - meta:set_int("distance", dist) - minetest.chat_send_player(user:get_player_name(), S("distance=@1/10", dist*2)) - return itemstack -end - -minetest.register_tool("testtools:object_mover", { - description = S("Object Mover"), - inventory_image = "testtools_object_mover.png", - groups = { testtool = 1, disable_repair = 1 }, - on_place = mover_config, - on_secondary_use = mover_config, - on_use = function(itemstack, user, pointed_thing) - if pointed_thing.type ~= "object" then - return - end - local obj = pointed_thing.ref - if not (user and user:is_player()) then - return - end - local yaw = user:get_look_horizontal() - local dir = minetest.yaw_to_dir(yaw) - local pos = obj:get_pos() - local pitch = user:get_look_vertical() - if pitch > 0.25 * math.pi then - dir.y = -1 - dir.x = 0 - dir.z = 0 - elseif pitch < -0.25 * math.pi then - dir.y = 1 - dir.x = 0 - dir.z = 0 - end - local ctrl = user:get_player_control() - if ctrl.sneak then - dir = vector.multiply(dir, -1) - end - local meta = itemstack:get_meta() - if meta:contains("distance") then - local dist = meta:get_int("distance") - dir = vector.multiply(dir, dist*0.2) - end - pos = vector.add(pos, dir) - obj:set_pos(pos) - end, -}) - - - -minetest.register_tool("testtools:entity_scaler", { - description = S("Entity Visual Scaler"), - inventory_image = "testtools_entity_scaler.png", - groups = { testtool = 1, disable_repair = 1 }, - on_use = function(itemstack, user, pointed_thing) - if pointed_thing.type ~= "object" then - return - end - local obj = pointed_thing.ref - if obj:is_player() then - -- No player scaling - return - else - local diff = 0.1 - if user and user:is_player() then - local ctrl = user:get_player_control() - if ctrl.sneak then - diff = -0.1 - end - end - local prop = obj:get_properties() - if not prop.visual_size then - prop.visual_size = { x=1, y=1, z=1 } - else - prop.visual_size = { x=prop.visual_size.x+diff, y=prop.visual_size.y+diff, z=prop.visual_size.z+diff } - if prop.visual_size.x <= 0.1 then - prop.visual_size.x = 0.1 - end - if prop.visual_size.y <= 0.1 then - prop.visual_size.y = 0.1 - end - if prop.visual_size.z <= 0.1 then - prop.visual_size.z = 0.1 - end - end - obj:set_properties(prop) - end - end, -}) - -local selections = {} -local entity_list -local function get_entity_list() - if entity_list then - return entity_list - end - local ents = minetest.registered_entities - local list = {} - for k,_ in pairs(ents) do - table.insert(list, k) - end - table.sort(list) - entity_list = list - return entity_list -end -minetest.register_tool("testtools:entity_spawner", { - description = S("Entity Spawner"), - inventory_image = "testtools_entity_spawner.png", - groups = { testtool = 1, disable_repair = 1 }, - on_place = function(itemstack, user, pointed_thing) - local name = user:get_player_name() - if selections[name] and pointed_thing.type == "node" then - local pos = pointed_thing.above - minetest.add_entity(pos, get_entity_list()[selections[name]]) - end - end, - on_use = function(itemstack, user, pointed_thing) - if pointed_thing.type == "object" then - return - end - if user and user:is_player() then - local list = table.concat(get_entity_list(), ",") - local name = user:get_player_name() - local sel = selections[name] or "" - minetest.show_formspec(name, "testtools:entity_list", - "size[9,9]".. - "textlist[0,0;9,8;entity_list;"..list..";"..sel..";false]".. - "button[0,8;4,1;spawn;Spawn entity]" - ) - end - end, -}) - -local function prop_to_string(property) - if type(property) == "string" then - return "\"" .. property .. "\"" - elseif type(property) == "table" then - return tostring(dump(property)):gsub("\n", "") - else - return tostring(property) - end -end - -local property_formspec_data = {} -local property_formspec_index = {} -local selected_objects = {} -local function get_object_properties_form(obj, playername) - if not playername then return "" end - local props = obj:get_properties() - local str = "" - property_formspec_data[playername] = {} - local proplist = {} - for k,_ in pairs(props) do - table.insert(proplist, k) - end - table.sort(proplist) - for p=1, #proplist do - local k = proplist[p] - local v = props[k] - local newline = "" - newline = k .. " = " - newline = newline .. prop_to_string(v) - str = str .. F(newline) - if p < #proplist then - str = str .. "," - end - table.insert(property_formspec_data[playername], k) - end - return str -end - -local editor_formspec_selindex = {} - -local editor_formspec = function(playername, obj, value, sel) - if not value then - value = "" - end - if not sel then - sel = "" - end - local list = get_object_properties_form(obj, playername) - local title - if obj:is_player() then - title = S("Object properties of player “@1”", obj:get_player_name()) - else - local ent = obj:get_luaentity() - title = S("Object properties of @1", ent.name) - end - minetest.show_formspec(playername, "testtools:object_editor", - "size[9,9]".. - "label[0,0;"..F(title).."]".. - "textlist[0,0.5;9,7.5;object_props;"..list..";"..sel..";false]".. - "field[0.2,8.75;8,1;value;"..F(S("Value"))..";"..F(value).."]".. - "button[8,8.5;1,1;submit;"..F(S("Submit")).."]" - ) -end - -minetest.register_tool("testtools:object_editor", { - description = S("Object Property Editor"), - inventory_image = "testtools_object_editor.png", - groups = { testtool = 1, disable_repair = 1 }, - on_use = function(itemstack, user, pointed_thing) - if user and user:is_player() then - local name = user:get_player_name() - - if pointed_thing.type == "object" then - selected_objects[name] = pointed_thing.ref - elseif pointed_thing.type == "nothing" then - -- Use on yourself if pointing nothing - selected_objects[name] = user - else - -- Unsupported pointed thing - return - end - - local sel = editor_formspec_selindex[name] - local val - if selected_objects[name] and selected_objects[name]:get_properties() then - local props = selected_objects[name]:get_properties() - local keys = property_formspec_data[name] - if property_formspec_index[name] and props then - local key = keys[property_formspec_index[name]] - val = prop_to_string(props[key]) - end - end - - editor_formspec(name, selected_objects[name], val, sel) - end - end, -}) - -local ent_parent = {} -local ent_child = {} -local DEFAULT_ATTACH_OFFSET_Y = 11 - -local attacher_config = function(itemstack, user, pointed_thing) - if not (user and user:is_player()) then - return - end - if pointed_thing.type == "object" then - return - end - local name = user:get_player_name() - local ctrl = user:get_player_control() - local meta = itemstack:get_meta() - if ctrl.aux1 then - local rot_x = meta:get_float("rot_x") - if ctrl.sneak then - rot_x = rot_x - math.pi/8 - else - rot_x = rot_x + math.pi/8 - end - if rot_x > 6.2 then - rot_x = 0 - elseif rot_x < 0 then - rot_x = math.pi * (15/8) - end - minetest.chat_send_player(name, S("rotation=@1", minetest.pos_to_string({x=rot_x,y=0,z=0}))) - meta:set_float("rot_x", rot_x) - else - local pos_y - if meta:contains("pos_y") then - pos_y = meta:get_int("pos_y") - else - pos_y = DEFAULT_ATTACH_OFFSET_Y - end - if ctrl.sneak then - pos_y = pos_y - 1 - else - pos_y = pos_y + 1 - end - minetest.chat_send_player(name, S("position=@1", minetest.pos_to_string({x=0,y=pos_y,z=0}))) - meta:set_int("pos_y", pos_y) - end - return itemstack -end - -minetest.register_tool("testtools:object_attacher", { - description = S("Object Attacher"), - inventory_image = "testtools_object_attacher.png", - groups = { testtool = 1, disable_repair = 1 }, - on_place = attacher_config, - on_secondary_use = attacher_config, - on_use = function(itemstack, user, pointed_thing) - if user and user:is_player() then - local name = user:get_player_name() - local selected_object - if pointed_thing.type == "object" then - selected_object = pointed_thing.ref - elseif pointed_thing.type == "nothing" then - selected_object = user - else - return - end - local ctrl = user:get_player_control() - if ctrl.sneak then - if selected_object:get_attach() then - selected_object:set_detach() - minetest.chat_send_player(name, S("Object detached!")) - else - minetest.chat_send_player(name, S("Object is not attached!")) - end - return - end - local parent = ent_parent[name] - local child = ent_child[name] - local ename = S("") - if not parent then - parent = selected_object - ent_parent[name] = parent - elseif not child then - child = selected_object - ent_child[name] = child - end - local entity = selected_object:get_luaentity() - if entity then - ename = entity.name - elseif selected_object:is_player() then - ename = selected_object:get_player_name() - end - if selected_object == parent then - minetest.chat_send_player(name, S("Parent object selected: @1", ename)) - elseif selected_object == child then - minetest.chat_send_player(name, S("Child object selected: @1", ename)) - end - if parent and child then - if parent == child then - minetest.chat_send_player(name, S("Can't attach an object to itself!")) - ent_parent[name] = nil - ent_child[name] = nil - return - end - local meta = itemstack:get_meta() - local y - if meta:contains("pos_y") then - y = meta:get_int("pos_y") - else - y = DEFAULT_ATTACH_OFFSET_Y - end - local rx = meta:get_float("rot_x") or 0 - local offset = {x=0,y=y,z=0} - local angle = {x=rx,y=0,z=0} - child:set_attach(parent, "", offset, angle) - local check_parent = child:get_attach() - if check_parent then - minetest.chat_send_player(name, S("Object attached! position=@1, rotation=@2", - minetest.pos_to_string(offset), minetest.pos_to_string(angle))) - else - minetest.chat_send_player(name, S("Attachment failed!")) - end - ent_parent[name] = nil - ent_child[name] = nil - end - end - end, -}) - --- Use loadstring to parse param as a Lua value -local function use_loadstring(param, player) - -- For security reasons, require 'server' priv, just in case - -- someone is actually crazy enough to run this on a public server. - local privs = minetest.get_player_privs(player:get_player_name()) - if not privs.server then - return false, "You need 'server' privilege to change object properties!" - end - if not param then - return false, "Failed: parameter is nil" - end - --[[ DANGER ZONE ]] - -- Interpret string as Lua value - local func, errormsg = loadstring("return (" .. param .. ")") - if not func then - return false, "Failed: " .. errormsg - end - - -- Apply sandbox here using setfenv - setfenv(func, {}) - - -- Run it - local good, errOrResult = pcall(func) - if not good then - -- A Lua error was thrown - return false, "Failed: " .. errOrResult - end - - -- errOrResult will be the value - return true, errOrResult -end - -minetest.register_on_player_receive_fields(function(player, formname, fields) - if not (player and player:is_player()) then - return - end - if formname == "testtools:entity_list" then - local name = player:get_player_name() - if fields.entity_list then - local expl = minetest.explode_textlist_event(fields.entity_list) - if expl.type == "DCL" then - local pos = vector.add(player:get_pos(), {x=0,y=1,z=0}) - selections[name] = expl.index - minetest.add_entity(pos, get_entity_list()[expl.index]) - return - elseif expl.type == "CHG" then - selections[name] = expl.index - return - end - elseif fields.spawn and selections[name] then - local pos = vector.add(player:get_pos(), {x=0,y=1,z=0}) - minetest.add_entity(pos, get_entity_list()[selections[name]]) - return - end - elseif formname == "testtools:object_editor" then - local name = player:get_player_name() - if fields.object_props then - local expl = minetest.explode_textlist_event(fields.object_props) - if expl.type == "DCL" or expl.type == "CHG" then - property_formspec_index[name] = expl.index - - local props = selected_objects[name]:get_properties() - local keys = property_formspec_data[name] - if (not property_formspec_index[name]) or (not props) then - return - end - local key = keys[property_formspec_index[name]] - editor_formspec_selindex[name] = expl.index - editor_formspec(name, selected_objects[name], prop_to_string(props[key]), expl.index) - return - end - end - if fields.submit then - local props = selected_objects[name]:get_properties() - local keys = property_formspec_data[name] - if (not property_formspec_index[name]) or (not props) then - return - end - local key = keys[property_formspec_index[name]] - if not key then - return - end - local success, str = use_loadstring(fields.value, player) - if success then - props[key] = str - else - minetest.chat_send_player(name, str) - return - end - selected_objects[name]:set_properties(props) - local sel = editor_formspec_selindex[name] - editor_formspec(name, selected_objects[name], prop_to_string(props[key]), sel) - return - end - end -end) diff --git a/games/minimal/mods/testtools/mod.conf b/games/minimal/mods/testtools/mod.conf deleted file mode 100644 index cde1b2685..000000000 --- a/games/minimal/mods/testtools/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = testtools -description = Some tools to directly manipulate nodes and entities. Great for development and testing diff --git a/games/minimal/mods/testtools/textures/testtools_entity_rotator.png b/games/minimal/mods/testtools/textures/testtools_entity_rotator.png deleted file mode 100644 index 17ebb2d35..000000000 Binary files a/games/minimal/mods/testtools/textures/testtools_entity_rotator.png and /dev/null differ diff --git a/games/minimal/mods/testtools/textures/testtools_entity_scaler.png b/games/minimal/mods/testtools/textures/testtools_entity_scaler.png deleted file mode 100644 index 4909c25b0..000000000 Binary files a/games/minimal/mods/testtools/textures/testtools_entity_scaler.png and /dev/null differ diff --git a/games/minimal/mods/testtools/textures/testtools_entity_spawner.png b/games/minimal/mods/testtools/textures/testtools_entity_spawner.png deleted file mode 100644 index 6199e0145..000000000 Binary files a/games/minimal/mods/testtools/textures/testtools_entity_spawner.png and /dev/null differ diff --git a/games/minimal/mods/testtools/textures/testtools_falling_node_tool.png b/games/minimal/mods/testtools/textures/testtools_falling_node_tool.png deleted file mode 100644 index 30099a7ef..000000000 Binary files a/games/minimal/mods/testtools/textures/testtools_falling_node_tool.png and /dev/null differ diff --git a/games/minimal/mods/testtools/textures/testtools_node_setter.png b/games/minimal/mods/testtools/textures/testtools_node_setter.png deleted file mode 100644 index 8599438de..000000000 Binary files a/games/minimal/mods/testtools/textures/testtools_node_setter.png and /dev/null differ diff --git a/games/minimal/mods/testtools/textures/testtools_object_attacher.png b/games/minimal/mods/testtools/textures/testtools_object_attacher.png deleted file mode 100644 index 4d9bf6fd1..000000000 Binary files a/games/minimal/mods/testtools/textures/testtools_object_attacher.png and /dev/null differ diff --git a/games/minimal/mods/testtools/textures/testtools_object_editor.png b/games/minimal/mods/testtools/textures/testtools_object_editor.png deleted file mode 100644 index d1ce9cecd..000000000 Binary files a/games/minimal/mods/testtools/textures/testtools_object_editor.png and /dev/null differ diff --git a/games/minimal/mods/testtools/textures/testtools_object_mover.png b/games/minimal/mods/testtools/textures/testtools_object_mover.png deleted file mode 100644 index 8b14e9fb2..000000000 Binary files a/games/minimal/mods/testtools/textures/testtools_object_mover.png and /dev/null differ diff --git a/games/minimal/mods/testtools/textures/testtools_param2tool.png b/games/minimal/mods/testtools/textures/testtools_param2tool.png deleted file mode 100644 index dbc663575..000000000 Binary files a/games/minimal/mods/testtools/textures/testtools_param2tool.png and /dev/null differ diff --git a/games/minimal/mods/testtools/textures/testtools_remover.png b/games/minimal/mods/testtools/textures/testtools_remover.png deleted file mode 100644 index 73f14cd54..000000000 Binary files a/games/minimal/mods/testtools/textures/testtools_remover.png and /dev/null differ diff --git a/games/minimal/mods/tiled/init.lua b/games/minimal/mods/tiled/init.lua deleted file mode 100644 index 68ead8e3a..000000000 --- a/games/minimal/mods/tiled/init.lua +++ /dev/null @@ -1,33 +0,0 @@ -minetest.register_node("tiled:tiled", { - description = "Tiled Node (world-aligned)", - tiles = {{ - name = "tiled_tiled.png", - align_style = "world", - scale = 8, - }}, - groups = {cracky=3}, -}) - -minetest.register_node("tiled:tiled_n", { - description = "Tiled Node (node-aligned)", - tiles = {{ - name = "tiled_tiled.png", - align_style = "node", - scale = 8, - }}, - groups = {cracky=3}, -}) - -stairs.register_stair_and_slab("tiled_n", "tiled:tiled", - {cracky=3}, - {{name="tiled_tiled.png", align_style="node", scale=8}}, - "Tiled Stair (node-aligned)", - "Tiled Slab (node-aligned)") - -stairs.register_stair_and_slab("tiled", "tiled:tiled", - {cracky=3}, - {{name="tiled_tiled.png", align_style="world", scale=8}}, - "Tiled Stair (world-aligned)", - "Tiled Slab (world-aligned)") - - diff --git a/games/minimal/mods/tiled/mod.conf b/games/minimal/mods/tiled/mod.conf deleted file mode 100644 index 78b19f93b..000000000 --- a/games/minimal/mods/tiled/mod.conf +++ /dev/null @@ -1,3 +0,0 @@ -name = tiled -description = Add nodes with a special texture that spans multiple nodes (aka "world-aligned") -depends = stairs diff --git a/games/minimal/mods/tiled/textures/tiled_tiled.png b/games/minimal/mods/tiled/textures/tiled_tiled.png deleted file mode 100644 index 363a26487..000000000 Binary files a/games/minimal/mods/tiled/textures/tiled_tiled.png and /dev/null differ diff --git a/games/minimal/mods/unittests/crafting.lua b/games/minimal/mods/unittests/crafting.lua deleted file mode 100644 index eff13ce09..000000000 --- a/games/minimal/mods/unittests/crafting.lua +++ /dev/null @@ -1,120 +0,0 @@ --- Test minetest.clear_craft function -local function test_clear_craft() - minetest.log("info", "[unittests] Testing minetest.clear_craft") - -- Clearing by output - minetest.register_craft({ - output = "foo", - recipe = {{"bar"}} - }) - minetest.register_craft({ - output = "foo 4", - recipe = {{"foo", "bar"}} - }) - assert(#minetest.get_all_craft_recipes("foo") == 2) - minetest.clear_craft({output="foo"}) - assert(minetest.get_all_craft_recipes("foo") == nil) - -- Clearing by input - minetest.register_craft({ - output = "foo 4", - recipe = {{"foo", "bar"}} - }) - assert(#minetest.get_all_craft_recipes("foo") == 1) - minetest.clear_craft({recipe={{"foo", "bar"}}}) - assert(minetest.get_all_craft_recipes("foo") == nil) -end - --- Test minetest.get_craft_result function -local function test_get_craft_result() - minetest.log("info", "[unittests] Testing minetest.get_craft_result") - - -- normal - local input = { - method = "normal", - width = 2, - items = {"", "unittests:coal_lump", "", "unittests:stick"} - } - minetest.log("info", "[unittests] torch crafting input: "..dump(input)) - local output, decremented_input = minetest.get_craft_result(input) - minetest.log("info", "[unittests] torch crafting output: "..dump(output)) - minetest.log("info", "[unittests] torch crafting decremented input: "..dump(decremented_input)) - assert(output.item) - minetest.log("info", "[unittests] torch crafting output.item:to_table(): "..dump(output.item:to_table())) - assert(output.item:get_name() == "unittests:torch") - assert(output.item:get_count() == 4) - - -- fuel - input = { - method = "fuel", - width = 1, - items = {"unittests:coal_lump"} - } - minetest.log("info", "[unittests] coal fuel input: "..dump(input)) - output, decremented_input = minetest.get_craft_result(input) - minetest.log("info", "[unittests] coal fuel output: "..dump(output)) - minetest.log("info", "[unittests] coal fuel decremented input: "..dump(decremented_input)) - assert(output.time) - assert(output.time > 0) - - -- cooking - input = { - method = "cooking", - width = 1, - items = {"unittests:iron_lump"} - } - minetest.log("info", "[unittests] iron lump cooking input: "..dump(output)) - output, decremented_input = minetest.get_craft_result(input) - minetest.log("info", "[unittests] iron lump cooking output: "..dump(output)) - minetest.log("info", "[unittests] iron lump cooking decremented input: "..dump(decremented_input)) - assert(output.time) - assert(output.time > 0) - assert(output.item) - minetest.log("info", "[unittests] iron lump cooking output.item:to_table(): "..dump(output.item:to_table())) - assert(output.item:get_name() == "unittests:steel_ingot") - assert(output.item:get_count() == 1) - - -- tool repair (repairable) - input = { - method = "normal", - width = 2, - -- Using a wear of 60000 - items = {"unittests:repairable_tool 1 60000", "unittests:repairable_tool 1 60000"} - } - minetest.log("info", "[unittests] repairable tool crafting input: "..dump(input)) - output, decremented_input = minetest.get_craft_result(input) - minetest.log("info", "[unittests] repairable tool crafting output: "..dump(output)) - minetest.log("info", "[unittests] repairable tool crafting decremented input: "..dump(decremented_input)) - assert(output.item) - minetest.log("info", "[unittests] repairable tool crafting output.item:to_table(): "..dump(output.item:to_table())) - assert(output.item:get_name() == "unittests:repairable_tool") - -- Test the wear value. - -- See src/craftdef.cpp in Minetest source code for the formula. The formula to calculate - -- the value 51187 is: - -- 65536 - ((65536-60000)+(65536-60000)) + floor(additonal_wear * 65536 + 0.5) = 51187 - -- where additional_wear = 0.05 - assert(output.item:get_wear() == 51187) - assert(output.item:get_count() == 1) - - -- failing tool repair (unrepairable) - input = { - method = "normal", - width = 2, - items = {"unittests:unrepairable_tool 1 60000", "unittests:unrepairable_tool 1 60000"} - } - minetest.log("info", "[unittests] unrepairable tool crafting input: "..dump(input)) - output, decremented_input = minetest.get_craft_result(input) - minetest.log("info", "[unittests] unrepairable tool crafting output: "..dump(output)) - minetest.log("info", "[unittests] unrepairable tool crafting decremented input: "..dump(decremented_input)) - assert(output.item) - minetest.log("info", "[unittests] unrepairable tool crafting output.item:to_table(): "..dump(output.item:to_table())) - -- unrepairable tool must not yield any output - assert(output.item:get_name() == "") - -end - -function unittests.test_crafting() - test_clear_craft() - test_get_craft_result() - minetest.log("action", "[unittests] Crafting tests passed!") - return true -end - diff --git a/games/minimal/mods/unittests/crafting_prepare.lua b/games/minimal/mods/unittests/crafting_prepare.lua deleted file mode 100644 index a09734827..000000000 --- a/games/minimal/mods/unittests/crafting_prepare.lua +++ /dev/null @@ -1,88 +0,0 @@ --- Registering some dummy items and recipes for the crafting tests - -minetest.register_craftitem("unittests:torch", { - description = "Crafting Test Item: Torch", - inventory_image = "unittests_torch.png", - - groups = { dummy = 1 }, -}) -minetest.register_craftitem("unittests:coal_lump", { - description = "Crafting Test Item: Coal Lump", - inventory_image = "unittests_coal_lump.png", - - groups = { dummy = 1 }, -}) -minetest.register_craftitem("unittests:stick", { - description = "Crafting Test Item: Stick", - inventory_image = "unittests_stick.png", - - groups = { dummy = 1 }, -}) -minetest.register_craftitem("unittests:iron_lump", { - description = "Crafting Test Item: Iron Lump", - inventory_image = "unittests_iron_lump.png", - - groups = { dummy = 1 }, -}) -minetest.register_craftitem("unittests:steel_ingot", { - description = "Crafting Test Item: Steel Ingot", - inventory_image = "unittests_steel_ingot.png", - - groups = { dummy = 1 }, -}) - --- Recipes for tests: Normal crafting, cooking and fuel - -minetest.register_craft({ - output = 'unittests:torch 4', - recipe = { - {'unittests:coal_lump'}, - {'unittests:stick'}, - } -}) - -minetest.register_craft({ - type = "cooking", - output = "unittests:steel_ingot", - recipe = "unittests:iron_lump", -}) - -minetest.register_craft({ - type = "fuel", - recipe = "unittests:coal_lump", - burntime = 40, -}) - --- Test tool repair -minetest.register_craft({ - type = "toolrepair", - additional_wear = -0.05, -}) - --- Test the disable_repair=1 group -minetest.register_tool("unittests:unrepairable_tool", { - description = "Crafting Test Item: Unrepairable Tool", - inventory_image = "unittests_unrepairable_tool.png", - tool_capabilities = { - groupcaps = { - cracky = { - times = {3, 2, 1}, - } - } - }, - groups = { disable_repair = 1, dummy = 1 } -}) - -minetest.register_tool("unittests:repairable_tool", { - description = "Crafting Test Item: Repairable Tool", - inventory_image = "unittests_repairable_tool.png", - tool_capabilities = { - groupcaps = { - cracky = { - times = {3, 2, 1}, - } - } - }, - - groups = { dummy = 1 }, -}) diff --git a/games/minimal/mods/unittests/init.lua b/games/minimal/mods/unittests/init.lua deleted file mode 100644 index 6c1728420..000000000 --- a/games/minimal/mods/unittests/init.lua +++ /dev/null @@ -1,16 +0,0 @@ -unittests = {} - -local modpath = minetest.get_modpath("unittests") -dofile(modpath .. "/random.lua") -dofile(modpath .. "/player.lua") -dofile(modpath .. "/crafting_prepare.lua") -dofile(modpath .. "/crafting.lua") - -if minetest.settings:get_bool("devtest_unittests_autostart", false) then - unittests.test_random() - unittests.test_crafting() - minetest.register_on_joinplayer(function(player) - unittests.test_player(player) - end) -end - diff --git a/games/minimal/mods/unittests/mod.conf b/games/minimal/mods/unittests/mod.conf deleted file mode 100644 index 0d5e3c959..000000000 --- a/games/minimal/mods/unittests/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = unittests -description = Adds automated unit tests for the engine diff --git a/games/minimal/mods/unittests/player.lua b/games/minimal/mods/unittests/player.lua deleted file mode 100644 index 10781a95f..000000000 --- a/games/minimal/mods/unittests/player.lua +++ /dev/null @@ -1,73 +0,0 @@ --- --- HP Change Reasons --- -local expect = nil -local function run_hpchangereason_tests(player) - expect = { type = "set_hp", from = "mod" } - player:set_hp(3) - assert(expect == nil) - - expect = { a = 234, type = "set_hp", from = "mod" } - player:set_hp(7, { a= 234 }) - assert(expect == nil) - - expect = { df = 3458973454, type = "fall", from = "mod" } - player:set_hp(10, { type = "fall", df = 3458973454 }) - assert(expect == nil) - - player:set_hp(20) -end - -local function run_player_meta_tests(player) - local meta = player:get_meta() - meta:set_string("foo", "bar") - assert(meta:contains("foo")) - assert(meta:get_string("foo") == "bar") - assert(meta:get("foo") == "bar") - - local meta2 = player:get_meta() - assert(meta2:get_string("foo") == "bar") - assert(meta2:get("foo") == "bar") - assert(meta:equals(meta2)) - - meta:set_string("bob", "dillan") - assert(meta:get_string("foo") == "bar") - assert(meta:get_string("bob") == "dillan") - assert(meta:get("bob") == "dillan") - assert(meta2:get_string("foo") == "bar") - assert(meta2:get_string("bob") == "dillan") - assert(meta2:get("bob") == "dillan") - assert(meta:equals(meta2)) - - meta:set_string("foo", "") - assert(not meta:contains("foo")) - assert(meta:get("foo") == nil) - assert(meta:get_string("foo") == "") - assert(meta:equals(meta2)) -end - -function unittests.test_player(player) - minetest.register_on_player_hpchange(function(player, hp, reason) - if not expect then - return - end - - for key, value in pairs(reason) do - assert(expect[key] == value) - end - - for key, value in pairs(expect) do - assert(reason[key] == value) - end - - expect = nil - end) - - run_hpchangereason_tests(player) - run_player_meta_tests(player) - local msg = "Player tests passed for player '"..player:get_player_name().."'!" - minetest.chat_send_all(msg) - minetest.log("action", "[unittests] "..msg) - return true -end - diff --git a/games/minimal/mods/unittests/random.lua b/games/minimal/mods/unittests/random.lua deleted file mode 100644 index f94f0a88e..000000000 --- a/games/minimal/mods/unittests/random.lua +++ /dev/null @@ -1,10 +0,0 @@ -function unittests.test_random() - -- Try out PseudoRandom - minetest.log("action", "[unittests] Testing PseudoRandom ...") - local pseudo = PseudoRandom(13) - assert(pseudo:next() == 22290) - assert(pseudo:next() == 13854) - minetest.log("action", "[unittests] PseudoRandom test passed!") - return true -end - diff --git a/games/minimal/mods/unittests/textures/unittests_coal_lump.png b/games/minimal/mods/unittests/textures/unittests_coal_lump.png deleted file mode 100644 index f460d909e..000000000 Binary files a/games/minimal/mods/unittests/textures/unittests_coal_lump.png and /dev/null differ diff --git a/games/minimal/mods/unittests/textures/unittests_iron_lump.png b/games/minimal/mods/unittests/textures/unittests_iron_lump.png deleted file mode 100644 index 22f43e9cc..000000000 Binary files a/games/minimal/mods/unittests/textures/unittests_iron_lump.png and /dev/null differ diff --git a/games/minimal/mods/unittests/textures/unittests_repairable_tool.png b/games/minimal/mods/unittests/textures/unittests_repairable_tool.png deleted file mode 100644 index 46fbbaa74..000000000 Binary files a/games/minimal/mods/unittests/textures/unittests_repairable_tool.png and /dev/null differ diff --git a/games/minimal/mods/unittests/textures/unittests_steel_ingot.png b/games/minimal/mods/unittests/textures/unittests_steel_ingot.png deleted file mode 100644 index 6977696a2..000000000 Binary files a/games/minimal/mods/unittests/textures/unittests_steel_ingot.png and /dev/null differ diff --git a/games/minimal/mods/unittests/textures/unittests_stick.png b/games/minimal/mods/unittests/textures/unittests_stick.png deleted file mode 100644 index ffdce70d4..000000000 Binary files a/games/minimal/mods/unittests/textures/unittests_stick.png and /dev/null differ diff --git a/games/minimal/mods/unittests/textures/unittests_torch.png b/games/minimal/mods/unittests/textures/unittests_torch.png deleted file mode 100644 index ba5eebef0..000000000 Binary files a/games/minimal/mods/unittests/textures/unittests_torch.png and /dev/null differ diff --git a/games/minimal/mods/unittests/textures/unittests_unrepairable_tool.png b/games/minimal/mods/unittests/textures/unittests_unrepairable_tool.png deleted file mode 100644 index c676213a5..000000000 Binary files a/games/minimal/mods/unittests/textures/unittests_unrepairable_tool.png and /dev/null differ diff --git a/games/minimal/mods/util_commands/init.lua b/games/minimal/mods/util_commands/init.lua deleted file mode 100644 index ad8d3f9ba..000000000 --- a/games/minimal/mods/util_commands/init.lua +++ /dev/null @@ -1,137 +0,0 @@ -minetest.register_chatcommand("hotbar", { - params = "", - description = "Set hotbar size", - func = function(name, param) - local player = minetest.get_player_by_name(name) - if not player then - return false, "No player." - end - local size = tonumber(param) - if not size then - return false, "Missing or incorrect size parameter!" - end - local ok = player:hud_set_hotbar_itemcount(size) - if ok then - return true - else - return false, "Invalid item count!" - end - end, -}) - -minetest.register_chatcommand("hp", { - params = "", - description = "Set your health", - func = function(name, param) - local player = minetest.get_player_by_name(name) - if not player then - return false, "No player." - end - local hp = tonumber(param) - if not hp then - return false, "Missing or incorrect hp parameter!" - end - player:set_hp(hp) - return true - end, -}) - -minetest.register_chatcommand("zoom", { - params = "[]", - description = "Set or display your zoom_fov", - func = function(name, param) - local player = minetest.get_player_by_name(name) - if not player then - return false, "No player." - end - if param == "" then - local fov = player:get_properties().zoom_fov - return true, "zoom_fov = "..tostring(fov) - end - local fov = tonumber(param) - if not fov then - return false, "Missing or incorrect zoom_fov parameter!" - end - player:set_properties({zoom_fov = fov}) - fov = player:get_properties().zoom_fov - return true, "zoom_fov = "..tostring(fov) - end, -}) - - - -local s_infplace = minetest.settings:get("devtest_infplace") -if s_infplace == "true" then - infplace = true -elseif s_infplace == "false" then - infplace = false -else - infplace = minetest.settings:get_bool("creative_mode", false) -end - -minetest.register_chatcommand("infplace", { - params = "", - description = "Toggle infinite node placement", - func = function(name, param) - infplace = not infplace - if infplace then - minetest.chat_send_all("Infinite node placement enabled!") - minetest.log("action", "Infinite node placement enabled") - else - minetest.chat_send_all("Infinite node placement disabled!") - minetest.log("action", "Infinite node placement disabled") - end - return true - end, -}) - -minetest.register_chatcommand("detach", { - params = "[]", - description = "Detach all objects nearby", - func = function(name, param) - local radius = tonumber(param) - if type(radius) ~= "number" then - radius = 8 - end - if radius < 1 then - radius = 1 - end - local player = minetest.get_player_by_name(name) - if not player then - return false, "No player." - end - local objs = minetest.get_objects_inside_radius(player:get_pos(), radius) - local num = 0 - for o=1, #objs do - if objs[o]:get_attach() then - objs[o]:set_detach() - num = num + 1 - end - end - return true, string.format("%d object(s) detached.", num) - end, -}) - - --- Unlimited node placement -minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) - if placer and placer:is_player() then - return infplace - end -end) - --- Don't pick up if the item is already in the inventory -local old_handle_node_drops = minetest.handle_node_drops -function minetest.handle_node_drops(pos, drops, digger) - if not digger or not digger:is_player() or not infplace then - return old_handle_node_drops(pos, drops, digger) - end - local inv = digger:get_inventory() - if inv then - for _, item in ipairs(drops) do - if not inv:contains_item("main", item, true) then - inv:add_item("main", item) - end - end - end -end diff --git a/games/minimal/mods/util_commands/mod.conf b/games/minimal/mods/util_commands/mod.conf deleted file mode 100644 index fea6dd3e9..000000000 --- a/games/minimal/mods/util_commands/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name = util_commands -description = Random server commands to make testing easier and more convenient diff --git a/games/minimal/screenshot.png b/games/minimal/screenshot.png deleted file mode 100644 index 7324883f6..000000000 Binary files a/games/minimal/screenshot.png and /dev/null differ diff --git a/games/minimal/settingtypes.txt b/games/minimal/settingtypes.txt deleted file mode 100644 index 40ee5845b..000000000 --- a/games/minimal/settingtypes.txt +++ /dev/null @@ -1,37 +0,0 @@ -# If enabled, nodes won't be used up when placed. -# Note: This behavior can also be toggled in-game with the /infplace command. -# -# - true: enabled -# - false: disabled -# - auto: only enabled when Creative Mode is enabled (default) -devtest_infplace (Infinite node placement) enum auto true,false,auto - -# If enabled, new players receive some initial items when joining for the first time. -give_initial_stuff (Give initial stuff) bool true - -# If enabled, automated tests of the Lua API such as player health, crafting and PseudoRandom will be performed on startup. -devtest_unittests_autostart (Perform unit tests) bool false - -# If enabled, the game will use all mapgen aliases for the v6 mapgen. -# If disabled, it will only use a minimal set of mapgen aliases. -# If enabled, there should be biome-specific tree, leaves and ground nodes. If disabled, stuff should use fallback nodes (like stone instead of desert stone). -# -# Many mapgen aliases have fallback values when no value is provided. Having this setting disabled can be useful to test whether those fallback values are functional. -devtest_v6_mapgen_aliases (Use all v6 mapgen aliases) bool false - -# If enabled, the game will use dungeon stairs by enabling the corresponding mapgen aliases. -# -# Disabling this setting can be useful to test whether dungeons still work when stairs are not defined. -devtest_dungeon_stairs (Generate dungeon stairs) bool false - -# If enabled, the mapgen alias 'mapgen_mossycobble' will be used. This should enable random mossy cobblestone in dungeons. -# If disabled, it won't be used. The engine should fall back to cobble instead. -devtest_dungeon_mossycobble (Generate mossy cobblestone) bool false - -# If enabled, some very basic biomes will be registered. -devtest_register_biomes (Register biomes) bool true - -# If set to true, will show an inventory image for nodes that have no inventory image as of Minetest 5.1.0. -# This is due to . -# This is only added to make the items more visible to avoid confusion, but you will no longer see the default inventory images for these items. When you want to test the default inventory image of drawtypes, this should be turned off. -testnodes_show_fallback_image (Use fallback inventory images) bool false diff --git a/src/unittest/CMakeLists.txt b/src/unittest/CMakeLists.txt index 82f9a4a13..5703b8906 100644 --- a/src/unittest/CMakeLists.txt +++ b/src/unittest/CMakeLists.txt @@ -43,7 +43,7 @@ set (UNITTEST_CLIENT_SRCS PARENT_SCOPE) set (TEST_WORLDDIR ${CMAKE_CURRENT_SOURCE_DIR}/test_world) -set (TEST_SUBGAME_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../games/minimal) +set (TEST_SUBGAME_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../games/devtest) configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/test_config.h.in" diff --git a/src/unittest/test_servermodmanager.cpp b/src/unittest/test_servermodmanager.cpp index 0757323f4..799936757 100644 --- a/src/unittest/test_servermodmanager.cpp +++ b/src/unittest/test_servermodmanager.cpp @@ -88,7 +88,7 @@ void TestServerModManager::testCreation() { std::string path = std::string(TEST_WORLDDIR) + DIR_DELIM + "world.mt"; Settings world_config; - world_config.set("gameid", "minimal"); + world_config.set("gameid", "devtest"); UASSERTEQ(bool, world_config.updateConfigFile(path.c_str()), true); ServerModManager sm(TEST_WORLDDIR); } @@ -118,10 +118,10 @@ void TestServerModManager::testGetMods() const auto &mods = sm.getMods(); UASSERTEQ(bool, mods.empty(), false); - // Ensure we found default mod inside the test folder + // Ensure we found basenodes mod (part of devtest) bool default_found = false; for (const auto &m : mods) { - if (m.name == "default") + if (m.name == "basenodes") default_found = true; // Verify if paths are not empty @@ -135,7 +135,7 @@ void TestServerModManager::testGetModspec() { ServerModManager sm(std::string(TEST_WORLDDIR)); UASSERTEQ(const ModSpec *, sm.getModSpec("wrongmod"), NULL); - UASSERT(sm.getModSpec("default") != NULL); + UASSERT(sm.getModSpec("basenodes") != NULL); } void TestServerModManager::testGetModNamesWrongDir() @@ -152,7 +152,7 @@ void TestServerModManager::testGetModNames() std::vector result; sm.getModNames(result); UASSERTEQ(bool, result.empty(), false); - UASSERT(std::find(result.begin(), result.end(), "default") != result.end()); + UASSERT(std::find(result.begin(), result.end(), "basenodes") != result.end()); } void TestServerModManager::testGetModMediaPathsWrongDir() diff --git a/util/test_multiplayer.sh b/util/test_multiplayer.sh index 9ebfe73be..176cf11d9 100755 --- a/util/test_multiplayer.sh +++ b/util/test_multiplayer.sh @@ -1,6 +1,6 @@ #!/bin/bash dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -gameid=minimal +gameid=devtest minetest=$dir/../bin/minetest testspath=$dir/../tests worldpath=$testspath/testworld_$gameid -- cgit v1.2.3 From 65a6a316d081d3951438bbbcfce74c9c65db407a Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 26 May 2020 02:11:19 +0200 Subject: Add minetest.is_creative_enabled --- builtin/common/misc_helpers.lua | 10 ++-------- builtin/game/item.lua | 2 +- builtin/game/misc.lua | 6 ++++++ doc/lua_api.txt | 7 +++++++ games/devtest/mods/util_commands/init.lua | 2 +- 5 files changed, 17 insertions(+), 10 deletions(-) (limited to 'doc') diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index 1a0c71efd..a88adf96d 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -345,18 +345,12 @@ if INIT == "game" then --Wrapper for rotate_and_place() to check for sneak and assume Creative mode --implies infinite stacks when performing a 6d rotation. -------------------------------------------------------------------------------- - local creative_mode_cache = core.settings:get_bool("creative_mode") - local function is_creative(name) - return creative_mode_cache or - core.check_player_privs(name, {creative = true}) - end - core.rotate_node = function(itemstack, placer, pointed_thing) local name = placer and placer:get_player_name() or "" local invert_wall = placer and placer:get_player_control().sneak or false return core.rotate_and_place(itemstack, placer, pointed_thing, - is_creative(name), - {invert_wall = invert_wall}, true) + core.is_creative_enabled(name), + {invert_wall = invert_wall}, true) end end diff --git a/builtin/game/item.lua b/builtin/game/item.lua index 3aaa71ef2..f680ce0d4 100644 --- a/builtin/game/item.lua +++ b/builtin/game/item.lua @@ -582,7 +582,7 @@ function core.node_dig(pos, node, digger) wielded = wdef.after_use(wielded, digger, node, dp) or wielded else -- Wear out tool - if not core.settings:get_bool("creative_mode") then + if not core.is_creative_enabled(diggername) then wielded:add_wear(dp.wear) if wielded:get_count() == 0 and wdef.sound and wdef.sound.breaks then core.sound_play(wdef.sound.breaks, { diff --git a/builtin/game/misc.lua b/builtin/game/misc.lua index 0ed11ada0..341e613c2 100644 --- a/builtin/game/misc.lua +++ b/builtin/game/misc.lua @@ -164,6 +164,12 @@ function core.record_protection_violation(pos, name) end end +-- To be overridden by Creative mods + +local creative_mode_cache = core.settings:get_bool("creative_mode") +function core.is_creative_enabled(name) + return creative_mode_cache +end -- Checks if specified volume intersects a protected volume diff --git a/doc/lua_api.txt b/doc/lua_api.txt index c4310aa5b..bb9df5373 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -5475,6 +5475,13 @@ Misc. * `minetest.record_protection_violation(pos, name)` * This function calls functions registered with `minetest.register_on_protection_violation`. +* `minetest.is_creative_enabled(name)`: returns boolean + * Returning `true` means that Creative Mode is enabled for player `name`. + * `name` will be `""` for non-players or if the player is unknown. + * This function should be overridden by Creative Mode-related mods to + implement a per-player Creative Mode. + * By default, this function returns `true` if the setting + `creative_mode` is `true` and `false` otherwise. * `minetest.is_area_protected(pos1, pos2, player_name, interval)` * Returns the position of the first node that `player_name` may not modify in the specified cuboid between `pos1` and `pos2`. diff --git a/games/devtest/mods/util_commands/init.lua b/games/devtest/mods/util_commands/init.lua index ad8d3f9ba..3a0e91a41 100644 --- a/games/devtest/mods/util_commands/init.lua +++ b/games/devtest/mods/util_commands/init.lua @@ -66,7 +66,7 @@ if s_infplace == "true" then elseif s_infplace == "false" then infplace = false else - infplace = minetest.settings:get_bool("creative_mode", false) + infplace = minetest.is_creative_enabled("") end minetest.register_chatcommand("infplace", { -- cgit v1.2.3 From 34862a644256f2717923de6d35288114a84acd19 Mon Sep 17 00:00:00 2001 From: MoNTE48 Date: Wed, 11 Dec 2019 20:03:12 +0100 Subject: Add disable_jump check for the player's feet --- doc/lua_api.txt | 1 + games/devtest/mods/testnodes/properties.lua | 11 +++++++++-- src/client/localplayer.cpp | 4 +++- 3 files changed, 13 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index bb9df5373..8c81b7020 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1666,6 +1666,7 @@ to games. * `2`: the node always gets the digging time 0.5 seconds (rail, sign) * `3`: the node always gets the digging time 0 seconds (torch) * `disable_jump`: Player (and possibly other things) cannot jump from node + or if their feet are in the node. Note: not supported for `new_move = false` * `fall_damage_add_percent`: damage speed = `speed * (1 + value/100)` * `falling_node`: if there is no walkable block under the node it will fall * `float`: the node will not fall through liquids diff --git a/games/devtest/mods/testnodes/properties.lua b/games/devtest/mods/testnodes/properties.lua index e169d4b08..01846a5f0 100644 --- a/games/devtest/mods/testnodes/properties.lua +++ b/games/devtest/mods/testnodes/properties.lua @@ -56,11 +56,18 @@ minetest.register_node("testnodes:attached_wallmounted", { minetest.register_node("testnodes:nojump", { description = S("Non-jumping Node"), groups = {disable_jump=1, dig_immediate=3}, - - tiles = {"testnodes_nojump_top.png", "testnodes_nojump_side.png"}, }) +-- Jump disabled plant +minetest.register_node("testnodes:nojump_walkable", { + description = S("Non-jumping Plant Node"), + drawtype = "plantlike", + groups = {disable_jump=1, dig_immediate=3}, + walkable = false, + tiles = {"testnodes_nojump_top.png"}, +}) + -- Climbable up and down with jump and sneak keys minetest.register_node("testnodes:climbable", { description = S("Climbable Node"), diff --git a/src/client/localplayer.cpp b/src/client/localplayer.cpp index c20c3619f..011898bcf 100644 --- a/src/client/localplayer.cpp +++ b/src/client/localplayer.cpp @@ -436,9 +436,11 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, Check properties of the node on which the player is standing */ const ContentFeatures &f = nodemgr->get(map->getNode(m_standing_node)); + const ContentFeatures &f1 = nodemgr->get(map->getNode(m_standing_node + v3s16(0, 1, 0))); // Determine if jumping is possible - m_disable_jump = itemgroup_get(f.groups, "disable_jump"); + m_disable_jump = itemgroup_get(f.groups, "disable_jump") || + itemgroup_get(f1.groups, "disable_jump"); m_can_jump = ((touching_ground && !is_climbing) || sneak_can_jump) && !m_disable_jump; // Jump key pressed while jumping off from a bouncy block -- cgit v1.2.3 From 60bab8b2d7b61383188c10f5d931dc7b5522d042 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Sat, 6 Jun 2020 17:17:08 +0100 Subject: Add HTTP API to main menu (#9998) --- builtin/fstk/dialog.lua | 19 +++ builtin/fstk/ui.lua | 2 +- builtin/init.lua | 1 + builtin/mainmenu/dlg_contentstore.lua | 49 +++--- doc/fst_api.txt | 7 +- doc/menu_lua_api.txt | 273 +++++++++++++++++++++++----------- src/script/lua_api/l_http.cpp | 44 +++++- src/script/lua_api/l_http.h | 6 + src/script/scripting_mainmenu.cpp | 2 + 9 files changed, 290 insertions(+), 113 deletions(-) (limited to 'doc') diff --git a/builtin/fstk/dialog.lua b/builtin/fstk/dialog.lua index df887f413..ea57df1d2 100644 --- a/builtin/fstk/dialog.lua +++ b/builtin/fstk/dialog.lua @@ -67,3 +67,22 @@ function dialog_create(name,get_formspec,buttonhandler,eventhandler) ui.add(self) return self end + +function messagebox(name, message) + return dialog_create(name, + function() + return ([[ + formspec_version[3] + size[8,3] + textarea[0.375,0.375;7.25,1.2;;;%s] + button[3,1.825;2,0.8;ok;%s] + ]]):format(message, fgettext("OK")) + end, + function(this, fields) + if fields.ok then + this:delete() + return true + end + end, + nil) +end diff --git a/builtin/fstk/ui.lua b/builtin/fstk/ui.lua index 884100543..6d26aabf0 100644 --- a/builtin/fstk/ui.lua +++ b/builtin/fstk/ui.lua @@ -85,7 +85,7 @@ function ui.update() "box[0.5,1.2;13,5;#000]", ("textarea[0.5,1.2;13,5;;%s;%s]"):format( error_title, error_message), - "button[5,6.6;4,1;btn_error_confirm;" .. fgettext("Ok") .. "]" + "button[5,6.6;4,1;btn_error_confirm;" .. fgettext("OK") .. "]" } else local active_toplevel_ui_elements = 0 diff --git a/builtin/init.lua b/builtin/init.lua index f76174be7..75bb3db85 100644 --- a/builtin/init.lua +++ b/builtin/init.lua @@ -36,6 +36,7 @@ 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 8ac4dba68..ae119f48f 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -1,5 +1,5 @@ --Minetest ---Copyright (C) 2018 rubenwardy +--Copyright (C) 2018-20 rubenwardy -- --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 @@ -15,8 +15,18 @@ --with this program; if not, write to the Free Software Foundation, Inc., --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +if not minetest.get_http_api then + function create_store_dlg() + return messagebox("store", + fgettext("ContentDB is not available when Minetest was compiled without cURL")) + end + return +end + local store = { packages = {}, packages_full = {} } +local http = minetest.get_http_api() + -- Screenshot local screenshot_dir = core.get_cache_path() .. DIR_DELIM .. "cdb" assert(core.create_dir(screenshot_dir)) @@ -171,11 +181,6 @@ local function get_screenshot(package) end function store.load() - local tmpdir = os.tempfolder() - local target = tmpdir .. DIR_DELIM .. "packages.json" - - assert(core.create_dir(tmpdir)) - local version = core.get_version() local base_url = core.settings:get("contentdb_url") local url = base_url .. @@ -189,31 +194,29 @@ function store.load() end end - core.download_file(url, target) + local timeout = tonumber(minetest.settings:get("curl_file_download_timeout")) + local response = http.fetch_sync({ url = url, timeout = timeout }) + if not response.succeeded then + return + end - local file = io.open(target, "r") - if file then - store.packages_full = core.parse_json(file:read("*all")) or {} - file:close() + store.packages_full = core.parse_json(response.data) or {} - for _, package in pairs(store.packages_full) do - package.url = base_url .. "/packages/" .. + for _, package in pairs(store.packages_full) do + package.url = base_url .. "/packages/" .. package.author .. "/" .. package.name .. "/releases/" .. package.release .. "/download/" - local name_len = #package.name - if package.type == "game" and name_len > 5 and package.name:sub(name_len - 4) == "_game" then - package.id = package.author:lower() .. "/" .. package.name:sub(1, name_len - 5) - else - package.id = package.author:lower() .. "/" .. package.name - end + local name_len = #package.name + if package.type == "game" and name_len > 5 and package.name:sub(name_len - 4) == "_game" then + package.id = package.author:lower() .. "/" .. package.name:sub(1, name_len - 5) + else + package.id = package.author:lower() .. "/" .. package.name end - - store.packages = store.packages_full - store.loaded = true end - core.delete_dir(tmpdir) + store.packages = store.packages_full + store.loaded = true end function store.update_paths() diff --git a/doc/fst_api.txt b/doc/fst_api.txt index c8bcb1e91..6f9aa14b3 100644 --- a/doc/fst_api.txt +++ b/doc/fst_api.txt @@ -101,6 +101,9 @@ dialog_create(name, cbf_formspec, cbf_button_handler, cbf_events) ^ cbf_events: function to handle events function(dialog, event) +messagebox(name, message) +^ creates a message dialog + Class reference dialog: methods: @@ -113,13 +116,13 @@ methods: ^ hide dialog - delete() ^ delete dialog from ui - + members: - data ^ variable data attached to this dialog - parent ^ parent component to return to on exit - + File: fst/buttonbar.lua ----------------------- diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index 485c50110..4eccf5d10 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -3,34 +3,53 @@ Minetest Lua Mainmenu API Reference 5.3.0 Introduction ------------- + The main menu is defined as a formspec by Lua in builtin/mainmenu/ Description of formspec language to show your menu is in lua_api.txt + Callbacks --------- + core.buttonhandler(fields): called when a button is pressed. ^ fields = {name1 = value1, name2 = value2, ...} core.event_handler(event) ^ event: "MenuQuit", "KeyEnter", "ExitButton" or "EditBoxEnter" + Gamedata -------- + The "gamedata" table is read when calling core.start(). It should contain: { - playername = , - password = , - address = , - port = , - selected_world = , -- 0 for client mode - singleplayer = , + playername = , + password = , + address = , + port = , + selected_world = , -- 0 for client mode + singleplayer = , } + Functions --------- + core.start() core.close() +core.get_min_supp_proto() +^ returns the minimum supported network protocol version +core.get_max_supp_proto() +^ returns the maximum supported network protocol version +core.open_url(url) +^ opens the URL in a web browser, returns false on failure. +^ Must begin with http:// or https:// +core.get_version() (possible in async calls) +^ returns current core version + + +Filesystem +---------- -Filesystem: core.get_builtin_path() ^ returns path to builtin root core.create_dir(absolute_path) (possible in async calls) @@ -48,12 +67,6 @@ core.extract_zip(zipfile,destination) [unzip within path required] ^ zipfile to extract ^ destination folder to extract to ^ returns true/false -core.download_file(url,target) (possible in async calls) -^ url to download -^ target to store to -^ returns true/false -core.get_version() (possible in async calls) -^ returns current core version core.sound_play(spec, looped) -> handle ^ spec = SimpleSoundSpec (see lua-api.txt) ^ looped = bool @@ -67,7 +80,82 @@ core.get_mapgen_names([include_hidden=false]) -> table of map generator algorith registered in the core (possible in async calls) core.get_cache_path() -> path of cache -Formspec: + +HTTP Requests +------------- + +* core.download_file(url, target) (possible in async calls) + * url to download, and target to store to + * returns true/false +* `minetest.get_http_api()` (possible in async calls) + * 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" + } + + +Formspec +-------- + core.update_formspec(formspec) core.get_table_index(tablename) -> index ^ can also handle textlists @@ -82,7 +170,10 @@ core.explode_textlist_event(string) -> table core.set_formspec_prepend(formspec) ^ string to be added to every mainmenu formspec, to be used for theming. -GUI: + +GUI +--- + core.set_background(type, texturepath,[tile],[minsize]) ^ type: "background", "overlay", "header" or "footer" ^ tile: tile the image instead of scaling (background only) @@ -102,86 +193,96 @@ core.show_path_select_dialog(formname, caption, is_file_select) ^ returns nil or selected file/folder core.get_screen_info() ^ returns { - density = , - display_width = , - display_height = , - window_width = , - window_height = - } + density = , + display_width = , + display_height = , + window_width = , + window_height = + } -### Content and Packages + +Content and Packages +-------------------- Content - an installed mod, modpack, game, or texture pack (txt) Package - content which is downloadable from the content db, may or may not be installed. * core.get_modpath() (possible in async calls) - * returns path to global modpath + * returns path to global modpath * core.get_clientmodpath() (possible in async calls) - * returns path to global client-side modpath + * returns path to global client-side modpath * core.get_gamepath() (possible in async calls) - * returns path to global gamepath + * returns path to global gamepath * core.get_texturepath() (possible in async calls) - * returns path to default textures + * returns path to default textures * core.get_game(index) - * returns: - - { - id = , - path = , - gamemods_path = , - name = , - menuicon_path = , - author = "author", - DEPRECATED: - addon_mods_paths = {[1] = ,}, - } + * returns: + + { + id = , + path = , + gamemods_path = , + name = , + menuicon_path = , + author = "author", + DEPRECATED: + addon_mods_paths = {[1] = ,}, + } * core.get_games() -> table of all games in upper format (possible in async calls) * core.get_content_info(path) - * returns + * returns - { - name = "name of content", - type = "mod" or "modpack" or "game" or "txp", - description = "description", - author = "author", - path = "path/to/content", - depends = {"mod", "names"}, -- mods only - optional_depends = {"mod", "names"}, -- mods only - } + { + name = "name of content", + type = "mod" or "modpack" or "game" or "txp", + description = "description", + author = "author", + path = "path/to/content", + depends = {"mod", "names"}, -- mods only + optional_depends = {"mod", "names"}, -- mods only + } -Favorites: +Favorites +--------- + core.get_favorites(location) -> list of favorites (possible in async calls) ^ location: "local" or "online" ^ returns { - [1] = { - clients = , - clients_max = , - version = , - password = , - creative = , - damage = , - pvp = , - description = , - name = , - address =
, - port = - clients_list = - mods = - }, - ... + [1] = { + clients = , + clients_max = , + version = , + password = , + creative = , + damage = , + pvp = , + description = , + name = , + address =
, + port = + clients_list = + mods = + }, + ... } core.delete_favorite(id, location) -> success -Logging: + +Logging +------- + core.debug(line) (possible in async calls) ^ Always printed to stderr and logfile (print() is redirected here) core.log(line) (possible in async calls) core.log(loglevel, line) (possible in async calls) ^ loglevel one of "error", "action", "info", "verbose" -Settings: + +Settings +-------- + core.settings:set(name, value) core.settings:get(name) -> string or nil (possible in async calls) core.settings:set_bool(name, value) @@ -191,19 +292,25 @@ core.settings:save() -> nil, save all settings to config file For a complete list of methods of the Settings object see [lua_api.txt](https://github.com/minetest/minetest/blob/master/doc/lua_api.txt) -Worlds: + +Worlds +------ + core.get_worlds() -> list of worlds (possible in async calls) ^ returns { - [1] = { - path = , - name = , - gameid = , - }, + [1] = { + path = , + name = , + gameid = , + }, } core.create_world(worldname, gameid) core.delete_world(index) -Helpers: + +Helpers +------- + core.get_us_time() ^ returns time with microsecond precision core.gettext(string) -> string @@ -228,18 +335,10 @@ minetest.encode_base64(string) (possible in async calls) minetest.decode_base64(string) (possible in async calls) ^ Decodes a string encoded in base64. -Version compat: -core.get_min_supp_proto() -^ returns the minimum supported network protocol version -core.get_max_supp_proto() -^ returns the maximum supported network protocol version -Other: -core.open_url(url) -^ opens the URL in a web browser, returns false on failure. -^ Must begin with http:// or https:// +Async +----- -Async: core.handle_async(async_job,parameters,finished) ^ execute a function asynchronously ^ async_job is a function receiving one parameter and returning one parameter @@ -250,11 +349,13 @@ core.handle_async(async_job,parameters,finished) Limitations of Async operations -No access to global lua variables, don't even try -Limited set of available functions - e.g. No access to functions modifying menu like core.start,core.close, - core.show_path_select_dialog + e.g. No access to functions modifying menu like core.start,core.close, + core.show_path_select_dialog + Background music ---------------- + The main menu supports background music. It looks for a `main_menu` sound in `$USER_PATH/sounds`. The same naming conventions as for normal sounds apply. diff --git a/src/script/lua_api/l_http.cpp b/src/script/lua_api/l_http.cpp index 2ff651cb5..73b4586e0 100644 --- a/src/script/lua_api/l_http.cpp +++ b/src/script/lua_api/l_http.cpp @@ -83,6 +83,24 @@ void ModApiHttp::push_http_fetch_result(lua_State *L, HTTPFetchResult &res, bool setstringfield(L, -1, "data", res.data); } +// http_api.fetch_sync(HTTPRequest definition) +int ModApiHttp::l_http_fetch_sync(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + HTTPFetchRequest req; + read_http_fetch_request(L, req); + + infostream << "Mod performs HTTP request with URL " << req.url << std::endl; + + HTTPFetchResult res; + httpfetch_sync(req, res); + + push_http_fetch_result(L, res, true); + + return 1; +} + // http_api.fetch_async(HTTPRequest definition) int ModApiHttp::l_http_fetch_async(lua_State *L) { @@ -180,11 +198,35 @@ int ModApiHttp::l_request_http_api(lua_State *L) return 1; } + +int ModApiHttp::l_get_http_api(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + lua_newtable(L); + HTTP_API(fetch_async); + HTTP_API(fetch_async_get); + HTTP_API(fetch_sync); + + return 1; +} + #endif void ModApiHttp::Initialize(lua_State *L, int top) { #if USE_CURL - API_FCT(request_http_api); + + bool isMainmenu = false; +#ifndef SERVER + isMainmenu = ModApiBase::getGuiEngine(L) != nullptr; +#endif + + if (isMainmenu) { + API_FCT(get_http_api); + } else { + API_FCT(request_http_api); + } + #endif } diff --git a/src/script/lua_api/l_http.h b/src/script/lua_api/l_http.h index 3d9cdad29..c665235a9 100644 --- a/src/script/lua_api/l_http.h +++ b/src/script/lua_api/l_http.h @@ -32,6 +32,9 @@ private: static void read_http_fetch_request(lua_State *L, HTTPFetchRequest &req); static void push_http_fetch_result(lua_State *L, HTTPFetchResult &res, bool completed = true); + // http_fetch_sync({url=, timeout=, post_data=}) + static int l_http_fetch_sync(lua_State *L); + // http_fetch_async({url=, timeout=, post_data=}) static int l_http_fetch_async(lua_State *L); @@ -40,6 +43,9 @@ private: // request_http_api() static int l_request_http_api(lua_State *L); + + // get_http_api() + static int l_get_http_api(lua_State *L); #endif public: diff --git a/src/script/scripting_mainmenu.cpp b/src/script/scripting_mainmenu.cpp index b6068439a..08858b1a5 100644 --- a/src/script/scripting_mainmenu.cpp +++ b/src/script/scripting_mainmenu.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content/mods.h" #include "cpp_api/s_internal.h" #include "lua_api/l_base.h" +#include "lua_api/l_http.h" #include "lua_api/l_mainmenu.h" #include "lua_api/l_sound.h" #include "lua_api/l_util.h" @@ -67,6 +68,7 @@ void MainMenuScripting::initializeModApi(lua_State *L, int top) ModApiMainMenu::Initialize(L, top); ModApiUtil::Initialize(L, top); ModApiSound::Initialize(L, top); + ModApiHttp::Initialize(L, top); asyncEngine.registerStateInitializer(registerLuaClasses); asyncEngine.registerStateInitializer(ModApiMainMenu::InitializeAsync); -- cgit v1.2.3 From e746607d0f8531e3a8b12cc45294aecf36217b17 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Sat, 6 Jun 2020 23:25:18 +0300 Subject: Restore visual_scale support for nodeboxes (and allfaces) (#9906) --- doc/lua_api.txt | 2 +- src/client/content_mapblock.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 8c81b7020..898531880 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6941,7 +6941,7 @@ Used by `minetest.register_node`. visual_scale = 1.0, -- Supported for drawtypes "plantlike", "signlike", "torchlike", - -- "firelike", "mesh". + -- "firelike", "mesh", "nodebox", "allfaces". -- For plantlike and firelike, the image will start at the bottom of the -- node. For torchlike, the image will start at the surface to which the -- node "attaches". For the other drawtypes the image will be centered diff --git a/src/client/content_mapblock.cpp b/src/client/content_mapblock.cpp index 50efd2e40..f7d20001f 100644 --- a/src/client/content_mapblock.cpp +++ b/src/client/content_mapblock.cpp @@ -366,6 +366,7 @@ void MapblockMeshGenerator::generateCuboidTextureCoords(const aabb3f &box, f32 * void MapblockMeshGenerator::drawAutoLightedCuboid(aabb3f box, const f32 *txc, TileSpec *tiles, int tile_count) { + bool scale = std::fabs(f->visual_scale - 1.0f) > 1e-3f; f32 texture_coord_buf[24]; f32 dx1 = box.MinEdge.X; f32 dy1 = box.MinEdge.Y; @@ -373,6 +374,14 @@ void MapblockMeshGenerator::drawAutoLightedCuboid(aabb3f box, const f32 *txc, f32 dx2 = box.MaxEdge.X; f32 dy2 = box.MaxEdge.Y; f32 dz2 = box.MaxEdge.Z; + if (scale) { + if (!txc) { // generate texture coords before scaling + generateCuboidTextureCoords(box, texture_coord_buf); + txc = texture_coord_buf; + } + box.MinEdge *= f->visual_scale; + box.MaxEdge *= f->visual_scale; + } box.MinEdge += origin; box.MaxEdge += origin; if (!txc) { @@ -1323,7 +1332,7 @@ void MapblockMeshGenerator::drawNodeboxNode() std::vector boxes; n.getNodeBoxes(nodedef, &boxes, neighbors_set); - for (const auto &box : boxes) + for (auto &box : boxes) drawAutoLightedCuboid(box, nullptr, tiles, 6); } -- cgit v1.2.3 From 7148834440d10bc211628aa2652e31166bdd58a0 Mon Sep 17 00:00:00 2001 From: NetherEran <55532075+NetherEran@users.noreply.github.com> Date: Tue, 9 Jun 2020 17:38:39 +0000 Subject: Some vector functions useful for working with rotations (#9572) * added vector.rotate * added vector.forward_from_rotation and vector.up_from_rotation * added vector.forward_up_to_rotatiton * fixed some bugs and formatting with vector functions * shortened name of some new vector functions and added documentation * made vector.rotate not require a unit vector as axis * fixed crash with vector.forward_up_to_rot * renamed new vector functions, made vector.rotate apply a rotation matrix, old vector.rotate is now called vector.rotate_around_axis * documented vector function changes * removed some whitespace to appease luacheck * implemented and fixed optimization of vector.rotate_around_axis by SmallJoker * added some unit tests for rotation vector functions * clarified that rotation vectors are in radians and according to the left hand rule * hopefully appeased luacheck * renamed rotation_to_horizontal to forward_at_rotation, rotation_to_vertical to up_at_rotation * handled cases where sin or cos are 0 in rotation vector functions * added more comments * clarified documentation of rotation vector functions * added more unit tests * changed way in which vector.rotate_around_axis is adjusted for left handed coordinate systems * made vector.rotate_around_axis actually left handed * unrolled matrix multiplication * removed vector.forward_at_rotation and vector.up_at_rotation * prettified vector.rotate_around_axis, made previous commits not break anything * removed references to removed vector.forward_at_rotation and vector.up_at_rotation * removed documentation of removed vector functions * clarified documentation and fixed styling of rotation vector functions * restyled comments minorly * spelling fixes and some hopefully better comments * allowed 'up' to be missing from vector.directions_to_rotation and removed requirement for unit vectors as arguments * made vector.rotate_around_axis() right handed again for consistency * documented previous changes * made matrix multiplication actually multiply * renamed vector.directions_to_rotation() to vector.dir_to_rotation() * optimized a distance comparison * Fixed potential false positive in unit tests. Co-authored-by: NetherEran --- builtin/common/tests/vector_spec.lua | 142 +++++++++++++++++++++++++++++++++++ builtin/common/vector.lua | 93 +++++++++++++++++++++++ doc/lua_api.txt | 18 +++++ 3 files changed, 253 insertions(+) (limited to 'doc') diff --git a/builtin/common/tests/vector_spec.lua b/builtin/common/tests/vector_spec.lua index 79f032f28..6f308a4a8 100644 --- a/builtin/common/tests/vector_spec.lua +++ b/builtin/common/tests/vector_spec.lua @@ -43,4 +43,146 @@ describe("vector", function() it("add()", function() assert.same({ x = 2, y = 4, z = 6 }, vector.add(vector.new(1, 2, 3), { x = 1, y = 2, z = 3 })) end) + + -- This function is needed because of floating point imprecision. + local function almost_equal(a, b) + if type(a) == "number" then + return math.abs(a - b) < 0.00000000001 + end + return vector.distance(a, b) < 0.000000000001 + end + + describe("rotate_around_axis()", function() + it("rotates", function() + assert.True(almost_equal({x = -1, y = 0, z = 0}, + vector.rotate_around_axis({x = 1, y = 0, z = 0}, {x = 0, y = 1, z = 0}, math.pi))) + assert.True(almost_equal({x = 0, y = 1, z = 0}, + vector.rotate_around_axis({x = 0, y = 0, z = 1}, {x = 1, y = 0, z = 0}, math.pi / 2))) + assert.True(almost_equal({x = 4, y = 1, z = 1}, + vector.rotate_around_axis({x = 4, y = 1, z = 1}, {x = 4, y = 1, z = 1}, math.pi / 6))) + end) + it("keeps distance to axis", function() + local rotate1 = {x = 1, y = 3, z = 1} + local axis1 = {x = 1, y = 3, z = 2} + local rotated1 = vector.rotate_around_axis(rotate1, axis1, math.pi / 13) + assert.True(almost_equal(vector.distance(axis1, rotate1), vector.distance(axis1, rotated1))) + local rotate2 = {x = 1, y = 1, z = 3} + local axis2 = {x = 2, y = 6, z = 100} + local rotated2 = vector.rotate_around_axis(rotate2, axis2, math.pi / 23) + assert.True(almost_equal(vector.distance(axis2, rotate2), vector.distance(axis2, rotated2))) + local rotate3 = {x = 1, y = -1, z = 3} + local axis3 = {x = 2, y = 6, z = 100} + local rotated3 = vector.rotate_around_axis(rotate3, axis3, math.pi / 2) + assert.True(almost_equal(vector.distance(axis3, rotate3), vector.distance(axis3, rotated3))) + end) + it("rotates back", function() + local rotate1 = {x = 1, y = 3, z = 1} + local axis1 = {x = 1, y = 3, z = 2} + local rotated1 = vector.rotate_around_axis(rotate1, axis1, math.pi / 13) + rotated1 = vector.rotate_around_axis(rotated1, axis1, -math.pi / 13) + assert.True(almost_equal(rotate1, rotated1)) + local rotate2 = {x = 1, y = 1, z = 3} + local axis2 = {x = 2, y = 6, z = 100} + local rotated2 = vector.rotate_around_axis(rotate2, axis2, math.pi / 23) + rotated2 = vector.rotate_around_axis(rotated2, axis2, -math.pi / 23) + assert.True(almost_equal(rotate2, rotated2)) + local rotate3 = {x = 1, y = -1, z = 3} + local axis3 = {x = 2, y = 6, z = 100} + local rotated3 = vector.rotate_around_axis(rotate3, axis3, math.pi / 2) + rotated3 = vector.rotate_around_axis(rotated3, axis3, -math.pi / 2) + assert.True(almost_equal(rotate3, rotated3)) + end) + it("is right handed", function() + local v_before1 = {x = 0, y = 1, z = -1} + local v_after1 = vector.rotate_around_axis(v_before1, {x = 1, y = 0, z = 0}, math.pi / 4) + assert.True(almost_equal(vector.normalize(vector.cross(v_after1, v_before1)), {x = 1, y = 0, z = 0})) + + local v_before2 = {x = 0, y = 3, z = 4} + local v_after2 = vector.rotate_around_axis(v_before2, {x = 1, y = 0, z = 0}, 2 * math.pi / 5) + assert.True(almost_equal(vector.normalize(vector.cross(v_after2, v_before2)), {x = 1, y = 0, z = 0})) + + local v_before3 = {x = 1, y = 0, z = -1} + local v_after3 = vector.rotate_around_axis(v_before3, {x = 0, y = 1, z = 0}, math.pi / 4) + assert.True(almost_equal(vector.normalize(vector.cross(v_after3, v_before3)), {x = 0, y = 1, z = 0})) + + local v_before4 = {x = 3, y = 0, z = 4} + local v_after4 = vector.rotate_around_axis(v_before4, {x = 0, y = 1, z = 0}, 2 * math.pi / 5) + assert.True(almost_equal(vector.normalize(vector.cross(v_after4, v_before4)), {x = 0, y = 1, z = 0})) + + local v_before5 = {x = 1, y = -1, z = 0} + local v_after5 = vector.rotate_around_axis(v_before5, {x = 0, y = 0, z = 1}, math.pi / 4) + assert.True(almost_equal(vector.normalize(vector.cross(v_after5, v_before5)), {x = 0, y = 0, z = 1})) + + local v_before6 = {x = 3, y = 4, z = 0} + local v_after6 = vector.rotate_around_axis(v_before6, {x = 0, y = 0, z = 1}, 2 * math.pi / 5) + assert.True(almost_equal(vector.normalize(vector.cross(v_after6, v_before6)), {x = 0, y = 0, z = 1})) + end) + end) + + describe("rotate()", function() + it("rotates", function() + assert.True(almost_equal({x = -1, y = 0, z = 0}, + vector.rotate({x = 1, y = 0, z = 0}, {x = 0, y = math.pi, z = 0}))) + assert.True(almost_equal({x = 0, y = -1, z = 0}, + vector.rotate({x = 1, y = 0, z = 0}, {x = 0, y = 0, z = math.pi / 2}))) + assert.True(almost_equal({x = 1, y = 0, z = 0}, + vector.rotate({x = 1, y = 0, z = 0}, {x = math.pi / 123, y = 0, z = 0}))) + end) + it("is counterclockwise", function() + local v_before1 = {x = 0, y = 1, z = -1} + local v_after1 = vector.rotate(v_before1, {x = math.pi / 4, y = 0, z = 0}) + assert.True(almost_equal(vector.normalize(vector.cross(v_after1, v_before1)), {x = 1, y = 0, z = 0})) + + local v_before2 = {x = 0, y = 3, z = 4} + local v_after2 = vector.rotate(v_before2, {x = 2 * math.pi / 5, y = 0, z = 0}) + assert.True(almost_equal(vector.normalize(vector.cross(v_after2, v_before2)), {x = 1, y = 0, z = 0})) + + local v_before3 = {x = 1, y = 0, z = -1} + local v_after3 = vector.rotate(v_before3, {x = 0, y = math.pi / 4, z = 0}) + assert.True(almost_equal(vector.normalize(vector.cross(v_after3, v_before3)), {x = 0, y = 1, z = 0})) + + local v_before4 = {x = 3, y = 0, z = 4} + local v_after4 = vector.rotate(v_before4, {x = 0, y = 2 * math.pi / 5, z = 0}) + assert.True(almost_equal(vector.normalize(vector.cross(v_after4, v_before4)), {x = 0, y = 1, z = 0})) + + local v_before5 = {x = 1, y = -1, z = 0} + local v_after5 = vector.rotate(v_before5, {x = 0, y = 0, z = math.pi / 4}) + assert.True(almost_equal(vector.normalize(vector.cross(v_after5, v_before5)), {x = 0, y = 0, z = 1})) + + local v_before6 = {x = 3, y = 4, z = 0} + local v_after6 = vector.rotate(v_before6, {x = 0, y = 0, z = 2 * math.pi / 5}) + assert.True(almost_equal(vector.normalize(vector.cross(v_after6, v_before6)), {x = 0, y = 0, z = 1})) + end) + end) + + it("dir_to_rotation()", function() + -- Comparing rotations (pitch, yaw, roll) is hard because of certain ambiguities, + -- e.g. (pi, 0, pi) looks exactly the same as (0, pi, 0) + -- So instead we convert the rotation back to vectors and compare these. + local function forward_at_rot(rot) + return vector.rotate(vector.new(0, 0, 1), rot) + end + local function up_at_rot(rot) + return vector.rotate(vector.new(0, 1, 0), rot) + end + local rot1 = vector.dir_to_rotation({x = 1, y = 0, z = 0}, {x = 0, y = 1, z = 0}) + assert.True(almost_equal({x = 1, y = 0, z = 0}, forward_at_rot(rot1))) + assert.True(almost_equal({x = 0, y = 1, z = 0}, up_at_rot(rot1))) + local rot2 = vector.dir_to_rotation({x = 1, y = 1, z = 0}, {x = 0, y = 0, z = 1}) + assert.True(almost_equal({x = 1/math.sqrt(2), y = 1/math.sqrt(2), z = 0}, forward_at_rot(rot2))) + assert.True(almost_equal({x = 0, y = 0, z = 1}, up_at_rot(rot2))) + for i = 1, 1000 do + local rand_vec = vector.new(math.random(), math.random(), math.random()) + if vector.length(rand_vec) ~= 0 then + local rot_1 = vector.dir_to_rotation(rand_vec) + local rot_2 = { + x = math.atan2(rand_vec.y, math.sqrt(rand_vec.z * rand_vec.z + rand_vec.x * rand_vec.x)), + y = -math.atan2(rand_vec.x, rand_vec.z), + z = 0 + } + assert.True(almost_equal(rot_1, rot_2)) + end + end + + end) end) diff --git a/builtin/common/vector.lua b/builtin/common/vector.lua index ca6541eb4..1fd784ce2 100644 --- a/builtin/common/vector.lua +++ b/builtin/common/vector.lua @@ -141,3 +141,96 @@ function vector.sort(a, b) return {x = math.min(a.x, b.x), y = math.min(a.y, b.y), z = math.min(a.z, b.z)}, {x = math.max(a.x, b.x), y = math.max(a.y, b.y), z = math.max(a.z, b.z)} end + +local function sin(x) + if x % math.pi == 0 then + return 0 + else + return math.sin(x) + end +end + +local function cos(x) + if x % math.pi == math.pi / 2 then + return 0 + else + return math.cos(x) + end +end + +function vector.rotate_around_axis(v, axis, angle) + local cosangle = cos(angle) + local sinangle = sin(angle) + axis = vector.normalize(axis) + -- https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula + local dot_axis = vector.multiply(axis, vector.dot(axis, v)) + local cross = vector.cross(v, axis) + return vector.new( + cross.x * sinangle + (v.x - dot_axis.x) * cosangle + dot_axis.x, + cross.y * sinangle + (v.y - dot_axis.y) * cosangle + dot_axis.y, + cross.z * sinangle + (v.z - dot_axis.z) * cosangle + dot_axis.z + ) +end + +function vector.rotate(v, rot) + local sinpitch = sin(-rot.x) + local sinyaw = sin(-rot.y) + local sinroll = sin(-rot.z) + local cospitch = cos(rot.x) + local cosyaw = cos(rot.y) + local cosroll = math.cos(rot.z) + -- Rotation matrix that applies yaw, pitch and roll + local matrix = { + { + sinyaw * sinpitch * sinroll + cosyaw * cosroll, + sinyaw * sinpitch * cosroll - cosyaw * sinroll, + sinyaw * cospitch, + }, + { + cospitch * sinroll, + cospitch * cosroll, + -sinpitch, + }, + { + cosyaw * sinpitch * sinroll - sinyaw * cosroll, + cosyaw * sinpitch * cosroll + sinyaw * sinroll, + cosyaw * cospitch, + }, + } + -- Compute matrix multiplication: `matrix` * `v` + return vector.new( + matrix[1][1] * v.x + matrix[1][2] * v.y + matrix[1][3] * v.z, + matrix[2][1] * v.x + matrix[2][2] * v.y + matrix[2][3] * v.z, + matrix[3][1] * v.x + matrix[3][2] * v.y + matrix[3][3] * v.z + ) +end + +function vector.dir_to_rotation(forward, up) + forward = vector.normalize(forward) + local rot = {x = math.asin(forward.y), y = -math.atan2(forward.x, forward.z), z = 0} + if not up then + return rot + end + assert(vector.dot(forward, up) < 0.000001, + "Invalid vectors passed to vector.dir_to_rotation().") + up = vector.normalize(up) + -- Calculate vector pointing up with roll = 0, just based on forward vector. + local forwup = vector.rotate({x = 0, y = 1, z = 0}, rot) + -- 'forwup' and 'up' are now in a plane with 'forward' as normal. + -- The angle between them is the absolute of the roll value we're looking for. + rot.z = vector.angle(forwup, up) + + -- Since vector.angle never returns a negative value or a value greater + -- than math.pi, rot.z has to be inverted sometimes. + -- To determine wether this is the case, we rotate the up vector back around + -- the forward vector and check if it worked out. + local back = vector.rotate_around_axis(up, forward, -rot.z) + + -- We don't use vector.equals for this because of floating point imprecision. + if (back.x - forwup.x) * (back.x - forwup.x) + + (back.y - forwup.y) * (back.y - forwup.y) + + (back.z - forwup.z) * (back.z - forwup.z) > 0.0000001 then + rot.z = -rot.z + end + return rot +end diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 898531880..ed060c4ad 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -3007,6 +3007,24 @@ For the following functions `x` can be either a vector or a number: * `vector.divide(v, x)`: * Returns a scaled vector or Schur quotient. +For the following functions `a` is an angle in radians and `r` is a rotation +vector ({x = , y = , z = }) where pitch, yaw and roll are +angles in radians. + +* `vector.rotate(v, r)`: + * Applies the rotation `r` to `v` and returns the result. + * `vector.rotate({x = 0, y = 0, z = 1}, r)` and + `vector.rotate({x = 0, y = 1, z = 0}, r)` return vectors pointing + forward and up relative to an entity's rotation `r`. +* `vector.rotate_around_axis(v1, v2, a)`: + * Returns `v1` rotated around axis `v2` by `a` radians according to + the right hand rule. +* `vector.dir_to_rotation(direction[, up])`: + * Returns a rotation vector for `direction` pointing forward using `up` + as the up vector. + * If `up` is omitted, the roll of the returned vector defaults to zero. + * Otherwise `direction` and `up` need to be vectors in a 90 degree angle to each other. + -- cgit v1.2.3 From 982a030f330bd4f4953ed7d4a7f88286f6fd645d Mon Sep 17 00:00:00 2001 From: luk3yx Date: Sat, 13 Jun 2020 04:54:20 +1200 Subject: Add LevelDB player database (#9982) --- doc/minetest.6 | 6 +- src/database/database-leveldb.cpp | 112 ++++++++++++++++++++++++++++++++++++++ src/database/database-leveldb.h | 15 +++++ src/serverenvironment.cpp | 9 ++- 4 files changed, 138 insertions(+), 4 deletions(-) (limited to 'doc') diff --git a/doc/minetest.6 b/doc/minetest.6 index cb5ed57ef..bac70fe1a 100644 --- a/doc/minetest.6 +++ b/doc/minetest.6 @@ -105,12 +105,12 @@ Migrate from current map backend to another. Possible values are sqlite3, leveldb, redis, postgresql, and dummy. .TP .B \-\-migrate-auth -Migrate from current auth backend to another. Possible values are sqlite3 and -files. +Migrate from current auth backend to another. Possible values are sqlite3, +leveldb, and files. .TP .B \-\-migrate-players Migrate from current players backend to another. Possible values are sqlite3, -postgresql, dummy, and files. +leveldb, postgresql, dummy, and files. .TP .B \-\-terminal Display an interactive terminal over ncurses during execution. diff --git a/src/database/database-leveldb.cpp b/src/database/database-leveldb.cpp index 1aab4c43d..1976ae13d 100644 --- a/src/database/database-leveldb.cpp +++ b/src/database/database-leveldb.cpp @@ -26,6 +26,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "filesys.h" #include "exceptions.h" +#include "remoteplayer.h" +#include "server/player_sao.h" #include "util/serialize.h" #include "util/string.h" @@ -98,6 +100,116 @@ void Database_LevelDB::listAllLoadableBlocks(std::vector &dst) delete it; } +PlayerDatabaseLevelDB::PlayerDatabaseLevelDB(const std::string &savedir) +{ + leveldb::Options options; + options.create_if_missing = true; + leveldb::Status status = leveldb::DB::Open(options, + savedir + DIR_DELIM + "players.db", &m_database); + ENSURE_STATUS_OK(status); +} + +PlayerDatabaseLevelDB::~PlayerDatabaseLevelDB() +{ + delete m_database; +} + +void PlayerDatabaseLevelDB::savePlayer(RemotePlayer *player) +{ + /* + u8 version = 1 + u16 hp + v3f position + f32 pitch + f32 yaw + u16 breath + u32 attribute_count + for each attribute { + std::string name + std::string (long) value + } + std::string (long) serialized_inventory + */ + + std::ostringstream os; + writeU8(os, 1); + + PlayerSAO *sao = player->getPlayerSAO(); + sanity_check(sao); + writeU16(os, sao->getHP()); + writeV3F32(os, sao->getBasePosition()); + writeF32(os, sao->getLookPitch()); + writeF32(os, sao->getRotation().Y); + writeU16(os, sao->getBreath()); + + StringMap stringvars = sao->getMeta().getStrings(); + writeU32(os, stringvars.size()); + for (const auto &it : stringvars) { + os << serializeString(it.first); + os << serializeLongString(it.second); + } + + player->inventory.serialize(os); + + leveldb::Status status = m_database->Put(leveldb::WriteOptions(), + player->getName(), os.str()); + ENSURE_STATUS_OK(status); + player->onSuccessfulSave(); +} + +bool PlayerDatabaseLevelDB::removePlayer(const std::string &name) +{ + leveldb::Status s = m_database->Delete(leveldb::WriteOptions(), name); + return s.ok(); +} + +bool PlayerDatabaseLevelDB::loadPlayer(RemotePlayer *player, PlayerSAO *sao) +{ + std::string raw; + leveldb::Status s = m_database->Get(leveldb::ReadOptions(), + player->getName(), &raw); + if (!s.ok()) + return false; + std::istringstream is(raw); + + if (readU8(is) > 1) + return false; + + sao->setHPRaw(readU16(is)); + sao->setBasePosition(readV3F32(is)); + sao->setLookPitch(readF32(is)); + sao->setPlayerYaw(readF32(is)); + sao->setBreath(readU16(is), false); + + u32 attribute_count = readU32(is); + for (u32 i = 0; i < attribute_count; i++) { + std::string name = deSerializeString(is); + std::string value = deSerializeLongString(is); + sao->getMeta().setString(name, value); + } + sao->getMeta().setModified(false); + + // This should always be last. + try { + player->inventory.deSerialize(is); + } catch (SerializationError &e) { + errorstream << "Failed to deserialize player inventory. player_name=" + << player->getName() << " " << e.what() << std::endl; + } + + return true; +} + +void PlayerDatabaseLevelDB::listPlayers(std::vector &res) +{ + leveldb::Iterator* it = m_database->NewIterator(leveldb::ReadOptions()); + res.clear(); + for (it->SeekToFirst(); it->Valid(); it->Next()) { + res.push_back(it->key().ToString()); + } + delete it; +} + AuthDatabaseLevelDB::AuthDatabaseLevelDB(const std::string &savedir) { leveldb::Options options; diff --git a/src/database/database-leveldb.h b/src/database/database-leveldb.h index a9bd0faa4..61def1256 100644 --- a/src/database/database-leveldb.h +++ b/src/database/database-leveldb.h @@ -45,6 +45,21 @@ private: leveldb::DB *m_database; }; +class PlayerDatabaseLevelDB : public PlayerDatabase +{ +public: + PlayerDatabaseLevelDB(const std::string &savedir); + ~PlayerDatabaseLevelDB(); + + void savePlayer(RemotePlayer *player); + bool loadPlayer(RemotePlayer *player, PlayerSAO *sao); + bool removePlayer(const std::string &name); + void listPlayers(std::vector &res); + +private: + leveldb::DB *m_database; +}; + class AuthDatabaseLevelDB : public AuthDatabase { public: diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index 222b4d203..2c6a39ee3 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -2089,6 +2089,7 @@ PlayerDatabase *ServerEnvironment::openPlayerDatabase(const std::string &name, if (name == "dummy") return new Database_Dummy(); + #if USE_POSTGRESQL if (name == "postgresql") { std::string connect_string; @@ -2096,6 +2097,12 @@ PlayerDatabase *ServerEnvironment::openPlayerDatabase(const std::string &name, return new PlayerDatabasePostgreSQL(connect_string); } #endif + +#if USE_LEVELDB + if (name == "leveldb") + return new PlayerDatabaseLevelDB(savedir); +#endif + if (name == "files") return new PlayerDatabaseFiles(savedir + DIR_DELIM + "players"); @@ -2116,7 +2123,7 @@ bool ServerEnvironment::migratePlayersDatabase(const GameParams &game_params, if (!world_mt.exists("player_backend")) { errorstream << "Please specify your current backend in world.mt:" << std::endl - << " player_backend = {files|sqlite3|postgresql}" + << " player_backend = {files|sqlite3|leveldb|postgresql}" << std::endl; return false; } -- cgit v1.2.3 From 2424dfe007e451bb02f87884c2b272cf307d6e7c Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sat, 13 Jun 2020 19:03:26 +0200 Subject: Server pushing media at runtime (#9961) --- doc/lua_api.txt | 14 +++ src/client/client.cpp | 12 ++- src/client/client.h | 9 +- src/client/clientmedia.cpp | 10 +- src/client/clientmedia.h | 5 + src/client/filecache.cpp | 8 ++ src/client/filecache.h | 1 + src/filesys.cpp | 6 ++ src/network/clientopcodes.cpp | 2 +- src/network/clientpackethandler.cpp | 46 +++++++++ src/network/networkprotocol.h | 9 ++ src/network/serveropcodes.cpp | 2 +- src/script/lua_api/l_server.cpp | 22 +++- src/script/lua_api/l_server.h | 3 + src/server.cpp | 195 +++++++++++++++++++++++------------- src/server.h | 4 + 16 files changed, 263 insertions(+), 85 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index ed060c4ad..cb968958f 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -5217,6 +5217,20 @@ Server * Returns a code (0: successful, 1: no such player, 2: player is connected) * `minetest.remove_player_auth(name)`: remove player authentication data * Returns boolean indicating success (false if player nonexistant) +* `minetest.dynamic_add_media(filepath)` + * Adds the file at the given path to the media sent to clients by the server + on startup and also pushes this file to already connected clients. + The file must be a supported image, sound or model format. It must not be + modified, deleted, moved or renamed after calling this function. + The list of dynamically added media is not persisted. + * Returns boolean indicating success (duplicate files count as error) + * The media will be ready to use (in e.g. entity textures, sound_play) + immediately after calling this function. + Old clients that lack support for this feature will not see the media + unless they reconnect to the server. + * Since media transferred this way does not use client caching or HTTP + transfers, dynamic media should not be used with big files or performance + will suffer. Bans ---- diff --git a/src/client/client.cpp b/src/client/client.cpp index c03c062c6..34f97a9de 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -670,11 +670,9 @@ void Client::step(float dtime) } } -bool Client::loadMedia(const std::string &data, const std::string &filename) +bool Client::loadMedia(const std::string &data, const std::string &filename, + bool from_media_push) { - // Silly irrlicht's const-incorrectness - Buffer data_rw(data.c_str(), data.size()); - std::string name; const char *image_ext[] = { @@ -690,6 +688,9 @@ bool Client::loadMedia(const std::string &data, const std::string &filename) io::IFileSystem *irrfs = RenderingEngine::get_filesystem(); video::IVideoDriver *vdrv = RenderingEngine::get_video_driver(); + // Silly irrlicht's const-incorrectness + Buffer data_rw(data.c_str(), data.size()); + // Create an irrlicht memory file io::IReadFile *rfile = irrfs->createMemoryReadFile( *data_rw, data_rw.getSize(), "_tempreadfile"); @@ -727,7 +728,6 @@ bool Client::loadMedia(const std::string &data, const std::string &filename) ".x", ".b3d", ".md2", ".obj", NULL }; - name = removeStringEnd(filename, model_ext); if (!name.empty()) { verbosestream<<"Client: Storing model into memory: " @@ -744,6 +744,8 @@ bool Client::loadMedia(const std::string &data, const std::string &filename) }; name = removeStringEnd(filename, translate_ext); if (!name.empty()) { + if (from_media_push) + return false; TRACESTREAM(<< "Client: Loading translation: " << "\"" << filename << "\"" << std::endl); g_client_translations->loadTranslation(data); diff --git a/src/client/client.h b/src/client/client.h index 3b1095ac2..733634db1 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -222,6 +222,7 @@ public: void handleCommand_FormspecPrepend(NetworkPacket *pkt); void handleCommand_CSMRestrictionFlags(NetworkPacket *pkt); void handleCommand_PlayerSpeed(NetworkPacket *pkt); + void handleCommand_MediaPush(NetworkPacket *pkt); void ProcessData(NetworkPacket *pkt); @@ -376,7 +377,8 @@ public: // The following set of functions is used by ClientMediaDownloader // Insert a media file appropriately into the appropriate manager - bool loadMedia(const std::string &data, const std::string &filename); + bool loadMedia(const std::string &data, const std::string &filename, + bool from_media_push = false); // Send a request for conventional media transfer void request_media(const std::vector &file_requests); @@ -488,6 +490,7 @@ private: Camera *m_camera = nullptr; Minimap *m_minimap = nullptr; bool m_minimap_disabled_by_server = false; + // Server serialization version u8 m_server_ser_ver; @@ -529,7 +532,6 @@ private: AuthMechanism m_chosen_auth_mech; void *m_auth_data = nullptr; - bool m_access_denied = false; bool m_access_denied_reconnect = false; std::string m_access_denied_reason = ""; @@ -538,7 +540,10 @@ private: bool m_nodedef_received = false; bool m_activeobjects_received = false; bool m_mods_loaded = false; + ClientMediaDownloader *m_media_downloader; + // Set of media filenames pushed by server at runtime + std::unordered_set m_media_pushed_files; // time_of_day speed approximation for old protocol bool m_time_of_day_set = false; diff --git a/src/client/clientmedia.cpp b/src/client/clientmedia.cpp index 6da99bbbf..8cd3b6bcc 100644 --- a/src/client/clientmedia.cpp +++ b/src/client/clientmedia.cpp @@ -35,6 +35,15 @@ static std::string getMediaCacheDir() return porting::path_cache + DIR_DELIM + "media"; } +bool clientMediaUpdateCache(const std::string &raw_hash, const std::string &filedata) +{ + FileCache media_cache(getMediaCacheDir()); + std::string sha1_hex = hex_encode(raw_hash); + if (!media_cache.exists(sha1_hex)) + return media_cache.update(sha1_hex, filedata); + return true; +} + /* ClientMediaDownloader */ @@ -559,7 +568,6 @@ bool ClientMediaDownloader::checkAndLoad( return true; } - /* Minetest Hashset File Format diff --git a/src/client/clientmedia.h b/src/client/clientmedia.h index 92831082c..5a918535b 100644 --- a/src/client/clientmedia.h +++ b/src/client/clientmedia.h @@ -33,6 +33,11 @@ struct HTTPFetchResult; #define MTHASHSET_FILE_SIGNATURE 0x4d544853 // 'MTHS' #define MTHASHSET_FILE_NAME "index.mth" +// Store file into media cache (unless it exists already) +// Validating the hash is responsibility of the caller +bool clientMediaUpdateCache(const std::string &raw_hash, + const std::string &filedata); + class ClientMediaDownloader { public: diff --git a/src/client/filecache.cpp b/src/client/filecache.cpp index 3d1b302a8..46bbe4059 100644 --- a/src/client/filecache.cpp +++ b/src/client/filecache.cpp @@ -82,8 +82,16 @@ bool FileCache::update(const std::string &name, const std::string &data) std::string path = m_dir + DIR_DELIM + name; return updateByPath(path, data); } + bool FileCache::load(const std::string &name, std::ostream &os) { std::string path = m_dir + DIR_DELIM + name; return loadByPath(path, os); } + +bool FileCache::exists(const std::string &name) +{ + std::string path = m_dir + DIR_DELIM + name; + std::ifstream fis(path.c_str(), std::ios_base::binary); + return fis.good(); +} diff --git a/src/client/filecache.h b/src/client/filecache.h index 96e4c8ba1..ea6afc4b2 100644 --- a/src/client/filecache.h +++ b/src/client/filecache.h @@ -33,6 +33,7 @@ public: bool update(const std::string &name, const std::string &data); bool load(const std::string &name, std::ostream &os); + bool exists(const std::string &name); private: std::string m_dir; diff --git a/src/filesys.cpp b/src/filesys.cpp index f61b39b94..0bc351669 100644 --- a/src/filesys.cpp +++ b/src/filesys.cpp @@ -691,6 +691,12 @@ std::string AbsolutePath(const std::string &path) const char *GetFilenameFromPath(const char *path) { const char *filename = strrchr(path, DIR_DELIM_CHAR); + // Consistent with IsDirDelimiter this function handles '/' too + if (DIR_DELIM_CHAR != '/') { + const char *tmp = strrchr(path, '/'); + if (tmp && tmp > filename) + filename = tmp; + } return filename ? filename + 1 : path; } diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp index 0f20047c0..f812a08a1 100644 --- a/src/network/clientopcodes.cpp +++ b/src/network/clientopcodes.cpp @@ -68,7 +68,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] = { "TOCLIENT_TIME_OF_DAY", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_TimeOfDay }, // 0x29 { "TOCLIENT_CSM_RESTRICTION_FLAGS", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_CSMRestrictionFlags }, // 0x2A { "TOCLIENT_PLAYER_SPEED", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_PlayerSpeed }, // 0x2B - null_command_handler, + { "TOCLIENT_MEDIA_PUSH", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_MediaPush }, // 0x2C null_command_handler, null_command_handler, { "TOCLIENT_CHAT_MESSAGE", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ChatMessage }, // 0x2F diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index e000acc92..5934eaf8c 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -39,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "script/scripting_client.h" #include "util/serialize.h" #include "util/srp.h" +#include "util/sha1.h" #include "tileanimation.h" #include "gettext.h" #include "skyparams.h" @@ -1471,6 +1472,51 @@ void Client::handleCommand_PlayerSpeed(NetworkPacket *pkt) player->addVelocity(added_vel); } +void Client::handleCommand_MediaPush(NetworkPacket *pkt) +{ + std::string raw_hash, filename, filedata; + bool cached; + + *pkt >> raw_hash >> filename >> cached; + filedata = pkt->readLongString(); + + if (raw_hash.size() != 20 || filedata.empty() || filename.empty() || + !string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) { + throw PacketError("Illegal filename, data or hash"); + } + + verbosestream << "Server pushes media file \"" << filename << "\" with " + << filedata.size() << " bytes of data (cached=" << cached + << ")" << std::endl; + + if (m_media_pushed_files.count(filename) != 0) { + // Silently ignore for synchronization purposes + return; + } + + // Compute and check checksum of data + std::string computed_hash; + { + SHA1 ctx; + ctx.addBytes(filedata.c_str(), filedata.size()); + unsigned char *buf = ctx.getDigest(); + computed_hash.assign((char*) buf, 20); + free(buf); + } + if (raw_hash != computed_hash) { + verbosestream << "Hash of file data mismatches, ignoring." << std::endl; + return; + } + + // Actually load media + loadMedia(filedata, filename, true); + m_media_pushed_files.insert(filename); + + // Cache file for the next time when this client joins the same server + if (cached) + clientMediaUpdateCache(raw_hash, filedata); +} + /* * Mod channels */ diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index ab924f1db..fd683eac9 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -323,6 +323,15 @@ enum ToClientCommand v3f added_vel */ + TOCLIENT_MEDIA_PUSH = 0x2C, + /* + std::string raw_hash + std::string filename + bool should_be_cached + u32 len + char filedata[len] + */ + // (oops, there is some gap here) TOCLIENT_CHAT_MESSAGE = 0x2F, diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp index 6ee4ff256..2fc3197c2 100644 --- a/src/network/serveropcodes.cpp +++ b/src/network/serveropcodes.cpp @@ -167,7 +167,7 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] = { "TOCLIENT_TIME_OF_DAY", 0, true }, // 0x29 { "TOCLIENT_CSM_RESTRICTION_FLAGS", 0, true }, // 0x2A { "TOCLIENT_PLAYER_SPEED", 0, true }, // 0x2B - null_command_factory, // 0x2C + { "TOCLIENT_MEDIA_PUSH", 0, true }, // 0x2C (sent over channel 1 too) null_command_factory, // 0x2D null_command_factory, // 0x2E { "TOCLIENT_CHAT_MESSAGE", 0, true }, // 0x2F diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index b6754938e..6f934bb9d 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/c_converter.h" #include "common/c_content.h" #include "cpp_api/s_base.h" +#include "cpp_api/s_security.h" #include "server.h" #include "environment.h" #include "remoteplayer.h" @@ -412,9 +413,6 @@ int ModApiServer::l_get_modnames(lua_State *L) std::vector modlist; getServer(L)->getModNames(modlist); - // Take unsorted items from mods_unsorted and sort them into - // mods_sorted; not great performance but the number of mods on a - // server will likely be small. std::sort(modlist.begin(), modlist.end()); // Package them up for Lua @@ -474,6 +472,23 @@ int ModApiServer::l_sound_fade(lua_State *L) return 0; } +// dynamic_add_media(filepath) +int ModApiServer::l_dynamic_add_media(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + // Reject adding media before the server has started up + if (!getEnv(L)) + throw LuaError("Dynamic media cannot be added before server has started up"); + + std::string filepath = readParam(L, 1); + CHECK_SECURE_PATH(L, filepath.c_str(), false); + + bool ok = getServer(L)->dynamicAddMedia(filepath); + lua_pushboolean(L, ok); + return 1; +} + // is_singleplayer() int ModApiServer::l_is_singleplayer(lua_State *L) { @@ -538,6 +553,7 @@ void ModApiServer::Initialize(lua_State *L, int top) API_FCT(sound_play); API_FCT(sound_stop); API_FCT(sound_fade); + API_FCT(dynamic_add_media); API_FCT(get_player_information); API_FCT(get_player_privs); diff --git a/src/script/lua_api/l_server.h b/src/script/lua_api/l_server.h index 3aa1785a2..938bfa8ef 100644 --- a/src/script/lua_api/l_server.h +++ b/src/script/lua_api/l_server.h @@ -70,6 +70,9 @@ private: // sound_fade(handle, step, gain) static int l_sound_fade(lua_State *L); + // dynamic_add_media(filepath) + static int l_dynamic_add_media(lua_State *L); + // get_player_privs(name, text) static int l_get_player_privs(lua_State *L); diff --git a/src/server.cpp b/src/server.cpp index 6ecbd7097..fe2bb3840 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2405,9 +2405,87 @@ bool Server::SendBlock(session_t peer_id, const v3s16 &blockpos) return true; } +bool Server::addMediaFile(const std::string &filename, + const std::string &filepath, std::string *filedata_to, + std::string *digest_to) +{ + // If name contains illegal characters, ignore the file + if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) { + infostream << "Server: ignoring illegal file name: \"" + << filename << "\"" << std::endl; + return false; + } + // If name is not in a supported format, ignore it + const char *supported_ext[] = { + ".png", ".jpg", ".bmp", ".tga", + ".pcx", ".ppm", ".psd", ".wal", ".rgb", + ".ogg", + ".x", ".b3d", ".md2", ".obj", + // Custom translation file format + ".tr", + NULL + }; + if (removeStringEnd(filename, supported_ext).empty()) { + infostream << "Server: ignoring unsupported file extension: \"" + << filename << "\"" << std::endl; + return false; + } + // Ok, attempt to load the file and add to cache + + // Read data + std::ifstream fis(filepath.c_str(), std::ios_base::binary); + if (!fis.good()) { + errorstream << "Server::addMediaFile(): Could not open \"" + << filename << "\" for reading" << std::endl; + return false; + } + std::string filedata; + bool bad = false; + for (;;) { + char buf[1024]; + fis.read(buf, sizeof(buf)); + std::streamsize len = fis.gcount(); + filedata.append(buf, len); + if (fis.eof()) + break; + if (!fis.good()) { + bad = true; + break; + } + } + if (bad) { + errorstream << "Server::addMediaFile(): Failed to read \"" + << filename << "\"" << std::endl; + return false; + } else if (filedata.empty()) { + errorstream << "Server::addMediaFile(): Empty file \"" + << filepath << "\"" << std::endl; + return false; + } + + SHA1 sha1; + sha1.addBytes(filedata.c_str(), filedata.length()); + + unsigned char *digest = sha1.getDigest(); + std::string sha1_base64 = base64_encode(digest, 20); + std::string sha1_hex = hex_encode((char*) digest, 20); + if (digest_to) + *digest_to = std::string((char*) digest, 20); + free(digest); + + // Put in list + m_media[filename] = MediaInfo(filepath, sha1_base64); + verbosestream << "Server: " << sha1_hex << " is " << filename + << std::endl; + + if (filedata_to) + *filedata_to = std::move(filedata); + return true; +} + void Server::fillMediaCache() { - infostream<<"Server: Calculating media file checksums"< paths; @@ -2419,80 +2497,15 @@ void Server::fillMediaCache() for (const std::string &mediapath : paths) { std::vector dirlist = fs::GetDirListing(mediapath); for (const fs::DirListNode &dln : dirlist) { - if (dln.dir) // Ignode dirs - continue; - std::string filename = dln.name; - // If name contains illegal characters, ignore the file - if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) { - infostream<<"Server: ignoring illegal file name: \"" - << filename << "\"" << std::endl; - continue; - } - // If name is not in a supported format, ignore it - const char *supported_ext[] = { - ".png", ".jpg", ".bmp", ".tga", - ".pcx", ".ppm", ".psd", ".wal", ".rgb", - ".ogg", - ".x", ".b3d", ".md2", ".obj", - // Custom translation file format - ".tr", - NULL - }; - if (removeStringEnd(filename, supported_ext).empty()){ - infostream << "Server: ignoring unsupported file extension: \"" - << filename << "\"" << std::endl; + if (dln.dir) // Ignore dirs continue; - } - // Ok, attempt to load the file and add to cache - std::string filepath; - filepath.append(mediapath).append(DIR_DELIM).append(filename); - - // Read data - std::ifstream fis(filepath.c_str(), std::ios_base::binary); - if (!fis.good()) { - errorstream << "Server::fillMediaCache(): Could not open \"" - << filename << "\" for reading" << std::endl; - continue; - } - std::ostringstream tmp_os(std::ios_base::binary); - bool bad = false; - for(;;) { - char buf[1024]; - fis.read(buf, 1024); - std::streamsize len = fis.gcount(); - tmp_os.write(buf, len); - if (fis.eof()) - break; - if (!fis.good()) { - bad = true; - break; - } - } - if(bad) { - errorstream<<"Server::fillMediaCache(): Failed to read \"" - << filename << "\"" << std::endl; - continue; - } - if(tmp_os.str().length() == 0) { - errorstream << "Server::fillMediaCache(): Empty file \"" - << filepath << "\"" << std::endl; - continue; - } - - SHA1 sha1; - sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length()); - - unsigned char *digest = sha1.getDigest(); - std::string sha1_base64 = base64_encode(digest, 20); - std::string sha1_hex = hex_encode((char*)digest, 20); - free(digest); - - // Put in list - m_media[filename] = MediaInfo(filepath, sha1_base64); - verbosestream << "Server: " << sha1_hex << " is " << filename - << std::endl; + std::string filepath = mediapath; + filepath.append(DIR_DELIM).append(dln.name); + addMediaFile(dln.name, filepath); } } + + infostream << "Server: " << m_media.size() << " media files collected" << std::endl; } void Server::sendMediaAnnouncement(session_t peer_id, const std::string &lang_code) @@ -3428,6 +3441,44 @@ void Server::deleteParticleSpawner(const std::string &playername, u32 id) SendDeleteParticleSpawner(peer_id, id); } +bool Server::dynamicAddMedia(const std::string &filepath) +{ + std::string filename = fs::GetFilenameFromPath(filepath.c_str()); + if (m_media.find(filename) != m_media.end()) { + errorstream << "Server::dynamicAddMedia(): file \"" << filename + << "\" already exists in media cache" << std::endl; + return false; + } + + // Load the file and add it to our media cache + std::string filedata, raw_hash; + bool ok = addMediaFile(filename, filepath, &filedata, &raw_hash); + if (!ok) + return false; + + // Push file to existing clients + NetworkPacket pkt(TOCLIENT_MEDIA_PUSH, 0); + pkt << raw_hash << filename << (bool) true; + pkt.putLongString(filedata); + + auto client_ids = m_clients.getClientIDs(CS_DefinitionsSent); + for (session_t client_id : client_ids) { + /* + The network layer only guarantees ordered delivery inside a channel. + Since the very next packet could be one that uses the media, we have + to push the media over ALL channels to ensure it is processed before + it is used. + In practice this means we have to send it twice: + - channel 1 (HUD) + - channel 0 (everything else: e.g. play_sound, object messages) + */ + m_clients.send(client_id, 1, &pkt, true); + m_clients.send(client_id, 0, &pkt, true); + } + + return true; +} + // actions: time-reversed list // Return value: success/failure bool Server::rollbackRevertActions(const std::list &actions, diff --git a/src/server.h b/src/server.h index 27943cc29..f44716531 100644 --- a/src/server.h +++ b/src/server.h @@ -236,6 +236,8 @@ public: void deleteParticleSpawner(const std::string &playername, u32 id); + bool dynamicAddMedia(const std::string &filepath); + ServerInventoryManager *getInventoryMgr() const { return m_inventory_mgr.get(); } void sendDetachedInventory(Inventory *inventory, const std::string &name, session_t peer_id); @@ -435,6 +437,8 @@ private: // Sends blocks to clients (locks env and con on its own) void SendBlocks(float dtime); + bool addMediaFile(const std::string &filename, const std::string &filepath, + std::string *filedata = nullptr, std::string *digest = nullptr); void fillMediaCache(); void sendMediaAnnouncement(session_t peer_id, const std::string &lang_code); void sendRequestedMedia(session_t peer_id, -- cgit v1.2.3 From e7e065f553b430173e9112ad55c7046cfc02f2c5 Mon Sep 17 00:00:00 2001 From: Lars Müller <34514239+appgurueu@users.noreply.github.com> Date: Sat, 13 Jun 2020 22:46:20 +0200 Subject: Exposing the zoom key to Lua API (#9903) Co-authored-by: Raul Ferriz --- doc/lua_api.txt | 7 ++++--- src/client/game.cpp | 5 +++-- src/network/serverpackethandler.cpp | 1 + src/script/lua_api/l_object.cpp | 2 ++ 4 files changed, 10 insertions(+), 5 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index cb968958f..07e9698e8 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6106,13 +6106,14 @@ object you are working with still exists. * `get_formspec_prepend(formspec)`: returns a formspec string. * `get_player_control()`: returns table with player pressed keys * The table consists of fields with boolean value representing the pressed - keys, the fields are jump, right, left, LMB, RMB, sneak, aux1, down, up. + keys, the fields are jump, right, left, LMB, RMB, sneak, aux1, down, up, zoom. * example: `{jump=false, right=true, left=false, LMB=false, RMB=false, - sneak=true, aux1=false, down=false, up=false}` + sneak=true, aux1=false, down=false, up=false, zoom=false}` + * The `zoom` field is available since 5.3 * `get_player_control_bits()`: returns integer with bit packed player pressed keys. * bit nr/meaning: 0/up, 1/down, 2/left, 3/right, 4/jump, 5/aux1, 6/sneak, - 7/LMB, 8/RMB + 7/LMB, 8/RMB, 9/zoom (zoom available since 5.3) * `set_physics_override(override_table)` * `override_table` is a table with the following fields: * `speed`: multiplier to default walking speed value (default: `1`) diff --git a/src/client/game.cpp b/src/client/game.cpp index 139742cec..069c482ca 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2490,7 +2490,7 @@ void Game::updatePlayerControl(const CameraOrientation &cam) input->joystick.getAxisWithoutDead(JA_FORWARD_MOVE) ); - u32 keypress_bits = + u32 keypress_bits = ( ( (u32)(isKeyDown(KeyType::FORWARD) & 0x1) << 0) | ( (u32)(isKeyDown(KeyType::BACKWARD) & 0x1) << 1) | ( (u32)(isKeyDown(KeyType::LEFT) & 0x1) << 2) | @@ -2499,7 +2499,8 @@ void Game::updatePlayerControl(const CameraOrientation &cam) ( (u32)(isKeyDown(KeyType::SPECIAL1) & 0x1) << 5) | ( (u32)(isKeyDown(KeyType::SNEAK) & 0x1) << 6) | ( (u32)(input->getLeftState() & 0x1) << 7) | - ( (u32)(input->getRightState() & 0x1) << 8 + ( (u32)(input->getRightState() & 0x1) << 8) | + ( (u32)(isKeyDown(KeyType::ZOOM) & 0x1) << 9) ); #ifdef ANDROID diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index fed3b6f85..b3008bb50 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -501,6 +501,7 @@ void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao, player->control.sneak = (keyPressed & 64); player->control.LMB = (keyPressed & 128); player->control.RMB = (keyPressed & 256); + player->control.zoom = (keyPressed & 512); if (playersao->checkMovementCheat()) { // Call callbacks diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 0a9f3117b..e7394133a 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -1459,6 +1459,8 @@ int ObjectRef::l_get_player_control(lua_State *L) lua_setfield(L, -2, "LMB"); lua_pushboolean(L, control.RMB); lua_setfield(L, -2, "RMB"); + lua_pushboolean(L, control.zoom); + lua_setfield(L, -2, "zoom"); return 1; } -- cgit v1.2.3 From 3a6dfda358112e2fb5d6f887a1a1e936eacddadd Mon Sep 17 00:00:00 2001 From: Danila Shutov Date: Tue, 16 Jun 2020 22:48:31 +0300 Subject: Make shading of CAOs optional (#10033) --- client/shaders/object_shader/opengl_vertex.glsl | 4 ++++ doc/lua_api.txt | 3 +++ games/devtest/mods/testentities/visuals.lua | 12 +++++++++++- src/client/content_cao.cpp | 15 +++++++++++---- src/client/mesh.cpp | 2 +- src/client/shader.cpp | 6 +++++- src/client/tile.h | 2 ++ src/object_properties.cpp | 6 ++++++ src/object_properties.h | 1 + src/script/common/c_content.cpp | 3 +++ 10 files changed, 47 insertions(+), 7 deletions(-) (limited to 'doc') diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index 59171145f..968a07e22 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -39,11 +39,15 @@ void main(void) lightVec = sunPosition - worldPosition; eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz; +#if (MATERIAL_TYPE == TILE_MATERIAL_PLAIN) || (MATERIAL_TYPE == TILE_MATERIAL_PLAIN_ALPHA) + vIDiff = 1.0; +#else // This is intentional comparison with zero without any margin. // If normal is not equal to zero exactly, then we assume it's a valid, just not normalized vector vIDiff = length(gl_Normal) == 0.0 ? 1.0 : directional_ambient(normalize(gl_Normal)); +#endif gl_FrontColor = gl_BackColor = gl_Color; } diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 07e9698e8..11c5cfb91 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6644,6 +6644,9 @@ Player properties need to be saved manually. damage_texture_modifier = "^[brighten", -- Texture modifier to be applied for a short duration when object is hit + + shaded = true, + -- Setting this to 'false' disables diffuse lighting of entity } Entity definition diff --git a/games/devtest/mods/testentities/visuals.lua b/games/devtest/mods/testentities/visuals.lua index 314f51657..83f361f16 100644 --- a/games/devtest/mods/testentities/visuals.lua +++ b/games/devtest/mods/testentities/visuals.lua @@ -55,6 +55,17 @@ minetest.register_entity("testentities:mesh", { }, }) +minetest.register_entity("testentities:mesh_unshaded", { + initial_properties = { + visual = "mesh", + mesh = "testnodes_pyramid.obj", + textures = { + "testnodes_mesh_stripes2.png" + }, + shaded = false, + }, +}) + -- Advanced visual tests -- A test entity for testing animated and yaw-modulated sprites @@ -71,4 +82,3 @@ minetest.register_entity("testentities:yawsprite", { self.object:set_sprite({x=0, y=0}, 1, 0, true) end, }) - diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index eec4e3de0..5352c35f4 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -577,10 +577,16 @@ void GenericCAO::addToScene(ITextureSource *tsrc) if (m_enable_shaders) { IShaderSource *shader_source = m_client->getShaderSource(); - u32 shader_id = shader_source->getShader( - "object_shader", - (m_prop.use_texture_alpha) ? TILE_MATERIAL_ALPHA : TILE_MATERIAL_BASIC, - NDT_NORMAL); + MaterialType material_type; + + if (m_prop.shaded && m_prop.glow == 0) + material_type = (m_prop.use_texture_alpha) ? + TILE_MATERIAL_ALPHA : TILE_MATERIAL_BASIC; + else + material_type = (m_prop.use_texture_alpha) ? + TILE_MATERIAL_PLAIN_ALPHA : TILE_MATERIAL_PLAIN; + + u32 shader_id = shader_source->getShader("object_shader", material_type, NDT_NORMAL); m_material_type = shader_source->getShaderInfo(shader_id).material; } else { m_material_type = (m_prop.use_texture_alpha) ? @@ -1504,6 +1510,7 @@ bool GenericCAO::visualExpiryRequired(const ObjectProperties &new_) const return old.backface_culling != new_.backface_culling || old.is_visible != new_.is_visible || old.mesh != new_.mesh || + old.shaded != new_.shaded || old.use_texture_alpha != new_.use_texture_alpha || old.visual != new_.visual || old.visual_size != new_.visual_size || diff --git a/src/client/mesh.cpp b/src/client/mesh.cpp index 68832849e..e1ec22068 100644 --- a/src/client/mesh.cpp +++ b/src/client/mesh.cpp @@ -341,7 +341,7 @@ bool checkMeshNormals(scene::IMesh *mesh) // hurting the performance and covering only really weird broken models. f32 length = buffer->getNormal(0).getLength(); - if (!std::isfinite(length) || std::fabs(length) < 1e-10f) + if (!std::isfinite(length) || length < 1e-10f) return false; } diff --git a/src/client/shader.cpp b/src/client/shader.cpp index eda415ce6..ee6079f7a 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -537,11 +537,13 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp shaderinfo.base_material = video::EMT_SOLID; break; case TILE_MATERIAL_ALPHA: + case TILE_MATERIAL_PLAIN_ALPHA: case TILE_MATERIAL_LIQUID_TRANSPARENT: case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT: shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL; break; case TILE_MATERIAL_BASIC: + case TILE_MATERIAL_PLAIN: case TILE_MATERIAL_WAVING_LEAVES: case TILE_MATERIAL_WAVING_PLANTS: case TILE_MATERIAL_WAVING_LIQUID_BASIC: @@ -644,9 +646,11 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp "TILE_MATERIAL_WAVING_LIQUID_BASIC", "TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT", "TILE_MATERIAL_WAVING_LIQUID_OPAQUE", + "TILE_MATERIAL_PLAIN", + "TILE_MATERIAL_PLAIN_ALPHA", }; - for (int i = 0; i < 10; i++){ + for (int i = 0; i < 12; i++){ shaders_header += "#define "; shaders_header += materialTypes[i]; shaders_header += " "; diff --git a/src/client/tile.h b/src/client/tile.h index 533df676e..52e0a2b2b 100644 --- a/src/client/tile.h +++ b/src/client/tile.h @@ -150,6 +150,8 @@ enum MaterialType{ TILE_MATERIAL_WAVING_LIQUID_BASIC, TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT, TILE_MATERIAL_WAVING_LIQUID_OPAQUE, + TILE_MATERIAL_PLAIN, + TILE_MATERIAL_PLAIN_ALPHA }; // Material flags diff --git a/src/object_properties.cpp b/src/object_properties.cpp index 6ff344dce..8d51bcbfa 100644 --- a/src/object_properties.cpp +++ b/src/object_properties.cpp @@ -69,6 +69,7 @@ std::string ObjectProperties::dump() os << ", zoom_fov=" << zoom_fov; os << ", use_texture_alpha=" << use_texture_alpha; os << ", damage_texture_modifier=" << damage_texture_modifier; + os << ", shaded=" << shaded; return os.str(); } @@ -116,6 +117,7 @@ void ObjectProperties::serialize(std::ostream &os) const writeF32(os, zoom_fov); writeU8(os, use_texture_alpha); os << serializeString(damage_texture_modifier); + writeU8(os, shaded); // Add stuff only at the bottom. // Never remove anything, because we don't want new versions of this @@ -170,5 +172,9 @@ void ObjectProperties::deSerialize(std::istream &is) use_texture_alpha = readU8(is); try { damage_texture_modifier = deSerializeString(is); + u8 tmp = readU8(is); + if (is.eof()) + throw SerializationError(""); + shaded = tmp; } catch (SerializationError &e) {} } diff --git a/src/object_properties.h b/src/object_properties.h index f7848f5a2..f010c1daf 100644 --- a/src/object_properties.h +++ b/src/object_properties.h @@ -61,6 +61,7 @@ struct ObjectProperties float eye_height = 1.625f; float zoom_fov = 0.0f; bool use_texture_alpha = false; + bool shaded = true; ObjectProperties(); std::string dump(); diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 2157d087d..3dfd7ce61 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -327,6 +327,7 @@ void read_object_properties(lua_State *L, int index, getfloatfield(L, -1, "zoom_fov", prop->zoom_fov); getboolfield(L, -1, "use_texture_alpha", prop->use_texture_alpha); + getboolfield(L, -1, "shaded", prop->shaded); getstringfield(L, -1, "damage_texture_modifier", prop->damage_texture_modifier); } @@ -411,6 +412,8 @@ void push_object_properties(lua_State *L, ObjectProperties *prop) lua_setfield(L, -2, "zoom_fov"); lua_pushboolean(L, prop->use_texture_alpha); lua_setfield(L, -2, "use_texture_alpha"); + lua_pushboolean(L, prop->shaded); + lua_setfield(L, -2, "shaded"); lua_pushlstring(L, prop->damage_texture_modifier.c_str(), prop->damage_texture_modifier.size()); lua_setfield(L, -2, "damage_texture_modifier"); } -- cgit v1.2.3 From a1b444bb61e6c9dcb0581a8550fd7795a3555cec Mon Sep 17 00:00:00 2001 From: oilboi <47129783+oilboi@users.noreply.github.com> Date: Wed, 17 Jun 2020 13:59:02 -0400 Subject: Fix typo (#10043) --- doc/menu_lua_api.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index 4eccf5d10..724e37855 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -11,7 +11,7 @@ Description of formspec language to show your menu is in lua_api.txt Callbacks --------- -core.buttonhandler(fields): called when a button is pressed. +core.button_handler(fields): called when a button is pressed. ^ fields = {name1 = value1, name2 = value2, ...} core.event_handler(event) ^ event: "MenuQuit", "KeyEnter", "ExitButton" or "EditBoxEnter" -- cgit v1.2.3 From f7c78993f61e410f969f981c31833e465e015fde Mon Sep 17 00:00:00 2001 From: v-rob Date: Tue, 23 Jun 2020 09:59:02 -0700 Subject: Document deprecation of *_hovered and *_pressed styles (#10092) --- doc/lua_api.txt | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 11c5cfb91..f2a83eca5 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2706,13 +2706,17 @@ Some types may inherit styles from parent types. * alpha - boolean, whether to draw alpha in bgimg. Default true. * bgcolor - color, sets button tint. * bgcolor_hovered - color when hovered. Defaults to a lighter bgcolor when not provided. + * This is deprecated, use states instead. * bgcolor_pressed - color when pressed. Defaults to a darker bgcolor when not provided. + * This is deprecated, use states instead. * bgimg - standard background image. Defaults to none. * bgimg_hovered - background image when hovered. Defaults to bgimg when not provided. + * This is deprecated, use states instead. * bgimg_middle - Makes the bgimg textures render in 9-sliced mode and defines the middle rect. See background9[] documentation for more details. This property also pads the button's content when set. * bgimg_pressed - background image when pressed. Defaults to bgimg when not provided. + * This is deprecated, use states instead. * border - boolean, draw border. Set to false to hide the bevelled button pane. Default true. * content_offset - 2d vector, shifts the position of the button's content without resizing it. * noclip - boolean, set to true to allow the element to exceed formspec bounds. @@ -2741,7 +2745,9 @@ Some types may inherit styles from parent types. * image_button (additional properties) * fgimg - standard image. Defaults to none. * fgimg_hovered - image when hovered. Defaults to fgimg when not provided. + * This is deprecated, use states instead. * fgimg_pressed - image when pressed. Defaults to fgimg when not provided. + * This is deprecated, use states instead. * NOTE: The parameters of any given image_button will take precedence over fgimg/fgimg_pressed * tabheader * noclip - boolean, set to true to allow the element to exceed formspec bounds. -- cgit v1.2.3 From 2384c10e104fd0c945f3677130e7d25c0a841482 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 9 Jul 2020 22:04:22 +0200 Subject: Continue with 5.4.0-dev --- CMakeLists.txt | 4 ++-- doc/client_lua_api.txt | 2 +- doc/menu_lua_api.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'doc') diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d33a2a7e..fec9709d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,12 +16,12 @@ set(CLANG_MINIMUM_VERSION "3.4") # Also remember to set PROTOCOL_VERSION in network/networkprotocol.h when releasing set(VERSION_MAJOR 5) -set(VERSION_MINOR 3) +set(VERSION_MINOR 4) set(VERSION_PATCH 0) set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string") # Change to false for releases -set(DEVELOPMENT_BUILD FALSE) +set(DEVELOPMENT_BUILD TRUE) set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") if(VERSION_EXTRA) diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index c9cd8ac93..04815aaa4 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -1,4 +1,4 @@ -Minetest Lua Client Modding API Reference 5.3.0 +Minetest Lua Client Modding API Reference 5.4.0 ================================================ * More information at * Developer Wiki: diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index 724e37855..76bebe08b 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -1,4 +1,4 @@ -Minetest Lua Mainmenu API Reference 5.3.0 +Minetest Lua Mainmenu API Reference 5.4.0 ========================================= Introduction -- cgit v1.2.3 From b1ff04e06da531dc52f6ee91e2967b39743033e6 Mon Sep 17 00:00:00 2001 From: v-rob Date: Fri, 10 Jul 2020 03:11:26 -0700 Subject: Formspec: Make dropdowns optionally return event based on index, not value (#9496) --- doc/lua_api.txt | 15 ++++++++++++--- src/gui/guiFormSpecMenu.cpp | 39 +++++++++++++++++++++++---------------- src/gui/guiFormSpecMenu.h | 1 + src/network/networkprotocol.h | 4 +++- 4 files changed, 39 insertions(+), 20 deletions(-) (limited to 'doc') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index f2a83eca5..2ac4d6766 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2443,7 +2443,7 @@ Elements * `color` is color specified as a `ColorString`. If the alpha component is left blank, the box will be semitransparent. -### `dropdown[,;;;,, ...,;]` +### `dropdown[,;;;,, ...,;;]` * Show a dropdown field * **Important note**: There are two different operation modes: @@ -2454,8 +2454,12 @@ Elements * Fieldname data is transferred to Lua * Items to be shown in dropdown * Index of currently selected dropdown item +* `index event` (optional, allowed parameter since formspec version 4): Specifies the + event field value for selected items. + * `true`: Selected item index + * `false` (default): Selected item value -### `dropdown[,;,;;,, ...,;]` +### `dropdown[,;,;;,, ...,;;]` * Show a dropdown field * **Important note**: This syntax for dropdowns can only be used with the @@ -2468,6 +2472,10 @@ Elements * Fieldname data is transferred to Lua * Items to be shown in dropdown * Index of currently selected dropdown item +* `index event` (optional, allowed parameter since formspec version 4): Specifies the + event field value for selected items. + * `true`: Selected item index + * `false` (default): Selected item value ### `checkbox[,;;