From cd185163724b5dd530be3792c7609bd9cbdb8834 Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Wed, 20 Jun 2018 18:35:53 +0300 Subject: [PATCH] Fluid tanks!! More API functions --- bucket/init.lua | 19 ++++ fluid_lib/buffer.lua | 8 +- fluid_lib/init.lua | 29 ++++++ fluid_tanks/depends.txt | 1 + fluid_tanks/init.lua | 197 ++++++++++++++++++++++++++++++++++++++++ fluid_tanks/mod.conf | 3 + 6 files changed, 253 insertions(+), 4 deletions(-) create mode 100644 fluid_tanks/depends.txt create mode 100644 fluid_tanks/init.lua create mode 100644 fluid_tanks/mod.conf diff --git a/bucket/init.lua b/bucket/init.lua index 5e14a3e..93dcfbd 100644 --- a/bucket/init.lua +++ b/bucket/init.lua @@ -117,6 +117,9 @@ function bucket.register_liquid(source, flowing, itemname, inventory_image, name for buffer in pairs(buffers) do if fluid_lib.can_insert_into_buffer(ppos, buffer, source, 1000) == 1000 then fluid_lib.insert_into_buffer(ppos, buffer, source, 1000) + if ndef.on_timer then + minetest.get_node_timer(ppos):start(ndef.node_timer_seconds or 1.0) + end place = false break end @@ -134,6 +137,19 @@ function bucket.register_liquid(source, flowing, itemname, inventory_image, name end end +function bucket.get_liquid_for_bucket(itemname) + local found = nil + + for source, b in pairs(bucket.liquids) do + if b.itemname and b.itemname == itemname then + found = source + break + end + end + + return found +end + minetest.register_craftitem("bucket:bucket_empty", { description = "Empty Bucket", inventory_image = "bucket.png", @@ -240,6 +256,9 @@ minetest.register_craftitem("bucket:bucket_empty", { local fluid = fluid_lib.take_from_buffer(lpos, buffer, 1000) if bucket.liquids[fluid] then itemstack = ItemStack(bucket.liquids[fluid].itemname) + if ndef.on_timer then + minetest.get_node_timer(lpos):start(ndef.node_timer_seconds or 1.0) + end end break end diff --git a/fluid_lib/buffer.lua b/fluid_lib/buffer.lua index f89a1b6..b42ea9f 100644 --- a/fluid_lib/buffer.lua +++ b/fluid_lib/buffer.lua @@ -42,15 +42,15 @@ 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.accepts == true or bfdata.accepts == fluid then - return true - 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 diff --git a/fluid_lib/init.lua b/fluid_lib/init.lua index 3fb27bb..8df014b 100644 --- a/fluid_lib/init.lua +++ b/fluid_lib/init.lua @@ -9,4 +9,33 @@ 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 + dofile(modpath.."/buffer.lua") diff --git a/fluid_tanks/depends.txt b/fluid_tanks/depends.txt new file mode 100644 index 0000000..e43a56a --- /dev/null +++ b/fluid_tanks/depends.txt @@ -0,0 +1 @@ +bucket diff --git a/fluid_tanks/init.lua b/fluid_tanks/init.lua new file mode 100644 index 0000000..186d504 --- /dev/null +++ b/fluid_tanks/init.lua @@ -0,0 +1,197 @@ +-- Fluid Tanks +-- Copyright (c) 2018 Evert "Diamond" Prants + +fluid_tanks = {} + +-- Preserve fluid count in the item stack dropped +local function preserve_metadata(pos, oldnode, oldmeta, drops) + local buffer = fluid_lib.get_buffer_data(pos, "buffer") + local meta = minetest.get_meta(pos) + local fluid_cnt = meta:get_int("buffer_fluid_storage") + + if fluid_cnt > 0 then + local node = minetest.get_node(pos) + local ndef = minetest.registered_nodes[node.name] + + for i,stack in pairs(drops) do + local stack_meta = stack:get_meta() + stack_meta:set_int("fluid_storage", fluid_cnt) + stack_meta:set_string("description", ndef.description .. "\nContains " .. + buffer.amount .. "/" .. buffer.capacity .. " mB") + + drops[i] = stack + end + end + + return drops +end + +-- Retrieve fluid count from itemstack when placed +local function after_place_node(pos, placer, itemstack, pointed_thing) + local item_meta = itemstack:get_meta() + local fluid_cnt = item_meta:get_int("fluid_storage") + + if fluid_cnt then + local meta = minetest.get_meta(pos) + meta:set_int("buffer_fluid_storage", fluid_cnt) + end + + minetest.get_node_timer(pos):start(0.2) + + return false +end + +local function tank_on_timer(pos, elapsed) + local node = minetest.get_node(pos) + local meta = minetest.get_meta(pos) + + local buffer = fluid_lib.get_buffer_data(pos, "buffer") + local percentile = buffer.amount / buffer.capacity + + local node_name = node.name + local ndef = minetest.registered_nodes[node_name] + if buffer.amount == 0 and ndef['_base_node'] then + node_name = ndef['_base_node'] + end + + -- Select valid tank for current fluid + if buffer.amount > 0 and not ndef['_base_node'] and buffer.fluid ~= "" then + local fluid_name = fluid_lib.cleanse_node_name(buffer.fluid) + local new_node_name = node.name .. "_" .. fluid_name + local new_def = minetest.registered_nodes[new_node_name] + if new_def then + node_name = new_node_name + ndef = new_def + end + end + + if buffer.amount == 0 and ndef['_base_node'] then + node_name = ndef['_base_node'] + ndef = minetest.registered_nodes[node_name] + meta:set_string("buffer_fluid", "") + end + + -- Update infotext + meta:set_string("infotext", ("%s (%d/%d %s)"):format(ndef.description, buffer.amount, buffer.capacity, fluid_lib.unit)) + + local param2 = math.min(percentile * 63, 63) + + -- Node changed, lets switch it + if node_name ~= node.name or param2 ~= node.param2 then + minetest.swap_node(pos, {name = node_name, param2 = param2, param1 = node.param1}) + end + + return false +end + +local function create_tank_node(tankname, def, fluid_name) + local capacity = def.capacity or 16000 + local tiles = def.tiles or {"default_glass.png", "default_glass_detail.png"} + local desc = def.description + local srcnode = def.srcnode or nil + local accepts = def.accepts or true + + local groups = {cracky = 1, oddly_breakable_by_hand = 3, fluid_container = 1} + + if srcnode then + groups["not_in_creative_inventory"] = 1 + end + + if minetest.registered_nodes[tankname] then + return + end + + local special_tiles = {} + if fluid_name then + local fdef = minetest.registered_nodes[fluid_name] + if fdef and fdef.tiles then + special_tiles = fdef.tiles + end + + local fluid_desc = fluid_lib.cleanse_node_description(fluid_name) + desc = desc .. " of "..fluid_desc + end + + minetest.register_node(tankname, { + description = desc, + drawtype = "glasslike_framed_optional", + paramtype = "light", + paramtype2 = "glasslikeliquidlevel", + is_ground_content = false, + sunlight_propagates = true, + special_tiles = special_tiles, + fluid_buffers = { + buffer = { + capacity = capacity, + accepts = accepts, + drainable = true, + } + }, + on_construct = function ( pos ) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", "Empty "..desc) + end, + on_timer = tank_on_timer, + groups = groups, + tiles = tiles, + _base_node = srcnode, + node_timer_seconds = 0.2, + preserve_metadata = preserve_metadata, + after_place_node = after_place_node, + }) +end + +function fluid_tanks.register_tank(tankname, def) + local accepts = def.accepts or true + + if not accepts then return end + + if not minetest.registered_nodes[tankname] then + create_tank_node(tankname, def) + end + + if type(accepts) == "string" then + accepts = {accepts} + end + + if type(accepts) == "table" then + local new_accepts = {} + for _,s in ipairs(accepts) do + if s:match("^group:") then + local grp = s:gsub("^(group:)", "") + for f in pairs(bucket.liquids) do + if minetest.get_item_group(f, grp) > 0 then + new_accepts[#new_accepts + 1] = f + end + end + else + if bucket.liquids[s] then + new_accepts[#new_accepts + 1] = s + end + end + end + accepts = new_accepts + end + + if accepts == true then + accepts = {} + for _,i in pairs(bucket.liquids) do + accepts[#accepts + 1] = i.source + end + end + + def.srcnode = tankname + + for _, src in ipairs(accepts) do + local fluid = fluid_lib.cleanse_node_name(src) + create_tank_node(tankname .. "_" .. fluid, def, src) + end +end + +--minetest.after(0.2, function () + fluid_tanks.register_tank("fluid_tanks:tank", { + description = "Fluid Tank", + capacity = 16000, + accepts = true, + }) +--end) diff --git a/fluid_tanks/mod.conf b/fluid_tanks/mod.conf new file mode 100644 index 0000000..0103f7a --- /dev/null +++ b/fluid_tanks/mod.conf @@ -0,0 +1,3 @@ +name = fluid_tanks +description = API for fluid storage. +depends = bucket