diff options
Diffstat (limited to 'games')
52 files changed, 1037 insertions, 78 deletions
diff --git a/games/devtest/.luacheckrc b/games/devtest/.luacheckrc new file mode 100644 index 000000000..1c7d3994f --- /dev/null +++ b/games/devtest/.luacheckrc @@ -0,0 +1,43 @@ +unused_args = false +allow_defined_top = true +max_string_line_length = false +max_line_length = false + +ignore = { + "131", -- Unused global variable + "211", -- Unused local variable + "231", -- Local variable never accessed + "311", -- Value assigned to a local variable is unused + "412", -- Redefining an argument + "421", -- Shadowing a local variable + "431", -- Shadowing an upvalue + "432", -- Shadowing an upvalue argument + "611", -- Line contains only whitespace +} + +read_globals = { + "ItemStack", + "INIT", + "DIR_DELIM", + "dump", "dump2", + "fgettext", "fgettext_ne", + "vector", + "VoxelArea", + "profiler", + "Settings", + "check", + "PseudoRandom", + + string = {fields = {"split", "trim"}}, + table = {fields = {"copy", "getn", "indexof", "insert_all"}}, + math = {fields = {"hypot", "round"}}, +} + +globals = { + "aborted", + "minetest", + "core", + os = { fields = { "tempfolder" } }, + "_", +} + diff --git a/games/devtest/game.conf b/games/devtest/game.conf index d6e382ad7..0f5656c99 100644 --- a/games/devtest/game.conf +++ b/games/devtest/game.conf @@ -1,2 +1,2 @@ -name = Development Test +title = 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/mods/basetools/init.lua b/games/devtest/mods/basetools/init.lua index fd83b82eb..3ec69d39f 100644 --- a/games/devtest/mods/basetools/init.lua +++ b/games/devtest/mods/basetools/init.lua @@ -279,50 +279,135 @@ minetest.register_tool("basetools:sword_wood", { }) minetest.register_tool("basetools:sword_stone", { description = "Stone Sword".."\n".. - "Damage: fleshy=4", + "Damage: fleshy=5", inventory_image = "basetools_stonesword.png", tool_capabilities = { full_punch_interval = 1.0, max_drop_level=0, - damage_groups = {fleshy=4}, + damage_groups = {fleshy=5}, } }) minetest.register_tool("basetools:sword_steel", { description = "Steel Sword".."\n".. - "Damage: fleshy=6", + "Damage: fleshy=10", inventory_image = "basetools_steelsword.png", tool_capabilities = { full_punch_interval = 1.0, max_drop_level=1, - damage_groups = {fleshy=6}, + damage_groups = {fleshy=10}, + } +}) +minetest.register_tool("basetools:sword_titanium", { + description = "Titanium Sword".."\n".. + "Damage: fleshy=100", + inventory_image = "basetools_titaniumsword.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=1, + damage_groups = {fleshy=100}, + } +}) +minetest.register_tool("basetools:sword_blood", { + description = "Blood Sword".."\n".. + "Damage: fleshy=1000", + inventory_image = "basetools_bloodsword.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=1, + damage_groups = {fleshy=1000}, + } +}) + +-- Max. damage sword +minetest.register_tool("basetools:sword_mese", { + description = "Mese Sword".."\n".. + "Damage: fleshy=32767, fiery=32767, icy=32767".."\n".. + "Full Punch Interval: 0.0s", + inventory_image = "basetools_mesesword.png", + tool_capabilities = { + full_punch_interval = 0.0, + max_drop_level=1, + damage_groups = {fleshy=32767, fiery=32767, icy=32767}, } }) -- Fire/Ice sword: Deal damage to non-fleshy damage groups minetest.register_tool("basetools:sword_fire", { description = "Fire Sword".."\n".. - "Damage: icy=6", + "Damage: icy=10", inventory_image = "basetools_firesword.png", tool_capabilities = { full_punch_interval = 1.0, max_drop_level=0, - damage_groups = {icy=6}, + damage_groups = {icy=10}, } }) minetest.register_tool("basetools:sword_ice", { description = "Ice Sword".."\n".. - "Damage: fiery=6", + "Damage: fiery=10", inventory_image = "basetools_icesword.png", tool_capabilities = { full_punch_interval = 1.0, max_drop_level=0, - damage_groups = {fiery=6}, + damage_groups = {fiery=10}, + } +}) +minetest.register_tool("basetools:sword_elemental", { + description = "Elemental Sword".."\n".. + "Damage: fiery=10, icy=10", + inventory_image = "basetools_elementalsword.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=0, + damage_groups = {fiery=10, icy=10}, } }) +-- Healing weapons: heal HP +minetest.register_tool("basetools:dagger_heal", { + description = "Healing Dagger".."\n".. + "Heal: fleshy=1".."\n".. + "Full Punch Interval: 0.5s", + inventory_image = "basetools_healdagger.png", + tool_capabilities = { + full_punch_interval = 0.5, + damage_groups = {fleshy=-1}, + } +}) +minetest.register_tool("basetools:sword_heal", { + description = "Healing Sword".."\n".. + "Heal: fleshy=10", + inventory_image = "basetools_healsword.png", + tool_capabilities = { + full_punch_interval = 1.0, + damage_groups = {fleshy=-10}, + } +}) +minetest.register_tool("basetools:sword_heal_super", { + description = "Super Healing Sword".."\n".. + "Heal: fleshy=32768, fiery=32768, icy=32768", + inventory_image = "basetools_superhealsword.png", + tool_capabilities = { + full_punch_interval = 1.0, + damage_groups = {fleshy=-32768, fiery=-32768, icy=-32768}, + } +}) + + -- -- Dagger: Low damage, fast punch interval -- +minetest.register_tool("basetools:dagger_wood", { + description = "Wooden Dagger".."\n".. + "Damage: fleshy=1".."\n".. + "Full Punch Interval: 0.5s", + inventory_image = "basetools_wooddagger.png", + tool_capabilities = { + full_punch_interval = 0.5, + max_drop_level=0, + damage_groups = {fleshy=1}, + } +}) minetest.register_tool("basetools:dagger_steel", { description = "Steel Dagger".."\n".. "Damage: fleshy=2".."\n".. @@ -343,7 +428,7 @@ for i=1, #uses do minetest.register_tool("basetools:pick_uses_"..string.format("%05d", u), { description = u.."-Uses Pickaxe".."\n".. "Digs cracky=3", - inventory_image = "basetools_steelpick.png^[colorize:"..color..":127", + inventory_image = "basetools_usespick.png^[colorize:"..color..":127", tool_capabilities = { max_drop_level=0, groupcaps={ @@ -355,7 +440,7 @@ for i=1, #uses do minetest.register_tool("basetools:sword_uses_"..string.format("%05d", u), { description = u.."-Uses Sword".."\n".. "Damage: fleshy=1", - inventory_image = "basetools_woodsword.png^[colorize:"..color..":127", + inventory_image = "basetools_usessword.png^[colorize:"..color..":127", tool_capabilities = { damage_groups = {fleshy=1}, punch_attack_uses = u, diff --git a/games/devtest/mods/basetools/textures/basetools_bloodsword.png b/games/devtest/mods/basetools/textures/basetools_bloodsword.png Binary files differnew file mode 100644 index 000000000..a521ba4a2 --- /dev/null +++ b/games/devtest/mods/basetools/textures/basetools_bloodsword.png diff --git a/games/devtest/mods/basetools/textures/basetools_elementalsword.png b/games/devtest/mods/basetools/textures/basetools_elementalsword.png Binary files differnew file mode 100644 index 000000000..d007217ee --- /dev/null +++ b/games/devtest/mods/basetools/textures/basetools_elementalsword.png diff --git a/games/devtest/mods/basetools/textures/basetools_firesword.png b/games/devtest/mods/basetools/textures/basetools_firesword.png Binary files differindex ee2809ab7..eca999ba1 100644 --- a/games/devtest/mods/basetools/textures/basetools_firesword.png +++ b/games/devtest/mods/basetools/textures/basetools_firesword.png diff --git a/games/devtest/mods/basetools/textures/basetools_healdagger.png b/games/devtest/mods/basetools/textures/basetools_healdagger.png Binary files differnew file mode 100644 index 000000000..3e6eb9cd0 --- /dev/null +++ b/games/devtest/mods/basetools/textures/basetools_healdagger.png diff --git a/games/devtest/mods/basetools/textures/basetools_healsword.png b/games/devtest/mods/basetools/textures/basetools_healsword.png Binary files differnew file mode 100644 index 000000000..f93fddfb2 --- /dev/null +++ b/games/devtest/mods/basetools/textures/basetools_healsword.png diff --git a/games/devtest/mods/basetools/textures/basetools_icesword.png b/games/devtest/mods/basetools/textures/basetools_icesword.png Binary files differindex 35ba8214b..55a8d609d 100644 --- a/games/devtest/mods/basetools/textures/basetools_icesword.png +++ b/games/devtest/mods/basetools/textures/basetools_icesword.png diff --git a/games/devtest/mods/basetools/textures/basetools_mesepick.png b/games/devtest/mods/basetools/textures/basetools_mesepick.png Binary files differindex 2b5e12cdb..2993b475b 100644 --- a/games/devtest/mods/basetools/textures/basetools_mesepick.png +++ b/games/devtest/mods/basetools/textures/basetools_mesepick.png diff --git a/games/devtest/mods/basetools/textures/basetools_mesesword.png b/games/devtest/mods/basetools/textures/basetools_mesesword.png Binary files differnew file mode 100644 index 000000000..bc82769bc --- /dev/null +++ b/games/devtest/mods/basetools/textures/basetools_mesesword.png diff --git a/games/devtest/mods/basetools/textures/basetools_superhealsword.png b/games/devtest/mods/basetools/textures/basetools_superhealsword.png Binary files differnew file mode 100644 index 000000000..4175a0917 --- /dev/null +++ b/games/devtest/mods/basetools/textures/basetools_superhealsword.png diff --git a/games/devtest/mods/basetools/textures/basetools_titaniumsword.png b/games/devtest/mods/basetools/textures/basetools_titaniumsword.png Binary files differnew file mode 100644 index 000000000..55e22c7d5 --- /dev/null +++ b/games/devtest/mods/basetools/textures/basetools_titaniumsword.png diff --git a/games/devtest/mods/basetools/textures/basetools_usespick.png b/games/devtest/mods/basetools/textures/basetools_usespick.png Binary files differnew file mode 100644 index 000000000..27850f961 --- /dev/null +++ b/games/devtest/mods/basetools/textures/basetools_usespick.png diff --git a/games/devtest/mods/basetools/textures/basetools_usessword.png b/games/devtest/mods/basetools/textures/basetools_usessword.png Binary files differnew file mode 100644 index 000000000..0eaf4cf38 --- /dev/null +++ b/games/devtest/mods/basetools/textures/basetools_usessword.png diff --git a/games/devtest/mods/basetools/textures/basetools_wooddagger.png b/games/devtest/mods/basetools/textures/basetools_wooddagger.png Binary files differnew file mode 100644 index 000000000..6e5ab0fd6 --- /dev/null +++ b/games/devtest/mods/basetools/textures/basetools_wooddagger.png diff --git a/games/devtest/mods/testentities/armor.lua b/games/devtest/mods/testentities/armor.lua index 306953d50..415e5bd19 100644 --- a/games/devtest/mods/testentities/armor.lua +++ b/games/devtest/mods/testentities/armor.lua @@ -4,10 +4,19 @@ local phasearmor = { [0]={icy=100}, [1]={fiery=100}, - [2]={fleshy=100}, - [3]={immortal=1}, - [4]={punch_operable=1}, + [2]={icy=100, fiery=100}, + [3]={fleshy=-100}, + [4]={fleshy=1}, + [5]={fleshy=10}, + [6]={fleshy=50}, + [7]={fleshy=100}, + [8]={fleshy=200}, + [9]={fleshy=1000}, + [10]={fleshy=32767}, + [11]={immortal=1}, + [12]={punch_operable=1}, } +local max_phase = 12 minetest.register_entity("testentities:armorball", { initial_properties = { @@ -17,11 +26,11 @@ minetest.register_entity("testentities:armorball", { visual = "sprite", visual_size = {x=1, y=1}, textures = {"testentities_armorball.png"}, - spritediv = {x=1, y=5}, + spritediv = {x=1, y=max_phase+1}, initial_sprite_basepos = {x=0, y=0}, }, - _phase = 2, + _phase = 7, on_activate = function(self, staticdata) minetest.log("action", "[testentities] armorball.on_activate") @@ -32,10 +41,21 @@ minetest.register_entity("testentities:armorball", { on_rightclick = function(self, clicker) -- Change armor group and sprite self._phase = self._phase + 1 - if self._phase >= 5 then + if self._phase >= max_phase + 1 then self._phase = 0 end self.object:set_sprite({x=0, y=self._phase}) self.object:set_armor_groups(phasearmor[self._phase]) end, + + on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage) + if not puncher then + return + end + local name = puncher:get_player_name() + if not name then + return + end + minetest.chat_send_player(name, "time_from_last_punch="..string.format("%.3f", time_from_last_punch).."; damage="..tostring(damage)) + end, }) diff --git a/games/devtest/mods/testentities/callbacks.lua b/games/devtest/mods/testentities/callbacks.lua index 320690b39..a212fbfbe 100644 --- a/games/devtest/mods/testentities/callbacks.lua +++ b/games/devtest/mods/testentities/callbacks.lua @@ -31,8 +31,8 @@ minetest.register_entity("testentities:callback", { on_activate = function(self, staticdata, dtime_s) message("Callback entity: on_activate! pos="..spos(self).."; dtime_s="..dtime_s) end, - on_deactivate = function(self) - message("Callback entity: on_deactivate! pos="..spos(self)) + on_deactivate = function(self, removal) + message("Callback entity: on_deactivate! pos="..spos(self) .. "; removal=" .. tostring(removal)) end, on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage) local name = get_object_name(puncher) diff --git a/games/devtest/mods/testentities/textures/testentities_armorball.png b/games/devtest/mods/testentities/textures/testentities_armorball.png Binary files differindex 88147bd1f..708c7b36d 100644 --- a/games/devtest/mods/testentities/textures/testentities_armorball.png +++ b/games/devtest/mods/testentities/textures/testentities_armorball.png diff --git a/games/devtest/mods/testformspec/formspec.lua b/games/devtest/mods/testformspec/formspec.lua index c0db695b7..5f1f8970e 100644 --- a/games/devtest/mods/testformspec/formspec.lua +++ b/games/devtest/mods/testformspec/formspec.lua @@ -195,8 +195,10 @@ local style_fs = [[ style[one_btn15;border=false;bgcolor=#1cc;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] + style[one_btn16;border=false;bgimg=testformspec_bg_9slice.png;bgimg_middle=4,6;padding=5,7;fgimg=testformspec_bg.png;fgimg_middle=1] + style[one_btn16:hovered;bgimg=testformspec_bg_9slice_hovered.png;fgimg=testformspec_bg_hovered.png] + style[one_btn16:pressed;bgimg=testformspec_bg_9slice_pressed.png;fgimg=testformspec_bg_pressed.png] + image_button[2.5,9.6;2,1;;one_btn16;9-Slice Bg] @@ -375,12 +377,16 @@ local pages = { -- Animation [[ - formspec_version[3] + formspec_version[6] 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] + image[0.5,3;1,1;testformspec_bg.png;1] + animated_image[0.5,4.25;1,1;;[combine:16x48:0,0=testformspec_bg.png:0,16=testformspec_bg_hovered.png:0,32=testformspec_bg_pressed.png;3;250;1;1] + image[0.5,5.5;2,1;testformspec_9slice.png;16,0,-16,-16] + animated_image[2.75,5.5;1.5,0.5;;[combine:300x140:0,0=testformspec_9slice.png:0,70=(testformspec_9slice.png^[transformFX);2;500;1;16,0,-16,-16] 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] @@ -430,6 +436,33 @@ mouse control = true] checkbox[0.5,5.5.5;snd_chk;Sound;] tabheader[0.5,7;8,0.65;snd_tab;Soundtab1,Soundtab2,Soundtab3;1;false;false] ]], + + -- Background + [[ + formspec_version[3] + size[12,13] + box[0,0;12,13;#f0f1] + background[0,0;0,0;testformspec_bg.png;true] + box[3.9,2.9;6.2,4.2;#d00f] + scroll_container[4,3;6,4;scrbar;vertical] + background9[1,0.5;0,0;testformspec_bg_9slice.png;true;4,6] + label[0,0.2;Backgrounds are not be applied to scroll containers,] + label[0,0.5;but to the whole form.] + scroll_container_end[] + scrollbar[3.5,3;0.3,4;vertical;scrbar;0] + container[2,11] + box[-0.1,0.5;3.2,1;#fff5] + background[0,0;2,3;testformspec_bg.png;false] + background9[1,0;2,3;testformspec_bg_9slice.png;false;4,6] + container_end[] + ]], + + -- Unsized + [[ + formspec_version[3] + background9[0,0;0,0;testformspec_bg_9slice.png;true;4,6] + background[1,1;0,0;testformspec_bg.png;true] + ]], } local page_id = 2 @@ -439,7 +472,7 @@ local function show_test_formspec(pname) page = page() end - local fs = page .. "tabheader[0,0;8,0.65;maintabs;Real Coord,Styles,Noclip,Hypertext,Tabs,Invs,Window,Anim,Model,ScrollC,Sound;" .. page_id .. ";false;false]" + local fs = page .. "tabheader[0,0;11,0.65;maintabs;Real Coord,Styles,Noclip,Hypertext,Tabs,Invs,Window,Anim,Model,ScrollC,Sound,Background,Unsized;" .. page_id .. ";false;false]" minetest.show_formspec(pname, "testformspec:formspec", fs) end diff --git a/games/devtest/mods/testformspec/textures/testformspec_9slice.png b/games/devtest/mods/testformspec/textures/testformspec_9slice.png Binary files differnew file mode 100644 index 000000000..70b6412a4 --- /dev/null +++ b/games/devtest/mods/testformspec/textures/testformspec_9slice.png diff --git a/games/devtest/mods/testitems/init.lua b/games/devtest/mods/testitems/init.lua new file mode 100644 index 000000000..33ebf50fc --- /dev/null +++ b/games/devtest/mods/testitems/init.lua @@ -0,0 +1,55 @@ +local S = minetest.get_translator("testitems") + +-- +-- Texture overlays for items +-- + +-- For the global overlay color test +local GLOBAL_COLOR_ARG = "orange" + +-- Punch handler to set random color with "color" argument in item metadata +local overlay_on_use = function(itemstack, user, pointed_thing) + local meta = itemstack:get_meta() + local color = math.random(0x0, 0xFFFFFF) + local colorstr = string.format("#%06x", color) + meta:set_string("color", colorstr) + minetest.log("action", "[testitems] Color of "..itemstack:get_name().." changed to "..colorstr) + return itemstack +end +-- Place handler to clear item metadata color +local overlay_on_place = function(itemstack, user, pointed_thing) + local meta = itemstack:get_meta() + meta:set_string("color", "") + return itemstack +end + +minetest.register_craftitem("testitems:overlay_meta", { + description = S("Texture Overlay Test Item, Meta Color") .. "\n" .. + S("Image must be a square with rainbow cross (inventory and wield)") .. "\n" .. + S("Item meta color must only change square color") .. "\n" .. + S("Punch: Set random color") .. "\n" .. + S("Place: Clear color"), + -- Base texture: A grayscale square (can be colorized) + inventory_image = "testitems_overlay_base.png", + wield_image = "testitems_overlay_base.png", + -- Overlay: A rainbow cross (NOT to be colorized!) + inventory_overlay = "testitems_overlay_overlay.png", + wield_overlay = "testitems_overlay_overlay.png", + + on_use = overlay_on_use, + on_place = overlay_on_place, + on_secondary_use = overlay_on_place, +}) +minetest.register_craftitem("testitems:overlay_global", { + description = S("Texture Overlay Test Item, Global Color") .. "\n" .. + S("Image must be an orange square with rainbow cross (inventory and wield)"), + -- Base texture: A grayscale square (to be colorized) + inventory_image = "testitems_overlay_base.png", + wield_image = "testitems_overlay_base.png", + -- Overlay: A rainbow cross (NOT to be colorized!) + inventory_overlay = "testitems_overlay_overlay.png", + wield_overlay = "testitems_overlay_overlay.png", + color = GLOBAL_COLOR_ARG, +}) + + diff --git a/games/devtest/mods/testitems/mod.conf b/games/devtest/mods/testitems/mod.conf new file mode 100644 index 000000000..f91febe01 --- /dev/null +++ b/games/devtest/mods/testitems/mod.conf @@ -0,0 +1,2 @@ +name = testitems +description = Test mod to test misc. items that are neither tools nor nodes diff --git a/games/devtest/mods/testitems/textures/testitems_overlay_base.png b/games/devtest/mods/testitems/textures/testitems_overlay_base.png Binary files differnew file mode 100644 index 000000000..f473623be --- /dev/null +++ b/games/devtest/mods/testitems/textures/testitems_overlay_base.png diff --git a/games/devtest/mods/testitems/textures/testitems_overlay_overlay.png b/games/devtest/mods/testitems/textures/testitems_overlay_overlay.png Binary files differnew file mode 100644 index 000000000..75a7d9fc3 --- /dev/null +++ b/games/devtest/mods/testitems/textures/testitems_overlay_overlay.png diff --git a/games/devtest/mods/testnodes/init.lua b/games/devtest/mods/testnodes/init.lua index 92e2c5630..d355c4278 100644 --- a/games/devtest/mods/testnodes/init.lua +++ b/games/devtest/mods/testnodes/init.lua @@ -8,3 +8,4 @@ dofile(path.."/properties.lua") dofile(path.."/liquids.lua") dofile(path.."/light.lua") dofile(path.."/textures.lua") +dofile(path.."/overlays.lua") diff --git a/games/devtest/mods/testnodes/overlays.lua b/games/devtest/mods/testnodes/overlays.lua new file mode 100644 index 000000000..294e06a16 --- /dev/null +++ b/games/devtest/mods/testnodes/overlays.lua @@ -0,0 +1,93 @@ +local S = minetest.get_translator("testnodes") + +minetest.register_node("testnodes:overlay", { + description = S("Texture Overlay Test Node") .. "\n" .. + S("Uncolorized"), + tiles = {{name = "testnodes_overlayable.png"}}, + overlay_tiles = {{name = "testnodes_overlay.png"}}, + groups = { dig_immediate = 2 }, +}) +minetest.register_node("testnodes:overlay_color_all", { + description = S("Texture Overlay Test Node, Colorized") .. "\n" .. + S("param2 changes color"), + tiles = {{name = "testnodes_overlayable.png"}}, + overlay_tiles = {{name = "testnodes_overlay.png"}}, + paramtype2 = "color", + palette = "testnodes_palette_full.png", + + + groups = { dig_immediate = 2 }, +}) +minetest.register_node("testnodes:overlay_color_overlay", { + description = S("Texture Overlay Test Node, Colorized Overlay") .. "\n" .. + S("param2 changes color of overlay"), + tiles = {{name = "testnodes_overlayable.png", color="white"}}, + overlay_tiles = {{name = "testnodes_overlay.png"}}, + paramtype2 = "color", + palette = "testnodes_palette_full.png", + + + groups = { dig_immediate = 2 }, +}) +minetest.register_node("testnodes:overlay_color_overlayed", { + description = S("Texture Overlay Test Node, Colorized Base") .. "\n" .. + S("param2 changes color of base texture"), + tiles = {{name = "testnodes_overlayable.png"}}, + overlay_tiles = {{name = "testnodes_overlay.png", color="white"}}, + paramtype2 = "color", + palette = "testnodes_palette_full.png", + + + groups = { dig_immediate = 2 }, +}) + +local global_overlay_color = "#FF2000" +minetest.register_node("testnodes:overlay_global", { + description = S("Texture Overlay Test Node, Global Color") .. "\n" .. + S("Global color = @1", global_overlay_color), + tiles = {{name = "testnodes_overlayable.png"}}, + overlay_tiles = {{name = "testnodes_overlay.png"}}, + color = global_overlay_color, + + + groups = { dig_immediate = 2 }, +}) +minetest.register_node("testnodes:overlay_global_color_all", { + description = S("Texture Overlay Test Node, Global Color + Colorized") .. "\n" .. + S("Global color = @1", global_overlay_color) .. "\n" .. + S("param2 changes color"), + tiles = {{name = "testnodes_overlayable.png"}}, + overlay_tiles = {{name = "testnodes_overlay.png"}}, + color = global_overlay_color, + paramtype2 = "color", + palette = "testnodes_palette_full.png", + + + groups = { dig_immediate = 2 }, +}) +minetest.register_node("testnodes:overlay_global_color_overlay", { + description = S("Texture Overlay Test Node, Global Color + Colorized Overlay") .. "\n" .. + S("Global color = @1", global_overlay_color) .. "\n" .. + S("param2 changes color of overlay"), + tiles = {{name = "testnodes_overlayable.png", color=global_overlay_color}}, + overlay_tiles = {{name = "testnodes_overlay.png"}}, + color = global_overlay_color, + paramtype2 = "color", + palette = "testnodes_palette_full.png", + + + groups = { dig_immediate = 2 }, +}) +minetest.register_node("testnodes:overlay_global_color_overlayed", { + description = S("Texture Overlay Test Node, Global Color + Colorized Base") .. "\n" .. + S("Global color = @1", global_overlay_color) .. "\n" .. + S("param2 changes color of base texture"), + tiles = {{name = "testnodes_overlayable.png"}}, + overlay_tiles = {{name = "testnodes_overlay.png", color=global_overlay_color}}, + color = global_overlay_color, + paramtype2 = "color", + palette = "testnodes_palette_full.png", + + + groups = { dig_immediate = 2 }, +}) diff --git a/games/devtest/mods/testnodes/properties.lua b/games/devtest/mods/testnodes/properties.lua index 51f703d7c..bacd555cd 100644 --- a/games/devtest/mods/testnodes/properties.lua +++ b/games/devtest/mods/testnodes/properties.lua @@ -13,6 +13,20 @@ minetest.register_node("testnodes:falling", { groups = { falling_node = 1, dig_immediate = 3 }, }) +minetest.register_node("testnodes:falling_facedir", { + description = S("Falling Facedir Node"), + tiles = { + "testnodes_1.png", + "testnodes_2.png", + "testnodes_3.png", + "testnodes_4.png", + "testnodes_5.png", + "testnodes_6.png", + }, + paramtype2 = "facedir", + 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"), @@ -252,9 +266,9 @@ for i=-100, 100, 25 do end -- Bouncy nodes (various bounce levels) -for i=20, 180, 20 do +for i=-140, 180, 20 do local val = math.floor(((i-20)/200)*255) - minetest.register_node("testnodes:bouncy"..i, { + minetest.register_node(("testnodes:bouncy"..i):gsub("-","NEG"), { description = S("Bouncy Node (@1%)", i), groups = {bouncy=i, dig_immediate=3}, diff --git a/games/devtest/mods/testnodes/textures.lua b/games/devtest/mods/testnodes/textures.lua index dc581b0c7..2faacdd78 100644 --- a/games/devtest/mods/testnodes/textures.lua +++ b/games/devtest/mods/testnodes/textures.lua @@ -171,3 +171,120 @@ minetest.register_node("testnodes:generated_png_dst_emb", { groups = { dig_immediate = 2 }, }) + +--[[ + +The following nodes can be used to demonstrate the TGA format support. + +Minetest supports TGA types 1, 2, 3 & 10. While adding the support for +TGA type 9 (RLE-compressed, color-mapped) is easy, it is not advisable +to do so, as it is not backwards compatible with any Minetest pre-5.5; +content creators should therefore either use TGA type 1 or 10, or PNG. + +TODO: Types 1, 2 & 10 should have two test nodes each (i.e. bottom-top +and top-bottom) for 16bpp (A1R5G5B5), 24bpp (B8G8R8), 32bpp (B8G8R8A8) +colors. + +Note: Minetest requires the optional TGA footer for a texture to load. +If a TGA image does not load in Minetest, append eight (8) null bytes, +then the string “TRUEVISION-XFILE.”, then another null byte. + +]]-- + +minetest.register_node("testnodes:tga_type1_24bpp_bt", { + description = S("TGA Type 1 (color-mapped RGB) 24bpp bottom-top Test Node"), + drawtype = "glasslike", + paramtype = "light", + sunlight_propagates = true, + tiles = { "testnodes_tga_type1_24bpp_bt.tga" }, + groups = { dig_immediate = 2 }, +}) + +minetest.register_node("testnodes:tga_type1_24bpp_tb", { + description = S("TGA Type 1 (color-mapped RGB) 24bpp top-bottom Test Node"), + drawtype = "glasslike", + paramtype = "light", + sunlight_propagates = true, + tiles = { "testnodes_tga_type1_24bpp_tb.tga" }, + groups = { dig_immediate = 2 }, +}) + +minetest.register_node("testnodes:tga_type2_16bpp_bt", { + description = S("TGA Type 2 (uncompressed RGB) 16bpp bottom-top Test Node"), + drawtype = "glasslike", + paramtype = "light", + sunlight_propagates = true, + tiles = { "testnodes_tga_type2_16bpp_bt.tga" }, + use_texture_alpha = "clip", + groups = { dig_immediate = 2 }, +}) + +minetest.register_node("testnodes:tga_type2_16bpp_tb", { + description = S("TGA Type 2 (uncompressed RGB) 16bpp top-bottom Test Node"), + drawtype = "glasslike", + paramtype = "light", + sunlight_propagates = true, + tiles = { "testnodes_tga_type2_16bpp_tb.tga" }, + use_texture_alpha = "clip", + groups = { dig_immediate = 2 }, +}) + +minetest.register_node("testnodes:tga_type2_32bpp_bt", { + description = S("TGA Type 2 (uncompressed RGB) 32bpp bottom-top Test Node"), + drawtype = "glasslike", + paramtype = "light", + sunlight_propagates = true, + tiles = { "testnodes_tga_type2_32bpp_bt.tga" }, + use_texture_alpha = "blend", + groups = { dig_immediate = 2 }, +}) + +minetest.register_node("testnodes:tga_type2_32bpp_tb", { + description = S("TGA Type 2 (uncompressed RGB) 32bpp top-bottom Test Node"), + drawtype = "glasslike", + paramtype = "light", + sunlight_propagates = true, + tiles = { "testnodes_tga_type2_32bpp_tb.tga" }, + use_texture_alpha = "blend", + groups = { dig_immediate = 2 }, +}) + +minetest.register_node("testnodes:tga_type3_16bpp_bt", { + description = S("TGA Type 3 (uncompressed grayscale) 16bpp bottom-top Test Node"), + drawtype = "glasslike", + paramtype = "light", + sunlight_propagates = true, + tiles = { "testnodes_tga_type3_16bpp_bt.tga" }, + use_texture_alpha = "blend", + groups = { dig_immediate = 2 }, +}) + +minetest.register_node("testnodes:tga_type3_16bpp_tb", { + description = S("TGA Type 3 (uncompressed grayscale) 16bpp top-bottom Test Node"), + drawtype = "glasslike", + paramtype = "light", + sunlight_propagates = true, + tiles = { "testnodes_tga_type3_16bpp_tb.tga" }, + use_texture_alpha = "blend", + groups = { dig_immediate = 2 }, +}) + +minetest.register_node("testnodes:tga_type10_32bpp_bt", { + description = S("TGA Type 10 (RLE-compressed RGB) 32bpp bottom-top Test Node"), + tiles = { "testnodes_tga_type10_32bpp_bt.tga" }, + drawtype = "glasslike", + paramtype = "light", + sunlight_propagates = true, + use_texture_alpha = "blend", + groups = { dig_immediate = 2 }, +}) + +minetest.register_node("testnodes:tga_type10_32bpp_tb", { + description = S("TGA Type 10 (RLE-compressed RGB) 32bpp top-bottom Test Node"), + drawtype = "glasslike", + paramtype = "light", + sunlight_propagates = true, + tiles = { "testnodes_tga_type10_32bpp_tb.tga" }, + use_texture_alpha = "blend", + groups = { dig_immediate = 2 }, +}) diff --git a/games/devtest/mods/testnodes/textures/testnodes_overlay.png b/games/devtest/mods/testnodes/textures/testnodes_overlay.png Binary files differnew file mode 100644 index 000000000..1c69b5e08 --- /dev/null +++ b/games/devtest/mods/testnodes/textures/testnodes_overlay.png diff --git a/games/devtest/mods/testnodes/textures/testnodes_overlayable.png b/games/devtest/mods/testnodes/textures/testnodes_overlayable.png Binary files differnew file mode 100644 index 000000000..431bc94f4 --- /dev/null +++ b/games/devtest/mods/testnodes/textures/testnodes_overlayable.png diff --git a/games/devtest/mods/testnodes/textures/testnodes_tga_type10_32bpp_bt.tga b/games/devtest/mods/testnodes/textures/testnodes_tga_type10_32bpp_bt.tga Binary files differnew file mode 100644 index 000000000..2dc587bc3 --- /dev/null +++ b/games/devtest/mods/testnodes/textures/testnodes_tga_type10_32bpp_bt.tga diff --git a/games/devtest/mods/testnodes/textures/testnodes_tga_type10_32bpp_tb.tga b/games/devtest/mods/testnodes/textures/testnodes_tga_type10_32bpp_tb.tga Binary files differnew file mode 100644 index 000000000..b44a81c79 --- /dev/null +++ b/games/devtest/mods/testnodes/textures/testnodes_tga_type10_32bpp_tb.tga diff --git a/games/devtest/mods/testnodes/textures/testnodes_tga_type1_24bpp_bt.tga b/games/devtest/mods/testnodes/textures/testnodes_tga_type1_24bpp_bt.tga Binary files differnew file mode 100644 index 000000000..d2c2ca6d2 --- /dev/null +++ b/games/devtest/mods/testnodes/textures/testnodes_tga_type1_24bpp_bt.tga diff --git a/games/devtest/mods/testnodes/textures/testnodes_tga_type1_24bpp_tb.tga b/games/devtest/mods/testnodes/textures/testnodes_tga_type1_24bpp_tb.tga Binary files differnew file mode 100644 index 000000000..dfcb98864 --- /dev/null +++ b/games/devtest/mods/testnodes/textures/testnodes_tga_type1_24bpp_tb.tga diff --git a/games/devtest/mods/testnodes/textures/testnodes_tga_type2_16bpp_bt.tga b/games/devtest/mods/testnodes/textures/testnodes_tga_type2_16bpp_bt.tga Binary files differnew file mode 100644 index 000000000..0206216bb --- /dev/null +++ b/games/devtest/mods/testnodes/textures/testnodes_tga_type2_16bpp_bt.tga diff --git a/games/devtest/mods/testnodes/textures/testnodes_tga_type2_16bpp_tb.tga b/games/devtest/mods/testnodes/textures/testnodes_tga_type2_16bpp_tb.tga Binary files differnew file mode 100644 index 000000000..2563f084b --- /dev/null +++ b/games/devtest/mods/testnodes/textures/testnodes_tga_type2_16bpp_tb.tga diff --git a/games/devtest/mods/testnodes/textures/testnodes_tga_type2_32bpp_bt.tga b/games/devtest/mods/testnodes/textures/testnodes_tga_type2_32bpp_bt.tga Binary files differnew file mode 100644 index 000000000..3350500f8 --- /dev/null +++ b/games/devtest/mods/testnodes/textures/testnodes_tga_type2_32bpp_bt.tga diff --git a/games/devtest/mods/testnodes/textures/testnodes_tga_type2_32bpp_tb.tga b/games/devtest/mods/testnodes/textures/testnodes_tga_type2_32bpp_tb.tga Binary files differnew file mode 100644 index 000000000..216de0634 --- /dev/null +++ b/games/devtest/mods/testnodes/textures/testnodes_tga_type2_32bpp_tb.tga diff --git a/games/devtest/mods/testnodes/textures/testnodes_tga_type3_16bpp_bt.tga b/games/devtest/mods/testnodes/textures/testnodes_tga_type3_16bpp_bt.tga Binary files differnew file mode 100644 index 000000000..695bb4bb1 --- /dev/null +++ b/games/devtest/mods/testnodes/textures/testnodes_tga_type3_16bpp_bt.tga diff --git a/games/devtest/mods/testnodes/textures/testnodes_tga_type3_16bpp_tb.tga b/games/devtest/mods/testnodes/textures/testnodes_tga_type3_16bpp_tb.tga Binary files differnew file mode 100644 index 000000000..c08a093b2 --- /dev/null +++ b/games/devtest/mods/testnodes/textures/testnodes_tga_type3_16bpp_tb.tga diff --git a/games/devtest/mods/testtools/README.md b/games/devtest/mods/testtools/README.md index a1eb95ed7..72f0a2db0 100644 --- a/games/devtest/mods/testtools/README.md +++ b/games/devtest/mods/testtools/README.md @@ -40,6 +40,14 @@ Usage: * Punch: Open node metadata editor +## Item Meta Editor +Edit and view metadata of items. + +Usage: + +* Place/Punch: Opens item metadata editor of the item in the next + inventory slot from the wielded item + ## Entity Rotator Changes the entity rotation (with `set_rotation`). diff --git a/games/devtest/mods/testtools/init.lua b/games/devtest/mods/testtools/init.lua index 1041acdeb..abc1ed79b 100644 --- a/games/devtest/mods/testtools/init.lua +++ b/games/devtest/mods/testtools/init.lua @@ -693,30 +693,40 @@ local function use_loadstring(param, player) return true, errOrResult end --- Node Meta Editor +-- Item Meta Editor + Node Meta Editor local node_meta_posses = {} -local node_meta_latest_keylist = {} +local meta_latest_keylist = {} -local function show_node_meta_formspec(user, pos, key, value, keylist) +local function show_meta_formspec(user, metatype, pos_or_item, key, value, keylist) local textlist if keylist then textlist = "textlist[0,0.5;2.5,6.5;keylist;"..keylist.."]" else textlist = "" end - minetest.show_formspec(user:get_player_name(), - "testtools:node_meta_editor", - "size[15,9]".. + + local form = "size[15,9]".. "label[0,0;"..F(S("Current keys:")).."]".. textlist.. "field[3,0.5;12,1;key;"..F(S("Key"))..";"..F(key).."]".. "textarea[3,1.5;12,6;value;"..F(S("Value (use empty value to delete key)"))..";"..F(value).."]".. - "button[0,8;3,1;get;"..F(S("Get value")).."]".. - "button[4,8;3,1;set;"..F(S("Set value")).."]".. - "label[0,7.2;"..F(S("pos = @1", minetest.pos_to_string(pos))).."]") + "button[4,8;3,1;set;"..F(S("Set value")).."]" + + local extra_label + local formname + if metatype == "node" then + formname = "testtools:node_meta_editor" + extra_label = S("pos = @1", minetest.pos_to_string(pos_or_item)) + else + formname = "testtools:item_meta_editor" + extra_label = S("item = @1", pos_or_item:get_name()) + end + form = form .. "label[0,7.2;"..F(extra_label).."]" + + minetest.show_formspec(user:get_player_name(), formname, form) end -local function get_node_meta_keylist(meta, playername, escaped) +local function get_meta_keylist(meta, playername, escaped) local keys = {} local ekeys = {} local mtable = meta:to_table() @@ -729,7 +739,7 @@ local function get_node_meta_keylist(meta, playername, escaped) end end if playername then - node_meta_latest_keylist[playername] = keys + meta_latest_keylist[playername] = keys end return table.concat(ekeys, ",") end @@ -750,11 +760,47 @@ minetest.register_tool("testtools:node_meta_editor", { node_meta_posses[user:get_player_name()] = pos local meta = minetest.get_meta(pos) local inv = meta:get_inventory() - show_node_meta_formspec(user, pos, "", "", get_node_meta_keylist(meta, user:get_player_name(), true)) + show_meta_formspec(user, "node", pos, "", "", get_meta_keylist(meta, user:get_player_name(), true)) return itemstack end, }) +local function get_item_next_to_wielded_item(player) + local inv = player:get_inventory() + local wield = player:get_wield_index() + local itemstack = inv:get_stack("main", wield+1) + return itemstack +end +local function set_item_next_to_wielded_item(player, itemstack) + local inv = player:get_inventory() + local wield = player:get_wield_index() + inv:set_stack("main", wield+1, itemstack) +end + +local function use_item_meta_editor(itemstack, user, pointed_thing) + if not user:is_player() then + return itemstack + end + local item_to_edit = get_item_next_to_wielded_item(user) + if item_to_edit:is_empty() then + minetest.chat_send_player(user:get_player_name(), S("Place an item next to the Item Meta Editor in your inventory first!")) + return itemstack + end + local meta = item_to_edit:get_meta() + show_meta_formspec(user, "item", item_to_edit, "", "", get_meta_keylist(meta, user:get_player_name(), true)) + return itemstack +end + +minetest.register_tool("testtools:item_meta_editor", { + description = S("Item Meta Editor") .. "\n" .. + S("Punch/Place: Edit item metadata of item in the next inventory slot"), + inventory_image = "testtools_item_meta_editor.png", + groups = { testtool = 1, disable_repair = 1 }, + on_use = use_item_meta_editor, + on_secondary_use = use_item_meta_editor, + on_place = use_item_meta_editor, +}) + minetest.register_on_player_receive_fields(function(player, formname, fields) if not (player and player:is_player()) then return @@ -832,17 +878,30 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) player:set_wielded_item(witem) end end - elseif formname == "testtools:node_meta_editor" then + elseif formname == "testtools:node_meta_editor" or formname == "testtools:item_meta_editor" then local name = player:get_player_name() - local pos = node_meta_posses[name] + local metatype + local pos_or_item + if formname == "testtools:node_meta_editor" then + metatype = "node" + pos_or_item = node_meta_posses[name] + else + metatype = "item" + pos_or_item = get_item_next_to_wielded_item(player) + end if fields.keylist then local evnt = minetest.explode_textlist_event(fields.keylist) if evnt.type == "DCL" or evnt.type == "CHG" then - local keylist_table = node_meta_latest_keylist[name] - if not pos then + local keylist_table = meta_latest_keylist[name] + if metatype == "node" and not pos_or_item then return end - local meta = minetest.get_meta(pos) + local meta + if metatype == "node" then + meta = minetest.get_meta(pos_or_item) + else + meta = pos_or_item:get_meta() + end if not keylist_table then return end @@ -856,31 +915,37 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) keylist_escaped[k] = F(v) end local keylist = table.concat(keylist_escaped, ",") - show_node_meta_formspec(player, pos, key, value, keylist) + show_meta_formspec(player, metatype, pos_or_item, key, value, keylist) return end elseif fields.key and fields.key ~= "" and fields.value then - if not pos then + if metatype == "node" and not pos_or_item then return end - local meta = minetest.get_meta(pos) - if fields.get then - local value = meta:get_string(fields.key) - show_node_meta_formspec(player, pos, fields.key, value, - get_node_meta_keylist(meta, name, true)) - return - elseif fields.set then + local meta + if metatype == "node" then + meta = minetest.get_meta(pos_or_item) + elseif metatype == "item" then + if pos_or_item:is_empty() then + return + end + meta = pos_or_item:get_meta() + end + if fields.set then meta:set_string(fields.key, fields.value) - show_node_meta_formspec(player, pos, fields.key, fields.value, - get_node_meta_keylist(meta, name, true)) - return + if metatype == "item" then + set_item_next_to_wielded_item(player, pos_or_item) + end + show_meta_formspec(player, metatype, pos_or_item, fields.key, fields.value, + get_meta_keylist(meta, name, true)) end + return end end end) minetest.register_on_leaveplayer(function(player) local name = player:get_player_name() - node_meta_latest_keylist[name] = nil + meta_latest_keylist[name] = nil node_meta_posses[name] = nil end) diff --git a/games/devtest/mods/testtools/textures/testtools_item_meta_editor.png b/games/devtest/mods/testtools/textures/testtools_item_meta_editor.png Binary files differnew file mode 100644 index 000000000..5cebb0a9d --- /dev/null +++ b/games/devtest/mods/testtools/textures/testtools_item_meta_editor.png diff --git a/games/devtest/mods/unittests/async_env.lua b/games/devtest/mods/unittests/async_env.lua new file mode 100644 index 000000000..b7edf941e --- /dev/null +++ b/games/devtest/mods/unittests/async_env.lua @@ -0,0 +1,168 @@ +-- helper + +core.register_async_dofile(core.get_modpath(core.get_current_modname()) .. + DIR_DELIM .. "inside_async_env.lua") + +local function deepequal(a, b) + if type(a) == "function" then + return type(b) == "function" + elseif type(a) ~= "table" then + return a == b + elseif type(b) ~= "table" then + return false + end + for k, v in pairs(a) do + if not deepequal(v, b[k]) then + return false + end + end + for k, v in pairs(b) do + if not deepequal(a[k], v) then + return false + end + end + return true +end + +-- Object Passing / Serialization + +local test_object = { + name = "stairs:stair_glass", + type = "node", + groups = {oddly_breakable_by_hand = 3, cracky = 3, stair = 1}, + description = "Glass Stair", + sounds = { + dig = {name = "default_glass_footstep", gain = 0.5}, + footstep = {name = "default_glass_footstep", gain = 0.3}, + dug = {name = "default_break_glass", gain = 1} + }, + node_box = { + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + {-0.5, 0, 0, 0.5, 0.5, 0.5} + }, + type = "fixed" + }, + tiles = { + {name = "stairs_glass_split.png", backface_culling = true}, + {name = "default_glass.png", backface_culling = true}, + {name = "stairs_glass_stairside.png^[transformFX", backface_culling = true} + }, + on_place = function(itemstack, placer) + return core.is_player(placer) + end, + sunlight_propagates = true, + is_ground_content = false, + light_source = 0, +} + +local function test_object_passing() + local tmp = core.serialize_roundtrip(test_object) + assert(deepequal(test_object, tmp)) + + local circular_key = {"foo", "bar"} + circular_key[circular_key] = true + tmp = core.serialize_roundtrip(circular_key) + assert(tmp[1] == "foo") + assert(tmp[2] == "bar") + assert(tmp[tmp] == true) + + local circular_value = {"foo"} + circular_value[2] = circular_value + tmp = core.serialize_roundtrip(circular_value) + assert(tmp[1] == "foo") + assert(tmp[2] == tmp) + + -- Two-segment cycle + local cycle_seg_1, cycle_seg_2 = {}, {} + cycle_seg_1[1] = cycle_seg_2 + cycle_seg_2[1] = cycle_seg_1 + tmp = core.serialize_roundtrip(cycle_seg_1) + assert(tmp[1][1] == tmp) + + -- Duplicated value without a cycle + local acyclic_dup_holder = {} + tmp = ItemStack("") + acyclic_dup_holder[tmp] = tmp + tmp = core.serialize_roundtrip(acyclic_dup_holder) + for k, v in pairs(tmp) do + assert(rawequal(k, v)) + end +end +unittests.register("test_object_passing", test_object_passing) + +local function test_userdata_passing(_, pos) + -- basic userdata passing + local obj = table.copy(test_object.tiles[1]) + obj.test = ItemStack("default:cobble 99") + local tmp = core.serialize_roundtrip(obj) + assert(type(tmp.test) == "userdata") + assert(obj.test:to_string() == tmp.test:to_string()) + + -- object can't be passed, should error + obj = core.raycast(pos, pos) + assert(not pcall(core.serialize_roundtrip, obj)) + + -- VManip + local vm = core.get_voxel_manip(pos, pos) + local expect = vm:get_node_at(pos) + local vm2 = core.serialize_roundtrip(vm) + assert(deepequal(vm2:get_node_at(pos), expect)) +end +unittests.register("test_userdata_passing", test_userdata_passing, {map=true}) + +-- Asynchronous jobs + +local function test_handle_async(cb) + -- Basic test including mod name tracking and unittests.async_test() + -- which is defined inside_async_env.lua + local func = function(x) + return core.get_last_run_mod(), _VERSION, unittests[x]() + end + local expect = {core.get_last_run_mod(), _VERSION, true} + + core.handle_async(func, function(...) + if not deepequal(expect, {...}) then + return cb("Values did not equal") + end + if core.get_last_run_mod() ~= expect[1] then + return cb("Mod name not tracked correctly") + end + + -- Test passing of nil arguments and return values + core.handle_async(function(a, b) + return a, b + end, function(a, b) + if b ~= 123 then + return cb("Argument went missing") + end + cb() + end, nil, 123) + end, "async_test") +end +unittests.register("test_handle_async", test_handle_async, {async=true}) + +local function test_userdata_passing2(cb, _, pos) + -- VManip: check transfer into other env + local vm = core.get_voxel_manip(pos, pos) + local expect = vm:get_node_at(pos) + + core.handle_async(function(vm_, pos_) + return vm_:get_node_at(pos_) + end, function(ret) + if not deepequal(expect, ret) then + return cb("Node data mismatch (one-way)") + end + + -- VManip: test a roundtrip + core.handle_async(function(vm_) + return vm_ + end, function(vm2) + if not deepequal(expect, vm2:get_node_at(pos)) then + return cb("Node data mismatch (roundtrip)") + end + cb() + end, vm) + end, vm, pos) +end +unittests.register("test_userdata_passing2", test_userdata_passing2, {map=true, async=true}) diff --git a/games/devtest/mods/unittests/entity.lua b/games/devtest/mods/unittests/entity.lua new file mode 100644 index 000000000..68635cad7 --- /dev/null +++ b/games/devtest/mods/unittests/entity.lua @@ -0,0 +1,132 @@ +local log = {} + +local function insert_log(...) + log[#log+1] = string.format(...) +end + +local function objref_str(self, ref) + if ref and ref:is_player() then + return "player" + end + return self.object == ref and "self" or tostring(ref) +end + +core.register_entity("unittests:callbacks", { + initial_properties = { + hp_max = 5, + visual = "upright_sprite", + textures = { "unittests_stick.png" }, + static_save = false, + }, + + on_activate = function(self, staticdata, dtime_s) + self.object:set_armor_groups({test = 100}) + assert(self.object:get_hp() == self.initial_properties.hp_max) + insert_log("on_activate(%d)", #staticdata) + end, + on_deactivate = function(self, removal) + insert_log("on_deactivate(%s)", tostring(removal)) + end, + on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage) + insert_log("on_punch(%s, %.1f, %d)", objref_str(self, puncher), + time_from_last_punch, damage) + end, + on_death = function(self, killer) + assert(self.object:get_hp() == 0) + insert_log("on_death(%s)", objref_str(self, killer)) + end, + on_rightclick = function(self, clicker) + insert_log("on_rightclick(%s)", objref_str(self, clicker)) + end, + on_attach_child = function(self, child) + insert_log("on_attach_child(%s)", objref_str(self, child)) + end, + on_detach_child = function(self, child) + insert_log("on_detach_child(%s)", objref_str(self, child)) + end, + on_detach = function(self, parent) + insert_log("on_detach(%s)", objref_str(self, parent)) + end, + get_staticdata = function(self) + assert(false) + end, +}) + +-- + +local function check_log(expect) + if #expect ~= #log then + error("Log mismatch: " .. core.write_json(log)) + end + for i, s in ipairs(expect) do + if log[i] ~= s then + error("Log mismatch at " .. i .. ": " .. core.write_json(log)) + end + end + log = {} -- clear it for next time +end + +local function test_entity_lifecycle(_, pos) + log = {} + + -- with binary in staticdata + local obj = core.add_entity(pos, "unittests:callbacks", "abc\000def") + check_log({"on_activate(7)"}) + + obj:set_hp(0) + check_log({"on_death(nil)", "on_deactivate(true)"}) + + -- objectref must be invalid now + assert(obj:get_velocity() == nil) +end +unittests.register("test_entity_lifecycle", test_entity_lifecycle, {map=true}) + +local function test_entity_interact(_, pos) + log = {} + + local obj = core.add_entity(pos, "unittests:callbacks") + check_log({"on_activate(0)"}) + + -- rightclick + obj:right_click(obj) + check_log({"on_rightclick(self)"}) + + -- useless punch + obj:punch(obj, 0.5, {}) + check_log({"on_punch(self, 0.5, 0)"}) + + -- fatal punch + obj:punch(obj, 1.9, { + full_punch_interval = 1.0, + damage_groups = { test = 10 }, + }) + check_log({ + -- does 10 damage even though we only have 5 hp + "on_punch(self, 1.9, 10)", + "on_death(self)", + "on_deactivate(true)" + }) +end +unittests.register("test_entity_interact", test_entity_interact, {map=true}) + +local function test_entity_attach(player, pos) + log = {} + + local obj = core.add_entity(pos, "unittests:callbacks") + check_log({"on_activate(0)"}) + + -- attach player to entity + player:set_attach(obj) + check_log({"on_attach_child(player)"}) + player:set_detach() + check_log({"on_detach_child(player)"}) + + -- attach entity to player + obj:set_attach(player) + check_log({}) + obj:set_detach() + check_log({"on_detach(player)"}) + + obj:remove() +end +unittests.register("test_entity_attach", test_entity_attach, {player=true, map=true}) diff --git a/games/devtest/mods/unittests/init.lua b/games/devtest/mods/unittests/init.lua index 0754d507f..0e041be76 100644 --- a/games/devtest/mods/unittests/init.lua +++ b/games/devtest/mods/unittests/init.lua @@ -36,6 +36,7 @@ local function await(invoke) called_early = {...} else coroutine.resume(co, ...) + co = nil end end) if called_early ~= true then @@ -112,7 +113,7 @@ local function wait_for_map(player, callback) if core.get_node_or_nil(player:get_pos()) ~= nil then callback() else - minetest.after(0, check) + core.after(0, check) end end check() @@ -170,11 +171,13 @@ end -------------- -local modpath = minetest.get_modpath("unittests") +local modpath = core.get_modpath("unittests") dofile(modpath .. "/misc.lua") dofile(modpath .. "/player.lua") dofile(modpath .. "/crafting.lua") dofile(modpath .. "/itemdescription.lua") +dofile(modpath .. "/async_env.lua") +dofile(modpath .. "/entity.lua") -------------- @@ -183,7 +186,7 @@ if core.settings:get_bool("devtest_unittests_autostart", false) then coroutine.wrap(unittests.run_all)() end) else - minetest.register_chatcommand("unittests", { + core.register_chatcommand("unittests", { privs = {basic_privs=true}, description = "Runs devtest unittests (may modify player or map state)", func = function(name, param) diff --git a/games/devtest/mods/unittests/inside_async_env.lua b/games/devtest/mods/unittests/inside_async_env.lua new file mode 100644 index 000000000..4ed0fccd2 --- /dev/null +++ b/games/devtest/mods/unittests/inside_async_env.lua @@ -0,0 +1,25 @@ +unittests = {} + +core.log("info", "Hello World") + +local function do_tests() + assert(core == minetest) + -- stuff that should not be here + assert(not core.get_player_by_name) + assert(not core.set_node) + assert(not core.object_refs) + -- stuff that should be here + assert(ItemStack) + assert(core.registered_items[""]) + -- alias handling + assert(core.registered_items["unittests:steel_ingot_alias"].name == + "unittests:steel_ingot") +end + +function unittests.async_test() + local ok, err = pcall(do_tests) + if not ok then + core.log("error", err) + end + return ok +end diff --git a/games/devtest/mods/unittests/itemdescription.lua b/games/devtest/mods/unittests/itemdescription.lua index dc62de7f0..b4c218c98 100644 --- a/games/devtest/mods/unittests/itemdescription.lua +++ b/games/devtest/mods/unittests/itemdescription.lua @@ -1,17 +1,7 @@ -local full_description = "Colorful Pickaxe\nThe best pick." -minetest.register_tool("unittests:colorful_pick", { +local full_description = "Description Test Item\nFor testing item decription" +minetest.register_tool("unittests:description_test", { description = full_description, - inventory_image = "basetools_mesepick.png", - tool_capabilities = { - full_punch_interval = 1.0, - max_drop_level=3, - groupcaps={ - cracky={times={[1]=2.0, [2]=1.0, [3]=0.5}, uses=20, maxlevel=3}, - crumbly={times={[1]=2.0, [2]=1.0, [3]=0.5}, uses=20, maxlevel=3}, - snappy={times={[1]=2.0, [2]=1.0, [3]=0.5}, uses=20, maxlevel=3} - }, - damage_groups = {fleshy=4}, - }, + inventory_image = "unittests_description_test.png", }) minetest.register_chatcommand("item_description", { @@ -30,18 +20,18 @@ local function test_short_desc() return ItemStack(item):get_short_description() end - local stack = ItemStack("unittests:colorful_pick") - assert(stack:get_short_description() == "Colorful Pickaxe") - assert(get_short_description("unittests:colorful_pick") == "Colorful Pickaxe") - assert(minetest.registered_items["unittests:colorful_pick"].short_description == nil) + local stack = ItemStack("unittests:description_test") + assert(stack:get_short_description() == "Description Test Item") + assert(get_short_description("unittests:description_test") == "Description Test Item") + assert(minetest.registered_items["unittests:description_test"].short_description == nil) assert(stack:get_description() == full_description) - assert(stack:get_description() == minetest.registered_items["unittests:colorful_pick"].description) + assert(stack:get_description() == minetest.registered_items["unittests:description_test"].description) stack:get_meta():set_string("description", "Hello World") assert(stack:get_short_description() == "Hello World") assert(stack:get_description() == "Hello World") assert(get_short_description(stack) == "Hello World") - assert(get_short_description("unittests:colorful_pick") == "Colorful Pickaxe") + assert(get_short_description("unittests:description_test") == "Description Test Item") stack:get_meta():set_string("short_description", "Foo Bar") assert(stack:get_short_description() == "Foo Bar") diff --git a/games/devtest/mods/unittests/misc.lua b/games/devtest/mods/unittests/misc.lua index cf4f92cfa..4811c8008 100644 --- a/games/devtest/mods/unittests/misc.lua +++ b/games/devtest/mods/unittests/misc.lua @@ -24,7 +24,7 @@ local function test_dynamic_media(cb, player) to_player = player:get_player_name(), }, function(name) if not call_ok then - cb("impossible condition") + return cb("impossible condition") end cb() end) @@ -36,3 +36,47 @@ local function test_dynamic_media(cb, player) -- if the callback isn't called this test will just hang :shrug: end unittests.register("test_dynamic_media", test_dynamic_media, {async=true, player=true}) + +local function test_v3f_metatable(player) + assert(vector.check(player:get_pos())) +end +unittests.register("test_v3f_metatable", test_v3f_metatable, {player=true}) + +local function test_v3s16_metatable(player, pos) + local node = minetest.get_node(pos) + local found_pos = minetest.find_node_near(pos, 0, node.name, true) + assert(vector.check(found_pos)) +end +unittests.register("test_v3s16_metatable", test_v3s16_metatable, {map=true}) + +local function test_clear_meta(_, pos) + local ref = core.get_meta(pos) + + for way = 1, 3 do + ref:set_string("foo", "bar") + assert(ref:contains("foo")) + + if way == 1 then + ref:from_table({}) + elseif way == 2 then + ref:from_table(nil) + else + ref:set_string("foo", "") + end + + assert(#core.find_nodes_with_meta(pos, pos) == 0, "clearing failed " .. way) + end +end +unittests.register("test_clear_meta", test_clear_meta, {map=true}) + +local on_punch_called +minetest.register_on_punchnode(function() + on_punch_called = true +end) +unittests.register("test_punch_node", function(_, pos) + minetest.place_node(pos, {name="basenodes:dirt"}) + on_punch_called = false + minetest.punch_node(pos) + minetest.remove_node(pos) + -- currently failing: assert(on_punch_called) +end, {map=true}) diff --git a/games/devtest/mods/unittests/textures/unittests_description_test.png b/games/devtest/mods/unittests/textures/unittests_description_test.png Binary files differnew file mode 100644 index 000000000..a6be43314 --- /dev/null +++ b/games/devtest/mods/unittests/textures/unittests_description_test.png diff --git a/games/devtest/mods/util_commands/init.lua b/games/devtest/mods/util_commands/init.lua index 79acaa0d0..c37364042 100644 --- a/games/devtest/mods/util_commands/init.lua +++ b/games/devtest/mods/util_commands/init.lua @@ -246,3 +246,64 @@ function minetest.handle_node_drops(pos, drops, digger) end end end + +minetest.register_chatcommand("set_displayed_itemcount", { + params = "(-s \"<string>\" [-c <color>]) | -a <alignment_num>", + description = "Set the displayed itemcount of the wielded item", + func = function(name, param) + local player = minetest.get_player_by_name(name) + local item = player:get_wielded_item() + local meta = item:get_meta() + local flag1 = param:sub(1, 2) + if flag1 == "-s" then + if param:sub(3, 4) ~= " \"" then + return false, "Error: Space and string with \"s expected after -s." + end + local se = param:find("\"", 5, true) + if not se then + return false, "Error: String with two \"s expected after -s." + end + local s = param:sub(5, se - 1) + if param:sub(se + 1, se + 4) == " -c " then + s = minetest.colorize(param:sub(se + 5), s) + end + meta:set_string("count_meta", s) + elseif flag1 == "-a" then + local num = tonumber(param:sub(4)) + if not num then + return false, "Error: Invalid number: "..param:sub(4) + end + meta:set_int("count_alignment", num) + else + return false + end + player:set_wielded_item(item) + return true, "Displayed itemcount set." + end, +}) + +minetest.register_chatcommand("dump_item", { + params = "", + description = "Prints a dump of the wielded item in table form", + func = function(name, param) + local player = minetest.get_player_by_name(name) + local item = player:get_wielded_item() + local str = dump(item:to_table()) + print(str) + return true, str + end, +}) + +-- shadow control +minetest.register_on_joinplayer(function (player) + player:set_lighting({shadows={intensity = 0.33}}) +end) + +core.register_chatcommand("set_shadow", { + params = "<shadow_intensity>", + description = "Set shadow parameters of current player.", + func = function(player_name, param) + local shadow_intensity = tonumber(param) + minetest.get_player_by_name(player_name):set_lighting({shadows = { intensity = shadow_intensity} }) + end +}) |