848 lines
34 KiB
Lua

require("util")
local compound_entities = require("prototypes.compound_entities.main_list")
return function (mod_name)
local common = {}
------------------------------------------------------------------------------------
-- Get mod name and path to mod
common.modName = script and script.mod_name or mod_name
common.modRoot = "__" .. common.modName .. "__"
------------------------------------------------------------------------------------
-- Greatly improved version check for mods (thanks to eradicator!)
common.Version = {}
do
local V = common.Version
local function parse_version(vstr) -- string "Major.Minor.Patch"
local err = function()
error('Invalid Version String: <' .. tostring(vstr) .. '>')
end
local r = {vstr:match('^(%d+)%.(%d+)%.(%d+)$')}
if #r ~= 3 then
err()
end
for i=1, 3 do
r[i] = tonumber(r[i])
end
return r
end
V.gtr = function(verA, verB)
local a, b, c = unpack(parse_version(verA))
local x, y, z = unpack(parse_version(verB))
return (a > x) or (a == x and b > y) or (a == x and b == y and c > z)
end
local map = {
['=' ] = function(A, B) return not (V.gtr(A, B) or V.gtr(B, A)) end,
['>' ] = V.gtr,
['!='] = function(A, B) return (V.gtr(A, B) or V.gtr(B, A)) end,
['<='] = function(A, B) return V.gtr(B, A) or (not V.gtr(A, B)) end,
['>='] = function(A, B) return V.gtr(A, B) or (not V.gtr(B, A)) end,
['~='] = function(A, B) return (V.gtr(A, B) or V.gtr(B, A)) end,
['<' ] = function(A, B) return V.gtr(B, A) end,
}
--~ common.Version.compare = function(mod_name, operator, need_version)
common.check_version = function(mod_name, operator, need_version)
local mod_version = (mods and mods[mod_name]) or (script and script.active_mods[mod_name])
return map[operator](mod_version, need_version)
end
end
------------------------------------------------------------------------------------
-- Sane values for collision masks
-- Default: {"item-layer", "object-layer", "rail-layer", "floor-layer", "water-tile"}
--~ common.RAIL_BRIDGE_MASK = {"floor-layer", "object-layer", "consider-tile-transitions"}
common.RAIL_BRIDGE_MASK = {"object-layer", "consider-tile-transitions"}
-- "Transport Drones" removes "object-layer" from rails, so if bridges have only
-- {"object-layer"}, there collision mask will be empty, and they can be built even
-- over cliffs. So we need to add another layer to bridges ("floor-layer").
-- As of Factorio 1.1.0, rails need to have "rail-layer" in their mask. This will work
-- alright, but isn't available in earlier versions of Factorio, so we will use
-- "floor-layer" there instead.
local need = common.check_version("base", ">=", "1.1.0") and "rail-layer" or "floor-layer"
table.insert(common.RAIL_BRIDGE_MASK, need)
-- Rails use basically the same mask as rail bridges, ...
common.RAIL_MASK = util.table.deepcopy(common.RAIL_BRIDGE_MASK)
-- ... we just need to add some layers so our rails have the same mask as vanilla rails.
table.insert(common.RAIL_MASK, "item-layer")
table.insert(common.RAIL_MASK, "water-tile")
--~ log("common.RAIL_BRIDGE_MASK: " .. serpent.block(common.RAIL_BRIDGE_MASK))
--~ log("common.RAIL_MASK: " .. serpent.block(common.RAIL_MASK))
------------------------------------------------------------------------------------
-- Set maximum_wire_distance of Power-to-rail connectors
common.POWER_TO_RAIL_WIRE_DISTANCE = 4
------------------------------------------------------------------------------------
-- List of compound entities
-- Key: name of the base entity
-- tab: name of the global table where data of these entity are stored
-- hidden: table containing the hidden entities needed by this entity
-- (Key: name under which the hidden entity will be stored in the table;
-- Value: name of the entity that should be placed)
common.compound_entities = compound_entities.get_HE_list()
-- Map the short handles of hidden entities (e.g. "pole") to real prototype types
-- (e.g. "electric-pole")
common.HE_map = compound_entities.HE_map
-- Reverse lookup
common.HE_map_reverse = compound_entities.HE_map_reverse
------------------------------------------------------------------------------------
-- There may be trees for which we don't want to create variations. These patterns
-- are used to build a list of trees we want to ignore.
common.ignore_name_patterns = {
-- Ignore our own trees
"bio%-tree%-.+%-%d",
-- Tree prototypes created by "Robot Tree Farm" or "Tral's Robot Tree Farm"
"rtf%-.+%-%d+",
}
-- Get list of tree prototypes that we want to ignore
common.get_tree_ignore_list = function()
--~ log("Entered function get_tree_ignore_list!")
local ignore = {}
local trees = game and
game.get_filtered_entity_prototypes({{filter = "type", type = "tree"}}) or
data.raw.tree
for tree_name, tree in pairs(trees) do
--~ log("tree_name: " .. tree_name)
for p, pattern in ipairs(common.ignore_name_patterns) do
--~ log("Check for match against pattern " .. pattern)
if tree_name:match(pattern) then
--~ log("Pattern matches!")
ignore[tree_name] = true
break
end
end
end
--~ log("Tree ignore list (" .. table_size(ignore) .. "): " .. serpent.block(ignore))
return ignore
end
------------------------------------------------------------------------------------
-- Enable writing to log file until startup options are set, so debugging output
-- from the start of a game session can be logged. This depends on a locally
-- installed dummy mod to allow debugging output during development without
-- spamming real users.
-- If the "_debug" dummy mod is active, debugging will always be on. If you don't
-- have this dummy mod but want to turn on logging anyway, set the default value
-- to "true"!
local default = false
common.is_debug = ( (mods and mods["_debug"]) or
(script and script.active_mods["_debug"])) and
true or default
------------------------------------------------------------------------------------
-- DEBUGGING FUNCTIONS --
------------------------------------------------------------------------------------
------------------------------------------------------------------------------------
-- Output debugging text
common.writeDebug = function(msg, tab, print_line)
local args = {}
-- Use serpent.line instead of serpent.block if this is true!
local line = print_line and
(string.lower(print_line) == "line" or string.lower(print_line) == "l") and
true or false
if common.is_debug then
if type(tab) ~= "table" then
tab = { tab }
end
local v
for k = 1, #tab do
v = tab[k]
-- NIL
if v == nil then
args[#args + 1] = "NIL"
-- TABLE
elseif type(v) == "table" then
args[#args + 1] = line and serpent.line(table.deepcopy(v)) or
serpent.block(table.deepcopy(v))
-- OTHER VALUE
else
args[#args + 1] = v
end
end
if #args == 0 then
args[1] = "nil"
end
args.n = #args
-- Print the message text to log and game
log(string.format(tostring(msg), table.unpack(args)))
if game then
game.print(string.format(tostring(msg), table.unpack(args)))
end
end
end
------------------------------------------------------------------------------------
-- Simple helper to show a single value with descriptive text
common.show = function(desc, term)
if common.is_debug then
common.writeDebug(tostring(desc) .. ": %s", type(term) == "table" and { term } or term)
end
end
------------------------------------------------------------------------------------
-- Print "entityname (id)"
common.print_name_id = function(entity)
local id
local name = "unknown entity"
if entity and entity.valid then
-- Stickers don't have an index or unit_number!
id = (entity.type == "sticker" and entity.type) or
entity.unit_number or entity.type
name = entity.name
end
--~ return name .. " (" .. tostring(id) .. ")"
return string.format("%s (%s)", name, id or "nil")
end
------------------------------------------------------------------------------------
-- Print "entityname"
common.print_name = function(entity)
return entity and entity.valid and entity.name or ""
end
------------------------------------------------------------------------------------
-- Throw an error if a wrong argument has been passed to a function
common.arg_err = function(arg, arg_type)
error(string.format(
"Wrong argument! %s is not %s!",
(arg or "nil"), (arg_type and "a valid " .. arg_type or "valid")
)
)
end
------------------------------------------------------------------------------------
-- Rudimentary check of the arguments passed to a function
common.check_args = function(arg, arg_type, desc)
if not (arg and type(arg) == arg_type) then
common.arg_err(arg or "nil", desc or arg_type or "nil")
end
end
------------------------------------------------------------------------------------
-- MOD SPECIFIC --
------------------------------------------------------------------------------------
------------------------------------------------------------------------------------
-- Are tiles from Alien Biomes available? (Returns true or false)
common.AB_tiles = function()
local ret = false
if game then
local AB = game.item_prototypes["fertilizer"].place_as_tile_result.result.name
-- In data stage, place_as_tile is only changed to Alien Biomes tiles if
-- both "vegetation-green-grass-1" and "vegetation-green-grass-3" exist. Therefore,
-- we only need to check for one tile in the control stage.
ret = (AB == "vegetation-green-grass-3") and true or false
else
ret = data.raw.tile["vegetation-green-grass-1"] and
data.raw.tile["vegetation-green-grass-3"] and true or false
end
return ret
end
------------------------------------------------------------------------------------
-- Function for removing individual entities
common.remove_entity = function(entity)
if entity and entity.valid then
--~ entity.destroy()
entity.destroy{raise_destroy = true}
end
end
------------------------------------------------------------------------------------
-- Function for removing invalid prototypes from list of compound entities
common.rebuild_compound_entity_list = function()
local f_name = "rebuild_compound_entity_list"
common.writeDebug("Entered function %s()", {f_name})
local ret = {}
local h_type
for c_name, c_data in pairs(common.compound_entities) do
common.show("base_name", c_name)
common.show("data", c_data)
-- Is the base entity in the game?
if c_data.base and c_data.base.name and game.entity_prototypes[c_data.base.name] then
-- Make a copy of the compound-entity data
common.writeDebug("%s exists -- copying data", {c_name})
ret[c_name] = util.table.deepcopy(c_data)
-- Check hidden entities
for h_key, h_data in pairs(ret[c_name].hidden) do
--~ h_type = common.HE_map[h_key]
common.writeDebug("h_key: %s\th_data: %s", {h_key, h_data})
-- Remove hidden entity if it doesn't exist
if not game.entity_prototypes[h_data.name] then
common.writeDebug("Removing %s (%s) from list of hidden entities!", {h_data.name, h_key})
ret[c_name].hidden[h_key] = nil
end
end
-- Clean table
else
local tab = c_data.tab
if tab then
-- Remove main table from global
common.writeDebug("Removing %s (%s obsolete entries)", {tab, #tab})
global[tab] = nil
end
-- If this compound entity requires additional tables in global, initialize
-- them now!
local related_tables = c_data.add_global_tables
if related_tables then
for t, tab in ipairs(related_tables or {}) do
common.writeDebug("Removing global[%s] (%s values)", {tab, table_size(global[tab])})
global[tab] = nil
end
end
-- If this compound entity requires additional values in global, remove them!
local related_vars = c_data.add_global_values
if related_vars then
for var_name, value in pairs(related_vars or {}) do
common.writeDebug("Removing global[%s] (was: %s)", {var_name, global[var_name]})
global[var_name] = nil
end
end
end
end
common.show("ret", ret)
return ret
end
------------------------------------------------------------------------------------
-- Function to add all optional values for a compound entity to the table entry.
common.add_optional_data = function(base)
local f_name = "add_optional_data"
common.writeDebug("Entered function %s(%s)", {f_name, common.print_name_id(base)})
if not (base and base.valid and global.compound_entities[base.name]) then
common.arg_err(base, "base of a compound entity")
end
-- Add optional values to global table
local data = global.compound_entities[base.name]
common.show("data", data)
local tab = data.tab
common.show("tab", tab)
common.show("global[tab]", global[tab] or "nil")
local entry = global[tab][base.unit_number]
for k, v in pairs(data.optional or {}) do
if entry[k] then
common.writeDebug("%s already exists: %s", {k, entry[k]})
else
entry[k] = v
common.writeDebug("Added data to %s: %s = %s", {common.print_name_id(base), k, v})
end
end
end
------------------------------------------------------------------------------------
-- Function for removing all parts of invalid compound entities
common.clean_global_compounds_table = function(entity_name)
local f_name = "clean_table"
common.writeDebug("Entered function %s(%s)", {f_name, entity_name or "nil"})
common.writeDebug("Entries in common.compound_entities[%s]: %s", {entity_name, table_size(global.compound_entities[entity_name])})
--~ local entity_table = global[common.compound_entities[entity_name].tab]
--~ local hidden_entities = common.compound_entities[entity_name].hidden
local entity_table = global.compound_entities[entity_name]
common.show("entity_table", entity_table and entity_table.tab)
entity_table = entity_table and entity_table.tab and global[entity_table.tab]
common.writeDebug("entity_table: %s", {entity_table}, "line")
local hidden_entities = global.compound_entities[entity_name].hidden
common.show("hidden_entities", hidden_entities)
local removed = 0
-- Scan the whole table
for c, compound in pairs(entity_table) do
common.writeDebug ("c: %s\tcompound: %s", {c, compound})
-- No or invalid base entity!
if not (compound.base and compound.base.valid) then
common.writeDebug("%s (%s) has no valid base entity -- removing entry!", {entity_name, c})
for h_name, h_entity in pairs(hidden_entities) do
common.writeDebug("Removing %s (%s)", {h_name, h_entity.name})
common.remove_entity(compound[h_name])
end
entity_table[c] = nil
removed = removed + 1
common.writeDebug("Removed %s %s", {entity_name, c})
end
end
common.show("Removed entities", removed)
common.show("Pruned list size", table_size(entity_table))
--~ common.show("Pruned list", entity_table)
return removed
end
------------------------------------------------------------------------------------
-- Function to resore missing parts of compound entities
common.restore_missing_entities = function(entity_name)
local f_name = "restore_missing_entities"
common.writeDebug("Entered function %s(%s)", {f_name, entity_name or "nil"})
--~ common.writeDebug("global.compound_entities[%s]: %s", {entity_name, global.compound_entities[entity_name]})
common.writeDebug("global.compound_entities[%s]: %s entries", {entity_name, table_size(global.compound_entities[entity_name])})
local check = global.compound_entities[entity_name]
local entity_table = check and global[check.tab] or {}
local hidden_entities = check and check.hidden or {}
local checked = 0
local restored = 0
-- Scan the whole table
for c, compound in pairs(entity_table) do
--~ common.writeDebug("c: %s\tcompound: %s", {c, compound})
-- Base entity is valid!
if (compound.base and compound.base.valid) then
common.writeDebug("%s is valid -- checking hidden entities!", {common.print_name_id(compound.base)})
for h_name, h_entity in pairs(hidden_entities) do
--~ common.writeDebug("h_name: %s\th_entity: %s", {h_name, h_entity})
-- Hidden entity is missing
if compound[h_name] and compound[h_name].valid then
common.writeDebug("%s: OK", {h_name})
else
common.writeDebug("%s: MISSING!", {h_name})
common.create_entities(entity_table, compound.base, {[h_name] = h_entity.name})
restored = restored + 1
common.writeDebug("Created %s (%s) for %s",
{h_name, h_entity.name, common.print_name_id(compound.base)})
end
end
checked = checked + 1
--~ common.writeDebug("Restored %s %s", {entity_name, c})
end
end
common.writeDebug("Checked %s compound entities", {checked})
common.writeDebug("Restored %s entities", {restored})
--~ common.show("Fixed list", entity_table)
return {checked = checked, restored = restored}
end
------------------------------------------------------------------------------------
-- Function to find all unregistered compound entities of a particular type
common.register_in_compound_entity_tab = function(compound_name)
local f_name = "register_in_compound_entity_tab"
common.writeDebug("Entered function %s(%s)", {f_name, compound_name})
local cnt = 0
local h_cnt = 0
local data = global.compound_entities[compound_name]
if not data then
common.arg_err(compound_name, "name of a compound entity")
end
local g_tab = global[data.tab]
local found, h_found ,created
-- Scan all surfaces
for s, surface in pairs(game.surfaces) do
-- Check the bases of all compound entities on the surface
found = surface.find_entities_filtered({name = compound_name})
for b, base in ipairs(found) do
-- Base entity isn't registered yet!
if not g_tab[base.unit_number] then
common.writeDebug("Found unregistered entity: %s!", {common.print_name_id(base)})
-- Create an entry in the global table
g_tab[base.unit_number] = {base = base}
-- Add optional data to the table, if there are any
common.add_optional_data(base)
-- Check if it already has any hidden entities
for h_name, h_data in pairs(data.hidden) do
h_found = surface.find_entities_filtered({
name = h_data.name,
type = h_data.type,
position = common.offset_position(base.position, h_data.base_offset),
})
-- Check for multiple hidden entities of the same type in the same position!
if #h_found > 1 then
local cnt = 0
for duplicate = 2, #h_found do
h_found[duplicate].destroy({raise_destroy = true})
cnt = cnt + 1
end
common.writeDebug("Removed %s duplicate entities (%s)!", {cnt, h_data.name})
end
-- There still is one hidden entity left. Add it to the table!
if next(h_found) then
common.writeDebug("Found %s -- adding it to the table.", {common.print_name_id(base)})
g_tab[base.unit_number][h_name] = h_found[1]
-- Create hidden entity! This will automatically add it to the table.
else
created = common.create_entities(g_tab, base, {[h_name] = h_data})
common.writeDebug("Created hidden %s: %s",
{h_name, created and common.print_name_id(created) or "nil"})
h_cnt = h_cnt + 1
end
end
cnt = cnt + 1
end
end
end
common.writeDebug("Registered %s compound entities and created %s hidden entities", {cnt, h_cnt})
return cnt
end
------------------------------------------------------------------------------------
-- Function to find all unregistered compound entities
common.find_unregistered_entities = function()
local f_name = "find_unregistered_entities"
common.writeDebug("Entered function %s()", {f_name})
local cnt = 0
for compound_entity, c in pairs(global.compound_entities) do
cnt = cnt + common.register_in_compound_entity_tab(compound_entity)
end
--~ common.writeDebug("Registered %s compound entities", {cnt})
common.writeDebug("Registered %s compound entities.", {cnt})
return cnt
end
------------------------------------------------------------------------------------
-- Function to normalize positions
common.normalize_position = function(pos)
if pos and type(pos) == "table" and table_size(pos) == 2 then
local x = pos.x or pos[1]
local y = pos.y or pos[2]
if x and y and type(x) == "number" and type(y) == "number" then
return { x = x, y = y }
end
end
end
------------------------------------------------------------------------------------
-- Calculate the offset position of a hidden entity
common.offset_position = function(base_pos, offset)
common.check_args(base_pos, "table", "position")
offset = offset or {x = 0, y = 0}
common.check_args(offset, "table", "position")
base_pos = common.normalize_position(base_pos)
offset = common.normalize_position(offset)
common.show("base_pos", base_pos)
common.show("offset", offset)
common.show("new", {x = base_pos.x + offset.x, y = base_pos.y + offset.y})
return {x = base_pos.x + offset.x, y = base_pos.y + offset.y}
end
------------------------------------------------------------------------------------
-- Check if argument is a valid surface
common.is_surface = function(surface)
local t = type(surface)
surface = (t == "number" or t == "string" and game.surfaces[surface]) or
(t == "table" and surface.object_name and
surface.object_name == "LuaSurface" and surface)
return surface
end
------------------------------------------------------------------------------------
-- Make hidden entities unminable and indestructible
local function make_unminable(entities)
for e, entity in ipairs(entities or {}) do
if entity.valid then
entity.minable = false
entity.destructible = false
end
end
end
--------------------------------------------------------------------
-- Create and register hidden entities
--~ common.create_entities = function(g_table, base_entity, hidden_entity_names, position, ...)
common.create_entities = function(g_table, base_entity, hidden_entities)
local f_name = "create_entities"
common.writeDebug("Entered function %s(%s, %s, %s)",
{f_name, "g_table", base_entity, hidden_entities})
common.show("#g_table", g_table and table_size(g_table))
--~ common.show("hidden_entities", hidden_entities)
common.check_args(g_table, "table")
common.check_args(base_entity, "table")
if not base_entity.valid then
common.arg_err(base_entity, "base entity")
-- A table is required, but it may be empty! (This is needed for the
-- bio gardens, which only have a hidden pole if the "Easy Gardens"
-- setting is enabled.)
elseif not (hidden_entities and type(hidden_entities) == "table") then
common.arg_err(hidden_entities, "array of hidden-entity names")
end
local base_pos = common.normalize_position(base_entity.position) or
common.arg_err(position or "nil", "position")
local entity, offset, pos
-- Initialize entry in global table
g_table[base_entity.unit_number] = g_table[base_entity.unit_number] or {}
g_table[base_entity.unit_number].base = base_entity
-- Create hidden entities
local data
for key, tab in pairs(hidden_entities) do
common.writeDebug("key: %s\tname: %s", {key, tab})
--~ data = common.compound_entities[base_entity.name].hidden[key]
data = global.compound_entities[base_entity.name].hidden[key]
--~ common.show("common.compound_entities[base_entity.name].hidden",
--~ common.compound_entities[base_entity.name].hidden)
common.show("data", data)
entity = base_entity.surface.create_entity({
name = data.name,
type = data.type,
position = common.offset_position(base_pos, data.base_offset),
force = base_entity.force,
})
-- Raise the event manually, so we can pass on extra data!
script.raise_event(defines.events.script_raised_built, {
entity = entity,
base_entity = base_entity
})
-- Make hidden entity unminable/undestructible
make_unminable({entity})
-- Add hidden entity to global table
g_table[base_entity.unit_number][key] = entity
end
-- Add optional values to global table
--~ local optional = global.compound_entities[base_entity.name].optional
--~ for k, v in pairs(optional or {}) do
--~ g_table[base_entity.unit_number][k] = v
--~ end
common.add_optional_data(base_entity)
common.writeDebug("g_table[%s]: %s", {base_entity.unit_number, g_table[base_entity.unit_number]})
end
--------------------------------------------------------------------
-- Make a list of the pole types that Bio gardens may connect to
common.get_garden_pole_connectors = function()
--~ local ret = {}
local ret
if common.get_startup_setting("BI_Easy_Bio_Gardens") then
common.writeDebug("\"Easy gardens\": Compiling list of poles they can connect to!" )
ret = {}
local poles = game.get_filtered_entity_prototypes({
{filter = "type", type = "electric-pole"},
{filter = "name", name = {
-- Poles named here will be ignored!
"bi-bio-garden-hidden-pole"
}, invert = "true", mode = "and"
}
})
for p, pole in pairs(poles) do
ret[#ret + 1] = pole.name
end
else
common.writeDebug("\"Easy gardens\": Not active -- nothing to do!" )
end
return ret
end
--------------------------------------------------------------------
-- Connect hidden poles of Bio gardens!
-- (This function may be called for hidden poles that have not been
-- added to the table yet if the pole has just been built. In this
-- case, we pass on the new pole explicitly!)
common.connect_garden_pole = function(base, new_pole)
local compound_entity = global.compound_entities["bi-bio-garden"]
--~ local pole_type = "electric-pole"
--~ local pole = global[compound_entity.tab][base.unit_number] and
--~ global[compound_entity.tab][base.unit_number][pole_type] or
--~ new_pole
local pole = global[compound_entity.tab][base.unit_number] and
global[compound_entity.tab][base.unit_number].pole or
new_pole
--~ if pole and pole.valid then
--~ local wire_reach = game.entity_prototypes[compound_entity.hidden[pole_type]] and
--~ game.entity_prototypes[compound_entity.hidden[pole_type]].max_wire_distance
if pole and pole.valid and compound_entity.hidden and
compound_entity.hidden.pole and
compound_entity.hidden.pole.name then
local wire_reach = game.entity_prototypes[compound_entity.hidden.pole.name] and
game.entity_prototypes[compound_entity.hidden.pole.name].max_wire_distance
if not wire_reach then
error("Prototype for hidden pole of Bio gardens doesn't exist!")
end
pole.disconnect_neighbour()
-- Each pole can only have 5 connections. Let's connect to other hidden
-- poles first!
local connected
local neighbours = pole.surface.find_entities_filtered({
position = pole.position,
radius = wire_reach,
type = "electric-pole",
name = compound_entity.hidden.pole.name
})
common.writeDebug("Pole %g has %s neighbours", {pole.unit_number, #neighbours - 1})
for n, neighbour in pairs(neighbours or{}) do
if pole ~= neighbour then
connected = pole.connect_neighbour(neighbour)
common.writeDebug("Connected pole %g to %s %g: %s",
{pole.unit_number, neighbour.name, neighbour.unit_number, connected})
end
end
--~ -- Connect hidden poles to other poles that may be in reach.
--~ common.garden_pole_connectors = common.garden_pole_connectors and next() or
--~ common.get_garden_pole_connectors()
--~ common.show("Poles hidden bio-garden poles may connect to", global.mod_settings.garden_pole_connectors)
-- Look for other poles around this one
neighbours = pole.surface.find_entities_filtered({
position = pole.position,
radius = wire_reach,
type = "electric-pole",
name = global.mod_settings.garden_pole_connectors,
})
common.writeDebug("Pole %g has %s neighbours", {pole.unit_number, #neighbours})
for n, neighbour in pairs(neighbours or{}) do
connected = pole.connect_neighbour(neighbour)
common.writeDebug("Connected pole %g to neighbour %s (%g): %s",
{pole.unit_number, neighbour.name, neighbour.unit_number, connected})
end
end
end
--------------------------------------------------------------------
-- Connect hidden poles of powered rails -- this is also used in
-- migration scripts, so make it a function in common.lua!
-- (This function may be called for hidden poles that have not been
-- added to the table yet if the pole has just been built. In this
-- case, we pass on the new pole explicitly!)
common.connect_power_rail = function(base, new_pole)
--~ local pole_type = "electric-pole"
local pole = global.bi_power_rail_table[base.unit_number].pole or new_pole
if pole and pole.valid then
-- Remove all copper wires from new pole
pole.disconnect_neighbour()
common.writeDebug("Removed all wires from %s %g", {pole.name, pole.unit_number})
-- Look for connecting rails at front and back of the new rail
for s, side in ipairs( {"front", "back"} ) do
common.writeDebug("Looking for rails at %s", {side})
local neighbour
-- Look in all three directions
for d, direction in ipairs( {"left", "straight", "right"} ) do
common.writeDebug("Looking for rails in %s direction", {direction})
neighbour = base.get_connected_rail{
rail_direction = defines.rail_direction[side],
rail_connection_direction = defines.rail_connection_direction[direction]
}
common.writeDebug("Rail %s of %s (%s): %s (%s)", {direction, base.name, base.unit_number, (neighbour and neighbour.name or "nil"), (neighbour and neighbour.unit_number or "nil")})
-- Only make a connection if found rail is a powered rail
-- (We'll know it's the right type if we find it in our table!)
neighbour = neighbour and neighbour.valid and global.bi_power_rail_table[neighbour.unit_number]
if neighbour and neighbour.pole and neighbour.pole.valid then
pole.connect_neighbour(neighbour.pole)
common.writeDebug("Connected poles!")
end
end
end
-- Look for Power-rail connectors
local connector = base.surface.find_entities_filtered{
position = base.position,
radius = common.POWER_TO_RAIL_WIRE_DISTANCE, -- maximum_wire_distance of Power-to-rail-connectors
name = "bi-power-to-rail-pole"
}
-- Connect to first Power-rail connector we've found
if connector and next(connector) then
pole.connect_neighbour(connector[1])
common.writeDebug("Connected " .. pole.name .. " (" .. pole.unit_number ..
") to " .. connector[1].name .. " (" .. connector[1].unit_number .. ")")
common.writeDebug("Connected %s (%g) to %s (%g)", {pole.name, pole.unit_number, connector[1].name, connector[1].unit_number})
end
common.writeDebug("Stored %s (%g) in global table", {base.name, base.unit_number})
end
end
------------------------------------------------------------------------------------
-- Get the value of a startup setting
common.get_startup_setting = function(setting_name)
return settings.startup[setting_name] and settings.startup[setting_name].value
end
------------------------------------------------------------------------------------
-- Add the "icons" property based on the value of "icon"
------------------------------------------------------------------------------------
common.BI_add_icons = function()
for tab_name, tab in pairs(data.raw) do
--~ common.writeDebug("Checking data.raw[%s]", {tab_name})
for proto_type_name, proto_type in pairs(data.raw[tab_name] or {}) do
--~ common.show("proto_type.BI_add_icon", proto_type.BI_add_icon or "nil" )
if proto_type.BI_add_icon then
proto_type.icons = {
{
icon = proto_type.icon,
icon_size = proto_type.icon_size,
icon_mipmaps = proto_type.icon_mipmaps
}
}
proto_type.BI_add_icon = nil
common.writeDebug("Added \"icons\" property to data.raw[\"%s\"][\"%s\"]: %s",
{tab_name, proto_type_name, proto_type.icons}, "line")
end
end
end
end
------------------------------------------------------------------------------------
-- END OF FILE
------------------------------------------------------------------------------------
return common
end