128 lines
5.1 KiB
Lua
128 lines
5.1 KiB
Lua
--- For working with surfaces.
|
|
-- Surfaces are the "domain" of the world.
|
|
-- @module Surface
|
|
-- @usage local Surface = require('stdlib/area/surface')
|
|
-- @see LuaSurface
|
|
|
|
local Surface = {_module_name = 'Surface'}
|
|
setmetatable(Surface, {__index = require('stdlib/core')})
|
|
|
|
local Is = require('stdlib/utils/is')
|
|
local Area = require('stdlib/area/area')
|
|
|
|
--- Flexible and safe lookup function for surfaces.
|
|
-- <ul>
|
|
-- <li>May be given a single surface name or an array of surface names in @{string}.
|
|
-- <li>May be given a single surface object or an array of surface objects in @{LuaSurface}.
|
|
-- <li>May also be given a @{nil}.
|
|
-- <li>Returns an array of surface objects of all valid and existing surfaces.
|
|
-- <li>Returns an empty array if no surfaces are given or if they are not found.
|
|
-- </ul>
|
|
-- @tparam ?|nil|string|{string,...}|LuaSurface|{LuaSurface,...} surface the surfaces to look up
|
|
-- @treturn {nil|LuaSurface,...} an array of all valid surfaces or nil otherwise
|
|
function Surface.lookup(surface)
|
|
if not surface then
|
|
return {}
|
|
end
|
|
if type(surface) == 'string' or type(surface) == 'number' then
|
|
local lookup = game.surfaces[surface]
|
|
if lookup then
|
|
return {lookup}
|
|
end
|
|
return {}
|
|
end
|
|
if type(surface) == 'table' and surface['__self'] then
|
|
return Surface.lookup(surface.name)
|
|
end
|
|
local results = {}
|
|
for _, surface_item in pairs(surface) do
|
|
if type(surface_item) == 'string' then
|
|
if game.surfaces[surface_item] then
|
|
table.insert(results, game.surfaces[surface_item])
|
|
end
|
|
elseif type(surface_item) == 'table' and surface_item['__self'] then
|
|
table.insert(results, surface_item)
|
|
end
|
|
end
|
|
return results
|
|
end
|
|
|
|
--- Given a @{search_criteria|search criteria}, find all entities that match the criteria.
|
|
-- <ul>
|
|
-- <li>If ***search\_criteria.name*** is not supplied, search for entities with any name.
|
|
-- <li>If ***search\_criteria.type*** is not supplied, search for entities of any type.
|
|
-- <li>If ***search\_criteria.force*** is not supplied, search for entities owned by any force.
|
|
-- <li>If ***search\_criteria.surface*** is not supplied, search for entities on all surfaces.
|
|
-- <li>If ***search\_criteria.area*** is not supplied, search the entire specified surface.
|
|
-- </ul>
|
|
-- @usage
|
|
-- surface.find_all_entities({ type = 'unit', surface = 'nauvis', area = {{-1000,20},{-153,2214}})
|
|
-- -- returns a list containing all unit entities on the nauvis surface in the given area
|
|
-- @param search_criteria (<span class="types">@{search_criteria}</span>) a table used to search for entities
|
|
-- @treturn {nil|LuaEntity,...} an array of all entities that matched the criteria **OR** *nil* if there were no matches
|
|
function Surface.find_all_entities(search_criteria)
|
|
Is.Assert.Table(search_criteria, 'missing search_criteria argument')
|
|
if search_criteria.name == nil and search_criteria.type == nil and search_criteria.force == nil and search_criteria.area == nil then
|
|
error('Missing search criteria field: name or type or force or area of entity', 2)
|
|
end
|
|
|
|
local surface_list = Surface.lookup(search_criteria.surface)
|
|
if search_criteria.surface == nil then
|
|
surface_list = game.surfaces
|
|
end
|
|
|
|
local results = {}
|
|
|
|
for _, surface in pairs(surface_list) do
|
|
local entities =
|
|
surface.find_entities_filtered(
|
|
{
|
|
area = search_criteria.area,
|
|
name = search_criteria.name,
|
|
type = search_criteria.type,
|
|
force = search_criteria.force
|
|
}
|
|
)
|
|
for _, entity in pairs(entities) do
|
|
table.insert(results, entity)
|
|
end
|
|
end
|
|
|
|
return results
|
|
end
|
|
|
|
---
|
|
-- This table should be passed into @{find_all_entities} function to find entities that match the criteria.
|
|
-- @tfield[opt] string name internal name of an entity — (example: "locomotive")
|
|
-- @tfield[opt] string type type of an entity — (example: "unit")
|
|
-- @tfield[opt] string|LuaForce force the force of an entity — (examples: "neutral", "enemy")
|
|
-- @tfield[opt] ?|nil|string|{string,...}|LuaSurface|{LuaSurface,...} surface the surface to search — (example: "nauvis")
|
|
-- @tfield[opt] Concepts.BoundingBox area the area to search
|
|
-- @table search_criteria
|
|
|
|
--- Gets the area which covers the entirety of a given surface.
|
|
-- This function is useful if you wish to compare the total number of chunks against the number of chunks within the entire area of a given surface.
|
|
-- @tparam LuaSurface surface the surface for which to get the area
|
|
-- @treturn Concepts.BoundingBox the area of a given surface
|
|
function Surface.get_surface_bounds(surface)
|
|
Is.Assert(surface, 'missing surface value')
|
|
local x1, y1, x2, y2 = 0, 0, 0, 0
|
|
|
|
for chunk in surface.get_chunks() do
|
|
if chunk.x < x1 then
|
|
x1 = chunk.x
|
|
elseif chunk.x > x2 then
|
|
x2 = chunk.x
|
|
end
|
|
if chunk.y < y1 then
|
|
y1 = chunk.y
|
|
elseif chunk.y > y2 then
|
|
y2 = chunk.y
|
|
end
|
|
end
|
|
|
|
return Area.construct(x1 * 32, y1 * 32, x2 * 32, y2 * 32)
|
|
end
|
|
|
|
return Surface
|