Add utility script, extend vector

main
copygirl 8 months ago
parent cf4c8d95ba
commit efc5e81946
  1. 49
      contraption.lua
  2. 46
      utility.lua

@ -1,9 +1,12 @@
local math, pairs, ipairs, setmetatable, table_insert, print
= math, pairs, ipairs, setmetatable, table.insert, print
local math, pairs, ipairs, setmetatable, table_insert
= math, pairs, ipairs, setmetatable, table.insert
local minetest, vector, nodecore
= minetest, vector, nodecore
local utility = include("utility")
local error = utility.error
local mod_name = minetest.get_current_modname()
local mod_storage = minetest.get_mod_storage()
@ -28,22 +31,18 @@ local active_contraptions = {}
-- TODO: Water physics!
-- TODO: Rotation.
-- TODO: Sound.
-- TODO: Discoveries.
-- TODO: Push items in a pyramid.
-- TODO: Damage players colliding with fast-moving contraption.
-- TODO: Damage players when squishing them into a wall.
-- TODO: Allow glueing separate contraptions together?
-- TODO: Add region type.
-- TODO: Unload and save contraptions when they're in unloaded chunks.
-- TODO: Use meta field `infotext` for displaying debug info about a contraption?
-- TODO: Use voxel manipulator for moving contraptions.
local function error(...)
local str = "[" .. mod_name .. "] "
for _, v in ipairs({...}) do str = str + tostring(v) end
print(str)
end
--------------------
-- EVENT HANDLING --
--------------------
@ -139,8 +138,7 @@ function contraption.create(region)
local node = minetest.get_node(pos)
if nodecore.match(node, PLANK) then
local offset = pos - region.min
local pos_hash = minetest.hash_node_position(offset)
nodes[pos_hash] = CONTRAPTION_WOOD
nodes[offset:hash()] = CONTRAPTION_WOOD
num_nodes = num_nodes + 1
end
end
@ -165,7 +163,7 @@ function contraption.create(region)
-- Change nodes from base nodes to their contraption version.
for pos_hash, node in pairs(nodes) do
local rel_pos = vector.copy(minetest.get_position_from_hash(pos_hash))
local rel_pos = vector.convert(pos_hash)
local abs_pos = region.min + rel_pos
minetest.set_node(abs_pos, node)
end
@ -178,13 +176,12 @@ end
function contraption:on_initialize()
local above_nodes = {}
for orig_pos_hash, node in pairs(self.nodes) do
local orig_pos = vector.copy(minetest.get_position_from_hash(orig_pos_hash))
local orig_pos = vector.convert(orig_pos_hash)
-- Calculate the nodes above the contraption that it
-- could potentially pull along with it as it moves.
local above_pos = orig_pos:offset(0, 1, 0)
local above_pos_hash = minetest.hash_node_position(above_pos)
if not self.nodes[above_pos_hash] then
if not self.nodes[above_pos:hash()] then
-- Non-contraption block above this one. Move items here along.
table_insert(above_nodes, above_pos)
end
@ -207,8 +204,8 @@ function contraption.load_from_string(id, str)
nodes = obj.nodes,
num_nodes = obj.num_nodes,
motion = obj.motion and vector.copy(obj.motion ) or nil,
partial = obj.partial and vector.copy(obj.partial) or nil,
motion = obj.motion and vector.convert(obj.motion ) or nil,
partial = obj.partial and vector.convert(obj.partial) or nil,
}, metatable)
result:on_initialize()
@ -234,7 +231,7 @@ function contraption:destroy()
active_contraptions[self.id] = nil
for pos_hash, node in pairs(self.nodes) do
local rel_pos = vector.copy(minetest.get_position_from_hash(pos_hash))
local rel_pos = vector.convert(pos_hash)
local abs_pos = self.region.min + rel_pos
local def = minetest.registered_nodes[node.name]
minetest.set_node(abs_pos, def.drop_in_place)
@ -326,18 +323,17 @@ function contraption:move(offset)
local abs_pos = self.region.min + rel_pos
local node = minetest.get_node(abs_pos)
if contraption.is_pushable(node) then
local pos_hash = minetest.hash_node_position(rel_pos)
to_push[pos_hash] = { node = node, meta = minetest.get_meta(abs_pos):to_table() }
to_push[rel_pos:hash()] = { node = node, meta = minetest.get_meta(abs_pos):to_table() }
end
end
for old_rel_pos_hash, node in pairs(self.nodes) do
local old_rel_pos = vector.copy(minetest.get_position_from_hash(old_rel_pos_hash))
local old_rel_pos = vector.convert(old_rel_pos_hash)
local old_abs_pos = self.region.min + old_rel_pos
local new_abs_pos = old_abs_pos + offset
local new_rel_pos = old_rel_pos + offset
local new_rel_pos_hash = minetest.hash_node_position(new_rel_pos)
local new_rel_pos_hash = new_rel_pos:hash()
-- Node is being moved to this position, no need to clear here.
to_clear[new_rel_pos_hash] = nil
@ -356,7 +352,7 @@ function contraption:move(offset)
while true do
new_abs_pos = new_abs_pos + offset
new_rel_pos = new_rel_pos + offset
new_rel_pos_hash = minetest.hash_node_position(new_rel_pos)
new_rel_pos_hash = new_rel_pos:hash()
local pushable = to_push[new_rel_pos_hash]
if pushable then
-- The next node is a pushable node that was going to
@ -394,13 +390,12 @@ function contraption:move(offset)
-- The `to_push` table contains "lose" nodes that are not directly
-- pushed by the contraption, and may or may not be pushed.
for pos_hash, node in pairs(to_push) do
local rel_pos = vector.copy(minetest.get_position_from_hash(pos_hash))
local rel_pos = vector.convert(pos_hash)
local forward_rel_pos = rel_pos + offset
local forward_rel_pos_hash = minetest.hash_node_position(forward_rel_pos)
-- If there's a node to push ahead of this one, skip.
-- 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
@ -417,7 +412,7 @@ function contraption:move(offset)
while true do
local backward_rel_pos = rel_pos - offset
local backward_rel_pos_hash = minetest.hash_node_position(backward_rel_pos)
local backward_rel_pos_hash = backward_rel_pos:hash()
node = to_push[backward_rel_pos_hash]
if not node then break end
@ -439,7 +434,7 @@ function contraption:move(offset)
-- Clear nodes that need to be cleared (to AIR).
for pos_hash, node in pairs(to_clear) do
local rel_pos = vector.copy(minetest.get_position_from_hash(pos_hash))
local rel_pos = vector.convert(pos_hash)
local abs_pos = self.region.min + rel_pos
minetest.set_node(abs_pos, node)
end

@ -0,0 +1,46 @@
local ipairs, setmetatable, tostring, print
= ipairs, setmetatable, tostring, print
local minetest, vector
= minetest, vector
local mod_name = minetest.get_current_modname()
local utility = {}
-- Prints an error message by concatenating the parameters as strings.
function error(...)
local str = "[" .. mod_name .. "] "
for _, v in ipairs({...}) do str = str + tostring(v) end
print(str)
end
utility.error = utility
if not vector.convert then
function vector.convert(v)
local t = type(v)
if t == "number" then
-- Assume the number was created by calling `vector.hash`.
return setmetatable(minetest.get_position_from_hash(v), vector.metatable)
elseif t == "string" then
-- Assume the string is either in `(x, y, z)` or `{x=x, y=y, z=z}` format.
local first_chr = v:byte(1)
if first_chr == "(" then return vector.from_string(v)
elseif first_chr == "{" then return setmetatable(minetest.deserialize(v), vector.metatable)
else error("Cannot convert string '" .. v .. "' to vector") end
elseif t == "table" then
-- Assume the table already has `x`, `y` and `z` entries.
-- Returns the same table, making sure its metatable is set.
return setmetatable(v, vector.metatable)
else error("Cannot convert type '" .. t .. "' to vector") end
end
end
if not vector.hash then
function vector:hash()
return minetest.hash_node_position(self)
end
end
return utility
Loading…
Cancel
Save