Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 84 additions & 50 deletions tubes/signal.lua
Original file line number Diff line number Diff line change
@@ -1,70 +1,104 @@
-- luacheck: globals DIR_DELIM

local S = core.get_translator("pipeworks")
local storage = core.get_mod_storage()
local STORAGE_PREFIX = "detector_timer_"

-- the core.after() calls below can sometimes trigger after a tube
-- breaks, at which point item_exit() is no longer valid, so we have to make
-- sure that there even IS a callback to run, first.
if core.get_modpath("mesecons") and pipeworks.enable_detector_tube then
local detector_tube_step = 5 * (tonumber(core.settings:get("dedicated_server_step")) or 0.09)

local function after_break(pos)
local name = core.get_node(pos).name
if core.registered_nodes[name].item_exit then
core.registered_nodes[name].item_exit(pos)
-- in-memory table to avoid traversing the whole storage in globalstep
-- { [position_hash] = time }
local detector_timers = {}

-- populate our in-memory table from storage
for key, val in pairs(storage:to_table().fields) do
local short_key = string.match(key, "^"..STORAGE_PREFIX.."(.+)")
if short_key then
local hash = tonumber(short_key)
detector_timers[hash] = tonumber(val)
end
end

local function detector_set_timer(pos, time)
local hash = core.hash_node_position(pos)
time = time or detector_tube_step
-- timer will be refreshed if already set
detector_timers[hash] = time
storage:set_float(string.format("%s%.0f", STORAGE_PREFIX, hash), time)
end

local function detector_remove_timer(pos)
local hash = core.hash_node_position(pos)
detector_timers[hash] = nil
storage:set_string(string.format("%s%.0f", STORAGE_PREFIX, hash), "")
end

core.register_globalstep(function(dtime)
for hash, time in pairs(detector_timers) do
local pos = core.get_position_from_hash(hash)
time = time - dtime
if time <= 0 then
local node = core.get_node_or_nil(pos)
if node then
detector_remove_timer(pos)
if string.find(node.name, "pipeworks:detector_tube_on_", 1, true) then
node.name = string.gsub(node.name, "on", "off", 1)
core.swap_node(pos, node)
mesecon.receptor_off(pos, pipeworks.mesecons_rules)
end
end
-- in case the area wasn't loaded, do not remove the timer
else
detector_set_timer(pos, time)
end
end
end)

-- cleanup metadata from previous versions
local function detector_cleanup_metadata(pos)
local meta = core.get_meta(pos)
if not meta then return end
-- an empty string deletes the key even if the previous value wasn't a string
meta:set_string("nitems", "")
end
end

if core.get_modpath("mesecons") and pipeworks.enable_detector_tube then
local detector_tube_step = 5 * (tonumber(core.settings:get("dedicated_server_step")) or 0.09)
pipeworks.register_tube("pipeworks:detector_tube_on", {
description = S("Detecting Pneumatic Tube Segment on"),
inventory_image = "pipeworks_detector_tube_inv.png",
plain = { "pipeworks_detector_tube_plain.png" },
node_def = {
tube = {can_go = function(pos, node, velocity, stack)
local meta = core.get_meta(pos)
local nitems = meta:get_int("nitems")+1
meta:set_int("nitems", nitems)
local saved_pos = vector.new(pos)
core.after(detector_tube_step, after_break, saved_pos)
return pipeworks.notvel(pipeworks.meseadjlist,velocity)
end},
tube = {
can_go = function(pos, node, velocity, stack)
detector_cleanup_metadata(pos)
detector_set_timer(pos)
return pipeworks.notvel(pipeworks.meseadjlist, velocity)
end,
},
groups = {mesecon = 2, not_in_creative_inventory = 1},
drop = "pipeworks:detector_tube_off_1",
mesecons = {receptor = {state = "on", rules = pipeworks.mesecons_rules}},
item_exit = function(pos)
local meta = core.get_meta(pos)
local nitems = meta:get_int("nitems")-1
local node = core.get_node(pos)
local name = node.name
local fdir = node.param2
if nitems == 0 then
core.set_node(pos, {name = string.gsub(name, "on", "off"), param2 = fdir})
mesecon.receptor_off(pos, pipeworks.mesecons_rules)
else
meta:set_int("nitems", nitems)
end
end,
on_construct = function(pos)
local meta = core.get_meta(pos)
meta:set_int("nitems", 1)
core.after(detector_tube_step, after_break, pos)
end,
},
})

pipeworks.register_tube("pipeworks:detector_tube_off", {
description = S("Detecting Pneumatic Tube Segment"),
inventory_image = "pipeworks_detector_tube_inv.png",
plain = { "pipeworks_detector_tube_plain.png" },
node_def = {
tube = {can_go = function(pos, node, velocity, stack)
local node = core.get_node(pos)
local name = node.name
local fdir = node.param2
core.set_node(pos,{name = string.gsub(name, "off", "on"), param2 = fdir})
mesecon.receptor_on(pos, pipeworks.mesecons_rules)
return pipeworks.notvel(pipeworks.meseadjlist, velocity)
end},
groups = {mesecon = 2},
mesecons = {receptor = {state = "off", rules = pipeworks.mesecons_rules }},
description = S("Detecting Pneumatic Tube Segment"),
inventory_image = "pipeworks_detector_tube_inv.png",
plain = {"pipeworks_detector_tube_plain.png"},
node_def = {
tube = {
can_go = function(pos, node, velocity, stack)
detector_cleanup_metadata(pos)
node.name = string.gsub(node.name, "off", "on", 1)
core.swap_node(pos, node)
mesecon.receptor_on(pos, pipeworks.mesecons_rules)
detector_set_timer(pos)
return pipeworks.notvel(pipeworks.meseadjlist, velocity)
end,
},
groups = {mesecon = 2},
mesecons = {receptor = {state = "off", rules = pipeworks.mesecons_rules}},
},
})

core.register_craft( {
Expand Down