From 6885943d0491db83268f8bb4743bfd82ed725ea2 Mon Sep 17 00:00:00 2001 From: Vanessa Ezekowitz Date: Tue, 14 Mar 2017 00:04:17 -0400 Subject: [PATCH] update coloredwood, digilines, technic, gloopblocks, homedecor, mesecons, pipeworks, player_textures, signs_lib, unifieddyes, and worldedit --- coloredwood/init.lua | 75 ++++---- digilines/settingtypes.txt | 13 ++ extranodes/depends.txt | 1 + extranodes/init.lua | 70 +++++++ extranodes/models/technic_insulator_clip.obj | 173 ++++++++++++++++++ .../textures/technic_insulator_clip.png | Bin 0 -> 226 bytes gloopblocks/crafts.lua | 9 + homedecor/crafts.lua | 10 +- homedecor/furniture.lua | 20 +- mesecons_extrawires/vertical.lua | 2 +- mesecons_gates/doc/and/description.html | 2 +- mesecons_gates/doc/diode/description.html | 2 +- mesecons_gates/doc/nand/description.html | 2 +- mesecons_gates/doc/nor/description.html | 2 +- mesecons_gates/doc/not/description.html | 2 +- mesecons_gates/doc/or/description.html | 2 +- mesecons_gates/init.lua | 25 ++- mesecons_insulated/init.lua | 4 +- mesecons_lamp/doc/lamp/description.html | 2 +- mesecons_lamp/init.lua | 2 +- mesecons_lightstone/init.lua | 19 +- .../doc/luacontroller/description.html | 4 +- mesecons_luacontroller/init.lua | 14 +- mesecons_stickyblocks/init.lua | 2 +- pipeworks/filter-injector.lua | 1 + player_textures/init.lua | 7 +- signs_lib/init.lua | 4 +- technic/README.md | 8 + technic/locale/it.txt | 48 ++--- technic/machines/HV/quarry.lua | 13 +- technic/machines/init.lua | 1 + technic/machines/other/constructor.lua | 2 +- technic/machines/power_monitor.lua | 67 +++++++ technic/machines/register/cables.lua | 108 ++++++++++- technic/machines/supply_converter.lua | 61 +++++- technic/machines/switching_station.lua | 81 +++++--- ...c_hv_nuclear_reactor_siren_danger_loop.ogg | Bin 13059 -> 36524 bytes .../technic_power_monitor_bottom_back.png | Bin 0 -> 506 bytes .../textures/technic_power_monitor_front.png | Bin 0 -> 428 bytes .../textures/technic_power_monitor_sides.png | Bin 0 -> 456 bytes technic/tools/mining_drill.lua | 46 ++--- technic_chests/common.lua | 23 +-- technic_chests/register.lua | 35 +++- technic_worldgen/oregen.lua | 10 +- unifieddyes/init.lua | 2 + worldedit_commands/wand.lua | 10 - worldedit_gui/depends.txt | 3 +- worldedit_gui/functionality.lua | 109 +++++++---- worldedit_gui/init.lua | 30 +++ .../textures/worldedit_gui_unknown.png | Bin 0 -> 597 bytes 50 files changed, 893 insertions(+), 233 deletions(-) create mode 100644 digilines/settingtypes.txt create mode 100644 extranodes/models/technic_insulator_clip.obj create mode 100644 extranodes/textures/technic_insulator_clip.png create mode 100644 technic/machines/power_monitor.lua create mode 100644 technic/textures/technic_power_monitor_bottom_back.png create mode 100644 technic/textures/technic_power_monitor_front.png create mode 100644 technic/textures/technic_power_monitor_sides.png create mode 100644 worldedit_gui/textures/worldedit_gui_unknown.png diff --git a/coloredwood/init.lua b/coloredwood/init.lua index a68c3880..1e3b0089 100644 --- a/coloredwood/init.lua +++ b/coloredwood/init.lua @@ -114,35 +114,36 @@ table.insert(coloredwood.hues_plus_greys, "grey") -- helper functions -local function is_stairsplus(name) - local s1, s2 +local function is_stairsplus(name, colorized) - local a,b = string.find(name, ":stair") - if a then s1 = string.sub(name, a+1, b) end + -- the format of a coloredwood stairsplus node is: + -- moreblocks:class_wood_color_shape + -- where class is "slab", "stair", etc. and shape is "three quarter", "alt", etc. - a,b = string.find(name, ":slab") - if a then s1 = string.sub(name, a+1, b) end + local a = string.find(name, ":") + local b = string.find(name, "_") - a,b = string.find(name, ":panel") - if a then s1 = string.sub(name, a+1, b) end + local class = string.sub(name, a+1, b-1) -- from colon to underscore is the class + local shape = "" + local rest - a,b = string.find(name, ":micro") - if a then s1 = string.sub(name, a+1, b) end + if class == "stair" + or class == "slab" + or class == "panel" + or class == "micro" + or class == "slope" then - a,b = string.find(name, ":slope") - if a then s1 = string.sub(name, a+1, b) end - - local h, s, v = unifieddyes.get_hsv(name) - - a,b = string.find(name, "wood") - if b then - s2 = string.sub(name, b+1) - local a,b = string.find(name, "grey") - if not a then - a,b = string.find(name, "_"..h..s) + if colorized then + colorshape = string.sub(name, b+6) + local c = string.find(colorshape, "_") or 0 -- first word after "_wood_" is color + shape = string.sub(colorshape, c) -- everything after the color is the shape + if colorshape == shape then shape = "" end -- if there was no shape + else + shape = string.sub(name, b+5) -- everything after "_wood_" is the shape end - return s1, string.sub(s2, 5) end + print(name, class, shape) + return class, shape end -- the actual nodes! @@ -187,22 +188,25 @@ for _, color in ipairs(coloredwood.hues_plus_greys) do end end --- force on_rightclick for stairsplus default wood stair/slab/etc nodes +-- force replacement node type for stairsplus default wood stair/slab/etc nodes if coloredwood.enable_stairsplus then for _, i in pairs(minetest.registered_nodes) do if string.find(i.name, "moreblocks:stair_wood") - or string.find(i.name, "moreblocks:slab_wood") - or string.find(i.name, "moreblocks:panel_wood") - or string.find(i.name, "moreblocks:micro_wood") - or string.find(i.name, "moreblocks:slope_wood") then - local s1, s2 = is_stairsplus(i.name) - minetest.override_item(i.name, { - ud_replacement_node = "coloredwood:"..s1.."_wood_grey", - paramtype2 = "colorfacedir", - groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1, not_in_creative_inventory=1, ud_param2_colorable = 1}, - }) + or string.find(i.name, "moreblocks:slab_wood") + or string.find(i.name, "moreblocks:panel_wood") + or string.find(i.name, "moreblocks:micro_wood") + or string.find(i.name, "moreblocks:slope_wood") then + local a,b = string.find(i.name, "wood_tile") + if not a then + local s1, s2 = is_stairsplus(i.name, false) + minetest.override_item(i.name, { + ud_replacement_node = "coloredwood:"..s1.."_wood_grey"..s2, + paramtype2 = "colorfacedir", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1, not_in_creative_inventory=1, ud_param2_colorable = 1}, + }) + end end end @@ -217,8 +221,7 @@ end then mname = string.gsub(i.name, "coloredwood:", "moreblocks:") - local s1, s2 = is_stairsplus(mname) - + local s1, s2 = is_stairsplus(mname, true) minetest.override_item(i.name, { drop = "moreblocks:"..s1.."_wood"..s2 }) @@ -332,7 +335,7 @@ minetest.register_lbm({ local name = node.name local hue, sat, val = unifieddyes.get_hsv(name) local color = val..hue..sat - local s1, s2 = is_stairsplus(name) + local s1, s2 = is_stairsplus(name, true) if meta and (meta:get_string("dye") ~= "") then return end -- node has already been converted before. diff --git a/digilines/settingtypes.txt b/digilines/settingtypes.txt new file mode 100644 index 00000000..ad16ac82 --- /dev/null +++ b/digilines/settingtypes.txt @@ -0,0 +1,13 @@ + +# If enabled, makes some nodes with inventories (like chests) send signals +# when items are moved in the inventory. +digilines_enable_inventory (Enable inventory signals) bool true + +# Enable or disable the LCD panel with visible text. +digilines_enable_lcd (Enable LCD) bool true + +# Enable or disable the light sensor component. +digilines_enable_lightsensor (Enable light sensor) bool true + +# Enable or disable the real time clock component. +digilines_enable_rtc (Enable RTC) bool true diff --git a/extranodes/depends.txt b/extranodes/depends.txt index 6335bfdc..3f123b02 100644 --- a/extranodes/depends.txt +++ b/extranodes/depends.txt @@ -1,5 +1,6 @@ default technic_worldgen concrete +unifieddyes intllib? moreblocks? diff --git a/extranodes/init.lua b/extranodes/init.lua index 22a1d9f9..74fb0280 100644 --- a/extranodes/init.lua +++ b/extranodes/init.lua @@ -101,3 +101,73 @@ if minetest.get_modpath("moreblocks") then register_technic_stairs_alias("stairsplus", "marble_bricks", "technic", "marble_bricks") end + +minetest.register_node(":technic:insulator_clip", { + description = "Insulator/cable clip", + drawtype = "mesh", + mesh = "technic_insulator_clip.obj", + tiles = {"technic_insulator_clip.png"}, + is_ground_content = false, + groups = {choppy=1, snappy=1, oddly_breakable_by_hand=1, ud_param2_colorable = 1}, + sounds = default.node_sound_stone_defaults(), + paramtype2 = "colorwallmounted", + palette = "unifieddyes_palette_colorwallmounted.png", + after_place_node = unifieddyes.fix_rotation, + after_dig_node = unifieddyes.after_dig_node, +}) + +minetest.register_node(":technic:insulator_clip_fencepost", { + description = "Insulator/cable clip", + tiles = {"technic_insulator_clip.png"}, + is_ground_content = false, + paramtype = "light", + paramtype2 = "color", + palette = "unifieddyes_palette_extended.png", + after_dig_node = unifieddyes.after_dig_node, + drawtype = "nodebox", + node_box = { + type = "connected", + fixed = { + { -0.25, 0.75, -0.25, 0.25, 1.25, 0.25 }, -- the clip on top + { -0.125, 0.6875, -0.125, 0.125, 0.75, 0.125 }, + { -0.1875, 0.625, -0.1875, 0.1875, 0.6875, 0.1875 }, + { -0.125, 0.5625, -0.125, 0.125, 0.625, 0.125 }, + { -0.1875, 0.5, -0.1875, 0.1875, 0.5625, 0.1875 }, + { -0.125, 0.4375, -0.125, 0.125, 0.5, 0.125 }, + { -0.1875, 0.375, -0.1875, 0.1875, 0.4375, 0.1875 }, + { -0.125, -0.5, -0.125, 0.125, 0.375, 0.125 }, -- the post, slightly short + }, + -- connect_top = + -- connect_bottom = + connect_front = {{-1/16,3/16,-1/2,1/16,5/16,-1/8}, + {-1/16,-5/16,-1/2,1/16,-3/16,-1/8}}, + connect_left = {{-1/2,3/16,-1/16,-1/8,5/16,1/16}, + {-1/2,-5/16,-1/16,-1/8,-3/16,1/16}}, + connect_back = {{-1/16,3/16,1/8,1/16,5/16,1/2}, + {-1/16,-5/16,1/8,1/16,-3/16,1/2}}, + connect_right = {{1/8,3/16,-1/16,1/2,5/16,1/16}, + {1/8,-5/16,-1/16,1/2,-3/16,1/16}}, + }, + connects_to = {"group:fence", "group:wood", "group:tree"}, + groups = {fence=1, choppy=1, snappy=1, oddly_breakable_by_hand=1, ud_param2_colorable = 1}, + sounds = default.node_sound_stone_defaults(), + place_param2 = 171 -- medium amber, low saturation, closest color to default:wood +}) + +minetest.register_craft({ + output = "technic:insulator_clip", + recipe = { + { "", "dye:white", ""}, + { "", "technic:raw_latex", ""}, + { "technic:raw_latex", "default:stone", "technic:raw_latex"}, + } +}) + +minetest.register_craft({ + output = "technic:insulator_clip_fencepost 2", + recipe = { + { "", "dye:white", ""}, + { "", "technic:raw_latex", ""}, + { "technic:raw_latex", "default:fence_wood", "technic:raw_latex"}, + } +}) diff --git a/extranodes/models/technic_insulator_clip.obj b/extranodes/models/technic_insulator_clip.obj new file mode 100644 index 00000000..1da5e886 --- /dev/null +++ b/extranodes/models/technic_insulator_clip.obj @@ -0,0 +1,173 @@ +# Blender v2.72 (sub 0) OBJ File: '' +# 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.249997 0.500000 0.249997 +v -0.249997 0.500000 -0.249997 +v 0.249997 0.500000 -0.249997 +v 0.249997 0.500000 0.249997 +v -0.187500 0.500000 0.187500 +v -0.187500 0.500000 -0.187500 +v 0.187500 0.500000 -0.187500 +v 0.187500 0.500000 0.187500 +v -0.187500 0.750000 0.187500 +v -0.187500 0.750000 -0.187500 +v 0.187500 0.750000 -0.187500 +v 0.187500 0.750000 0.187500 +v -0.250000 0.750000 0.250000 +v -0.250000 0.750000 -0.250000 +v 0.250000 0.750000 -0.250000 +v 0.250000 0.750000 0.250000 +v -0.250000 1.250000 0.250000 +v -0.250000 1.250000 -0.250000 +v 0.250000 1.250000 -0.250000 +v 0.250000 1.250000 0.250000 +v -0.500000 0.312500 0.500000 +v -0.500000 0.312500 -0.500000 +v 0.500000 0.312500 -0.500000 +v 0.500000 0.312500 0.500000 +v 0.187500 0.625000 0.187500 +v 0.187500 0.625000 -0.187500 +v -0.187500 0.625000 -0.187500 +v -0.187500 0.625000 0.187500 +v 0.187500 0.562500 0.187500 +v 0.187500 0.687500 -0.187500 +v -0.187500 0.687500 -0.187500 +v -0.187500 0.562500 0.187500 +v 0.187500 0.687500 0.187500 +v 0.187500 0.562500 -0.187500 +v -0.187500 0.562500 -0.187500 +v -0.187500 0.687500 0.187500 +v 0.168668 0.531250 0.168668 +v 0.168668 0.718750 -0.168668 +v -0.168668 0.718750 -0.168668 +v -0.168668 0.531250 0.168668 +v 0.168668 0.656250 0.168668 +v 0.168668 0.593750 -0.168668 +v -0.168668 0.593750 -0.168668 +v -0.168668 0.656250 0.168668 +v 0.168668 0.593750 0.168668 +v 0.168668 0.656250 -0.168668 +v -0.168668 0.656250 -0.168668 +v -0.168668 0.593750 0.168668 +v 0.168668 0.718750 0.168668 +v 0.168668 0.531250 -0.168668 +v -0.168668 0.531250 -0.168668 +v -0.168668 0.718750 0.168668 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 0.749997 0.749997 +vt 0.749997 0.250003 +vt 0.250003 0.250003 +vt 0.250003 0.749997 +vt 0.000000 0.812500 +vt 1.000000 0.812500 +vt 0.312500 0.312500 +vt 0.312500 0.687500 +vt 0.687500 0.312500 +vt 0.687500 0.687500 +vt 0.331332 1.218750 +vt 0.668668 1.218750 +vt 0.687500 1.250000 +vt 0.312500 1.250000 +vt 0.750000 1.250000 +vt 0.750000 1.750000 +vt 0.250000 1.750000 +vt 0.250000 1.250000 +vt 0.331332 1.093750 +vt 0.668668 1.093750 +vt 0.687500 1.125000 +vt 0.312500 1.125000 +vt 0.331332 1.093750 +vt 0.668668 1.093750 +vt 0.331332 1.156250 +vt 0.668668 1.156250 +vt 0.687500 1.187500 +vt 0.312500 1.187500 +vt 0.331332 1.156250 +vt 0.668668 1.156250 +vt 0.331332 1.031250 +vt 0.668668 1.031250 +vt 0.687500 1.062500 +vt 0.312500 1.062500 +vt 0.312500 1.000000 +vt 0.687500 1.000000 +vn 0.000000 -1.000000 -0.000000 +vn -0.600000 0.800000 -0.000000 +vn 0.000000 0.800000 -0.600000 +vn 0.600000 0.800000 0.000000 +vn -0.000000 0.000000 1.000000 +vn 0.000000 1.000000 0.000000 +vn 0.856500 -0.516200 0.000000 +vn 0.000000 -0.516200 -0.856500 +vn -0.000000 -0.516200 0.856500 +vn -0.856500 -0.516200 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 -0.000000 -1.000000 +vn 1.000000 -0.000000 0.000000 +vn -0.000000 0.800000 0.600000 +vn 0.856500 0.516200 0.000000 +vn 0.000000 0.516200 -0.856500 +vn -0.000000 0.516200 0.856500 +vn -0.856500 0.516200 -0.000000 +g Cube_Cube_Material +s off +f 1/1/1 2/2/1 3/3/1 4/4/1 +f 25/2/2 5/5/2 6/6/2 26/1/2 +f 26/1/3 6/6/3 7/7/3 27/4/3 +f 27/4/4 7/7/4 8/8/4 28/3/4 +f 25/9/5 1/4/5 4/1/5 28/10/5 +f 8/8/6 7/7/6 11/11/6 12/12/6 +f 7/7/6 6/6/6 10/13/6 11/11/6 +f 5/5/6 8/8/6 12/12/6 9/14/6 +f 6/6/6 5/5/6 9/14/6 10/13/6 +f 53/15/7 42/16/7 15/17/7 16/18/7 +f 42/15/8 43/16/8 14/17/8 15/18/8 +f 56/15/9 53/16/9 16/17/9 13/18/9 +f 43/15/10 56/16/10 13/17/10 14/18/10 +f 14/4/1 18/4/1 19/4/1 15/4/1 +f 17/19/11 21/20/11 22/21/11 18/22/11 +f 18/19/12 22/20/12 23/21/12 19/22/12 +f 19/19/13 23/20/13 24/21/13 20/22/13 +f 21/21/5 17/22/5 20/19/5 24/20/5 +f 21/5/6 24/8/6 23/7/6 22/6/6 +f 15/4/1 19/4/1 20/4/1 16/4/1 +f 16/4/1 20/4/1 17/4/1 13/4/1 +f 13/4/1 17/4/1 18/4/1 14/4/1 +f 1/1/11 25/10/11 26/9/11 2/4/11 +f 2/1/12 26/10/12 27/9/12 3/4/12 +f 3/1/13 27/10/13 28/9/13 4/4/13 +f 5/5/14 25/2/14 28/3/14 8/8/14 +f 49/23/7 46/24/7 30/25/7 29/26/7 +f 46/27/8 47/28/8 31/25/8 30/26/8 +f 52/23/9 49/24/9 29/25/9 32/26/9 +f 47/23/10 52/24/10 32/25/10 31/26/10 +f 45/29/7 50/30/7 34/31/7 37/32/7 +f 50/33/8 51/34/8 35/31/8 34/32/8 +f 48/33/9 45/34/9 37/31/9 40/32/9 +f 51/29/10 48/30/10 40/31/10 35/32/10 +f 41/35/7 54/36/7 38/37/7 33/38/7 +f 54/35/8 55/36/8 39/37/8 38/38/8 +f 44/35/9 41/36/9 33/37/9 36/38/9 +f 55/35/10 44/36/10 36/37/10 39/38/10 +f 37/32/15 34/31/15 42/16/15 53/15/15 +f 34/32/16 35/31/16 43/16/16 42/15/16 +f 40/32/17 37/31/17 53/16/17 56/15/17 +f 35/32/18 40/31/18 56/16/18 43/15/18 +f 33/38/15 38/37/15 46/24/15 49/23/15 +f 38/38/16 39/37/16 47/28/16 46/27/16 +f 36/38/17 33/37/17 49/24/17 52/23/17 +f 39/38/18 36/37/18 52/24/18 47/23/18 +f 29/26/15 30/25/15 50/30/15 45/29/15 +f 30/26/16 31/25/16 51/34/16 50/33/16 +f 32/26/17 29/25/17 45/34/17 48/33/17 +f 31/26/18 32/25/18 48/30/18 51/29/18 +f 12/39/15 11/40/15 54/36/15 41/35/15 +f 11/39/16 10/40/16 55/36/16 54/35/16 +f 9/39/17 12/40/17 41/36/17 44/35/17 +f 10/39/18 9/40/18 44/36/18 55/35/18 diff --git a/extranodes/textures/technic_insulator_clip.png b/extranodes/textures/technic_insulator_clip.png new file mode 100644 index 0000000000000000000000000000000000000000..44cdc6ae4ea8e7f0a8b1a092cd7913e0e6a25283 GIT binary patch literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^0wBx*Bp9q_EZ7UAR(iTPhDcmyJs6nfY{+wWWpf6TX`dflcok~vm#{c{*7XI=2Y8bT ZuiIN?6y!KDb-e^R-qY33Wt~$(69Bn)Sb_im literal 0 HcmV?d00001 diff --git a/gloopblocks/crafts.lua b/gloopblocks/crafts.lua index d404621b..3906da1e 100644 --- a/gloopblocks/crafts.lua +++ b/gloopblocks/crafts.lua @@ -376,4 +376,13 @@ minetest.register_craft({ if minetest.get_modpath("technic") then technic.register_grinder_recipe({input={"gloopblocks:pumice"},output="default:sand"}) technic.register_grinder_recipe({input={"gloopblocks:basalt"},output="default:cobble"}) + minetest.register_craft({ + type = "shapeless", + output = "technic:concrete 3", + recipe = { + "gloopblocks:wet_cement", + "group:sand", + "default:gravel", + } + }) end diff --git a/homedecor/crafts.lua b/homedecor/crafts.lua index 98c44ac9..7df86959 100644 --- a/homedecor/crafts.lua +++ b/homedecor/crafts.lua @@ -1298,15 +1298,7 @@ minetest.register_craft( { -- other types of fences minetest.register_craft( { - output = "homedecor:fence_wrought_iron_2 2", - recipe = { - { "homedecor:pole_wrought_iron", "default:iron_lump" }, - { "homedecor:pole_wrought_iron", "default:iron_lump" }, - }, -}) - -minetest.register_craft( { - output = "homedecor:fence_wrought_iron_2 2", + output = "homedecor:fence_wrought_iron_2 4", recipe = { { "homedecor:pole_wrought_iron", "default:iron_lump" }, { "homedecor:pole_wrought_iron", "default:iron_lump" }, diff --git a/homedecor/furniture.lua b/homedecor/furniture.lua index 2f3d5eea..a7258bcc 100644 --- a/homedecor/furniture.lua +++ b/homedecor/furniture.lua @@ -162,7 +162,25 @@ minetest.register_alias('armchair', 'homedecor:armchair') homedecor.old_static_chairs = {} -for _, color in ipairs(lrfurn.colors) do +local chair_colors = { + "black", + "brown", + "blue", + "cyan", + "dark_grey", + "dark_green", + "green", + "grey", + "magenta", + "orange", + "pink", + "red", + "violet", + "white", + "yellow", +} + +for _, color in ipairs(chair_colors) do table.insert(homedecor.old_static_chairs, "homedecor:chair_"..color) table.insert(homedecor.old_static_chairs, "homedecor:armchair_"..color) end diff --git a/mesecons_extrawires/vertical.lua b/mesecons_extrawires/vertical.lua index f3232d8b..9fabee09 100644 --- a/mesecons_extrawires/vertical.lua +++ b/mesecons_extrawires/vertical.lua @@ -77,7 +77,7 @@ end -- Vertical wire mesecon.register_node("mesecons_extrawires:vertical", { - description = "Vertical mesecon", + description = "Vertical Mesecon", drawtype = "nodebox", walkable = false, paramtype = "light", diff --git a/mesecons_gates/doc/and/description.html b/mesecons_gates/doc/and/description.html index eafbeda9..528839ce 100644 --- a/mesecons_gates/doc/and/description.html +++ b/mesecons_gates/doc/and/description.html @@ -1 +1 @@ -And gates power their output if both inputs (from left and right) are powered. +AND gates power their output if both inputs (from left and right) are powered. diff --git a/mesecons_gates/doc/diode/description.html b/mesecons_gates/doc/diode/description.html index 174fd643..5f82706b 100644 --- a/mesecons_gates/doc/diode/description.html +++ b/mesecons_gates/doc/diode/description.html @@ -1 +1 @@ -Mesecon diodes, just like real ones, only transfer power (signals) in one direction only. +Diodes conduct signals in one direction only. diff --git a/mesecons_gates/doc/nand/description.html b/mesecons_gates/doc/nand/description.html index a520fd2b..69c1d4f3 100644 --- a/mesecons_gates/doc/nand/description.html +++ b/mesecons_gates/doc/nand/description.html @@ -1 +1 @@ -Nand gates do not power their output if both inputs (from left and right) are powered, but power it in every other case. +NAND gates do not power their output if both inputs (from left and right) are powered, but power it in every other case. diff --git a/mesecons_gates/doc/nor/description.html b/mesecons_gates/doc/nor/description.html index cfcd4c0e..28d66a42 100644 --- a/mesecons_gates/doc/nor/description.html +++ b/mesecons_gates/doc/nor/description.html @@ -1 +1 @@ -Nor gates only power their output if none of their two inputs is powered. They are basically or gates with a not gate at their output. +NOR gates only power their output if none of their two inputs is powered. They are basically OR gates with a NOT gate at their output. diff --git a/mesecons_gates/doc/not/description.html b/mesecons_gates/doc/not/description.html index 8bd6795e..7538dc9b 100644 --- a/mesecons_gates/doc/not/description.html +++ b/mesecons_gates/doc/not/description.html @@ -1 +1 @@ -Not gates invert signals, just like a mesecon torch does, but faster. The input is at the opposite side of the output. +NOT gates invert signals, just like a mesecon torch does, but faster. The input is at the opposite side of the output. diff --git a/mesecons_gates/doc/or/description.html b/mesecons_gates/doc/or/description.html index 0a74abd4..f7f5539a 100644 --- a/mesecons_gates/doc/or/description.html +++ b/mesecons_gates/doc/or/description.html @@ -1 +1 @@ -Or gates power their output if either of their inputs (or both) are powered. You could basically get the same behaviour with two diodes, but or gates save some space. +OR gates power their output if either of their inputs (or both) are powered. You could basically get the same behaviour with two diodes, but OR gates save some space. diff --git a/mesecons_gates/init.lua b/mesecons_gates/init.lua index 57815efa..13e583be 100644 --- a/mesecons_gates/init.lua +++ b/mesecons_gates/init.lua @@ -54,10 +54,10 @@ local function update_gate(pos, node, link, newstate) end end -local function register_gate(name, inputnumber, assess, recipe) +local function register_gate(name, inputnumber, assess, recipe, description) local get_inputrules = inputnumber == 2 and gate_get_input_rules_twoinputs or gate_get_input_rules_oneinput - local description = "Mesecons Logic Gate: "..name + description = "Logic Gate: "..name local basename = "mesecons_gates:"..name mesecon.register_node(basename, { @@ -103,32 +103,39 @@ local function register_gate(name, inputnumber, assess, recipe) end register_gate("diode", 1, function (input) return input end, - {{"mesecons:mesecon", "mesecons_torch:mesecon_torch_on", "mesecons_torch:mesecon_torch_on"}}) + {{"mesecons:mesecon", "mesecons_torch:mesecon_torch_on", "mesecons_torch:mesecon_torch_on"}}, + "Diode") register_gate("not", 1, function (input) return not input end, - {{"mesecons:mesecon", "mesecons_torch:mesecon_torch_on", "mesecons:mesecon"}}) + {{"mesecons:mesecon", "mesecons_torch:mesecon_torch_on", "mesecons:mesecon"}}, + "NOT Gate") register_gate("and", 2, function (val1, val2) return val1 and val2 end, {{"mesecons:mesecon", "", ""}, {"", "mesecons_materials:silicon", "mesecons:mesecon"}, - {"mesecons:mesecon", "", ""}}) + {"mesecons:mesecon", "", ""}}, + "AND Gate") register_gate("nand", 2, function (val1, val2) return not (val1 and val2) end, {{"mesecons:mesecon", "", ""}, {"", "mesecons_materials:silicon", "mesecons_torch:mesecon_torch_on"}, - {"mesecons:mesecon", "", ""}}) + {"mesecons:mesecon", "", ""}}, + "NAND Gate") register_gate("xor", 2, function (val1, val2) return (val1 or val2) and not (val1 and val2) end, {{"mesecons:mesecon", "", ""}, {"", "mesecons_materials:silicon", "mesecons_materials:silicon"}, - {"mesecons:mesecon", "", ""}}) + {"mesecons:mesecon", "", ""}}, + "XOR Gate") register_gate("nor", 2, function (val1, val2) return not (val1 or val2) end, {{"mesecons:mesecon", "", ""}, {"", "mesecons:mesecon", "mesecons_torch:mesecon_torch_on"}, - {"mesecons:mesecon", "", ""}}) + {"mesecons:mesecon", "", ""}}, + "NOR Gate") register_gate("or", 2, function (val1, val2) return (val1 or val2) end, {{"mesecons:mesecon", "", ""}, {"", "mesecons:mesecon", "mesecons:mesecon"}, - {"mesecons:mesecon", "", ""}}) + {"mesecons:mesecon", "", ""}}, + "OR Gate") diff --git a/mesecons_insulated/init.lua b/mesecons_insulated/init.lua index 15b916b9..891b5d3d 100644 --- a/mesecons_insulated/init.lua +++ b/mesecons_insulated/init.lua @@ -9,7 +9,7 @@ end minetest.register_node("mesecons_insulated:insulated_on", { drawtype = "nodebox", - description = "Insulated Mesecon", + description = "Straight Insulated Mesecon", tiles = { "jeija_insulated_wire_sides_on.png", "jeija_insulated_wire_sides_on.png", @@ -41,7 +41,7 @@ minetest.register_node("mesecons_insulated:insulated_on", { minetest.register_node("mesecons_insulated:insulated_off", { drawtype = "nodebox", - description = "Insulated Mesecon", + description = "Straight Insulated Mesecon", tiles = { "jeija_insulated_wire_sides_off.png", "jeija_insulated_wire_sides_off.png", diff --git a/mesecons_lamp/doc/lamp/description.html b/mesecons_lamp/doc/lamp/description.html index 5bfe6c56..72f24ed1 100644 --- a/mesecons_lamp/doc/lamp/description.html +++ b/mesecons_lamp/doc/lamp/description.html @@ -1 +1 @@ -Lamps are effectors that if powered emit light. +Mesecon lamps are effectors that if powered emit light. diff --git a/mesecons_lamp/init.lua b/mesecons_lamp/init.lua index 811e6593..6f38b270 100644 --- a/mesecons_lamp/init.lua +++ b/mesecons_lamp/init.lua @@ -42,7 +42,7 @@ minetest.register_node("mesecons_lamp:lamp_off", { node_box = mesecon_lamp_box, selection_box = mesecon_lamp_box, groups = {dig_immediate=3, mesecon_receptor_off = 1, mesecon_effector_off = 1}, - description="Meselamp", + description="Mesecon Lamp", sounds = default.node_sound_glass_defaults(), mesecons = {effector = { action_on = function (pos, node) diff --git a/mesecons_lightstone/init.lua b/mesecons_lightstone/init.lua index da7cc41e..ab820bff 100644 --- a/mesecons_lightstone/init.lua +++ b/mesecons_lightstone/init.lua @@ -14,11 +14,14 @@ local lightstone_rules = { {x=0, y=-1, z=0}, } -function mesecon.lightstone_add(name, base_item, texture_off, texture_on) +function mesecon.lightstone_add(name, base_item, texture_off, texture_on, desc) + if not desc then + desc = name .. " Lightstone" + end minetest.register_node("mesecons_lightstone:lightstone_" .. name .. "_off", { tiles = {texture_off}, groups = {cracky=2, mesecon_effector_off = 1, mesecon = 2}, - description=name.." Lightstone", + description = desc, sounds = default.node_sound_stone_defaults(), mesecons = {effector = { rules = lightstone_rules, @@ -52,9 +55,9 @@ function mesecon.lightstone_add(name, base_item, texture_off, texture_on) end -mesecon.lightstone_add("red", "dye:red", "jeija_lightstone_red_off.png", "jeija_lightstone_red_on.png") -mesecon.lightstone_add("green", "dye:green", "jeija_lightstone_green_off.png", "jeija_lightstone_green_on.png") -mesecon.lightstone_add("blue", "dye:blue", "jeija_lightstone_blue_off.png", "jeija_lightstone_blue_on.png") -mesecon.lightstone_add("gray", "dye:grey", "jeija_lightstone_gray_off.png", "jeija_lightstone_gray_on.png") -mesecon.lightstone_add("darkgray", "dye:dark_grey", "jeija_lightstone_darkgray_off.png", "jeija_lightstone_darkgray_on.png") -mesecon.lightstone_add("yellow", "dye:yellow", "jeija_lightstone_yellow_off.png", "jeija_lightstone_yellow_on.png") +mesecon.lightstone_add("red", "dye:red", "jeija_lightstone_red_off.png", "jeija_lightstone_red_on.png", "Red Lightstone") +mesecon.lightstone_add("green", "dye:green", "jeija_lightstone_green_off.png", "jeija_lightstone_green_on.png", "Green Lightstone") +mesecon.lightstone_add("blue", "dye:blue", "jeija_lightstone_blue_off.png", "jeija_lightstone_blue_on.png", "Blue Lightstone") +mesecon.lightstone_add("gray", "dye:grey", "jeija_lightstone_gray_off.png", "jeija_lightstone_gray_on.png", "Grey Lightstone") +mesecon.lightstone_add("darkgray", "dye:dark_grey", "jeija_lightstone_darkgray_off.png", "jeija_lightstone_darkgray_on.png", "Dark Grey Lightstone") +mesecon.lightstone_add("yellow", "dye:yellow", "jeija_lightstone_yellow_off.png", "jeija_lightstone_yellow_on.png", "Yellow Lightstone") diff --git a/mesecons_luacontroller/doc/luacontroller/description.html b/mesecons_luacontroller/doc/luacontroller/description.html index ca146155..e549ffe5 100644 --- a/mesecons_luacontroller/doc/luacontroller/description.html +++ b/mesecons_luacontroller/doc/luacontroller/description.html @@ -1,5 +1,5 @@ -The luacontroller is an advanced programmable component. -You can simply code it in the language mesecons uses itself: Lua! +The Luacontroller is an advanced programmable component. +You can simply code it in the language Mesecons uses itself: Lua! All the code runs in a sandbox, so it's completely safe (but I won't guarantee that for absolute certainty!). Documentation is available here! diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index d874fdf2..c754eda7 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -12,7 +12,7 @@ -- ports = get_real_port_states(pos): gets if inputs are powered from outside -- newport = merge_port_states(state1, state2): just does result = state1 or state2 for every port -- set_port(pos, rule, state): activates/deactivates the mesecons according to the port states --- set_port_states(pos, ports): Applies new port states to a LuaController at pos +-- set_port_states(pos, ports): Applies new port states to a Luacontroller at pos -- run(pos): runs the code in the controller at pos -- reset_meta(pos, code, errmsg): performs a software-reset, installs new code and prints error messages -- resetn(pos): performs a hardware reset, turns off all ports @@ -219,7 +219,7 @@ end local function safe_string_find(...) if (select(4, ...)) ~= true then debug.sethook() -- Clear hook - error("string.find: 'plain' (fourth parameter) must always be true in a LuaController") + error("string.find: 'plain' (fourth parameter) must always be true in a Luacontroller") end return string.find(...) @@ -232,7 +232,7 @@ local function remove_functions(x) end -- Make sure to not serialize the same table multiple times, otherwise - -- writing mem.test = mem in the LuaController will lead to infinite recursion + -- writing mem.test = mem in the Luacontroller will lead to infinite recursion local seen = {} local function rfuncs(x) @@ -308,8 +308,8 @@ local function create_environment(pos, mem, event) for k, v in pairs(vports) do vports_copy[k] = v end local rports = get_real_port_states(pos) - -- Create new library tables on each call to prevent one LuaController - -- from breaking a library and messing up other LuaControllers. + -- Create new library tables on each call to prevent one Luacontroller + -- from breaking a library and messing up other Luacontrollers. local env = { pin = merge_port_states(vports, rports), port = vports_copy, @@ -595,7 +595,7 @@ for d = 0, 1 do } minetest.register_node(node_name, { - description = "LuaController", + description = "Luacontroller", drawtype = "nodebox", tiles = { top, @@ -636,7 +636,7 @@ end end ------------------------------ --- Overheated LuaController -- +-- Overheated Luacontroller -- ------------------------------ minetest.register_node(BASENAME .. "_burnt", { diff --git a/mesecons_stickyblocks/init.lua b/mesecons_stickyblocks/init.lua index 659a227a..e1241434 100644 --- a/mesecons_stickyblocks/init.lua +++ b/mesecons_stickyblocks/init.lua @@ -3,7 +3,7 @@ -- All sides sticky block minetest.register_node("mesecons_stickyblocks:sticky_block_all", { - description = "All-sides sticky block", + description = "All-Sides Sticky Block", tiles = {"default_grass.png^default_footprint.png"}, groups = {dig_immediate=2}, mvps_sticky = function (pos, node) diff --git a/pipeworks/filter-injector.lua b/pipeworks/filter-injector.lua index 6f3271f0..72f7badc 100644 --- a/pipeworks/filter-injector.lua +++ b/pipeworks/filter-injector.lua @@ -167,6 +167,7 @@ local function punch_filter(data, filtpos, filtnode, msg) local fakePlayer = { get_player_name = delay(owner), is_fake_player = ":pipeworks", + get_wielded_item = delay(ItemStack(nil)) } -- TODO: use a mechanism as the wielder one local dir = minetest.facedir_to_right_dir(filtnode.param2) local frompos = vector.subtract(filtpos, dir) diff --git a/player_textures/init.lua b/player_textures/init.lua index 5aa2ec49..5f2fb48a 100644 --- a/player_textures/init.lua +++ b/player_textures/init.lua @@ -7,16 +7,17 @@ local function pivot(table) end local textures = pivot(minetest.get_dir_list(minetest.get_modpath("player_textures")..DIR_DELIM.."textures")) +local mesh = minetest.get_modpath("3d_armor") and "3d_armor_character.b3d" or "character.b3d" local function applyskin(player) local name = player:get_player_name() if textures[string.format("player_%s.png",name)] then if minetest.get_modpath("default") then - default.player_set_textures(player,string.format("[combine:64x32:0,0=player_%s.png",name)) + default.player_set_textures(player,string.format("player_%s.png",name)) end - player:set_properties({textures={string.format("[combine:64x32:0,0=player_%s.png",name)}}) + player:set_properties({textures={string.format("player_%s.png",name)}}) end - player:set_properties({visual="mesh",visual_size={x=1,y=1},mesh="character.b3d"}) + player:set_properties({visual="mesh",visual_size={x=1,y=1},mesh=mesh}) end minetest.register_on_joinplayer(function(player) diff --git a/signs_lib/init.lua b/signs_lib/init.lua index b89cff7b..536066f3 100644 --- a/signs_lib/init.lua +++ b/signs_lib/init.lua @@ -571,7 +571,9 @@ function signs_lib.determine_sign_type(itemstack, placer, pointed_thing, locked) local node=minetest.get_node(pointed_thing.under) - if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then + if minetest.registered_nodes[node.name] and + minetest.registered_nodes[node.name].on_rightclick and + not placer:get_player_control().sneak then return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack, pointed_thing) else local above = pointed_thing.above diff --git a/technic/README.md b/technic/README.md index b6aa05fe..e5adf319 100644 --- a/technic/README.md +++ b/technic/README.md @@ -25,3 +25,11 @@ RealBadAngel: (WTFPL) * Everything else. CC BY-SA 3.0: + +Sound licenses: + +veikk0 (Veikko Mäkelä) (CC BY-SA 4.0): + * technic_hv_nuclear_reactor_siren_danger_loop.ogg + * Derived from "Nuclear alarm.wav" by Freesound.org user rene___ from . Originally licensed under CC0 1.0 + +CC BY-SA 4.0: \ No newline at end of file diff --git a/technic/locale/it.txt b/technic/locale/it.txt index 59ba7f6b..a092a53d 100644 --- a/technic/locale/it.txt +++ b/technic/locale/it.txt @@ -26,8 +26,8 @@ Graphite = Lastra in graffite Carbon Cloth = Fibra di carbonio Raw Latex = Latex grezzo Rubber Fiber = Fibra di gomma -%.1f%%-Fissile Uranium Ingot = -%.1f%%-Fissile Uranium Block = +%.1f%%-Fissile Uranium Ingot = %.1f%%-Lingotto di uranio fissile +%.1f%%-Fissile Uranium Block = %.1f%%-Blocco di uranio fissile ## Machine misc Machine cannot be removed because it is not empty = La macchina non può essere rimossa perchè non è vuota @@ -36,7 +36,7 @@ Inventory move disallowed due to protection = Impossibile muovere l'inventario a @1 Active (@2 EU) = @1 Attivo (@2 EU) %s Active = %s Attivo %s Disabled = %s Disabilitato -%s Enabled = +%s Enabled = %s Abilitato %s Idle = %s Inattivo %s Improperly Placed = %s Piazzato impropiamente %s Unpowered = %s Non alimentato @@ -46,18 +46,18 @@ Inventory move disallowed due to protection = Impossibile muovere l'inventario a %s Finished = %s Finito Enable/Disable = Abilita/Disabilita Range = Raggio -Upgrade Slots = +Upgrade Slots = Alloggi di aggiornamento In: = Ingresso: Out: = Uscita: -Slot %d = +Slot %d = Alloggio %d Itemwise = Singolo elemento Stackwise = pila completa -Owner: = -Unlocked = -Locked = -Radius: = -Enabled = -Disabled = +Owner: = Proprietario: +Unlocked = Non chiuso a chiave +Locked = Chiuso a chiave +Radius: = Raggio: +Enabled = Abilitato +Disabled = Disabilitato ## Machine names # $1: Tier @@ -84,10 +84,10 @@ Self-Contained Injector = Ignettore Constructor Mk%d = Costruttore Mk%d Frame = Cornice Frame Motor = Cornice del motore -Template = -Template (replacing) = Template (rimpiazzato) -Template Motor = -Template Tool = +Template = Sagoma +Template (replacing) = Sagoma (di rimpiazzo) +Template Motor = Motore per sagome +Template Tool = Strumento per sagome Battery Box = Box batterie Supply Converter = Trasformatore Switching Station = Stazione di controllo @@ -96,7 +96,7 @@ Fuel-Fired Furnace = Fornace a carbone Wind Mill Frame = Pala eolica Forcefield = Campo di forza Nuclear Reactor Rod Compartment = Compartimento combustibile nucleare -Administrative World Anchor = +Administrative World Anchor = Ancora-mondo amministrativa ## Machine-specific # $1: Pruduced EU @@ -111,12 +111,12 @@ Production at %d%% = Produzione a %d%% Choose Milling Program: = Scegliere un programma di Fresatura Slim Elements half / normal height: = Metà elementi sottili / altezza normale: Current track %s = Traccia corrente %s -Stopped = -Keeping %d/%d map blocks loaded = -Digging not started = -Digging finished = -Digging %d m above machine = -Digging %d m below machine = +Stopped = Fermato +Keeping %d/%d map blocks loaded = Mantenimento di %d/%d blocchi mappa caricati +Digging not started = Scavo non iniziato +Digging finished = Scavo finito +Digging %d m above machine = Scavo di %d m sopra la macchina +Digging %d m below machine = Scavo di %d m sotto la macchina ## CNC Cylinder = Cilindro @@ -174,10 +174,10 @@ Talinite = Talinite Tin = Stagno Wrought Iron = Ferro Battuto Zinc = Zinco -%.1f%%-Fissile Uranium = +%.1f%%-Fissile Uranium = %.1f%%-Uranio fissile ## Tools -RE Battery = +RE Battery = Batteria RE Water Can = Serbatoio d'acqua Lava Can = Serbatoio di lava Chainsaw = Motosega diff --git a/technic/machines/HV/quarry.lua b/technic/machines/HV/quarry.lua index 82556763..8d87b654 100644 --- a/technic/machines/HV/quarry.lua +++ b/technic/machines/HV/quarry.lua @@ -12,6 +12,7 @@ minetest.register_craft({ local quarry_dig_above_nodes = 3 -- How far above the quarry we will dig nodes local quarry_max_depth = 100 local quarry_demand = 10000 +local quarry_eject_dir = vector.new(0, 1, 0) local function set_quarry_formspec(meta) local radius = meta:get_int("size") @@ -83,7 +84,7 @@ local function quarry_handle_purge(pos) if stack then local item = stack:to_table() if item then - technic.tube_inject_item(pos, pos, vector.new(0, 1, 0), item) + technic.tube_inject_item(pos, pos, quarry_eject_dir, item) stack:clear() inv:set_stack("cache", i, stack) break @@ -217,6 +218,16 @@ minetest.register_node("technic:quarry", { connect_sides = {"bottom", "front", "left", "right"}, tube = { connect_sides = {top = 1}, + -- lower priority than other tubes, so that quarries will prefer any + -- other tube to another quarry, which could lead to server freezes + -- in certain quarry placements (2x2 for example would never eject) + priority = 10, + can_go = function(pos, node, velocity, stack) + -- always eject the same, even if items came in another way + -- this further mitigates loops and generally avoids random sideway movement + -- that can be expected in certain quarry placements + return { quarry_eject_dir } + end }, on_construct = function(pos) local meta = minetest.get_meta(pos) diff --git a/technic/machines/init.lua b/technic/machines/init.lua index ad79eab3..f2e31c9f 100644 --- a/technic/machines/init.lua +++ b/technic/machines/init.lua @@ -8,6 +8,7 @@ dofile(path.."/MV/init.lua") dofile(path.."/HV/init.lua") dofile(path.."/switching_station.lua") +dofile(path.."/power_monitor.lua") dofile(path.."/supply_converter.lua") dofile(path.."/other/init.lua") diff --git a/technic/machines/other/constructor.lua b/technic/machines/other/constructor.lua index 3396ac76..9c640517 100644 --- a/technic/machines/other/constructor.lua +++ b/technic/machines/other/constructor.lua @@ -21,7 +21,7 @@ local function deploy_node(inv, slot_name, pos, node, machine_node) end if remove_to then for i = 1, remove_to do - inv:remove_item(drops[i]) + inv:remove_item(slot_name, drops[i]) end else minetest.remove_node(pos) diff --git a/technic/machines/power_monitor.lua b/technic/machines/power_monitor.lua new file mode 100644 index 00000000..43066938 --- /dev/null +++ b/technic/machines/power_monitor.lua @@ -0,0 +1,67 @@ +-- POWER MONITOR +-- The power monitor can be used to monitor how much power is available on a network, +-- similarly to the old "slave" switching stations. + +local S = technic.getter + +minetest.register_craft({ + output = "technic:power_monitor", + recipe = { + {"", "", ""}, + {"", "technic:machine_casing", "default:copper_ingot"}, + {"technic:lv_cable", "technic:lv_cable", "technic:lv_cable"} + } +}) + +minetest.register_node("technic:power_monitor",{ + description = S("Power Monitor"), + tiles = { + "technic_power_monitor_sides.png", + "technic_power_monitor_bottom_back.png", + "technic_power_monitor_sides.png", + "technic_power_monitor_sides.png", + "technic_power_monitor_bottom_back.png", + "technic_power_monitor_front.png" + }, + paramtype2 = "facedir", + groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_all_tiers=1, technic_machine=1}, + connect_sides = {"bottom", "back"}, + sounds = default.node_sound_wood_defaults(), + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", S("Power Monitor")) + end, +}) + +minetest.register_abm({ + nodenames = {"technic:power_monitor"}, + label = "Power Monitor", + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local meta = minetest.get_meta(pos) + local network_hash = technic.cables[minetest.hash_node_position(pos)] + local network = network_hash and minetest.get_position_from_hash(network_hash) + local sw_pos = network and {x=network.x,y=network.y+1,z=network.z} + local timeout = 0 + for tier in pairs(technic.machines) do + timeout = math.max(meta:get_int(tier.."_EU_timeout"),timeout) + end + if timeout > 0 and sw_pos and minetest.get_node(sw_pos).name == "technic:switching_station" then + local sw_meta = minetest.get_meta(sw_pos) + local supply = sw_meta:get_int("supply") + local demand = sw_meta:get_int("demand") + meta:set_string("infotext", + S("Power Monitor. Supply: @1 Demand: @2", + technic.pretty_num(supply), technic.pretty_num(demand))) + else + meta:set_string("infotext",S("Power Monitor Has No Network")) + end + end, +}) + +for tier in pairs(technic.machines) do + -- RE in order to use the "timeout" functions, although it consumes 0 power + technic.register_machine(tier, "technic:power_monitor", "RE") +end + diff --git a/technic/machines/register/cables.lua b/technic/machines/register/cables.lua index 28984c02..165db988 100644 --- a/technic/machines/register/cables.lua +++ b/technic/machines/register/cables.lua @@ -11,8 +11,110 @@ function technic.get_cable_tier(name) return cable_tier[name] end -local function clear_networks() - technic.networks = {} +local function check_connections(pos) + -- Build a table of all machines + local machines = {} + for tier,list in pairs(technic.machines) do + for k,v in pairs(list) do + machines[k] = v + end + end + local connections = {} + local positions = { + {x=pos.x+1, y=pos.y, z=pos.z}, + {x=pos.x-1, y=pos.y, z=pos.z}, + {x=pos.x, y=pos.y+1, z=pos.z}, + {x=pos.x, y=pos.y-1, z=pos.z}, + {x=pos.x, y=pos.y, z=pos.z+1}, + {x=pos.x, y=pos.y, z=pos.z-1}} + for _,connected_pos in pairs(positions) do + local name = minetest.get_node(connected_pos).name + if machines[name] or technic.get_cable_tier(name) then + table.insert(connections,connected_pos) + end + end + return connections +end + +local function clear_networks(pos) + local node = minetest.get_node(pos) + local meta = minetest.get_meta(pos) + local placed = node.name ~= "air" + local positions = check_connections(pos) + if #positions < 1 then return end + local dead_end = #positions == 1 + for _,connected_pos in pairs(positions) do + local net = technic.cables[minetest.hash_node_position(connected_pos)] + if net and technic.networks[net] then + if dead_end and placed then + -- Dead end placed, add it to the network + -- Get the network + local network_id = technic.cables[minetest.hash_node_position(positions[1])] + if not network_id then + -- We're evidently not on a network, nothing to add ourselves to + return + end + local sw_pos = minetest.get_position_from_hash(network_id) + sw_pos.y = sw_pos.y + 1 + local network = technic.networks[network_id] + local tier = network.tier + + -- Actually add it to the (cached) network + -- This is similar to check_node_subp + technic.cables[minetest.hash_node_position(pos)] = network_id + pos.visited = 1 + if technic.is_tier_cable(name, tier) then + table.insert(network.all_nodes,pos) + elseif technic.machines[tier][node.name] then + meta:set_string(tier.."_network",minetest.pos_to_string(sw_pos)) + if technic.machines[tier][node.name] == technic.producer then + table.insert(network.PR_nodes,pos) + elseif technic.machines[tier][node.name] == technic.receiver then + table.insert(network.RE_nodes,pos) + elseif technic.machines[tier][node.name] == technic.producer_receiver then + table.insert(network.PR_nodes,pos) + table.insert(network.RE_nodes,pos) + elseif technic.machines[tier][node.name] == "SPECIAL" and + (pos.x ~= sw_pos.x or pos.y ~= sw_pos.y or pos.z ~= sw_pos.z) and + from_below then + table.insert(network.SP_nodes,pos) + elseif technic.machines[tier][node.name] == technic.battery then + table.insert(network.BA_nodes,pos) + end + end + elseif dead_end and not placed then + -- Dead end removed, remove it from the network + -- Get the network + local network_id = technic.cables[minetest.hash_node_position(positions[1])] + if not network_id then + -- We're evidently not on a network, nothing to add ourselves to + return + end + local network = technic.networks[network_id] + + -- Search for and remove machine + technic.cables[minetest.hash_node_position(pos)] = nil + for tblname,table in pairs(network) do + if tblname ~= "tier" then + for machinenum,machine in pairs(table) do + if machine.x == pos.x + and machine.y == pos.y + and machine.z == pos.z then + table[machinenum] = nil + end + end + end + end + else + -- Not a dead end, so the whole network needs to be recalculated + for _,v in pairs(technic.networks[net].all_nodes) do + local pos1 = minetest.hash_node_position(v) + technic.cables[pos1] = nil + end + technic.networks[net] = nil + end + end + end end function technic.register_cable(tier, size) @@ -55,7 +157,7 @@ end local function clear_nets_if_machine(pos, node) for tier, machine_list in pairs(technic.machines) do if machine_list[node.name] ~= nil then - return clear_networks() + return clear_networks(pos) end end end diff --git a/technic/machines/supply_converter.lua b/technic/machines/supply_converter.lua index 32597deb..15c761d3 100644 --- a/technic/machines/supply_converter.lua +++ b/technic/machines/supply_converter.lua @@ -9,12 +9,62 @@ local S = technic.getter +local function set_supply_converter_formspec(meta) + local formspec = "size[5,2.25]".. + "field[0.3,0.5;2,1;power;"..S("Input Power")..";"..meta:get_int("power").."]" + -- The names for these toggle buttons are explicit about which + -- state they'll switch to, so that multiple presses (arising + -- from the ambiguity between lag and a missed press) only make + -- the single change that the user expects. + if meta:get_int("mesecon_mode") == 0 then + formspec = formspec.."button[0,1;5,1;mesecon_mode_1;"..S("Ignoring Mesecon Signal").."]" + else + formspec = formspec.."button[0,1;5,1;mesecon_mode_0;"..S("Controlled by Mesecon Signal").."]" + end + if meta:get_int("enabled") == 0 then + formspec = formspec.."button[0,1.75;5,1;enable;"..S("%s Disabled"):format(S("Supply Converter")).."]" + else + formspec = formspec.."button[0,1.75;5,1;disable;"..S("%s Enabled"):format(S("Supply Converter")).."]" + end + meta:set_string("formspec", formspec) +end + +local supply_converter_receive_fields = function(pos, formname, fields, sender) + local meta = minetest.get_meta(pos) + local power = nil + if fields.power then + power = tonumber(fields.power) or 0 + power = 100 * math.floor(power / 100) + power = math.max(power, 0) + power = math.min(power, 10000) + if power == meta:get_int("power") then power = nil end + end + if power then meta:set_int("power", power) end + if fields.enable then meta:set_int("enabled", 1) end + if fields.disable then meta:set_int("enabled", 0) end + if fields.mesecon_mode_0 then meta:set_int("mesecon_mode", 0) end + if fields.mesecon_mode_1 then meta:set_int("mesecon_mode", 1) end + set_supply_converter_formspec(meta) +end + +local mesecons = { + effector = { + action_on = function(pos, node) + minetest.get_meta(pos):set_int("mesecon_effect", 1) + end, + action_off = function(pos, node) + minetest.get_meta(pos):set_int("mesecon_effect", 0) + end + } +} + local run = function(pos, node) - local demand = 10000 local remain = 0.9 -- Machine information local machine_name = S("Supply Converter") local meta = minetest.get_meta(pos) + local enabled = meta:get_int("enabled") ~= 0 and (meta:get_int("mesecon_mode") == 0 or meta:get_int("mesecon_effect") ~= 0) + local demand = enabled and meta:get_int("power") or 10000 local pos_up = {x=pos.x, y=pos.y+1, z=pos.z} local pos_down = {x=pos.x, y=pos.y-1, z=pos.z} @@ -53,12 +103,19 @@ minetest.register_node("technic:supply_converter", { technic_machine=1, technic_all_tiers=1}, connect_sides = {"top", "bottom"}, sounds = default.node_sound_wood_defaults(), + on_receive_fields = supply_converter_receive_fields, on_construct = function(pos) local meta = minetest.get_meta(pos) meta:set_string("infotext", S("Supply Converter")) - meta:set_float("active", false) + meta:set_int("power", 10000) + meta:set_int("enabled", 1) + meta:set_int("mesecon_mode", 0) + meta:set_int("mesecon_effect", 0) + set_supply_converter_formspec(meta) end, + mesecons = mesecons, technic_run = run, + technic_on_disable = run, }) minetest.register_craft({ diff --git a/technic/machines/switching_station.lua b/technic/machines/switching_station.lua index f7ec0b69..f925817b 100644 --- a/technic/machines/switching_station.lua +++ b/technic/machines/switching_station.lua @@ -32,6 +32,7 @@ -- This way the supplies are separated per network. technic.networks = {} +technic.cables = {} local S = technic.getter @@ -57,6 +58,11 @@ minetest.register_node("technic:switching_station",{ meta:set_string("infotext", S("Switching Station")) meta:set_string("active", 1) end, + after_dig_node = function(pos) + minetest.forceload_free_block(pos) + pos.y = pos.y - 1 + minetest.forceload_free_block(pos) + end, }) -------------------------------------------------- @@ -64,7 +70,8 @@ minetest.register_node("technic:switching_station",{ -------------------------------------------------- -- Add a wire node to the LV/MV/HV network -local add_new_cable_node = function(nodes, pos) +local add_new_cable_node = function(nodes, pos, network_id) + technic.cables[minetest.hash_node_position(pos)] = network_id -- Ignore if the node has already been added for i = 1, #nodes do if pos.x == nodes[i].x and @@ -78,31 +85,31 @@ local add_new_cable_node = function(nodes, pos) end -- Generic function to add found connected nodes to the right classification array -local check_node_subp = function(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, pos, machines, tier, sw_pos, from_below) +local check_node_subp = function(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, pos, machines, tier, sw_pos, from_below, network_id) technic.get_or_load_node(pos) local meta = minetest.get_meta(pos) local name = minetest.get_node(pos).name if technic.is_tier_cable(name, tier) then - add_new_cable_node(all_nodes, pos) + add_new_cable_node(all_nodes, pos,network_id) elseif machines[name] then --dprint(name.." is a "..machines[name]) + meta:set_string(tier.."_network",minetest.pos_to_string(sw_pos)) if machines[name] == technic.producer then - add_new_cable_node(PR_nodes, pos) + add_new_cable_node(PR_nodes, pos, network_id) elseif machines[name] == technic.receiver then - add_new_cable_node(RE_nodes, pos) + add_new_cable_node(RE_nodes, pos, network_id) elseif machines[name] == technic.producer_receiver then - add_new_cable_node(PR_nodes, pos) - add_new_cable_node(RE_nodes, pos) + add_new_cable_node(PR_nodes, pos, network_id) + add_new_cable_node(RE_nodes, pos, network_id) elseif machines[name] == "SPECIAL" and (pos.x ~= sw_pos.x or pos.y ~= sw_pos.y or pos.z ~= sw_pos.z) and from_below then -- Another switching station -> disable it - add_new_cable_node(SP_nodes, pos) + add_new_cable_node(SP_nodes, pos, network_id) meta:set_int("active", 0) - meta:set_string("active_pos", minetest.serialize(sw_pos)) elseif machines[name] == technic.battery then - add_new_cable_node(BA_nodes, pos) + add_new_cable_node(BA_nodes, pos, network_id) end meta:set_int(tier.."_EU_timeout", 2) -- Touch node @@ -110,7 +117,7 @@ local check_node_subp = function(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nod end -- Traverse a network given a list of machines and a cable type name -local traverse_network = function(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, i, machines, tier, sw_pos) +local traverse_network = function(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, i, machines, tier, sw_pos, network_id) local pos = all_nodes[i] local positions = { {x=pos.x+1, y=pos.y, z=pos.z}, @@ -121,7 +128,7 @@ local traverse_network = function(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_no {x=pos.x, y=pos.y, z=pos.z-1}} --print("ON") for i, cur_pos in pairs(positions) do - check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, cur_pos, machines, tier, sw_pos, i == 3) + check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, cur_pos, machines, tier, sw_pos, i == 3, network_id) end end @@ -153,11 +160,11 @@ local get_network = function(sw_pos, pos1, tier) local all_nodes = {pos1} repeat traverse_network(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, - i, technic.machines[tier], tier, sw_pos) + i, technic.machines[tier], tier, sw_pos, minetest.hash_node_position(pos1)) i = i + 1 until all_nodes[i] == nil technic.networks[minetest.hash_node_position(pos1)] = {tier = tier, PR_nodes = PR_nodes, - RE_nodes = RE_nodes, BA_nodes = BA_nodes, SP_nodes = SP_nodes} + RE_nodes = RE_nodes, BA_nodes = BA_nodes, SP_nodes = SP_nodes, all_nodes = all_nodes} return PR_nodes, BA_nodes, RE_nodes end @@ -183,27 +190,30 @@ minetest.register_abm({ local BA_nodes local RE_nodes local machine_name = S("Switching Station") - - if meta:get_int("active") ~= 1 then - meta:set_int("active", 1) - local active_pos = minetest.deserialize(meta:get_string("active_pos")) - if active_pos then - local meta1 = minetest.get_meta(active_pos) - meta:set_string("infotext", S("%s (Slave)"):format(meta1:get_string("infotext"))) - end - return - end -- Which kind of network are we on: pos1 = {x=pos.x, y=pos.y-1, z=pos.z} + --Disable if necessary + if meta:get_int("active") ~= 1 then + minetest.forceload_free_block(pos) + minetest.forceload_free_block(pos1) + meta:set_string("infotext",S("%s Already Present"):format(machine_name)) + return + end + local name = minetest.get_node(pos1).name local tier = technic.get_cable_tier(name) if tier then + -- Forceload switching station + minetest.forceload_block(pos) + minetest.forceload_block(pos1) PR_nodes, BA_nodes, RE_nodes = get_network(pos, pos1, tier) else --dprint("Not connected to a network") meta:set_string("infotext", S("%s Has No Network"):format(machine_name)) + minetest.forceload_free_block(pos) + minetest.forceload_free_block(pos1) return end @@ -291,6 +301,10 @@ minetest.register_abm({ S("@1. Supply: @2 Demand: @3", machine_name, technic.pretty_num(PR_eu_supply), technic.pretty_num(RE_eu_demand))) + -- Data that will be used by the power monitor + meta:set_int("supply",PR_eu_supply) + meta:set_int("demand",RE_eu_demand) + -- If the PR supply is enough for the RE demand supply them all if PR_eu_supply >= RE_eu_demand then --dprint("PR_eu_supply"..PR_eu_supply.." >= RE_eu_demand"..RE_eu_demand) @@ -352,6 +366,7 @@ minetest.register_abm({ meta1 = minetest.get_meta(pos1) meta1:set_int(eu_input_str, 0) end + end, }) @@ -374,6 +389,7 @@ minetest.register_abm({ interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) + local meta = minetest.get_meta(pos) for tier, machines in pairs(technic.machines) do if machines[node.name] and switching_station_timeout_count(pos, tier) then local nodedef = minetest.registered_nodes[node.name] @@ -392,6 +408,23 @@ minetest.register_abm({ end, }) +--Re-enable disabled switching station if necessary, similar to the timeout above +minetest.register_abm({ + nodenames = {"technic:switching_station"}, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local meta = minetest.get_meta(pos) + local pos1 = {x=pos.x,y=pos.y-1,z=pos.z} + local tier = technic.get_cable_tier(minetest.get_node(pos1).name) + if not tier then return end + if switching_station_timeout_count(pos, tier) then + local meta = minetest.get_meta(pos) + meta:set_int("active",1) + end + end, +}) + for tier, machines in pairs(technic.machines) do -- SPECIAL will not be traversed technic.register_machine(tier, "technic:switching_station", "SPECIAL") diff --git a/technic/sounds/technic_hv_nuclear_reactor_siren_danger_loop.ogg b/technic/sounds/technic_hv_nuclear_reactor_siren_danger_loop.ogg index 3d290b05755590b4ab4603b86da1456eb3b5f918..1f21a16938c769ad389622bf7fea3469dcf7f713 100644 GIT binary patch literal 36524 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 literal 13059 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 diff --git a/technic/textures/technic_power_monitor_bottom_back.png b/technic/textures/technic_power_monitor_bottom_back.png new file mode 100644 index 0000000000000000000000000000000000000000..c857039330eedb8021c112f167c54d68338ac45d GIT binary patch literal 506 zcmV$@ zOKwy#5Jl_fw%wumM1YWxGROjY1}un0u?Y5oA~9tRhyh9l>3;9|Q&kKKT1ZecyX@=h zdkSxFZ`XA#rKoDod0p39>-l^}#GLaOgPF|?0Cu~bs*zIw*@kM{Z72WAdM zGb0hHwf5fUoB;6Se%6dby>%bc&#MA}yAx3;5+X*3Vf4+leE&J$zD(B#I&WSw0RSSV zlv-=06ms|25)lCC!=68(hm%f&oRAQLz_KhsNm5F+*4A3kF^4vM40m%X^!kNd0t`M9 zPFicVRseXqr_*ZtOlrPtwswyTV~j{##u#(XtE;Qi=>!0uzP$T4)|8T&1qZyjxj{r# zW#%ykA`+3Asj7(NoR?(*fKtkwQ&lMv_#17^mAjkSx~?L^%<;*Tl9*Y<8XQzL8u3)X wx=gN_Nnj2-01(TV*6_{D?%rC30RSkaR;$&oq1(14A~v7Ti=ucA{fx&0nx-j=V!2$3 zl+p|0=Ld`}abpYs>~_0fLpMz$rQ~H$>fB`<1vG`hS1^64BTLWLd^Jch2Q`&KP@d+fN6Zx9#nA%kvxnLI{F$ zj)X9!rf7`1pNFayx;GwwNi?i9mmmHtF^x0Z$vzf zW39!^?hXJsXEP%+TWjTaN8e@FlN-0Fd%x1Rt77-#+)wLD?%sCN}&hy-Rt12@;pU*LdyAzR!wARcl z1jO*(n@cH(C?d=p8;A%I=bW`xRTU9L3={w$5vjG#IaO6v%`6z_oI^AK?7agB00EksNyjWJ3oviAmnU=@4KET!b`!72oNKA%X5Z?{{mHO9i(y?4&} z=jX@Fn0fE*?m6eRmWa?=D^`bYRShd2k4H-B^?HSey>~=pW*(T;FEf{PZN=h<3Q)o6#AQ8@5_w9%`e-dYQ)5ok(D+&##sYGA|z yB1TQz{o7o3muNwx6Cs3vud`v)7~?pOl+qtSGFhUUDvWyo0000=5 then mode=1 end minetest.chat_send_player(player_name, S("Mining Drill Mk%d Mode %d"):format(2, mode)..": "..mining_drill_mode_text[mode][1]) - item["name"]="technic:mining_drill_mk2_"..mode + itemstack:set_name("technic:mining_drill_mk2_"..mode); meta["mode"]=mode - item["metadata"]=minetest.serialize(meta) - itemstack:replace(item) + itemstack:set_metadata(minetest.serialize(meta)) return itemstack end @@ -276,10 +277,9 @@ local function mining_drill_mk3_setmode(user,itemstack) mode=mode+1 if mode>=6 then mode=1 end minetest.chat_send_player(player_name, S("Mining Drill Mk%d Mode %d"):format(3, mode)..": "..mining_drill_mode_text[mode][1]) - item["name"]="technic:mining_drill_mk3_"..mode + itemstack:set_name("technic:mining_drill_mk3_"..mode); meta["mode"]=mode - item["metadata"]=minetest.serialize(meta) - itemstack:replace(item) + itemstack:set_metadata(minetest.serialize(meta)) return itemstack end @@ -296,7 +296,7 @@ local function mining_drill_mk2_handler(itemstack, user, pointed_thing) end local charge_to_take = cost_to_use(2, meta.mode) if meta.charge >= charge_to_take then - local pos = minetest.get_pointed_thing_position(pointed_thing, above) + local pos = minetest.get_pointed_thing_position(pointed_thing, false) drill_dig_it(pos, user, meta.mode) if not technic.creative_mode then meta.charge = meta.charge - charge_to_take @@ -319,7 +319,7 @@ local function mining_drill_mk3_handler(itemstack, user, pointed_thing) end local charge_to_take = cost_to_use(3, meta.mode) if meta.charge >= charge_to_take then - local pos = minetest.get_pointed_thing_position(pointed_thing, above) + local pos = minetest.get_pointed_thing_position(pointed_thing, false) drill_dig_it(pos, user, meta.mode) if not technic.creative_mode then meta.charge = meta.charge - charge_to_take @@ -348,7 +348,7 @@ minetest.register_tool("technic:mining_drill", { end local charge_to_take = cost_to_use(1, 1) if meta.charge >= charge_to_take then - local pos = minetest.get_pointed_thing_position(pointed_thing, above) + local pos = minetest.get_pointed_thing_position(pointed_thing, false) drill_dig_it(pos, user, 1) if not technic.creative_mode then meta.charge = meta.charge - charge_to_take diff --git a/technic_chests/common.lua b/technic_chests/common.lua index 47054f5a..32b34eb9 100644 --- a/technic_chests/common.lua +++ b/technic_chests/common.lua @@ -26,12 +26,7 @@ technic.chests.can_dig = function(pos, player) end local function inv_change(pos, count, player) - local meta = minetest.get_meta(pos) - if not has_locked_chest_privilege(meta, player) then - minetest.log("action", player:get_player_name().. - " tried to access a locked chest belonging to ".. - meta:get_string("owner").." at ".. - minetest.pos_to_string(pos)) + if not default.can_interact_with_node(player, pos) then return 0 end return count @@ -54,18 +49,14 @@ function technic.chests.on_inv_move(pos, from_list, from_index, to_list, to_inde end function technic.chests.on_inv_put(pos, listname, index, stack, player) - minetest.log("action", player:get_player_name().. - " puts stuff in to chest at " - ..minetest.pos_to_string(pos)) + minetest.log("action", player:get_player_name() .. + " moves " .. stack:get_name() .. + " to chest at " .. minetest.pos_to_string(pos)) end function technic.chests.on_inv_take(pos, listname, index, stack, player) - minetest.log("action", player:get_player_name().. - " takes stuff from chest at " - ..minetest.pos_to_string(pos)) -end - -function has_locked_chest_privilege(meta, player) - return player:get_player_name() == meta:get_string("owner") + minetest.log("action", player:get_player_name() .. + " takes " .. stack:get_name() .. + " from chest at " .. minetest.pos_to_string(pos)) end diff --git a/technic_chests/register.lua b/technic_chests/register.lua index 25e4cded..6a5b8db2 100644 --- a/technic_chests/register.lua +++ b/technic_chests/register.lua @@ -263,12 +263,45 @@ function technic.chests:definition(name, data) on_receive_fields = get_receive_fields(name, data), on_metadata_inventory_move = self.on_inv_move, on_metadata_inventory_put = self.on_inv_put, - on_metadata_inventory_take = self.on_inv_take, + on_metadata_inventory_take = self.on_inv_take, + on_blast = function(pos) + local drops = {} + default.get_inventory_drops(pos, "main", drops) + drops[#drops+1] = "technic:"..name:lower()..(data.locked and "_locked" or "").."_chest" + minetest.remove_node(pos) + return drops + end, } if data.locked then def.allow_metadata_inventory_move = self.inv_move def.allow_metadata_inventory_put = self.inv_put def.allow_metadata_inventory_take = self.inv_take + def.on_blast = function() end + def.can_dig = function(pos,player) + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory() + return inv:is_empty("main") and default.can_interact_with_node(player, pos) + end + def.on_skeleton_key_use = function(pos, player, newsecret) + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + local name = player:get_player_name() + + -- verify placer is owner of lockable chest + if owner ~= name then + minetest.record_protection_violation(pos, name) + minetest.chat_send_player(name, "You do not own this chest.") + return nil + end + + local secret = meta:get_string("key_lock_secret") + if secret == "" then + secret = newsecret + meta:set_string("key_lock_secret", secret) + end + + return secret, "a locked chest", owner + end end return def end diff --git a/technic_worldgen/oregen.lua b/technic_worldgen/oregen.lua index 795f0ec9..c6782e66 100644 --- a/technic_worldgen/oregen.lua +++ b/technic_worldgen/oregen.lua @@ -54,13 +54,13 @@ minetest.register_ore({ ore_type = "scatter", ore = "technic:mineral_zinc", wherein = "default:stone", - clust_scarcity = 8*8*8, - clust_num_ores = 4, - clust_size = 3, + clust_scarcity = 9*9*9, + clust_num_ores = 5, + clust_size = 7, y_min = -32, y_max = 2, - noise_params = zinc_params, - noise_threshhold = zinc_threshhold, + noise_params = lead_params, + noise_threshhold = lead_threshhold, }) minetest.register_ore({ diff --git a/unifieddyes/init.lua b/unifieddyes/init.lua index 1221a726..a713c453 100644 --- a/unifieddyes/init.lua +++ b/unifieddyes/init.lua @@ -505,6 +505,8 @@ function unifieddyes.on_use(itemstack, player, pointed_thing) local nodedef = minetest.registered_nodes[node.name] local playername = player:get_player_name() + if not nodedef then return end -- target was an unknown node, just bail out + -- if the node has an on_punch defined, bail out and call that instead, unless "sneak" is pressed. if not player:get_player_control().sneak then local onpunch = nodedef.on_punch(pos, node, player, pointed_thing) diff --git a/worldedit_commands/wand.lua b/worldedit_commands/wand.lua index 16f92654..07808019 100644 --- a/worldedit_commands/wand.lua +++ b/worldedit_commands/wand.lua @@ -3,16 +3,6 @@ minetest.register_tool(":worldedit:wand", { inventory_image = "worldedit_wand.png", stack_max = 1, -- there is no need to have more than one liquids_pointable = true, -- ground with only water on can be selected as well - -- the tool_capabilities are completely irrelevant here - no need to dig - tool_capabilities = { - full_punch_interval = 1.0, - max_drop_level = 0, - groupcaps={ - fleshy={times={[2]=0.80, [3]=0.40}, uses=1/0.05, maxlevel=1}, - snappy={times={[2]=0.80, [3]=0.40}, uses=1/0.05, maxlevel=1}, - choppy={times={[3]=0.90}, uses=1/0.05, maxlevel=0} - } - }, on_use = function(itemstack, placer, pointed_thing) if placer ~= nil and pointed_thing ~= nil and pointed_thing.type == "node" then diff --git a/worldedit_gui/depends.txt b/worldedit_gui/depends.txt index d603ac9c..2558dce1 100644 --- a/worldedit_gui/depends.txt +++ b/worldedit_gui/depends.txt @@ -2,4 +2,5 @@ worldedit worldedit_commands unified_inventory? inventory_plus? -creative? \ No newline at end of file +sfinv? +creative? diff --git a/worldedit_gui/functionality.lua b/worldedit_gui/functionality.lua index 7010b149..5cbf8fa6 100644 --- a/worldedit_gui/functionality.lua +++ b/worldedit_gui/functionality.lua @@ -40,7 +40,7 @@ local angle_values = {90, 180, 270} setmetatable(angle_indices, {__index = function () return 1 end}) setmetatable(angle_values, {__index = function () return 90 end}) ---given multiple sets of privileges, produces a single set of privs that would have the same effect as requiring all of them at the same time +-- given multiple sets of privileges, produces a single set of privs that would have the same effect as requiring all of them at the same time local combine_privs = function(...) local result = {} for i, privs in ipairs({...}) do @@ -54,6 +54,12 @@ local combine_privs = function(...) return result end +-- display node (or unknown_node image otherwise) at specified pos in formspec +local formspec_node = function(pos, nodename) + return nodename and string.format("item_image[%s;1,1;%s]", pos, nodename) + or string.format("image[%s;1,1;worldedit_gui_unknown.png]", pos) +end + worldedit.register_gui_function("worldedit_gui_about", { name = "About", privs = minetest.chatcommands["/about"].privs, on_select = function(name) @@ -155,8 +161,7 @@ worldedit.register_gui_function("worldedit_gui_set", { return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_set") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_set_node;Name;%s]", minetest.formspec_escape(node)) .. "button[4,1.18;1.5,0.8;worldedit_gui_set_search;Search]" .. - (nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", nodename) .. "button_exit[0,2.5;3,0.8;worldedit_gui_set_submit;Set Nodes]" end, }) @@ -166,7 +171,10 @@ worldedit.register_gui_handler("worldedit_gui_set", function(name, fields) gui_nodename1[name] = tostring(fields.worldedit_gui_set_node) worldedit.show_page(name, "worldedit_gui_set") if fields.worldedit_gui_set_submit then - minetest.chatcommands["/set"].func(name, gui_nodename1[name]) + local n = worldedit.normalize_nodename(gui_nodename1[name]) + if n then + minetest.chatcommands["/set"].func(name, n) + end end return true end @@ -181,12 +189,10 @@ worldedit.register_gui_function("worldedit_gui_replace", { return "size[6.5,4]" .. worldedit.get_formspec_header("worldedit_gui_replace") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_replace_search;Name;%s]", minetest.formspec_escape(search)) .. "button[4,1.18;1.5,0.8;worldedit_gui_replace_search_search;Search]" .. - (search_nodename and string.format("item_image[5.5,1.1;1,1;%s]", search_nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", search_nodename) .. string.format("field[0.5,2.5;4,0.8;worldedit_gui_replace_replace;Name;%s]", minetest.formspec_escape(replace)) .. "button[4,2.18;1.5,0.8;worldedit_gui_replace_replace_search;Search]" .. - (replace_nodename and string.format("item_image[5.5,2.1;1,1;%s]", replace_nodename) - or "image[5.5,2.1;1,1;unknown_node.png]") .. + formspec_node("5.5,2.1", replace_nodename) .. "button_exit[0,3.5;3,0.8;worldedit_gui_replace_submit;Replace Nodes]" .. "button_exit[3.5,3.5;3,0.8;worldedit_gui_replace_submit_inverse;Replace Inverse]" end, @@ -198,10 +204,19 @@ worldedit.register_gui_handler("worldedit_gui_replace", function(name, fields) gui_nodename1[name] = tostring(fields.worldedit_gui_replace_search) gui_nodename2[name] = tostring(fields.worldedit_gui_replace_replace) worldedit.show_page(name, "worldedit_gui_replace") + + local submit = nil if fields.worldedit_gui_replace_submit then - minetest.chatcommands["/replace"].func(name, string.format("%s %s", gui_nodename1[name], gui_nodename2[name])) + submit = "replace" elseif fields.worldedit_gui_replace_submit_inverse then - minetest.chatcommands["/replaceinverse"].func(name, string.format("%s %s", gui_nodename1[name], gui_nodename2[name])) + submit = "replaceinverse" + end + if submit then + local n1 = worldedit.normalize_nodename(gui_nodename1[name]) + local n2 = worldedit.normalize_nodename(gui_nodename2[name]) + if n1 and n2 then + minetest.chatcommands["/"..submit].func(name, string.format("%s %s", n1, n2)) + end end return true end @@ -216,8 +231,7 @@ worldedit.register_gui_function("worldedit_gui_sphere_dome", { return "size[6.5,5]" .. worldedit.get_formspec_header("worldedit_gui_sphere_dome") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_sphere_dome_node;Name;%s]", minetest.formspec_escape(node)) .. "button[4,1.18;1.5,0.8;worldedit_gui_sphere_dome_search;Search]" .. - (nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", nodename) .. string.format("field[0.5,2.5;4,0.8;worldedit_gui_sphere_dome_radius;Radius;%s]", minetest.formspec_escape(radius)) .. "button_exit[0,3.5;3,0.8;worldedit_gui_sphere_dome_submit_hollow;Hollow Sphere]" .. "button_exit[3.5,3.5;3,0.8;worldedit_gui_sphere_dome_submit_solid;Solid Sphere]" .. @@ -233,14 +247,22 @@ worldedit.register_gui_handler("worldedit_gui_sphere_dome", function(name, field gui_nodename1[name] = tostring(fields.worldedit_gui_sphere_dome_node) gui_distance2[name] = tostring(fields.worldedit_gui_sphere_dome_radius) worldedit.show_page(name, "worldedit_gui_sphere_dome") + + local submit = nil if fields.worldedit_gui_sphere_dome_submit_hollow then - minetest.chatcommands["/hollowsphere"].func(name, string.format("%s %s", gui_distance2[name], gui_nodename1[name])) + submit = "hollowsphere" elseif fields.worldedit_gui_sphere_dome_submit_solid then - minetest.chatcommands["/sphere"].func(name, string.format("%s %s", gui_distance2[name], gui_nodename1[name])) + submit = "sphere" elseif fields.worldedit_gui_sphere_dome_submit_hollow_dome then - minetest.chatcommands["/hollowdome"].func(name, string.format("%s %s", gui_distance2[name], gui_nodename1[name])) + submit = "hollowdome" elseif fields.worldedit_gui_sphere_dome_submit_solid_dome then - minetest.chatcommands["/dome"].func(name, string.format("%s %s", gui_distance2[name], gui_nodename1[name])) + submit = "dome" + end + if submit then + local n = worldedit.normalize_nodename(gui_nodename1[name]) + if n then + minetest.chatcommands["/"..submit].func(name, string.format("%s %s", gui_distance2[name], n)) + end end return true end @@ -255,8 +277,7 @@ worldedit.register_gui_function("worldedit_gui_cylinder", { return "size[6.5,5]" .. worldedit.get_formspec_header("worldedit_gui_cylinder") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_cylinder_node;Name;%s]", minetest.formspec_escape(node)) .. "button[4,1.18;1.5,0.8;worldedit_gui_cylinder_search;Search]" .. - (nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", nodename) .. string.format("field[0.5,2.5;4,0.8;worldedit_gui_cylinder_length;Length;%s]", minetest.formspec_escape(length)) .. string.format("dropdown[4,2.18;2.5;worldedit_gui_cylinder_axis;X axis,Y axis,Z axis,Look direction;%d]", axis) .. string.format("field[0.5,3.5;4,0.8;worldedit_gui_cylinder_radius;Radius;%s]", minetest.formspec_escape(radius)) .. @@ -273,10 +294,18 @@ worldedit.register_gui_handler("worldedit_gui_cylinder", function(name, fields) gui_distance1[name] = tostring(fields.worldedit_gui_cylinder_length) gui_distance2[name] = tostring(fields.worldedit_gui_cylinder_radius) worldedit.show_page(name, "worldedit_gui_cylinder") + + local submit = nil if fields.worldedit_gui_cylinder_submit_hollow then - minetest.chatcommands["/hollowcylinder"].func(name, string.format("%s %s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_distance2[name], gui_nodename1[name])) + submit = "hollowcylinder" elseif fields.worldedit_gui_cylinder_submit_solid then - minetest.chatcommands["/cylinder"].func(name, string.format("%s %s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_distance2[name], gui_nodename1[name])) + submit = "cylinder" + end + if submit then + local n = worldedit.normalize_nodename(gui_nodename1[name]) + if n then + minetest.chatcommands["/"..submit].func(name, string.format("%s %s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_distance2[name], n)) + end end return true end @@ -296,8 +325,7 @@ worldedit.register_gui_function("worldedit_gui_pyramid", { return "size[6.5,4]" .. worldedit.get_formspec_header("worldedit_gui_pyramid") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_pyramid_node;Name;%s]", minetest.formspec_escape(node)) .. "button[4,1.18;1.5,0.8;worldedit_gui_pyramid_search;Search]" .. - (nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", nodename) .. string.format("field[0.5,2.5;4,0.8;worldedit_gui_pyramid_length;Length;%s]", minetest.formspec_escape(length)) .. string.format("dropdown[4,2.18;2.5;worldedit_gui_pyramid_axis;X axis,Y axis,Z axis,Look direction;%d]", axis) .. "button_exit[0,3.5;3,0.8;worldedit_gui_pyramid_submit_hollow;Hollow Pyramid]" .. @@ -311,10 +339,18 @@ worldedit.register_gui_handler("worldedit_gui_pyramid", function(name, fields) gui_axis1[name] = axis_indices[fields.worldedit_gui_pyramid_axis] gui_distance1[name] = tostring(fields.worldedit_gui_pyramid_length) worldedit.show_page(name, "worldedit_gui_pyramid") + + local submit = nil if fields.worldedit_gui_pyramid_submit_solid then - minetest.chatcommands["/pyramid"].func(name, string.format("%s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_nodename1[name])) + submit = "pyramid" elseif fields.worldedit_gui_pyramid_submit_hollow then - minetest.chatcommands["/hollowpyramid"].func(name, string.format("%s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_nodename1[name])) + submit = "hollowpyramid" + end + if submit then + local n = worldedit.normalize_nodename(gui_nodename1[name]) + if n then + minetest.chatcommands["/"..submit].func(name, string.format("%s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], n)) + end end return true end @@ -334,8 +370,7 @@ worldedit.register_gui_function("worldedit_gui_spiral", { return "size[6.5,6]" .. worldedit.get_formspec_header("worldedit_gui_spiral") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_spiral_node;Name;%s]", minetest.formspec_escape(node)) .. "button[4,1.18;1.5,0.8;worldedit_gui_spiral_search;Search]" .. - (nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", nodename) .. string.format("field[0.5,2.5;4,0.8;worldedit_gui_spiral_length;Side Length;%s]", minetest.formspec_escape(length)) .. string.format("field[0.5,3.5;4,0.8;worldedit_gui_spiral_height;Height;%s]", minetest.formspec_escape(height)) .. string.format("field[0.5,4.5;4,0.8;worldedit_gui_spiral_space;Wall Spacing;%s]", minetest.formspec_escape(space)) .. @@ -351,7 +386,10 @@ worldedit.register_gui_handler("worldedit_gui_spiral", function(name, fields) gui_distance3[name] = tostring(fields.worldedit_gui_spiral_space) worldedit.show_page(name, "worldedit_gui_spiral") if fields.worldedit_gui_spiral_submit then - minetest.chatcommands["/spiral"].func(name, string.format("%s %s %s %s", gui_distance1[name], gui_distance2[name], gui_distance3[name], gui_nodename1[name])) + local n = worldedit.normalize_nodename(gui_nodename1[name]) + if n then + minetest.chatcommands["/spiral"].func(name, string.format("%s %s %s %s", gui_distance1[name], gui_distance2[name], gui_distance3[name], n)) + end end return true end @@ -456,7 +494,6 @@ worldedit.register_gui_function("worldedit_gui_transpose", { worldedit.register_gui_handler("worldedit_gui_transpose", function(name, fields) if fields.worldedit_gui_transpose_submit then gui_axis1[name] = axis_indices[fields.worldedit_gui_transpose_axis1] - gui_axis2[name] = axis_indices[fields.worldedit_gui_transpose_axis2] worldedit.show_page(name, "worldedit_gui_transpose") minetest.chatcommands["/transpose"].func(name, string.format("%s %s", axis_values[gui_axis1[name]], axis_values[gui_axis2[name]])) return true @@ -578,8 +615,7 @@ worldedit.register_gui_function("worldedit_gui_suppress", { return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_suppress") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_suppress_node;Name;%s]", minetest.formspec_escape(node)) .. "button[4,1.18;1.5,0.8;worldedit_gui_suppress_search;Search]" .. - (nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", nodename) .. "button_exit[0,2.5;3,0.8;worldedit_gui_suppress_submit;Suppress Nodes]" end, }) @@ -589,7 +625,10 @@ worldedit.register_gui_handler("worldedit_gui_suppress", function(name, fields) gui_nodename1[name] = tostring(fields.worldedit_gui_suppress_node) worldedit.show_page(name, "worldedit_gui_suppress") if fields.worldedit_gui_suppress_submit then - minetest.chatcommands["/suppress"].func(name, gui_nodename1[name]) + local n = worldedit.normalize_nodename(gui_nodename1[name]) + if n then + minetest.chatcommands["/suppress"].func(name, n) + end end return true end @@ -604,8 +643,7 @@ worldedit.register_gui_function("worldedit_gui_highlight", { return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_highlight") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_highlight_node;Name;%s]", minetest.formspec_escape(node)) .. "button[4,1.18;1.5,0.8;worldedit_gui_highlight_search;Search]" .. - (nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", nodename) .. "button_exit[0,2.5;3,0.8;worldedit_gui_highlight_submit;Highlight Nodes]" end, }) @@ -615,7 +653,10 @@ worldedit.register_gui_handler("worldedit_gui_highlight", function(name, fields) gui_nodename1[name] = tostring(fields.worldedit_gui_highlight_node) worldedit.show_page(name, "worldedit_gui_highlight") if fields.worldedit_gui_highlight_submit then - minetest.chatcommands["/highlight"].func(name, gui_nodename1[name]) + local n = worldedit.normalize_nodename(gui_nodename1[name]) + if n then + minetest.chatcommands["/highlight"].func(name, n) + end end return true end diff --git a/worldedit_gui/init.lua b/worldedit_gui/init.lua index 57fd9a88..0a770c6b 100644 --- a/worldedit_gui/init.lua +++ b/worldedit_gui/init.lua @@ -131,7 +131,37 @@ elseif rawget(_G, "inventory_plus") then --inventory++ installed inventory_plus.set_inventory_formspec(player, get_formspec(name, page)) end end +elseif rawget(_G, "sfinv") then --sfinv installed (part of minetest_game since 0.4.15) + assert(sfinv.enabled) + local orig_get = sfinv.pages["sfinv:crafting"].get + sfinv.override_page("sfinv:crafting", { + get = function(self, player, context) + local can_worldedit = minetest.check_player_privs(player, {worldedit=true}) + local fs = orig_get(self, player, context) + return fs .. (can_worldedit and "image_button[0,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]" or "") + end + }) + + --show the form when the button is pressed and hide it when done + minetest.register_on_player_receive_fields(function(player, formname, fields) + if fields.worldedit_gui then --main page + worldedit.show_page(player:get_player_name(), "worldedit_gui") + return true + elseif fields.worldedit_gui_exit then --return to original page + sfinv.set_page(player, "sfinv:crafting") + return true + end + return false + end) + + worldedit.show_page = function(name, page) + local player = minetest.get_player_by_name(name) + if player then + player:set_inventory_formspec(get_formspec(name, page)) + end + end else --fallback button + -- FIXME: this is a huge clusterfuck and the back button is broken local player_formspecs = {} local update_main_formspec = function(name) diff --git a/worldedit_gui/textures/worldedit_gui_unknown.png b/worldedit_gui/textures/worldedit_gui_unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..f57436ca16aef91522a9af86f6254b837fbd5b30 GIT binary patch literal 597 zcmV-b0;>IqP)uIyy&3M_XH4US3{eVq#-sV`*t=Y;0_9Zf=Bx zgocKOiHV7gjg6C&la`j2n3$NGo131Vo}{FtrKP2&rlzN-r>Ll?tE;QGx3|5$y}`l3 z!otGI$;r;n&e74)($dn?)6>`2*Vx$D+}zyV-QDQu=;`U{?Ck9B?(XmJ@9^;O@bK{Q z@$vTd_V@Sq`1ttw`T70*{r~^};APuH0000!bW%=J0HdU&rKhK>tgWrEv9h+jy}rJ{ z!NSSP%goNu(9zP>)z;S5*xcXY;pOJ&=;`b1?(XyS_4oJp`1$+%{QbwHx{?3@00Cl4 zM?^n9V=#39007ZRL_t(I%e~ac4#F@HMbQj3q4(Z|00000NkvXXu0mjfa5^C* literal 0 HcmV?d00001