Added Nore's item transport mod and integrated it into pipeworks
authorVanessa Ezekowitz <vanessaezekowitz@gmail.com>
Mon, 14 Jan 2013 02:45:03 +0000 (21:45 -0500)
committerVanessa Ezekowitz <vanessaezekowitz@gmail.com>
Mon, 14 Jan 2013 02:45:03 +0000 (21:45 -0500)
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.

changelog.txt
compat.lua [new file with mode: 0644]
init.lua
item_transport.lua [new file with mode: 0644]
textures/filter_input.png [new file with mode: 0644]
textures/filter_output.png [new file with mode: 0644]
textures/filter_side.png [new file with mode: 0644]
textures/filter_top.png [new file with mode: 0644]

index 9e51430a24ac6033246fc789705985dfaa1ed3a6..251df29b55e160dd24b88a898f541f22d8707cf6 100644 (file)
@@ -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 
diff --git a/compat.lua b/compat.lua
new file mode 100644 (file)
index 0000000..31e59a2
--- /dev/null
@@ -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,
+})
index 977c4a94a7b7a2dfa0241160ac414ddfba252847..142eb975c21c978da02fd33aa408dce975ff7bbf 100644 (file)
--- a/init.lua
+++ b/init.lua
@@ -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!")
diff --git a/item_transport.lua b/item_transport.lua
new file mode 100644 (file)
index 0000000..aad3d85
--- /dev/null
@@ -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
diff --git a/textures/filter_input.png b/textures/filter_input.png
new file mode 100644 (file)
index 0000000..0788b0c
Binary files /dev/null and b/textures/filter_input.png differ
diff --git a/textures/filter_output.png b/textures/filter_output.png
new file mode 100644 (file)
index 0000000..791dbde
Binary files /dev/null and b/textures/filter_output.png differ
diff --git a/textures/filter_side.png b/textures/filter_side.png
new file mode 100644 (file)
index 0000000..6dd757e
Binary files /dev/null and b/textures/filter_side.png differ
diff --git a/textures/filter_top.png b/textures/filter_top.png
new file mode 100644 (file)
index 0000000..3483ddf
Binary files /dev/null and b/textures/filter_top.png differ