183 lines
4.5 KiB
Lua

local config = require 'config'
local _M = {}
_M.EVERYTHING = {type = 'virtual', name = 'signal-everything'}
local cache_mt = {
__index = function(self, key)
local entity = self.__entity.surface.create_entity {
name = config.SIGNAL_CACHE_NAME,
position = self.__entity.position,
force = self.__entity.force,
create_build_effect_smoke = false,
}
self.__cache_entities[key] = entity
entity.destructible = false
self.__entity.connect_neighbour {
wire = defines.wire_type.red,
target_entity = entity,
source_circuit_id = self.__circuit_id or nil,
}
self.__entity.connect_neighbour {
wire = defines.wire_type.green,
target_entity = entity,
source_circuit_id = self.__circuit_id or nil,
}
self[key] = {
__cb = entity.get_or_create_control_behavior(),
}
return self[key]
end,
}
function _M.init_global()
global.signals = global.signals or {}
global.signals.cache = global.signals.cache or {}
end
function _M.on_load()
for _, cache in pairs(global.signals.cache) do setmetatable(cache, cache_mt); end
end
_M.cache = {}
function _M.cache.get(entity, circuit_id)
local cache = global.signals.cache[entity.unit_number]
if not cache then
cache = setmetatable({
__entity = entity,
__circuit_id = circuit_id or false, -- Avoid calling __index when the id is nil
__cache_entities = {},
}, cache_mt)
global.signals.cache[entity.unit_number] = cache
end
return cache
end
function _M.cache.reset(entity, name)
local cache = global.signals.cache[entity.unit_number]
if cache and rawget(cache, name) then
global.signals.cache[entity.unit_number][name] = {
control_behavior = entity.get_or_create_control_behavior(),
}
end
end
function _M.cache.drop(entity)
local cache = global.signals.cache[entity.unit_number]
if cache then
for key, e in pairs(cache.__cache_entities) do e.destroy(); end
global.signals.cache[entity.unit_number] = nil
end
end
function _M.cache.move(entity)
local cache = global.signals.cache[entity.unit_number]
if cache then
for _, e in pairs(cache.__cache_entities) do e.teleport(entity); end
end
end
function _M.get_merged_signals(entity, circuit_id)
return circuit_id and (entity.get_merged_signals(circuit_id) or {}) or entity.get_merged_signals() or {}
end
function _M.get_merged_signal(entity, signal, circuit_id)
if circuit_id then return entity.get_merged_signal(signal, circuit_id)
else return entity.get_merged_signal(signal); end
end
function _M.get_highest(entity, circuit_id, update_count)
local cache = _M.cache.get(entity, circuit_id)
if cache.highest.valid
and not cache.highest.__cb.disabled
and (not cache.highest.value or not cache.highest_present.__cb.disabled)
then
if update_count and cache.highest.value and cache.highest_count.__cb.disabled then
local count = _M.get_merged_signal(entity, cache.highest.value.signal, circuit_id)
cache.highest.value.count = count
cache.highest_count.__cb.circuit_condition = {condition = {
comparator = '=',
first_signal = cache.highest.value.signal,
constant = count,
}}
end
return cache.highest.value
end
local highest = nil
for _, signal in pairs(_M.get_merged_signals(entity, circuit_id)) do
if highest == nil or signal.count > highest.count then highest = signal; end
end
cache.highest.valid = true
if highest then
cache.highest.value = highest
cache.highest.__cb.circuit_condition = {condition = {
comparator = '',
first_signal = _M.EVERYTHING,
second_signal = highest.signal,
}}
cache.highest_present.__cb.circuit_condition = {condition = {
comparator = '',
first_signal = highest.signal,
constant = 0,
}}
cache.highest_count.__cb.circuit_condition = {condition = {
comparator = '=',
first_signal = highest.signal,
constant = highest.count,
}}
else
cache.highest.value = nil
cache.highest.__cb.circuit_condition = {condition = {
comparator = '=',
first_signal = _M.EVERYTHING,
constant = 0,
}}
end
return highest
end
function _M.watch_highest_presence(entity, circuit_id)
local highest = _M.get_highest(entity, circuit_id)
local cache = _M.cache.get(entity, circuit_id)
if not highest then
cache.signal_present.valid = false
else
cache.signal_present.valid = true
cache.signal_present.__cb.circuit_condition = {condition = {
comparator = '>',
first_signal = highest.signal,
constant = 0,
}}
end
return highest
end
function _M.signal_present(entity, circuit_id)
local cache = _M.cache.get(entity, circuit_id)
return cache.signal_present.valid and not cache.signal_present.__cb.disabled
end
return _M