diff --git a/elepower_dynamics/textures/elepower_electrum_ingot.png b/elepower_dynamics/textures/elepower_electrum_ingot.png index 851efbb..539706d 100644 Binary files a/elepower_dynamics/textures/elepower_electrum_ingot.png and b/elepower_dynamics/textures/elepower_electrum_ingot.png differ diff --git a/elepower_machines/crafting.lua b/elepower_machines/crafting.lua index 3c07a62..f18f711 100644 --- a/elepower_machines/crafting.lua +++ b/elepower_machines/crafting.lua @@ -47,6 +47,10 @@ local alloy_recipes = { output = "basic_materials:brass_ingot 3", time = 8, }, + { + recipe = { "default:bronze_ingot", "default:steel_ingot 4" }, + output = "elepower_machines:heat_casing 4", + }, } -- Register alloy furnace recipes @@ -687,10 +691,10 @@ minetest.register_craft({ -- Advanced Machine Block minetest.register_craft({ - output = "elepower_machines:advanced_machine_block 8", + output = "elepower_machines:advanced_machine_block 4", recipe = { {"elepower_dynamics:electrum_plate", "elepower_dynamics:induction_coil_advanced", "elepower_dynamics:electrum_plate"}, - {"elepower_dynamics:brass_plate", "elepower_machines:machine_block", "elepower_dynamics:brass_plate"}, + {"elepower_dynamics:brass_plate", "elepower_machines:heat_casing", "elepower_dynamics:brass_plate"}, {"elepower_dynamics:electrum_plate", "elepower_dynamics:induction_coil_advanced", "elepower_dynamics:electrum_plate"}, } }) diff --git a/elepower_machines/nodes.lua b/elepower_machines/nodes.lua index 0903d0b..01af5c2 100644 --- a/elepower_machines/nodes.lua +++ b/elepower_machines/nodes.lua @@ -6,8 +6,14 @@ minetest.register_node("elepower_machines:machine_block", { groups = {oddly_breakable_by_hand = 1, cracky = 1}, }) +minetest.register_node("elepower_machines:heat_casing", { + description = "Heat Casing", + tiles = {"elepower_heat_casing.png"}, + groups = {cracky = 3, ele_evaporator_node = 1}, +}) + minetest.register_node("elepower_machines:advanced_machine_block", { description = "Advanced Machine Block\nSafe for decoration", tiles = {"elepower_advblock_combined.png"}, - groups = {oddly_breakable_by_hand = 1, cracky = 1}, + groups = {cracky = 3}, }) diff --git a/elepower_machines/textures/elepower_heat_casing.png b/elepower_machines/textures/elepower_heat_casing.png new file mode 100644 index 0000000..772c052 Binary files /dev/null and b/elepower_machines/textures/elepower_heat_casing.png differ diff --git a/elepower_nuclear/fluids.lua b/elepower_nuclear/fluids.lua index 54bf606..d2213bf 100644 --- a/elepower_nuclear/fluids.lua +++ b/elepower_nuclear/fluids.lua @@ -107,19 +107,6 @@ ele.helpers.register_liquid("hot_coolant", { groups = {liquid = 3, coolant = 1, hot = 1}, }) --- Brine - -ele.helpers.register_liquid("brine", { - description = "Brine", - drawtype = "liquid", - tiles = {"elenuclear_brine.png"}, - special_tiles = {"elenuclear_brine.png", "elenuclear_brine.png"}, - alpha = 240, - liquid_viscosity = 7, - post_effect_color = {a = 200, r = 215, g = 221, b = 187}, - groups = {brine = 3, saline = 1, liquid = 3, puts_out_fire = 1, cools_lava = 1}, -}) - -- Corium ele.helpers.register_liquid("corium", { @@ -175,9 +162,6 @@ if minetest.get_modpath("bucket") ~= nil then bucket.register_liquid("elepower_nuclear:heavy_water_source", "elepower_nuclear:heavy_water_flowing", "elepower_nuclear:bucket_heavy_water", "#0d4579", "Heavy Water Bucket") - bucket.register_liquid("elepower_nuclear:brine_source", "elepower_nuclear:brine_flowing", - "elepower_nuclear:bucket_heavy_water", "#d7ddbb", "Brine Bucket") - fluid_tanks.register_tank(":elepower_dynamics:portable_tank", { description = "Portable Tank", capacity = 8000, diff --git a/elepower_nuclear/machines/fusion_reactor.lua b/elepower_nuclear/machines/fusion_reactor.lua index 8f757f5..7e2c5ee 100644 --- a/elepower_nuclear/machines/fusion_reactor.lua +++ b/elepower_nuclear/machines/fusion_reactor.lua @@ -454,7 +454,7 @@ minetest.register_node("elepower_nuclear:reactor_fluid", { node_io_accepts_millibuckets = function(pos, node, side) return true end, node_io_put_liquid = function(pos, node, side, putter, liquid, millibuckets) local ctrl, ctrl_meta = get_port_controller(pos) - if not ctrl then return nil end + if not ctrl then return millibuckets end local buffers = fluid_lib.get_node_buffers(ctrl) local leftovers = 0 @@ -468,7 +468,7 @@ minetest.register_node("elepower_nuclear:reactor_fluid", { end, node_io_room_for_liquid = function(pos, node, side, liquid, millibuckets) local ctrl, ctrl_meta = get_port_controller(pos) - if not ctrl then return nil end + if not ctrl then return 0 end local buffers = fluid_lib.get_node_buffers(ctrl) local insertable = 0 diff --git a/elepower_thermal/crafting.lua b/elepower_thermal/crafting.lua new file mode 100644 index 0000000..6a47a5c --- /dev/null +++ b/elepower_thermal/crafting.lua @@ -0,0 +1,30 @@ + +-- Thermal Evaporator Controller +minetest.register_craft({ + output = "elepower_thermal:evaporator_controller", + recipe = { + {"elepower_dynamics:electrum_plate", "elepower_dynamics:bronze_plate", "elepower_dynamics:electrum_plate"}, + {"elepower_dynamics:portable_tank", "elepower_machines:heat_casing", "elepower_dynamics:portable_tank"}, + {"elepower_dynamics:brass_plate", "elepower_dynamics:lcd_panel", "elepower_dynamics:brass_plate"}, + } +}) + +-- Thermal Evaporator Fluid Port +minetest.register_craft({ + output = "elepower_thermal:evaporator_input", + recipe = { + {"elepower_dynamics:electrum_plate", "elepower_dynamics:bronze_plate", "elepower_dynamics:electrum_plate"}, + {"fluid_transfer:fluid_duct", "elepower_machines:heat_casing", "elepower_dynamics:servo_valve"}, + {"elepower_dynamics:brass_plate", "elepower_dynamics:steel_plate", "elepower_dynamics:brass_plate"}, + } +}) + +-- Thermal Evaporator Fluid Port (Output) +minetest.register_craft({ + output = "elepower_thermal:evaporator_output", + recipe = { + {"elepower_dynamics:electrum_plate", "elepower_dynamics:bronze_plate", "elepower_dynamics:electrum_plate"}, + {"elepower_dynamics:servo_valve", "elepower_machines:heat_casing", "fluid_transfer:fluid_duct"}, + {"elepower_dynamics:brass_plate", "elepower_dynamics:steel_plate", "elepower_dynamics:brass_plate"}, + } +}) diff --git a/elepower_thermal/depends.txt b/elepower_thermal/depends.txt new file mode 100644 index 0000000..7541380 --- /dev/null +++ b/elepower_thermal/depends.txt @@ -0,0 +1,3 @@ +elepower_papi +elepower_dynamics +elepower_machines diff --git a/elepower_thermal/fluids.lua b/elepower_thermal/fluids.lua new file mode 100644 index 0000000..a043492 --- /dev/null +++ b/elepower_thermal/fluids.lua @@ -0,0 +1,27 @@ + +-- Brine + +ele.helpers.register_liquid("brine", { + description = "Brine", + drawtype = "liquid", + tiles = {"elenuclear_brine.png"}, + special_tiles = {"elenuclear_brine.png", "elenuclear_brine.png"}, + alpha = 240, + liquid_viscosity = 7, + post_effect_color = {a = 200, r = 215, g = 221, b = 187}, + groups = {brine = 3, saline = 1, liquid = 3, puts_out_fire = 1, cools_lava = 1}, +}) + +if minetest.get_modpath("bucket") ~= nil then + bucket.register_liquid("elepower_thermal:brine_source", "elepower_thermal:brine_flowing", + "elepower_thermal:bucket_heavy_water", "#d7ddbb", "Brine Bucket") + + fluid_tanks.register_tank(":elepower_dynamics:portable_tank", { + description = "Portable Tank", + capacity = 8000, + accepts = true, + tiles = { + "elepower_tank_base.png", "elepower_tank_side.png", "elepower_tank_base.png^elepower_power_port.png", + } + }) +end diff --git a/elepower_thermal/init.lua b/elepower_thermal/init.lua new file mode 100644 index 0000000..4632697 --- /dev/null +++ b/elepower_thermal/init.lua @@ -0,0 +1,11 @@ +-- An Elepower Mod +-- Copyright 2018 Evert "Diamond" Prants + +local modpath = minetest.get_modpath(minetest.get_current_modname()) + +elethermal = rawget(_G, "elethermal") or {} +elethermal.modpath = modpath + +dofile(modpath.."/machines/init.lua") +dofile(modpath.."/fluids.lua") +dofile(modpath.."/crafting.lua") diff --git a/elepower_thermal/machines/evaporation_plant.lua b/elepower_thermal/machines/evaporation_plant.lua new file mode 100644 index 0000000..76ffc90 --- /dev/null +++ b/elepower_thermal/machines/evaporation_plant.lua @@ -0,0 +1,405 @@ +-- Thermal Evaporation Plant +-- Used to extract salt from water +elethermal.cache = {} +local results = { + { + input = "default:water_source 1000", + output = "elepower_thermal:brine_source 100", + heat = 200 + }, + { + input = "elepower_thermal:brine_source 1000", + output = "elepower_dynamics:lithium_source 100", + heat = 200 + } +} + +-- Validate evaporator structure from controller position +local function validate_structure(pos, player) + local inputs = {} + local outputs = {} + local all = {} + local thermal = 0 + local height = 0 + local height_cancel = false + + local node = minetest.get_node(pos) + local dir = minetest.facedir_to_dir(node.param2) + + for y = 0, 18 do + if height_cancel then break end + y = y - 4 + local i = 0 + for x = 0, 3 do + x = x - 3 + for z = 0, 3 do + z = z - 2 + local rx = x + local rz = z + if dir.z ~= 0 then + rx = z * -dir.z + rz = x * -dir.z + else + rx = rx * -dir.x + rz = rz * -dir.x + end + + local p = vector.add(pos, {x = rx, y = y, z = rz}) + local n = minetest.get_node(p) + + if n.name == "elepower_thermal:evaporator_controller" and not vector.equals(pos, p) then + height = 0 + if player then minetest.chat_send_player(player, "Multiple controllers detected.") end + break + end + + if minetest.get_item_group(n.name, "ele_evaporator_node") > 0 then + i = i + 1 + elseif minetest.get_item_group(n.name, "ele_solar_generator") > 0 then + i = i + 1 + local m = minetest.get_meta(p) + local generation = ele.helpers.get_node_property(m, p, "usage") + thermal = thermal + generation + height_cancel = true + end + + if n.name == "elepower_thermal:evaporator_output" then + table.insert(outputs, p) + elseif n.name == "elepower_thermal:evaporator_input" then + table.insert(inputs, p) + end + + table.insert(all, p) + end + end + + if i == 16 or i == 12 then + height = height + 1 + elseif height == 0 and y < 0 then + -- Continue.. + else + break + end + end + + if height <= 2 then + if player then minetest.chat_send_player(player, "Invalid structure surrounding the controller.") end + return nil + end + + if player then minetest.chat_send_player(player, "Structure complete.") end + + elethermal.cache[minetest.pos_to_string(pos)] = { + height = height, + inputs = inputs, + outputs = outputs, + thermal = thermal, + all = all + } + + return height, inputs, outputs, thermal, all +end + +local function start_timer(pos) + local t = minetest.get_node_timer(pos) + if not t:is_started() then + t:start(1.0) + end +end + +local function get_port_controller(pos) + for ctrl,t in pairs(elethermal.cache) do + local ctrlpos = minetest.string_to_pos(ctrl) + local found = false + for _,p in pairs(t.all) do + if vector.equals(p, pos) then + found = true + break + end + end + if found then + return ctrlpos, minetest.get_meta(ctrlpos) + end + end + return nil +end + +local function get_recipe(i1, heat) + local result = nil + + for _, d in pairs(results) do + local i1a = ItemStack(d.input) + + if i1a:get_name() == i1.fluid then + result = d + result.output = ItemStack(result.output) + result.input = i1a + break + end + end + + return result +end + +local function controller_formspec (input, output, heat) + local bar = "image[1.5,3;6,1;elethermal_gradient_bg.png^[transformR270]" + if heat then + bar = "image[1.5,3;6,1;elethermal_gradient_bg.png^[lowpart:".. + (100 * heat / 1000)..":elethermal_gradient.png^[transformR270]" + end + return "size[8,4.5]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + bar.. + "tooltip[1.5,3;6,1;Heat: "..heat.."K]".. + ele.formspec.fluid_bar(0, 0, input).. + ele.formspec.fluid_bar(7, 0, output) +end + +local function break_structure(pos) + local ctrl = get_port_controller(pos) + if not ctrl then return end + elethermal.cache[minetest.pos_to_string(ctrl)] = nil + start_timer(ctrl) +end + +local function controller_timer (pos, elapsed) + local meta = minetest.get_meta(pos) + local refresh = false + + if not elethermal.cache[minetest.pos_to_string(pos)] and not validate_structure(pos) then + refresh = false + meta:set_string("infotext", "Thermal Evaporation Plant Incomplete") + meta:set_string("formspec", "") + return + end + + local contpos = minetest.pos_to_string(pos) + local th = elethermal.cache[contpos] + + local in_buffer = fluid_lib.get_buffer_data(pos, "input") + local out_buffer = fluid_lib.get_buffer_data(pos, "output") + + local heat = meta:get_int("heat") + + while true do + local recipe = get_recipe(in_buffer, heat) + -- TODO: check sunlight for solar panels + heat = math.floor(th.thermal + (th.height * 10) + (100 * (minetest.get_heat(pos) + 1))) + if heat < 0 then + heat = 0 + end + + if not recipe then + break + end + + local heat_perc = heat / recipe.heat + local take_perc = math.floor(heat_perc * recipe.input:get_count()) + local outp_perc = math.floor(heat_perc * recipe.output:get_count()) + + if in_buffer.amount < take_perc then + break + end + + if out_buffer.amount + outp_perc > out_buffer.capacity then + break + end + + if out_buffer.fluid ~= "" and out_buffer.fluid ~= recipe.output:get_name() then + break + end + + out_buffer.fluid = recipe.output:get_name() + out_buffer.amount = out_buffer.amount + outp_perc + in_buffer.amount = in_buffer.amount - take_perc + refresh = true + + break + end + + meta:set_int("heat", heat) + + meta:set_string("input_fluid", in_buffer.fluid) + meta:set_int("input_fluid_storage", in_buffer.amount) + + meta:set_string("output_fluid", out_buffer.fluid) + meta:set_int("output_fluid_storage", out_buffer.amount) + + meta:set_string("infotext", "") + meta:set_string("formspec", controller_formspec(in_buffer, out_buffer, heat)) + return refresh +end + +minetest.register_node("elepower_thermal:evaporator_controller", { + description = "Thermal Evaporation Plant Controller", + tiles = { + "elepower_heat_casing.png", "elepower_heat_casing.png", "elepower_heat_casing.png", + "elepower_heat_casing.png", "elepower_heat_casing.png", "elepower_heat_casing.png^elenuclear_fusion_controller.png", + }, + paramtype2 = "facedir", + groups = { + cracky = 3, + ele_evaporator_node = 1, + }, + fluid_buffers = { + input = { + capacity = 8000, + accepts = {"elepower_thermal:brine_source", "default:water_source"}, + drainable = false, + }, + output = { + capacity = 8000, + accepts = nil, + drainable = true, + }, + }, + on_timer = controller_timer, + on_punch = function (pos, node, puncher, pointed_thing) + if validate_structure(pos, puncher:get_player_name()) then + start_timer(pos) + end + minetest.node_punch(pos, node, puncher, pointed_thing) + end, + on_destruct = break_structure, +}) + +minetest.register_node("elepower_thermal:evaporator_output", { + description = "Thermal Evaporation Plant Output", + tiles = { + "elepower_heat_casing.png", "elepower_heat_casing.png", "elepower_heat_casing.png", + "elepower_heat_casing.png", "elepower_heat_casing.png", "elepower_heat_casing.png^elenuclear_fluid_port_out.png^elepower_power_port.png", + }, + paramtype2 = "facedir", + groups = { + cracky = 3, + fluid_container = 1, + ele_evaporator_node = 1, + }, + fluid_buffers = {}, + node_io_can_put_liquid = function (pos, node, side) + return false + end, + node_io_can_take_liquid = function (pos, node, side) + return true + end, + node_io_accepts_millibuckets = function(pos, node, side) return true end, + node_io_take_liquid = function(pos, node, side, taker, want_liquid, want_millibuckets) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return nil end + + local buffers = fluid_lib.get_node_buffers(ctrl) + local buffer = "output" + local took = 0 + local name = "" + + local bfdata = fluid_lib.get_buffer_data(ctrl, 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(ctrl, buffer, want_millibuckets) + end + + start_timer(ctrl) + + return {name = name, millibuckets = took} + end, + node_io_get_liquid_size = function (pos, node, side) + return 1 + end, + node_io_get_liquid_name = function(pos, node, side, index) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return "" end + return ctrl_meta:get_string("output_fluid") + end, + node_io_get_liquid_stack = function(pos, node, side, index) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return ItemStack(nil) end + + return ItemStack(ctrl_meta:get_string("output_fluid") .. " " .. + ctrl_meta:get_int("output_fluid_storage")) + end, + on_destruct = break_structure, +}) + +minetest.register_node("elepower_thermal:evaporator_input", { + description = "Thermal Evaporation Plant Input", + tiles = { + "elepower_heat_casing.png", "elepower_heat_casing.png", "elepower_heat_casing.png", + "elepower_heat_casing.png", "elepower_heat_casing.png", "elepower_heat_casing.png^elenuclear_fluid_port.png^elepower_power_port.png", + }, + paramtype2 = "facedir", + groups = { + cracky = 3, + fluid_container = 1, + ele_evaporator_node = 1, + }, + fluid_buffers = {}, + node_io_can_put_liquid = function (pos, node, side) + return true + end, + node_io_can_take_liquid = function (pos, node, side) + return false + end, + node_io_get_liquid_size = function (pos, node, side) + return 1 + end, + node_io_get_liquid_name = function(pos, node, side, index) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return "" end + + return ctrl_meta:get_string("input_fluid") + end, + node_io_get_liquid_stack = function(pos, node, side, index) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return ItemStack(nil) end + + return ItemStack(ctrl_meta:get_string("input_fluid") .. " " .. + ctrl_meta:get_int("input_fluid_storage")) + end, + node_io_accepts_millibuckets = function(pos, node, side) return true end, + node_io_put_liquid = function(pos, node, side, putter, liquid, millibuckets) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return millibuckets end + + local buffers = fluid_lib.get_node_buffers(ctrl) + local leftovers = 0 + for buffer,data in pairs(buffers) do + if millibuckets == 0 then break end + local didnt_fit = fluid_lib.insert_into_buffer(ctrl, buffer, liquid, millibuckets) + millibuckets = millibuckets - (millibuckets - didnt_fit) + leftovers = leftovers + didnt_fit + end + start_timer(ctrl) + return leftovers + end, + node_io_room_for_liquid = function(pos, node, side, liquid, millibuckets) + local ctrl, ctrl_meta = get_port_controller(pos) + if not ctrl then return 0 end + + local buffers = fluid_lib.get_node_buffers(ctrl) + local insertable = 0 + for buffer,data in pairs(buffers) do + local insert = fluid_lib.can_insert_into_buffer(ctrl, buffer, liquid, millibuckets) + if insert > 0 then + insertable = insert + break + end + end + return insertable + end, + on_destruct = break_structure, +}) + +minetest.override_item("elepower_machines:heat_casing", { + on_destruct = break_structure, +}) + +minetest.register_lbm({ + label = "Enable Thermal Evaporators on load", + name = "elepower_thermal:evaporator_controllers", + nodenames = {"elepower_thermal:evaporator_controller"}, + run_at_every_load = true, + action = start_timer, +}) diff --git a/elepower_thermal/machines/init.lua b/elepower_thermal/machines/init.lua new file mode 100644 index 0000000..b3fab25 --- /dev/null +++ b/elepower_thermal/machines/init.lua @@ -0,0 +1,4 @@ + +local mp = elethermal.modpath .. "/machines/" + +dofile(mp.."evaporation_plant.lua") diff --git a/elepower_thermal/mod.conf b/elepower_thermal/mod.conf new file mode 100644 index 0000000..9420ab7 --- /dev/null +++ b/elepower_thermal/mod.conf @@ -0,0 +1,3 @@ +name = elepower_thermal +description = Thermal Systems +depends = elepower_papi,elepower_dynamics,elepower_machines diff --git a/elepower_thermal/textures/elethermal_gradient.png b/elepower_thermal/textures/elethermal_gradient.png new file mode 100644 index 0000000..2d2ae4d Binary files /dev/null and b/elepower_thermal/textures/elethermal_gradient.png differ diff --git a/elepower_thermal/textures/elethermal_gradient_bg.png b/elepower_thermal/textures/elethermal_gradient_bg.png new file mode 100644 index 0000000..6c8f3b7 Binary files /dev/null and b/elepower_thermal/textures/elethermal_gradient_bg.png differ