From 109729cfb27efd816238f094a738a8ac23e83dda Mon Sep 17 00:00:00 2001 From: Vanessa Ezekowitz Date: Sun, 13 Jan 2013 21:45:03 -0500 Subject: [PATCH] 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. --- changelog.txt | 51 +++++- compat.lua | 166 +++++++++++++++++++ init.lua | 4 +- item_transport.lua | 331 +++++++++++++++++++++++++++++++++++++ textures/filter_input.png | Bin 0 -> 169 bytes textures/filter_output.png | Bin 0 -> 174 bytes textures/filter_side.png | Bin 0 -> 215 bytes textures/filter_top.png | Bin 0 -> 213 bytes 8 files changed, 549 insertions(+), 3 deletions(-) create mode 100644 compat.lua create mode 100644 item_transport.lua create mode 100644 textures/filter_input.png create mode 100644 textures/filter_output.png create mode 100644 textures/filter_side.png create mode 100644 textures/filter_top.png diff --git a/changelog.txt b/changelog.txt index 9e51430..251df29 100644 --- a/changelog.txt +++ b/changelog.txt @@ -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 index 0000000..31e59a2 --- /dev/null +++ b/compat.lua @@ -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, +}) diff --git a/init.lua b/init.lua index 977c4a9..142eb97 100644 --- 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 index 0000000..aad3d85 --- /dev/null +++ b/item_transport.lua @@ -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 index 0000000000000000000000000000000000000000..0788b0cba25d414f9150e40c47166cff5031e178 GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#E+dZ+gNFUpH+z9Xk|nMYCC>S|xv6<249-QVi6yBi3gww484B*6z5(HleBwYw z%APKcAsXkC|NQ@N&+OTt!u$XK|MVmU!JaIMs}8!nJxkQ`8Hzo51U*9@Is=t6c)I$z JtaD0e0svz_Eam_J literal 0 HcmV?d00001 diff --git a/textures/filter_output.png b/textures/filter_output.png new file mode 100644 index 0000000000000000000000000000000000000000..791dbde980b0ca0c9b9ad22c8a3965824defd24d GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#E+dZ+gLvoWgAG6-$r9Iy66gHf+|;}h2Ir#G#FEq$h4Rdj33y!}BETk^GFfhnRaY{Q`ZMg;1 O!{F)a=d#Wzp$PyAnJu&c literal 0 HcmV?d00001 diff --git a/textures/filter_side.png b/textures/filter_side.png new file mode 100644 index 0000000000000000000000000000000000000000..6dd757e069cae44c94107c8cedcec984dcfb9229 GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#E+dbimDwZHjsJi`k|nMYCC>S|xv6<249-QVi6yBi3gww484B*6z5(HleBwYw zfu1goAsXkWPV(epFyLVJ{rErLuYa48)Lu^G9ZgGeA9ctuFr+=>`n7D`;<*8fwq95e zDREK2rDXdxe}$Fv^|d;p@-nZyl9XC2z3a*|T~*%O-}i|)X-UQ|Z+HkaoWax8&t;uc GLK6TI4MTST literal 0 HcmV?d00001 diff --git a/textures/filter_top.png b/textures/filter_top.png new file mode 100644 index 0000000000000000000000000000000000000000..3483ddff3e09da2753f37c8b2e3b5db1530c40cb GIT binary patch literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#E+dbixxv04S#3Ze$r9Iy66gHf+|;}h2Ir#G#FEq$h4Rdj3*>iDk`^*xiL9Rdcw4W%W&(@?w31d4R{m% zeeN%|-nQ!MwhbXqZ)#r1TX)Bb(OGzEw6(yu({HQgr!JS%zhD3G4bW%?Pgg&ebxsLQ E04#k)<^TWy literal 0 HcmV?d00001