diff --git a/gasoline.lua b/gasoline.lua new file mode 100644 index 0000000..33501d8 --- /dev/null +++ b/gasoline.lua @@ -0,0 +1,435 @@ + + + + +local function register_fluid(modname, name, info) + local fname = modname..":"..name + local full_fname = modname..":"..name.."_full" + + local gname = modname.."_"..name.."_fluid" + + local groups = { liquid = 3, [gname]=1} + for n,l in pairs(info.groups) do + groups[n] = l + end + + local full_groups = {not_in_creative_inventory = 1} + for n,l in pairs(groups) do + full_groups[n] = l + end + + + minetest.register_node(fname, { + description = info.desc, + drawtype = "nodebox", + paramtype = "light", + tiles = { + { + name = "default_river_water_source_animated.png"..info.colorize, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + }, + }, + special_tiles = { + { + name = "default_river_water_source_animated.png"..info.colorize, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + backface_culling = false, + }, + }, + leveled = 64, + alpha = 160, + drop = "", + drowning = 1, + walkable = false, -- because viscosity doesn't work for regular nodes, and the liquid hack can't be leveled + climbable = true, -- because viscosity doesn't work for regular nodes, and the liquid hack can't be leveled + pointable = false, + diggable = false, + buildable_to = true, + post_effect_color = info.post_effect_color, + groups = groups, + sounds = default.node_sound_water_defaults(), + node_box = { + type = "leveled", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, -- NodeBox1 + } + } + }) + + + + + -- this is a special node used to optimize large pools of water + -- its flowing abm runs much less frequently + minetest.register_node(full_fname, { + description = info.desc, + drawtype = "nodebox", + paramtype = "light", + tiles = { + { + name = "default_river_water_source_animated.png"..info.colorize, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + }, + }, + special_tiles = { + { + name = "default_river_water_source_animated.png"..info.colorize, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + backface_culling = false, + }, + }, + leveled = 64, + alpha = 160, + drop = "", + drowning = 1, + walkable = false, -- because viscosity doesn't work for regular nodes, and the liquid hack can't be leveled + climbable = true, -- because viscosity doesn't work for regular nodes, and the liquid hack can't be leveled + pointable = false, + diggable = false, + buildable_to = true, + post_effect_color = info.post_effect_color, + groups = full_groups, + sounds = default.node_sound_water_defaults(), + node_box = { + type = "leveled", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, -- NodeBox1 + } + } + }) + + + + local soak = { + ["default:cobble"] = 10, + ["default:desert_cobble"] = 10, + ["default:mossycobble"] = 9, + ["default:dirt"] = 2, + ["default:dirt_with_grass"] = 2, + ["default:dirt_with_grass_footsteps"] = 2, + ["default:dirt_with_dry_grass"] = 2, + ["default:dirt_with_coniferous_litter"] = 2, + ["default:dirt_with_rainforest_litter"] = 1, + ["default:gravel"] = 8, + ["default:coral_orange"] = 6, + ["default:coral_brown"] = 6, + ["default:coral_skeleton"] = 6, + ["default:sand"] = 6, + ["default:sand_with_kelp"] = 6, + ["default:desert_sand"] = 7, + ["default:silver_sand"] = 7, + ["default:snow"] = 4, + ["default:snowblock"] = 4, + ["default:leaves"] = 60, + ["default:bush_leaves"] = 60, + ["default:jungleleaves"] = 60, + ["default:pine_needles"] = 60, + ["default:acacia_leaves"] = 60, + ["default:acacia_bush_leaves"] = 60, + ["default:aspen_leaves"] = 60, + + -- dilution + ["default:water_source"] = 65, + ["default:water_flowing"] = 65, + ["default:river_water_source"] = 65, + ["default:river_water_flowing"] = 65, + + -- boiling -- TODO: steam effect + ["default:lava_source"] = 65, + ["default:lava_flowing"] = 65, + + -- no ladder hacks + ["default:ladder_wood"] = 65, + -- ["default:ladder_steel"] = 65, -- need to figure out a way for water to flow through ladders + ["default:sign_wall_wood"] = 65, + ["default:sign_wall_steel"] = 65, + + ["default:fence_wood"] = 65, + ["default:fence_acacia_wood"] = 65, + ["default:fence_junglewood"] = 65, + ["default:fence_pine_wood"] = 65, + ["default:fence_aspen_wood"] = 65, + + ["default:torch"] = 65, + ["carts:rail"] = 65, + ["carts:brakerail"] = 65, + ["carts:powerrail"] = 65, + + + } + + local soak_names = {} + for n,_ in pairs(soak) do + table.insert(soak_names, n) + end + + + -- todo: superflammability + -- boil-off for water near fire + -- vapors or explosions + + + + + if info.evap_chance > 0 then + + -- evaporation + minetest.register_abm({ + nodenames = {"group:"..gname}, + neighbors = {"group:"..gname, "air"}, + interval = info.evap_interval, + chance = info.evap_chance, + action = function(pos) + local mylevel = minetest.get_node_level(pos) + if math.random(16 - minetest.get_node_light(pos)) == 1 then + if mylevel > info.evap_rate then + minetest.set_node_level(pos, mylevel - info.evap_rate) + else + minetest.set_node(pos, {name = "air"}) + end + end + end + }) + + end + + -- de-stagnation (faster flowing) + minetest.register_abm({ + nodenames = {full_fname}, + neighbors = {"air"}, + interval = 5, + chance = 1, + action = function(pos) + -- if it's near air it might flow + minetest.set_node(pos, {name = fname}) + end + }) + + + + -- flowing + minetest.register_abm({ + nodenames = {fname}, + neighbors = {"group:"..gname, "air"}, + interval = 1, + chance = 1, + action = function(pos) + local mylevel = minetest.get_node_level(pos) + -- print("\n mylevel ".. mylevel) + + -- falling + local below = {x=pos.x, y=pos.y - 1, z=pos.z} + local nbelow = minetest.get_node(below).name + if nbelow == "air" then + minetest.set_node(below, {name=fname}) + minetest.set_node_level(below, mylevel) + minetest.set_node(pos, {name="air"}) + return + elseif nbelow == fname then + local blevel = minetest.get_node_level(below) + if blevel < 64 then + local sum = mylevel + blevel + minetest.set_node_level(below, math.min(64, sum)) + + if sum > 64 then + mylevel = sum - 64 + minetest.set_node_level(pos, mylevel) + -- keep flowing the liquid. this speeds up cascades + else + minetest.set_node(pos, {name="air"}) + return + end + end + else -- check soaking + local rate = soak[nbelow] + if rate ~= nil then + local remains = mylevel - rate + if remains > 0 then + minetest.set_node_level(pos, remains) + else + minetest.set_node(pos, {name="air"}) + end + + if 1 == math.random(120 / mylevel) then + minetest.set_node(below, {name = "air"}) + end + + mylevel = remains + --return -- keep the fluid mechanics + end + end + + local air_nodes = minetest.find_nodes_in_area( + {x=pos.x - 1, y=pos.y - 1, z=pos.z - 1}, + {x=pos.x + 1, y=pos.y, z=pos.z + 1}, + "air" + ) + + + + + -- print("x: "..pos.x.." y: "..pos.y.." z: "..pos.z) + -- print("air list len ".. #air_nodes) + local off = math.random(#air_nodes) + + for i = 1,#air_nodes do + --local theirlevel = minetest.get_node_level(fp) + local fp = air_nodes[((i + off) % #air_nodes) + 1] + if mylevel >= 2 then + local half = math.ceil(mylevel / 2) + + minetest.set_node_level(pos, mylevel - half) + minetest.set_node(fp, {name= fname}) + minetest.set_node_level(fp, half) + -- minetest.check_for_falling(fp) + return + end + end + + local flow_nodes = minetest.find_nodes_in_area( + {x=pos.x - 1, y=pos.y , z=pos.z - 1}, + {x=pos.x + 1, y=pos.y, z=pos.z + 1}, + "group:"..gname + ) + + -- print("x: "..pos.x.." y: "..pos.y.." z: "..pos.z) + -- print("list len ".. #flow_nodes) + local off = math.random(#flow_nodes) + + for i = 1,#flow_nodes do + local fp = flow_nodes[((i + off) % #flow_nodes) + 1] + local theirlevel = minetest.get_node_level(fp) + -- print("theirlevel "..theirlevel) + if mylevel - theirlevel >= 2 then + local diff = (mylevel - theirlevel) + local half = math.ceil(diff / 2) + + minetest.set_node_level(pos, mylevel - half) + minetest.set_node_level(fp, theirlevel + (diff - half)) + return + end + end + + -- local n = minetest.get_node(fp); + -- -- check above to make sure it can get here + -- local na = minetest.get_node({x=fp.x, y=fp.y+1, z=fp.z}) + -- + -- -- print("name: " .. na.name .. " l: " ..g) + -- if na.name == "default:river_water_flowing" or na.name == "default:river_water_flowing" then + -- minetest.set_node(fp, {name=node.name}) + -- minetest.set_node(pos, {name=n.name}) + -- return + -- end + -- end + + + -- stagnation: this may not work + if mylevel == 64 then + --print("stagnating ".. pos.x .. ","..pos.y..","..pos.z) + minetest.set_node(pos, {name = full_fname}) + end + end + }) + +end + + +register_fluid("bitumen", "mineral_spirits", { + desc = "Mineral Spirits", + groups = {flammable=1, petroleum=1}, + + colorize = "^[colorize:white:160", + post_effect_color = {a = 103, r = 30, g = 76, b = 90}, + + evap_interval = 5, + evap_chance = 5, + evap_rate = 5, +}) + +register_fluid("bitumen", "gasoline", { + desc = "Gasoline", + groups = {flammable=1, petroleum=1}, + + colorize = "^[colorize:yellow:160", + post_effect_color = {a = 103, r = 30, g = 76, b = 90}, + + evap_interval = 5, + evap_chance = 5, + evap_rate = 5, +}) + +register_fluid("bitumen", "diesel", { + desc = "Diesel", + groups = {flammable=1, petroleum=1}, + + colorize = "^[colorize:red:160", + post_effect_color = {a = 103, r = 230, g = 76, b = 90}, + + evap_interval = 5, + evap_chance = 10, + evap_rate = 2, +}) + +register_fluid("bitumen", "kerosene", { + desc = "Kerosene", + groups = {flammable=1, petroleum=1}, + + colorize = "^[colorize:white:100", + post_effect_color = {a = 103, r = 80, g = 76, b = 190}, + + evap_interval = 5, + evap_chance = 10, + evap_rate = 8, +}) + +register_fluid("bitumen", "light_oil", { + desc = "Light Oil", + groups = {flammable=1, petroleum=1}, + + colorize = "^[colorize:brown:220", + post_effect_color = {a = 103, r = 80, g = 76, b = 90}, + + evap_chance = 0, +}) + +register_fluid("bitumen", "heavy_oil", { + desc = "Heavy Oil", + groups = {flammable=1, petroleum=1}, + + colorize = "^[colorize:brown:240", + post_effect_color = {a = 103, r = 80, g = 76, b = 90}, + + evap_chance = 0, +}) + +register_fluid("bitumen", "tar", { + desc = "Tar", + groups = {flammable=1, petroleum=1}, + + colorize = "^[colorize:black:240", + post_effect_color = {a = 103, r = 80, g = 76, b = 90}, + + evap_chance = 0, +}) + + diff --git a/init.lua b/init.lua index e1ee16c..3b312e3 100644 --- a/init.lua +++ b/init.lua @@ -1,15 +1,108 @@ local modpath = minetest.get_modpath("bitumen") bitumen ={} + +-- first, to initialize the pipe API +dofile(modpath.."/pipes.lua") + + -- dofile(modpath.."/plastic.lua") --dofile(modpath.."/craftitems.lua") --dofile(modpath.."/containers.lua") ---dofile(modpath.."/pipes.lua") --dofile(modpath.."/pumping.lua") --dofile(modpath.."/tarsands.lua") +dofile(modpath.."/crude.lua") dofile(modpath.."/oilshale.lua") ---dofile(modpath.."/refinery.lua") +dofile(modpath.."/refinery.lua") +dofile(modpath.."/gasoline.lua") +minetest.register_node("bitumen:glass", { + description = "Glass", + drawtype = "glasslike_framed_optional", + tiles = {"default_glass.png", "default_glass_detail.png"}, + special_tiles = {"default_stone.png"}, + paramtype = "light", + paramtype2 = "glasslikeliquidlevel", + --param2 = 30; + sunlight_propagates = true, + use_texture_alpha = true, + is_ground_content = false, + groups = {cracky = 3, oddly_breakable_by_hand = 3}, + sounds = default.node_sound_glass_defaults(), + on_construct = function(pos) + --local n = minetest.get_node(pos) + --n.param2 = 32 + --minetest.set_node_level(pos, 32) + --minetest.swap_node(pos, {name = "bitumen:glass", param2 = 120}) + end, +}) + +local support = {} + +minetest.register_abm({ + nodenames = {"bitumen:glass"}, + interval = 1, + chance = 1, + action = function(pos) +-- minetest.set_node_level(pos, 30) + local sides = {} + local on = minetest.get_node(pos) + + local npos = { + {x=pos.x+1, y=pos.y, z=pos.z}, + {x=pos.x-1, y=pos.y, z=pos.z}, + {x=pos.x, y=pos.y, z=pos.z+1}, + {x=pos.x, y=pos.y, z=pos.z-1}, + } + + pos.y = pos.y - 1 + local ym = minetest.get_node(pos) + local sb = support[minetest.hash_node_position(pos)] + pos.y = pos.y + 1 + + + local hash = minetest.hash_node_position(pos) + + if ym.name == "air" then + local nb = {} + print("air below") + + for _,p in ipairs(npos) do + local n = minetest.get_node(p) + nb[n.name] = (nb[n.name] or 0) + 1 + end + + if (nb["air"] or 0) == 4 then + support[hash] = nil + minetest.spawn_falling_node(pos, on) + return + end + + if (nb["bitumen:glass"] or 0) > 0 then + for _,p in ipairs(npos) do + local s = support[minetest.hash_node_position(p)] + if s ~= nil then + print("found support: " .. s) + support[hash] = math.min(support[hash] or 999, s + 1) + end + end + end + + if support[hash] == nil or support[hash] > 4 then + support[hash] = nil + minetest.spawn_falling_node(pos, on) + return + end + + else + --print("setting support to 0") + support[hash] = sb or 0 + end + + --minetest.swap_node(pos, {name = "bitumen:glass", param2 = math.random(255)}) + end +}) + diff --git a/pipes.lua b/pipes.lua index a77e02f..d5ec75e 100644 --- a/pipes.lua +++ b/pipes.lua @@ -1,187 +1,566 @@ ---[[ - -most of this code is blatantly stolen from the technic wires system. -tiers represent the type of fluid in the pipe. pipes can change type -but machines cannot. the sources determines the type of fluid in a system. - - -]] +local networks = {} +local net_members = {} +local netname = 1 + +local mod_storage = minetest.get_mod_storage() + + + +networks = minetest.deserialize(mod_storage:get_string("networks")) or {} +net_members = minetest.deserialize(mod_storage:get_string("net_members")) or {} +netname = mod_storage:get_int("netname") or 1 + + +local function save_data() + --print("saving") + + mod_storage:set_string("networks", minetest.serialize(networks)) + mod_storage:set_string("net_members", minetest.serialize(net_members)) + mod_storage:set_int("netname", netname) +end + + +-- centralized network creation for consistency +local function new_network(pos) + local hash = minetest.hash_node_position(pos) + print("new network: hash: ".. hash .." name: " ..netname); + + networks[hash] = { + hash = hash, + pos = {x=pos.x, y=pos.y, z=pos.z}, + fluid = 'air', + name = netname, + count = 1, + inputs = { + [hash] = 1, + }, + outputs = {}, + buffer = 0, + in_pressure = -32000, + } + + net_members[hash] = hash + + netname = netname + 1 + + return networks[hash], hash +end + + +-- check nearby nodes for existing networks +local function check_merge(pos) + local hash = minetest.hash_node_position(pos) + + local merge_list = {} + local current_net = nil + local found_net = 0 + + local check_net = function(npos) + local nhash = minetest.hash_node_position(npos) + local nphash = net_members[nhash] + if nphash ~= nil then + local pnet = networks[nphash] + + if nil == current_net then + print("joining existing network: ".. pnet.name) + net_members[hash] = nphash + current_net = nphash + pnet.count = pnet.count + 1 + pnet.inputs[hash] = 1 + table.insert(merge_list, pnet) + elseif current_net == nphash then + print("alternate connection to existing network") + else + print("found seconday network: "..pnet.name) + table.insert(merge_list, pnet) + end + + found_net = 1 + end + end + + check_net({x=pos.x, y=pos.y - 1, z=pos.z}) + check_net({x=pos.x, y=pos.y + 1, z=pos.z}) + check_net({x=pos.x + 1, y=pos.y, z=pos.z}) + check_net({x=pos.x - 1, y=pos.y, z=pos.z}) + check_net({x=pos.x, y=pos.y, z=pos.z + 1}) + check_net({x=pos.x, y=pos.y, z=pos.z - 1}) + + return found_net, merge_list +end + +-- merge a list if networks, if the are multiple nets in the list +local function try_merge(merge_list) + if #merge_list > 1 then + print("\n merging "..#merge_list.." networks") + + local biggest = {count = 0} + local mlookup = {} + + for _,n in ipairs(merge_list) do + mlookup[n.hash] = 1 + if n.count > biggest.count then + biggest = n + end + end + + mlookup[biggest.hash] = 0 + + for k,v in pairs(net_members) do + if mlookup[v] == 1 then + net_members[k] = biggest.hash + end + end + + + for _,n in ipairs(merge_list) do + if n.hash ~= biggest.hash then + biggest.count = biggest.count + n.count + n.count = 0 + end + end + + end +end + + ---[[ very old code bitumen.pipes = {} - -function bitumen.register_pipe(tier, size) - local ltier = string.lower(tier) - - for x1 = 0, 1 do - for x2 = 0, 1 do - for y1 = 0, 1 do - for y2 = 0, 1 do - for z1 = 0, 1 do - for z2 = 0, 1 do - local id = bitumen.get_pipe_id({x1, x2, y1, y2, z1, z2}) - - bitumen.pipes["bitumen:"..ltier.."_pipe"..id] = tier - - local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2} - if id ~= 0 then - groups.not_in_creative_inventory = 1 - end - - minetest.register_node("bitumen:"..ltier.."_pipe"..id, { - description = tier.." Cable", - tiles = {"bitumen_"..ltier.."_pipe.png"}, - inventory_image = "bitumen_"..ltier.."_pipe_wield.png", - wield_image = "bitumen_"..ltier.."_pipe_wield.png", - groups = groups, - sounds = default.node_sound_wood_defaults(), - drop = "bitumen:"..ltier.."_pipe0", - paramtype = "light", - sunlight_propagates = true, - drawtype = "nodebox", - node_box = { - type = "fixed", - fixed = bitumen.gen_pipe_nodebox(x1, y1, z1, x2, y2, z2, size) - }, - after_place_node = function(pos) - local node = minetest.get_node(pos) - bitumen.update_pipes(pos, bitumen.get_pipe_tier(node.name)) - end, - after_dig_node = function(pos, oldnode) - local tier = bitumen.get_pipe_tier(oldnode.name) - bitumen.update_pipes(pos, tier, true) - end - }) - end - end - end - end - end - end -end - - -minetest.register_on_placenode(function(pos, node) - for tier, machine_list in pairs(bitumen.machines) do - for machine_name, _ in pairs(machine_list) do - if node.name == machine_name then - bitumen.update_pipes(pos, tier, true) - end - end - end -end) - - -minetest.register_on_dignode(function(pos, node) - for tier, machine_list in pairs(bitumen.machines) do - for machine_name, _ in pairs(machine_list) do - if node.name == machine_name then - bitumen.update_pipes(pos, tier, true) - end - end - end -end) - - -function bitumen.get_pipe_id(links) - return (links[6] * 1) + (links[5] * 2) - + (links[4] * 4) + (links[3] * 8) - + (links[2] * 16) + (links[1] * 32) -end - - - - -function bitumen.update_pipes(pos, tier, no_set, secondrun) - local link_positions = { - {x=pos.x+1, y=pos.y, z=pos.z}, - {x=pos.x-1, y=pos.y, z=pos.z}, - {x=pos.x, y=pos.y+1, z=pos.z}, - {x=pos.x, y=pos.y-1, z=pos.z}, - {x=pos.x, y=pos.y, z=pos.z+1}, - {x=pos.x, y=pos.y, z=pos.z-1}} - - local links = {0, 0, 0, 0, 0, 0} - - for i, link_pos in pairs(link_positions) do - local connect_type = bitumen.pipes_should_connect(pos, link_pos, tier) - if connect_type then - links[i] = 1 - -- Have pipes next to us update theirselves, - -- but only once. (We don't want to update the entire - -- network or start an infinite loop of updates) - if not secondrun and connect_type == "pipe" then - bitumen.update_pipes(link_pos, tier, false, true) - end - end - end - -- We don't want to set ourselves if we have been removed or we are - -- updating a machine - if not no_set then - minetest.set_node(pos, {name="bitumen:"..string.lower(tier) - .."_pipe"..bitumen.get_pipe_id(links)}) - - end -end - - -function bitumen.is_tier_pipe(name, tier) - return bitumen.pipes[name] and bitumen.pipes[name] == tier -end - - -function bitumen.get_pipe_tier(name) - return bitumen.pipes[name] -end - - -function bitumen.pipes_should_connect(pos1, pos2, tier) - local name = minetest.get_node(pos2).name - - if bitumen.is_tier_pipe(name, tier) then - return "pipe" - elseif bitumen.machines[tier][name] then - return "machine" - end - return false -end - - -function bitumen.gen_pipe_nodebox(x1, y1, z1, x2, y2, z2, size) - --rounded Nodeboxes +-- used by external machines to connect to a network in their on_construct callback +bitumen.pipes.on_construct = function(pos) + local found_net, merge_list = check_merge(pos) - local box_center = {-size, -size, -size, size, size, size} - local box_y1 = {-size, -size, -size, size, 0.5, size} -- y+ - local box_x1 = {-size, -size, -size, 0.5, size, size} -- x+ - local box_z1 = {-size, -size, size, size, size, 0.5} -- z+ - local box_z2 = {-size, -size, -0.5, size, size, size} -- z- - local box_y2 = {-size, -0.5, -size, size, size, size} -- y- - local box_x2 = {-0.5, -size, -size, size, size, size} -- x- - - local box = {box_center} - if x1 == 1 then - table.insert(box, box_x1) + if found_net == 0 then + local hash = minetest.hash_node_position(pos) + local net = new_network(pos) end - if y1 == 1 then - table.insert(box, box_y1) - end - if z1 == 1 then - table.insert(box, box_z1) - end - if x2 == 1 then - table.insert(box, box_x2) - end - if y2 == 1 then - table.insert(box, box_y2) - end - if z2 == 1 then - table.insert(box, box_z2) - end - return box + + try_merge(merge_list) + + save_data() end -]] + +-- used by external machines to find the network for a node +bitumen.pipes.get_net = function(pos) + local hash = minetest.hash_node_position(pos) + local phash = net_members[hash] + if phash == nil then + return nil, nil, hash + end + + return networks[phash], phash, hash +end + + +-- used by external machines to add fluid into the pipe network +bitumen.pipes.push_fluid = function(pos, fluid, amount, extra_pressure) + local hash = minetest.hash_node_position(pos) + + local phash = net_members[hash] + if phash == nil then + return 0 -- no network + end + local pnet = networks[phash] + + if pnet.fluid == 'air' or pnet.buffer == 0 then + if minetest.registered_nodes[fluid].groups.petroleum ~= nil then + -- BUG: check for "full" nodes + pnet.fluid = fluid + else + return 0 -- no available liquids + end + else -- only suck in existing fluid + if fluid ~= pnet.fluid and fluid ~= pnet.fluid.."_full" then + --print("no water near intake") + return 0 + end + end + + if amount < 1 then + print("!!!!!!!!!!!! push amount less than one?") + return 0 + end + + local input_pres = pos.y + extra_pressure + + pnet.in_pressure = pnet.in_pressure or -32000 + + if pnet.in_pressure > input_pres then + print("backflow at intake: " .. pnet.in_pressure.. " > " ..input_pres ) + return 0 + end + + pnet.in_pressure = math.max(pnet.in_pressure, input_pres) + + local rate = amount --math.max(1, math.ceil(ulevel / 2)) + + local cap = 64 + local take = math.max(0, math.min(amount, cap - pnet.buffer)) + pnet.buffer = pnet.buffer + take + + return take +end + + + +minetest.register_node("bitumen:intake", { + description = "Intake", + drawtype = "nodebox", + node_box = { + type = "connected", + fixed = {{-.1, -.1, -.1, .1, .1, .1}}, + -- connect_bottom = + connect_front = {{-.1, -.1, -.5, .1, .1, .1}}, + connect_left = {{-.5, -.1, -.1, -.1, .1, .1}}, + connect_back = {{-.1, -.1, .1, .1, .1, .5}}, + connect_right = {{ .1, -.1, -.1, .5, .1, .1}}, + connect_bottom = {{ -.1, -.5, -.1, .1, .1, .1}}, + }, + connects_to = { "group:petroleum_pipe", "group:petroleum_fixture"}, + paramtype = "light", + is_ground_content = false, + tiles = { "default_tin_block.png" }, + walkable = true, + groups = { cracky = 3, petroleum_fixture = 1, }, + on_construct = function(pos) + print("\nintake placed at "..pos.x..","..pos.y..","..pos.z) + + local found_net, merge_list = check_merge(pos) + + if found_net == 0 then + local hash = minetest.hash_node_position(pos) + local net = new_network(pos) + net.in_pressure = pos.z + net.inputs[hash] = 1 + end + + try_merge(merge_list) + + save_data() + + end + +}) + + +minetest.register_abm({ + nodenames = {"bitumen:intake"}, + neighbors = {"group:petroleum"}, + interval = 1, + chance = 1, + action = function(pos) + local hash = minetest.hash_node_position(pos) + + pos.y = pos.y + 1 + local unode = minetest.get_node(pos) + + local phash = net_members[hash] + local pnet = networks[phash] + + if pnet.fluid == 'air' or pnet.buffer == 0 then + if minetest.registered_nodes[unode.name].groups.petroleum ~= nil then + -- BUG: check for "full" nodes + pnet.fluid = unode.name + else + return -- no available liquids + end + else -- only suck in existing fluid + if unode.name ~= pnet.fluid and unode.name ~= pnet.fluid.."_full" then + --print("no water near intake") + return + end + end + + local ulevel = minetest.get_node_level(pos) + if ulevel < 1 then + print("!!!!!!!!!!!! intake level less than one?") + return + end + + pnet.in_pressure = pnet.in_pressure or -32000 + + if pnet.in_pressure > pos.y - 1 then + print("backflow at intake: " .. pnet.in_pressure.. " > " ..(pos.y - 1) ) + return + end + + pnet.in_pressure = math.max(pnet.in_pressure, pos.y - 1) + + local rate = math.max(1, math.ceil(ulevel / 2)) + + local cap = 64 + local take = math.max(0, math.min(ulevel, cap - pnet.buffer)) + pnet.buffer = pnet.buffer + take + --print("intake took "..take.. " water") + if ulevel - rate > 0 then + minetest.set_node_level(pos, ulevel - take) + else + minetest.set_node(pos, {name = "air"}) + end + end +}) + + + +minetest.register_node("bitumen:spout", { + description = "Spout", + drawtype = "nodebox", + node_box = { + type = "connected", + fixed = {{-.1, -.1, -.1, .1, .1, .1}}, + -- connect_bottom = + connect_front = {{-.1, -.1, -.5, .1, .1, .1}}, + connect_left = {{-.5, -.1, -.1, -.1, .1, .1}}, + connect_back = {{-.1, -.1, .1, .1, .1, .5}}, + connect_right = {{ .1, -.1, -.1, .5, .1, .1}}, + connect_top = {{ -.1, -.1, -.1, .1, .5, .1}}, + }, + connects_to = { "group:petroleum_pipe", "group:petroleum_fixture" }, + paramtype = "light", + is_ground_content = false, + tiles = { "default_copper_block.png" }, + walkable = true, + groups = { cracky = 3, petroleum_fixture = 1, }, + on_construct = function(pos) + print("\nspout placed at "..pos.x..","..pos.y..","..pos.z) + + local found_net, merge_list = check_merge(pos) + + if found_net == 0 then + local hash = minetest.hash_node_position(pos) + local pnet = new_network(pos) + pnet.outputs[hash] = 1 + end + + try_merge(merge_list) + + save_data() + end + +}) + + +minetest.register_abm({ + nodenames = {"bitumen:spout"}, +-- neighbors = {"group:fresh_water"}, + interval = 1, + chance = 1, + action = function(pos) + local hash = minetest.hash_node_position(pos) + local phash = net_members[hash] + local pnet = networks[phash] + + if pnet.buffer <= 0 then + --print("spout: no water in pipe") + return -- no water in the pipe + end + + -- hack + pnet.in_pressure = pnet.in_pressure or -32000 + + if pnet.in_pressure <= pos.y then + print("insufficient pressure at spout: ".. pnet.in_pressure .. " < " ..pos.y ) + return + end + + + pos.y = pos.y - 1 + + local bnode = minetest.get_node(pos) + local avail = 10 -- pnet.buffer / #pnet.outputs + if bnode.name == pnet.fluid then + local blevel = minetest.get_node_level(pos) + local cap = 64 - blevel + local out = math.min(cap, math.min(avail, cap)) + --print("cap: ".. cap .." avail: ".. avail .. " out: "..out) + pnet.buffer = pnet.buffer - out + minetest.set_node_level(pos, blevel + out) + elseif bnode.name == "air" then + local out = math.min(64, math.max(0, avail)) + pnet.buffer = pnet.buffer - out + minetest.set_node(pos, {name = pnet.fluid}) + minetest.set_node_level(pos, out) + end + + + end +}) + + +local function pnet_for(pos) + local hash = minetest.hash_node_position(pos) + local ph = net_members[hash] + if ph == nil then + return nil, hash + end + + return networks[ph], hash +end + +local function walk_net(opos) + local members = {} + local count = 0 + + local opnet = pnet_for(pos) + if opnet == nil then + return nil, 0, nil + end + + local stack = {} + table.insert(stack, opos) + + + while #stack > 0 do + + local pos = table.remove(stack) + local pnet, hash = pnet_for(pos) + if pnet ~= nil and members[hash] == nil then + + if pnet.name == opnet.name then + members[hash] = pos + count = count + 1 + + table.insert(stack, {x=pos.x-1, y=pos.y, z=pos.z}) + table.insert(stack, {x=pos.x+1, y=pos.y, z=pos.z}) + table.insert(stack, {x=pos.x, y=pos.y-1, z=pos.z}) + table.insert(stack, {x=pos.x, y=pos.y+1, z=pos.z}) + table.insert(stack, {x=pos.x, y=pos.y, z=pos.z-1}) + table.insert(stack, {x=pos.x, y=pos.y, z=pos.z+1}) + end + end + end + + return members, count, opnet +end + + + +minetest.register_node("bitumen:pipe", { + description = "water pipe", + drawtype = "nodebox", + node_box = { + type = "connected", + fixed = {{-.1, -.1, -.1, .1, .1, .1}}, + -- connect_bottom = + connect_front = {{-.1, -.1, -.5, .1, .1, .1}}, + connect_left = {{-.5, -.1, -.1, -.1, .1, .1}}, + connect_back = {{-.1, -.1, .1, .1, .1, .5}}, + connect_right = {{ .1, -.1, -.1, .5, .1, .1}}, + connect_top = {{ -.1, -.1, -.1, .1, .5, .1}}, + connect_bottom = {{ -.1, -.5, -.1, .1, .1, .1}}, + }, + connects_to = { "group:petroleum_pipe", "group:petroleum_fixture" }, + paramtype = "light", + is_ground_content = false, + tiles = { "default_steel_block.png" }, + walkable = true, + groups = { cracky = 3, petroleum_pipe = 1, }, + + on_construct = function(pos) + print("\npipe placed at "..pos.x..","..pos.y..","..pos.z) + + local found_net, merge_list = check_merge(pos) + + if found_net == 0 then + local net = new_network(pos) + end + + try_merge(merge_list) + + save_data() + end, + + after_destruct = function(pos) + -- see if we need to split the network + + local hash = minetest.hash_node_position(pos) + if hash == nil then + print("wtf: after_destruct pipe hash has no network") + return + end + + + local phash = net_members[hash] + local pnet = networks[phash] + if pnet == nil then + print("wtf: no network in after_destruct for pipe") + return + end + + -- remove this node from the network + net_members[hash] = nil + + + local check_pos = { + {x=pos.x+1, y=pos.y, z=pos.z}, + {x=pos.x-1, y=pos.y, z=pos.z}, + {x=pos.x, y=pos.y+1, z=pos.z}, + {x=pos.x, y=pos.y-1, z=pos.z}, + {x=pos.x, y=pos.y, z=pos.z+1}, + {x=pos.x, y=pos.y, z=pos.z-1}, + } + + local stack = {} + local found = 0 + for _,p in ipairs(check_pos) do + local h = minetest.hash_node_position(p) + + local lphash = net_members[h] + if lphash ~= nil then + local lpnet = networks[lphash] + if lpnet and lpnet.name == pnet.name then + stack[h] = p + found = found + 1 + print("check stack: "..p.x..","..p.y..","..p.z) + else + print("no lpnet") + end + else + print("no lphash "..p.x..","..p.y..","..p.z) + end + end + + if found > 1 then + print("check to split the network") + for h,p in pairs(stack) do + + -- BUG: spouts and intakes can be counted as pipes when walking the network + --local net, cnt, lpnet = walk_net(p) + + -- just rename the net + end + + end + + end, + +}) + + +minetest.register_craft({ + output = "bitumen:pipe 3", + recipe = { + {"default:steel_ingot", "", "default:steel_ingot"}, + {"default:steel_ingot", "", "default:steel_ingot"}, + {"default:steel_ingot", "", "default:steel_ingot"}, + } +}) + +minetest.register_craft({ + output = "bitumen:intake 1", + type = "shapeless", + recipe = {"bitumen:pipe", "default:tin_ingot"}, +}) + +minetest.register_craft({ + output = "bitumen:spout 1", + type = "shapeless", + recipe = {"bitumen:pipe", "default:copper_ingot"}, +}) + + diff --git a/refinery.lua b/refinery.lua index 13bc946..521c0a0 100644 --- a/refinery.lua +++ b/refinery.lua @@ -32,9 +32,9 @@ local extractor_formspec = --need pipeworks integration -minetest.register_node("bitumen:cracking_column", { +minetest.register_node("bitumen:distillation_column", { paramtype = "light", - description = "Cracking Column Segment", + description = "Distillation Column Segment", tiles = {"bitumen_cracking_column.png", "bitumen_cracking_column.png", "bitumen_cracking_column.png", "bitumen_cracking_column.png", "bitumen_cracking_column.png", "bitumen_cracking_column.png"}, node_box = { @@ -60,69 +60,143 @@ minetest.register_node("bitumen:cracking_column", { }, }, drawtype = "nodebox", - groups = {cracky=3,oddly_breakable_by_hand=3}, + groups = {cracky=3,oddly_breakable_by_hand=3 }, legacy_facedir_simple = true, sounds = default.node_sound_wood_defaults(), on_construct = function(pos) - local meta = minetest.get_meta(pos) - local inv = meta:get_inventory() - inv:set_size("dst", 1) + end, }) -bitumen.cracking_stack = { - "lube_oil", - "fuel_oil", +minetest.register_node("bitumen:distillation_column_outlet", { + paramtype = "light", + description = "Distillation Column Outlet", + tiles = {"bitumen_cracking_column.png", "bitumen_cracking_column_outlet.png", "bitumen_cracking_column_outlet.png", + "bitumen_cracking_column_outlet.png", "bitumen_cracking_column_outlet.png", "bitumen_cracking_column.png"}, + node_box = { + type = "fixed", + fixed = { + --11.25 + {-0.49, -0.5, -0.10, 0.49, 0.5, 0.10}, + {-0.10, -0.5, -0.49, 0.10, 0.5, 0.49}, + --22.5 + {-0.46, -0.5, -0.19, 0.46, 0.5, 0.19}, + {-0.19, -0.5, -0.46, 0.19, 0.5, 0.46}, + -- 33.75 + {-0.416, -0.5, -0.28, 0.416, 0.5, 0.28}, + {-0.28, -0.5, -0.416, 0.28, 0.5, 0.416}, + --45 + {-0.35, -0.5, -0.35, 0.35, 0.5, 0.35}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + }, + }, + drawtype = "nodebox", + groups = {cracky=3,oddly_breakable_by_hand=3, petroleum_fixture=1}, + legacy_facedir_simple = true, + sounds = default.node_sound_wood_defaults(), + on_construct = function(pos) + -- connect to the pipe network + bitumen.pipes.on_construct(pos) + end, +}) + +bitumen.distillation_stack = { + "tar", + "heavy_oil", + "light_oil", "diesel", + "kerosene", "gasoline", - "jet_fuel", - "lpg", + "mineral_spirits", +-- "lpg", } -local function check_cracking_stack(pos) +local function check_stack(pos) local ret = { } + local oh = pos.y pos.y = pos.y + 1 - local height = 1 + local height = 0 local n - while minetest.get_node(pos).name == "bitumen:cracking_column" and height < 7 do - ret[bitumen.cracking_stack[height]] = pos - print("Found stack "..bitumen.cracking_stack[height].." at ".. height) - height = height+1 + while height < 8*2 do + if minetest.get_node(pos).name == "bitumen:distillation_column" then + -- noop + elseif minetest.get_node(pos).name == "bitumen:distillation_column_outlet" then + height = height+1 + local t = bitumen.distillation_stack[height] + + ret[t] = {x=pos.x, y=pos.y, z=pos.z} + + print(t.." at ".. (pos.y).. " - " .. height) + else + -- end of the stack + break + end pos.y = pos.y+1 end return ret end -minetest.register_node("bitumen:cracking_boiler", { - description = "Cracking Column Boiler", - tiles = {"technic_lv_grinder_top.png", "technic_lv_grinder_bottom.png", "technic_lv_grinder_side.png", - "technic_lv_grinder_side.png", "technic_lv_grinder_side.png", "technic_lv_grinder_front.png"}, + +local function dcb_node_timer(pos, elapsed) + + + +end + + +minetest.register_node("bitumen:distillation_column_boiler", { + description = "Distillation Column Boiler", + tiles = {"default_steel_block.png", "default_steel_block.png", "default_steel_block.png", + "default_steel_block.png", "default_steel_block.png", "default_steel_block.png"}, paramtype2 = "facedir", - groups = {cracky=2}, - legacy_facedir_simple = true, + groups = {cracky=2, petroleum_fixture=1}, sounds = default.node_sound_wood_defaults(), + can_dig = function(pos,player) + return true + end, + + on_timer = dcb_node_timer, on_construct = function(pos) local meta = minetest.get_meta(pos) - meta:set_string("infotext", "Extractor") - meta:set_string("formspec", extractor_formspec) + meta:set_string("infotext", "Boiler") + meta:set_string("formspec", "") local inv = meta:get_inventory() - inv:set_size("src", 4) - end, - can_dig = function(pos,player) - local meta = minetest.get_meta(pos); - local inv = meta:get_inventory() - if not inv:is_empty("src") then - minetest.chat_send_player(player:get_player_name(), - "Machine cannot be removed because it is not empty"); - return false - else - return true - end + inv:set_size('fuel', 6) + + -- connect to the pipe network + bitumen.pipes.on_construct(pos) + + print("constructed") + minetest.get_node_timer(pos):start(1.0) + end, + }) +--temp hack for dev +minetest.register_abm({ + nodenames = {"bitumen:distillation_column_boiler"}, + interval = 3, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local stack = check_stack(pos) + + for fluid,p in pairs(stack) do + print("pushing "..fluid.." at "..p.y) + bitumen.pipes.push_fluid(p, "bitumen:"..fluid, 10, 10) + end + + + end +}) +--[[ minetest.register_node("bitumen:cracking_boiler_active", { description = "Cracking Column Boiler", tiles = {"technic_lv_grinder_top.png", "technic_lv_grinder_bottom.png", @@ -144,8 +218,20 @@ minetest.register_node("bitumen:cracking_boiler_active", { end end, }) - +]] +-- must add up to 100 +bitumen.distillation_yield = { + tar = 20, + heavy_oil = 20, + light_oil = 10, + diesel = 20, + kerosene = 15, + gasoline = 10, + mineral_spirits = 5, +} + + @@ -170,6 +256,8 @@ bitumen.energy_density = { lube_oil = { 12 }, synth_crude = { 10 } } + + --temp hack for dev minetest.register_abm({ nodenames = {"bitumen:cracking_boiler", "bitumen:cracking_boiler_active"}, diff --git a/textures/bitumen_cracking_column_outlet.png b/textures/bitumen_cracking_column_outlet.png new file mode 100644 index 0000000..08be500 Binary files /dev/null and b/textures/bitumen_cracking_column_outlet.png differ