cargo component refactoring

This commit is contained in:
2026-06-21 18:35:02 +02:00
parent 665060bcd2
commit a472ec196c
17 changed files with 188 additions and 114 deletions

View File

@@ -6,13 +6,14 @@
#include "Building.h"
#include "BuildingSystem.h"
#include "CargoComponent.h"
#include "DeliverScrapBehavior.h"
#include "EntityAdmin.h"
#include <map>
#include "ModuleOwnerComponent.h"
#include "PositionComponent.h"
#include "SalvageCargoComponent.h"
#include "SalvagerComponent.h"
#include "ScrapDataComponent.h"
#include "ScrapSystem.h"
#include "tracing.h"
@@ -32,44 +33,53 @@ void SalvagerSystem::tick(Tick currentTick, ScrapSystem& scraps, BuildingSystem&
const std::vector<ScrapInfo> allScrap = scraps.allScrapInfo();
// Tick down per-module collection cooldowns.
m_admin.forEach<SalvageCargoComponent>(
[](entt::entity /*e*/, SalvageCargoComponent& c)
m_admin.forEach<SalvagerComponent>(
[](entt::entity /*e*/, SalvagerComponent& s)
{
if (c.cooldownTicksRemaining > 0) { --c.cooldownTicksRemaining; }
if (s.cooldownTicksRemaining > 0) { --s.cooldownTicksRemaining; }
});
// Scrap units already claimed by not-yet-applied collection cycles, so two
// modules don't both target the last unit of the same pile (the claim would be
// dropped at apply time). A pile is available while its amount exceeds its claims.
std::map<entt::entity, int> claimedUnits;
// Collection cycles already in flight toward each ship's shared cargo pool, so
// concurrent modules on the same ship never start more cycles than the remaining
// capacity can hold (REQ-SHP-SALVAGE).
std::map<entt::entity, int> pendingByShip;
for (const PendingCollection& pc : m_pendingCollections)
{
++claimedUnits[pc.scrap];
++pendingByShip[pc.ship];
}
// Cycle start: each ready, in-range module with free cargo begins a collection
// cycle — emit the beam now, collect one scrap mid-beam, start the cooldown now.
m_admin.forEach<SalvageCargoComponent, ModuleOwnerComponent>(
[&](entt::entity moduleEntity, SalvageCargoComponent& c, const ModuleOwnerComponent& o)
// Cycle start: each ready, in-range module whose ship's pool has free space begins
// a collection cycle — emit the beam now, collect one scrap mid-beam, start the
// cooldown now.
m_admin.forEach<SalvagerComponent, ModuleOwnerComponent>(
[&](entt::entity /*moduleEntity*/, SalvagerComponent& s, const ModuleOwnerComponent& o)
{
if (c.current >= c.capacity || c.cooldownTicksRemaining > 0) { return; }
if (c.collectionIntervalTicks <= 0) { return; }
if (!m_admin.hasAll<PositionComponent>(o.owner)) { return; }
if (s.cooldownTicksRemaining > 0 || s.collectionIntervalTicks <= 0) { return; }
if (!m_admin.hasAll<PositionComponent, CargoComponent>(o.owner)) { return; }
const CargoComponent& cargo = m_admin.get<CargoComponent>(o.owner);
if (cargo.current + pendingByShip[o.owner] >= cargo.maxCapacity) { return; }
const QVector2D ownerPos = m_admin.get<PositionComponent>(o.owner).value;
for (const ScrapInfo& si : allScrap)
{
if ((si.position - ownerPos).length() > c.collectionRange_tiles) { continue; }
if ((si.position - ownerPos).length() > s.collectionRange_tiles) { continue; }
if (claimedUnits[si.entity] >= m_admin.get<ScrapDataComponent>(si.entity).amount)
{
continue; // every remaining unit of this pile is already spoken for
}
outBeamFiredEvents.push_back(
BeamFiredEvent{BeamKind::Salvage, o.owner, si.entity, currentTick});
m_pendingCollections.push_back({moduleEntity, si.entity,
m_pendingCollections.push_back({o.owner, si.entity,
currentTick + kBeamImpactDelayTicks});
++claimedUnits[si.entity];
c.cooldownTicksRemaining = c.collectionIntervalTicks;
++pendingByShip[o.owner];
s.cooldownTicksRemaining = s.collectionIntervalTicks;
break;
}
});
@@ -86,18 +96,14 @@ void SalvagerSystem::tick(Tick currentTick, ScrapSystem& scraps, BuildingSystem&
bay->anchor.y() + bay->footprint.height() / 2.0f);
if ((pos.value - bayCenter).length() > 1.0f) { return; }
// Decrement the first non-empty salvage child belonging to this ship.
bool delivered = false;
m_admin.forEach<SalvageCargoComponent, ModuleOwnerComponent>(
[&](entt::entity /*ce*/, SalvageCargoComponent& c, const ModuleOwnerComponent& o)
{
if (delivered || o.owner != ship || c.current <= 0) { return; }
if (buildings.deliverScrapToSalvageBay(deliver.deliveryBay))
{
--c.current;
delivered = true;
}
});
// Hand over one unit from the ship's shared cargo pool.
if (!m_admin.hasAll<CargoComponent>(ship)) { return; }
CargoComponent& cargo = m_admin.get<CargoComponent>(ship);
if (cargo.current <= 0) { return; }
if (buildings.deliverScrapToSalvageBay(deliver.deliveryBay))
{
--cargo.current;
}
});
}
@@ -108,12 +114,12 @@ void SalvagerSystem::applyPendingCollections(Tick currentTick, ScrapSystem& scra
{
if (it->appliesAt <= currentTick)
{
if (m_admin.isValid(it->module) && m_admin.hasAll<SalvageCargoComponent>(it->module))
if (m_admin.isValid(it->ship) && m_admin.hasAll<CargoComponent>(it->ship))
{
SalvageCargoComponent& c = m_admin.get<SalvageCargoComponent>(it->module);
if (c.current < c.capacity && scraps.collectOne(it->scrap))
CargoComponent& cargo = m_admin.get<CargoComponent>(it->ship);
if (cargo.current < cargo.maxCapacity && scraps.collectOne(it->scrap))
{
++c.current;
++cargo.current;
}
}
it = m_pendingCollections.erase(it);