forked from mtcontrib/pipeworks
109729cfb2
Items can now flow from one chest (or Nore's filter object) to another via the pneumatic tubes! Thanks to Nore and RealBadAngel for the code. Note that this mod has to redefine the default chests and furnaces (see compat.lua) in order to add some new group definitions so that tubes can appear to connect to these objects.
332 lines
9.1 KiB
Lua
332 lines
9.1 KiB
Lua
minetest.register_craftitem(":item_transport:filter", {
|
|
description = "Filter",
|
|
stack_max = 99,
|
|
})
|
|
|
|
minetest.register_node(":item_transport:filter", {
|
|
description = "filter",
|
|
tiles = {"filter_top.png", "filter_top.png", "filter_output.png",
|
|
"filter_input.png", "filter_side.png", "filter_top.png"},
|
|
paramtype2 = "facedir",
|
|
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,tubedevice=1,mesecon=2},
|
|
legacy_facedir_simple = true,
|
|
sounds = default.node_sound_wood_defaults(),
|
|
on_construct = function(pos)
|
|
local meta = minetest.env:get_meta(pos)
|
|
meta:set_string("formspec",
|
|
"invsize[9,9;]"..
|
|
"list[current_name;main;0,2;8,2;]"..
|
|
"list[current_player;main;0,5;8,4;]")
|
|
meta:set_string("infotext", "Filter")
|
|
local inv = meta:get_inventory()
|
|
inv:set_size("main", 8*4)
|
|
end,
|
|
can_dig = function(pos,player)
|
|
local meta = minetest.env:get_meta(pos);
|
|
local inv = meta:get_inventory()
|
|
return inv:is_empty("main")
|
|
end,
|
|
mesecons={effector={action_on=function(pos,node)
|
|
minetest.registered_nodes[node.name].on_punch(pos,node,nil)
|
|
end}},
|
|
on_punch = function (pos, node, puncher)
|
|
local meta = minetest.env:get_meta(pos);
|
|
local inv = meta:get_inventory()
|
|
local frompos
|
|
local dir
|
|
if node.param2==0 then
|
|
frompos={x=pos.x-1,y=pos.y,z=pos.z}
|
|
dir={x=1,y=0,z=0}
|
|
elseif node.param2==1 then
|
|
frompos={x=pos.x,y=pos.y,z=pos.z+1}
|
|
dir={x=0,y=0,z=-1}
|
|
elseif node.param2==2 then
|
|
frompos={x=pos.x+1,y=pos.y,z=pos.z}
|
|
dir={x=-1,y=0,z=0}
|
|
else
|
|
frompos={x=pos.x,y=pos.y,z=pos.z-1}
|
|
dir={x=0,y=0,z=1}
|
|
end
|
|
local fromnode=minetest.env:get_node(frompos)
|
|
local frominv
|
|
if not (minetest.registered_nodes[fromnode.name].tube and
|
|
minetest.registered_nodes[fromnode.name].tube.input_inventory) then
|
|
return
|
|
end
|
|
local frommeta=minetest.env:get_meta(frompos)
|
|
local frominvname=minetest.registered_nodes[fromnode.name].tube.input_inventory
|
|
local frominv=frommeta:get_inventory()
|
|
for _,filter in ipairs(inv:get_list("main")) do
|
|
local sname=filter:get_name()
|
|
if sname ~="" then
|
|
for spos,stack in ipairs(frominv:get_list(frominvname)) do
|
|
if stack:get_name()==sname then
|
|
item=stack:take_item()
|
|
frominv:set_stack(frominvname,spos,stack)
|
|
pos1=pos
|
|
item1=tube_item({x=pos1.x,y=pos1.y,z=pos1.z},item)
|
|
item1:get_luaentity().start_pos = {x=pos1.x,y=pos1.y,z=pos1.z}
|
|
item1:setvelocity(dir)
|
|
item1:setacceleration({x=0, y=0, z=0})
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if inv:is_empty("main") then
|
|
for spos,stack in ipairs(frominv:get_list(frominvname)) do
|
|
if stack:get_name()~="" then
|
|
item=stack:take_item()
|
|
frominv:set_stack(frominvname,spos,stack)
|
|
pos1=pos
|
|
item1=tube_item({x=pos1.x,y=pos1.y,z=pos1.z},item)
|
|
item1:get_luaentity().start_pos = {x=pos1.x,y=pos1.y,z=pos1.z}
|
|
item1:setvelocity(dir)
|
|
item1:setacceleration({x=0, y=0, z=0})
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end,
|
|
})
|
|
|
|
|
|
function tube_item(pos, item)
|
|
-- Take item in any format
|
|
local stack = ItemStack(item)
|
|
local obj = minetest.env:add_entity(pos, "item_transport:tubed_item")
|
|
obj:get_luaentity():set_item(stack:to_string())
|
|
return obj
|
|
end
|
|
|
|
minetest.register_entity(":item_transport:tubed_item", {
|
|
initial_properties = {
|
|
hp_max = 1,
|
|
physical = false,
|
|
collisionbox = {0,0,0,0,0,0},
|
|
visual = "sprite",
|
|
visual_size = {x=0.5, y=0.5},
|
|
textures = {""},
|
|
spritediv = {x=1, y=1},
|
|
initial_sprite_basepos = {x=0, y=0},
|
|
is_visible = false,
|
|
start_pos={},
|
|
route={}
|
|
},
|
|
|
|
itemstring = '',
|
|
physical_state = false,
|
|
|
|
set_item = function(self, itemstring)
|
|
self.itemstring = itemstring
|
|
local stack = ItemStack(itemstring)
|
|
local itemtable = stack:to_table()
|
|
local itemname = nil
|
|
if itemtable then
|
|
itemname = stack:to_table().name
|
|
end
|
|
local item_texture = nil
|
|
local item_type = ""
|
|
if minetest.registered_items[itemname] then
|
|
item_texture = minetest.registered_items[itemname].inventory_image
|
|
item_type = minetest.registered_items[itemname].type
|
|
end
|
|
prop = {
|
|
is_visible = true,
|
|
visual = "sprite",
|
|
textures = {"unknown_item.png"}
|
|
}
|
|
if item_texture and item_texture ~= "" then
|
|
prop.visual = "sprite"
|
|
prop.textures = {item_texture}
|
|
prop.visual_size = {x=0.3, y=0.3}
|
|
else
|
|
prop.visual = "wielditem"
|
|
prop.textures = {itemname}
|
|
prop.visual_size = {x=0.15, y=0.15}
|
|
end
|
|
self.object:set_properties(prop)
|
|
end,
|
|
|
|
get_staticdata = function(self)
|
|
|
|
return minetest.serialize({
|
|
itemstring=self.itemstring,
|
|
velocity=self.object:getvelocity(),
|
|
start_pos=self.start_pos
|
|
})
|
|
end,
|
|
|
|
on_activate = function(self, staticdata)
|
|
if staticdata=="" or staticdata==nil then return end
|
|
local item = minetest.deserialize(staticdata)
|
|
local stack = ItemStack(item.itemstring)
|
|
local itemtable = stack:to_table()
|
|
local itemname = nil
|
|
if itemtable then
|
|
itemname = stack:to_table().name
|
|
end
|
|
|
|
if itemname then
|
|
self.start_pos=item.start_pos
|
|
self.object:setvelocity(item.velocity)
|
|
self.object:setacceleration({x=0, y=0, z=0})
|
|
self.object:setpos(item.start_pos)
|
|
end
|
|
self:set_item(item.itemstring)
|
|
end,
|
|
|
|
on_step = function(self, dtime)
|
|
if self.start_pos then
|
|
local pos = self.object:getpos()
|
|
local node = minetest.env:get_node(pos)
|
|
local meta = minetest.env:get_meta(pos)
|
|
tubelike=meta:get_int("tubelike")
|
|
local stack = ItemStack(self.itemstring)
|
|
local drop_pos=nil
|
|
|
|
local velocity=self.object:getvelocity()
|
|
|
|
if velocity==nil then return end
|
|
|
|
if minetest.get_item_group(node.name,"tubedevice_receiver")==1 then
|
|
leftover = minetest.registered_nodes[node.name].tube.insert_object(pos,node,stack,velocity)
|
|
drop_pos=minetest.env:find_node_near(pos,1,"air")
|
|
if drop_pos and not leftover:is_empty() then minetest.item_drop(leftover,"",drop_pos) end
|
|
self.object:remove()
|
|
return
|
|
end
|
|
|
|
if math.abs(velocity.x)==1 then
|
|
local next_node=math.abs(pos.x-self.start_pos.x)
|
|
if next_node >= 1 then
|
|
self.start_pos.x=self.start_pos.x+velocity.x
|
|
if go_next (self.start_pos, velocity, stack)==0 then
|
|
drop_pos=minetest.env:find_node_near({x=self.start_pos.x,y=self.start_pos.y,z=self.start_pos.z+velocity.x}, 1, "air")
|
|
if drop_pos then minetest.item_drop(stack, "", drop_pos) end
|
|
self.object:remove()
|
|
end
|
|
self.object:setpos(self.start_pos)
|
|
self.object:setvelocity(velocity)
|
|
return
|
|
end
|
|
end
|
|
|
|
if math.abs(velocity.y)==1 then
|
|
local next_node=math.abs(pos.y-self.start_pos.y)
|
|
if next_node >= 1 then
|
|
self.start_pos.y=self.start_pos.y+velocity.y
|
|
if go_next (self.start_pos, velocity, stack)==0 then
|
|
drop_pos=minetest.env:find_node_near({x=self.start_pos.x+velocity.x,y=self.start_pos.y+velocity.y,z=self.start_pos.z+velocity.z}, 1, "air")
|
|
if drop_pos then minetest.item_drop(stack, "", drop_pos) end
|
|
self.object:remove()
|
|
end
|
|
self.object:setpos(self.start_pos)
|
|
self.object:setvelocity(velocity)
|
|
return
|
|
end
|
|
end
|
|
|
|
if math.abs(velocity.z)==1 then
|
|
local next_node=math.abs(pos.z-self.start_pos.z)
|
|
if next_node >= 1 then
|
|
self.start_pos.z=self.start_pos.z+velocity.z
|
|
if go_next (self.start_pos, velocity, stack)==0 then
|
|
drop_pos=minetest.env:find_node_near({x=self.start_pos.x+velocity.x,y=self.start_pos.y+velocity.y,z=self.start_pos.z+velocity.z}, 1, "air")
|
|
if drop_pos then minetest.item_drop(stack, "", drop_pos) end
|
|
self.object:remove()
|
|
end
|
|
self.object:setpos(self.start_pos)
|
|
self.object:setvelocity(velocity)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
})
|
|
|
|
|
|
function addVect(pos,vect)
|
|
return {x=pos.x+vect.x,y=pos.y+vect.y,z=pos.z+vect.z}
|
|
end
|
|
|
|
adjlist={{x=0,y=0,z=1},{x=0,y=0,z=-1},{x=0,y=1,z=0},{x=0,y=-1,z=0},{x=1,y=0,z=0},{x=-1,y=0,z=0}}
|
|
|
|
function go_next(pos,velocity,stack)
|
|
print(dump(pos))
|
|
local chests={}
|
|
local tubes={}
|
|
local cmeta=minetest.env:get_meta(pos)
|
|
local node
|
|
local meta
|
|
local tubelike
|
|
local tube_receiver
|
|
local len=1
|
|
local n
|
|
for _,vect in ipairs(adjlist) do
|
|
if vect.x~=-velocity.x or vect.y~=-velocity.y or vect.z~=-velocity.z then
|
|
npos=addVect(pos,vect)
|
|
node=minetest.env:get_node(npos)
|
|
tube_receiver=minetest.get_item_group(node.name,"tubedevice_receiver")
|
|
--tubelike=minetest.get_item_group(node.name,"tubelike")
|
|
meta=minetest.env:get_meta(npos)
|
|
tubelike=meta:get_int("tubelike")
|
|
if tube_receiver==1 then
|
|
if minetest.registered_nodes[node.name].tube.can_insert(npos,node,stack,vect) then
|
|
local i=1
|
|
repeat
|
|
if chests[i]==nil then break end
|
|
i=i+1
|
|
until false
|
|
chests[i]={}
|
|
chests[i].pos=npos
|
|
chests[i].vect=vect
|
|
end
|
|
elseif tubelike==1 then
|
|
local i=1
|
|
repeat
|
|
if tubes[i]==nil then break end
|
|
i=i+1
|
|
until false
|
|
tubes[i]={}
|
|
tubes[i].pos=npos
|
|
tubes[i].vect=vect
|
|
end
|
|
end
|
|
end
|
|
if chests[1]==nil then--no chests found
|
|
if tubes[1]==nil then
|
|
return 0
|
|
else
|
|
local i=1
|
|
repeat
|
|
if tubes[i]==nil then break end
|
|
i=i+1
|
|
until false
|
|
n=meta:get_int("tubedir")+1
|
|
if n==i then
|
|
n=1
|
|
end
|
|
meta:set_int("tubedir",n)
|
|
velocity.x=tubes[n].vect.x
|
|
velocity.y=tubes[n].vect.y
|
|
velocity.z=tubes[n].vect.z
|
|
end
|
|
else
|
|
local i=1
|
|
repeat
|
|
if chests[i]==nil then break end
|
|
i=i+1
|
|
until false
|
|
n=meta:get_int("tubedir")+1
|
|
if n==i then
|
|
n=1
|
|
end
|
|
velocity.x=chests[n].vect.x
|
|
velocity.y=chests[n].vect.y
|
|
velocity.z=chests[n].vect.z
|
|
end
|
|
return 1
|
|
end
|