technic-cd2025/technic/machines/switching_station.lua

178 lines
5.2 KiB
Lua

-- See also technic/doc/api.md
local mesecons_path = minetest.get_modpath("mesecons")
local S = technic.getter
local cable_entry = "^technic_cable_connection_overlay.png"
minetest.register_craft({
output = "technic:switching_station",
recipe = {
{"", "technic:lv_transformer", ""},
{"default:copper_ingot", "technic:machine_casing", "default:copper_ingot"},
{"technic:lv_cable", "technic:lv_cable", "technic:lv_cable"}
}
})
local function start_network(pos)
local tier = technic.sw_pos2tier(pos)
if not tier then
local meta = minetest.get_meta(pos)
meta:set_string("infotext", S("%s Has No Network"):format(S("Switching Station")))
return
end
local network_id = technic.sw_pos2network(pos) or technic.create_network(pos)
technic.activate_network(network_id)
end
local mesecon_def
if mesecons_path then
mesecon_def = {effector = {
rules = mesecon.rules.default,
}}
end
minetest.register_node("technic:switching_station",{
description = S("Switching Station"),
tiles = {
"technic_water_mill_top_active.png",
"technic_water_mill_top_active.png"..cable_entry,
"technic_water_mill_top_active.png",
"technic_water_mill_top_active.png",
"technic_water_mill_top_active.png",
"technic_water_mill_top_active.png"},
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_all_tiers=1},
connect_sides = {"bottom"},
sounds = default.node_sound_wood_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", S("Switching Station"))
meta:set_string("formspec", "field[channel;Channel;${channel}]")
start_network(pos)
-- start nodetimer
minetest.get_node_timer(pos):start(1.0)
end,
on_destruct = function(pos)
-- Remove network when switching station is removed, if
-- there's another switching station network will be rebuilt.
local network_id = technic.sw_pos2network(pos)
if technic.networks[network_id] then
technic.remove_network(network_id)
end
end,
on_receive_fields = function(pos, formname, fields, sender)
if not fields.channel then
return
end
local plname = sender:get_player_name()
if minetest.is_protected(pos, plname) then
minetest.record_protection_violation(pos, plname)
return
end
local meta = minetest.get_meta(pos)
meta:set_string("channel", fields.channel)
end,
-- nodetimer for network activation
on_timer = function(pos)
local network_id = technic.sw_pos2network(pos)
-- Check if network is overloaded / conflicts with another network
if network_id then
local infotext
local meta = minetest.get_meta(pos)
if technic.is_overloaded(network_id) then
local remaining = technic.reset_overloaded(network_id)
if remaining > 0 then
infotext = S("%s Network Overloaded, Restart in %dms"):format(S("Switching Station"), remaining / 1000)
else
infotext = S("%s Restarting Network"):format(S("Switching Station"))
end
technic.network_infotext(network_id, infotext)
else
-- Network exists and is not overloaded, reactivate network
technic.activate_network(network_id)
infotext = technic.network_infotext(network_id)
end
meta:set_string("infotext", infotext)
else
-- Network does not exist yet, attempt to create new network here
start_network(pos)
end
-- restart the nodetimer again
return true
end,
-- mesecons
mesecons = mesecon_def,
-- digiline
digiline = {
receptor = {
rules = technic.digilines.rules,
action = function() end
},
effector = {
rules = technic.digilines.rules,
action = function(pos, node, channel, msg)
if msg ~= "GET" and msg ~= "get" then
return
end
local meta = minetest.get_meta(pos)
if channel ~= meta:get_string("channel") then
return
end
local network_id = technic.sw_pos2network(pos)
local network = network_id and technic.networks[network_id]
if network then
digilines.receptor_send(pos, technic.digilines.rules, channel, {
supply = network.supply,
demand = network.demand,
lag = network.lag
})
else
digilines.receptor_send(pos, technic.digilines.rules, channel, {
error = "No network",
})
end
end
},
},
})
-----------------------------------------------
-- The action code for the switching station --
-----------------------------------------------
-- Timeout ABM
-- Timeout for a node in case it was disconnected from the network
-- A node must be touched by the station continuously in order to function
minetest.register_abm({
label = "Machines: timeout check",
nodenames = {"group:technic_machine"},
interval = 1,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
if not technic.machine_tiers[node.name] then
-- https://github.com/mt-mods/technic/issues/123
return
end
-- Check for machine timeouts for all tiers
local tiers = technic.machine_tiers[node.name]
local timed_out = true
for _, tier in ipairs(tiers) do
local timeout = technic.get_timeout(tier, pos)
if timeout > 0 then
technic.touch_node(tier, pos, timeout - 1)
timed_out = false
end
end
-- If all tiers for machine timed out take action
if timed_out then
technic.disable_machine(pos, node)
end
end,
})