free the buffer setup and belt registration from BuildingSystem

This commit is contained in:
2026-08-05 06:55:13 +02:00
parent 114a43b205
commit fd85e8e10a
5 changed files with 224 additions and 177 deletions

View File

@@ -0,0 +1,173 @@
#include "BuildingBuffers.h"
#include <algorithm>
#include <cassert>
#include "BuildingType.h"
#include "ItemType.h"
#include "ModulesConfig.h"
#include "ShipsConfig.h"
void initBuffers(Building& b, const RecipeDef& recipe)
{
b.inputBuffer.counts.clear();
b.inputBuffer.caps.clear();
for (const RecipeIngredient& ing : recipe.inputs)
{
const ItemType type{ing.item};
b.inputBuffer.counts[type] = 0;
b.inputBuffer.caps[type] = 2 * ing.amount;
}
b.outputBuffer.items.clear();
if (b.type == BuildingType::ReprocessingPlant)
{
// 1× max-per-roll (REQ-MAT-OUTPUT-BUFFER-REPROCESSING).
int maxAmount = 0;
for (const RecipeOutput& out : recipe.outputs)
{
if (out.amount > maxAmount)
{
maxAmount = out.amount;
}
}
b.outputBuffer.capacity = maxAmount;
}
else
{
// 2× per-cycle output.
int totalAmount = 0;
for (const RecipeOutput& out : recipe.outputs)
{
totalAmount += out.amount;
}
b.outputBuffer.capacity = 2 * totalAmount;
}
}
void initAutoBuffers(const GameConfig& config, Building& b)
{
b.inputBuffer.counts.clear();
b.inputBuffer.caps.clear();
// Union the inputs of every recipe of this building type; the cap for each
// item is twice the largest per-cycle requirement across those recipes.
// Output capacity follows the same rules as initBuffers: the Reprocessing
// Plant holds one cycle's max output (REQ-MAT-OUTPUT-BUFFER-REPROCESSING),
// other auto buildings hold twice the largest per-cycle output.
int outputCapacity = 0;
for (const RecipeDef& recipe : config.recipes.recipes)
{
if (recipe.building != b.type)
{
continue;
}
for (const RecipeIngredient& ing : recipe.inputs)
{
const ItemType type{ing.item};
b.inputBuffer.counts[type] = 0;
b.inputBuffer.caps[type] =
std::max(b.inputBuffer.caps[type], 2 * ing.amount);
}
if (b.type == BuildingType::ReprocessingPlant)
{
int maxAmount = 0;
for (const RecipeOutput& out : recipe.outputs)
{
maxAmount = std::max(maxAmount, out.amount);
}
outputCapacity = std::max(outputCapacity, maxAmount);
}
else
{
int totalAmount = 0;
for (const RecipeOutput& out : recipe.outputs)
{
totalAmount += out.amount;
}
outputCapacity = std::max(outputCapacity, 2 * totalAmount);
}
}
b.outputBuffer.items.clear();
b.outputBuffer.capacity = outputCapacity;
}
void initShipyardBuffers(const GameConfig& config, Building& b)
{
b.inputBuffer.counts.clear();
b.inputBuffer.caps.clear();
b.outputBuffer.items.clear();
b.outputBuffer.capacity = 0;
const ShipDef* def = config.ships.findShipDef(b.recipeId);
if (!def)
{
return;
}
for (const RecipeIngredient& ing : def->schematic.materials)
{
const ItemType type{ing.item};
b.inputBuffer.counts[type] = 0;
b.inputBuffer.caps[type] = 2 * ing.amount;
}
if (b.shipLayout.has_value())
{
for (const PlacedModule& pm : b.shipLayout->placedModules)
{
const ModuleDef* modDef = config.modules.findModuleDef(pm.moduleId);
if (!modDef)
{
continue;
}
for (const RecipeIngredient& ing : modDef->materials)
{
const ItemType type{ing.item};
b.inputBuffer.counts.try_emplace(type, 0);
b.inputBuffer.caps[type] += 2 * ing.amount;
}
}
}
}
void initSalvageBayBuffer(const GameConfig& config, Building& b)
{
// Salvage Bay has no recipe-driven buffer; its output-buffer holding size for
// ship drop-off is config-defined (REQ-BLD-SALVAGE-BAY).
b.outputBuffer.items.clear();
const BuildingDef* def = config.buildings.findBuildingDef(BuildingType::SalvageBay);
b.outputBuffer.capacity =
(def && def->outputBufferCapacity) ? *def->outputBufferCapacity : 0;
}
void reregisterBeltTile(BeltSystem& belts, const GameConfig& config,
const Building& building,
const std::vector<ItemType>& splitterFilterA,
const std::vector<ItemType>& splitterFilterB)
{
switch (building.type)
{
case BuildingType::Belt:
belts.placeBelt(building.anchor, building.rotation);
break;
case BuildingType::Splitter:
assert(building.outputPorts.size() >= 2);
belts.placeSplitter(building.anchor,
building.outputPorts[0].direction,
building.outputPorts[1].direction);
belts.setSplitterFilters(building.anchor, splitterFilterA, splitterFilterB);
break;
case BuildingType::TunnelEntry:
belts.placeTunnelEntry(building.anchor, building.rotation,
config.world.tunnelMaxDistance_tiles);
break;
case BuildingType::TunnelExit:
belts.placeTunnelExit(building.anchor, building.rotation);
break;
default:
break;
}
}