elepower/elepower_machines/machines/pump.lua

280 lines
7.2 KiB
Lua

local c_air = minetest.get_content_id("air")
local function get_formspec(power, fluid, state, level)
if not level then level = 0 end
return "size[8,8.5]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
ele.formspec.state_switcher(7, 2.5, state)..
ele.formspec.power_meter(power)..
ele.formspec.fluid_bar(7, 0, fluid)..
"label[1,0;Pump level: "..level.."]"..
"list[current_player;main;0,4.25;8,1;]"..
"list[current_player;main;0,5.5;8,3;8]"..
default.get_hotbar_bg(0, 4.25)
end
-- Dig a node in a certain radius on the same Y level
local function dig_node_leveled_radius(pos, radius, node)
local c_node = minetest.get_content_id(node)
local startp = vector.subtract(pos, {x=radius,y=0,z=radius})
local endp = vector.add(pos, {x=radius,y=0,z=radius})
local manip = minetest.get_voxel_manip()
local e1, e2 = manip:read_from_map(startp, endp)
local area = VoxelArea:new{MinEdge=e1, MaxEdge=e2}
local data = manip:get_data()
local dug = false
for i in area:iter(
startp.x, startp.y, startp.z,
endp.x, endp.y, endp.z
) do
if data[i] == c_node then
data[i] = c_air
dug = true
break
end
end
if dug then
manip:set_data(data)
manip:write_to_map()
end
return dug
end
local function timer(pos, elapsed)
local refresh = false
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local machine_node = "elepower_machines:pump"
local machine_def = minetest.registered_nodes[machine_node]
local capacity = ele.helpers.get_node_property(meta, pos, "capacity")
local usage = ele.helpers.get_node_property(meta, pos, "usage")
local storage = ele.helpers.get_node_property(meta, pos, "storage")
local state = meta:get_int("state")
local comps = meta:get_string("components")
local status = "Idle"
local is_enabled = ele.helpers.state_enabled(meta, pos, state)
local res_time = 0
local pow_buffer = {capacity = capacity, storage = storage, usage = 0}
local fl_buffer = fluid_lib.get_buffer_data(pos, "pump")
-- Pump level
local plevel = meta:get_int("level")
local pliquid = meta:get_string("liquid")
if plevel == 0 then plevel = -1 end
local ppos = vector.add(pos, {x=0,y=plevel,z=0})
local heavy = comps:match("elepower_machines:heavy_filter") ~= nil
while true do
if not is_enabled then
status = "Off"
break
end
if pow_buffer.storage < usage then
status = "Out of Power!"
break
end
local dig_node = pliquid
local amount = 1000
if pliquid == "elepower_nuclear:heavy_water_source" and heavy then
dig_node = "default:water_source"
amount = 200
end
if fl_buffer.amount + amount > fl_buffer.capacity then
status = "Tank Full!"
break
end
if pliquid == "" then
local node = minetest.get_node_or_nil(ppos)
if not node or node.name == "air" or (bucket.liquids[node.name] and bucket.liquids[node.name].flowing == node.name) then
plevel = plevel - 1
status = "Seeking"
refresh = true
if plevel < -16 then
plevel = -1
end
break
end
-- Valid liquid, proceed pumping
if bucket.liquids[node.name] and bucket.liquids[node.name].source == node.name then
if node.name == "default:water_source" and heavy then
node.name = "elepower_nuclear:heavy_water_source"
end
pliquid = node.name
refresh = true
else
-- Run into a non-liquid node, stop the timer
refresh = false
end
break
end
if pliquid ~= "" then
-- Filter was installed
if pliquid == "default:water_source" and heavy and fl_buffer.amount > 0 then
pliquid = "elepower_nuclear:heavy_water_source"
fl_buffer.amount = 0
refresh = true
break
end
-- We are looking for `fl_buffer.fluid` on Y level `plevel`
-- If we find a fluid node, we dig it, and add it to the buffer's storage
-- If we don't find a fluid node, we go a level down
local dug = dig_node_leveled_radius(ppos, 16, dig_node)
if not dug then
local node = minetest.get_node_or_nil(ppos)
if node.name == "default:water_source" and heavy then
node.name = "elepower_nuclear:heavy_water_source"
end
if not node or (node.name ~= pliquid and node.name ~= "air") then
status = "No More Fluid!"
refresh = false
break
end
plevel = plevel - 1
refresh = true
if plevel < -16 then
plevel = -1
end
break
else
fl_buffer.amount = fl_buffer.amount + amount
pow_buffer.usage = usage
pow_buffer.storage = pow_buffer.storage - usage
status = "Pumping"
refresh = true
end
end
break
end
fl_buffer.fluid = pliquid
-- Spawn tube entities
if status == "Pumping" or status == "Seeking" then
for i = 1, math.abs(plevel) do
local tentpos = vector.subtract(pos, {x=0,y=i,z=0})
local skip = false
for i, ob in pairs(minetest.get_objects_inside_radius(tentpos, 0.5)) do
if ob:get_luaentity() and ob:get_luaentity().name == "elepower_machines:pump_tube" then
skip = true
break
end
end
if not skip then
local e = minetest.add_entity(tentpos, "elepower_machines:pump_tube")
local ent = e:get_luaentity()
ent.pump = pos
ent.level = i * -1
end
end
end
meta:set_string("formspec", get_formspec(pow_buffer, fl_buffer, state, plevel))
meta:set_string("infotext", ("%s %s"):format(machine_def.description, status) ..
"\n" .. ele.capacity_text(capacity, storage))
meta:set_int("storage", pow_buffer.storage)
meta:set_int("level", plevel)
meta:set_string("liquid", pliquid)
meta:set_int("pump_fluid_storage", fl_buffer.amount)
meta:set_string("pump_fluid", fl_buffer.fluid)
return refresh
end
ele.register_machine("elepower_machines:pump", {
description = "Pump",
tiles = {
"elepower_machine_top.png^elepower_power_port.png", "elepower_machine_base.png^elepower_pump_base.png",
"elepower_machine_side.png^elepower_pump_side.png",
"elepower_machine_side.png^elepower_pump_side.png", "elepower_machine_side.png^elepower_pump_side.png",
"elepower_machine_side.png^elepower_pump_side.png",
},
groups = {
ele_machine = 1,
ele_user = 1,
fluid_container = 1,
oddly_breakable_by_hand = 1,
},
ele_no_automatic_ports = true,
fluid_buffers = {
pump = {
capacity = 16000,
drainable = true,
},
},
on_timer = timer,
on_construct = function (pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", get_formspec(nil, nil, 0, -1))
end,
-- Upgradable
ele_upgrades = {
pump_filter = {},
capacitor = {"capacity"},
},
})
minetest.register_entity("elepower_machines:pump_tube", {
initial_properties = {
hp_max = 1,
visual = "mesh",
mesh = "elepower_pump_tube.obj",
physical = false,
textures = {"elepower_pump_tube.png"}
},
timer = 0,
pump = {x=0,y=0,z=0},
level = 0,
on_step = function (self, dt)
self.timer = self.timer + 1
if self.timer < 50 then
return self
end
self.timer = 0
-- Check for pump
local pump = minetest.get_node_or_nil(self.pump)
if not pump or pump.name ~= "elepower_machines:pump" then
-- Delete self if pump wasn't found
self.object:remove()
return self
else
-- Delete self if pump's discovery level is above tube's level
local meta = minetest.get_meta(self.pump)
local pl = meta:get_int("level")
if pl > self.level then
self.object:remove()
return self
end
end
end
})