Added Nore's item transport mod and integrated it into pipeworks

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.
This commit is contained in:
Vanessa Ezekowitz 2013-01-13 21:45:03 -05:00
parent 14102d7c3a
commit 109729cfb2
8 changed files with 549 additions and 3 deletions

@ -1,8 +1,55 @@
Changelog
---------
2012-08-24: Added square-ish pneumatic tubes, with their own autoplace code
(they do not connect to the steel pipes or their related devices).
2013-01-13: Tubes can transport items now! Namely, I added Novatux/Nore's item
transport mod as a default part of this mod, to make tubes do something useful!
Thanks to Nore and RealBadAngel for the code contributions!
2013-01-05: made storage tanks connect from top/bottom, made storage tank and
pipe textures use the ^ combine operator so they can show the actual liquid
going through the pipes/tanks.
2013-01-04 (a bit later): Made pipes able to carry water! It was just a minor
logic error resulting from moving the water flowing code into it's own file
when I originally imported it. Many thanks to Mauvebic for writing it!
2013-01-04: First stage of integrating Mauvebic's water flowing code. This is
experimental and doesn't move water yet - but at least it doesn't break
anything :-)
2013-01-01: Various minor tweaks to textures, facedir settings, some other
stuff. Changed crafting recipes to account for revamped pumps, valves, etc.
Now requires the moreores mod and most recent git (for mese crystal fragments)
to craft a pump. Added a "sealed" entry/exit panel (really just a horizontal
pipe with a metal panel overlayed into the middle). Also, tweaked pipes to
always drop the empty ones. Revamped pumps so that now they should sit in/on
liquid and be connected only from the top, relegated grates to decorational-
only, added outlet spigot. Got rid of a few obsolete textures. Got rid of
that whole _x and _z naming thing - now all directional devices (pumps, valves,
spigots, tanks) use facedir. Valves, spigots no longer auto-rotate to find
nearby pipes.
2012-09-17: Added test object for pneumatic tube autorouting code, made tubes
connect to it and any object that bears groups={tubedevice=1} (connects to any
side)
2012-09-05: All recipes doubled except for junglegrass -> plastic sheet (since
that is derived from home decor)
2012-09-02: Fixed plastic sheeting recipe. Added crafting recipes for various
objects, with options: If homedecor is installed, use the plastic sheeting
therein. If not, we define it manually. If the Technic mod is installed,
don't define any recipes at all. Also removed the extra "loaded!" messages and
tweaked the default pipe alias to point to something that is actually visible
:-)
2012-09-01: flattened wielded pipe segment.
2012-08-24: Added square-ish pneumatic tubes with their own autoplace code
(does not connect to steel pipes or pipe-oriented devices), then revised their
textures shortly after. Fixed a recursion bug that sometimes caused a stack
overflow. Old pipes were overriding the pipeworks:pipe defintion that belongs
with the new pipes.
2012-08-22: Added outlet grate, made it participate in autoplace algorithm.
Extended storage tank to show fill level in 10% steps (0% to 100%). Added

166
compat.lua Normal file

@ -0,0 +1,166 @@
default.furnace_inactive_formspec =
"size[8,9]"..
"image[2,2;1,1;default_furnace_fire_bg.png]"..
"list[current_name;fuel;2,3;1,1;]"..
"list[current_name;src;2,1;1,1;]"..
"list[current_name;dst;5,1;2,2;]"..
"list[current_player;main;0,5;8,4;]"
minetest.register_node(":default:furnace", {
description = "Furnace",
tiles = {"default_furnace_top.png", "default_furnace_bottom.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_side.png", "default_furnace_front.png"},
paramtype2 = "facedir",
groups = {cracky=2,tubedevice=1,tubedevice_receiver=1},
tube={insert_object=function(pos,node,stack,direction)
local meta=minetest.env:get_meta(pos)
local inv=meta:get_inventory()
if direction.y==1 then
return inv:add_item("fuel",stack)
elseif direction.y==-1 then
return inv:add_item("src",stack)
else
return stack
end
end,
can_insert=function(pos,node,stack,direction)
local meta=minetest.env:get_meta(pos)
local inv=meta:get_inventory()
if direction.y==1 then
return inv:room_for_item("fuel",stack)
elseif direction.y==-1 then
return inv:room_for_item("src",stack)
else
return 0
end
end,
input_inventory="dst"},
legacy_facedir_simple = true,
sounds = default.node_sound_stone_defaults(),
on_construct = function(pos)
local meta = minetest.env:get_meta(pos)
meta:set_string("formspec", default.furnace_inactive_formspec)
meta:set_string("infotext", "Furnace")
local inv = meta:get_inventory()
inv:set_size("fuel", 1)
inv:set_size("src", 1)
inv:set_size("dst", 4)
end,
can_dig = function(pos,player)
local meta = minetest.env:get_meta(pos);
local inv = meta:get_inventory()
if not inv:is_empty("fuel") then
return false
elseif not inv:is_empty("dst") then
return false
elseif not inv:is_empty("src") then
return false
end
return true
end,
})
minetest.register_node(":default:furnace_active", {
description = "Furnace",
tiles = {"default_furnace_top.png", "default_furnace_bottom.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_side.png", "default_furnace_front_active.png"},
paramtype2 = "facedir",
light_source = 8,
drop = "default:furnace",
groups = {cracky=2, not_in_creative_inventory=1,tubedevice=1,tubedevice_receiver=1},
tube={insert_object=function(pos,node,stack,direction)
local meta=minetest.env:get_meta(pos)
local inv=meta:get_inventory()
if direction.y==1 then
return inv:add_item("fuel",stack)
elseif direction.y==-1 then
return inv:add_item("src",stack)
else
return stack
end
end,
can_insert=function(pos,node,stack,direction)
local meta=minetest.env:get_meta(pos)
local inv=meta:get_inventory()
if direction.y==1 then
return inv:room_for_item("fuel",stack)
elseif direction.y==-1 then
return inv:room_for_item("src",stack)
else
return 0
end
end,
input_inventory="dst"},
legacy_facedir_simple = true,
sounds = default.node_sound_stone_defaults(),
on_construct = function(pos)
local meta = minetest.env:get_meta(pos)
meta:set_string("formspec", default.furnace_inactive_formspec)
meta:set_string("infotext", "Furnace");
local inv = meta:get_inventory()
inv:set_size("fuel", 1)
inv:set_size("src", 1)
inv:set_size("dst", 4)
end,
can_dig = function(pos,player)
local meta = minetest.env:get_meta(pos);
local inv = meta:get_inventory()
if not inv:is_empty("fuel") then
return false
elseif not inv:is_empty("dst") then
return false
elseif not inv:is_empty("src") then
return false
end
return true
end,
})
minetest.register_node(":default:chest", {
description = "Chest",
tiles = {"default_chest_top.png", "default_chest_top.png", "default_chest_side.png",
"default_chest_side.png", "default_chest_side.png", "default_chest_front.png"},
paramtype2 = "facedir",
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,tubedevice=1,tubedevice_receiver=1},
tube={insert_object=function(pos,node,stack,direction)
local meta=minetest.env:get_meta(pos)
local inv=meta:get_inventory()
return inv:add_item("main",stack)
end,
can_insert=function(pos,node,stack,direction)
local meta=minetest.env:get_meta(pos)
local inv=meta:get_inventory()
return inv:room_for_item("main",stack)
end,
input_inventory="main"},
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",
"size[8,9]"..
"list[current_name;main;0,0;8,4;]"..
"list[current_player;main;0,5;8,4;]")
meta:set_string("infotext", "Chest")
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,
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
minetest.log("action", player:get_player_name()..
" moves stuff in chest at "..minetest.pos_to_string(pos))
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
minetest.log("action", player:get_player_name()..
" moves stuff to chest at "..minetest.pos_to_string(pos))
end,
on_metadata_inventory_take = function(pos, listname, index, stack, player)
minetest.log("action", player:get_player_name()..
" takes stuff from chest at "..minetest.pos_to_string(pos))
end,
})

@ -13,7 +13,7 @@
--
minetest.register_alias("pipeworks:pipe", "pipeworks:pipe_110000_empty")
local DEBUG = true
local DEBUG = false
pipeworks_liquid_texture = "default_water.png"
@ -326,5 +326,7 @@ dofile(minetest.get_modpath("pipeworks").."/devices.lua")
dofile(minetest.get_modpath("pipeworks").."/autoplace.lua")
dofile(minetest.get_modpath("pipeworks").."/crafts.lua")
dofile(minetest.get_modpath("pipeworks").."/flowing_logic.lua")
dofile(minetest.get_modpath("pipeworks").."/compat.lua")
dofile(minetest.get_modpath("pipeworks").."/item_transport.lua")
print("Pipeworks loaded!")

331
item_transport.lua Normal file

@ -0,0 +1,331 @@
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

BIN
textures/filter_input.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

BIN
textures/filter_output.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

BIN
textures/filter_side.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

BIN
textures/filter_top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B