From 334a78c6cc8e716ec974a2e124b2e8bc27135896 Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Fri, 27 Jul 2018 22:40:35 +0300 Subject: [PATCH] Reactor heats coolant --- elepower_nuclear/fluids.lua | 120 ++++++++++++++++-- elepower_nuclear/machines/fission_reactor.lua | 89 +++++++++++-- .../textures/elenuclear_cold_coolant.png | Bin 6067 -> 6328 bytes .../textures/elenuclear_hot_coolant.png | Bin 5944 -> 6245 bytes elepower_nuclear/textures/gui_sheen.png | Bin 4223 -> 0 bytes 5 files changed, 187 insertions(+), 22 deletions(-) delete mode 100644 elepower_nuclear/textures/gui_sheen.png diff --git a/elepower_nuclear/fluids.lua b/elepower_nuclear/fluids.lua index 03c80a0..7b14c7d 100644 --- a/elepower_nuclear/fluids.lua +++ b/elepower_nuclear/fluids.lua @@ -6,18 +6,6 @@ -- These nodes are used as "fluids" -- They do not actually exist as nodes that should be placed. -minetest.register_node("elepower_nuclear:coolant", { - description = "Coolant (cold)", - groups = {not_in_creative_inventory = 1, oddly_breakable_by_hand = 1, coolant = 1}, - tiles = {"elenuclear_cold_coolant.png"}, -}) - -minetest.register_node("elepower_nuclear:coolant_hot", { - description = "Coolant (hot)", - groups = {not_in_creative_inventory = 1, oddly_breakable_by_hand = 1, coolant = 1, hot = 1}, - tiles = {"elenuclear_hot_coolant.png"}, -}) - minetest.register_node("elepower_nuclear:heavy_water", { description = "Heavy Water", groups = {not_in_creative_inventory = 1, oddly_breakable_by_hand = 1, water = 1}, @@ -41,3 +29,111 @@ minetest.register_node("elepower_nuclear:helium", { groups = {not_in_creative_inventory = 1, oddly_breakable_by_hand = 1, gas = 1}, tiles = {"elenuclear_helium.png"}, }) + +------------ +-- Fluids -- +------------ + +-- Cold coolant + +minetest.register_node("elepower_nuclear:coolant_source", { + description = "Cold Coolant Source", + drawtype = "liquid", + tiles = {"elenuclear_cold_coolant.png"}, + alpha = 200, + paramtype = "light", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drop = "", + drowning = 1, + liquidtype = "source", + liquid_alternative_source = "elepower_nuclear:coolant_source", + liquid_alternative_flowing = "elepower_nuclear:coolant_flowing", + liquid_viscosity = 2, + post_effect_color = {a = 128, r = 36, g = 150, b = 255}, + groups = {liquid = 3, coolant = 1}, + sounds = default.node_sound_water_defaults(), +}) + +minetest.register_node("elepower_nuclear:coolant_flowing", { + description = "Cold Coolant Flowing", + drawtype = "flowingliquid", + tiles = {"elenuclear_cold_coolant.png"}, + special_tiles = {"elenuclear_cold_coolant.png", "elenuclear_cold_coolant.png"}, + alpha = 200, + paramtype = "light", + paramtype2 = "flowingliquid", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drop = "", + drowning = 1, + liquidtype = "flowing", + liquid_alternative_flowing = "elepower_nuclear:coolant_flowing", + liquid_alternative_source = "elepower_nuclear:coolant_source", + liquid_viscosity = 2, + post_effect_color = {a = 128, r = 36, g = 150, b = 255}, + groups = {coolant = 3, liquid = 3, not_in_creative_inventory = 1}, + sounds = default.node_sound_water_defaults(), +}) + +-- Hot coolant + +minetest.register_node("elepower_nuclear:hot_coolant_source", { + description = "Hot Coolant Source", + drawtype = "liquid", + tiles = {"elenuclear_hot_coolant.png"}, + alpha = 200, + paramtype = "light", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + damage_per_second = 4 * 2, + drop = "", + drowning = 1, + liquidtype = "source", + liquid_alternative_source = "elepower_nuclear:hot_coolant_source", + liquid_alternative_flowing = "elepower_nuclear:hot_coolant_flowing", + liquid_viscosity = 2, + post_effect_color = {a = 128, r = 136, g = 100, b = 158}, + groups = {liquid = 3, coolant = 1, hot = 1}, + sounds = default.node_sound_water_defaults(), +}) + +minetest.register_node("elepower_nuclear:hot_coolant_flowing", { + description = "Hot Coolant Flowing", + drawtype = "flowingliquid", + tiles = {"elenuclear_hot_coolant.png"}, + special_tiles = {"elenuclear_hot_coolant.png", "elenuclear_hot_coolant.png"}, + alpha = 200, + paramtype = "light", + paramtype2 = "flowingliquid", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + damage_per_second = 4 * 2, + drop = "", + drowning = 1, + liquidtype = "flowing", + liquid_alternative_flowing = "elepower_nuclear:hot_coolant_flowing", + liquid_alternative_source = "elepower_nuclear:hot_coolant_source", + liquid_viscosity = 2, + post_effect_color = {a = 128, r = 136, g = 100, b = 158}, + groups = {coolant = 3, liquid = 3, not_in_creative_inventory = 1, hot = 1}, + sounds = default.node_sound_water_defaults(), +}) + +bucket.register_liquid("elepower_nuclear:coolant_source", "elepower_nuclear:hot_coolant_flowing", + "elepower_nuclear:bucket_coolant", "#2497ff", "Coolant (Cold)") + +bucket.register_liquid("elepower_nuclear:hot_coolant_source", "elepower_nuclear:hot_coolant_flowing", + "elepower_nuclear:bucket_hot_coolant", "#88649e", "Coolant (Hot)") diff --git a/elepower_nuclear/machines/fission_reactor.lua b/elepower_nuclear/machines/fission_reactor.lua index 92e53da..47d998a 100644 --- a/elepower_nuclear/machines/fission_reactor.lua +++ b/elepower_nuclear/machines/fission_reactor.lua @@ -13,7 +13,6 @@ Hot coolant ..in order to keep the heat below critical. Any other detected node will either be MOLTEN or ACTIVATED (TODO) (you don't want this!) Reactor core will be replaced by a molten core when the heat reaches 100%. All components and fuel will be lost! - Do NOT run the reactor at 100% power 100% percent of the time! Keep some control rods partially inserted at all times. ]] local AREA_SIZE = 8 @@ -33,7 +32,7 @@ local function calculate_fitness(pos) local ids = { c_water = minetest.get_content_id("default:water_source"), - c_lava = minetest.get_content_id("default:lava"), + c_lava = minetest.get_content_id("default:lava_source"), } local excession = 0 @@ -220,6 +219,7 @@ local function reactor_core_timer(pos) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() local headless = false + local fuel_reactor = 0 -- SAFEGUARD: Expect a controller to be above the core local controller_pos = {x = pos.x, y = pos.y + 1, z = pos.z} @@ -270,7 +270,7 @@ local function reactor_core_timer(pos) end if power_setting > 0 then - local fuel_reactor = fuel_after_depletion(inv) + fuel_reactor = fuel_after_depletion(inv) if fuel_reactor == 0 then -- Enforce zero power setting when no fuel present power_setting = 0 @@ -292,7 +292,7 @@ local function reactor_core_timer(pos) if heat > ceiling then heat = heat - 1 else - heat = heat + 1 + heat = heat + fuel_reactor end end elseif heat > 0 then @@ -306,11 +306,25 @@ local function reactor_core_timer(pos) return false end + -- Nothing left to do in this timer, exit + if power_setting == 0 and heat == 0 then + meta:set_int("heat", heat) + meta:set_string("formspec", get_core_formspec(heat, power_setting)) + return false + end + -- Expect a fluid port below the core + -- TODO: Allow multiple fluid ports in the core's affected area local fluid_port_pos = {x = pos.x, y = pos.y - 1, z = pos.z} local fluid_port_node = minetest.get_node_or_nil(fluid_port_pos) if fluid_port_node ~= nil and fluid_port_node.name == "elepower_nuclear:reactor_fluid_port" then - -- TODO: Heat coolant + local fpmeta = minetest.get_meta(fluid_port_pos) + + if fpmeta:get_int("burst") == 0 and heat > 0 then + fpmeta:set_int("burst", 1) + minetest.get_node_timer(fluid_port_pos):start(1.0) + heat = heat - 1 + end end meta:set_int("heat", heat) @@ -332,10 +346,24 @@ local function reactor_controller_timer(pos) meta:set_int("setting", 100 - (averg / 4)) meta:set_string("formspec", get_controller_formspec(settings, meta:get_int("selected"))) + -- Ping the core + local core_pos = {x = pos.x, y = pos.y - 1, z = pos.z} + local core_node = minetest.get_node_or_nil(core_pos) + if core_node and core_node.name == "elepower_nuclear:fission_core" then + local timer = minetest.get_node_timer(core_pos) + if not timer:is_started() then + timer:start(1.0) + end + end + return false end local function reactor_controller_manage(pos, formname, fields, sender) + if sender and sender ~= "" and minetest.is_protected(pos, sender:get_player_name()) then + return + end + local meta = minetest.get_meta(pos) local selected = meta:get_int("selected") local change = false @@ -384,12 +412,40 @@ local function reactor_controller_manage(pos, formname, fields, sender) end if change then - minetest.get_node_timer(pos):start(1.0) + minetest.get_node_timer(pos):start(0.2) end end local function reactor_port_timer(pos) - return false + local refresh = false + local meta = minetest.get_meta(pos) + local cool = fluid_lib.get_buffer_data(pos, "cool") + local hot = fluid_lib.get_buffer_data(pos, "hot") + + local heat_burst = meta:get_int("burst") + if heat_burst > 0 then + -- Convert a bucket of cold coolant into hot coolant + + local coolant = math.min(cool.amount, 1000) + if coolant > 0 and hot.amount + coolant < hot.capacity then + meta:set_int("burst", 0) + + cool.amount = cool.amount - coolant + hot.amount = hot.amount + coolant + + refresh = true + + meta:set_string("cool_fluid", "elepower_nuclear:coolant_source") + meta:set_string("hot_fluid", "elepower_nuclear:hot_coolant_source") + + meta:set_int("cool_fluid_storage", cool.amount) + meta:set_int("hot_fluid_storage", hot.amount) + end + end + + meta:set_string("formspec", get_port_formspec(cool, hot)) + + return refresh end -- Reactor Core @@ -469,20 +525,33 @@ ele.register_base_device("elepower_nuclear:reactor_fluid_port", { on_timer = reactor_port_timer, on_construct = function (pos) local meta = minetest.get_meta(pos) - local inv = meta:get_inventory() + + meta:set_string("cool_fluid", "elepower_nuclear:coolant_source") + meta:set_string("hot_fluid", "elepower_nuclear:hot_coolant_source") meta:set_string("formspec", get_port_formspec()) end, fluid_buffers = { cool = { capacity = 16000, - accepts = {"default:water_source", "elepower_nuclear:coolant"}, + accepts = {"default:water_source", "elepower_nuclear:coolant_source"}, drainable = false, }, hot = { capacity = 16000, - accepts = {"elepower_nuclear:coolant_hot"}, + accepts = {"elepower_nuclear:hot_coolant_source"}, drainable = true, } }, }) + +-- Load reactor cores +minetest.register_lbm({ + label = "Refresh Reactors on load", + name = "elepower_nuclear:fission_core", + nodenames = {"elepower_nuclear:fission_core"}, + run_at_every_load = true, + action = function (pos) + minetest.get_node_timer(pos):start(1.0) + end, +}) diff --git a/elepower_nuclear/textures/elenuclear_cold_coolant.png b/elepower_nuclear/textures/elenuclear_cold_coolant.png index 6438afbbefafeb64ad1a7d42217af07e7d7b060d..dd19557316034672ec279e6d35cdc0c0b3ee009a 100644 GIT binary patch delta 2023 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 U%!yxgr~m)}07*qoM6N<$f@As(8~^|S delta 1525 zcmVq}z|1I!BjX1J&#*(!pVtw=Xo!=4q}{ zg5gHVAbSYP2wVQwZGK0n_fb$pHf^ln7mrGV7lSz>V+mqlg!%$iCct{XufeMWgEC=G z2(Z{=XaN0((4Aav673);cwYrfu`LCF2p$NWAruD&Y#=8T$VO%pi2!5*K?SZe3hJ{D z0wMu_5>(UNnNS;ZkOB8OrNj6#7&5R>uKhT&<^YFVVKbx?xR^%JJlhpV6bi7@0&^}KrB6kO?A~`QW^R@48Cp=% z>>c!Q+Kd=c6c@9KSF;w zS~W{H;!adiQtJ;A##@PFc{&O#L`~=tz9Ao=RLx9PlarNqW_+aK%EIGfjc>&}>3`0D zLmj{`r+)cWYad3G3ik>)-B>C*QZ)NUu9@i&YZwZPeZ6U?L4I1=6^Q1a%G>7`$Khsw zmupwR6eqKT*)m@y+LyH7{xuyq^DK$I=Fz<`zY1kJpV?<=8&SZlksp`ZBZ?3H;+OJ2 zl{F$|eK)V2a~tRH+Sy$T=218s_xK}!U|(^%h%g^@sJ(cX>P{w!ny~fV7PL*8ZR-y2 z-PF`N-)W^G_+3Y48K`P9e5o~E+TCV%-(6Uw$I)hHcck4j_l$i-w~qyyHqAU9f9&+T z0auPD!~9fItlEGX*0gvC)NfNE*5; z*k42^z?LmPa?LwsTc8Vq&V!|F{;;xC$LJVvC=Ag)T3k=|bG|FE!^G>Ws`3CbO%&oj z9eFqa01rd6?gh^RBsDQ)VKOsjWGy%_H!>|WV=-hcIXE*lEoNmfVly^1Ff?K{G?U>7 zjtww3F*Y_cGBq(WGc!1odU53|0vQ$+M(ElN%Nw2m}uUG^^jcC6hxI zD1V+wL_t(2&n?oyu_Q$h15ins)iZyc#TIP9LLxSp>8?tN1Ki*7@y|d0n#qiN)wwrF z0KMw|>}sjxGa!4F9f^AGL*o5&%^3jy>6s)}DM@t!IM4Aoj(SxBJFoWziBcRO*ZY!~ zF~wdr#}rj+RaNo(d8#ze)Y5T!)ts4t;(ts?s8ppSnlr!u{)hxnS5=F|I3VrB@tGv+ z)o~>0Jm>YZ9Nhmr5})tb@bTHFT55R=aK;YK8BsiYNW6Ys394|tJAqWQ9q0Ay@)?p< z1keB|N(8XK&w8)>bH+me!TwC|V~3^veX6S|0(`zFPOtJY;vxWo32;tUlOzC;>VH*8 z&KV#eDUMAQrF{ZY0)W`-eZ^@6NxCaZoH?^r1K9g?kt$?B0oeCQXxmkyaDVQ;UMxvW z(&^X|YFz-5)FKk?`~MMZH4upeW?My26!$&*yQ|czs!O#Lpo;1unPeOl8mJJ z*X!pZp>ywU+36*ZXPZPEkK?JX^ERAX1#o|#>%IE*>*c^>k9(CXvj+gBzRKgZ%8os8 b_H+IPzU@Q++0A)e00000NkvXXu0mjfiHpv* diff --git a/elepower_nuclear/textures/gui_sheen.png b/elepower_nuclear/textures/gui_sheen.png deleted file mode 100644 index 6f0b38d1b25aaf618c2c4d60fef7de8fcdca8969..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4223 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