Module:Building data: Difference between revisions
From Beyond These Stars Official Wiki
Added skip for building controls when retrieving all buildings only. also added interface constant for building Names without portraits to avoid page lookup |
m luadoc update only |
||
| (8 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
--[[ | --[[ | ||
Test in Scribunto console with: | Test in Scribunto console with: | ||
=mw.dumpObject(p.get_all_buildings()) | |||
=mw.dumpObject(p.get_building("Ore Smelter")) | =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 = {} | ||
| Line 7: | Line 11: | ||
--#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 287: | 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 417: | Line 423: | ||
---@field BuildingTasks_9_Inputs_1_Resource string|nil | ---@field BuildingTasks_9_Inputs_1_Resource string|nil | ||
---@field BuildingTasks_9_Inputs_1_Value 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 423: | 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 431: | Line 447: | ||
"guid", | "guid", | ||
"Name", | "Name", | ||
FILTER_CATEGORY, | |||
"DisplayNameTerm_en", | "DisplayNameTerm_en", | ||
"DisplayNamePluralTerm_en", | "DisplayNamePluralTerm_en", | ||
| Line 707: | 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 844: | 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 859: | 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 875: | 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 904: | 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 | if not result or #result == 0 then return nil end | ||
result = skip_unwanted_buildings(result) | |||
return result[1] | return result[1] | ||
end | end | ||
| Line 914: | Line 968: | ||
--#region | --#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. | --- Restructures the construction resources of a building record from the database into a more usable format. | ||
| Line 975: | 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 .. "_%d_" | 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 or put_resource or put_value then | if put_type or put_resource or put_value then | ||
table.insert(task_io, { | table.insert(task_io, { | ||
| Line 998: | 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 then | if task_name then | ||
table.insert(tasks, { | table.insert(tasks, { | ||
| Line 1,024: | 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 1,071: | 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 1,079: | 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,088: | 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,099: | Line 1,247: | ||
p.BUILDING_PORTRAIT_PREFIX = "BuildingPortrait_" | p.BUILDING_PORTRAIT_PREFIX = "BuildingPortrait_" | ||
p.PORTRAITS_MISSING_NAMES = { | p.PORTRAITS_MISSING_NAMES = { | ||
["CompostingSite"] = true, | ["CompostingSite"] = true, | ||
[" | ["Forest_WorldTwo"] = true, | ||
["HomeSpaceshipLanded"] = true, | ["HomeSpaceshipLanded"] = true, | ||
["Mill"] = true, | ["Mill"] = true, | ||
| Line 1,114: | Line 1,261: | ||
} | } | ||
p.SKIPPED_BUILDINGS_NAMES = { | p.SKIPPED_BUILDINGS_NAMES = { | ||
["CompostTool"] = true, | |||
["ConstructionConsumption"] = true, | ["ConstructionConsumption"] = true, | ||
["DemolitionControl"] = true, | ["DemolitionControl"] = true, | ||
| Line 1,127: | Line 1,275: | ||
["RampConstruction"] = true, | ["RampConstruction"] = true, | ||
["RepairControl"] = true, | ["RepairControl"] = true, | ||
[" | ["ResourceCache"] = true, | ||
["RoadConstruction"] = true, | ["RoadConstruction"] = true, | ||
["SettlementSpaceshipReload"] = true, | ["SettlementSpaceshipReload"] = true, | ||
["ThornyStems"] = true, | ["ThornyStems"] = true, | ||
} | |||
p.FILTERS = { | |||
CATEGORY = FILTER_CATEGORY, | |||
} | } | ||
| Line 1,189: | 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,200: | 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,216: | Line 1,381: | ||
local new_records = {} | local new_records = {} | ||
for _, raw_record in ipairs(raw_records) do | 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 | ||
end | end | ||
return | 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


