From 534fb41fb4728d82f2c7b3d6950b168186a31def Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Wed, 22 Aug 2018 16:41:00 +0300 Subject: [PATCH] Rewrite fluid transfer to use Node IO --- elepower_fapi/buffer.lua | 152 +++++++++++++++++++++++++++++++++++++ elepower_fapi/depends.txt | 1 + elepower_fapi/mod.conf | 1 + elepower_fapi/transfer.lua | 65 ++++++++++------ elepower_papi/depends.txt | 2 + elepower_papi/machine.lua | 48 ++++++++++++ elepower_papi/mod.conf | 3 +- 7 files changed, 248 insertions(+), 24 deletions(-) create mode 100644 elepower_fapi/buffer.lua diff --git a/elepower_fapi/buffer.lua b/elepower_fapi/buffer.lua new file mode 100644 index 0000000..0e640f7 --- /dev/null +++ b/elepower_fapi/buffer.lua @@ -0,0 +1,152 @@ +-- Fluid buffer support functions. + +local function node_data(pos) + local node = minetest.get_node(pos) + local nodedef = minetest.registered_nodes[node.name] + return node, nodedef +end + +function elefluid.get_node_buffers(pos) + local node, nodedef = node_data(pos) + if not nodedef['fluid_buffers'] then + return nil + end + + return nodedef['fluid_buffers'] +end + +function elefluid.get_buffer_data(pos, buffer) + local node, nodedef = node_data(pos) + local buffers = elefluid.get_node_buffers(pos) + + if not buffers[buffer] then + return nil + end + + local meta = minetest.get_meta(pos) + local fluid = meta:get_string(buffer .. "_fluid") + local amount = meta:get_int(buffer .. "_fluid_storage") + local capacity = buffers[buffer].capacity + local accepts = buffers[buffer].accepts + local drainable = buffers[buffer].drainable + + if drainable == nil then + drainable = true + end + + return { + fluid = fluid, + amount = amount, + accepts = accepts, + capacity = capacity, + drainable = drainable, + } +end + +function elefluid.buffer_accepts_fluid(pos, buffer, fluid) + local bfdata = elefluid.get_buffer_data(pos, buffer) + if not bfdata then return false end + + if bfdata.fluid ~= "" and bfdata.fluid ~= fluid then + return false + end + + if bfdata.accepts == true or bfdata.accepts == fluid then + return true + end + + if type(bfdata.accepts) ~= "table" then + bfdata.accepts = { bfdata.accepts } + end + + for _,pf in pairs(bfdata.accepts) do + if pf == fluid then + return true + elseif pf:match("^group") and ele.helpers.get_item_group(fluid, pf:gsub("group:", "")) then + return true + end + end + + return false +end + +function elefluid.can_insert_into_buffer(pos, buffer, fluid, count) + local bfdata = elefluid.get_buffer_data(pos, buffer) + if not bfdata then return 0 end + if not elefluid.buffer_accepts_fluid(pos, buffer, fluid) then return 0 end + + local can_put = 0 + if bfdata.amount + count > bfdata.capacity then + can_put = bfdata.capacity - bfdata.amount + else + can_put = count + end + + return can_put +end + +function elefluid.insert_into_buffer(pos, buffer, fluid, count) + local bfdata = elefluid.get_buffer_data(pos, buffer) + if not bfdata then return nil end + if bfdata.fluid ~= fluid and bfdata.fluid ~= "" then return nil end + + local can_put = elefluid.can_insert_into_buffer(pos, buffer, fluid, count) + + if can_put == 0 then return count end + + local meta = minetest.get_meta(pos) + meta:set_int(buffer .. "_fluid_storage", bfdata.amount + can_put) + meta:set_string(buffer .. "_fluid", fluid) + + return 0 +end + +function elefluid.can_take_from_buffer(pos, buffer, count) + local bfdata = elefluid.get_buffer_data(pos, buffer) + if not bfdata or not bfdata.drainable then return 0 end + + local amount = bfdata.amount + local take_count = 0 + + if amount < count then + take_count = amount + else + take_count = count + end + + return take_count +end + +function elefluid.take_from_buffer(pos, buffer, count) + local bfdata = elefluid.get_buffer_data(pos, buffer) + if not bfdata then return nil end + + local fluid = bfdata.fluid + local amount = bfdata.amount + + local take_count = elefluid.can_take_from_buffer(pos, buffer, count) + + local new_storage = amount - take_count + if new_storage == 0 then + fluid = "" + end + + local meta = minetest.get_meta(pos) + meta:set_int(buffer .. "_fluid_storage", new_storage) + meta:set_string(buffer .. "_fluid", fluid) + + return bfdata.fluid, take_count +end + +function elefluid.buffer_to_string(buffer) + if not buffer then return "" end + local amount = elefluid.comma_value(buffer.amount) + local capacity = elefluid.comma_value(buffer.capacity) + local description = "Empty" + + if buffer.fluid ~= "" then + description = elefluid.cleanse_node_description(buffer.fluid) + end + + return ("%s (%s / %s %s)"):format(description, amount, capacity, elefluid.unit) +end diff --git a/elepower_fapi/depends.txt b/elepower_fapi/depends.txt index fe2c979..de13e3b 100644 --- a/elepower_fapi/depends.txt +++ b/elepower_fapi/depends.txt @@ -1,2 +1,3 @@ elepower_papi fluid_lib +node_io? diff --git a/elepower_fapi/mod.conf b/elepower_fapi/mod.conf index ee810ae..82d844a 100644 --- a/elepower_fapi/mod.conf +++ b/elepower_fapi/mod.conf @@ -1,3 +1,4 @@ name = elepower_fapi description = Elepower Fluid Transfer API depends = elepower_papi,fluid_lib +optional_depends = node_io diff --git a/elepower_fapi/transfer.lua b/elepower_fapi/transfer.lua index 80be996..b695038 100644 --- a/elepower_fapi/transfer.lua +++ b/elepower_fapi/transfer.lua @@ -64,9 +64,10 @@ local function fluid_targets(p_pos, pos) local all_nodes = {} local node = minetest.get_node(pos) + local ndef = minetest.registered_nodes[node.name] if node and ele.helpers.get_item_group(node.name, "elefluid_transport") then add_duct_node(all_nodes, pos, pnodeid, queue) - elseif node and ele.helpers.get_item_group(node.name, "fluid_container") then + elseif node and ndef['node_io_put_liquid'] and ndef['node_io_room_for_liquid'] then queue = {p_pos} end @@ -98,8 +99,9 @@ function elefluid.transfer_timer_tick(pos, elapsed) -- Only allow the node directly behind to be a start of a network local tpos = vector.add(minetest.facedir_to_dir(node.param2), pos) local tname = minetest.get_node(tpos).name + local ndef = minetest.registered_nodes[tname] if not ele.helpers.get_item_group(tname, "elefluid_transport") and - not ele.helpers.get_item_group(tname, "fluid_container") then + not ndef['node_io_put_liquid'] and ndef['node_io_room_for_liquid'] then minetest.forceload_free_block(pos) return end @@ -121,15 +123,24 @@ function elefluid.transfer_timer_tick(pos, elapsed) return true end + local srcdef = minetest.registered_nodes[srcnode.name] + -- Make sure source node is a registered fluid container - if not ele.helpers.get_item_group(srcnode.name, "fluid_container") then - return true + if not srcdef['node_io_take_liquid'] or not srcdef['node_io_can_take_liquid'] then + return false end + local c = srcdef.node_io_can_take_liquid(srcpos, srcnode, "") + if not c then return false end + local srcmeta = minetest.get_meta(srcpos) local srcdef = minetest.registered_nodes[srcnode.name] - local buffers = fluid_lib.get_node_buffers(srcpos) - if not buffers then return true end + local fl_size = srcdef.node_io_get_liquid_size(srcpos, srcnode, "") + local buffers = {} + for i = 1, fl_size do + buffers[i] = srcdef.node_io_get_liquid_name(srcpos, srcnode, "", i) + end + if not #buffers then return true end -- Limit the amount of fluid pumped per cycle local pcapability = ele.helpers.get_node_property(meta, pos, "fluid_pump_capacity") @@ -139,29 +150,37 @@ function elefluid.transfer_timer_tick(pos, elapsed) for _,pos in pairs(targets) do if not vector.equals(pos, srcpos) then if pumped >= pcapability then break end - local pp = fluid_lib.get_node_buffers(pos) + local destnode = minetest.get_node(pos) + local destdef = minetest.registered_nodes[destnode.name] + local pp = nil + + if destdef['node_io_can_put_liquid'] then + if destdef.node_io_can_put_liquid(pos, destnode, "") then + pp = {} + local fl_size = destdef.node_io_get_liquid_size(pos, destnode, "") + for i = 1, fl_size do + pp[i] = destdef.node_io_get_liquid_name(pos, destnode, "", i) + end + if not #pp then pp = nil end + end + end local changed = false if pp ~= nil then - for name in pairs(pp) do - for bname in pairs(buffers) do + for bindex,bfluid in pairs(pp) do + for aindex,afluid in pairs(buffers) do if pumped >= pcapability then break end - local buffer_data = fluid_lib.get_buffer_data(srcpos, bname) - local target_data = fluid_lib.get_buffer_data(pos, name) - - if (target_data.fluid == buffer_data.fluid or target_data.fluid == "") and - buffer_data.fluid ~= "" and buffer_data.amount > 0 and - (buffer_data.drainable == nil or buffer_data.drainable == true) and - fluid_lib.buffer_accepts_fluid(pos, name, buffer_data.fluid) then - - if fluid_lib.can_insert_into_buffer(pos, name, buffer_data.fluid, pcapability) > 0 then - local res_f, count = fluid_lib.take_from_buffer(srcpos, bname, pcapability) - if count > 0 then - fluid_lib.insert_into_buffer(pos, name, res_f, count) - pumped = pumped + count - changed = true + if (afluid == bfluid or bfluid == "") then + local defi = srcdef.node_io_take_liquid(srcpos, srcnode, "", nil, afluid, pcapability) + if defi.millibuckets > 0 then + local idef = destdef.node_io_room_for_liquid(pos, destnode, "", afluid, defi.millibuckets) + if idef > 0 then + local lo = destdef.node_io_put_liquid(pos, destnode, "", nil, afluid, idef) + idef = idef - lo end + pumped = pumped + idef + changed = true end end end diff --git a/elepower_papi/depends.txt b/elepower_papi/depends.txt index daf4df0..58a114b 100644 --- a/elepower_papi/depends.txt +++ b/elepower_papi/depends.txt @@ -1,3 +1,5 @@ default pipeworks? tubelib? +mesecons? +node_io? diff --git a/elepower_papi/machine.lua b/elepower_papi/machine.lua index b9a58a3..2af669d 100644 --- a/elepower_papi/machine.lua +++ b/elepower_papi/machine.lua @@ -311,6 +311,46 @@ function ele.register_base_device(nodename, nodedef) end end + -- Node IO Support + if minetest.get_modpath("node_io") and (nodedef.groups["tubedevice"] or nodedef.groups["tube"]) then + nodedef.node_io_can_put_item = function(pos, node, side) return true end + nodedef.node_io_room_for_item = function(pos, node, side, itemstack, count) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local istack_real = ItemStack(itemstack) + istack_real:set_count(count) + return inv:room_for_item("src", istack_real) + end + nodedef.node_io_put_item = function(pos, node, side, putter, itemstack) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return inv:add_item("src", itemstack) + end + nodedef.node_io_can_take_item = function(pos, node, side) return true end + nodedef.node_io_get_item_size = function(pos, node, side) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return inv:get_size("dst") + end + nodedef.node_io_get_item_name = function(pos, node, side, index) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return inv:get_stack("dst", index):get_name() + end + nodedef.node_io_get_item_stack = function(pos, node, side, index) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return inv:get_stack("dst", index) + end + nodedef.node_io_take_item = function(pos, node, side, taker, want_item, want_count) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local stack = ItemStack(want_item) + stack:set_count(want_count) + return inv:take_item("dst", stack) + end + end + -- Mesecons support if mc then nodedef["mesecons"] = mesecons_def @@ -376,6 +416,14 @@ function ele.register_base_device(nodename, nodedef) tubelib.register_node(nodename, extras, tubelib_tube) end + + -- nodeio fluids + if nodedef.groups and nodedef.groups['fluid_container'] then + fluid_lib.register_node(nodename) + if active_name then + fluid_lib.register_node(active_name) + end + end end function ele.register_machine(nodename, nodedef) diff --git a/elepower_papi/mod.conf b/elepower_papi/mod.conf index b239f82..c67ea9c 100644 --- a/elepower_papi/mod.conf +++ b/elepower_papi/mod.conf @@ -1,3 +1,4 @@ name = elepower_papi description = Elepower Power Network API -optional_depends = default,pipeworks,tubelib,mesecons +depends = default +optional_depends = pipeworks,tubelib,mesecons,node_io