1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-10 00:43:27 +02:00
ComfyFactorio/maps/planet_prison/mod/bp.lua
2021-03-22 22:34:45 +01:00

402 lines
9.8 KiB
Lua

local CommonFunctions = require 'maps.planet_prison.mod.common'
local Global = require 'utils.global'
local Token = require 'utils.token'
local this = {
_bps = {}
}
local Public = {}
local insert = table.insert
local remove = table.remove
Global.register(
this,
function(tbl)
this = tbl
end
)
--[[
push_blueprint - Pushes blueprint into a list.
@param name - Handle of a blueprint.
@param bp - Blueprint in JSON format.
--]]
Public.push_blueprint = function(name, bp)
local entry = {
bp = game.json_to_table(bp).blueprint,
hook = nil,
refs = {}
}
this._bps[name] = entry
end
--[[
set_blueprint_hook - Set callback to a blueprint.
@param name - Handle of a blueprint
@param hook - Callback that will be called after blueprint is placed.
--]]
Public.set_blueprint_hook = function(name, hook)
if name == nil then
log('bp.set_blueprint_hook: name is nil')
return
end
if this._bps[name] == nil then
log('bp.set_blueprint_hook: unrecognized blueprint')
return
end
if hook and type(hook) ~= 'number' then
local token = Token.register(hook)
this._bps[name].hook = token
else
this._bps[name].hook = hook
end
end
--[[
get_references - Get all references of the blueprint on the map.
@param name - Blueprint handle.
--]]
Public.get_references = function(name)
if name == nil then
log('bp.get_references: name is nil')
return {}
end
local object = this._bps[name]
if object == nil then
log('bp.get_references: unrecognized blueprint')
return {}
end
return object.refs
end
--[[
get_references - Gets opaque object representing bp references.
@param name - Blueprint handle.
--]]
Public.get_references = function(name)
if name == nil then
log('bp.get_references: name is nil')
return
end
local object = this._bps[name]
if object == nil then
log('bp.get_references: unrecognized blueprint')
return
end
return object.refs
end
--[[
reference_get_bounding_box - Return bounding box from the reference.
@param reference - Valid reference object fetched from get_references.
--]]
Public.reference_get_bounding_box = function(reference)
return reference.bb
end
--[[
reference_get_entities - Return references to entities.
@param reference - Valid reference object fetched from get_references.
--]]
Public.reference_get_entities = function(reference)
return reference.entities
end
--[[
reference_get_timestamp - Return timestamp of a reference
@param reference - Valid reference object fetched from get_references.
--]]
Public.reference_get_timestamp = function(reference)
return reference.timestamp
end
--[[
unlink_references_filtered - Unlinks all references of blueprint on the map if they
meet the query rules.
@param name - Blueprint handle.
@param query - Additional parameter by which unlinking is guided
@param query.timestamp - If reference is older that submitted timestamp, it will be
unlinked.
@return An array of unlinked references.
--]]
Public.unlink_references_filtered = function(name, query)
if name == nil then
log('bp.get_references: name is nil')
return
end
local object = this._bps[name]
if object == nil then
log('bp.get_references: unrecognized blueprint')
return
end
local refs = {}
for i = #object.refs, 1, -1 do
local ref = object.refs[i]
if query and query.timestamp then
if ref.timestamp > query.timestamp then
goto continue
end
end
insert(refs, ref)
remove(object.refs, i)
::continue::
end
return refs
end
--[[
destroy_references_filtered - Destroys all references of blueprint on the map if they
meet the query rules.
@param surf - Surface on which blueprints are placed.
@param name - Blueprint handle.
@param query - Additional parameter by which removal is guided
@param query.timestamp - If reference is older that submitted timestamp, it will be
removed.
--]]
Public.destroy_references_filtered = function(surf, name, query)
if name == nil then
log('bp.get_references: name is nil')
return
end
local object = this._bps[name]
if object == nil then
log('bp.get_references: unrecognized blueprint')
return
end
for i = 1, #object.refs do
local ref = object.refs[i]
if query and query.timestamp then
if ref.timestamp > query.timestamp then
goto continue
end
end
for _, ent in pairs(ref.entities) do
if ent.valid then
ent.destroy()
end
end
local tiles = {}
for _, tile in pairs(ref.tiles) do
tile.name = 'concrete'
insert(tiles, tile)
end
surf.set_tiles(tiles)
remove(object.refs, i)
::continue::
end
end
--[[
destroy_references - Destroys all references of blueprint on the map
@param surf - Surface on which blueprints are placed.
@param name - Blueprint handle.
--]]
Public.destroy_references = function(surf, name)
Public.destroy_references_filtered(surf, name, {})
end
local _bp_destroy_reference = function(surf, ref)
for _, ent in pairs(ref.entities) do
if ent.valid then
ent.destroy()
end
end
local tiles = {}
for _, tile in pairs(ref.tiles) do
if tile.valid then
goto continue
end
tile.name = 'concrete'
insert(tiles, tile)
::continue::
end
surf.set_tiles(tiles)
end
--[[
destroy_reference - Destroys reference of a blueprint at given surface.
@param surf - Surface on which blueprints are placed.
@param reference - Any valid reference.
--]]
Public.destroy_reference = function(surf, reference)
for _, meta in pairs(this._bps) do
for i = 1, #meta.refs do
local ref = meta.refs[i]
if reference.id == ref.id then
_bp_destroy_reference(surf, ref)
remove(meta.refs, i)
return
end
end
end
end
local function _build_tiles(surf, point, tiles)
local _tiles = {}
local get_axis = CommonFunctions.get_axis
for _, tile in pairs(tiles) do
local _tile = {
name = tile.name,
position = {
x = get_axis(tile.position, 'x') + get_axis(point, 'x'),
y = get_axis(tile.position, 'y') + get_axis(point, 'y')
}
}
insert(_tiles, _tile)
end
surf.set_tiles(_tiles)
return _tiles
end
local function _build_entities(surf, point, entities, hook, player)
local _entities = {}
local get_axis = CommonFunctions.get_axis
for _, ent in pairs(entities) do
local ent_info = {
position = {
x = get_axis(ent.position, 'x') + get_axis(point, 'x'),
y = get_axis(ent.position, 'y') + get_axis(point, 'y')
},
name = ent.name
}
local e = surf.create_entity(ent_info)
if not e or not e.valid then
goto continue
end
if ent.fill then
e.insert({name = ent.fill.name, count = ent.fill.count})
end
if ent.revoke_minable then
e.minable = false
end
if ent.operable then
e.operable = false
end
if hook then
local token = Token.get(hook)
if token then
local data = {player = player, entity = e}
token(data)
end
end
insert(_entities, e)
::continue::
end
return _entities
end
--[[
build - Place blueprint at given point.
@param surf - LuaSurface on which action will be taken.
@param name - Blueprint handle.
@param point - Position at which place blueprint.
@param args - If hook was set, this will be argument passed.
--]]
Public.build = function(surf, name, point, args)
if surf == nil then
log('bp.build: surf is nil')
return
end
if name == nil then
log('bp.build: name is nil')
return
end
local object = this._bps[name]
if object == nil then
log('bp.set_blueprint_hook: unrecognized blueprint')
return
end
local instance = {
entities = {},
tiles = {},
bb = nil,
timestamp = game.tick
}
local bbs = {}
local tiles = object.bp.tiles
if tiles and #tiles > 0 then
instance.tiles = _build_tiles(surf, point, tiles)
local bb = CommonFunctions.create_bounding_box_by_points(instance.tiles)
insert(bbs, bb)
local query = {
name = 'character',
area = bb,
invert = true
}
for _, ent in pairs(surf.find_entities_filtered(query)) do
if ent.valid then
ent.destroy()
end
end
end
local entities = object.bp.entities
if entities and #entities > 0 then
instance.entities = _build_entities(surf, point, entities, object.hook, args)
local bb = CommonFunctions.create_bounding_box_by_points(instance.entities)
insert(bbs, bb)
local query = {
name = 'character',
area = bb,
invert = true
}
for _, ent_found in pairs(surf.find_entities_filtered(query)) do
if not ent_found.valid then
goto continue
end
for _, ent_spawned in pairs(instance.entities) do
if ent_found == ent_spawned then
goto continue
end
end
ent_found.die()
::continue::
end
end
instance.bb = CommonFunctions.merge_bounding_boxes(bbs)
instance.id = game.tick
insert(object.refs, instance)
return instance
end
return Public