forked from minetest-mods/mesecons
Make pistons and movestones move objects (push only yet)
This commit is contained in:
parent
e789794c75
commit
3b38bbcaf2
@ -22,3 +22,17 @@ end
|
||||
function mesecon:cmpPos(p1, p2)
|
||||
return (p1.x == p2.x and p1.y == p2.y and p1.z == p2.z)
|
||||
end
|
||||
|
||||
function mesecon:tablecopy(table) -- deep table copy
|
||||
local newtable = {}
|
||||
|
||||
for idx, item in pairs(table) do
|
||||
if type(item) == "table" then
|
||||
newtable[idx] = mesecon:tablecopy(item)
|
||||
else
|
||||
newtable[idx] = item
|
||||
end
|
||||
end
|
||||
|
||||
return newtable
|
||||
end
|
||||
|
@ -79,6 +79,7 @@ minetest.register_entity("mesecons_movestones:movestone_entity", {
|
||||
textures = {"jeija_movestone_side.png", "jeija_movestone_side.png", "jeija_movestone_side.png", "jeija_movestone_side.png", "jeija_movestone_arrows.png", "jeija_movestone_arrows.png"},
|
||||
collisionbox = {-0.5,-0.5,-0.5, 0.5, 0.5, 0.5},
|
||||
visual = "cube",
|
||||
lastdir = {x=0, y=0, z=0},
|
||||
|
||||
on_punch = function(self, hitter)
|
||||
self.object:remove()
|
||||
@ -90,21 +91,27 @@ minetest.register_entity("mesecons_movestones:movestone_entity", {
|
||||
pos.x, pos.y, pos.z = math.floor(pos.x), math.floor(pos.y), math.floor(pos.z)
|
||||
local direction = mesecon:get_movestone_direction(pos)
|
||||
|
||||
if not direction then
|
||||
if not direction then -- no mesecon power
|
||||
local name = minetest.env:get_node(pos).name
|
||||
if name ~= "air" and name ~= "ignore" and minetest.registered_nodes[name].liquidtype == "none" then
|
||||
mesecon:mvps_push(pos, direction, MOVESTONE_MAXIMUM_PUSH)
|
||||
if name ~= "air" and name ~= "ignore"
|
||||
and minetest.registered_nodes[name].liquidtype == "none" then
|
||||
mesecon:mvps_push(pos, self.lastdir, MOVESTONE_MAXIMUM_PUSH)
|
||||
end
|
||||
minetest.env:add_node(pos, {name="mesecons_movestones:movestone"})
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
local np = mesecon:addPosRule(pos, direction)
|
||||
if not mesecon:mvps_push(np, direction, MOVESTONE_MAXIMUM_PUSH) then
|
||||
local success, stack, oldstack =
|
||||
mesecon:mvps_push(pos, direction, MOVESTONE_MAXIMUM_PUSH)
|
||||
if not success then -- Too large stack/stopper in the way
|
||||
minetest.env:add_node(pos, {name="mesecons_movestones:movestone"})
|
||||
self.object:remove()
|
||||
return
|
||||
else
|
||||
mesecon:mvps_process_stack (stack)
|
||||
mesecon:mvps_move_objects (pos, direction, oldstack)
|
||||
self.lastdir = direction
|
||||
end
|
||||
|
||||
self.object:setvelocity({x=direction.x*2, y=direction.y*2, z=direction.z*2})
|
||||
@ -156,6 +163,7 @@ minetest.register_entity("mesecons_movestones:sticky_movestone_entity", {
|
||||
textures = {"jeija_movestone_side.png", "jeija_movestone_side.png", "jeija_movestone_side.png", "jeija_movestone_side.png", "jeija_sticky_movestone.png", "jeija_sticky_movestone.png"},
|
||||
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||
visual = "cube",
|
||||
lastdir = {x=0, y=0, z=0},
|
||||
|
||||
on_punch = function(self, hitter)
|
||||
self.object:remove()
|
||||
@ -167,21 +175,27 @@ minetest.register_entity("mesecons_movestones:sticky_movestone_entity", {
|
||||
pos.x, pos.y, pos.z = math.floor(pos.x), math.floor(pos.y), math.floor(pos.z)
|
||||
local direction = mesecon:get_movestone_direction(pos)
|
||||
|
||||
if not direction then
|
||||
if not direction then -- no mesecon power
|
||||
local name = minetest.env:get_node(pos).name
|
||||
if name ~= "air" and name ~= "ignore" and minetest.registered_nodes[name].liquidtype == "none" then
|
||||
mesecon:mvps_push(pos, direction, MOVESTONE_MAXIMUM_PUSH)
|
||||
if name ~= "air" and name ~= "ignore"
|
||||
and minetest.registered_nodes[name].liquidtype == "none" then
|
||||
mesecon:mvps_push(pos, self.lastdir, MOVESTONE_MAXIMUM_PUSH)
|
||||
end
|
||||
minetest.env:add_node(pos, {name="mesecons_movestones:sticky_movestone"})
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
local np = mesecon:addPosRule(pos, direction)
|
||||
if not mesecon:mvps_push(np, direction, MOVESTONE_MAXIMUM_PUSH) then
|
||||
local success, stack, oldstack =
|
||||
mesecon:mvps_push(pos, direction, MOVESTONE_MAXIMUM_PUSH)
|
||||
if not success then -- Too large stack/stopper in the way
|
||||
minetest.env:add_node(pos, {name="mesecons_movestones:sticky_movestone"})
|
||||
self.object:remove()
|
||||
return
|
||||
else
|
||||
mesecon:mvps_process_stack (stack)
|
||||
mesecon:mvps_move_objects (pos, direction, oldstack)
|
||||
self.lastdir = direction
|
||||
end
|
||||
|
||||
self.object:setvelocity({x=direction.x*2, y=direction.y*2, z=direction.z*2})
|
||||
@ -190,3 +204,7 @@ minetest.register_entity("mesecons_movestones:sticky_movestone_entity", {
|
||||
mesecon:mvps_pull_all(pos, direction)
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
mesecon:register_mvps_unmov("mesecons_movestones:movestone_entity")
|
||||
mesecon:register_mvps_unmov("mesecons_movestones:sticky_movestone_entity")
|
||||
|
@ -1,6 +1,7 @@
|
||||
--register stoppers for movestones/pistons
|
||||
|
||||
mesecon.mvps_stoppers = {}
|
||||
mesecon.mvps_unmov = {}
|
||||
|
||||
function mesecon:is_mvps_stopper(node, pushdir, stack, stackid)
|
||||
local get_stopper = mesecon.mvps_stoppers[node.name]
|
||||
@ -17,6 +18,15 @@ function mesecon:register_mvps_stopper(nodename, get_stopper)
|
||||
mesecon.mvps_stoppers[nodename] = get_stopper
|
||||
end
|
||||
|
||||
-- Objects that cannot be moved (e.g. movestones)
|
||||
function mesecon:register_mvps_unmov(objectname)
|
||||
mesecon.mvps_unmov[objectname] = true;
|
||||
end
|
||||
|
||||
function mesecon:is_mvps_unmov(objectname)
|
||||
return mesecon.mvps_unmov[objectname]
|
||||
end
|
||||
|
||||
function mesecon:mvps_process_stack(stack)
|
||||
-- update mesecons for placed nodes ( has to be done after all nodes have been added )
|
||||
for _, n in ipairs(stack) do
|
||||
@ -26,13 +36,12 @@ function mesecon:mvps_process_stack(stack)
|
||||
end
|
||||
end
|
||||
|
||||
function mesecon:mvps_push(pos, dir, maximum) -- pos: pos of mvps; dir: direction of push; maximum: maximum nodes to be pushed
|
||||
np = {x = pos.x, y = pos.y, z = pos.z}
|
||||
|
||||
function mesecon:mvps_get_stack(pos, dir, maximum)
|
||||
-- determine the number of nodes to be pushed
|
||||
local np = {x = pos.x, y = pos.y, z = pos.z}
|
||||
local nodes = {}
|
||||
while true do
|
||||
nn = minetest.env:get_node_or_nil(np)
|
||||
local nn = minetest.env:get_node_or_nil(np)
|
||||
if not nn or #nodes > maximum then
|
||||
-- don't push at all, something is in the way (unloaded map or too many nodes)
|
||||
return
|
||||
@ -47,6 +56,11 @@ function mesecon:mvps_push(pos, dir, maximum) -- pos: pos of mvps; dir: directio
|
||||
|
||||
np = mesecon:addPosRule(np, dir)
|
||||
end
|
||||
return nodes
|
||||
end
|
||||
|
||||
function mesecon:mvps_push(pos, dir, maximum) -- pos: pos of mvps; dir: direction of push; maximum: maximum nodes to be pushed
|
||||
local nodes = mesecon:mvps_get_stack(pos, dir, maximum)
|
||||
|
||||
-- determine if one of the nodes blocks the push
|
||||
for id, n in ipairs(nodes) do
|
||||
@ -74,11 +88,12 @@ function mesecon:mvps_push(pos, dir, maximum) -- pos: pos of mvps; dir: directio
|
||||
minetest.env:get_meta(np):from_table(n.meta)
|
||||
end
|
||||
|
||||
local oldstack = mesecon:tablecopy(nodes)
|
||||
for i in ipairs(nodes) do
|
||||
nodes[i].pos = mesecon:addPosRule(nodes[i].pos, dir)
|
||||
end
|
||||
|
||||
return true, nodes
|
||||
return true, nodes, oldstack
|
||||
end
|
||||
|
||||
function mesecon:mvps_pull_single(pos, dir) -- pos: pos of mvps; direction: direction of pull (matches push direction for sticky pistons)
|
||||
@ -123,5 +138,42 @@ function mesecon:mvps_pull_all(pos, direction) -- pos: pos of mvps; direction: d
|
||||
minetest.env:remove_node(oldpos)
|
||||
end
|
||||
|
||||
function mesecon:mvps_move_objects(pos, dir, nodestack)
|
||||
-- Move object at tip of stack
|
||||
local pushpos = mesecon:addPosRule(pos, -- get pos at tip of stack
|
||||
{x = dir.x * (#nodestack),
|
||||
y = dir.y * (#nodestack),
|
||||
z = dir.z * (#nodestack)})
|
||||
|
||||
|
||||
local objects = minetest.env:get_objects_inside_radius(pushpos, 1)
|
||||
for _, obj in ipairs(objects) do
|
||||
local entity = obj:get_luaentity()
|
||||
if not entity or not mesecon:is_mvps_unmov(entity.name) then
|
||||
obj:setpos(mesecon:addPosRule(obj:getpos(), dir))
|
||||
end
|
||||
end
|
||||
|
||||
-- Move objects lying/standing on the stack (before it was pushed - oldstack)
|
||||
local objects_above = {}
|
||||
if tonumber(minetest.setting_get("movement_gravity")) > 0 and dir.y == 0 then
|
||||
-- If gravity positive and dir horizontal, push players standing on the stack
|
||||
for _, n in ipairs(nodestack) do
|
||||
local p_above = mesecon:addPosRule(n.pos, {x=0, y=1, z=0})
|
||||
local objects = minetest.env:get_objects_inside_radius(p_above, 1)
|
||||
for _, obj in ipairs(objects) do
|
||||
table.insert(objects_above, obj)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, obj in ipairs(objects_above) do
|
||||
local entity = obj:get_luaentity()
|
||||
if not entity or not mesecon:is_mvps_unmov(entity.name) then
|
||||
obj:setpos(mesecon:addPosRule(obj:getpos(), dir))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
mesecon:register_mvps_stopper("default:chest_locked")
|
||||
mesecon:register_mvps_stopper("default:furnace")
|
||||
|
@ -70,13 +70,14 @@ end
|
||||
local piston_on = function (pos, node)
|
||||
local pistonspec = minetest.registered_nodes[node.name].mesecons_piston
|
||||
|
||||
dir = piston_get_direction(pistonspec.dir, node)
|
||||
local dir = piston_get_direction(pistonspec.dir, node)
|
||||
local np = mesecon:addPosRule(pos, dir)
|
||||
success, stack = mesecon:mvps_push(np, dir, PISTON_MAXIMUM_PUSH)
|
||||
local success, stack, oldstack = mesecon:mvps_push(np, dir, PISTON_MAXIMUM_PUSH)
|
||||
if success then
|
||||
minetest.env:add_node(pos, {param2 = node.param2, name = pistonspec.onname})
|
||||
minetest.env:add_node(np, {param2 = node.param2, name = pistonspec.pusher})
|
||||
mesecon:mvps_process_stack (stack)
|
||||
mesecon:mvps_move_objects (np, dir, oldstack)
|
||||
end
|
||||
end
|
||||
|
||||
@ -89,7 +90,7 @@ local piston_off = function (pos, node)
|
||||
dir = piston_get_direction(pistonspec.dir, node)
|
||||
pullpos = mesecon:addPosRule(pos, dir)
|
||||
stack = mesecon:mvps_pull_single(pullpos, dir)
|
||||
mesecon:mvps_process_stack(stack)
|
||||
mesecon:mvps_process_stack(pos, dir, stack)
|
||||
end
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user