many worldgen mods and gonna try technic now

This commit is contained in:
2026-09-13 03:30:48 -06:00
parent bac6ac94a3
commit 548749cb1a
4811 changed files with 163271 additions and 1 deletions
@@ -0,0 +1,22 @@
-- HV battery box
minetest.register_craft({
output = 'technic:hv_battery_box0',
recipe = {
{'technic:mv_battery_box0', 'technic:mv_battery_box0', 'technic:mv_battery_box0'},
{'technic:mv_battery_box0', 'technic:hv_transformer', 'technic:mv_battery_box0'},
{'', 'technic:hv_cable', ''},
}
})
technic.register_battery_box({
tier = "HV",
max_charge = 1000000,
charge_rate = 100000,
discharge_rate = 400000,
charge_step = 10000,
discharge_step = 40000,
upgrade = 1,
tube = 1,
})
@@ -0,0 +1,47 @@
minetest.register_craft({
output = 'technic:hv_cable 3',
recipe = {
{'homedecor:plastic_sheeting', 'homedecor:plastic_sheeting', 'homedecor:plastic_sheeting'},
{'technic:mv_cable', 'technic:mv_cable', 'technic:mv_cable'},
{'homedecor:plastic_sheeting', 'homedecor:plastic_sheeting', 'homedecor:plastic_sheeting'},
}
})
technic.register_cable("HV", 3/16)
if minetest.get_modpath("digilines") then
local S = technic.getter
if minetest.get_modpath("digistuff") then
minetest.register_craft({
output = 'technic:hv_digi_cable 1',
type = "shapeless",
recipe = {'digistuff:digimese', 'technic:hv_cable'}
})
else
minetest.register_craft({
output = 'technic:hv_digi_cable 1',
recipe = {
{'digilines:wire_std_00000000', 'digilines:wire_std_00000000', 'digilines:wire_std_00000000'},
{'digilines:wire_std_00000000', 'technic:hv_cable', 'digilines:wire_std_00000000'},
{'digilines:wire_std_00000000', 'digilines:wire_std_00000000', 'digilines:wire_std_00000000'},
}
})
end
technic.register_cable("HV", 3/16, S("HV Cable (digiline)"), "_digi", {
digiline = {
wire = {
rules = {
{x = 1, y = 0, z = 0},
{x =-1, y = 0, z = 0},
{x = 0, y = 1, z = 0},
{x = 0, y =-1, z = 0},
{x = 0, y = 0, z = 1},
{x = 0, y = 0, z =-1}
}
}
}
})
end
@@ -0,0 +1,12 @@
-- HV compressor
minetest.register_craft({
output = 'technic:hv_compressor',
recipe = {
{'technic:carbon_plate', 'technic:mv_compressor', 'technic:composite_plate'},
{'pipeworks:tube_1', 'technic:hv_transformer', 'pipeworks:tube_1'},
{'technic:stainless_steel_ingot', 'technic:hv_cable', 'technic:stainless_steel_ingot'},
}
})
technic.register_compressor({tier = "HV", demand = {1500, 1000, 750}, speed = 5, upgrade = 1, tube = 1})
@@ -0,0 +1,18 @@
-- MV Electric Furnace
-- This is a faster version of the stone furnace which runs on EUs
-- In addition to this it can be upgraded with microcontrollers and batteries
-- This new version uses the batteries to lower the power consumption of the machine
-- Also in addition this furnace can be attached to the pipe system from the pipeworks mod.
-- FIXME: kpoppel I'd like to introduce an induction heating element here also
minetest.register_craft({
output = 'technic:hv_electric_furnace',
recipe = {
{'technic:stainless_steel_ingot', 'technic:mv_electric_furnace', 'technic:stainless_steel_ingot'},
{'pipeworks:tube_1', 'technic:hv_transformer', 'pipeworks:tube_1'},
{'technic:stainless_steel_ingot', 'technic:hv_cable', 'technic:stainless_steel_ingot'},
}
})
technic.register_electric_furnace({tier="HV", upgrade=1, tube=1, demand={4000, 2500, 1500}, speed=12})
@@ -0,0 +1,390 @@
--- Forcefield generator.
-- @author ShadowNinja
--
-- Forcefields are powerful barriers but they consume huge amounts of power.
-- The forcefield Generator is an HV machine.
-- How expensive is the generator?
-- Leaves room for upgrades lowering the power drain?
local digilines_path = minetest.get_modpath("digilines")
local forcefield_power_drain = 10
local S = technic.getter
local cable_entry = "^technic_cable_connection_overlay.png"
minetest.register_craft({
output = "technic:forcefield_emitter_off",
recipe = {
{"default:mese", "basic_materials:motor", "default:mese" },
{"technic:deployer_off", "technic:machine_casing", "technic:deployer_off"},
{"default:mese", "technic:hv_cable", "default:mese" },
}
})
local replaceable_cids = {}
minetest.after(0, function()
for name, ndef in pairs(minetest.registered_nodes) do
if ndef.buildable_to == true and name ~= "ignore" then
replaceable_cids[minetest.get_content_id(name)] = true
end
end
end)
-- Idea: Let forcefields have different colors by upgrade slot.
-- Idea: Let forcefields add up by detecting if one hits another.
-- ___ __
-- / \/ \
-- | |
-- \___/\___/
local function update_forcefield(pos, meta, active)
if active then
-- rate limit by chance
if math.floor(math.random()*4) ~= 0 then
return
end
end
local shape = meta:get_int("shape")
local range = meta:get_int("range")
local vm = VoxelManip()
local MinEdge, MaxEdge = vm:read_from_map(vector.subtract(pos, range),
vector.add(pos, range))
local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge})
local data = vm:get_data()
local c_air = minetest.get_content_id("air")
local c_field = minetest.get_content_id("technic:forcefield")
for z = -range, range do
for y = -range, range do
local vi = area:index(pos.x + (-range), pos.y + y, pos.z + z)
for x = -range, range do
local relevant
if shape == 0 then
local squared = x * x + y * y + z * z
relevant =
squared <= range * range + range and
squared >= (range - 1) * (range - 1) + (range - 1)
else
relevant =
x == -range or x == range or
y == -range or y == range or
z == -range or z == range
end
if relevant then
local cid = data[vi]
if active and replaceable_cids[cid] then
data[vi] = c_field
elseif not active and cid == c_field then
data[vi] = c_air
end
end
vi = vi + 1
end
end
end
vm:set_data(data)
vm:update_liquids()
vm:write_to_map()
end
local function set_forcefield_formspec(meta)
local formspec
if digilines_path then
formspec = "size[5,3.25]"..
"field[0.3,3;5,1;channel;Digiline Channel;"..meta:get_string("channel").."]"
else
formspec = "size[5,2.25]"
end
formspec = formspec..
"field[0.3,0.5;2,1;range;"..S("Range")..";"..meta:get_int("range").."]"
-- The names for these toggle buttons are explicit about which
-- state they'll switch to, so that multiple presses (arising
-- from the ambiguity between lag and a missed press) only make
-- the single change that the user expects.
if meta:get_int("shape") == 0 then
formspec = formspec.."button[3,0.2;2,1;shape1;"..S("Sphere").."]"
else
formspec = formspec.."button[3,0.2;2,1;shape0;"..S("Cube").."]"
end
if meta:get_int("mesecon_mode") == 0 then
formspec = formspec.."button[0,1;5,1;mesecon_mode_1;"..S("Ignoring Mesecon Signal").."]"
else
formspec = formspec.."button[0,1;5,1;mesecon_mode_0;"..S("Controlled by Mesecon Signal").."]"
end
if meta:get_int("enabled") == 0 then
formspec = formspec..
"button[0,1.75;5,1;enable;"..S("%s Disabled"):format(S("%s Forcefield Emitter"):format("HV")).."]"
else
formspec = formspec..
"button[0,1.75;5,1;disable;"..S("%s Enabled"):format(S("%s Forcefield Emitter"):format("HV")).."]"
end
meta:set_string("formspec", formspec)
end
local forcefield_receive_fields = function(pos, formname, fields, sender)
local player_name = sender:get_player_name()
if minetest.is_protected(pos, player_name) then
minetest.chat_send_player(player_name, "You are not allowed to edit this!")
minetest.record_protection_violation(pos, player_name)
return
end
local meta = minetest.get_meta(pos)
local range = nil
if fields.range then
range = tonumber(fields.range) or 0
-- Smallest field is 5. Anything less is asking for trouble.
-- Largest is 20. It is a matter of pratical node handling.
-- At the maximim range updating the forcefield takes about 0.2s
range = math.max(range, 5)
range = math.min(range, 20)
if range == meta:get_int("range") then range = nil end
end
if fields.shape0 or fields.shape1 or range then
update_forcefield(pos, meta, false)
end
if range then meta:set_int("range", range) end
if fields.channel then meta:set_string("channel", fields.channel) end
if fields.shape0 then meta:set_int("shape", 0) end
if fields.shape1 then meta:set_int("shape", 1) end
if fields.enable then meta:set_int("enabled", 1) end
if fields.disable then meta:set_int("enabled", 0) end
if fields.mesecon_mode_0 then meta:set_int("mesecon_mode", 0) end
if fields.mesecon_mode_1 then meta:set_int("mesecon_mode", 1) end
set_forcefield_formspec(meta)
end
local mesecons = {
effector = {
action_on = function(pos, node)
minetest.get_meta(pos):set_int("mesecon_effect", 1)
end,
action_off = function(pos, node)
minetest.get_meta(pos):set_int("mesecon_effect", 0)
end
}
}
local digiline_def = {
receptor = {
rules = technic.digilines.rules,
action = function() end
},
effector = {
rules = technic.digilines.rules,
action = function(pos, node, channel, msg)
local meta = minetest.get_meta(pos)
if channel ~= meta:get_string("channel") then
return
end
local msgt = type(msg)
if msgt == "string" then
local smsg = msg:lower()
msg = {}
if smsg == "get" then
msg.command = "get"
elseif smsg == "off" then
msg.command = "off"
elseif smsg == "on" then
msg.command = "on"
elseif smsg == "toggle" then
msg.command = "toggle"
elseif smsg:sub(1, 5) == "range" then
msg.command = "range"
msg.value = tonumber(smsg:sub(7))
elseif smsg:sub(1, 5) == "shape" then
msg.command = "shape"
msg.value = smsg:sub(7):lower()
msg.value = tonumber(msg.value) or msg.value
end
elseif msgt ~= "table" then
return
end
if msg.command == "get" then
digilines.receptor_send(pos, technic.digilines.rules, channel, {
enabled = meta:get_int("enabled"),
range = meta:get_int("range"),
shape = meta:get_int("shape")
})
return
elseif msg.command == "off" then
meta:set_int("enabled", 0)
elseif msg.command == "on" then
meta:set_int("enabled", 1)
elseif msg.command == "toggle" then
local onn = meta:get_int("enabled")
onn = 1-onn -- Mirror onn with pivot 0.5, so switch between 1 and 0.
meta:set_int("enabled", onn)
elseif msg.command == "range" then
if type(msg.value) ~= "number" then
return
end
msg.value = math.max(msg.value, 5)
msg.value = math.min(msg.value, 20)
update_forcefield(pos, meta, false)
meta:set_int("range", msg.value)
elseif msg.command == "shape" then
local valuet = type(msg.value)
if valuet == "string" then
if msg.value == "sphere" then
msg.value = 0
elseif msg.value == "cube" then
msg.value = 1
end
elseif valuet ~= "number" then
return
end
if not msg.value then
return
end
update_forcefield(pos, meta, false)
meta:set_int("shape", msg.value)
else
return
end
set_forcefield_formspec(meta)
end
},
}
local function run(pos, node)
local meta = minetest.get_meta(pos)
local eu_input = meta:get_int("HV_EU_input")
local enabled = meta:get_int("enabled") ~= 0 and
(meta:get_int("mesecon_mode") == 0 or meta:get_int("mesecon_effect") ~= 0)
local machine_name = S("%s Forcefield Emitter"):format("HV")
local range = meta:get_int("range")
local power_requirement
if meta:get_int("shape") == 0 then
power_requirement = math.floor(4 * math.pi * range * range)
else
power_requirement = 24 * range * range
end
power_requirement = power_requirement * forcefield_power_drain
if not enabled then
if node.name == "technic:forcefield_emitter_on" then
update_forcefield(pos, meta, false)
technic.swap_node(pos, "technic:forcefield_emitter_off")
meta:set_string("infotext", S("%s Disabled"):format(machine_name))
end
meta:set_int("HV_EU_demand", 0)
return
end
meta:set_int("HV_EU_demand", power_requirement)
if eu_input < power_requirement then
meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
if node.name == "technic:forcefield_emitter_on" then
update_forcefield(pos, meta, false)
technic.swap_node(pos, "technic:forcefield_emitter_off")
end
elseif eu_input >= power_requirement then
if node.name == "technic:forcefield_emitter_off" then
technic.swap_node(pos, "technic:forcefield_emitter_on")
meta:set_string("infotext", S("%s Active"):format(machine_name))
end
update_forcefield(pos, meta, true)
end
end
minetest.register_node("technic:forcefield_emitter_off", {
description = S("%s Forcefield Emitter"):format("HV"),
tiles = {
"technic_forcefield_emitter_off.png",
"technic_machine_bottom.png"..cable_entry,
"technic_forcefield_emitter_off.png",
"technic_forcefield_emitter_off.png",
"technic_forcefield_emitter_off.png",
"technic_forcefield_emitter_off.png"
},
groups = {cracky = 1, technic_machine = 1, technic_hv = 1},
on_receive_fields = forcefield_receive_fields,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_int("HV_EU_input", 0)
meta:set_int("HV_EU_demand", 0)
meta:set_int("range", 10)
meta:set_int("enabled", 0)
meta:set_int("mesecon_mode", 0)
meta:set_int("mesecon_effect", 0)
if digilines_path then
meta:set_string("channel", "forcefield"..minetest.pos_to_string(pos))
end
meta:set_string("infotext", S("%s Forcefield Emitter"):format("HV"))
set_forcefield_formspec(meta)
end,
mesecons = mesecons,
digiline = digiline_def,
technic_run = run,
})
minetest.register_node("technic:forcefield_emitter_on", {
description = S("%s Forcefield Emitter"):format("HV"),
tiles = {
"technic_forcefield_emitter_on.png",
"technic_machine_bottom.png"..cable_entry,
"technic_forcefield_emitter_on.png",
"technic_forcefield_emitter_on.png",
"technic_forcefield_emitter_on.png",
"technic_forcefield_emitter_on.png"
},
groups = {cracky = 1, technic_machine = 1, technic_hv = 1,
not_in_creative_inventory=1},
drop = "technic:forcefield_emitter_off",
on_receive_fields = forcefield_receive_fields,
on_destruct = function(pos)
local meta = minetest.get_meta(pos)
update_forcefield(pos, meta, false)
end,
mesecons = mesecons,
digiline = digiline_def,
technic_run = run,
technic_on_disable = function (pos, node)
local meta = minetest.get_meta(pos)
update_forcefield(pos, meta, false)
technic.swap_node(pos, "technic:forcefield_emitter_off")
end,
on_blast = function(pos, intensity)
minetest.dig_node(pos)
return {"technic:forcefield_emitter_off"}
end,
})
minetest.register_node("technic:forcefield", {
description = S("%s Forcefield"):format("HV"),
sunlight_propagates = true,
drawtype = "glasslike",
groups = {not_in_creative_inventory=1},
paramtype = "light",
light_source = default.LIGHT_MAX,
diggable = false,
drop = '',
tiles = {{
name = "technic_forcefield_animated.png",
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1.0,
},
}},
on_blast = function(pos, intensity)
end,
})
if minetest.get_modpath("mesecons_mvps") then
mesecon.register_mvps_stopper("technic:forcefield")
end
technic.register_machine("HV", "technic:forcefield_emitter_on", technic.receiver)
technic.register_machine("HV", "technic:forcefield_emitter_off", technic.receiver)
@@ -0,0 +1,13 @@
minetest.register_alias("hv_generator", "technic:hv_generator")
minetest.register_craft({
output = 'technic:hv_generator',
recipe = {
{'technic:carbon_plate', 'technic:mv_generator', 'technic:composite_plate'},
{'pipeworks:tube_1', 'technic:hv_transformer', 'pipeworks:tube_1'},
{'technic:stainless_steel_ingot', 'technic:hv_cable', 'technic:stainless_steel_ingot'},
}
})
technic.register_generator({tier="HV", tube=1, supply=1200})
@@ -0,0 +1,13 @@
-- HV grinder
minetest.register_craft({
output = 'technic:hv_grinder',
recipe = {
{'technic:carbon_plate', 'technic:mv_grinder', 'technic:composite_plate'},
{'pipeworks:tube_1', 'technic:hv_transformer', 'pipeworks:tube_1'},
{'technic:stainless_steel_ingot', 'technic:hv_cable', 'technic:stainless_steel_ingot'},
}
})
technic.register_grinder({tier="HV", demand={1200, 900, 600}, speed=5, upgrade=1, tube=1})
@@ -0,0 +1,22 @@
technic.register_tier("HV", "High Voltage")
local path = technic.modpath.."/machines/HV"
-- Wiring stuff
dofile(path.."/cables.lua")
dofile(path.."/battery_box.lua")
-- Generators
dofile(path.."/solar_array.lua")
dofile(path.."/nuclear_reactor.lua")
dofile(path.."/generator.lua")
-- Machines
dofile(path.."/quarry.lua")
dofile(path.."/forcefield.lua")
dofile(path.."/electric_furnace.lua")
dofile(path.."/grinder.lua")
dofile(path.."/compressor.lua")
@@ -0,0 +1,514 @@
--[[
The enriched uranium rod driven EU generator.
A very large and advanced machine providing vast amounts of power.
Very efficient but also expensive to run as it needs uranium.
Provides 10000 HV EUs for one week (only counted when loaded).
The nuclear reactor core requires a casing of water and a protective
shield to work. This is checked now and then and if the casing is not
intact the reactor will melt down!
--]]
local burn_ticks = 7 * 24 * 60 * 60 -- Seconds
local power_supply = 100000 -- EUs
local fuel_type = "technic:uranium_fuel" -- The reactor burns this
local digiline_meltdown = technic.config:get_bool("enable_nuclear_reactor_digiline_selfdestruct")
local has_digilines = minetest.get_modpath("digilines")
local S = technic.getter
local reactor_desc = S("@1 Nuclear Reactor Core", S("HV"))
local cable_entry = "^technic_cable_connection_overlay.png"
-- FIXME: Recipe should make more sense like a rod recepticle, steam chamber, HV generator?
minetest.register_craft({
output = 'technic:hv_nuclear_reactor_core',
recipe = {
{'technic:carbon_plate', 'default:obsidian_glass', 'technic:carbon_plate'},
{'technic:composite_plate', 'technic:machine_casing', 'technic:composite_plate'},
{'technic:stainless_steel_ingot', 'technic:hv_cable', 'technic:stainless_steel_ingot'},
}
})
local function make_reactor_formspec(meta)
local f = "size[8,9]"..
"label[0,0;"..S("Nuclear Reactor Rod Compartment").."]"..
"list[context;src;2,1;3,2;]"..
"list[current_player;main;0,5;8,4;]"..
"listring[]"..
"button[5.5,1.5;2,1;start;Start]"..
"checkbox[5.5,2.5;autostart;automatic Start;"..meta:get_string("autostart").."]"
if not has_digilines then
return f
end
local digiline_enabled = meta:get_string("enable_digiline")
f = f.."checkbox[0.5,2.8;enable_digiline;Enable Digiline;"..digiline_enabled.."]"
if digiline_enabled ~= "true" then
return f
end
return f..
"button_exit[4.6,3.69;2,1;save;Save]"..
"field[1,4;4,1;remote_channel;Digiline Remote Channel;${remote_channel}]"
end
local SS_OFF = 0
local SS_DANGER = 1
local SS_CLEAR = 2
local reactor_siren = {}
local function siren_set_state(pos, state)
local hpos = minetest.hash_node_position(pos)
local siren = reactor_siren[hpos]
if not siren then
if state == SS_OFF then return end
siren = {state=SS_OFF}
reactor_siren[hpos] = siren
end
if state == SS_DANGER and siren.state ~= SS_DANGER then
if siren.handle then minetest.sound_stop(siren.handle) end
siren.handle = minetest.sound_play("technic_hv_nuclear_reactor_siren_danger_loop",
{pos=pos, gain=1.5, loop=true, max_hear_distance=48})
siren.state = SS_DANGER
elseif state == SS_CLEAR then
if siren.handle then minetest.sound_stop(siren.handle) end
local clear_handle = minetest.sound_play("technic_hv_nuclear_reactor_siren_clear",
{pos=pos, gain=1.5, loop=false, max_hear_distance=48})
siren.handle = clear_handle
siren.state = SS_CLEAR
minetest.after(10, function()
if siren.handle ~= clear_handle then return end
minetest.sound_stop(clear_handle)
if reactor_siren[hpos] == siren then
reactor_siren[hpos] = nil
end
end)
elseif state == SS_OFF and siren.state ~= SS_OFF then
if siren.handle then minetest.sound_stop(siren.handle) end
reactor_siren[hpos] = nil
end
end
local function siren_danger(pos, meta)
meta:set_int("siren", 1)
siren_set_state(pos, SS_DANGER)
end
local function siren_clear(pos, meta)
if meta:get_int("siren") ~= 0 then
siren_set_state(pos, SS_CLEAR)
meta:set_int("siren", 0)
end
end
--[[
The standard reactor structure consists of a 9x9x9 cube. A cross
section through the middle:
CCCC CCCC
CBBB BBBC
CBLL LLBC
CBLWWWLBC
CBLW#WLBC
CBLW|WLBC
CBLL|LLBC
CBBB|BBBC
CCCC|CCCC
C = Concrete, B = Blast-resistant concrete, L = Lead,
W = water node, # = reactor core, | = HV cable
The man-hole is optional (but necessary for refueling).
For the reactor to operate and not melt down, it insists on the inner
7x7x7 portion (from the core out to the blast-resistant concrete)
being intact. Intactness only depends on the number of nodes of the
right type in each layer. The water layer must have water in all but
at most one node; the steel and blast-resistant concrete layers must
have the right material in all but at most two nodes. The permitted
gaps are meant for the cable and man-hole, but can actually be anywhere
and contain anything. For the reactor to be useful, a cable must
connect to the core, but it can go in any direction.
The outer concrete layer of the standard structure is not required
for the reactor to operate. It is noted here because it used to
be mandatory, and for historical reasons (that it predates the
implementation of radiation) it needs to continue being adequate
shielding of legacy reactors. If it ever ceases to be adequate
shielding for new reactors, legacy ones should be grandfathered.
For legacy reasons, if the reactor has a stainless steel layer instead
of a lead layer it will be converted to a lead layer.
--]]
local function reactor_structure_badness(pos)
local vm = VoxelManip()
local pos1 = vector.subtract(pos, 3)
local pos2 = vector.add(pos, 3)
local MinEdge, MaxEdge = vm:read_from_map(pos1, pos2)
local data = vm:get_data()
local area = VoxelArea:new({MinEdge=MinEdge, MaxEdge=MaxEdge})
local c_blast_concrete = minetest.get_content_id("technic:blast_resistant_concrete")
local c_lead = minetest.get_content_id("technic:lead_block")
local c_steel = minetest.get_content_id("technic:stainless_steel_block")
local c_water_source = minetest.get_content_id("default:water_source")
local c_water_flowing = minetest.get_content_id("default:water_flowing")
local blast_layer, steel_layer, lead_layer, water_layer = 0, 0, 0, 0
for z = pos1.z, pos2.z do
for y = pos1.y, pos2.y do
for x = pos1.x, pos2.x do
local cid = data[area:index(x, y, z)]
if x == pos1.x or x == pos2.x or
y == pos1.y or y == pos2.y or
z == pos1.z or z == pos2.z then
if cid == c_blast_concrete then
blast_layer = blast_layer + 1
end
elseif x == pos1.x+1 or x == pos2.x-1 or
y == pos1.y+1 or y == pos2.y-1 or
z == pos1.z+1 or z == pos2.z-1 then
if cid == c_lead then
lead_layer = lead_layer + 1
elseif cid == c_steel then
steel_layer = steel_layer + 1
end
elseif x == pos1.x+2 or x == pos2.x-2 or
y == pos1.y+2 or y == pos2.y-2 or
z == pos1.z+2 or z == pos2.z-2 then
if cid == c_water_source or cid == c_water_flowing then
water_layer = water_layer + 1
end
end
end
end
end
if steel_layer >= 96 then
for z = pos1.z+1, pos2.z-1 do
for y = pos1.y+1, pos2.y-1 do
for x = pos1.x+1, pos2.x-1 do
local vi = area:index(x, y, z)
if x == pos1.x+1 or x == pos2.x-1 or
y == pos1.y+1 or y == pos2.y-1 or
z == pos1.z+1 or z == pos2.z-1 then
if data[vi] == c_steel then
data[vi] = c_lead
end
end
end
end
end
vm:set_data(data)
vm:write_to_map()
lead_layer = steel_layer
end
if water_layer > 25 then water_layer = 25 end
if lead_layer > 96 then lead_layer = 96 end
if blast_layer > 216 then blast_layer = 216 end
return (25 - water_layer) + (96 - lead_layer) + (216 - blast_layer)
end
local function melt_down_reactor(pos)
minetest.log("action", "A reactor melted down at "..minetest.pos_to_string(pos))
minetest.set_node(pos, {name = "technic:corium_source"})
end
local function start_reactor(pos, meta)
if minetest.get_node(pos).name ~= "technic:hv_nuclear_reactor_core" then
return false
end
local inv = meta:get_inventory()
if inv:is_empty("src") then
return false
end
local src_list = inv:get_list("src")
local correct_fuel_count = 0
for _, src_stack in pairs(src_list) do
if src_stack and src_stack:get_name() == fuel_type then
correct_fuel_count = correct_fuel_count + 1
end
end
-- Check that the reactor is complete and has the correct fuel
if correct_fuel_count ~= 6 or reactor_structure_badness(pos) ~= 0 then
return false
end
meta:set_int("burn_time", 1)
technic.swap_node(pos, "technic:hv_nuclear_reactor_core_active")
meta:set_int("HV_EU_supply", power_supply)
for idx, src_stack in pairs(src_list) do
src_stack:take_item()
inv:set_stack("src", idx, src_stack)
end
return true
end
minetest.register_abm({
label = "Machines: reactor melt-down check",
nodenames = {"technic:hv_nuclear_reactor_core_active"},
interval = 4,
chance = 1,
action = function (pos, node)
local meta = minetest.get_meta(pos)
local badness = reactor_structure_badness(pos)
local accum_badness = meta:get_int("structure_accumulated_badness")
if badness == 0 then
if accum_badness ~= 0 then
meta:set_int("structure_accumulated_badness", math.max(accum_badness - 4, 0))
siren_clear(pos, meta)
end
else
siren_danger(pos, meta)
accum_badness = accum_badness + badness
if accum_badness >= 25 then
melt_down_reactor(pos)
else
meta:set_int("structure_accumulated_badness", accum_badness)
end
end
end,
})
local function run(pos, node)
local meta = minetest.get_meta(pos)
local burn_time = meta:get_int("burn_time") or 0
if burn_time >= burn_ticks or burn_time == 0 then
if has_digilines and meta:get_int("HV_EU_supply") == power_supply then
digilines.receptor_send(pos, technic.digilines.rules, meta:get_string("remote_channel"), {
command = "fuel_used",
pos = pos
})
end
if meta:get_string("autostart") == "true" then
if start_reactor(pos, meta) then
return
end
end
meta:set_int("HV_EU_supply", 0)
meta:set_int("burn_time", 0)
meta:set_string("infotext", S("%s Idle"):format(reactor_desc))
technic.swap_node(pos, "technic:hv_nuclear_reactor_core")
meta:set_int("structure_accumulated_badness", 0)
siren_clear(pos, meta)
elseif burn_time > 0 then
burn_time = burn_time + 1
meta:set_int("burn_time", burn_time)
local percent = math.floor(burn_time / burn_ticks * 100)
meta:set_string("infotext", reactor_desc.." ("..percent.."%)")
meta:set_int("HV_EU_supply", power_supply)
end
end
local nuclear_reactor_receive_fields = function(pos, formname, fields, sender)
local player_name = sender:get_player_name()
if minetest.is_protected(pos, player_name) then
minetest.chat_send_player(player_name, "You are not allowed to edit this!")
minetest.record_protection_violation(pos, player_name)
return
end
local meta = minetest.get_meta(pos)
local update_formspec = false
if fields.remote_channel then
meta:set_string("remote_channel", fields.remote_channel)
end
if fields.start then
local b = start_reactor(pos, meta)
if b then
minetest.chat_send_player(player_name, "Start successful")
else
minetest.chat_send_player(player_name, "Error")
end
end
if fields.autostart then
meta:set_string("autostart", fields.autostart)
update_formspec = true
end
if fields.enable_digiline then
meta:set_string("enable_digiline", fields.enable_digiline)
update_formspec = true
end
if update_formspec then
meta:set_string("formspec", make_reactor_formspec(meta))
end
end
local digiline_def = function(pos, _, channel, msg)
local meta = minetest.get_meta(pos)
if meta:get_string("enable_digiline") ~= "true" or
channel ~= meta:get_string("remote_channel") then
return
end
-- Convert string messages to tables:
local msgt = type(msg)
if msgt == "string" then
local smsg = msg:lower()
msg = {}
if smsg == "get" then
msg.command = "get"
elseif smsg:sub(1, 13) == "self_destruct" then
msg.command = "self_destruct"
msg.timer = tonumber(smsg:sub(15)) or 0
elseif smsg == "start" then
msg.command = "start"
end
elseif msgt ~= "table" then
return
end
if msg.command == "get" then
local inv = meta:get_inventory()
local invtable = {}
for i = 1, 6 do
local stack = inv:get_stack("src", i)
if stack:is_empty() then
invtable[i] = 0
elseif stack:get_name() == fuel_type then
invtable[i] = stack:get_count()
else
invtable[i] = -stack:get_count()
end
end
digilines.receptor_send(pos, technic.digilines.rules, channel, {
burn_time = meta:get_int("burn_time"),
enabled = meta:get_int("HV_EU_supply") == power_supply,
siren = meta:get_int("siren") == 1,
structure_accumulated_badness = meta:get_int("structure_accumulated_badness"),
rods = invtable
})
elseif digiline_meltdown and msg.command == "self_destruct" and
minetest.get_node(pos).name == "technic:hv_nuclear_reactor_core_active" then
if msg.timer ~= 0 and type(msg.timer) == "number" then
siren_danger(pos, meta)
minetest.after(msg.timer, melt_down_reactor, pos)
else
melt_down_reactor(pos)
end
elseif msg.command == "start" then
local b = start_reactor(pos, meta)
if b then
digilines.receptor_send(pos, technic.digilines.rules, channel, {
command = "start_success",
pos = pos
})
else
digilines.receptor_send(pos, technic.digilines.rules, channel, {
command = "start_error",
pos = pos
})
end
end
end
minetest.register_node("technic:hv_nuclear_reactor_core", {
description = reactor_desc,
tiles = {
"technic_hv_nuclear_reactor_core.png",
"technic_hv_nuclear_reactor_core.png"..cable_entry
},
drawtype = "mesh",
mesh = "technic_reactor.obj",
groups = {cracky = 1, technic_machine = 1, technic_hv = 1},
legacy_facedir_simple = true,
sounds = default.node_sound_wood_defaults(),
paramtype = "light",
paramtype2 = "facedir",
stack_max = 1,
on_receive_fields = nuclear_reactor_receive_fields,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", reactor_desc)
meta:set_string("formspec", make_reactor_formspec(meta))
if has_digilines then
meta:set_string("remote_channel",
"nuclear_reactor"..minetest.pos_to_string(pos))
end
local inv = meta:get_inventory()
inv:set_size("src", 6)
end,
-- digiline interface
digiline = {
receptor = {
rules = technic.digilines.rules,
action = function() end,
},
effector = {
rules = technic.digilines.rules,
action = digiline_def,
},
},
can_dig = technic.machine_can_dig,
on_destruct = function(pos) siren_set_state(pos, SS_OFF) end,
allow_metadata_inventory_put = technic.machine_inventory_put,
allow_metadata_inventory_take = technic.machine_inventory_take,
allow_metadata_inventory_move = technic.machine_inventory_move,
technic_run = run,
})
minetest.register_node("technic:hv_nuclear_reactor_core_active", {
tiles = {
"technic_hv_nuclear_reactor_core.png",
"technic_hv_nuclear_reactor_core.png"..cable_entry
},
drawtype = "mesh",
mesh = "technic_reactor.obj",
groups = {cracky = 1, technic_machine = 1, technic_hv = 1, radioactive = 4,
not_in_creative_inventory = 1},
legacy_facedir_simple = true,
sounds = default.node_sound_wood_defaults(),
drop = "technic:hv_nuclear_reactor_core",
light_source = 14,
paramtype = "light",
paramtype2 = "facedir",
on_receive_fields = nuclear_reactor_receive_fields,
-- digiline interface
digiline = {
receptor = {
rules = technic.digilines.rules,
action = function() end,
},
effector = {
rules = technic.digilines.rules,
action = digiline_def,
},
},
can_dig = technic.machine_can_dig,
after_dig_node = melt_down_reactor,
on_destruct = function(pos) siren_set_state(pos, SS_OFF) end,
allow_metadata_inventory_put = technic.machine_inventory_put,
allow_metadata_inventory_take = technic.machine_inventory_take,
allow_metadata_inventory_move = technic.machine_inventory_move,
technic_run = run,
technic_on_disable = function(pos, node)
local timer = minetest.get_node_timer(pos)
timer:start(1)
end,
on_timer = function(pos, node)
-- Connected back?
if technic.get_timeout("HV", pos) > 0 then return false end
local meta = minetest.get_meta(pos)
local burn_time = meta:get_int("burn_time") or 0
if burn_time >= burn_ticks or burn_time == 0 then
meta:set_int("HV_EU_supply", 0)
meta:set_int("burn_time", 0)
technic.swap_node(pos, "technic:hv_nuclear_reactor_core")
meta:set_int("structure_accumulated_badness", 0)
siren_clear(pos, meta)
return false
end
meta:set_int("burn_time", burn_time + 1)
return true
end,
})
technic.register_machine("HV", "technic:hv_nuclear_reactor_core", technic.producer)
technic.register_machine("HV", "technic:hv_nuclear_reactor_core_active", technic.producer)
@@ -0,0 +1,421 @@
local S = technic.getter
local has_digilines = minetest.get_modpath("digilines")
local quarry_dig_above_nodes = tonumber(technic.config:get("quarry_dig_above_nodes"))
local quarry_max_depth = tonumber(technic.config:get("quarry_max_depth"))
local quarry_time_limit = tonumber(technic.config:get("quarry_time_limit"))
local quarry_demand = 10000
local quarry_eject_dir = vector.new(0, 1, 0)
local machine_name = S("%s Quarry"):format("HV")
local quarry_formspec =
"size[8,9]"..
"item_image[7,0;1,1;technic:quarry]"..
"list[context;cache;0,1;4,3;]"..
"listring[context;cache]"..
"list[current_player;main;0,5;8,4;]"..
"listring[current_player;main]"..
"label[0,0;"..machine_name.."]"..
"button[6,0.9;2,1;restart;"..S("Restart").."]"
if has_digilines then
quarry_formspec = quarry_formspec
.. "field[4.3,3.4;4,1;channel;Channel;${channel}]"
end
-- hard-coded spiral dig pattern for up to 17x17 dig area
local quarry_dig_pattern = {
0,1,2,2,3,3,0,0,0,1,1,1,2,2,2,2,3,3,3,3,0,0,0,0,0,1,1,1,1,1,2,2,
2,2,2,2,3,3,3,3,3,3,0,0,0,0,0,0,0,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,
2,2,2,2,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,
1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,
0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
}
local function is_player_allowed(pos, name)
local owner = minetest.get_meta(pos):get_string("owner")
if owner == "" or owner == name then
return true
end
if not minetest.is_protected(pos, name) then
return true
end
return false
end
local function reset_quarry(pos)
local meta = minetest.get_meta(pos)
local node = technic.get_or_load_node(pos) or minetest.get_node(pos)
meta:set_int("quarry_dir", node.param2)
meta:set_string("quarry_pos", minetest.pos_to_string(pos))
meta:set_string("dig_pos", "")
meta:set_int("dig_level", pos.y + quarry_dig_above_nodes)
local radius = meta:get_int("size")
local diameter = (radius*2)+1
meta:set_int("dig_steps", diameter*diameter)
meta:set_int("dig_index", 0)
meta:set_int("purge_on", 1)
meta:set_int("finished", 0)
meta:set_int("dug", 0)
end
local function set_quarry_status(pos)
local meta = minetest.get_meta(pos)
local formspec = quarry_formspec.."field[4.3,2.4;2,1;size;"..S("Radius:")..";"..meta:get_int("size").."]"
local status = S("Digging not started")
if meta:get_int("enabled") == 1 then
formspec = formspec.."button[4,0.9;2,1;disable;"..S("Enabled").."]"
if meta:get_int("purge_on") == 1 then
status = S("Purging cache")
meta:set_string("infotext", S("%s purging cache"):format(machine_name))
meta:set_int("HV_EU_demand", 0)
elseif meta:get_int("finished") == 1 then
status = S("Digging finished")
meta:set_string("infotext", S("%s Finished"):format(machine_name))
meta:set_int("HV_EU_demand", 0)
else
local rel_y = meta:get_int("dig_level") - pos.y
status = S("Digging %d m "..(rel_y > 0 and "above" or "below").." machine"):format(math.abs(rel_y))
if meta:get_int("HV_EU_input") >= quarry_demand then
meta:set_string("infotext", S("%s Active"):format(machine_name))
else
meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
end
meta:set_int("HV_EU_demand", quarry_demand)
end
else
formspec = formspec.."button[4,0.9;2,1;enable;"..S("Disabled").."]"
meta:set_string("infotext", S("%s Disabled"):format(machine_name))
meta:set_int("HV_EU_demand", 0)
end
meta:set_string("formspec", formspec.."label[0,4.1;"..minetest.formspec_escape(status).."]")
end
local function quarry_receive_fields(pos, formname, fields, sender)
local player_name = sender:get_player_name()
if not is_player_allowed(pos, player_name) then
minetest.chat_send_player(player_name, "You are not allowed to edit this!")
minetest.record_protection_violation(pos, player_name)
return
end
local meta = minetest.get_meta(pos)
if fields.size and string.find(fields.size, "^[0-9]+$") then
local size = tonumber(fields.size)
if size >= 1 and size <= 8 and size ~= meta:get_int("size") then
meta:set_int("size", size)
reset_quarry(pos)
end
end
if fields.channel then
meta:set_string("channel", fields.channel)
end
if fields.enable then meta:set_int("enabled", 1) end
if fields.disable then meta:set_int("enabled", 0) end
if fields.restart then reset_quarry(pos) end
set_quarry_status(pos)
end
local function quarry_handle_purge(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local cache = inv:get_list("cache")
if not cache then
inv:set_size("cache", 12)
return
end
local i = 0
for _,stack in ipairs(cache) do
i = i + 1
if stack then
local item = stack:to_table()
if item then
technic.tube_inject_item(pos, pos, quarry_eject_dir, item)
stack:clear()
inv:set_stack("cache", i, stack)
break
end
end
end
if inv:is_empty("cache") then
meta:set_int("purge_on", 0)
end
end
local function can_dig_node(pos, node_name, owner, digger)
if node_name == "air" or node_name == "vacuum:vacuum" then
return false
end
local def = minetest.registered_nodes[node_name]
if not def or not def.diggable or (def.can_dig and not def.can_dig(pos, digger)) then
return false
end
if minetest.is_protected(pos, owner) then
return false
end
return true
end
local function find_ground(quarry_pos, quarry_dir, meta)
local dir = minetest.facedir_to_dir(quarry_dir % 4)
local radius = meta:get_int("size")
local dig_level = meta:get_int("dig_level")
local middle_pos = vector.add(quarry_pos, vector.multiply(dir, radius + 1))
local pos1 = vector.new(middle_pos.x - radius, dig_level, middle_pos.z - radius)
local pos2 = vector.new(middle_pos.x + radius, dig_level, middle_pos.z + radius)
local nodes = minetest.find_nodes_in_area(pos1, pos2, {"air", "vacuum:vacuum"})
if #nodes < meta:get_int("dig_steps") then
return vector.new(middle_pos.x, dig_level, middle_pos.z)
end
meta:set_int("dig_level", dig_level - 1)
return nil
end
local function get_dig_pos(quarry_pos, quarry_dir, dig_pos, dig_index, dig_steps, meta)
if dig_index > 0 and dig_index < dig_steps then
local facedir = (quarry_dir + quarry_dig_pattern[dig_index]) % 4
dig_pos = vector.add(dig_pos, minetest.facedir_to_dir(facedir))
elseif dig_index >= dig_steps then
local dig_level = meta:get_int("dig_level")
if (quarry_pos.y - dig_level) >= quarry_max_depth then
return nil, dig_index
end
local dir = minetest.facedir_to_dir(quarry_dir % 4)
dig_pos = vector.add(quarry_pos, vector.multiply(dir, meta:get_int("size") + 1))
dig_pos.y = dig_level - 1
meta:set_int("dig_level", dig_pos.y)
dig_index = 0
end
dig_index = dig_index + 1
return dig_pos, dig_index
end
local function execute_dig(pos, node, meta)
local dig_pos = minetest.string_to_pos(meta:get_string("dig_pos"))
local quarry_dir = meta:get_int("quarry_dir")
if not dig_pos then
-- quarry has not hit ground yet
dig_pos = find_ground(pos, quarry_dir, meta)
else
local owner = meta:get_string("owner")
local digger = pipeworks.create_fake_player({name = owner})
local dig_steps = meta:get_int("dig_steps")
local dig_index = meta:get_int("dig_index")
local t0 = minetest.get_us_time()
local us_used = 0
-- search for something to dig
while us_used < quarry_time_limit do
dig_pos, dig_index = get_dig_pos(pos, quarry_dir, dig_pos, dig_index, dig_steps, meta)
if not dig_pos then
-- finished digging
meta:set_int("finished", 1)
meta:set_int("purge_on", 1)
break
end
local dig_node = technic.get_or_load_node(dig_pos) or minetest.get_node(dig_pos)
if can_dig_node(dig_pos, dig_node.name, owner, digger) then
-- found something to dig, dig it and stop searching
minetest.remove_node(dig_pos)
local inv = meta:get_inventory()
local drops = minetest.get_node_drops(dig_node.name, "")
for _, dropped_item in ipairs(drops) do
local left = inv:add_item("cache", dropped_item)
while not left:is_empty() do
meta:set_int("purge_on", 1)
quarry_handle_purge(pos)
left = inv:add_item("cache", left)
end
end
local dug_nodes = meta:get_int("dug") + 1
meta:set_int("dug", dug_nodes)
if dug_nodes % 100 == 0 then
meta:set_int("purge_on", 1)
end
break
end
us_used = minetest.get_us_time() - t0
end
meta:set_int("dig_index", dig_index)
end
if dig_pos then
meta:set_string("dig_pos", minetest.pos_to_string(dig_pos))
end
end
local function quarry_run(pos, node)
local meta = minetest.get_meta(pos)
if minetest.pos_to_string(pos) ~= meta:get_string("quarry_pos") then
-- quarry has been moved since last dig
reset_quarry(pos)
elseif meta:get_int("purge_on") == 1 then
quarry_handle_purge(pos)
elseif meta:get_int("enabled") and meta:get_int("HV_EU_input") >= quarry_demand and meta:get_int("finished") == 0 then
execute_dig(pos, node, meta)
elseif not meta:get_inventory():is_empty("cache") then
meta:set_int("purge_on", 1)
end
set_quarry_status(pos)
end
local digiline_def = function(pos, _, channel, msg)
local meta = minetest.get_meta(pos)
if channel ~= meta:get_string("channel") then
return
end
-- Convert string messages to tables:
if type(msg) == "string" then
local smsg = msg:lower()
msg = {}
if smsg == "get" then
msg.command = "get"
elseif smsg:sub(1,7) == "radius " then
msg.command = "radius"
msg.value = smsg:sub(8,-1)
elseif smsg == "on" then
msg.command = "on"
elseif smsg == "off" then
msg.command = "off"
elseif smsg == "restart" then
msg.command = "restart"
end
end
if type(msg) ~= "table" then
return
end
if msg.command == "get" then
digilines.receptor_send(pos, technic.digilines.rules, channel, {
enabled = meta:get_int("enabled"),
radius = meta:get_int("size"),
finished = meta:get_int("finished"),
dug_nodes = meta:get_int("dug"),
dig_level = meta:get_int("dig_level") - pos.y
})
elseif msg.command == "radius" then
local size = tonumber(msg.value)
if not size or size < 1 or size > 8 or size == meta:get_int("size") then
return
end
meta:set_int("size", size)
reset_quarry(pos)
set_quarry_status(pos)
elseif msg.command == "on" then
meta:set_int("enabled", 1)
set_quarry_status(pos)
elseif msg.command == "off" then
meta:set_int("enabled", 0)
set_quarry_status(pos)
elseif msg.command == "restart" then
reset_quarry(pos)
set_quarry_status(pos)
end
end
minetest.register_node("technic:quarry", {
description = S("%s Quarry"):format("HV"),
tiles = {
"technic_carbon_steel_block.png^pipeworks_tube_connection_metallic.png",
"technic_carbon_steel_block.png^technic_cable_connection_overlay.png",
"technic_carbon_steel_block.png^technic_cable_connection_overlay.png",
"technic_carbon_steel_block.png^technic_cable_connection_overlay.png",
"technic_carbon_steel_block.png^default_tool_mesepick.png",
"technic_carbon_steel_block.png^technic_cable_connection_overlay.png"
},
paramtype2 = "facedir",
groups = {cracky=2, tubedevice=1, technic_machine=1, technic_hv=1},
connect_sides = {"bottom", "front", "left", "right"},
tube = {
connect_sides = {top = 1},
-- lower priority than other tubes, so that quarries will prefer any
-- other tube to another quarry, which could lead to server freezes
-- in certain quarry placements (2x2 for example would never eject)
priority = 10,
can_go = function(pos, node, velocity, stack)
-- always eject the same, even if items came in another way
-- this further mitigates loops and generally avoids random sideway movement
-- that can be expected in certain quarry placements
return { quarry_eject_dir }
end
},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_int("size", 4)
meta:get_inventory():set_size("cache", 12)
reset_quarry(pos)
set_quarry_status(pos)
end,
on_rotate = function(pos, node, player, click, new_param2)
local meta = minetest.get_meta(pos)
if meta:get_int("enabled") == 1 then
return false
end
-- only allow rotation around y-axis
node.param2 = new_param2 % 4
minetest.swap_node(pos, node)
reset_quarry(pos)
set_quarry_status(pos)
return true
end,
after_place_node = function(pos, placer, itemstack)
minetest.get_meta(pos):set_string("owner", placer:get_player_name())
pipeworks.scan_for_tube_objects(pos)
end,
can_dig = function(pos,player)
return minetest.get_meta(pos):get_inventory():is_empty("cache")
end,
after_dig_node = pipeworks.scan_for_tube_objects,
on_receive_fields = quarry_receive_fields,
technic_run = quarry_run,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
return is_player_allowed(pos, player:get_player_name()) and count or 0
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
return is_player_allowed(pos, player:get_player_name()) and stack:get_count() or 0
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
return is_player_allowed(pos, player:get_player_name()) and stack:get_count() or 0
end,
mesecons = {
effector = {
action_on = function(pos)
local meta = minetest.get_meta(pos)
meta:set_int("enabled", 1)
set_quarry_status(pos)
end,
action_off = function(pos)
local meta = minetest.get_meta(pos)
meta:set_int("enabled", 0)
set_quarry_status(pos)
end
}
},
digiline = {
receptor = {
rules = technic.digilines.rules,
action = function() end,
},
effector = {
rules = technic.digilines.rules,
action = digiline_def,
},
},
})
minetest.register_craft({
recipe = {
{"technic:carbon_plate", "pipeworks:filter", "technic:composite_plate"},
{"basic_materials:motor", "technic:machine_casing", "technic:diamond_drill_head"},
{"technic:carbon_steel_block", "technic:hv_cable", "technic:carbon_steel_block"}},
output = "technic:quarry"
})
technic.register_machine("HV", "technic:quarry", technic.receiver)
@@ -0,0 +1,14 @@
-- The high voltage solar array is an assembly of medium voltage arrays.
-- Solar arrays are not able to store large amounts of energy.
minetest.register_craft({
output = 'technic:solar_array_hv 1',
recipe = {
{'technic:solar_array_mv', 'technic:solar_array_mv', 'technic:solar_array_mv'},
{'technic:carbon_plate', 'technic:hv_transformer', 'technic:composite_plate'},
{'', 'technic:hv_cable', ''},
}
})
technic.register_solar_array({tier="HV", power=100})