Module:Building data: Difference between revisions
From Beyond These Stars Official Wiki
Update to support buildings table module |
m luadoc update only |
||
| (14 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
--[[ | |||
Test in Scribunto console with: | |||
=mw.dumpObject(p.get_all_buildings()) | |||
=mw.dumpObject(p.get_building("Ore Smelter")) | |||
=mw.dumpObject(p.get_name_by_id("OreSmelter")) | |||
=mw.dumpObject(p.get_buildings_by_category("Construction")) | |||
=mw.dumpObject(p.get_building_names_with_tasks_including_resource("Iron")) | |||
]]-- | |||
local p = {} | local p = {} | ||
--#region Cargo | --#region MARK: Cargo types | ||
--- Cargo row from querying Buildings; all values are strings at runtime. | --- Cargo row from querying Buildings; all values are strings at runtime. | ||
| Line 283: | Line 291: | ||
--- Cargo row from querying BuildingTasks; all values are strings at runtime. | --- Cargo row from querying BuildingTasks; all values are strings at runtime. | ||
---@class CargoBuildingTasksRecord | ---@class CargoBuildingTasksRecord | ||
---@field page_name string|nil | |||
---@field guid string|nil | |||
---@field BuildingTasks_1_Name string|nil | ---@field BuildingTasks_1_Name string|nil | ||
---@field BuildingTasks_1_InitialState string|nil | ---@field BuildingTasks_1_InitialState string|nil | ||
| Line 300: | Line 310: | ||
---@field BuildingTasks_1_Inputs_2_Resource string|nil | ---@field BuildingTasks_1_Inputs_2_Resource string|nil | ||
---@field BuildingTasks_1_Inputs_2_Value string|nil | ---@field BuildingTasks_1_Inputs_2_Value string|nil | ||
---@field BuildingTasks_1_Inputs_3_Type string|nil | |||
---@field BuildingTasks_1_Inputs_3_Resource string|nil | |||
---@field BuildingTasks_1_Inputs_3_Value string|nil | |||
---@field BuildingTasks_1_Inputs_4_Type string|nil | |||
---@field BuildingTasks_1_Inputs_4_Resource string|nil | |||
---@field BuildingTasks_1_Inputs_4_Value string|nil | |||
---@field BuildingTasks_1_DescriptionTerm_en string|nil | |||
---@field BuildingTasks_2_Name string|nil | ---@field BuildingTasks_2_Name string|nil | ||
---@field BuildingTasks_2_InitialState string|nil | ---@field BuildingTasks_2_InitialState string|nil | ||
| Line 317: | Line 334: | ||
---@field BuildingTasks_2_Inputs_2_Resource string|nil | ---@field BuildingTasks_2_Inputs_2_Resource string|nil | ||
---@field BuildingTasks_2_Inputs_2_Value string|nil | ---@field BuildingTasks_2_Inputs_2_Value string|nil | ||
---@field BuildingTasks_2_Inputs_3_Type string|nil | |||
---@field BuildingTasks_2_Inputs_3_Resource string|nil | |||
---@field BuildingTasks_2_Inputs_3_Value string|nil | |||
---@field BuildingTasks_3_Name string|nil | ---@field BuildingTasks_3_Name string|nil | ||
---@field BuildingTasks_3_InitialState string|nil | ---@field BuildingTasks_3_InitialState string|nil | ||
| Line 363: | Line 383: | ||
---@field BuildingTasks_6_Outputs_1_Resource string|nil | ---@field BuildingTasks_6_Outputs_1_Resource string|nil | ||
---@field BuildingTasks_6_Outputs_1_Value string|nil | ---@field BuildingTasks_6_Outputs_1_Value string|nil | ||
---@field BuildingTasks_6_PollutionSlowdownThreshold string|nil | ---@field BuildingTasks_6_PollutionSlowdownThreshold string|nil | ||
---@field BuildingTasks_6_Inputs_1_Type string|nil | ---@field BuildingTasks_6_Inputs_1_Type string|nil | ||
| Line 373: | Line 390: | ||
---@field BuildingTasks_6_Inputs_2_Resource string|nil | ---@field BuildingTasks_6_Inputs_2_Resource string|nil | ||
---@field BuildingTasks_6_Inputs_2_Value string|nil | ---@field BuildingTasks_6_Inputs_2_Value string|nil | ||
---@field BuildingTasks_7_Name string|nil | |||
---@field BuildingTasks_7_InitialState string|nil | |||
---@field BuildingTasks_7_Time string|nil | |||
---@field BuildingTasks_7_MinimumTimeDelta string|nil | |||
---@field BuildingTasks_7_Outputs_1_Type string|nil | |||
---@field BuildingTasks_7_Outputs_1_Resource string|nil | |||
---@field BuildingTasks_7_Outputs_1_Value string|nil | |||
---@field BuildingTasks_7_PollutionSlowdownThreshold string|nil | |||
---@field BuildingTasks_7_Inputs_1_Type string|nil | |||
---@field BuildingTasks_7_Inputs_1_Resource string|nil | |||
---@field BuildingTasks_7_Inputs_1_Value string|nil | |||
---@field BuildingTasks_8_Name string|nil | |||
---@field BuildingTasks_8_InitialState string|nil | |||
---@field BuildingTasks_8_Time string|nil | |||
---@field BuildingTasks_8_MinimumTimeDelta string|nil | |||
---@field BuildingTasks_8_Outputs_1_Type string|nil | |||
---@field BuildingTasks_8_Outputs_1_Resource string|nil | |||
---@field BuildingTasks_8_Outputs_1_Value string|nil | |||
---@field BuildingTasks_8_PollutionSlowdownThreshold string|nil | |||
---@field BuildingTasks_8_Inputs_1_Type string|nil | |||
---@field BuildingTasks_8_Inputs_1_Resource string|nil | |||
---@field BuildingTasks_8_Inputs_1_Value string|nil | |||
---@field BuildingTasks_9_Name string|nil | |||
---@field BuildingTasks_9_InitialState string|nil | |||
---@field BuildingTasks_9_Time string|nil | |||
---@field BuildingTasks_9_MinimumTimeDelta string|nil | |||
---@field BuildingTasks_9_Outputs_1_Type string|nil | |||
---@field BuildingTasks_9_Outputs_1_Resource string|nil | |||
---@field BuildingTasks_9_Outputs_1_Value string|nil | |||
---@field BuildingTasks_9_PollutionSlowdownThreshold string|nil | |||
---@field BuildingTasks_9_Inputs_1_Type string|nil | |||
---@field BuildingTasks_9_Inputs_1_Resource string|nil | |||
---@field BuildingTasks_9_Inputs_1_Value string|nil | |||
--#endregion | |||
--#region MARK: Cargo consts | |||
local FILTER_CATEGORY = "Category" | |||
---@alias VALID_FILTER_FIELDS "Category" | |||
local QUERIES = { | local QUERIES = { | ||
| Line 379: | Line 438: | ||
WHERE_NAME = "page_name", | WHERE_NAME = "page_name", | ||
WHERE_ID = "Name", | WHERE_ID = "Name", | ||
WHERE_TASKS_GUID = "BuildingTasks", | |||
ORDER_BY = "page_name", | ORDER_BY = "page_name", | ||
FIELDS_NAME_ONLY = { | FIELDS_NAME_ONLY = { | ||
| Line 387: | Line 447: | ||
"guid", | "guid", | ||
"Name", | "Name", | ||
FILTER_CATEGORY, | |||
"DisplayNameTerm_en", | "DisplayNameTerm_en", | ||
"DisplayNamePluralTerm_en", | "DisplayNamePluralTerm_en", | ||
| Line 656: | Line 716: | ||
TABLE = "BuildingTasks", | TABLE = "BuildingTasks", | ||
WHERE_GUID = "guid", | WHERE_GUID = "guid", | ||
-- FIELDS that fit the pattern but | -- FIELDS that fit the pattern but are not declared in the DB table definition: | ||
-- BuildingTasks_4_Outputs_2_* | -- BuildingTasks_4_Outputs_2_* | ||
-- BuildingTasks_4_Inputs_2_* | -- BuildingTasks_4_Inputs_2_* | ||
| Line 663: | Line 723: | ||
-- Commented out fields are not used in BuildingTask | -- Commented out fields are not used in BuildingTask | ||
FIELDS = { | FIELDS = { | ||
"page_name", | |||
"guid", | |||
"BuildingTasks_1_Name", | "BuildingTasks_1_Name", | ||
-- "BuildingTasks_1_InitialState", | -- "BuildingTasks_1_InitialState", | ||
| Line 673: | Line 735: | ||
"BuildingTasks_1_Outputs_2_Resource", | "BuildingTasks_1_Outputs_2_Resource", | ||
"BuildingTasks_1_Outputs_2_Value", | "BuildingTasks_1_Outputs_2_Value", | ||
"BuildingTasks_1_Inputs_1_Type", | "BuildingTasks_1_Inputs_1_Type", | ||
"BuildingTasks_1_Inputs_1_Resource", | "BuildingTasks_1_Inputs_1_Resource", | ||
| Line 680: | Line 741: | ||
"BuildingTasks_1_Inputs_2_Resource", | "BuildingTasks_1_Inputs_2_Resource", | ||
"BuildingTasks_1_Inputs_2_Value", | "BuildingTasks_1_Inputs_2_Value", | ||
"BuildingTasks_1_Inputs_3_Type", | |||
"BuildingTasks_1_Inputs_3_Resource", | |||
"BuildingTasks_1_Inputs_3_Value", | |||
"BuildingTasks_1_Inputs_4_Type", | |||
"BuildingTasks_1_Inputs_4_Resource", | |||
"BuildingTasks_1_Inputs_4_Value", | |||
"BuildingTasks_1_PollutionSlowdownThreshold", | |||
"BuildingTasks_2_Name", | "BuildingTasks_2_Name", | ||
-- "BuildingTasks_2_InitialState", | -- "BuildingTasks_2_InitialState", | ||
| Line 697: | Line 765: | ||
"BuildingTasks_2_Inputs_2_Resource", | "BuildingTasks_2_Inputs_2_Resource", | ||
"BuildingTasks_2_Inputs_2_Value", | "BuildingTasks_2_Inputs_2_Value", | ||
"BuildingTasks_2_Inputs_3_Type", | |||
"BuildingTasks_2_Inputs_3_Resource", | |||
"BuildingTasks_2_Inputs_3_Value", | |||
"BuildingTasks_3_Name", | "BuildingTasks_3_Name", | ||
-- "BuildingTasks_3_InitialState", | -- "BuildingTasks_3_InitialState", | ||
| Line 743: | Line 814: | ||
"BuildingTasks_6_Outputs_1_Resource", | "BuildingTasks_6_Outputs_1_Resource", | ||
"BuildingTasks_6_Outputs_1_Value", | "BuildingTasks_6_Outputs_1_Value", | ||
"BuildingTasks_6_PollutionSlowdownThreshold", | "BuildingTasks_6_PollutionSlowdownThreshold", | ||
"BuildingTasks_6_Inputs_1_Type", | "BuildingTasks_6_Inputs_1_Type", | ||
| Line 753: | Line 821: | ||
"BuildingTasks_6_Inputs_2_Resource", | "BuildingTasks_6_Inputs_2_Resource", | ||
"BuildingTasks_6_Inputs_2_Value", | "BuildingTasks_6_Inputs_2_Value", | ||
"BuildingTasks_7_Name", | |||
-- "BuildingTasks_7_InitialState", | |||
"BuildingTasks_7_Time", | |||
-- "BuildingTasks_7_MinimumTimeDelta", | |||
"BuildingTasks_7_Outputs_1_Type", | |||
"BuildingTasks_7_Outputs_1_Resource", | |||
"BuildingTasks_7_Outputs_1_Value", | |||
"BuildingTasks_7_PollutionSlowdownThreshold", | |||
"BuildingTasks_7_Inputs_1_Type", | |||
"BuildingTasks_7_Inputs_1_Resource", | |||
"BuildingTasks_7_Inputs_1_Value", | |||
"BuildingTasks_8_Name", | |||
-- "BuildingTasks_8_InitialState", | |||
"BuildingTasks_8_Time", | |||
-- "BuildingTasks_8_MinimumTimeDelta", | |||
"BuildingTasks_8_Outputs_1_Type", | |||
"BuildingTasks_8_Outputs_1_Resource", | |||
"BuildingTasks_8_Outputs_1_Value", | |||
"BuildingTasks_8_PollutionSlowdownThreshold", | |||
"BuildingTasks_8_Inputs_1_Type", | |||
"BuildingTasks_8_Inputs_1_Resource", | |||
"BuildingTasks_8_Inputs_1_Value", | |||
"BuildingTasks_9_Name", | |||
-- "BuildingTasks_9_InitialState", | |||
"BuildingTasks_9_Time", | |||
-- "BuildingTasks_9_MinimumTimeDelta", | |||
"BuildingTasks_9_Outputs_1_Type", | |||
"BuildingTasks_9_Outputs_1_Resource", | |||
"BuildingTasks_9_Outputs_1_Value", | |||
"BuildingTasks_9_PollutionSlowdownThreshold", | |||
"BuildingTasks_9_Inputs_1_Type", | |||
"BuildingTasks_9_Inputs_1_Resource", | |||
"BuildingTasks_9_Inputs_1_Value", | |||
} | } | ||
} | } | ||
| Line 761: | Line 862: | ||
--#region | --#region MARK: Query buildings | ||
--- Skips unwanted buildings from a query result. | |||
---@param results CargoBuildingRecord[] | |||
---@return CargoBuildingRecord[] | |||
local function skip_unwanted_buildings(results) | |||
local new_results = {} | |||
for _, record in ipairs(results) do | |||
if not p.SKIPPED_BUILDINGS_NAMES[record.Name] then | |||
table.insert(new_results, record) | |||
end | |||
end | |||
return new_results | |||
end | |||
--- Queries cargo for all building records. | --- Queries cargo for all building records. | ||
| Line 776: | Line 890: | ||
}) | }) | ||
if not result or #result == 0 then return {} end | if not result or #result == 0 then return {} end | ||
result = skip_unwanted_buildings(result) | |||
return result | |||
end | |||
--- Queries cargo for building records by the given filter. | |||
---@param filter_field VALID_FILTER_FIELDS | |||
---@param filter_value string | |||
---@return CargoBuildingRecord[] | |||
local function query_buildings_by_filter(filter_field, filter_value) | |||
local cargo = mw.ext.cargo | |||
if not cargo then return {} end | |||
local result = cargo.query( | |||
QUERIES.BUILDINGS.TABLE, | |||
table.concat(QUERIES.BUILDINGS.FIELDS_FULL, ","), | |||
{ | |||
where = filter_field .. '="' .. filter_value .. '"', | |||
orderBy = QUERIES.BUILDINGS.ORDER_BY, | |||
}) | |||
if not result or #result == 0 then return {} end | |||
result = skip_unwanted_buildings(result) | |||
return result | return result | ||
end | end | ||
| Line 792: | Line 926: | ||
}) | }) | ||
if not result or #result == 0 then return nil end | if not result or #result == 0 then return nil end | ||
result = skip_unwanted_buildings(result) | |||
return result[1] | return result[1] | ||
end | end | ||
--- Queries cargo for the building | --- Queries cargo for the building name only with the given id. | ||
---@param | ---@param building_id string the id of the building to fetch | ||
---@return | ---@return CargoBuildingRecord|nil | ||
local function | local function query_building_name_only(building_id) | ||
local cargo = mw.ext.cargo | local cargo = mw.ext.cargo | ||
if not cargo then return nil end | if not cargo then return nil end | ||
local result = cargo.query( | local result = cargo.query( | ||
QUERIES. | QUERIES.BUILDINGS.TABLE, | ||
table.concat(QUERIES. | table.concat(QUERIES.BUILDINGS.FIELDS_NAME_ONLY, ","), | ||
{ | { | ||
where = QUERIES. | where = QUERIES.BUILDINGS.WHERE_ID .. '="' .. building_id .. '"', | ||
}) | }) | ||
if not result or #result == 0 then return nil end | if not result or #result == 0 then return nil end | ||
result = skip_unwanted_buildings(result) | |||
return result[1] | return result[1] | ||
end | end | ||
--- Queries cargo for the building name only with the given | --- Queries cargo for the building name only with the given guid. | ||
---@param | ---@param tasks_guid string the guid of the tasks list to look for in buildings | ||
---@return CargoBuildingRecord|nil | ---@return CargoBuildingRecord|nil | ||
local function | local function query_building_name_only_by_tasks_guid(tasks_guid) | ||
local cargo = mw.ext.cargo | local cargo = mw.ext.cargo | ||
if not cargo then return nil end | if not cargo then return nil end | ||
| Line 821: | Line 957: | ||
table.concat(QUERIES.BUILDINGS.FIELDS_NAME_ONLY, ","), | table.concat(QUERIES.BUILDINGS.FIELDS_NAME_ONLY, ","), | ||
{ | { | ||
where = QUERIES.BUILDINGS. | where = QUERIES.BUILDINGS.WHERE_TASKS_GUID .. '="' .. tasks_guid .. '"', | ||
}) | |||
if not result or #result == 0 then return nil end | |||
result = skip_unwanted_buildings(result) | |||
return result[1] | |||
end | |||
--#endregion | |||
--#region MARK: Query tasks | |||
--- Queries cargo for the building tasks record with the given guid. | |||
---@param building_tasks_guid string the guid of the building tasks to fetch | |||
---@return CargoBuildingTasksRecord|nil | |||
local function query_building_tasks(building_tasks_guid) | |||
local cargo = mw.ext.cargo | |||
if not cargo then return nil end | |||
local result = cargo.query( | |||
QUERIES.TASKS.TABLE, | |||
table.concat(QUERIES.TASKS.FIELDS, ","), | |||
{ | |||
where = QUERIES.TASKS.WHERE_GUID .. '="' .. building_tasks_guid .. '"', | |||
}) | }) | ||
if not result or #result == 0 then return nil end | if not result or #result == 0 then return nil end | ||
return result[1] | return result[1] | ||
end | |||
--- Queries cargo for all building tasks. | |||
---@return CargoBuildingTasksRecord[] | |||
local function query_all_building_tasks() | |||
local cargo = mw.ext.cargo | |||
if not cargo then return {} end | |||
local result = cargo.query( | |||
QUERIES.TASKS.TABLE, | |||
table.concat(QUERIES.TASKS.FIELDS, ",") | |||
) | |||
if not result or #result == 0 then return {} end | |||
return result | |||
end | end | ||
| Line 831: | Line 1,003: | ||
--#region | --#region MARK: Restructuring | ||
--- Restructures the construction resources of a building record from the database into a more usable format. | --- Restructures the construction resources of a building record from the database into a more usable format. | ||
| Line 892: | Line 1,064: | ||
--- Restructures the inputs or ouputs of a building task | --- Restructures the inputs or ouputs of a building task | ||
---@param | ---@param task_record CargoBuildingTasksRecord the building tasks record retrieved for the building | ||
---@param task_num number which task to restructure | ---@param task_num number which task to restructure | ||
---@param which_io "Inputs"|"Outputs" the type of tasks to restructure | ---@param which_io "Inputs"|"Outputs" the type of tasks to restructure | ||
---@return BuildingTaskIO[] | ---@return BuildingTaskIO[] | ||
local function restructure_task_io( | local function restructure_task_io(task_record, task_num, which_io) | ||
local task_io = {} | local task_io = {} | ||
local max = ((which_io == "Inputs") and p.MAX_BUILDING_TASK_INPUTS) or p.MAX_BUILDING_TASK_OUTPUTS | local max = ((which_io == "Inputs") and p.MAX_BUILDING_TASK_INPUTS) or p.MAX_BUILDING_TASK_OUTPUTS | ||
local task_type_prefix = "BuildingTasks_" .. task_num .. "_" .. which_io .. "_" | local task_type_prefix = "BuildingTasks_" .. task_num .. "_" .. which_io .. "_%d_" | ||
for i = 1, max do | for i = 1, max do | ||
local put_type = | local put_type = task_record[string.format(task_type_prefix .. "Type", i)] | ||
local put_resource = | local put_resource = task_record[string.format(task_type_prefix .. "Resource", i)] | ||
local put_value = | local put_value = task_record[string.format(task_type_prefix .. "Value", i)] | ||
if put_type | if put_type or put_resource or put_value then | ||
table.insert(task_io, { | table.insert(task_io, { | ||
type = put_type, | type = put_type, | ||
| Line 915: | Line 1,087: | ||
end | end | ||
--- Restructures | --- Restructures a task record from the database into a more usable format. | ||
---@param | ---@param task_record CargoBuildingTasksRecord | ||
---@return BuildingTask[] | ---@return BuildingTask[] | ||
local function restructure_tasks( | local function restructure_tasks(task_record) | ||
local tasks = {} | local tasks = {} | ||
for i = 1, p.MAX_BUILDING_TASKS do | for i = 1, p.MAX_BUILDING_TASKS do | ||
local task_name = | local task_name = task_record[string.format("BuildingTasks_%d_Name", i)] | ||
local time = tonumber( | local time = tonumber(task_record[string.format("BuildingTasks_%d_Time", i)]) | ||
local pollution_slowdown = tonumber( | local pollution_slowdown = tonumber(task_record[string.format("BuildingTasks_%d_PollutionSlowdownThreshold", i)]) | ||
local outputs = restructure_task_io( | local outputs = restructure_task_io(task_record, i, "Outputs") | ||
local inputs = restructure_task_io( | local inputs = restructure_task_io(task_record, i, "Inputs") | ||
if task_name | if task_name then | ||
table.insert(tasks, { | table.insert(tasks, { | ||
task_name = task_name, | task_name = task_name, | ||
| Line 940: | Line 1,108: | ||
end | end | ||
end | end | ||
return tasks | |||
end | |||
--- Restructures the tasks of a building record from the database into a more usable format. | |||
---@param building_record CargoBuildingRecord | |||
---@return BuildingTask[] | |||
local function restructure_tasks_in_building(building_record) | |||
local tasks_guid = building_record.BuildingTasks | |||
if not tasks_guid then return {} end | |||
local raw_tasks = query_building_tasks(tasks_guid) | |||
if not raw_tasks then return {} | |||
end | |||
local tasks = restructure_tasks(raw_tasks) | |||
return tasks | return tasks | ||
end | end | ||
| Line 947: | Line 1,128: | ||
---@return Building|nil | ---@return Building|nil | ||
local function restructure_building_record(record) | local function restructure_building_record(record) | ||
local portrait_icon_filename = nil | |||
if not p.PORTRAITS_MISSING_NAMES[record.Name] then | |||
portrait_icon_filename = p.BUILDING_PORTRAIT_PREFIX .. record.Name | |||
end | |||
local building = { | local building = { | ||
name = record.page_name, | name = record.page_name, | ||
category = record.Category, | category = record.Category, | ||
display_name = record.DisplayNameTerm_en, | display_name = record.DisplayNameTerm_en or record.page_name, | ||
display_name_plural = record.DisplayNamePluralTerm_en, | display_name_plural = record.DisplayNamePluralTerm_en, | ||
description = record.DescriptionTerm_en, | description = record.DescriptionTerm_en, | ||
icon = record.IconAddress, | icon = record.IconAddress, | ||
portrait_icon = | portrait_icon = portrait_icon_filename, | ||
construction_resources = {}, | construction_resources = {}, | ||
construction_time = tonumber(record.ConstructionTime), | construction_time = tonumber(record.ConstructionTime), | ||
| Line 983: | Line 1,168: | ||
building.unlock_values = restructure_unlock_values(record) | building.unlock_values = restructure_unlock_values(record) | ||
building.adjacency_bonuses = restructure_adjacency_bonuses(record) | building.adjacency_bonuses = restructure_adjacency_bonuses(record) | ||
building.tasks = | building.tasks = restructure_tasks_in_building(record) | ||
return building | return building | ||
end | end | ||
| Line 991: | Line 1,176: | ||
--#region Public interface | --#region MARK: Private helpers | ||
--- Maps the given tasks by the given building guiid. | |||
---@param list_of_tasks_records CargoBuildingTasksRecord[] | |||
---@return table<string, CargoBuildingTasksRecord> | |||
local function map_tasks_by_guid(list_of_tasks_records) | |||
local map = {} | |||
for _, tasks_record in ipairs(list_of_tasks_records) do | |||
local tasks_guid = tasks_record.guid | |||
if tasks_guid and tasks_guid ~= "" then | |||
map[tasks_guid] = tasks_record | |||
end | |||
end | |||
return map | |||
end | |||
--- Filters the given tasks by the given resource id. | |||
---@param tasks BuildingTask[] | |||
---@param resource_id string the id of the resource to filter tasks by | |||
---@return BuildingTask[] | |||
local function filter_tasks_by_resource(tasks, resource_id) | |||
local filtered_tasks = {} | |||
for _, task in ipairs(tasks) do | |||
local found = false | |||
for _, input in ipairs(task.inputs) do | |||
if input.resource == resource_id then | |||
table.insert(filtered_tasks, task) | |||
found = true | |||
break | |||
end | |||
end | |||
if not found then | |||
for _, output in ipairs(task.outputs) do | |||
if output.resource == resource_id then | |||
table.insert(filtered_tasks, task) | |||
break | |||
end | |||
end | |||
end | |||
end | |||
return filtered_tasks | |||
end | |||
--#endregion | |||
--#region MARK: Public interface | |||
---@class BuildingDataModule | ---@class BuildingDataModule | ||
| Line 1,000: | Line 1,232: | ||
---@field MAX_BUILDING_TASK_OUTPUTS number the maximum number of building task outputs | ---@field MAX_BUILDING_TASK_OUTPUTS number the maximum number of building task outputs | ||
---@field MAX_BUILDING_TASK_INPUTS number the maximum number of building task inputs | ---@field MAX_BUILDING_TASK_INPUTS number the maximum number of building task inputs | ||
---@field FILTERS table filter field names for building queries | |||
---@field get_name_by_id fun(id: string): string|nil looks up a building page name by codename | |||
---@field get_building fun(building_name: string): Building|nil looks up a building by page name | |||
---@field get_buildings_by_category fun(category: string): Building[] gets buildings in a category | |||
---@field get_all_buildings fun(): Building[] gets all buildings | ---@field get_all_buildings fun(): Building[] gets all buildings | ||
---@field | ---@field get_building_names_with_tasks_including_resource fun(resource_id: string): table<string, BuildingTask[]> building page names to matching tasks | ||
p.MAX_CONSTRUCTION_PAIRS = 6 | p.MAX_CONSTRUCTION_PAIRS = 6 | ||
| Line 1,008: | Line 1,244: | ||
p.MAX_BUILDING_TASKS = 9 | p.MAX_BUILDING_TASKS = 9 | ||
p.MAX_BUILDING_TASK_OUTPUTS = 2 | p.MAX_BUILDING_TASK_OUTPUTS = 2 | ||
p.MAX_BUILDING_TASK_INPUTS = | p.MAX_BUILDING_TASK_INPUTS = 4 | ||
p.BUILDING_PORTRAIT_PREFIX = "BuildingPortrait_" | p.BUILDING_PORTRAIT_PREFIX = "BuildingPortrait_" | ||
p.PORTRAITS_MISSING_NAMES = { | |||
["CompostingSite"] = true, | |||
["Forest_WorldTwo"] = true, | |||
["HomeSpaceshipLanded"] = true, | |||
["Mill"] = true, | |||
["WhaleTranslatorRuin"] = true, | |||
["OxygenGenerator"] = true, | |||
["Rock_WorldThree"] = true, | |||
["Ruin_WorldTwo"] = true, | |||
["SettlementSpaceshipLanded"] = true, | |||
["SettlementSpaceshipLauncher"] = true, | |||
["SteelBridge"] = true, | |||
["StorageExtension"] = true, | |||
} | |||
p.SKIPPED_BUILDINGS_NAMES = { | |||
["CompostTool"] = true, | |||
["ConstructionConsumption"] = true, | |||
["DemolitionControl"] = true, | |||
["Drone_Repair"] = true, | |||
["ForestPlantingTool"] = true, | |||
["CreateMineableArea"] = true, | |||
["MiningTile"] = true, | |||
["MoveBuildingControl"] = true, | |||
["PauseControl"] = true, | |||
["PeepConsumption"] = true, | |||
["PriorityControl"] = true, | |||
["LandFillingSite"] = true, | |||
["RampConstruction"] = true, | |||
["RepairControl"] = true, | |||
["ResourceCache"] = true, | |||
["RoadConstruction"] = true, | |||
["SettlementSpaceshipReload"] = true, | |||
["ThornyStems"] = true, | |||
} | |||
p.FILTERS = { | |||
CATEGORY = FILTER_CATEGORY, | |||
} | |||
---@class ConstructionPair | ---@class ConstructionPair | ||
| Line 1,067: | Line 1,340: | ||
---@field power_range number|nil the range of the power source for the building | ---@field power_range number|nil the range of the power source for the building | ||
---@field tasks BuildingTask[]|nil the tasks the building can work on | ---@field tasks BuildingTask[]|nil the tasks the building can work on | ||
--- Fetches a building's page name by its id. | |||
---@param id string the id of the building to fetch | |||
---@return string|nil the page name of the building | |||
function p.get_name_by_id(id) | |||
local raw_record = query_building_name_only(id) | |||
if not raw_record then return nil end | |||
return raw_record.page_name or nil | |||
end | |||
--- Fetches a building record from the database. | --- Fetches a building record from the database. | ||
| Line 1,078: | Line 1,360: | ||
end | end | ||
--- Fetches | --- Fetches building records for the given category. | ||
---@param | ---@param category string | ||
---@return | ---@return Building[] | ||
function p. | function p.get_buildings_by_category(category) | ||
local | local raw_records = query_buildings_by_filter(p.FILTERS.CATEGORY, category) | ||
if not | if not raw_records then return {} end | ||
local new_records = {} | |||
for _, raw_record in ipairs(raw_records) do | |||
local record = restructure_building_record(raw_record) | |||
table.insert(new_records, record) | |||
end | |||
return new_records | |||
end | end | ||
| Line 1,098: | Line 1,385: | ||
end | end | ||
return new_records | return new_records | ||
end | |||
--- Fetches all buildings whose work involves the given resource. | |||
---@param resource_id string the id of the resource to fetch buildings for | |||
---@return table<string, BuildingTask[]> | |||
function p.get_building_names_with_tasks_including_resource(resource_id) | |||
local raw_records = query_all_building_tasks() | |||
local raw_map_of_tasks = map_tasks_by_guid(raw_records) | |||
---@type table<string, BuildingTask[]> | |||
local map_building_map_of_tasks = {} | |||
for tasks_guid, tasks_record in pairs(raw_map_of_tasks) do | |||
local tasks = restructure_tasks(tasks_record) | |||
local filtered_tasks = filter_tasks_by_resource(tasks, resource_id) | |||
if filtered_tasks and #filtered_tasks > 0 then | |||
local building_record = query_building_name_only_by_tasks_guid(tasks_guid) | |||
if building_record then | |||
local building_name = building_record.page_name | |||
if building_name and building_name ~= "" then | |||
map_building_map_of_tasks[building_name] = filtered_tasks | |||
end | |||
end | |||
end | |||
end | |||
return map_building_map_of_tasks | |||
end | end | ||
Latest revision as of 03:33, 10 October 2026
Documentation for this module may be created at Module:Building data/doc
--[[
Test in Scribunto console with:
=mw.dumpObject(p.get_all_buildings())
=mw.dumpObject(p.get_building("Ore Smelter"))
=mw.dumpObject(p.get_name_by_id("OreSmelter"))
=mw.dumpObject(p.get_buildings_by_category("Construction"))
=mw.dumpObject(p.get_building_names_with_tasks_including_resource("Iron"))
]]--
local p = {}
--#region MARK: Cargo types
--- Cargo row from querying Buildings; all values are strings at runtime.
---@class CargoBuildingRecord
---@field page_name string|nil
---@field guid string|nil
---@field Name string|nil
---@field Category string|nil
---@field DisplayNameTerm_en string|nil
---@field DisplayNamePluralTerm_en string|nil
---@field DescriptionTerm_en string|nil
---@field UpgradeTerm string|nil
---@field UpgradeTerm_en string|nil
---@field IconAddress string|nil
---@field PlacementRules_1 string|nil
---@field PlacementRules_2 string|nil
---@field PlacementRules_3 string|nil
---@field PlacementRules_4 string|nil
---@field PlacementRules_5 string|nil
---@field PlacementRules_6 string|nil
---@field AnchorBuildingNames_1 string|nil
---@field AnchorBuildingNames_2 string|nil
---@field ConstructionResources string|nil
---@field ConstructionResources_1_Name string|nil
---@field ConstructionResources_1_Amount string|nil
---@field ConstructionResources_2_Name string|nil
---@field ConstructionResources_2_Amount string|nil
---@field ConstructionResources_3_Name string|nil
---@field ConstructionResources_3_Amount string|nil
---@field ConstructionResources_4_Name string|nil
---@field ConstructionResources_4_Amount string|nil
---@field ConstructionResources_5_Name string|nil
---@field ConstructionResources_5_Amount string|nil
---@field ConstructionResources_6_Name string|nil
---@field ConstructionResources_6_Amount string|nil
---@field SecondaryPrefabAddresses_1 string|nil
---@field SecondaryPrefabAddresses_2 string|nil
---@field RepairResources_1_Name string|nil
---@field RepairResources_1_Amount string|nil
---@field RepairResources_2_Name string|nil
---@field RepairResources_2_Amount string|nil
---@field RepairResources_3_Name string|nil
---@field RepairResources_3_Amount string|nil
---@field RepairResources_4_Name string|nil
---@field RepairResources_4_Amount string|nil
---@field RepairResources_5_Name string|nil
---@field RepairResources_5_Amount string|nil
---@field RepairResources_6_Name string|nil
---@field RepairResources_6_Amount string|nil
---@field ConstructionTime string|nil
---@field ConstructionPeepCount string|nil
---@field UnlockMode string|nil
---@field UnlockValues string|nil
---@field UnlockValues_1 string|nil
---@field UnlockValues_2 string|nil
---@field UnlockValues_3 string|nil
---@field UnlockValues_4 string|nil
---@field RequiredRecords_1 string|nil
---@field UpgradePointsEarned string|nil
---@field LockedInDemo string|nil
---@field FootprintIconAddress string|nil
---@field TechTreeDisplay string|nil
---@field TechTreePrevious string|nil
---@field TechTreeRow string|nil
---@field AdjacencyBonuses string|nil
---@field AdjacencyBonuses_1_GroupName string|nil
---@field AdjacencyBonuses_1_Evaluator string|nil
---@field AdjacencyBonuses_1_EvaluatorThreshold string|nil
---@field AdjacencyBonuses_1_Action string|nil
---@field AdjacencyBonuses_1_ActionNames string|nil
---@field AdjacencyBonuses_1_ActionNames_1 string|nil
---@field AdjacencyBonuses_1_ActionNames_2 string|nil
---@field AdjacencyBonuses_1_ActionNames_3 string|nil
---@field AdjacencyBonuses_1_ActionNames_4 string|nil
---@field AdjacencyBonuses_1_ActionNames_5 string|nil
---@field AdjacencyBonuses_1_EvaluatorValue string|nil
---@field AdjacencyBonuses_1_ActionValue string|nil
---@field AdjacencyBonuses_2_GroupName string|nil
---@field AdjacencyBonuses_2_Evaluator string|nil
---@field AdjacencyBonuses_2_EvaluatorThreshold string|nil
---@field AdjacencyBonuses_2_Action string|nil
---@field AdjacencyBonuses_2_ActionNames string|nil
---@field AdjacencyBonuses_2_ActionNames_1 string|nil
---@field AdjacencyBonuses_2_ActionNames_2 string|nil
---@field AdjacencyBonuses_2_ActionNames_3 string|nil
---@field AdjacencyBonuses_2_ActionNames_4 string|nil
---@field AdjacencyBonuses_2_ActionNames_5 string|nil
---@field AdjacencyBonuses_2_EvaluatorValue string|nil
---@field AdjacencyBonuses_2_ActionValue string|nil
---@field AdjacencyBonuses_3_GroupName string|nil
---@field AdjacencyBonuses_3_Evaluator string|nil
---@field AdjacencyBonuses_3_EvaluatorThreshold string|nil
---@field AdjacencyBonuses_3_Action string|nil
---@field AdjacencyBonuses_3_ActionNames string|nil
---@field AdjacencyBonuses_3_ActionNames_1 string|nil
---@field AdjacencyBonuses_3_ActionNames_2 string|nil
---@field AdjacencyBonuses_3_ActionNames_3 string|nil
---@field AdjacencyBonuses_3_ActionNames_4 string|nil
---@field AdjacencyBonuses_3_EvaluatorValue string|nil
---@field AdjacencyBonuses_3_ActionValue string|nil
---@field AdjacencyBonuses_4_GroupName string|nil
---@field AdjacencyBonuses_4_Evaluator string|nil
---@field AdjacencyBonuses_4_EvaluatorThreshold string|nil
---@field AdjacencyBonuses_4_Action string|nil
---@field AdjacencyBonuses_4_ActionNames string|nil
---@field AdjacencyBonuses_4_EvaluatorValue string|nil
---@field AdjacencyBonuses_4_ActionValue string|nil
---@field OperationRules string|nil
---@field OperationRules_1 string|nil
---@field OperationRules_2 string|nil
---@field OperationRules_3 string|nil
---@field OperationRules_4 string|nil
---@field OperationRules_5 string|nil
---@field OperationRules_6 string|nil
---@field OperationRules_7 string|nil
---@field OperationRules_8 string|nil
---@field OperationRules_9 string|nil
---@field OperationRules_10 string|nil
---@field OperationRules_11 string|nil
---@field OperationRules_12 string|nil
---@field OperationRules_13 string|nil
---@field MaxPeeps string|nil
---@field PeepExhaustionRemoved string|nil
---@field PeepAgeAdded string|nil
---@field PeepHappinessAdded string|nil
---@field PeepHappinessCost string|nil
---@field PollutionOutputMode string|nil
---@field SourceOfOxygenRange string|nil
---@field Resources string|nil
---@field Resources_1_Name string|nil
---@field Resources_1_Maximum string|nil
---@field Resources_1_StorageMode string|nil
---@field Resources_1_StartFull string|nil
---@field Resources_1_FetchInRange string|nil
---@field Resources_1_CanBeShared string|nil
---@field Resources_1_CycleThoughResourceSources string|nil
---@field Resources_1_GatheringMode string|nil
---@field Resources_1_DistributionMode string|nil
---@field Resources_1_DeliverInRange string|nil
---@field Resources_1_VehicleFetchsAndDelivers string|nil
---@field Resources_2_Name string|nil
---@field Resources_2_Maximum string|nil
---@field Resources_2_StorageMode string|nil
---@field Resources_2_StartFull string|nil
---@field Resources_2_FetchInRange string|nil
---@field Resources_2_CanBeShared string|nil
---@field Resources_2_CycleThoughResourceSources string|nil
---@field Resources_2_GatheringMode string|nil
---@field Resources_2_DistributionMode string|nil
---@field Resources_2_DeliverInRange string|nil
---@field Resources_2_VehicleFetchsAndDelivers string|nil
---@field Resources_3_Name string|nil
---@field Resources_3_Maximum string|nil
---@field Resources_3_StorageMode string|nil
---@field Resources_3_StartFull string|nil
---@field Resources_3_FetchInRange string|nil
---@field Resources_3_CanBeShared string|nil
---@field Resources_3_CycleThoughResourceSources string|nil
---@field Resources_3_GatheringMode string|nil
---@field Resources_3_DistributionMode string|nil
---@field Resources_3_DeliverInRange string|nil
---@field Resources_3_VehicleFetchsAndDelivers string|nil
---@field Resources_4_Name string|nil
---@field Resources_4_Maximum string|nil
---@field Resources_4_StorageMode string|nil
---@field Resources_4_StartFull string|nil
---@field Resources_4_FetchInRange string|nil
---@field Resources_4_CanBeShared string|nil
---@field Resources_4_CycleThoughResourceSources string|nil
---@field Resources_4_GatheringMode string|nil
---@field Resources_4_DistributionMode string|nil
---@field Resources_4_DeliverInRange string|nil
---@field Resources_4_VehicleFetchsAndDelivers string|nil
---@field Resources_5_Name string|nil
---@field Resources_5_Maximum string|nil
---@field Resources_5_StorageMode string|nil
---@field Resources_5_StartFull string|nil
---@field Resources_5_FetchInRange string|nil
---@field Resources_5_CanBeShared string|nil
---@field Resources_5_CycleThoughResourceSources string|nil
---@field Resources_5_GatheringMode string|nil
---@field Resources_5_DistributionMode string|nil
---@field Resources_5_DeliverInRange string|nil
---@field Resources_5_VehicleFetchsAndDelivers string|nil
---@field Resources_6_Name string|nil
---@field Resources_6_Maximum string|nil
---@field Resources_6_StorageMode string|nil
---@field Resources_6_StartFull string|nil
---@field Resources_6_FetchInRange string|nil
---@field Resources_6_CanBeShared string|nil
---@field Resources_6_CycleThoughResourceSources string|nil
---@field Resources_6_GatheringMode string|nil
---@field Resources_6_DistributionMode string|nil
---@field Resources_6_DeliverInRange string|nil
---@field Resources_6_VehicleFetchsAndDelivers string|nil
---@field Resources_7_Name string|nil
---@field Resources_7_Maximum string|nil
---@field Resources_7_StorageMode string|nil
---@field Resources_7_StartFull string|nil
---@field Resources_7_FetchInRange string|nil
---@field Resources_7_CanBeShared string|nil
---@field Resources_7_CycleThoughResourceSources string|nil
---@field Resources_7_GatheringMode string|nil
---@field Resources_7_DistributionMode string|nil
---@field Resources_7_DeliverInRange string|nil
---@field Resources_7_VehicleFetchsAndDelivers string|nil
---@field Resources_8_Name string|nil
---@field Resources_8_Maximum string|nil
---@field Resources_8_StorageMode string|nil
---@field Resources_8_StartFull string|nil
---@field Resources_8_FetchInRange string|nil
---@field Resources_8_CanBeShared string|nil
---@field Resources_8_CycleThoughResourceSources string|nil
---@field Resources_8_GatheringMode string|nil
---@field Resources_8_DistributionMode string|nil
---@field Resources_8_DeliverInRange string|nil
---@field Resources_8_VehicleFetchsAndDelivers string|nil
---@field Resources_9_Name string|nil
---@field Resources_9_Maximum string|nil
---@field Resources_9_StorageMode string|nil
---@field Resources_9_StartFull string|nil
---@field Resources_9_FetchInRange string|nil
---@field Resources_9_CanBeShared string|nil
---@field Resources_9_CycleThoughResourceSources string|nil
---@field Resources_9_GatheringMode string|nil
---@field Resources_9_DistributionMode string|nil
---@field Resources_9_DeliverInRange string|nil
---@field Resources_9_VehicleFetchsAndDelivers string|nil
---@field ResourceGroups string|nil
---@field ResourceGroups_1_Type string|nil
---@field ResourceGroups_1_Maximum string|nil
---@field ResourceGroups_1_GatheringMode string|nil
---@field ResourceGroups_1_DistributionMode string|nil
---@field ResourceGroups_1_StartFullResource string|nil
---@field ResourceGroups_2_Type string|nil
---@field ResourceGroups_2_Maximum string|nil
---@field ResourceGroups_2_GatheringMode string|nil
---@field ResourceGroups_2_DistributionMode string|nil
---@field ResourceGroups_2_StartFullResource string|nil
---@field DefinedResourceLists string|nil
---@field DefinedResourceLists_2_Name string|nil
---@field DefinedResourceLists_2_Maximum string|nil
---@field DefinedResourceLists_2_StorageMode string|nil
---@field DefinedResourceLists_2_StartFull string|nil
---@field DefinedResourceLists_2_FetchInRange string|nil
---@field DefinedResourceLists_2_CanBeShared string|nil
---@field DefinedResourceLists_2_CycleThoughResourceSources string|nil
---@field DefinedResourceLists_2_GatheringMode string|nil
---@field DefinedResourceLists_2_DistributionMode string|nil
---@field DefinedResourceLists_2_DeliverInRange string|nil
---@field DefinedResourceLists_2_VehicleFetchsAndDelivers string|nil
---@field DefaultFetchMode string|nil
---@field DefaultDeliveryMode string|nil
---@field FetchTime string|nil
---@field DeliveryTime string|nil
---@field TotalStorageMaximum string|nil
---@field MaxSeedSlots string|nil
---@field BuildingTasks string|nil
---@field PlayerSelectableTasks_1 string|nil
---@field PlayerSelectableTasks_2 string|nil
---@field PlayerSelectableTasks_3 string|nil
---@field SourceDefinition string|nil
---@field Hotkey string|nil
---@field ConstructionMustReplace string|nil
---@field AutoUnlock string|nil
---@field TechTreeListPreviousExit string|nil
---@field TechTreeListEntry string|nil
---@field TechTreeLineVerticalOffset string|nil
---@field PowerRange string|nil
---@field PeepEnergyAdded string|nil
---@field PeepEnergyCost string|nil
-- FIELDS that fit the pattern but were proven to not exist:
-- BuildingTasks_4_Outputs_2_*
-- BuildingTasks_4_Inputs_2_*
-- BuildingTasks_5_Outputs_2_*
-- BuildingTasks_5_Inputs_2_*
-- Commented out fields are not used in BuildingTask
--- Cargo row from querying BuildingTasks; all values are strings at runtime.
---@class CargoBuildingTasksRecord
---@field page_name string|nil
---@field guid string|nil
---@field BuildingTasks_1_Name string|nil
---@field BuildingTasks_1_InitialState string|nil
---@field BuildingTasks_1_Time string|nil
---@field BuildingTasks_1_MinimumTimeDelta string|nil
---@field BuildingTasks_1_Outputs_1_Type string|nil
---@field BuildingTasks_1_Outputs_1_Resource string|nil
---@field BuildingTasks_1_Outputs_1_Value string|nil
---@field BuildingTasks_1_Outputs_2_Type string|nil
---@field BuildingTasks_1_Outputs_2_Resource string|nil
---@field BuildingTasks_1_Outputs_2_Value string|nil
---@field BuildingTasks_1_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_1_Inputs_1_Type string|nil
---@field BuildingTasks_1_Inputs_1_Resource string|nil
---@field BuildingTasks_1_Inputs_1_Value string|nil
---@field BuildingTasks_1_Inputs_2_Type string|nil
---@field BuildingTasks_1_Inputs_2_Resource string|nil
---@field BuildingTasks_1_Inputs_2_Value string|nil
---@field BuildingTasks_1_Inputs_3_Type string|nil
---@field BuildingTasks_1_Inputs_3_Resource string|nil
---@field BuildingTasks_1_Inputs_3_Value string|nil
---@field BuildingTasks_1_Inputs_4_Type string|nil
---@field BuildingTasks_1_Inputs_4_Resource string|nil
---@field BuildingTasks_1_Inputs_4_Value string|nil
---@field BuildingTasks_1_DescriptionTerm_en string|nil
---@field BuildingTasks_2_Name string|nil
---@field BuildingTasks_2_InitialState string|nil
---@field BuildingTasks_2_Time string|nil
---@field BuildingTasks_2_MinimumTimeDelta string|nil
---@field BuildingTasks_2_Outputs_1_Type string|nil
---@field BuildingTasks_2_Outputs_1_Resource string|nil
---@field BuildingTasks_2_Outputs_1_Value string|nil
---@field BuildingTasks_2_Outputs_2_Type string|nil
---@field BuildingTasks_2_Outputs_2_Resource string|nil
---@field BuildingTasks_2_Outputs_2_Value string|nil
---@field BuildingTasks_2_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_2_Inputs_1_Type string|nil
---@field BuildingTasks_2_Inputs_1_Resource string|nil
---@field BuildingTasks_2_Inputs_1_Value string|nil
---@field BuildingTasks_2_Inputs_2_Type string|nil
---@field BuildingTasks_2_Inputs_2_Resource string|nil
---@field BuildingTasks_2_Inputs_2_Value string|nil
---@field BuildingTasks_2_Inputs_3_Type string|nil
---@field BuildingTasks_2_Inputs_3_Resource string|nil
---@field BuildingTasks_2_Inputs_3_Value string|nil
---@field BuildingTasks_3_Name string|nil
---@field BuildingTasks_3_InitialState string|nil
---@field BuildingTasks_3_Time string|nil
---@field BuildingTasks_3_MinimumTimeDelta string|nil
---@field BuildingTasks_3_Outputs_1_Type string|nil
---@field BuildingTasks_3_Outputs_1_Resource string|nil
---@field BuildingTasks_3_Outputs_1_Value string|nil
---@field BuildingTasks_3_Outputs_2_Type string|nil
---@field BuildingTasks_3_Outputs_2_Resource string|nil
---@field BuildingTasks_3_Outputs_2_Value string|nil
---@field BuildingTasks_3_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_3_Inputs_1_Type string|nil
---@field BuildingTasks_3_Inputs_1_Resource string|nil
---@field BuildingTasks_3_Inputs_1_Value string|nil
---@field BuildingTasks_3_Inputs_2_Type string|nil
---@field BuildingTasks_3_Inputs_2_Resource string|nil
---@field BuildingTasks_3_Inputs_2_Value string|nil
---@field BuildingTasks_4_Name string|nil
---@field BuildingTasks_4_InitialState string|nil
---@field BuildingTasks_4_Time string|nil
---@field BuildingTasks_4_MinimumTimeDelta string|nil
---@field BuildingTasks_4_Outputs_1_Type string|nil
---@field BuildingTasks_4_Outputs_1_Resource string|nil
---@field BuildingTasks_4_Outputs_1_Value string|nil
---@field BuildingTasks_4_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_4_Inputs_1_Type string|nil
---@field BuildingTasks_4_Inputs_1_Resource string|nil
---@field BuildingTasks_4_Inputs_1_Value string|nil
---@field BuildingTasks_5_Name string|nil
---@field BuildingTasks_5_InitialState string|nil
---@field BuildingTasks_5_Time string|nil
---@field BuildingTasks_5_MinimumTimeDelta string|nil
---@field BuildingTasks_5_Outputs_1_Type string|nil
---@field BuildingTasks_5_Outputs_1_Resource string|nil
---@field BuildingTasks_5_Outputs_1_Value string|nil
---@field BuildingTasks_5_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_5_Inputs_1_Type string|nil
---@field BuildingTasks_5_Inputs_1_Resource string|nil
---@field BuildingTasks_5_Inputs_1_Value string|nil
---@field BuildingTasks_6_Name string|nil
---@field BuildingTasks_6_InitialState string|nil
---@field BuildingTasks_6_Time string|nil
---@field BuildingTasks_6_MinimumTimeDelta string|nil
---@field BuildingTasks_6_Outputs_1_Type string|nil
---@field BuildingTasks_6_Outputs_1_Resource string|nil
---@field BuildingTasks_6_Outputs_1_Value string|nil
---@field BuildingTasks_6_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_6_Inputs_1_Type string|nil
---@field BuildingTasks_6_Inputs_1_Resource string|nil
---@field BuildingTasks_6_Inputs_1_Value string|nil
---@field BuildingTasks_6_Inputs_2_Type string|nil
---@field BuildingTasks_6_Inputs_2_Resource string|nil
---@field BuildingTasks_6_Inputs_2_Value string|nil
---@field BuildingTasks_7_Name string|nil
---@field BuildingTasks_7_InitialState string|nil
---@field BuildingTasks_7_Time string|nil
---@field BuildingTasks_7_MinimumTimeDelta string|nil
---@field BuildingTasks_7_Outputs_1_Type string|nil
---@field BuildingTasks_7_Outputs_1_Resource string|nil
---@field BuildingTasks_7_Outputs_1_Value string|nil
---@field BuildingTasks_7_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_7_Inputs_1_Type string|nil
---@field BuildingTasks_7_Inputs_1_Resource string|nil
---@field BuildingTasks_7_Inputs_1_Value string|nil
---@field BuildingTasks_8_Name string|nil
---@field BuildingTasks_8_InitialState string|nil
---@field BuildingTasks_8_Time string|nil
---@field BuildingTasks_8_MinimumTimeDelta string|nil
---@field BuildingTasks_8_Outputs_1_Type string|nil
---@field BuildingTasks_8_Outputs_1_Resource string|nil
---@field BuildingTasks_8_Outputs_1_Value string|nil
---@field BuildingTasks_8_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_8_Inputs_1_Type string|nil
---@field BuildingTasks_8_Inputs_1_Resource string|nil
---@field BuildingTasks_8_Inputs_1_Value string|nil
---@field BuildingTasks_9_Name string|nil
---@field BuildingTasks_9_InitialState string|nil
---@field BuildingTasks_9_Time string|nil
---@field BuildingTasks_9_MinimumTimeDelta string|nil
---@field BuildingTasks_9_Outputs_1_Type string|nil
---@field BuildingTasks_9_Outputs_1_Resource string|nil
---@field BuildingTasks_9_Outputs_1_Value string|nil
---@field BuildingTasks_9_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_9_Inputs_1_Type string|nil
---@field BuildingTasks_9_Inputs_1_Resource string|nil
---@field BuildingTasks_9_Inputs_1_Value string|nil
--#endregion
--#region MARK: Cargo consts
local FILTER_CATEGORY = "Category"
---@alias VALID_FILTER_FIELDS "Category"
local QUERIES = {
BUILDINGS = {
TABLE = "Buildings",
WHERE_NAME = "page_name",
WHERE_ID = "Name",
WHERE_TASKS_GUID = "BuildingTasks",
ORDER_BY = "page_name",
FIELDS_NAME_ONLY = {
"page_name",
},
FIELDS_FULL = {
"page_name",
"guid",
"Name",
FILTER_CATEGORY,
"DisplayNameTerm_en",
"DisplayNamePluralTerm_en",
"DescriptionTerm_en",
-- "UpgradeTerm",
-- "UpgradeTerm_en",
"IconAddress",
-- "PlacementRules_1",
-- "PlacementRules_2",
-- "PlacementRules_3",
-- "PlacementRules_4",
-- "PlacementRules_5",
-- "PlacementRules_6",
-- "AnchorBuildingNames_1",
-- "AnchorBuildingNames_2",
-- "ConstructionResources",
"ConstructionResources_1_Name",
"ConstructionResources_1_Amount",
"ConstructionResources_2_Name",
"ConstructionResources_2_Amount",
"ConstructionResources_3_Name",
"ConstructionResources_3_Amount",
"ConstructionResources_4_Name",
"ConstructionResources_4_Amount",
"ConstructionResources_5_Name",
"ConstructionResources_5_Amount",
"ConstructionResources_6_Name",
"ConstructionResources_6_Amount",
-- "SecondaryPrefabAddresses_1",
-- "SecondaryPrefabAddresses_2",
-- "RepairResources_1_Name",
-- "RepairResources_1_Amount",
-- "RepairResources_2_Name",
-- "RepairResources_2_Amount",
-- "RepairResources_3_Name",
-- "RepairResources_3_Amount",
-- "RepairResources_4_Name",
-- "RepairResources_4_Amount",
-- "RepairResources_5_Name",
-- "RepairResources_5_Amount",
-- "RepairResources_6_Name",
-- "RepairResources_6_Amount",
"ConstructionTime",
-- "ConstructionPeepCount",
"UnlockMode",
"UnlockValues",
"UnlockValues_1",
"UnlockValues_2",
"UnlockValues_3",
"UnlockValues_4",
-- "RequiredRecords_1",
-- "UpgradePointsEarned",
"LockedInDemo",
"FootprintIconAddress",
-- "TechTreeDisplay",
"TechTreePrevious",
-- "TechTreeRow",
-- "AdjacencyBonuses",
"AdjacencyBonuses_1_GroupName",
"AdjacencyBonuses_1_Evaluator",
"AdjacencyBonuses_1_EvaluatorThreshold",
"AdjacencyBonuses_1_Action",
-- "AdjacencyBonuses_1_ActionNames",
-- "AdjacencyBonuses_1_ActionNames_1",
-- "AdjacencyBonuses_1_ActionNames_2",
-- "AdjacencyBonuses_1_ActionNames_3",
-- "AdjacencyBonuses_1_ActionNames_4",
-- "AdjacencyBonuses_1_ActionNames_5",
"AdjacencyBonuses_1_EvaluatorValue",
"AdjacencyBonuses_1_ActionValue",
"AdjacencyBonuses_2_GroupName",
"AdjacencyBonuses_2_Evaluator",
"AdjacencyBonuses_2_EvaluatorThreshold",
"AdjacencyBonuses_2_Action",
-- "AdjacencyBonuses_2_ActionNames",
-- "AdjacencyBonuses_2_ActionNames_1",
-- "AdjacencyBonuses_2_ActionNames_2",
-- "AdjacencyBonuses_2_ActionNames_3",
-- "AdjacencyBonuses_2_ActionNames_4",
-- "AdjacencyBonuses_2_ActionNames_5",
"AdjacencyBonuses_2_EvaluatorValue",
"AdjacencyBonuses_2_ActionValue",
"AdjacencyBonuses_3_GroupName",
"AdjacencyBonuses_3_Evaluator",
"AdjacencyBonuses_3_EvaluatorThreshold",
"AdjacencyBonuses_3_Action",
-- "AdjacencyBonuses_3_ActionNames",
-- "AdjacencyBonuses_3_ActionNames_1",
-- "AdjacencyBonuses_3_ActionNames_2",
-- "AdjacencyBonuses_3_ActionNames_3",
-- "AdjacencyBonuses_3_ActionNames_4",
"AdjacencyBonuses_3_EvaluatorValue",
"AdjacencyBonuses_3_ActionValue",
"AdjacencyBonuses_4_GroupName",
"AdjacencyBonuses_4_Evaluator",
"AdjacencyBonuses_4_EvaluatorThreshold",
"AdjacencyBonuses_4_Action",
-- "AdjacencyBonuses_4_ActionNames",
"AdjacencyBonuses_4_EvaluatorValue",
"AdjacencyBonuses_4_ActionValue",
-- "OperationRules",
-- "OperationRules_1",
-- "OperationRules_2",
-- "OperationRules_3",
-- "OperationRules_4",
-- "OperationRules_5",
-- "OperationRules_6",
-- "OperationRules_7",
-- "OperationRules_8",
-- "OperationRules_9",
-- "OperationRules_10",
-- "OperationRules_11",
-- "OperationRules_12",
-- "OperationRules_13",
"MaxPeeps",
"PeepExhaustionRemoved",
"PeepAgeAdded",
"PeepHappinessAdded",
"PeepHappinessCost",
"PollutionOutputMode",
"SourceOfOxygenRange",
-- "Resources",
-- "Resources_1_Name",
-- "Resources_1_Maximum",
-- "Resources_1_StorageMode",
-- "Resources_1_StartFull",
-- "Resources_1_FetchInRange",
-- "Resources_1_CanBeShared",
-- "Resources_1_CycleThoughResourceSources",
-- "Resources_1_GatheringMode",
-- "Resources_1_DistributionMode",
-- "Resources_1_DeliverInRange",
-- "Resources_1_VehicleFetchsAndDelivers",
-- "Resources_2_Name",
-- "Resources_2_Maximum",
-- "Resources_2_StorageMode",
-- "Resources_2_StartFull",
-- "Resources_2_FetchInRange",
-- "Resources_2_CanBeShared",
-- "Resources_2_CycleThoughResourceSources",
-- "Resources_2_GatheringMode",
-- "Resources_2_DistributionMode",
-- "Resources_2_DeliverInRange",
-- "Resources_2_VehicleFetchsAndDelivers",
-- "Resources_3_Name",
-- "Resources_3_Maximum",
-- "Resources_3_StorageMode",
-- "Resources_3_StartFull",
-- "Resources_3_FetchInRange",
-- "Resources_3_CanBeShared",
-- "Resources_3_CycleThoughResourceSources",
-- "Resources_3_GatheringMode",
-- "Resources_3_DistributionMode",
-- "Resources_3_DeliverInRange",
-- "Resources_3_VehicleFetchsAndDelivers",
-- "Resources_4_Name",
-- "Resources_4_Maximum",
-- "Resources_4_StorageMode",
-- "Resources_4_StartFull",
-- "Resources_4_FetchInRange",
-- "Resources_4_CanBeShared",
-- "Resources_4_CycleThoughResourceSources",
-- "Resources_4_GatheringMode",
-- "Resources_4_DistributionMode",
-- "Resources_4_DeliverInRange",
-- "Resources_4_VehicleFetchsAndDelivers",
-- "Resources_5_Name",
-- "Resources_5_Maximum",
-- "Resources_5_StorageMode",
-- "Resources_5_StartFull",
-- "Resources_5_FetchInRange",
-- "Resources_5_CanBeShared",
-- "Resources_5_CycleThoughResourceSources",
-- "Resources_5_GatheringMode",
-- "Resources_5_DistributionMode",
-- "Resources_5_DeliverInRange",
-- "Resources_5_VehicleFetchsAndDelivers",
-- "Resources_6_Name",
-- "Resources_6_Maximum",
-- "Resources_6_StorageMode",
-- "Resources_6_StartFull",
-- "Resources_6_FetchInRange",
-- "Resources_6_CanBeShared",
-- "Resources_6_CycleThoughResourceSources",
-- "Resources_6_GatheringMode",
-- "Resources_6_DistributionMode",
-- "Resources_6_DeliverInRange",
-- "Resources_6_VehicleFetchsAndDelivers",
-- "Resources_7_Name",
-- "Resources_7_Maximum",
-- "Resources_7_StorageMode",
-- "Resources_7_StartFull",
-- "Resources_7_FetchInRange",
-- "Resources_7_CanBeShared",
-- "Resources_7_CycleThoughResourceSources",
-- "Resources_7_GatheringMode",
-- "Resources_7_DistributionMode",
-- "Resources_7_DeliverInRange",
-- "Resources_7_VehicleFetchsAndDelivers",
-- "Resources_8_Name",
-- "Resources_8_Maximum",
-- "Resources_8_StorageMode",
-- "Resources_8_StartFull",
-- "Resources_8_FetchInRange",
-- "Resources_8_CanBeShared",
-- "Resources_8_CycleThoughResourceSources",
-- "Resources_8_GatheringMode",
-- "Resources_8_DistributionMode",
-- "Resources_8_DeliverInRange",
-- "Resources_8_VehicleFetchsAndDelivers",
-- "Resources_9_Name",
-- "Resources_9_Maximum",
-- "Resources_9_StorageMode",
-- "Resources_9_StartFull",
-- "Resources_9_FetchInRange",
-- "Resources_9_CanBeShared",
-- "Resources_9_CycleThoughResourceSources",
-- "Resources_9_GatheringMode",
-- "Resources_9_DistributionMode",
-- "Resources_9_DeliverInRange",
-- "Resources_9_VehicleFetchsAndDelivers",
-- "ResourceGroups",
-- "ResourceGroups_1_Type",
-- "ResourceGroups_1_Maximum",
-- "ResourceGroups_1_GatheringMode",
-- "ResourceGroups_1_DistributionMode",
-- "ResourceGroups_1_StartFullResource",
-- "ResourceGroups_2_Type",
-- "ResourceGroups_2_Maximum",
-- "ResourceGroups_2_GatheringMode",
-- "ResourceGroups_2_DistributionMode",
-- "ResourceGroups_2_StartFullResource",
-- "DefinedResourceLists",
-- "DefinedResourceLists_2_Name",
-- "DefinedResourceLists_2_Maximum",
-- "DefinedResourceLists_2_StorageMode",
-- "DefinedResourceLists_2_StartFull",
-- "DefinedResourceLists_2_FetchInRange",
-- "DefinedResourceLists_2_CanBeShared",
-- "DefinedResourceLists_2_CycleThoughResourceSources",
-- "DefinedResourceLists_2_GatheringMode",
-- "DefinedResourceLists_2_DistributionMode",
-- "DefinedResourceLists_2_DeliverInRange",
-- "DefinedResourceLists_2_VehicleFetchsAndDelivers",
-- "DefaultFetchMode",
-- "DefaultDeliveryMode",
"FetchTime",
"DeliveryTime",
"TotalStorageMaximum",
-- "MaxSeedSlots",
"BuildingTasks",
-- "PlayerSelectableTasks_1",
-- "PlayerSelectableTasks_2",
-- "PlayerSelectableTasks_3",
-- "SourceDefinition",
-- "Hotkey",
-- "ConstructionMustReplace",
-- "AutoUnlock",
-- "TechTreeListPreviousExit",
-- "TechTreeListEntry",
-- "TechTreeLineVerticalOffset",
"PowerRange",
"PeepEnergyAdded",
"PeepEnergyCost",
},
},
TASKS = {
TABLE = "BuildingTasks",
WHERE_GUID = "guid",
-- FIELDS that fit the pattern but are not declared in the DB table definition:
-- BuildingTasks_4_Outputs_2_*
-- BuildingTasks_4_Inputs_2_*
-- BuildingTasks_5_Outputs_2_*
-- BuildingTasks_5_Inputs_2_*
-- Commented out fields are not used in BuildingTask
FIELDS = {
"page_name",
"guid",
"BuildingTasks_1_Name",
-- "BuildingTasks_1_InitialState",
"BuildingTasks_1_Time",
-- "BuildingTasks_1_MinimumTimeDelta",
"BuildingTasks_1_Outputs_1_Type",
"BuildingTasks_1_Outputs_1_Resource",
"BuildingTasks_1_Outputs_1_Value",
"BuildingTasks_1_Outputs_2_Type",
"BuildingTasks_1_Outputs_2_Resource",
"BuildingTasks_1_Outputs_2_Value",
"BuildingTasks_1_Inputs_1_Type",
"BuildingTasks_1_Inputs_1_Resource",
"BuildingTasks_1_Inputs_1_Value",
"BuildingTasks_1_Inputs_2_Type",
"BuildingTasks_1_Inputs_2_Resource",
"BuildingTasks_1_Inputs_2_Value",
"BuildingTasks_1_Inputs_3_Type",
"BuildingTasks_1_Inputs_3_Resource",
"BuildingTasks_1_Inputs_3_Value",
"BuildingTasks_1_Inputs_4_Type",
"BuildingTasks_1_Inputs_4_Resource",
"BuildingTasks_1_Inputs_4_Value",
"BuildingTasks_1_PollutionSlowdownThreshold",
"BuildingTasks_2_Name",
-- "BuildingTasks_2_InitialState",
"BuildingTasks_2_Time",
-- "BuildingTasks_2_MinimumTimeDelta",
"BuildingTasks_2_Outputs_1_Type",
"BuildingTasks_2_Outputs_1_Resource",
"BuildingTasks_2_Outputs_1_Value",
"BuildingTasks_2_Outputs_2_Type",
"BuildingTasks_2_Outputs_2_Resource",
"BuildingTasks_2_Outputs_2_Value",
"BuildingTasks_2_PollutionSlowdownThreshold",
"BuildingTasks_2_Inputs_1_Type",
"BuildingTasks_2_Inputs_1_Resource",
"BuildingTasks_2_Inputs_1_Value",
"BuildingTasks_2_Inputs_2_Type",
"BuildingTasks_2_Inputs_2_Resource",
"BuildingTasks_2_Inputs_2_Value",
"BuildingTasks_2_Inputs_3_Type",
"BuildingTasks_2_Inputs_3_Resource",
"BuildingTasks_2_Inputs_3_Value",
"BuildingTasks_3_Name",
-- "BuildingTasks_3_InitialState",
"BuildingTasks_3_Time",
-- "BuildingTasks_3_MinimumTimeDelta",
"BuildingTasks_3_Outputs_1_Type",
"BuildingTasks_3_Outputs_1_Resource",
"BuildingTasks_3_Outputs_1_Value",
"BuildingTasks_3_Outputs_2_Type",
"BuildingTasks_3_Outputs_2_Resource",
"BuildingTasks_3_Outputs_2_Value",
"BuildingTasks_3_PollutionSlowdownThreshold",
"BuildingTasks_3_Inputs_1_Type",
"BuildingTasks_3_Inputs_1_Resource",
"BuildingTasks_3_Inputs_1_Value",
"BuildingTasks_3_Inputs_2_Type",
"BuildingTasks_3_Inputs_2_Resource",
"BuildingTasks_3_Inputs_2_Value",
"BuildingTasks_4_Name",
-- "BuildingTasks_4_InitialState",
"BuildingTasks_4_Time",
-- "BuildingTasks_4_MinimumTimeDelta",
"BuildingTasks_4_Outputs_1_Type",
"BuildingTasks_4_Outputs_1_Resource",
"BuildingTasks_4_Outputs_1_Value",
"BuildingTasks_4_PollutionSlowdownThreshold",
"BuildingTasks_4_Inputs_1_Type",
"BuildingTasks_4_Inputs_1_Resource",
"BuildingTasks_4_Inputs_1_Value",
"BuildingTasks_5_Name",
-- "BuildingTasks_5_InitialState",
"BuildingTasks_5_Time",
-- "BuildingTasks_5_MinimumTimeDelta",
"BuildingTasks_5_Outputs_1_Type",
"BuildingTasks_5_Outputs_1_Resource",
"BuildingTasks_5_Outputs_1_Value",
"BuildingTasks_5_PollutionSlowdownThreshold",
"BuildingTasks_5_Inputs_1_Type",
"BuildingTasks_5_Inputs_1_Resource",
"BuildingTasks_5_Inputs_1_Value",
"BuildingTasks_6_Name",
-- "BuildingTasks_6_InitialState",
"BuildingTasks_6_Time",
-- "BuildingTasks_6_MinimumTimeDelta",
"BuildingTasks_6_Outputs_1_Type",
"BuildingTasks_6_Outputs_1_Resource",
"BuildingTasks_6_Outputs_1_Value",
"BuildingTasks_6_PollutionSlowdownThreshold",
"BuildingTasks_6_Inputs_1_Type",
"BuildingTasks_6_Inputs_1_Resource",
"BuildingTasks_6_Inputs_1_Value",
"BuildingTasks_6_Inputs_2_Type",
"BuildingTasks_6_Inputs_2_Resource",
"BuildingTasks_6_Inputs_2_Value",
"BuildingTasks_7_Name",
-- "BuildingTasks_7_InitialState",
"BuildingTasks_7_Time",
-- "BuildingTasks_7_MinimumTimeDelta",
"BuildingTasks_7_Outputs_1_Type",
"BuildingTasks_7_Outputs_1_Resource",
"BuildingTasks_7_Outputs_1_Value",
"BuildingTasks_7_PollutionSlowdownThreshold",
"BuildingTasks_7_Inputs_1_Type",
"BuildingTasks_7_Inputs_1_Resource",
"BuildingTasks_7_Inputs_1_Value",
"BuildingTasks_8_Name",
-- "BuildingTasks_8_InitialState",
"BuildingTasks_8_Time",
-- "BuildingTasks_8_MinimumTimeDelta",
"BuildingTasks_8_Outputs_1_Type",
"BuildingTasks_8_Outputs_1_Resource",
"BuildingTasks_8_Outputs_1_Value",
"BuildingTasks_8_PollutionSlowdownThreshold",
"BuildingTasks_8_Inputs_1_Type",
"BuildingTasks_8_Inputs_1_Resource",
"BuildingTasks_8_Inputs_1_Value",
"BuildingTasks_9_Name",
-- "BuildingTasks_9_InitialState",
"BuildingTasks_9_Time",
-- "BuildingTasks_9_MinimumTimeDelta",
"BuildingTasks_9_Outputs_1_Type",
"BuildingTasks_9_Outputs_1_Resource",
"BuildingTasks_9_Outputs_1_Value",
"BuildingTasks_9_PollutionSlowdownThreshold",
"BuildingTasks_9_Inputs_1_Type",
"BuildingTasks_9_Inputs_1_Resource",
"BuildingTasks_9_Inputs_1_Value",
}
}
}
--#endregion
--#region MARK: Query buildings
--- Skips unwanted buildings from a query result.
---@param results CargoBuildingRecord[]
---@return CargoBuildingRecord[]
local function skip_unwanted_buildings(results)
local new_results = {}
for _, record in ipairs(results) do
if not p.SKIPPED_BUILDINGS_NAMES[record.Name] then
table.insert(new_results, record)
end
end
return new_results
end
--- Queries cargo for all building records.
---@return CargoBuildingRecord[]
local function query_all_buildings()
local cargo = mw.ext.cargo
if not cargo then return {} end
local result = cargo.query(
QUERIES.BUILDINGS.TABLE,
table.concat(QUERIES.BUILDINGS.FIELDS_FULL, ","),
{
limit = 150,
orderBy = QUERIES.BUILDINGS.ORDER_BY,
})
if not result or #result == 0 then return {} end
result = skip_unwanted_buildings(result)
return result
end
--- Queries cargo for building records by the given filter.
---@param filter_field VALID_FILTER_FIELDS
---@param filter_value string
---@return CargoBuildingRecord[]
local function query_buildings_by_filter(filter_field, filter_value)
local cargo = mw.ext.cargo
if not cargo then return {} end
local result = cargo.query(
QUERIES.BUILDINGS.TABLE,
table.concat(QUERIES.BUILDINGS.FIELDS_FULL, ","),
{
where = filter_field .. '="' .. filter_value .. '"',
orderBy = QUERIES.BUILDINGS.ORDER_BY,
})
if not result or #result == 0 then return {} end
result = skip_unwanted_buildings(result)
return result
end
--- Queries cargo for the building record with the given name.
---@param building_name string the name of the building to fetch
---@return CargoBuildingRecord|nil
local function query_building(building_name)
local cargo = mw.ext.cargo
if not cargo then return nil end
local result = cargo.query(
QUERIES.BUILDINGS.TABLE,
table.concat(QUERIES.BUILDINGS.FIELDS_FULL, ","),
{
where = QUERIES.BUILDINGS.WHERE_NAME .. '="' .. building_name .. '"',
})
if not result or #result == 0 then return nil end
result = skip_unwanted_buildings(result)
return result[1]
end
--- Queries cargo for the building name only with the given id.
---@param building_id string the id of the building to fetch
---@return CargoBuildingRecord|nil
local function query_building_name_only(building_id)
local cargo = mw.ext.cargo
if not cargo then return nil end
local result = cargo.query(
QUERIES.BUILDINGS.TABLE,
table.concat(QUERIES.BUILDINGS.FIELDS_NAME_ONLY, ","),
{
where = QUERIES.BUILDINGS.WHERE_ID .. '="' .. building_id .. '"',
})
if not result or #result == 0 then return nil end
result = skip_unwanted_buildings(result)
return result[1]
end
--- Queries cargo for the building name only with the given guid.
---@param tasks_guid string the guid of the tasks list to look for in buildings
---@return CargoBuildingRecord|nil
local function query_building_name_only_by_tasks_guid(tasks_guid)
local cargo = mw.ext.cargo
if not cargo then return nil end
local result = cargo.query(
QUERIES.BUILDINGS.TABLE,
table.concat(QUERIES.BUILDINGS.FIELDS_NAME_ONLY, ","),
{
where = QUERIES.BUILDINGS.WHERE_TASKS_GUID .. '="' .. tasks_guid .. '"',
})
if not result or #result == 0 then return nil end
result = skip_unwanted_buildings(result)
return result[1]
end
--#endregion
--#region MARK: Query tasks
--- Queries cargo for the building tasks record with the given guid.
---@param building_tasks_guid string the guid of the building tasks to fetch
---@return CargoBuildingTasksRecord|nil
local function query_building_tasks(building_tasks_guid)
local cargo = mw.ext.cargo
if not cargo then return nil end
local result = cargo.query(
QUERIES.TASKS.TABLE,
table.concat(QUERIES.TASKS.FIELDS, ","),
{
where = QUERIES.TASKS.WHERE_GUID .. '="' .. building_tasks_guid .. '"',
})
if not result or #result == 0 then return nil end
return result[1]
end
--- Queries cargo for all building tasks.
---@return CargoBuildingTasksRecord[]
local function query_all_building_tasks()
local cargo = mw.ext.cargo
if not cargo then return {} end
local result = cargo.query(
QUERIES.TASKS.TABLE,
table.concat(QUERIES.TASKS.FIELDS, ",")
)
if not result or #result == 0 then return {} end
return result
end
--#endregion
--#region MARK: Restructuring
--- Restructures the construction resources of a building record from the database into a more usable format.
---@param record CargoBuildingRecord
---@return ConstructionPair[]
local function restructure_construction_resources(record)
local construction_resources = {}
for i = 1, p.MAX_CONSTRUCTION_PAIRS do
local construction_resource = record[string.format("ConstructionResources_%d_Name", i)]
local construction_amount = record[string.format("ConstructionResources_%d_Amount", i)]
if construction_resource and construction_amount then
table.insert(construction_resources, {
name = construction_resource,
amount = tonumber(construction_amount),
})
end
end
return construction_resources
end
--- Restructures the unlock values of a building record from the database into a more usable format.
---@param record CargoBuildingRecord
---@return string[]
local function restructure_unlock_values(record)
local unlock_values = {}
for i = 1, p.MAX_UNLOCK_VALUES do
local unlock_value = record[string.format("UnlockValues_%d", i)]
if unlock_value then
table.insert(unlock_values, unlock_value)
end
end
return unlock_values
end
--- Restructures the adjacency bonuses of a building record from the database into a more usable format.
---@param record CargoBuildingRecord
---@return AdjacencyBonus[]
local function restructure_adjacency_bonuses(record)
local adjacency_bonuses = {}
for i = 1, p.MAX_ADJACENCY_BONUSES do
local group_name = record[string.format("AdjacencyBonuses_%d_GroupName", i)]
local evaluator_type = record[string.format("AdjacencyBonuses_%d_Evaluator", i)]
local evaluator_threshold = record[string.format("AdjacencyBonuses_%d_EvaluatorThreshold", i)]
local evaluator_value = record[string.format("AdjacencyBonuses_%d_EvaluatorValue", i)]
local action = record[string.format("AdjacencyBonuses_%d_Action", i)]
local action_value = record[string.format("AdjacencyBonuses_%d_ActionValue", i)]
if group_name and evaluator_type and evaluator_threshold and evaluator_value and action and action_value then
table.insert(adjacency_bonuses, {
bonus_name = group_name,
evaluator_type = evaluator_type,
evaluator_threshold = tonumber(evaluator_threshold),
evaluator_value = evaluator_value,
action = action,
action_value = tonumber(action_value),
})
end
end
return adjacency_bonuses
end
--- Restructures the inputs or ouputs of a building task
---@param task_record CargoBuildingTasksRecord the building tasks record retrieved for the building
---@param task_num number which task to restructure
---@param which_io "Inputs"|"Outputs" the type of tasks to restructure
---@return BuildingTaskIO[]
local function restructure_task_io(task_record, task_num, which_io)
local task_io = {}
local max = ((which_io == "Inputs") and p.MAX_BUILDING_TASK_INPUTS) or p.MAX_BUILDING_TASK_OUTPUTS
local task_type_prefix = "BuildingTasks_" .. task_num .. "_" .. which_io .. "_%d_"
for i = 1, max do
local put_type = task_record[string.format(task_type_prefix .. "Type", i)]
local put_resource = task_record[string.format(task_type_prefix .. "Resource", i)]
local put_value = task_record[string.format(task_type_prefix .. "Value", i)]
if put_type or put_resource or put_value then
table.insert(task_io, {
type = put_type,
resource = put_resource,
value = put_value,
})
end
end
return task_io
end
--- Restructures a task record from the database into a more usable format.
---@param task_record CargoBuildingTasksRecord
---@return BuildingTask[]
local function restructure_tasks(task_record)
local tasks = {}
for i = 1, p.MAX_BUILDING_TASKS do
local task_name = task_record[string.format("BuildingTasks_%d_Name", i)]
local time = tonumber(task_record[string.format("BuildingTasks_%d_Time", i)])
local pollution_slowdown = tonumber(task_record[string.format("BuildingTasks_%d_PollutionSlowdownThreshold", i)])
local outputs = restructure_task_io(task_record, i, "Outputs")
local inputs = restructure_task_io(task_record, i, "Inputs")
if task_name then
table.insert(tasks, {
task_name = task_name,
time = time,
outputs = outputs,
inputs = inputs,
pollution_slowdown_threshold = pollution_slowdown,
})
end
end
return tasks
end
--- Restructures the tasks of a building record from the database into a more usable format.
---@param building_record CargoBuildingRecord
---@return BuildingTask[]
local function restructure_tasks_in_building(building_record)
local tasks_guid = building_record.BuildingTasks
if not tasks_guid then return {} end
local raw_tasks = query_building_tasks(tasks_guid)
if not raw_tasks then return {}
end
local tasks = restructure_tasks(raw_tasks)
return tasks
end
--- Restructures a flat building record from the database into a more usable format.
---@param record CargoBuildingRecord
---@return Building|nil
local function restructure_building_record(record)
local portrait_icon_filename = nil
if not p.PORTRAITS_MISSING_NAMES[record.Name] then
portrait_icon_filename = p.BUILDING_PORTRAIT_PREFIX .. record.Name
end
local building = {
name = record.page_name,
category = record.Category,
display_name = record.DisplayNameTerm_en or record.page_name,
display_name_plural = record.DisplayNamePluralTerm_en,
description = record.DescriptionTerm_en,
icon = record.IconAddress,
portrait_icon = portrait_icon_filename,
construction_resources = {},
construction_time = tonumber(record.ConstructionTime),
unlock_mode = record.UnlockMode,
unlock_values = {},
is_in_demo = record.LockedInDemo,
footprint_icon = record.FootprintIconAddress,
tech_tree_previous = record.TechTreePrevious,
adjacency_bonuses = {},
max_peeps = tonumber(record.MaxPeeps),
peep_exhaustion_removed = tonumber(record.PeepExhaustionRemoved),
peep_age_added = tonumber(record.PeepAgeAdded),
peep_happiness_added = tonumber(record.PeepHappinessAdded),
peep_happiness_cost = tonumber(record.PeepHappinessCost),
peep_energy_added = tonumber(record.PeepEnergyAdded),
peep_energy_cost = tonumber(record.PeepEnergyCost),
pollution_output_mode = record.PollutionOutputMode,
oxygen_source_range = tonumber(record.SourceOfOxygenRange),
fetch_mode = record.DefaultFetchMode,
delivery_mode = record.DefaultDeliveryMode,
fetch_time = tonumber(record.FetchTime),
delivery_time = tonumber(record.DeliveryTime),
storage_max = tonumber(record.TotalStorageMaximum),
power_range = tonumber(record.PowerRange),
tasks = {},
}
building.construction_resources = restructure_construction_resources(record)
building.unlock_values = restructure_unlock_values(record)
building.adjacency_bonuses = restructure_adjacency_bonuses(record)
building.tasks = restructure_tasks_in_building(record)
return building
end
--#endregion
--#region MARK: Private helpers
--- Maps the given tasks by the given building guiid.
---@param list_of_tasks_records CargoBuildingTasksRecord[]
---@return table<string, CargoBuildingTasksRecord>
local function map_tasks_by_guid(list_of_tasks_records)
local map = {}
for _, tasks_record in ipairs(list_of_tasks_records) do
local tasks_guid = tasks_record.guid
if tasks_guid and tasks_guid ~= "" then
map[tasks_guid] = tasks_record
end
end
return map
end
--- Filters the given tasks by the given resource id.
---@param tasks BuildingTask[]
---@param resource_id string the id of the resource to filter tasks by
---@return BuildingTask[]
local function filter_tasks_by_resource(tasks, resource_id)
local filtered_tasks = {}
for _, task in ipairs(tasks) do
local found = false
for _, input in ipairs(task.inputs) do
if input.resource == resource_id then
table.insert(filtered_tasks, task)
found = true
break
end
end
if not found then
for _, output in ipairs(task.outputs) do
if output.resource == resource_id then
table.insert(filtered_tasks, task)
break
end
end
end
end
return filtered_tasks
end
--#endregion
--#region MARK: Public interface
---@class BuildingDataModule
---@field MAX_CONSTRUCTION_PAIRS number the maximum number of construction pairs
---@field MAX_UNLOCK_VALUES number the maximum number of unlock values
---@field MAX_ADJACENCY_BONUSES number the maximum number of adjacency bonuses
---@field MAX_BUILDING_TASKS number the maximum number of building tasks
---@field MAX_BUILDING_TASK_OUTPUTS number the maximum number of building task outputs
---@field MAX_BUILDING_TASK_INPUTS number the maximum number of building task inputs
---@field FILTERS table filter field names for building queries
---@field get_name_by_id fun(id: string): string|nil looks up a building page name by codename
---@field get_building fun(building_name: string): Building|nil looks up a building by page name
---@field get_buildings_by_category fun(category: string): Building[] gets buildings in a category
---@field get_all_buildings fun(): Building[] gets all buildings
---@field get_building_names_with_tasks_including_resource fun(resource_id: string): table<string, BuildingTask[]> building page names to matching tasks
p.MAX_CONSTRUCTION_PAIRS = 6
p.MAX_UNLOCK_VALUES = 4
p.MAX_ADJACENCY_BONUSES = 4
p.MAX_BUILDING_TASKS = 9
p.MAX_BUILDING_TASK_OUTPUTS = 2
p.MAX_BUILDING_TASK_INPUTS = 4
p.BUILDING_PORTRAIT_PREFIX = "BuildingPortrait_"
p.PORTRAITS_MISSING_NAMES = {
["CompostingSite"] = true,
["Forest_WorldTwo"] = true,
["HomeSpaceshipLanded"] = true,
["Mill"] = true,
["WhaleTranslatorRuin"] = true,
["OxygenGenerator"] = true,
["Rock_WorldThree"] = true,
["Ruin_WorldTwo"] = true,
["SettlementSpaceshipLanded"] = true,
["SettlementSpaceshipLauncher"] = true,
["SteelBridge"] = true,
["StorageExtension"] = true,
}
p.SKIPPED_BUILDINGS_NAMES = {
["CompostTool"] = true,
["ConstructionConsumption"] = true,
["DemolitionControl"] = true,
["Drone_Repair"] = true,
["ForestPlantingTool"] = true,
["CreateMineableArea"] = true,
["MiningTile"] = true,
["MoveBuildingControl"] = true,
["PauseControl"] = true,
["PeepConsumption"] = true,
["PriorityControl"] = true,
["LandFillingSite"] = true,
["RampConstruction"] = true,
["RepairControl"] = true,
["ResourceCache"] = true,
["RoadConstruction"] = true,
["SettlementSpaceshipReload"] = true,
["ThornyStems"] = true,
}
p.FILTERS = {
CATEGORY = FILTER_CATEGORY,
}
---@class ConstructionPair
---@field name string the name of the construction resource
---@field amount number the amount of the construction resource
---@class AdjacencyBonus
---@field bonus_name string|nil the codename for the bonus group
---@field evaluator_type string|nil the type of evaluator that triggers the bonus
---@field evaluator_threshold number|nil the threshold value for the evaluator
---@field evaluator_value string|nil the codename for what condition evaluated for the trigger
---@field action string|nil the action to take when the bonus is triggered
---@field action_value number|nil the value to apply for the action
---@class BuildingTaskIO
---@field type string|nil the type of input/output
---@field resource string|nil the codename for the resource
---@field value string|nil the value of the input/output
---@class BuildingTask
---@field task_name string|nil the name of the task
---@field time number|nil the time it takes to complete the task
---@field outputs BuildingTaskIO[]|nil the outputs of the task
---@field inputs BuildingTaskIO[]|nil the inputs of the task
---@field pollution_slowdown_threshold number|nil the threshold at which pollution slows down the task
---@class Building
---@field name string|nil the in-game codename for the building
---@field category string|nil the category of the building
---@field display_name string|nil the display name of the building
---@field display_name_plural string|nil the plural display name of the building
---@field description string|nil the description of the building
---@field icon string|nil the flat icon asset name for this building
---@field portrait_icon string|nil the pre-rendered portrait icon asset name for this building
---@field construction_resources ConstructionPair[]|nil the construction resources of the building
---@field construction_time number|nil the time it takes to construct the building
---@field unlock_mode string|nil the requirement for unlocking the building
---@field unlock_values string[]|nil the values required for unlocking the building
---@field is_in_demo boolean whether the building is locked in the demo
---@field footprint_icon string|nil the icon filename for the building's footprint
---@field tech_tree_previous string|nil the previous building in the tech tree
---@field adjacency_bonuses AdjacencyBonus[]|nil the adjacency bonuses of the building
---@field max_peeps number|nil the maximum number of peeps that can be assigned to the building
---@field peep_exhaustion_removed number|nil the amount of exhaustion removed per peep per second
---@field peep_age_added number|nil the amount of age added per peep per second
---@field peep_happiness_added number|nil the amount of happiness added per peep per second
---@field peep_happiness_cost number|nil the cost of happiness per peep per second
---@field peep_energy_added number|nil the amount of energy added per peep per second
---@field peep_energy_cost number|nil the cost of energy per peep per second
---@field pollution_output_mode string|nil the level of pollution output from the building
---@field oxygen_source_range number|nil the range of the oxygen source for the building
---@field fetch_mode string|nil the mode for fetching resources from the building
---@field delivery_mode string|nil the mode for delivering resources to the building
---@field fetch_time number|nil the time it takes to fetch resources from the building
---@field delivery_time number|nil the time it takes to deliver resources to the building
---@field storage_max number|nil the maximum amount of storage for the building
---@field power_range number|nil the range of the power source for the building
---@field tasks BuildingTask[]|nil the tasks the building can work on
--- Fetches a building's page name by its id.
---@param id string the id of the building to fetch
---@return string|nil the page name of the building
function p.get_name_by_id(id)
local raw_record = query_building_name_only(id)
if not raw_record then return nil end
return raw_record.page_name or nil
end
--- Fetches a building record from the database.
---@param building_name string the in-game name of the building to fetch
---@return Building|nil
function p.get_building(building_name)
local raw_record = query_building(building_name)
if not raw_record then return nil end
local record = restructure_building_record(raw_record)
return record
end
--- Fetches building records for the given category.
---@param category string
---@return Building[]
function p.get_buildings_by_category(category)
local raw_records = query_buildings_by_filter(p.FILTERS.CATEGORY, category)
if not raw_records then return {} end
local new_records = {}
for _, raw_record in ipairs(raw_records) do
local record = restructure_building_record(raw_record)
table.insert(new_records, record)
end
return new_records
end
--- Fetches all building records from the database.
---@return Building[]
function p.get_all_buildings()
local raw_records = query_all_buildings()
if not raw_records then return {} end
local new_records = {}
for _, raw_record in ipairs(raw_records) do
local record = restructure_building_record(raw_record)
table.insert(new_records, record)
end
return new_records
end
--- Fetches all buildings whose work involves the given resource.
---@param resource_id string the id of the resource to fetch buildings for
---@return table<string, BuildingTask[]>
function p.get_building_names_with_tasks_including_resource(resource_id)
local raw_records = query_all_building_tasks()
local raw_map_of_tasks = map_tasks_by_guid(raw_records)
---@type table<string, BuildingTask[]>
local map_building_map_of_tasks = {}
for tasks_guid, tasks_record in pairs(raw_map_of_tasks) do
local tasks = restructure_tasks(tasks_record)
local filtered_tasks = filter_tasks_by_resource(tasks, resource_id)
if filtered_tasks and #filtered_tasks > 0 then
local building_record = query_building_name_only_by_tasks_guid(tasks_guid)
if building_record then
local building_name = building_record.page_name
if building_name and building_name ~= "" then
map_building_map_of_tasks[building_name] = filtered_tasks
end
end
end
end
return map_building_map_of_tasks
end
---@cast p BuildingDataModule
return p
--#endregion


