make deconstruction its own system
This commit is contained in:
@@ -181,7 +181,7 @@ int BuildingSystem::deconstruct(FactoryState& state, BuildingId id, Tick current
|
||||
state.deconstructionQueue.push_back(std::move(entry));
|
||||
if (wasEmpty)
|
||||
{
|
||||
startFrontDeconstruction(state, currentTick);
|
||||
startFrontDeconstruction(state, m_config, currentTick);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -189,17 +189,6 @@ int BuildingSystem::deconstruct(FactoryState& state, BuildingId id, Tick current
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BuildingSystem::startFrontDeconstruction(FactoryState& state, Tick currentTick)
|
||||
{
|
||||
if (state.deconstructionQueue.empty()) { return; }
|
||||
DeconstructionEntry& front = state.deconstructionQueue.front();
|
||||
if (front.completesAt == 0)
|
||||
{
|
||||
front.completesAt =
|
||||
currentTick + secondsToTicks(m_config.world.deconstructionTimeSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Set recipe
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -334,53 +323,6 @@ void BuildingSystem::setSiteSplitterFilters(FactoryState& state, BuildingId id,
|
||||
// Tick hooks
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void BuildingSystem::tickDeconstruction(FactoryState& state, Tick currentTick)
|
||||
{
|
||||
TRACE();
|
||||
if (state.deconstructionQueue.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DeconstructionEntry& front = state.deconstructionQueue.front();
|
||||
|
||||
// Guard: if the front entry's timer was never started, start it now.
|
||||
if (front.completesAt == 0)
|
||||
{
|
||||
startFrontDeconstruction(state, currentTick);
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentTick < front.completesAt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the building from the world and credit its refund (REQ-BLD-DECONSTRUCT).
|
||||
// Belt/tunnel/splitter tiles were already unregistered when the building was
|
||||
// queued (see deconstruct), so only tile occupancy and the record remain.
|
||||
for (std::vector<Building>::iterator it = state.buildings.begin();
|
||||
it != state.buildings.end();
|
||||
++it)
|
||||
{
|
||||
if (it->id != front.id) { continue; }
|
||||
|
||||
const BuildingDef* def = m_config.buildings.findBuildingDef(it->type);
|
||||
state.grid.release(it->bodyCells);
|
||||
state.buildings.erase(it);
|
||||
if (def)
|
||||
{
|
||||
m_addBuildingBlocks(def->cost * m_config.world.refundPercentage / 100);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
state.deconstructionQueue.pop_front();
|
||||
|
||||
// Start the next queued deconstruction, if any.
|
||||
startFrontDeconstruction(state, currentTick);
|
||||
}
|
||||
|
||||
void BuildingSystem::cancelDeconstruction(FactoryState& state, BuildingId id)
|
||||
{
|
||||
for (std::deque<DeconstructionEntry>::iterator it = state.deconstructionQueue.begin();
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "Building.h"
|
||||
#include "FactoryState.h"
|
||||
#include "BuildingBuffers.h"
|
||||
#include "DeconstructionSystem.h"
|
||||
#include "PlacementRules.h"
|
||||
#include "ProductionRules.h"
|
||||
#include "BuildingType.h"
|
||||
@@ -107,7 +108,6 @@ public:
|
||||
// Advances the deconstruction queue (REQ-BLD-DECON-QUEUE): one building at a
|
||||
// time, in parallel with tickConstruction. Removes the front building and
|
||||
// credits its refund when its timer elapses.
|
||||
void tickDeconstruction(FactoryState& state, Tick currentTick);
|
||||
void tickBeltPull(FactoryState& state);
|
||||
void tickProduction(FactoryState& state, Tick currentTick);
|
||||
void tickShipyardProduction(FactoryState& state, Tick currentTick);
|
||||
@@ -183,7 +183,6 @@ public:
|
||||
private:
|
||||
// Starts the front deconstruction-queue entry's timer if not yet started
|
||||
// (mirrors how tickConstruction starts a queued construction site).
|
||||
void startFrontDeconstruction(FactoryState& state, Tick currentTick);
|
||||
|
||||
// Registers a belt/splitter/tunnel building's tile with the belt subsystem
|
||||
// (on construction completion, or when un-queuing a deconstruction). No-op for
|
||||
|
||||
@@ -14,6 +14,7 @@ SET(HDRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingConfig.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingGrid.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ConstructionSystem.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/DeconstructionSystem.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingBuffers.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/FactoryState.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/FactoryQueries.h
|
||||
@@ -45,6 +46,7 @@ SET(SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingConfig.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingGrid.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ConstructionSystem.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/DeconstructionSystem.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingBuffers.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/FactoryQueries.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ProductionRules.cpp
|
||||
|
||||
67
src/lib/sim/DeconstructionSystem.cpp
Normal file
67
src/lib/sim/DeconstructionSystem.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "DeconstructionSystem.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Building.h"
|
||||
#include "tracing.h"
|
||||
|
||||
void startFrontDeconstruction(FactoryState& state, const GameConfig& config,
|
||||
Tick currentTick)
|
||||
{
|
||||
if (state.deconstructionQueue.empty()) { return; }
|
||||
DeconstructionEntry& front = state.deconstructionQueue.front();
|
||||
if (front.completesAt == 0)
|
||||
{
|
||||
front.completesAt =
|
||||
currentTick + secondsToTicks(config.world.deconstructionTimeSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DeconstructionSystem::tick(FactoryState& state, Tick currentTick)
|
||||
{
|
||||
TRACE();
|
||||
if (state.deconstructionQueue.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DeconstructionEntry& front = state.deconstructionQueue.front();
|
||||
|
||||
// Guard: if the front entry's timer was never started, start it now.
|
||||
if (front.completesAt == 0)
|
||||
{
|
||||
startFrontDeconstruction(state, m_config, currentTick);
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentTick < front.completesAt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the building from the world and credit its refund (REQ-BLD-DECONSTRUCT).
|
||||
// Belt/tunnel/splitter tiles were already unregistered when the building was
|
||||
// queued (see deconstruct), so only tile occupancy and the record remain.
|
||||
for (std::vector<Building>::iterator it = state.buildings.begin();
|
||||
it != state.buildings.end();
|
||||
++it)
|
||||
{
|
||||
if (it->id != front.id) { continue; }
|
||||
|
||||
const BuildingDef* def = m_config.buildings.findBuildingDef(it->type);
|
||||
state.grid.release(it->bodyCells);
|
||||
state.buildings.erase(it);
|
||||
if (def)
|
||||
{
|
||||
m_addBuildingBlocks(def->cost * m_config.world.refundPercentage / 100);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
state.deconstructionQueue.pop_front();
|
||||
|
||||
// Start the next queued deconstruction, if any.
|
||||
startFrontDeconstruction(state, m_config, currentTick);
|
||||
}
|
||||
|
||||
36
src/lib/sim/DeconstructionSystem.h
Normal file
36
src/lib/sim/DeconstructionSystem.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "FactoryState.h"
|
||||
#include "GameConfig.h"
|
||||
#include "Tick.h"
|
||||
|
||||
// The queue timer for pending demolitions (REQ-BLD-DECON-QUEUE): one building at a
|
||||
// time, in parallel with construction. When the front entry's timer elapses the
|
||||
// building is removed from the world, its tiles are released, and its partial refund
|
||||
// is credited.
|
||||
//
|
||||
// It needs no BeltSystem: a belt, splitter or tunnel end is unregistered the moment
|
||||
// it is queued (see BuildingSystem::deconstruct), not when the timer completes.
|
||||
//
|
||||
// Holds the config and the refund sink; the world arrives per tick.
|
||||
class DeconstructionSystem
|
||||
{
|
||||
public:
|
||||
DeconstructionSystem(const GameConfig& config,
|
||||
std::function<void(int)> addBuildingBlocks)
|
||||
: m_config(config), m_addBuildingBlocks(std::move(addBuildingBlocks)) {}
|
||||
|
||||
void tick(FactoryState& state, Tick currentTick);
|
||||
|
||||
private:
|
||||
const GameConfig& m_config;
|
||||
std::function<void(int)> m_addBuildingBlocks;
|
||||
};
|
||||
|
||||
// Starts the timer on the front entry of the deconstruction queue, if it has one and
|
||||
// it has not started yet. Shared: BuildingSystem::deconstruct starts the timer when it
|
||||
// queues the first entry, and DeconstructionSystem restarts it after each completion.
|
||||
void startFrontDeconstruction(FactoryState& state, const GameConfig& config,
|
||||
Tick currentTick);
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "FactoryQueries.h"
|
||||
#include "ConstructionSystem.h"
|
||||
#include "DeconstructionSystem.h"
|
||||
#include "PlacementRules.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -125,6 +126,8 @@ void Simulation::initializeSubsystems()
|
||||
[this](const std::string& itemId) -> bool { return isItemUnlocked(itemId); },
|
||||
m_rng);
|
||||
m_constructionSystem = std::make_unique<ConstructionSystem>(m_config);
|
||||
m_deconstructionSystem = std::make_unique<DeconstructionSystem>(
|
||||
m_config, [this](int amount) { m_buildingBlocksStock += amount; });
|
||||
m_shipSystem = std::make_unique<ShipSystem>(m_config, m_admin);
|
||||
m_aiSystem = std::make_unique<AiSystem>(m_config);
|
||||
m_movementIntentSystem = std::make_unique<MovementIntentSystem>();
|
||||
@@ -246,7 +249,7 @@ void Simulation::tick()
|
||||
|
||||
// Construction + production pipeline
|
||||
m_constructionSystem->tick(m_factoryState, m_beltSystem, m_currentTick);
|
||||
m_buildingSystem->tickDeconstruction(m_factoryState, m_currentTick); // parallel to construction
|
||||
m_deconstructionSystem->tick(m_factoryState, m_currentTick); // parallel to construction
|
||||
m_buildingSystem->tickBeltPull(m_factoryState); // step 3
|
||||
m_buildingSystem->tickProduction(m_factoryState, m_currentTick); // step 4
|
||||
m_buildingSystem->tickShipyardProduction(m_factoryState, m_currentTick); // step 4b
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
class AiSystem;
|
||||
class BuildingSystem;
|
||||
class ConstructionSystem;
|
||||
class DeconstructionSystem;
|
||||
struct Command;
|
||||
class Hasher;
|
||||
class CombatSystem;
|
||||
@@ -220,6 +221,7 @@ private:
|
||||
BeltSystem m_beltSystem;
|
||||
std::unique_ptr<BuildingSystem> m_buildingSystem;
|
||||
std::unique_ptr<ConstructionSystem> m_constructionSystem;
|
||||
std::unique_ptr<DeconstructionSystem> m_deconstructionSystem;
|
||||
std::unique_ptr<ShipSystem> m_shipSystem;
|
||||
std::unique_ptr<AiSystem> m_aiSystem;
|
||||
std::unique_ptr<MovementIntentSystem> m_movementIntentSystem;
|
||||
|
||||
Reference in New Issue
Block a user