From b717ea2bd788f02579b04efce560f3f14f731538 Mon Sep 17 00:00:00 2001 From: loosewheel <76670709+loosewheel@users.noreply.github.com> Date: Sun, 6 Mar 2022 16:37:25 +1000 Subject: [PATCH] Add files via upload --- change.log | 10 +- crafting.lua | 14 +- destroyer.lua | 164 ++++++++++++++ hopper.lua | 70 ++++-- init.lua | 3 +- pistons.lua | 580 +++++++++++++++++++++++++++++++++++++++++--------- readme.txt | 5 +- 7 files changed, 722 insertions(+), 124 deletions(-) create mode 100644 destroyer.lua diff --git a/change.log b/change.log index d2e384c..19d3273 100644 --- a/change.log +++ b/change.log @@ -53,7 +53,7 @@ v0.1.8 * Made changes to lwcomponents.register_spawner api - called function must now set velocity, can use force parameter. * Removed spawning from this mod. Created lwcomponents_spawners to - register spawers. + register spawners. v0.1.9 @@ -153,3 +153,11 @@ v0.1.25 * Improved unescaping item description. * Fixed custom item output from storage. * Added filtering to conduit forms. + + +v0.1.26 +* Added support for stickblocks to pistons. +* Changed description of hoppers to avoid confusion. +* Added destroyer. +* Cleaned up hopper code. +* Fixed recipe for solid conductor blocks. diff --git a/crafting.lua b/crafting.lua index c09cffb..5720e5b 100644 --- a/crafting.lua +++ b/crafting.lua @@ -101,6 +101,16 @@ minetest.register_craft( { }) +minetest.register_craft( { + output = "lwcomponents:destroyer", + recipe = { + { "default:stone", "", "group:wood" }, + { "", "default:steel_ingot", "" }, + { "group:wood", "", "default:stone" } + }, +}) + + minetest.register_craft( { output = "lwcomponents:cannon_shell 10", recipe = { @@ -437,7 +447,7 @@ end -- utils.digilines_supported and utils.mesecon_supported if utils.unifieddyes_supported and utils.mesecon_supported then minetest.register_craft ({ - output = "lwcomputers:solid_conductor_off 3", + output = "lwcomponents:solid_conductor_off 3", recipe = { { "default:mese_crystal_fragment", "group:wood", ""}, { "group:wood", "group:wood", "dye:white" }, @@ -446,7 +456,7 @@ minetest.register_craft ({ minetest.register_craft ({ - output = "lwcomputers:solid_horizontal_conductor_off 3", + output = "lwcomponents:solid_horizontal_conductor_off 3", recipe = { { "group:wood", "group:wood", ""}, { "default:mese_crystal_fragment", "group:wood", "dye:white" }, diff --git a/destroyer.lua b/destroyer.lua new file mode 100644 index 0000000..7aa9aaf --- /dev/null +++ b/destroyer.lua @@ -0,0 +1,164 @@ +local utils = ... +local S = utils.S + + + +local function trash (pos) + local meta = minetest.get_meta (pos) + local inv = (meta and meta:get_inventory ()) or nil + + if inv then + local stack = inv:get_stack ("trash", 1) + + if stack and not stack:is_empty () then + utils.on_destroy (stack) + + inv:set_stack ("trash", 1, nil) + end + end +end + + + +local function trash_delayed (pos) + minetest.after (0.1, trash, pos) +end + + + +local function after_place_node (pos, placer, itemstack, pointed_thing) + local meta = minetest.get_meta (pos) + + if meta then + local inv = meta:get_inventory () + + if inv then + meta:set_string ("inventory", "{ trash = { [1] = '' } }") + meta:set_string ("formspec", + "formspec_version[3]".. + "size[11.75,8.5,false]".. + "label[5.15,1.0;Destroy]".. + "list[context;trash;5.3,1.25;1,1;]".. + "list[current_player;main;1.0,2.75;8,4;]".. + "listring[]") + + inv:set_size ("trash", 1) + inv:set_width ("trash", 1) + end + end + + utils.pipeworks_after_place (pos) + + -- If return true no item is taken from itemstack + return false +end + + + +local function on_metadata_inventory_put (pos, listname, index, stack, player) + if listname == "trash" then + trash_delayed (pos) + end +end + + + +local function on_metadata_inventory_move (pos, from_list, from_index, + to_list, to_index, count, player) + if to_list == "trash" then + trash_delayed (pos) + end +end + + + +local function pipeworks_support () + if utils.pipeworks_supported then + return + { + priority = 100, + input_inventory = "trash", + connect_sides = { left = 1, right = 1, front = 1, back = 1, bottom = 1, top = 1 }, + + insert_object = function (pos, node, stack, direction) + local meta = minetest.get_meta (pos) + local inv = (meta and meta:get_inventory ()) or nil + + if inv then + trash_delayed (pos) + + return inv:add_item ("trash", stack) + end + + return stack + end, + + can_insert = function (pos, node, stack, direction) + local meta = minetest.get_meta (pos) + local inv = (meta and meta:get_inventory ()) or nil + + if inv then + return inv:room_for_item ("trash", stack) + end + + return false + end, + + can_remove = function (pos, node, stack, dir) + -- returns the maximum number of items of that stack that can be removed + return 0 + end, + + remove_items = function (pos, node, stack, dir, count) + -- removes count items and returns them + return stack + end + } + end + + return nil +end + + + +local destroyer_groups = { cracky = 3 } +if utils.pipeworks_supported then + destroyer_groups.tubedevice = 1 + destroyer_groups.tubedevice_receiver = 1 +end + + + +minetest.register_node("lwcomponents:destroyer", { + description = S("Destroyer"), + drawtype = "normal", + tiles = { "lwcomponents_destroyer_top.png", "lwcomponents_destroyer_top.png", + "lwcomponents_destroyer_side.png", "lwcomponents_destroyer_side.png", + "lwcomponents_destroyer_side.png", "lwcomponents_destroyer_side.png" }, + is_ground_content = false, + groups = table.copy (destroyer_groups), + sounds = default.node_sound_stone_defaults (), + paramtype = "none", + param1 = 0, + paramtype2 = "none", + param2 = 0, + floodable = false, + + tube = pipeworks_support (), + + after_place_node = after_place_node, + after_dig_node = utils.pipeworks_after_dig, + on_metadata_inventory_put = on_metadata_inventory_put, + on_metadata_inventory_move = on_metadata_inventory_move, +}) + + + +utils.hopper_add_container({ + {"bottom", "lwcomponents:destroyer", "trash"}, -- insert items below from hopper above + {"side", "lwcomponents:destroyer", "trash"}, -- insert items from hopper at side +}) + + + +-- diff --git a/hopper.lua b/hopper.lua index 89543a9..91f7662 100644 --- a/hopper.lua +++ b/hopper.lua @@ -149,6 +149,29 @@ end +local function call_allow_metadata_inventory_put (def, pos, listname, index, stack, placer) + if def.allow_metadata_inventory_put and placer then + local result, count = pcall (def.allow_metadata_inventory_put, + pos, listname, index, stack, placer) + + if result then + return count + end + end + + return utils.settings.default_stack_max +end + + + +local function call_on_metadata_inventory_put (def, pos, listname, index, stack, placer) + if def.on_metadata_inventory_put and placer then + pcall (def.on_metadata_inventory_put, pos, listname, index, stack, placer) + end +end + + + local function place_item (dest_pos, dest_node, dest_inv_name, stack, placer) local dest_def = minetest.registered_nodes[dest_node.name] @@ -169,16 +192,12 @@ local function place_item (dest_pos, dest_node, dest_inv_name, stack, placer) if inv_stack and not inv_stack:is_empty () and utils.is_same_item (inv_stack, stack) and inv_stack:get_count () < inv_stack:get_stack_max () and - (dest_def.allow_metadata_inventory_put == nil or - placer == nil or - dest_def.allow_metadata_inventory_put(dest_pos, dest_inv_name, slot, stack, placer) > 0) then + (call_allow_metadata_inventory_put (dest_def, dest_pos, dest_inv_name, slot, stack, placer) > 0) then inv_stack:set_count (inv_stack:get_count () + 1) dest_inv:set_stack (dest_inv_name, slot, inv_stack) - if dest_def.on_metadata_inventory_put and placer then - dest_def.on_metadata_inventory_put (dest_pos, dest_inv_name, slot, stack, placer) - end + call_on_metadata_inventory_put (dest_def, dest_pos, dest_inv_name, slot, stack, placer) return true end @@ -189,15 +208,11 @@ local function place_item (dest_pos, dest_node, dest_inv_name, stack, placer) local inv_stack = dest_inv:get_stack (dest_inv_name, slot) if not inv_stack or inv_stack:is_empty () and - (dest_def.allow_metadata_inventory_put == nil or - placer == nil or - dest_def.allow_metadata_inventory_put(dest_pos, dest_inv_name, slot, stack, placer) > 0) then + (call_allow_metadata_inventory_put (dest_def, dest_pos, dest_inv_name, slot, stack, placer) > 0) then dest_inv:set_stack (dest_inv_name, slot, stack) - if dest_def.on_metadata_inventory_put and placer then - dest_def.on_metadata_inventory_put (dest_pos, dest_inv_name, slot, stack, placer) - end + call_on_metadata_inventory_put (dest_def, dest_pos, dest_inv_name, slot, stack, placer) return true end @@ -209,6 +224,28 @@ end +local function get_player_object (pos) + local meta = minetest.get_meta (pos) + local placer_name = "" + + if meta then + placer_name = meta:get_string ("placer_name") + local placer = minetest.get_player_by_name (placer_name) + + if placer then + return placer + end + + if placer_name == "" then + placer_name = "" + end + end + + return utils.get_dummy_player (true, placer_name) +end + + + local function run_hopper_action (pos) local node = utils.get_far_node (pos) local dest_dir = get_output_dir (node) @@ -221,10 +258,7 @@ local function run_hopper_action (pos) local registered_dest_invs = hopper.get_registered_inventories_for (dest_node.name) if registered_dest_invs then - local meta = minetest.get_meta (pos) - local placer_name = (meta and meta:get_string ("placer_name")) or nil - local placer = (placer_name and minetest.get_player_by_name (placer_name)) or - utils.get_dummy_player (true, placer_name or "") + local placer = get_player_object (pos) local src_pos = vector.add (pos, get_input_dir (node)) local drop = nil local stack = nil @@ -310,7 +344,7 @@ end minetest.register_node ("lwcomponents:hopper", { - description = S("Hopper"), + description = S("Conduit Hopper"), tiles = { "lwcomponents_hopper_top.png", "lwcomponents_hopper_vert_spout.png", "lwcomponents_hopper_side.png", "lwcomponents_hopper_side.png", "lwcomponents_hopper_side.png", "lwcomponents_hopper_side.png" }, @@ -359,7 +393,7 @@ minetest.register_node ("lwcomponents:hopper", { minetest.register_node ("lwcomponents:hopper_horz", { - description = S("Hopper"), + description = S("Conduit Hopper"), tiles = { "lwcomponents_hopper_top.png", "lwcomponents_hopper_bottom.png", "lwcomponents_hopper_side.png", "lwcomponents_hopper_side.png", "lwcomponents_hopper_side_spout.png", "lwcomponents_hopper_side.png" }, diff --git a/init.lua b/init.lua index bb41514..63a2038 100644 --- a/init.lua +++ b/init.lua @@ -1,4 +1,4 @@ -local version = "0.1.25" +local version = "0.1.26" local mod_storage = minetest.get_mod_storage () @@ -41,6 +41,7 @@ loadfile (modpath.."/through_wire.lua") (utils) loadfile (modpath.."/camera.lua") (utils) loadfile (modpath.."/storage.lua") (utils) loadfile (modpath.."/force_field.lua") (utils) +loadfile (modpath.."/destroyer.lua") (utils) loadfile (modpath.."/extras.lua") (utils) loadfile (modpath.."/digiswitch.lua") (utils) loadfile (modpath.."/movefloor.lua") (utils) diff --git a/pistons.lua b/pistons.lua index 7c8d85b..4c19eaa 100644 --- a/pistons.lua +++ b/pistons.lua @@ -43,33 +43,36 @@ end -local function push_entities (pos, vec) - local tpos = vector.add (pos, vec) - local tnode = utils.get_far_node (tpos) - local can_move = false +local function push_entities (pos, movedir, entity_list, upper_limit) + local objects = minetest.get_objects_inside_radius (pos, 1.5) - if tnode then - if tnode.name == "air" then - can_move = true - else - local tdef = utils.find_item_def (tnode.name) + for _, obj in ipairs (objects) do + if obj.get_pos and obj.move_to then + local opos = obj:get_pos () - can_move = tdef and not tdef.walkable - end - end - - if can_move then - local object = minetest.get_objects_inside_radius (pos, 1.5) - - for j = 1, #object do - if object[j].get_pos then - local opos = object[j]:get_pos () - - if opos.x > (pos.x - 0.5) and opos.x < (pos.x + 0.5) and + if opos.x > (pos.x - 0.5) and opos.x < (pos.x + 0.5) and opos.z > (pos.z - 0.5) and opos.z < (pos.z + 0.5) and - opos.y > (pos.y - 0.5) and opos.y < (pos.y + 0.5) then + opos.y >= (pos.y - 0.5) and opos.y < (pos.y + upper_limit) then - object[j]:set_pos (vector.add (opos, vec)) + local newpos = vector.add (opos, movedir) + local node = utils.get_far_node (vector.round (newpos)) + local def = (node and utils.find_item_def (node.name)) or nil + + if (node.name == "air") or (def and not def.walkable) then + + entity_list[#entity_list + 1] = + { + obj = obj, + pos = newpos + } + + obj:move_to (newpos) + else + entity_list[#entity_list + 1] = + { + obj = obj, + pos = opos + } end end end @@ -78,76 +81,261 @@ end -local function push_nodes (pos, extent) - local node = utils.get_far_node (pos) +local function update_player_position (player_list) + for _, entry in ipairs (player_list) do + local player = minetest.get_player_by_name (entry.name) - if node then - local vec = direction_vector (node) - local last = vector.add (pos, vector.multiply (vec, extent)) - local maxnodes = utils.settings.max_piston_nodes + 1 - local count = 0 + if player then + local pos = player:get_pos () - for i = 1, maxnodes do - local tnode = utils.get_far_node (last) - - if not tnode then - return false + if pos.y < entry.pos.y then + pos.y = entry.pos.y + player:set_pos (pos) end + end + end +end - local tdef = utils.find_item_def (tnode.name) - if tnode.name == "air" or (tdef and not tdef.walkable) then - count = i - 1 - break - end - if i == maxnodes then - return false - end +local function queue_player_update (entity_list, movedir) + local players = { } - last = vector.add (last, vec) + for _, entry in ipairs (entity_list) do + if entry.obj and entry.obj:is_player () then + players[#players + 1] = + { + pos = entry.pos, + name = entry.obj:get_player_name () + } + end + end + + if #players > 0 then + minetest.after(0.1, update_player_position, players) + end +end + + + +local rules_alldirs = +{ + {x = 1, y = 0, z = 0}, + {x = -1, y = 0, z = 0}, + {x = 0, y = 1, z = 0}, + {x = 0, y = -1, z = 0}, + {x = 0, y = 0, z = 1}, + {x = 0, y = 0, z = -1}, +} + + + +local function add_pos_to_list (pos, dir, movedir, node_list, check_list) + local hash = minetest.hash_node_position (pos) + + if not check_list[hash] then + if minetest.is_protected (pos, "") then + return 0 end - push_entities (last, vec) + local node = utils.get_far_node (pos) - for i = 1, count, 1 do - local cpos = vector.subtract (last, vec) - local cnode = utils.get_far_node (cpos) - local cmeta = minetest.get_meta (cpos) + if not node then + return 0 + end - if not cnode or not cmeta then - return false + local def = utils.find_item_def (node.name) + + if node.name == "air" or (def and def.buildable_to) then + return 1 + end + + local meta = minetest.get_meta (pos) + local timer = minetest.get_node_timer (pos) + + check_list[hash] = true + + node_list[#node_list + 1] = + { + node = node, + def = def, + pos = vector.new (pos), + newpos = vector.add (pos, movedir), + meta = (meta and meta:to_table ()) or { }, + node_timer = + { + (timer and timer:get_timeout ()) or 0, + (timer and timer:get_elapsed ()) or 0 + } + } + + if def.mvps_sticky then + local sides = def.mvps_sticky (pos, node) + + for _, r in ipairs (sides) do + if add_pos_to_list (r, dir, movedir, node_list, check_list) == 0 then + return 0 + end end + end - local tmeta = cmeta:to_table () - local ctimer = minetest.get_node_timer (cpos) - local ctimeout = (ctimer and ctimer:get_timeout ()) or 0 - local celapsed = (ctimer and ctimer:get_elapsed ()) or 0 + -- If adjacent node is sticky block and connects add that + -- position to the connected table + for _, r in ipairs (rules_alldirs) do + local apos = vector.add (pos, r) + local anode = utils.get_far_node (apos) + local adef = (anode and minetest.registered_nodes[anode.name]) or nil - push_entities (cpos, vec) + if adef and adef.mvps_sticky then + local sides = adef.mvps_sticky (apos, anode) - minetest.remove_node (cpos) - minetest.set_node (last, cnode) + -- connects to this position? + for _, link in ipairs (sides) do + if vector.equals (link, pos) then + if add_pos_to_list (apos, dir, movedir, node_list, check_list) == 0 then + return 0 + end - if tmeta then - cmeta = minetest.get_meta (last) + break + end + end + end + end + end - if not cmeta then + return 2 +end + + + +local function node_list_last_pos (pos, node_list, length) + local movedir = node_list.movedir + local base_pos = node_list.base_pos + + if movedir then + if movedir.x ~= 0 then + return vector.new ({ + x = base_pos.x + (movedir.x * length), + y = pos.y, + z = pos.z + }) + elseif movedir.z ~= 0 then + return vector.new ({ + x = pos.x, + y = pos.y, + z = base_pos.z + (movedir.z * length) + }) + elseif movedir.y ~= 0 then + return vector.new ({ + x = pos.x, + y = base_pos.y + (movedir.y * length), + z = pos.z + }) + end + end + + return pos +end + + + +local function get_node_list (pos, extent, length, maxnodes, pushing, node_list, check_list) + local node = utils.get_far_node (pos) + node_list = node_list or { } + check_list = check_list or { } + + if node then + local dir = vector.round (direction_vector (node)) + local movedir = vector.round ((pushing and dir) or vector.multiply (dir, -1)) + + node_list.dir = dir + node_list.movedir = movedir + node_list.base_pos = vector.add (pos, vector.multiply (dir, extent)) + node_list.length = length + node_list.maxnodes = maxnodes + + check_list[minetest.hash_node_position (vector.add (pos, vector.multiply (dir, extent - 1)))] = true + + for i = 0, length - 1, 1 do + local tpos = vector.add (pos, vector.multiply (dir, extent + i)) + + local result = add_pos_to_list (tpos, dir, movedir, node_list, check_list) + + if result == 0 then + return false + elseif result == 1 then + break + end + end + + -- get any ahead of stickyblocks to limit + local copy_list = table.copy (node_list) + + for _, n in ipairs (copy_list) do + local hash = minetest.hash_node_position (n.newpos) + + if not check_list[hash] then + local last_pos = node_list_last_pos (n.newpos, node_list, length) + local this_pos = vector.new (n.newpos) + local count = 0 + + while not vector.equals (this_pos, last_pos) and count < length do + local result = add_pos_to_list (this_pos, dir, movedir, node_list, check_list) + + if result == 0 then + return false + elseif result == 1 then + break + end + + count = count + 1 + this_pos = vector.add (this_pos, movedir) + end + end + end + + return true + end + + return false +end + + + +local function can_node_list_move (node_list, check_list) + local movedir = node_list.movedir + local radius = math.floor (node_list.maxnodes / 2) + local base_pos = node_list.base_pos + + if movedir then + for _, n in ipairs (node_list) do + -- check connected stickyblocks don't extend too far laterally + if movedir.x ~= 0 then + if math.abs (n.pos.y - base_pos.y) > radius or + math.abs (n.pos.z - base_pos.z) > radius then return false end - - cmeta:from_table (tmeta) - end - - if ctimeout > 0 then - ctimer = minetest.get_node_timer (last) - - if ctimer then - ctimer:set (ctimeout, celapsed) + elseif movedir.z ~= 0 then + if math.abs (n.pos.y - base_pos.y) > radius or + math.abs (n.pos.x - base_pos.x) > radius then + return false + end + elseif movedir.y ~= 0 then + if math.abs (n.pos.x - base_pos.x) > radius or + math.abs (n.pos.z - base_pos.z) > radius then + return false end end - last = cpos + -- check moving to is clear + if not check_list[minetest.hash_node_position (n.newpos)] then + local node = utils.get_far_node (n.newpos) + local def = (node and utils.find_item_def (node.name)) or nil + + if node.name ~= "air" and def and not def.buildable_to then + return false + end + end end end @@ -156,47 +344,239 @@ end -local function pull_node (pos, extent) - local node = utils.get_far_node (pos) +local function sort_node_list (node_list) + local movedir = node_list.movedir - if node then - local vec = direction_vector (node) - local cpos = vector.add (pos, vector.multiply (vec, extent)) - local cnode = utils.get_far_node (cpos) - local cdef = cnode and utils.find_item_def (cnode.name) + if movedir then + if movedir.x > 0 then + table.sort (node_list , function (n1, n2) + return n1.pos.x > n2.pos.x + end) + elseif movedir.x < 0 then + table.sort (node_list , function (n1, n2) + return n1.pos.x < n2.pos.x + end) + elseif movedir.z > 0 then + table.sort (node_list , function (n1, n2) + return n1.pos.z > n2.pos.z + end) + elseif movedir.z < 0 then + table.sort (node_list , function (n1, n2) + return n1.pos.z < n2.pos.z + end) + elseif movedir.y > 0 then + table.sort (node_list , function (n1, n2) + return n1.pos.y > n2.pos.y + end) + elseif movedir.y < 0 then + table.sort (node_list , function (n1, n2) + return n1.pos.y < n2.pos.y + end) + end + end +end - if cnode and cnode.name ~= "air" and cdef and cdef.walkable then - local cmeta = minetest.get_meta (cpos) - if cmeta then - local tpos = vector.subtract (cpos, vec) - local tmeta = cmeta:to_table () - local ctimer = minetest.get_node_timer (cpos) - local ctimeout = (ctimer and ctimer:get_timeout ()) or 0 - local celapsed = (ctimer and ctimer:get_elapsed ()) or 0 +local on_mvps_move = function (node_list) +end - minetest.remove_node (cpos) - minetest.set_node (tpos, cnode) - if tmeta then - cmeta = minetest.get_meta (tpos) - if cmeta then - cmeta:from_table (tmeta) - end - end +local is_mvps_stopper = function (node, movedir, node_list, id) + return false +end - if ctimeout > 0 then - ctimer = minetest.get_node_timer (tpos) - if ctimer then - ctimer:set (ctimeout, celapsed) - end - end + +local update_mesecons_connections_removed = function (node_list) +end + + + +local update_mesecons_connections_added = function (node_list) +end + + +if utils.mesecon_supported then + if mesecon.on_mvps_move then + on_mvps_move = function (node_list) + for _, callback in ipairs (mesecon.on_mvps_move) do + callback (node_list) end end end + + if mesecon.is_mvps_stopper then + is_mvps_stopper = function (node, movedir, node_list, id) + return mesecon.is_mvps_stopper (node, movedir, node_list, id) + end + end + + if mesecon.on_dignode then + update_mesecons_connections_removed = function (node_list) + for _, node in ipairs (node_list) do + mesecon.on_dignode (node.oldpos, node.node) + end + end + end + + if mesecon.on_placenode then + update_mesecons_connections_added = function (node_list) + for _, node in ipairs (node_list) do + mesecon.on_placenode (node.pos, utils.get_far_node (node.pos)) + end + end + end +end + + + +local function push_nodes (pos, extent) + local node_list = { } + local check_list = { } + local entity_list = { } + local maxnodes = utils.settings.max_piston_nodes + + if not get_node_list (pos, extent, maxnodes, maxnodes, true, node_list, check_list) then + return false + end + + if not can_node_list_move (node_list, check_list, maxnodes) then + return false + end + + sort_node_list (node_list) + + for id, node in ipairs (node_list) do + if is_mvps_stopper (node.node, node_list.movedir, node_list, id) then + return false + end + end + + for _, node in ipairs (node_list) do + node.oldpos = vector.new (node.pos) + node.pos = vector.new (node.newpos) + node.newpos = nil + + minetest.remove_node (node.oldpos) + end + + update_mesecons_connections_removed (node_list) + + -- push entities in front first + for _, node in ipairs (node_list) do + if not check_list[minetest.hash_node_position (node.pos)] then + push_entities (node.pos, node_list.movedir, entity_list, 0.5) + end + end + + for _, node in ipairs (node_list) do + push_entities (node.oldpos, node_list.movedir, entity_list, 1.0) + + minetest.set_node (node.pos, node.node) + + if node.meta then + local meta = minetest.get_meta (node.pos) + + if meta then + meta:from_table (node.meta) + end + end + + if node.node_timer[1] > 0 then + local timer = minetest.get_node_timer (node.pos) + + if timer then + timer:set (node.node_timer[1], node.node_timer[2]) + end + end + end + + -- push any entities in front of pusher + push_entities (node_list.base_pos, node_list.movedir, entity_list, 0.5) + + on_mvps_move (node_list) + update_mesecons_connections_added (node_list) + + if node_list.movedir.y >= 0 then + queue_player_update (entity_list, node_list.movedir) + end + + return true +end + + + +local function pull_node (pos, extent) + local node_list = { } + local check_list = { } + local entity_list = { } + local maxnodes = utils.settings.max_piston_nodes + + if not get_node_list (pos, extent, 1, maxnodes, false, node_list, check_list) then + return false + end + + if not can_node_list_move (node_list, check_list, maxnodes) then + return false + end + + sort_node_list (node_list) + + for id, node in ipairs (node_list) do + if is_mvps_stopper (node.node, node_list.movedir, node_list, id) then + return false + end + end + + for _, node in ipairs (node_list) do + node.oldpos = vector.new (node.pos) + node.pos = vector.new (node.newpos) + node.newpos = nil + + minetest.remove_node (node.oldpos) + end + + update_mesecons_connections_removed (node_list) + + -- push entities in front first + for _, node in ipairs (node_list) do + if not check_list[minetest.hash_node_position (node.pos)] then + push_entities (node.pos, node_list.movedir, entity_list, 0.5) + end + end + + for _, node in ipairs (node_list) do + push_entities (node.oldpos, node_list.movedir, entity_list, 1.0) + + minetest.set_node (node.pos, node.node) + + if node.meta then + local meta = minetest.get_meta (node.pos) + + if meta then + meta:from_table (node.meta) + end + end + + if node.node_timer[1] > 0 then + local timer = minetest.get_node_timer (node.pos) + + if timer then + timer:set (node.node_timer[1], node.node_timer[2]) + end + end + end + + on_mvps_move (node_list) + update_mesecons_connections_added (node_list) + + if node_list.movedir.y >= 0 then + queue_player_update (entity_list, node_list.movedir) + end + + return true end diff --git a/readme.txt b/readme.txt index 64e43ad..c0bdea7 100644 --- a/readme.txt +++ b/readme.txt @@ -13,7 +13,7 @@ CC BY-SA 3.0 Version ======= -0.1.25 +0.1.26 Minetest Version @@ -59,7 +59,8 @@ Various components for mesecons and digilines. * Puncher, punches players or entities within a given reach. * Player button, sends digilines message with player name. * Breaker, digs the nodes directly in front. -* Deployers, places the nodes directly in front. +* Deployer, places the nodes directly in front. +* Destroyer, automated trash. * Hologram, projects a hologram above the hologram node. * Fan, blows any entity, player or drop in front of the fan. * Conduit, connected in a circuit to move items.