172 lines
4.4 KiB
Lua

local EAST = defines.direction.east
local NORTH = defines.direction.north
local SOUTH = defines.direction.south
local WEST = defines.direction.west
---@class EvaluatedBlueprint
---@field valid boolean Are all blueprint entities valid
---@field w number
---@field h number
---@field tw number Runtime transposed width
---@field th number Runtime transposed height
---@field ox number Start offset x
---@field oy number Start offset y
---@field entities BlueprintEntityEx[] All entities in the blueprint
---@field entity_names table<string, number>
---@field miner_name string Mining drill name
local bp_meta = {}
bp_meta.__index = bp_meta
---@class BlueprintEntityEx : BlueprintEntity
---@field capstone_x boolean
---@field capstone_y boolean
---Blueprint analysis data
---@param bp LuaItemStack
---@return EvaluatedBlueprint
function bp_meta:new(bp)
---@type EvaluatedBlueprint
local new = setmetatable({}, self)
new.valid = true
new.w, new.h = bp.blueprint_snap_to_grid.x, bp.blueprint_snap_to_grid.y
new.ox, new.oy = 0, 0
if bp.blueprint_position_relative_to_grid then
new.ox = bp.blueprint_position_relative_to_grid.x
new.oy = bp.blueprint_position_relative_to_grid.y
end
new.entities = bp.get_blueprint_entities() or {}
new.entity_names = bp.cost_to_build
new:evaluate_tiling()
new:evaluate_miners()
return new
end
---Marks capstone BlueprintEntities
function bp_meta:evaluate_tiling()
local sw, sh = self.w, self.h
local buckets_x, buckets_y = {}, {}
for i, ent in pairs(self.entities) do
local x, y = ent.position.x, ent.position.y
ent.direction = ent.direction or NORTH
if not buckets_x[x] then buckets_x[x] = {} end
table.insert(buckets_x[x], ent)
if not buckets_y[y] then buckets_y[y] = {} end
table.insert(buckets_y[y], ent)
end
for _, bucket in pairs(buckets_y) do
for i = 1, #bucket-1 do
local e1 = bucket[i] ---@type BlueprintEntityEx
local e1x = e1.position.x
for j = 2, #bucket do
local e2 = bucket[j] ---@type BlueprintEntityEx
local e2x = e2.position.x
if e1x + sw == e2x or e1x - sw == e2x then
e2.capstone_x = true
end
end
end
end
for _, bucket in pairs(buckets_x) do
for i = 1, #bucket-1 do
local e1 = bucket[i] ---@type BlueprintEntityEx
local e1y = e1.position.y
for j = 2, #bucket do
local e2 = bucket[j] ---@type BlueprintEntityEx
local e2y = e2.position.y
if e1y + sh == e2y or e1y - sh == e2y then
e2.capstone_y = true
end
end
end
end
end
function bp_meta:evaluate_miners()
for _, ent in pairs(self.entities) do
local name = ent.name
if game.entity_prototypes[name].type == "mining-drill" then
--local proto = game.entity_prototypes[name]
self.miner_name = name
return
end
end
end
---@return BlueprintEntityEx[]
function bp_meta:get_mining_drills()
local miner_name = self.miner_name
local mining_drills = {}
for _, ent in pairs(self.entities) do
if ent.name == miner_name then
mining_drills[#mining_drills+1] = ent
end
end
return mining_drills
end
function bp_meta:check_valid()
for k, v in pairs(self.entity_names) do
if not game.entity_prototypes[k] and not game.item_prototypes[k] then
self.valid = false
return false
end
end
self.valid = true
return true
end
---Returns resource categories for a blueprint
---@return table<string, boolean>
function bp_meta:get_resource_categories()
local categories = {}
local proto = game.entity_prototypes[self.miner_name]
if proto.resource_categories then
for cat, bool in pairs(proto.resource_categories) do
categories[cat] = bool
end
end
return categories
end
---@return table<string, GridBuilding>
function bp_meta:get_entity_categories()
---@type table<string, GridBuilding>
local categories = {
["mining-drill"] = "miner",
["beacon"] = "beacon",
["transport-belt"] = "belt",
["underground-belt"] = "belt",
["splitter"] = "belt",
["inserter"] = "inserter",
["container"] = "container",
["logistic-container"] = "container",
["loader"] = "inserter",
["loader-1x1"] = "inserter",
["electric-pole"] = "pole",
}
---@type table<string, GridBuilding>
local category_map = {}
for _, ent in pairs(self.entities) do
local name = ent.name
local category = category_map[name]
if not category then
local ent_type = game.entity_prototypes[name].type
category = categories[ent_type] or "other"
category_map[name] = category
end
end
return category_map
end
return bp_meta