Make to_set an array

main
copygirl 1 year ago
parent 8b4e042f79
commit cf4c8d95ba
  1. 43
      contraption.lua

@ -311,9 +311,12 @@ function contraption:update(delta_time)
end end
function contraption:move(offset) function contraption:move(offset)
local to_clear = {} -- Nodes to be cleared (to AIR). -- `to_clear` and `to_push` use a relative position hash
local to_push = {} -- Nodes that want to be pushed. -- as their key, since entries will need to be removed.
local to_set = {} -- Nodes that will be modified. local to_clear = {} -- Table of nodes to be cleared (to `AIR`).
local to_push = {} -- Table of nodes that want to be pushed.
-- `to_set` is an append-only array with `{ pos, node, [meta] }` entries.
local to_set = {} -- Array of nodes that will be modified.
-- Assume that every node this contraption occupies needs to be cleared. -- Assume that every node this contraption occupies needs to be cleared.
-- We'll remove entries from `to_clear` when we know a node is moved there. -- We'll remove entries from `to_clear` when we know a node is moved there.
@ -342,34 +345,35 @@ function contraption:move(offset)
local self_overlap = self.nodes[new_rel_pos_hash] local self_overlap = self.nodes[new_rel_pos_hash]
if self_overlap then if self_overlap then
if not nodecore.match(node, self_overlap) then if not nodecore.match(node, self_overlap) then
to_set[new_rel_pos_hash] = node table.insert(to_set, { pos = new_abs_pos, node = node })
end end
else else
local new_node = minetest.get_node(new_abs_pos) local new_node = minetest.get_node(new_abs_pos)
-- TODO: Could also just check `to_push` first instead of checking the node. -- TODO: Could also just check `to_push` first instead of checking the node.
if contraption.is_pushable(new_node) then if contraption.is_pushable(new_node) then
new_node = { node = new_node, meta = minetest.get_meta(new_abs_pos):to_table() } new_node = { node = new_node, meta = minetest.get_meta(new_abs_pos):to_table() }
to_set[new_rel_pos_hash] = node table.insert(to_set, { pos = new_abs_pos, node = node })
while true do while true do
new_abs_pos = new_abs_pos + offset
new_rel_pos = new_rel_pos + offset new_rel_pos = new_rel_pos + offset
new_rel_pos_hash = minetest.hash_node_position(new_rel_pos) new_rel_pos_hash = minetest.hash_node_position(new_rel_pos)
local pushable = to_push[new_rel_pos_hash] local pushable = to_push[new_rel_pos_hash]
if pushable then if pushable then
-- The next node is a pushable node that was going to -- The next node is a pushable node that was going to
-- get pushed by the contraption anyway, so continue. -- get pushed by the contraption anyway, so continue.
to_set[new_rel_pos_hash] = new_node table.insert(to_set, nodecore.underride({ pos = new_abs_pos }, new_node))
to_push[new_rel_pos_hash] = nil to_push[new_rel_pos_hash] = nil
new_node = pushable new_node = pushable
elseif self.nodes[new_rel_pos_hash] then elseif self.nodes[new_rel_pos_hash] then
-- The next node is part of the contraption. -- The next node is part of the contraption.
-- If it can move, this pushable node can move. -- If it can move, this pushable node can move.
to_set[new_rel_pos_hash] = new_node table.insert(to_set, nodecore.underride({ pos = new_abs_pos }, new_node))
-- Do not clear this node by the contraption moving. -- Do not clear this node by the contraption moving.
to_clear[new_rel_pos_hash] = nil to_clear[new_rel_pos_hash] = nil
break break
elseif nodecore.buildable_to(self.region.min + new_rel_pos) then elseif nodecore.buildable_to(new_abs_pos) then
-- The next node is replaceable, so we can replace it. -- The next node is replaceable, so we can replace it.
to_set[new_rel_pos_hash] = new_node table.insert(to_set, nodecore.underride({ pos = new_abs_pos }, new_node))
break break
else else
-- There's a node in the way, abort! -- There's a node in the way, abort!
@ -379,7 +383,7 @@ function contraption:move(offset)
end end
end end
elseif nodecore.buildable_to(new_node) then elseif nodecore.buildable_to(new_node) then
to_set[new_rel_pos_hash] = node table.insert(to_set, { pos = new_abs_pos, node = node })
else else
-- We bumped into a wall or something. -- We bumped into a wall or something.
return false return false
@ -395,20 +399,21 @@ function contraption:move(offset)
local forward_rel_pos_hash = minetest.hash_node_position(forward_rel_pos) local forward_rel_pos_hash = minetest.hash_node_position(forward_rel_pos)
-- If there's a node to push ahead of this one, skip. -- If there's a node to push ahead of this one, skip.
-- The node ahead will take care of pulling the ones behind it along with it. -- The node ahead will take care of pulling the ones behind along with it.
if to_push[forward_rel_pos_hash] then goto continue end if to_push[forward_rel_pos_hash] then goto continue end
local forward_abs_pos = self.region.min + forward_rel_pos
if self.nodes[forward_rel_pos] then if self.nodes[forward_rel_pos] then
-- Do not clear this node by the contraption moving. -- Do not clear this node by the contraption moving.
to_clear[forward_rel_pos] = nil to_clear[forward_rel_pos] = nil
else else
-- If the node(s) can't be pushed, then just don't, but continue -- If the node(s) can't be pushed, then just don't, but continue
-- moving the rest of the contraption and other pushable nodes. -- moving the rest of the contraption and other pushable nodes.
local forward_abs_pos = vector.add(self.region.min, forward_rel_pos)
if not nodecore.buildable_to(forward_abs_pos) then goto continue end if not nodecore.buildable_to(forward_abs_pos) then goto continue end
end end
to_set[forward_rel_pos_hash] = node table.insert(to_set, nodecore.underride({ pos = forward_abs_pos }, node))
while true do while true do
local backward_rel_pos = rel_pos - offset local backward_rel_pos = rel_pos - offset
@ -416,7 +421,8 @@ function contraption:move(offset)
node = to_push[backward_rel_pos_hash] node = to_push[backward_rel_pos_hash]
if not node then break end if not node then break end
to_set[pos_hash] = node local abs_pos = self.region.min + rel_pos
table.insert(to_set, nodecore.underride({ pos = abs_pos }, node))
rel_pos = backward_rel_pos rel_pos = backward_rel_pos
pos_hash = backward_rel_pos_hash pos_hash = backward_rel_pos_hash
end end
@ -426,12 +432,9 @@ function contraption:move(offset)
end end
-- Set nodes that need to be changed. -- Set nodes that need to be changed.
-- TODO: Can this use a vector key instead of hash, or an array? for _, e in ipairs(to_set) do
for pos_hash, node in pairs(to_set) do minetest.set_node(e.pos, e.node)
local rel_pos = vector.copy(minetest.get_position_from_hash(pos_hash)) if e.meta then minetest.get_meta(e.pos):from_table(e.meta) end
local abs_pos = self.region.min + rel_pos
minetest.set_node(abs_pos, node.node or node)
if node.meta then minetest.get_meta(abs_pos):from_table(node.meta) end
end end
-- Clear nodes that need to be cleared (to AIR). -- Clear nodes that need to be cleared (to AIR).

Loading…
Cancel
Save