|
|
|
@ -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 |
|
|
|
|