More work on fusion reactor..

This commit is contained in:
Evert Prants 2018-09-16 13:41:29 +03:00
parent 98a4457039
commit 5e9573d9b7
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
8 changed files with 477 additions and 35 deletions

View File

@ -9,7 +9,7 @@ elepm.electrolyzer_recipes = {
time = 20
},
{
recipe = "elepower_nuclear:heavy_water 1000",
recipe = "elepower_nuclear:heavy_water_source 1000",
output = {
"elepower_nuclear:deuterium 600",
"elepower_dynamics:oxygen 400",
@ -167,7 +167,7 @@ ele.register_machine("elepower_machines:electrolyzer", {
on_timer = electrolyzer_timer,
fluid_buffers = {
input = {
accepts = {"default:water_source", "elepower_nuclear:heavy_water",
accepts = {"default:water_source", "elepower_nuclear:heavy_water_source",
"group:biomass", "group:electrolysis_recipe"},
drainable = false,
capacity = 8000,

View File

@ -6,12 +6,6 @@
-- These nodes are used as "fluids"
-- They do not actually exist as nodes that should be placed.
minetest.register_node("elepower_nuclear:heavy_water", {
description = "Heavy Water",
groups = {not_in_creative_inventory = 1, oddly_breakable_by_hand = 1, water = 1},
tiles = {"elenuclear_heavy_water.png"},
})
minetest.register_node("elepower_nuclear:tritium", {
description = "Tritium Gas",
groups = {not_in_creative_inventory = 1, oddly_breakable_by_hand = 1, gas = 1},
@ -30,13 +24,112 @@ minetest.register_node("elepower_nuclear:helium", {
tiles = {"elenuclear_helium.png"},
})
minetest.register_node("elepower_nuclear:helium_plasma", {
description = "Helium Plasma\nSuperheated",
groups = {not_in_creative_inventory = 1, oddly_breakable_by_hand = 1, gas = 1},
tiles = {"elenuclear_helium_plasma.png"},
})
ele.register_gas(nil, "Tritium", "elepower_nuclear:tritium")
ele.register_gas(nil, "Deuterium", "elepower_nuclear:deuterium")
ele.register_gas(nil, "Helium", "elepower_nuclear:helium")
ele.register_gas(nil, "Helium Plasma", "elepower_nuclear:helium_plasma")
-------------
-- Liquids --
-------------
-- Heavy Water
minetest.register_node("elepower_nuclear:heavy_water_source", {
description = "Heavy Water Source",
drawtype = "liquid",
tiles = {
{
name = "elenuclear_heavy_water_source_animated.png",
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 2.0,
},
},
},
special_tiles = {
{
name = "elenuclear_heavy_water_source_animated.png",
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 2.0,
},
backface_culling = false,
},
},
alpha = 160,
paramtype = "light",
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
is_ground_content = false,
drop = "",
drowning = 1,
liquidtype = "source",
liquid_alternative_flowing = "elepower_nuclear:heavy_water_flowing",
liquid_alternative_source = "elepower_nuclear:heavy_water_source",
liquid_viscosity = 4,
post_effect_color = {a = 103, r = 13, g = 69, b = 121},
groups = {heavy_water = 3, liquid = 3, puts_out_fire = 1, cools_lava = 1},
sounds = default.node_sound_water_defaults(),
})
minetest.register_node("elepower_nuclear:heavy_water_flowing", {
description = "Flowing Heavy Water",
drawtype = "flowingliquid",
tiles = {"elenuclear_heavy_water.png"},
special_tiles = {
{
name = "elenuclear_heavy_water_flowing_animated.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 0.8,
},
},
{
name = "elenuclear_heavy_water_flowing_animated.png",
backface_culling = true,
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 0.8,
},
},
},
alpha = 160,
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:heavy_water_flowing",
liquid_alternative_source = "elepower_nuclear:heavy_water_source",
liquid_viscosity = 4,
post_effect_color = {a = 103, r = 13, g = 69, b = 121},
groups = {heavy_water = 3, liquid = 3, puts_out_fire = 1,
not_in_creative_inventory = 1, cools_lava = 1},
sounds = default.node_sound_water_defaults(),
})
------------
-- Fluids --
------------
-- Cold coolant
@ -136,8 +229,13 @@ minetest.register_node("elepower_nuclear:hot_coolant_flowing", {
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)")
if minetest.get_modpath("bucket") ~= nil then
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)")
bucket.register_liquid("elepower_nuclear:hot_coolant_source", "elepower_nuclear:hot_coolant_flowing",
"elepower_nuclear:bucket_hot_coolant", "#88649e", "Coolant (Hot)")
bucket.register_liquid("elepower_nuclear:heavy_water_source", "elepower_nuclear:heavy_water_flowing",
"elepower_nuclear:bucket_heavy_water", "#0d4579", "Heavy Water Bucket")
end

View File

@ -1,4 +1,6 @@
local struct_cache = {}
local iC = 1 -- Casing
local iR = 2 -- Controller
local iI = 3 -- Inputs
@ -55,9 +57,11 @@ local function determine_structure(pos, player)
local scan_pos = vector.add(pos, {x = relX, y = y, z = relZ})
local index = area:indexp(scan_pos)
if data[index] ~= ntype then
minetest.chat_send_player(player, ('Incorrect node at %d,%d,%d; expected %s, found %s'):format(
scan_pos.x,scan_pos.y,scan_pos.z,minetest.get_name_from_content_id(ntype),
minetest.get_name_from_content_id(data[index])))
if player then
minetest.chat_send_player(player, ('Incorrect node at %d,%d,%d; expected %s, found %s'):format(
scan_pos.x,scan_pos.y,scan_pos.z,minetest.get_name_from_content_id(ntype),
minetest.get_name_from_content_id(data[index])))
end
success = false
break
end
@ -73,13 +77,180 @@ local function determine_structure(pos, player)
end
end
if success then
if success and player then
minetest.chat_send_player(player, "Multi-node structure complete!")
end
return success, inputs, outputs, power
end
local function notify_controller_presence(posi, posj)
for _, pos in pairs(posi) do
local meta = minetest.get_meta(pos)
meta:set_string("ctrl", posj)
local t = minetest.get_node_timer(pos)
if not t:is_started() then
t:start(1.0)
end
end
end
local function controller_formspec(in1, in2, out, power, time, state)
local bar = "image[3.5,1;1,1;gui_furnace_arrow_bg.png^[transformR270]"
if time ~= nil then
bar = "image[3.5,1;1,1;gui_furnace_arrow_bg.png^[lowpart:"..
(time)..":gui_furnace_arrow_fg.png^[transformR270]"
end
return "size[8,8.5]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
ele.formspec.power_meter(power)..
ele.formspec.fluid_bar(1, 0, in1)..
ele.formspec.fluid_bar(2, 0, in2)..
bar..
ele.formspec.fluid_bar(7, 0, out)..
ele.formspec.state_switcher(7, 2.5, state)
end
local function controller_timer(pos)
local refresh = false
local meta = minetest.get_meta(pos)
-- Cache all reactor components
local cpos = minetest.pos_to_string(pos)
if not struct_cache[cpos] then
local st, i, o, p = determine_structure(pos)
if st then
struct_cache[cpos] = {
inputs = i,
outputs = o,
power = p,
}
notify_controller_presence(i, cpos)
notify_controller_presence(o, cpos)
notify_controller_presence(p, cpos)
else
return false
end
end
local in1_buffer = fluid_lib.get_buffer_data(pos, "in1")
local in2_buffer = fluid_lib.get_buffer_data(pos, "in2")
local out_buffer = fluid_lib.get_buffer_data(pos, "out")
local capacity = ele.helpers.get_node_property(meta, pos, "capacity")
local storage = ele.helpers.get_node_property(meta, pos, "storage")
local pow_buffer = {capacity = capacity, storage = storage, usage = 0}
meta:set_string("formspec", controller_formspec(in1_buffer, in2_buffer, out_buffer, pow_buffer, 0, 0))
-- Factors:
-- 1. Power. Power keeps these stats up:
-- 1. Field Strength
-- 2. Internal Temperature
-- 2. Fuel
-- Deuterium + Tritium -> Helium Plasma
-- Ignition temperature: 2000K (70% scale)
-- Field strength: >90%
-- 1000 + 1000 mB of fuel : 2600 sec, 675 neutrons/s
-- Helium plasma will be used to create electricity via heat exchange.
return refresh
end
local function get_port_controller(pos)
local meta = minetest.get_meta(pos)
local ctrl = minetest.string_to_pos(meta:get_string("ctrl"))
local ctrl_node = minetest.get_node_or_nil(ctrl)
if not ctrl_node or ctrl_node.name ~= "elepower_nuclear:reactor_controller" then
return nil
end
return ctrl, minetest.get_meta(ctrl)
end
local function port_destruct(pos)
local meta = minetest.get_meta(pos)
local ctrl, ctrl_meta = get_port_controller(pos)
if not ctrl then return nil end
-- Remove controller's cache entry, forcing it to redetect its structure
local ctrl_name = minetest.pos_to_string(ctrl)
if struct_cache[ctrl_name] then
struct_cache[ctrl_name] = nil
end
local t = minetest.get_node_timer(ctrl)
if not t:is_started() then
t:start(1.0)
end
end
-- Transfer power from the power port to the controller
local function power_timer(pos)
local refresh = false
local meta = minetest.get_meta(pos)
local ctrl, ctrl_meta = get_port_controller(pos)
if not ctrl then
meta:set_string("No controller found.")
return false
end
local localc = ele.helpers.get_node_property(meta, pos, "capacity")
local locals = ele.helpers.get_node_property(meta, pos, "storage")
local remotec = ele.helpers.get_node_property(ctrl_meta, ctrl, "capacity")
local remotes = ele.helpers.get_node_property(ctrl_meta, ctrl, "storage")
if remotes ~= remotec then
if remotes + locals > remotec then
local add = remotec - remotes
locals = locals - add
remotes = remotes + add
else
remotes = remotes + locals
locals = 0
end
refresh = true
end
if refresh then
meta:set_int("storage", locals)
ctrl_meta:set_int("storage", remotes)
local t = minetest.get_node_timer(ctrl)
if not t:is_started() then
t:start(1.0)
end
end
meta:set_string("infotext", ("Feeding controller at %s\nLocal %s"):format(
minetest.pos_to_string(ctrl), ele.capacity_text(localc, locals)))
return refresh
end
local function port_timer(pos)
local meta = minetest.get_meta(pos)
local ctrl = get_port_controller(pos)
if not ctrl then
meta:set_string("No controller found.")
return false
end
meta:set_string("infotext", "Feeding controller at " .. minetest.pos_to_string(ctrl))
return false
end
-----------
-- Nodes --
-----------
@ -90,9 +261,30 @@ minetest.register_node("elepower_nuclear:reactor_controller", {
"elepower_advblock_combined.png", "elepower_advblock_combined.png", "elepower_advblock_combined.png",
"elepower_advblock_combined.png", "elepower_advblock_combined.png", "elepower_advblock_combined.png^elenuclear_fusion_controller.png",
},
groups = {cracky = 2},
groups = {
cracky = 2,
},
fluid_buffers = {
in1 = {
capacity = 16000,
accepts = {"elepower_nuclear:deuterium"},
drainable = false,
},
in2 = {
capacity = 16000,
accepts = {"elepower_nuclear:tritium", "elepower_nuclear:helium"},
drainable = false,
},
out = {
capacity = 16000,
accepts = nil,
drainable = true,
},
},
ele_capacity = 64000,
on_timer = controller_timer,
on_punch = function (pos, node, puncher, pointed_thing)
print(determine_structure(pos, puncher:get_player_name()))
determine_structure(pos, puncher:get_player_name())
minetest.node_punch(pos, node, puncher, pointed_thing)
end,
})
@ -104,7 +296,16 @@ minetest.register_node("elepower_nuclear:reactor_power", {
"elepower_advblock_combined.png", "elepower_advblock_combined.png", "elepower_advblock_combined.png^elenuclear_power_port.png^elepower_power_port.png",
},
paramtype2 = "facedir",
groups = {cracky = 2},
groups = {
cracky = 2,
ele_machine = 1,
ele_user = 1,
},
ele_capacity = 8000,
ele_usage = 0,
ele_inrush = 64,
on_timer = power_timer,
on_destruct = port_destruct,
})
minetest.register_node("elepower_nuclear:reactor_fluid", {
@ -115,7 +316,66 @@ minetest.register_node("elepower_nuclear:reactor_fluid", {
"elepower_advblock_combined.png^elenuclear_fluid_port.png^elepower_power_port.png",
},
paramtype2 = "facedir",
groups = {cracky = 2},
groups = {
cracky = 2,
fluid_container = 1,
tube = 1,
},
fluid_buffers = {},
on_timer = port_timer,
on_destruct = port_destruct,
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 2
end,
node_io_get_liquid_name = function(pos, node, side, index)
local ctrl, ctrl_meta = get_port_controller(pos)
if not ctrl then return nil end
return ctrl_meta:get_string("in" .. index .. "_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("in" .. index .. "_fluid") .. " " ..
ctrl_meta:get_int("in" .. index .. "_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 nil 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
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 nil 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,
})
minetest.register_node("elepower_nuclear:reactor_output", {
@ -126,7 +386,67 @@ minetest.register_node("elepower_nuclear:reactor_output", {
"elepower_advblock_combined.png^elenuclear_fluid_port_out.png^elepower_power_port.png",
},
paramtype2 = "facedir",
groups = {cracky = 2},
groups = {
cracky = 2,
fluid_container = 1,
tube = 1,
},
fluid_buffers = {},
on_timer = port_timer,
on_destruct = port_destruct,
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 = "out"
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
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("out_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("out_fluid") .. " " ..
ctrl_meta:get_int("out_fluid_storage"))
end,
})
minetest.register_lbm({
label = "Enable Fusion Reactors on load",
name = "elepower_nuclear:fusion_reactors",
nodenames = {"elepower_nuclear:reactor_controller"},
run_at_every_load = true,
action = function (pos)
local t = minetest.get_node_timer(pos)
if not t:is_started() then
t:start(1.0)
end
end,
})
-- Define reactor structure with Content IDs

View File

@ -15,6 +15,17 @@ local function get_formspec(heat, cold, water, steam)
default.get_hotbar_bg(0, 4.25)
end
local heat_recipes = {
["elepower_nuclear:hot_coolant_source"] = {
out = "elepower_nuclear:coolant_source",
factor = 1,
},
["elepower_nuclear:helium_plasma"] = {
out = "elepower_nuclear:helium",
factor = 8,
},
}
local function heat_exchanger_timer(pos)
local meta = minetest.get_meta(pos)
local change = false
@ -24,15 +35,25 @@ local function heat_exchanger_timer(pos)
local water = fluid_lib.get_buffer_data(pos, "water")
local steam = fluid_lib.get_buffer_data(pos, "steam")
-- See if we have enough hot coolant
if heat.amount >= 1000 then
local water_convert = math.min(water.amount, 1000)
if steam.amount + water_convert > steam.capacity then
water_convert = steam.capacity - steam.amount
while true do
if heat.amount < 1000 or heat.fluid == "" or not heat_recipes[heat.fluid] then
break
end
if water_convert > 0 then
if cold.amount + 1000 < cold.capacity then
-- See if we have enough hot coolant
if heat.amount >= 1000 and heat.fluid ~= "" then
local damnt = heat_recipes[heat.fluid]
local water_convert = math.min(water.amount, 1000 * damnt.factor)
if cold.fluid ~= damnt.fluid and cold.fluid ~= "" then
break
end
if steam.amount + water_convert > steam.capacity then
water_convert = steam.capacity - steam.amount
end
if water_convert > 0 and cold.amount + 1000 < cold.capacity then
-- Conversion
heat.amount = heat.amount - 1000
cold.amount = cold.amount + 1000
@ -40,13 +61,16 @@ local function heat_exchanger_timer(pos)
water.amount = water.amount - water_convert
steam.amount = steam.amount + water_convert
cold.fluid = damnt.out
change = true
end
end
break
end
if change then
meta:set_string("cold_fluid", "elepower_nuclear:coolant_source")
meta:set_string("cold_fluid", cold.fluid)
meta:set_string("steam_fluid", "elepower_dynamics:steam")
meta:set_int("heat_fluid_storage", heat.amount)
@ -58,7 +82,7 @@ local function heat_exchanger_timer(pos)
meta:set_string("formspec", get_formspec(heat, cold, water, steam))
return false
return change
end
ele.register_machine("elepower_nuclear:heat_exchanger", {
@ -71,12 +95,12 @@ ele.register_machine("elepower_nuclear:heat_exchanger", {
fluid_buffers = {
heat = {
capacity = 8000,
accepts = {"elepower_nuclear:hot_coolant_source"},
accepts = {"elepower_nuclear:hot_coolant_source", "elepower_nuclear:helium_plasma"},
drainable = false,
},
cold = {
capacity = 8000,
accepts = {"elepower_nuclear:coolant_source"},
accepts = {"elepower_nuclear:coolant_source", "elepower_nuclear:helium"},
drainable = true,
},
water = {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 B

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB