From 1df1dffebe8f61a637eb438d433574941974fbea Mon Sep 17 00:00:00 2001 From: Shad MOrdre Date: Fri, 30 Aug 2019 15:57:55 -0700 Subject: [PATCH] Add files via upload --- init.lua | 113 +++++------ lib_materials_fluid_lib.lua | 47 +++++ lib_materials_fluid_lib_buffer.lua | 152 +++++++++++++++ lib_materials_fluid_lib_nodeio.lua | 100 ++++++++++ lib_materials_nodeio.lua | 299 +++++++++++++++++++++++++++++ lib_materials_nodeio_support.lua | 58 ++++++ 6 files changed, 713 insertions(+), 56 deletions(-) create mode 100644 lib_materials_fluid_lib.lua create mode 100644 lib_materials_fluid_lib_buffer.lua create mode 100644 lib_materials_fluid_lib_nodeio.lua create mode 100644 lib_materials_nodeio.lua create mode 100644 lib_materials_nodeio_support.lua diff --git a/init.lua b/init.lua index b23308d..859475f 100644 --- a/init.lua +++ b/init.lua @@ -89,68 +89,69 @@ end minetest.log(S("[MOD] lib_materials: Loading...")) -lib_materials.read_csv = dofile(lib_materials.path .. "/csv.lua") + lib_materials.read_csv = dofile(lib_materials.path .. "/csv.lua") -dofile(lib_materials.path.."/lib_materials_sound_defaults.lua") + dofile(lib_materials.path.."/lib_materials_sound_defaults.lua") - --dofile(lib_materials.path.."/type_fluids.lua") - --dofile(lib_materials.path.."/type_stone.lua") + dofile(lib_materials.path.."/lib_materials_nodeio.lua") + dofile(lib_materials.path.."/lib_materials_fluid_lib.lua") --dofile(lib_materials.path.."/lib_materials_toolcap_modifier.lua") --dofile(lib_materials.path.."/lib_materials_tool_ranks.lua") -dofile(lib_materials.path.."/lib_materials_node_registration.lua") + dofile(lib_materials.path.."/lib_materials_node_registration.lua") - --game.lib.node.register_csv("|", lib_materials.path.."/nodes.csv") + --game.lib.node.register_csv("|", lib_materials.path.."/nodes.csv") - --dofile(lib_materials.path.."/type_stone_deco.lua") - --dofile(lib_materials.path.."/type_dirt.lua") - --dofile(lib_materials.path.."/type_sand.lua") - --dofile(lib_materials.path.."/type_ice_snow.lua") - --dofile(lib_materials.path.."/type_ore.lua") - --dofile(lib_materials.path.."/type_glass.lua") + --dofile(lib_materials.path.."/type_stone_deco.lua") + --dofile(lib_materials.path.."/type_dirt.lua") + --dofile(lib_materials.path.."/type_sand.lua") + --dofile(lib_materials.path.."/type_ice_snow.lua") + --dofile(lib_materials.path.."/type_ore.lua") + --dofile(lib_materials.path.."/type_glass.lua") -dofile(lib_materials.path.."/lib_materials_liquid_containers.lua") + dofile(lib_materials.path.."/lib_materials_liquid_containers.lua") -dofile(lib_materials.path.."/lib_materials_vessels.lua") + dofile(lib_materials.path.."/lib_materials_vessels.lua") -dofile(lib_materials.path.."/lib_materials_water_dynamics.lua") -dofile(lib_materials.path.."/lib_materials_fire.lua") + dofile(lib_materials.path.."/lib_materials_water_dynamics.lua") -dofile(lib_materials.path.."/lib_materials_craftitems.lua") ---dofile(lib_materials.path.."/lib_materials_tools.lua") + dofile(lib_materials.path.."/lib_materials_fire.lua") ---dofile(lib_materials.path.."/lib_materials_craftfire.lua") + dofile(lib_materials.path.."/lib_materials_craftitems.lua") -dofile(lib_materials.path.."/lib_materials_craftrecipes.lua") + --dofile(lib_materials.path.."/lib_materials_tools.lua") + + --dofile(lib_materials.path.."/lib_materials_craftfire.lua") + + dofile(lib_materials.path.."/lib_materials_craftrecipes.lua") -dofile(lib_materials.path.."/lib_materials_schematics.lua") + dofile(lib_materials.path.."/lib_materials_schematics.lua") + dofile(lib_materials.path.."/lib_materials_biomes.lua") -dofile(lib_materials.path.."/lib_materials_biomes.lua") + --game.lib.biomes.register_csv("|", lib_materials.path.."/biomes.csv") + --dofile(lib_materials.path.."/lib_materials_ore_defs_ORIG.lua") + + dofile(lib_materials.path.."/lib_materials_ore_defs.lua") + + dofile(lib_materials.path.."/lib_materials_ecosystems.lua") + + dofile(lib_materials.path.."/lib_materials_lakes.lua") + + ----dofile(lib_materials.path.."/lib_materials_ore_defs_ORIG.lua") + ----dofile(lib_materials.path.."/lib_materials_ecosystems.lua") + --dofile(lib_materials.path.."/lvm_voxel.lua") + --dofile(lib_materials.path.."/burli_voxel.lua") + --dofile(lib_materials.path.."/lib_materials_lakes.lua") + + dofile(lib_materials.path.."/lib_materials_utils.lua") - --game.lib.biomes.register_csv("|", lib_materials.path.."/biomes.csv") - --dofile(lib_materials.path.."/lib_materials_ore_defs_ORIG.lua") - -dofile(lib_materials.path.."/lib_materials_ore_defs.lua") - -dofile(lib_materials.path.."/lib_materials_ecosystems.lua") - -dofile(lib_materials.path.."/lib_materials_lakes.lua") - - ----dofile(lib_materials.path.."/lib_materials_ore_defs_ORIG.lua") - ----dofile(lib_materials.path.."/lib_materials_ecosystems.lua") - --dofile(lib_materials.path.."/lvm_voxel.lua") - --dofile(lib_materials.path.."/burli_voxel.lua") - --dofile(lib_materials.path.."/lib_materials_lakes.lua") - -dofile(lib_materials.path.."/lib_materials_utils.lua") + dofile(lib_materials.path.."/lib_materials_rivers.lua") -dofile(lib_materials.path.."/lib_materials_rivers.lua") + dofile(lib_materials.path.."/lib_materials_abms.lua") -dofile(lib_materials.path.."/lib_materials_abms.lua") - -dofile(lib_materials.path.."/lib_materials_chatcommands.lua") + dofile(lib_materials.path.."/lib_materials_chatcommands.lua") @@ -159,26 +160,26 @@ dofile(lib_materials.path.."/lib_materials_chatcommands.lua") -minetest.register_alias("mapgen_stone", "lib_materials:stone") -minetest.register_alias("mapgen_water_source", "lib_materials:liquid_water_source") -minetest.register_alias("mapgen_river_water_source", "lib_materials:liquid_water_river_source") -minetest.register_alias("mapgen_lava_source", "lib_materials:liquid_lava_source") + minetest.register_alias("mapgen_stone", "lib_materials:stone") + minetest.register_alias("mapgen_water_source", "lib_materials:liquid_water_source") + minetest.register_alias("mapgen_river_water_source", "lib_materials:liquid_water_river_source") + minetest.register_alias("mapgen_lava_source", "lib_materials:liquid_lava_source") -default.node_sound_stone_defaults = lib_materials.node_sound_stone_defaults -default.node_sound_dirt_defaults = lib_materials.node_sound_dirt_defaults -default.node_sound_gravel_defaults = lib_materials.node_sound_gravel_defaults -default.node_sound_sand_defaults = lib_materials.node_sound_sand_defaults + default.node_sound_stone_defaults = lib_materials.node_sound_stone_defaults + default.node_sound_dirt_defaults = lib_materials.node_sound_dirt_defaults + default.node_sound_gravel_defaults = lib_materials.node_sound_gravel_defaults + default.node_sound_sand_defaults = lib_materials.node_sound_sand_defaults -default.node_sound_snow_defaults = lib_materials.node_sound_snow_defaults + default.node_sound_snow_defaults = lib_materials.node_sound_snow_defaults -default.node_sound_leaves_defaults = lib_materials.node_sound_leaves_defaults -default.node_sound_wood_defaults = lib_materials.node_sound_wood_defaults + default.node_sound_leaves_defaults = lib_materials.node_sound_leaves_defaults + default.node_sound_wood_defaults = lib_materials.node_sound_wood_defaults -default.node_sound_metal_defaults = lib_materials.node_sound_metal_defaults -default.node_sound_glass_defaults = lib_materials.node_sound_glass_defaults -default.node_sound_water_defaults = lib_materials.node_sound_water_defaults + default.node_sound_metal_defaults = lib_materials.node_sound_metal_defaults + default.node_sound_glass_defaults = lib_materials.node_sound_glass_defaults + default.node_sound_water_defaults = lib_materials.node_sound_water_defaults diff --git a/lib_materials_fluid_lib.lua b/lib_materials_fluid_lib.lua new file mode 100644 index 0000000..78ad579 --- /dev/null +++ b/lib_materials_fluid_lib.lua @@ -0,0 +1,47 @@ +-- Universal Fluid API implementation +-- Copyright (c) 2018 Evert "Diamond" Prants + +local modpath = minetest.get_modpath(minetest.get_current_modname()) + +fluid_lib = rawget(_G, "fluid_lib") or {} +fluid_lib.modpath = modpath + +fluid_lib.unit = "mB" +fluid_lib.unit_description = "milli-bucket" + +fluid_lib.fluid_name_cache = {} +fluid_lib.fluid_description_cache = {} + +function fluid_lib.cleanse_node_name(node) + if fluid_lib.fluid_name_cache[node] then + return fluid_lib.fluid_name_cache[node] + end + + local no_mod = node:gsub("^([%w_]+:)", "") + local no_source = no_mod:gsub("(_?source_?)", "") + + fluid_lib.fluid_name_cache[node] = no_source + return no_source +end + +function fluid_lib.cleanse_node_description(node) + if fluid_lib.fluid_description_cache[node] then + return fluid_lib.fluid_description_cache[node] + end + + local ndef = minetest.registered_nodes[node] + if not ndef then return nil end + + local no_source = ndef.description:gsub("(%s?Source%s?)", "") + + fluid_lib.fluid_description_cache[node] = no_source + return no_source +end + +function fluid_lib.comma_value(n) -- credit http://richard.warburton.it + local left,num,right = string.match(n,'^([^%d]*%d)(%d*)(.-)$') + return left..(num:reverse():gsub('(%d%d%d)','%1,'):reverse())..right +end + +dofile(modpath.."/lib_materials_fluid_lib_buffer.lua") +dofile(modpath.."/lib_materials_fluid_lib_nodeio.lua") diff --git a/lib_materials_fluid_lib_buffer.lua b/lib_materials_fluid_lib_buffer.lua new file mode 100644 index 0000000..2c24d65 --- /dev/null +++ b/lib_materials_fluid_lib_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 fluid_lib.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 fluid_lib.get_buffer_data(pos, buffer) + local node, nodedef = node_data(pos) + local buffers = fluid_lib.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 fluid_lib.buffer_accepts_fluid(pos, buffer, fluid) + local bfdata = fluid_lib.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 fluid_lib.can_insert_into_buffer(pos, buffer, fluid, count) + local bfdata = fluid_lib.get_buffer_data(pos, buffer) + if not bfdata then return 0 end + if not fluid_lib.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 fluid_lib.insert_into_buffer(pos, buffer, fluid, count) + local bfdata = fluid_lib.get_buffer_data(pos, buffer) + if not bfdata then return count end + if bfdata.fluid ~= fluid and bfdata.fluid ~= "" then return count end + + local can_put = fluid_lib.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 fluid_lib.can_take_from_buffer(pos, buffer, count) + local bfdata = fluid_lib.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 fluid_lib.take_from_buffer(pos, buffer, count) + local bfdata = fluid_lib.get_buffer_data(pos, buffer) + if not bfdata then return nil end + + local fluid = bfdata.fluid + local amount = bfdata.amount + + local take_count = fluid_lib.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 fluid_lib.buffer_to_string(buffer) + if not buffer then return "" end + local amount = fluid_lib.comma_value(buffer.amount) + local capacity = fluid_lib.comma_value(buffer.capacity) + local description = "Empty" + + if buffer.fluid ~= "" then + description = fluid_lib.cleanse_node_description(buffer.fluid) + end + + return ("%s (%s / %s %s)"):format(description, amount, capacity, fluid_lib.unit) +end diff --git a/lib_materials_fluid_lib_nodeio.lua b/lib_materials_fluid_lib_nodeio.lua new file mode 100644 index 0000000..6461a5c --- /dev/null +++ b/lib_materials_fluid_lib_nodeio.lua @@ -0,0 +1,100 @@ + +-- Node IO System +local nodeiodef = { + node_io_can_put_liquid = function (pos, node, side) + return minetest.get_item_group(node.name, 'fluid_container') > 0 + end, + node_io_can_take_liquid = function (pos, node, side) + return minetest.get_item_group(node.name, 'fluid_container') > 0 + end, + -- if false, transfer node should only put and take in 1000 increments + -- inventory nodes that don't accept milibuckets should: + -- return zero in node_io_room_for_liquid() if non-1000 increment + -- return millibuckets parameter in node_io_put_liquid() if non-1000 increment + -- only return upto a 1000 increment in node_io_take_liquid() + -- transfer nodes that can put non-1000 increments should always check this or the inventory node might pretend to be full + node_io_accepts_millibuckets = function(pos, node, side) return true end, + node_io_put_liquid = function(pos, node, side, putter, liquid, millibuckets) + local buffers = fluid_lib.get_node_buffers(pos) + local leftovers = 0 + for buffer,data in pairs(buffers) do + if millibuckets == 0 then break end + local didnt_fit = fluid_lib.insert_into_buffer(pos, buffer, liquid, millibuckets) + millibuckets = millibuckets - (millibuckets - didnt_fit) + leftovers = leftovers + didnt_fit + end + return leftovers + end, + -- returns millibuckets if inventory can hold entire amount, else returns amount the inventory can hold + -- use millibuckets=1 to check if not full, then call put_liquid() with actual amount to transfer + -- use millibuckets=1000 with room_for_liquid() and put_liquid() to only insert full buckets + node_io_room_for_liquid = function(pos, node, side, liquid, millibuckets) + local buffers = fluid_lib.get_node_buffers(pos) + local insertable = 0 + for buffer,data in pairs(buffers) do + local insert = fluid_lib.can_insert_into_buffer(pos, buffer, liquid, millibuckets) + if insert > 0 then + insertable = insert + break + end + end + return insertable + end, + + -- returns {name:string, millibuckets:int} with <= want_millibuckets or nil if inventory is empty or doesn't have want_liquid + -- want_liquid should be the name of a source liquid (in bucket.liquids of bucket mod) + node_io_take_liquid = function(pos, node, side, taker, want_liquid, want_millibuckets) + local buffers = fluid_lib.get_node_buffers(pos) + local took = 0 + local name = "" + for buffer,data in pairs(buffers) do + local bfdata = fluid_lib.get_buffer_data(pos, buffer) + local storage = bfdata.amount + local fluid = bfdata.fluid + if (fluid == want_liquid or want_liquid == "") and storage >= want_millibuckets then + name, took = fluid_lib.take_from_buffer(pos, buffer, want_millibuckets) + if took > 0 then break end + end + end + return {name = name, millibuckets = took} + end, + + node_io_get_liquid_size = function (pos, node, side) + -- this is always 1 unless inventory can hold multiple liquid types + local cnt = 0 + local bfs = fluid_lib.get_node_buffers(pos) + for _ in pairs(bfs) do + cnt = cnt + 1 + end + return cnt + end, + + node_io_get_liquid_name = function(pos, node, side, index) + local cnt = {} + local bfs = fluid_lib.get_node_buffers(pos) + for buf in pairs(bfs) do + cnt[#cnt + 1] = buf + end + if not cnt[index] then return ItemStack(nil) end + local meta = minetest.get_meta(pos) + + return meta:get_string(cnt[index] .. "_fluid") + end, + + node_io_get_liquid_stack = function(pos, node, side, index) + local cnt = {} + local bfs = fluid_lib.get_node_buffers(pos) + for buf in pairs(bfs) do + cnt[#cnt + 1] = buf + end + if not cnt[index] then return ItemStack(nil) end + local meta = minetest.get_meta(pos) + + return ItemStack(meta:get_string(cnt[index] .. "_fluid") .. " " .. + meta:get_int(cnt[index] .. "_fluid_storage")) + end, +} + +function fluid_lib.register_node(nodename) + minetest.override_item(nodename, nodeiodef) +end diff --git a/lib_materials_nodeio.lua b/lib_materials_nodeio.lua new file mode 100644 index 0000000..44e3158 --- /dev/null +++ b/lib_materials_nodeio.lua @@ -0,0 +1,299 @@ + + +local MP = minetest.get_modpath(minetest.get_current_modname()).."/" + + +node_io = {} + + +-- get target side + +node_io.get_target_side = function(pos, target_pos) + if pos.y > target_pos.y then return "U" end + if pos.y < target_pos.y then return "D" end + + if pos.z > target_pos.z then return "N" end + if pos.z < target_pos.z then return "S" end + + if pos.x > target_pos.x then return "E" end + return "W" +end + +-- get pointed side + +node_io.get_pointed_side = function(pointer, pointed_thing) + local p0 = pointed_thing.under + local p1 = pointed_thing.above + if p0.y == p1.y then + if p0.z > p1.z then return "S" end + if p0.z < p1.z then return "N" end + if p0.x > p1.x then return "W" end + return "E" + elseif p0.y < p1.y then + return "U" + else + return "D" + end +end + + + +-- notify all six neighbors of node changes (placed, dug, can_put, can_take) + +node_io.update_neighbors = function(pos) + local p, n, d + p={x=pos.x+1, y=pos.y, z=pos.z} n=minetest.get_node(p) d=minetest.registered_nodes[n.name] if d and d.node_io_on_neighbor_update then d.node_io_on_neighbor_update(p,n,"W") end + p={x=pos.x-1, y=pos.y, z=pos.z} n=minetest.get_node(p) d=minetest.registered_nodes[n.name] if d and d.node_io_on_neighbor_update then d.node_io_on_neighbor_update(p,n,"E") end + p={x=pos.x, y=pos.y+1, z=pos.z} n=minetest.get_node(p) d=minetest.registered_nodes[n.name] if d and d.node_io_on_neighbor_update then d.node_io_on_neighbor_update(p,n,"D") end + p={x=pos.x, y=pos.y-1, z=pos.z} n=minetest.get_node(p) d=minetest.registered_nodes[n.name] if d and d.node_io_on_neighbor_update then d.node_io_on_neighbor_update(p,n,"U") end + p={x=pos.x, y=pos.y, z=pos.z+1} n=minetest.get_node(p) d=minetest.registered_nodes[n.name] if d and d.node_io_on_neighbor_update then d.node_io_on_neighbor_update(p,n,"S") end + p={x=pos.x, y=pos.y, z=pos.z-1} n=minetest.get_node(p) d=minetest.registered_nodes[n.name] if d and d.node_io_on_neighbor_update then d.node_io_on_neighbor_update(p,n,"N") end +end + + + +-- query API + -- can_* functions should always be called first and return false if ndef isn't found (unknown node) + -- the other functions can safely skip the ndef check for performance + +node_io.can_put_item = function(pos, node, side) + local ndef = minetest.registered_nodes[node.name] + if not ndef or not ndef.node_io_can_put_item then return false end + return ndef.node_io_can_put_item(pos, node, side) +end +node_io.can_put_liquid = function(pos, node, side) + local ndef = minetest.registered_nodes[node.name] + if not ndef or not ndef.node_io_can_put_liquid then return false end + return ndef.node_io_can_put_liquid(pos, node, side) +end + +node_io.can_take_item = function(pos, node, side) + local ndef = minetest.registered_nodes[node.name] + if not ndef or not ndef.node_io_can_take_item then return false end + return ndef.node_io_can_take_item(pos, node, side) +end +node_io.can_take_liquid = function(pos, node, side) + local ndef = minetest.registered_nodes[node.name] + if not ndef or not ndef.node_io_can_take_liquid then return false end + return ndef.node_io_can_take_liquid(pos, node, side) +end +node_io.accepts_millibuckets = function(pos, node, side) + local ndef = minetest.registered_nodes[node.name] + if not ndef or not ndef.node_io_accepts_millibuckets then return false end + return ndef.node_io_accepts_millibuckets(pos, node, side) +end + +node_io.room_for_item = function(pos, node, side, itemstack, count) -- returns non-negative number + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_room_for_item then return 0 end + return ndef.node_io_room_for_item(pos, node, side, itemstack, count) +end +node_io.room_for_liquid = function(pos, node, side, liquid, millibuckets) -- returns non-negative number + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_room_for_liquid then return 0 end + return ndef.node_io_room_for_liquid(pos, node, side, liquid, millibuckets) +end + +node_io.get_item_size = function(pos, node, side) -- returns non-negative number + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_get_item_size then return 0 end + return ndef.node_io_get_item_size(pos, node, side) +end +node_io.get_liquid_size = function(pos, node, side) -- returns non-negative number + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_get_liquid_size then return 0 end + return ndef.node_io_get_liquid_size(pos, node, side) +end + +node_io.get_item_name = function(pos, node, side, index) -- returns string or empty string + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_get_item_name then return "" end + return ndef.node_io_get_item_name(pos, node, side, index) +end +node_io.get_liquid_name = function(pos, node, side, index) -- returns string or empty string + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_get_liquid_name then return "" end + return ndef.node_io_get_liquid_name(pos, node, side, index) +end + +node_io.get_item_stack = function(pos, node, side, index) -- returns itemstack or nil + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_get_item_stack then return nil end + return ndef.node_io_get_item_stack(pos, node, side, index) +end +node_io.get_liquid_stack = function(pos, node, side, index) -- returns itemstack or nil + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_get_liquid_stack then return nil end + return ndef.node_io_get_liquid_stack(pos, node, side, index) +end + + +-- access API + +node_io.put_item = function(pos, node, side, putter, itemstack) -- returns itemstack with leftovers or a cleared itemstack + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_put_item then return itemstack end + return ndef.node_io_put_item(pos, node, side, putter, itemstack) +end +node_io.put_liquid = function(pos, node, side, putter, liquid, millibuckets) -- returns leftover millibuckets or zero + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_put_liquid then return millibuckets end + return ndef.node_io_put_liquid(pos, node, side, putter, liquid, millibuckets) +end + +node_io.take_item = function(pos, node, side, taker, want_item, want_count) -- returns itemstack or nil + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_take_item then return nil end + return ndef.node_io_take_item(pos, node, side, taker, want_item, want_count) +end +node_io.take_liquid = function(pos, node, side, taker, want_liquid, want_count) -- returns {name:string, millibuckets:int} or nil + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_take_liquid then return nil end + return ndef.node_io_take_liquid(pos, node, side, taker, want_liquid, want_count) +end + + + + +-- functions for mods with inventories to implement API + +node_io.get_inventory = function(pos) + if pos.type then + -- {type="node", pos={x=, y=, z=}} + -- {type="detached", name=""} + -- {type="player", name=""} + return minetest.get_inventory(pos) + else + -- {x=, y=, z=} + return minetest.get_meta(pos):get_inventory() + end +end + +node_io.compare_itemstack = function(itemstack1, itemstack2) + if itemstack1:get_name() ~= itemstack2:get_name() then return false end + if itemstack1:get_wear() ~= itemstack2:get_wear() then return false end + if itemstack1:get_meta() ~= itemstack2:get_meta() then return false end + return true +end + +node_io.room_for_item_in_inventory = function(inv, inv_name, itemstack, count) + local max = itemstack:get_stack_max() + local put_count = max + if count < put_count then put_count = count end + local room = 0 + for i = 1, inv:get_size(inv_name) do + local stack = inv:get_stack("main", i) + if stack:is_empty() then return put_count end + if node_io.compare_itemstack(stack, itemstack) then + if stack:get_count() < max then + room = room + max - stack:get_count() + if room >= put_count then return put_count end + end + end + end + return room +end + +node_io.get_inventory_size = function(pos, inv_name) + local inv = node_io.get_inventory(pos) -- see node_io.get_inventory() for pos details + if not inv then return 0 end + return inv:get_size(inv_name) +end + +node_io.get_inventory_name = function(pos, inv_name, index) + local inv = node_io.get_inventory(pos) -- see node_io.get_inventory() for pos details + if not inv or index < 1 or index > inv:get_size(inv_name) then return "" end + return inv:get_stack(inv_name, index):get_name() +end + +node_io.get_inventory_stack = function(pos, inv_name, index) + local inv = node_io.get_inventory(pos) -- see node_io.get_inventory() for pos details + if not inv or index < 1 or index > inv:get_size(inv_name) then return nil end + local stack = inv:get_stack(inv_name, index) + if stack:is_empty() then return nil end + stack:set_count(1) + return stack +end + +node_io.put_item_in_inventory = function(pos, node, inv_name, putter, itemstack) + local inv = node_io.get_inventory(pos) -- see node_io.get_inventory() for pos details + if not inv or itemstack:is_empty() then return itemstack end + + local leftovers = inv:add_item(inv_name, itemstack) + + local ndef = minetest.registered_nodes[node.name] + if ndef.on_metadata_inventory_put and putter then + ndef.on_metadata_inventory_put(pos, inv_name, 0, itemstack, putter) + -- TODO: 0 is index in inv_name + end + + if leftovers then return leftovers end + itemstack:clear() + return itemstack +end + +node_io.take_item_from_inventory = function(pos, node, inv_name, taker, want_item, want_count) + local inv = node_io.get_inventory(pos) -- see node_io.get_inventory() for pos details + if not inv or inv:is_empty(inv_name) then return nil end + + for i = 1, inv:get_size(inv_name) do + local stack = inv:get_stack(inv_name, i) + local stack_item = stack:get_name() + if stack_item ~= "" and (want_item == nil or (type(want_item) == "userdata" and node_io.compare_itemstack(stack, want_item)) or stack_item == want_item) then + local result_stack + if stack:get_count() > want_count then + -- stack is larger than wanted + result_stack = stack:take_item(want_count) + inv:set_stack(inv_name, i, stack) + else + inv:remove_item(inv_name, stack) + result_stack = stack + end + + local ndef = minetest.registered_nodes[node.name] + if ndef.on_metadata_inventory_take and taker then + ndef.on_metadata_inventory_take(pos, inv_name, i, stack, taker) + end + + return result_stack + end + end +end + +node_io.init_main_inventory = function(node_name, allow_take) + local def = {} + + def.node_io_can_put_item = function(pos, node, side) return true end + def.node_io_room_for_item = function(pos, node, side, itemstack, count) + local inv = node_io.get_inventory(pos) -- see node_io.get_inventory() for pos details + if not inv then return 0 end + return node_io.room_for_item_in_inventory(inv, "main", itemstack, count) + end + def.node_io_put_item = function(pos, node, side, putter, itemstack) + return node_io.put_item_in_inventory(pos, node, "main", putter, itemstack) + end + + if allow_take then + def.node_io_can_take_item = function(pos, node, side) return true end + def.node_io_get_item_size = function(pos, node, side) + return node_io.get_inventory_size(pos, "main") + end + def.node_io_get_item_name = function(pos, node, side, index) + return node_io.get_inventory_name(pos, "main", index) + end + def.node_io_get_item_stack = function(pos, node, side, index) + return node_io.get_inventory_stack(pos, "main", index) + end + def.node_io_take_item = function(pos, node, side, taker, want_item, want_count) + return node_io.take_item_from_inventory(pos, node, "main", taker, want_item, want_count) + end + end + + minetest.override_item(node_name, def) +end + + + +dofile(MP.."lib_materials_nodeio_support.lua") + +print("[MOD] Node IO loaded") diff --git a/lib_materials_nodeio_support.lua b/lib_materials_nodeio_support.lua new file mode 100644 index 0000000..a94cce1 --- /dev/null +++ b/lib_materials_nodeio_support.lua @@ -0,0 +1,58 @@ +-- add support for default mod + +if minetest.get_modpath("default") then + print("[Node IO] default support enabled") + + -- chest + node_io.init_main_inventory("default:chest", true) + node_io.init_main_inventory("default:chest_open", true) + -- locked chest + node_io.init_main_inventory("default:chest_locked", false) + node_io.init_main_inventory("default:chest_locked_open", false) + + -- export function so pipeworks can use it to init its replacement furnace + node_io.init_default_furnace = function(node_name) + local def = {} + + def.node_io_can_put_item = function(pos, node, side) return true end + def.node_io_room_for_item = function(pos, node, side, itemstack, count) + local inv = minetest.get_meta(pos):get_inventory() + if not inv then return 0 end + local inv_name + if side == "U" then inv_name = "src" elseif side == "D" then inv_name = "dst" else inv_name = "fuel" end + return node_io.room_for_item_in_inventory(inv, inv_name, itemstack, count) + end + def.node_io_put_item = function(pos, node, side, putter, itemstack) + local inv_name + if side == "U" then inv_name = "src" elseif side == "D" then inv_name = "dst" else inv_name = "fuel" end + return node_io.put_item_in_inventory(pos, node, inv_name, putter, itemstack) + end + + def.node_io_can_take_item = function(pos, node, side) return true end + def.node_io_get_item_size = function(pos, node, side) + local inv_name + if side == "U" then inv_name = "src" elseif side == "D" then inv_name = "dst" else inv_name = "fuel" end + return node_io.get_inventory_size(pos, inv_name) + end + def.node_io_get_item_name = function(pos, node, side, index) + local inv_name + if side == "U" then inv_name = "src" elseif side == "D" then inv_name = "dst" else inv_name = "fuel" end + return node_io.get_inventory_name(pos, inv_name, index) + end + def.node_io_get_item_stack = function(pos, node, side, index) + local inv_name + if side == "U" then inv_name = "src" elseif side == "D" then inv_name = "dst" else inv_name = "fuel" end + return node_io.get_inventory_stack(pos, inv_name, index) + end + def.node_io_take_item = function(pos, node, side, taker, want_item, want_count) + local inv_name + if side == "U" then inv_name = "src" elseif side == "D" then inv_name = "dst" else inv_name = "fuel" end + return node_io.take_item_from_inventory(pos, node, inv_name, taker, want_item, want_count) + end + + minetest.override_item(node_name, def) + end + -- furnace + node_io.init_default_furnace("default:furnace") + node_io.init_default_furnace("default:furnace_active") +end