117 lines
3.2 KiB
Lua

local config = require 'config'
local _M = {}
local function get_entity(entity, position)
return entity.surface.find_entity(config.SETTINGS_ENTITY_NAME, position or entity.position)
end
local function get_or_create_entity(entity)
return get_entity(entity) or entity.surface.create_entity {
name = config.SETTINGS_ENTITY_NAME,
position = entity.position,
force = entity.force,
create_build_effect_smoke = false,
alert_parameters = {alert_message = 'nil'},
}
end
function _M.def(defs)
local res = {by_key = {}, by_name = {}}
for name, def in pairs(defs) do
if type(name) == 'string' then
if type(def) ~= 'table' then def = {def, 'raw'}; end
local key, typ = def[1], def[2]
local tdef = {name = name, key = key, type = typ}
res.by_key[key] = tdef; res.by_name[name] = tdef
if not typ then
tdef.type = 'table'
tdef.defs = _M.def(def)
end
end
end
return res
end
local function _dump(defs, tab)
if type(tab) ~= 'table' then return tab; end
local res = {}
for name, value in pairs(tab) do
local def = defs.by_name[name]
if def then
if def.type == 'table' then res[def.key] = _dump(def.defs, value)
elseif def.type == 'bool' then res[def.key] = (value and 1) or 0
else res[def.key] = value; end
end
end
return res
end
function _M.dump(defs, tab) return serpent.line(_dump(defs, tab), {compact = true}); end
local function _parse(defs, raw)
if type(raw) ~= 'table' then return raw; end
local res = {}
for key, value in pairs(raw) do
local def = defs.by_key[key]
if def then
if def.type == 'table' then res[def.name] = _parse(def.defs, value)
elseif def.type == 'bool' then res[def.name] = value == 1
else res[def.name] = value; end
end
end
return res
end
function _M.parse(defs, str) return _parse(defs, load('return '..str)()); end
function _M.read(defs, entity, default)
local e = get_or_create_entity(entity)
local res = _M.parse(defs, e.alert_parameters.alert_message)
if not res and default ~= nil then _M.update(defs, entity, default); end
return res or default
end
function _M.update(defs, entity, settings)
local e = get_or_create_entity(entity)
e.alert_parameters = {alert_message = _M.dump(defs, settings)}
end
function _M.move_entity(entity, original_position)
local e = get_entity(entity, original_position)
if e then e.teleport(entity.position); end
end
function _M.destroy(entity)
local e = get_entity(entity)
if e then e.destroy(); end
end
function _M.fill_defaults(target, defaults)
for key, value in pairs(defaults) do
if target[key] == nil then target[key] = value
elseif type(value) == 'table' then _M.fill_defaults(target[key], value); end
end
end
return setmetatable(_M, {__call=function(cls, defs)
return {
defs = _M.def(defs),
parse = function(self, str) return _M.parse(self.defs, str); end,
dump = function(self, tab) return _M.dump(self.defs, tab); end,
read = function(self, entity, default) return _M.read(self.defs, entity, default); end,
update = function(self, entity, settings) return _M.update(self.defs, entity, settings); end,
read_or_default = function(self, entity, default)
local res = self:read(entity, default)
_M.fill_defaults(res, default)
return res
end,
}
end})