Game.StorageCompanySystem
Assembly:
Namespace: Game.Simulation
Type: class
Base: GameSystemBase, IPostDeserialize
Summary:
StorageCompanySystem is an ECS system that manages storage companies, warehouse-like stations, and outside-connection stations in the simulation. It evaluates stored resources, incoming/outgoing transfer requests, trade costs and decides when to create StorageTransfer components (requests to transfer resources), or to clear obsolete requests. The system schedules three Burst-compiled jobs that run over matching entity groups:
- StorageJob — handles regular storage companies (company-owned warehouses).
- StationStorageJob — handles stations (city service / station-style buildings).
- OCStationStorageJob — handles outside-connection stations and special OC routing cases.
The system uses various game data (StorageCompanyData, StorageLimitData, TradeCost buffers, OwnedVehicle buffers, route/vehicle data, etc.) to compute when to export/import resources, choose vehicle/truck sizes for transfers and to adapt trade costs. It relies on EndFrameBarrier to enqueue commands safely from jobs.
Modding notes: - To influence storage decisions, change relevant prefab StorageCompanyData / StorageLimitData or edit TradeCost buffers on entities. - StorageTransfer components are added to entities to request an actual transfer — other systems/monobehaviours react to those. - Jobs run in parallel and use EntityCommandBuffer (m_EndFrameBarrier) — do not mutate world state directly from outside the command buffer while jobs are running.
Fields
-
private static readonly int kTransferCooldown
Constant cooldown (frames) between transfer requests for a resource. Default value: 400. Affects how often a company/station can issue new transfer requests. -
private static readonly int kCostFadeProbability
Probability denominator used to occasionally fade trade costs (tradeCost multipliers are multiplied by 0.99). Default: 256 (1/256 chance). -
private static readonly float kMaxTransportUnitCost
Maximum allowed unit transport cost (cost / amount) for non-station warehouses when deciding to export. Default: 0.03f. -
public static readonly int kStorageLowStockAmount
Low stock threshold used for storage entities (not stations). Default: 25000. -
public static readonly int kStationLowStockAmount
Low stock threshold used for stations. Default: 100000. -
public static readonly int kStorageExportStartAmount
Export threshold used for storage entities. Default: 100000. -
public static readonly int kStationExportStartAmount
Export threshold used for stations. Default: 200000. -
private static readonly int kStorageMinimalTransferAmount
Minimal transfer amount for storages. Default: 10000. -
private static readonly int kStationMinimalTransferAmount
Minimal transfer amount for stations. Default: 30000. -
private SimulationSystem m_SimulationSystem
Reference to the SimulationSystem (used for frameIndex and timing). -
private VehicleCapacitySystem m_VehicleCapacitySystem
Reference to the VehicleCapacitySystem — used to select delivery truck types and capacities. -
private EntityQuery m_CompanyGroup
EntityQuery selecting storage companies (company warehouses). Used to schedule StorageJob. -
private EntityQuery m_StationGroup
EntityQuery selecting regular stations (city-service / station-style storages). Used to schedule StationStorageJob. -
private EntityQuery m_OCStationGroup
EntityQuery selecting outside-connection stations. Used to schedule OCStationStorageJob. -
private EndFrameBarrier m_EndFrameBarrier
Barrier system used to create EntityCommandBuffer for safe structural changes from jobs. -
private TypeHandle __TypeHandle
Internal struct holding type handles/lookups required by the jobs (auto-generated).
Properties
- (none)
Constructors
public StorageCompanySystem()
Default constructor. The system initializes dependencies and queries in OnCreate (and OnCreateForCompiler for compiler-time assignments).
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
Returns the update interval (in simulation frames) used by the system. In this implementation the system returns 64. This interval is used by SimulationUtils.GetUpdateFrameWithInterval to schedule updates across frames. -
protected override void OnCreate()
Initializes system references and entity queries: - Grabs SimulationSystem, VehicleCapacitySystem and EndFrameBarrier.
- Creates three EntityQuery instances for companies, stations and outside-connection stations.
- Calls RequireAnyForUpdate so the system only runs when any of those queries has entities.
Modding note: If you add or remove components that determine membership of these queries (e.g. StorageCompany, PropertyRenter, CityServiceUpkeep, Game.Objects.OutsideConnection) the set of handled entities changes accordingly.
protected override void OnUpdate()
Main scheduling of Burst jobs:- Computes an update frame index (SimulationUtils.GetUpdateFrameWithInterval).
- Schedules StorageJob for m_CompanyGroup.
- Schedules StationStorageJob for m_StationGroup (depends on StorageJob).
- Schedules OCStationStorageJob for m_OCStationGroup (depends on StationStorageJob).
- Adds job handles to m_EndFrameBarrier (so command buffer is safe).
- Jobs get passed references/lookups (buffers, component lookups, RandomSeed, simulationFrame, delivery truck selection data, etc).
Summary of effects: - Jobs iterate matching chunks and call ProcessStorage (or OCProcessStorage) logic to decide on StorageTransfer creation, modify TradeCost entries and prune inconsistent StorageTransferRequest entries.
-
private static bool RemoveFromRequests(Resource resource, int amount, Entity owner, Entity target1, Entity target2, ref BufferLookup<StorageTransferRequest> storageTransferRequests)
Helper used to remove/update outgoing requests from an owner's StorageTransferRequest buffer. It searches requests targeting target1/target2 for the specified resource and removes/decrements them until the specified amount has been removed. Returns true if the requested amount was fully removed. -
private static bool ProcessStorage(int chunkIndex, Entity company, Entity building, Resource resource, StorageCompanyData storageCompanyData, DynamicBuffer<Resources> resourceBuffer, DynamicBuffer<StorageTransferRequest> requests, StorageLimitData limitData, SpawnableBuildingData spawnableData, BuildingData buildingData, DeliveryTruckSelectData truckSelectData, uint simulationFrame, DynamicBuffer<TradeCost> tradeCosts, EntityCommandBuffer.ParallelWriter commandBuffer, bool station, bool hasConnectedRoute, int incomingAmount, ref Random random, ref ComponentLookup<Game.Companies.StorageCompany> storageCompanies, ref BufferLookup<OwnedVehicle> ownedVehicles, ref BufferLookup<StorageTransferRequest> storageTransferRequests, ref ComponentLookup<Game.Vehicles.DeliveryTruck> trucks, ref ComponentLookup<Target> targets, ref BufferLookup<LayoutElement> layoutElements, ref ComponentLookup<PropertyRenter> propertyRenters, ref ComponentLookup<Game.Objects.OutsideConnection> outsideConnections)
Core algorithm that: - Determines whether the specified resource is relevant for this storage (based on storageCompanyData). - Tallies current resources and computes per-resource limit (limit / active resources). - Processes StorageTransferRequest buffer entries: - Validates and prunes invalid/obsolete requests. - For incoming/outgoing matching requests, computes effective amounts considering owned vehicles currently en route or assigned. - Uses TradeCost and simulation timing to throttle transfer requests (kTransferCooldown plus storageCompanyData.m_TransportInterval randomness). - Decides whether to add a StorageTransfer (positive m_Amount to export, negative to import) to the company/building via commandBuffer.AddComponent. - For export, picks truck/capacity (using truckSelectData) and enforces cost limit (kMaxTransportUnitCost) for non-station exports. - Adjusts trade costs occasionally (random fade). - Returns true if a transfer was initiated/queued.
Important: This method is static and performs no structural changes directly (it uses the passed EntityCommandBuffer).
-
public void PostDeserialize(Context context)
IPostDeserialize implementation. When loading from older versions (< Version.storageConditionReset) it clears TradeCost buffers on entities in m_CompanyGroup and m_StationGroup to reset trade state after a version upgrade. -
protected override void OnCreateForCompiler()
Internal helper used by generated code to assign type handles and queries for compiled builds. Calls __AssignQueries and assigns type handles. -
private void __AssignQueries(ref SystemState state)
Compiler helper stub to assign queries at compile time; in this implementation does nothing useful (creates and disposes an EntityQueryBuilder). Present for codegen compatibility. -
private struct TypeHandle { ... }
Internal container of EntityTypeHandle, ComponentTypeHandle, BufferTypeHandle and ComponentLookup/BufferLookup instances used to avoid fetching handles repeatedly in the hot path. The struct exposes __AssignHandles(ref SystemState state) to populate handles from the current SystemState. -
(Nested job structs)
StorageJob : IJobChunk
— iterates company-type entities and invokes ProcessStorage for each resource configured on the prefab.StationStorageJob : IJobChunk
— iterates station entities; supports installed upgrades (to combine stats), checks connected routes (CheckConnectedRoute) and then calls ProcessStorage with station=true.OCStationStorageJob : IJobChunk
— iterates outside-connection stations and uses specialized OCProcessStorage logic to consider whether the OC is before/after a station on a route and queue transfers accordingly.
Each job includes job-specific lookups and helper methods (CheckConnectedRoute, OCProcessStorage, CheckIfOCIsBeforeOrAfterStation).
Usage Example
// Typical usage in a mod (read-only): get the system and query its update interval.
var world = World.DefaultGameObjectInjectionWorld;
var storageSystem = world.GetExistingSystemManaged<Game.Simulation.StorageCompanySystem>();
if (storageSystem != null)
{
int interval = storageSystem.GetUpdateInterval(Game.SystemUpdatePhase.GameSimulation);
UnityEngine.Debug.Log($"StorageCompanySystem update interval: {interval}");
}
// To influence behavior at runtime you can modify storage component data on prefabs/entities:
// - adjust StorageCompanyData or StorageLimitData for a prefab
// - add/remove/modify TradeCost entries for a storage entity
// - add StorageTransferRequest entries to request transfers programmatically.
// Note: changes that must take effect inside the jobs should be made before the system's OnUpdate executes,
// and structural changes from jobs are performed using the EndFrameBarrier's command buffer.
If you want help locating the relevant component types (StorageCompanyData, StorageLimitData, TradeCost, StorageTransferRequest, StorageTransfer) or an example showing how to add/remove a StorageTransferRequest on an entity, tell me which exact operation you want and I can provide a code snippet.