Skip to content

Game.WaterStatisticsSystem

Assembly: Game
Namespace: Game.Simulation

Type: class

Base: GameSystemBase

Summary:
WaterStatisticsSystem is an ECS system that collects and caches aggregate water-related statistics for the city each update interval. It uses Burst-compiled IJobChunk jobs to sum capacities of water pumping stations and sewage outlets and to sum water consumption (wanted and fulfilled, fresh and sewage) from WaterConsumer components using NativePerThreadSumInt accumulators. The system stores the aggregated values in private "last" fields which are exposed via read-only properties. It also implements simple serialization (ISerializable/IDefaultSerializable) to persist the last cached values across saves/loads.


Fields

  • private EntityQuery m_PumpGroup
    Collects entities with WaterPumpingStation components (excluding Temp and Deleted). Used as the query target for pump capacity counting jobs.

  • private EntityQuery m_OutletGroup
    Collects entities with SewageOutlet components (excluding Temp and Deleted). Used as the query target for sewage outlet capacity counting jobs.

  • private EntityQuery m_ConsumerGroup
    Collects entities with WaterConsumer components (excluding Temp and Deleted). Used as the query target for water-consumer counting jobs.

  • private NativePerThreadSumInt m_FreshCapacity
    Thread-local accumulator used by the pump capacity job to aggregate fresh water capacity in parallel. Persistent allocator, disposed on system destroy.

  • private NativePerThreadSumInt m_SewageCapacity
    Thread-local accumulator used by the outlet capacity job to aggregate sewage capacity in parallel. Persistent allocator, disposed on system destroy.

  • private NativePerThreadSumInt m_Consumption
    Thread-local accumulator used by the consumer job to aggregate wanted water consumption (both fresh and sewage consumers combined).

  • private NativePerThreadSumInt m_FulfilledFreshConsumption
    Thread-local accumulator for how much fresh water consumption was fulfilled (summed across consumers).

  • private NativePerThreadSumInt m_FulfilledSewageConsumption
    Thread-local accumulator for how much sewage-related water consumption was fulfilled.

  • private int m_LastFreshCapacity
    Cached integer holding the last aggregated fresh capacity (copied from m_FreshCapacity.Count during OnUpdate).

  • private int m_LastFreshConsumption
    Cached integer holding the last aggregated fresh consumption (copied from m_Consumption.Count during OnUpdate).

  • private int m_LastFulfilledFreshConsumption
    Cached integer holding the last aggregated fulfilled fresh consumption (copied from m_FulfilledFreshConsumption.Count during OnUpdate).

  • private int m_LastSewageCapacity
    Cached integer holding the last aggregated sewage capacity (copied from m_SewageCapacity.Count during OnUpdate).

  • private int m_LastSewageConsumption
    Cached integer holding the last aggregated sewage consumption. (Note: implementation sets this from m_Consumption.Count — see "Gotchas" below.)

  • private int m_LastFulfilledSewageConsumption
    Cached integer holding the last aggregated fulfilled sewage consumption (copied from m_FulfilledSewageConsumption.Count during OnUpdate).

  • private TypeHandle __TypeHandle
    Internal struct storing ComponentTypeHandles used when scheduling jobs. Assigned in OnCreateForCompiler.

  • Nested job types (Burst-compiled):

  • CountPumpCapacityJob : IJobChunk — sums WaterPumpingStation.m_Capacity into m_FreshCapacity.
  • CountOutletCapacityJob : IJobChunk — sums SewageOutlet.m_Capacity into m_SewageCapacity.
  • CountWaterConsumptionJob : IJobChunk — sums WaterConsumer fields (wanted, fulfilled fresh, fulfilled sewage) into respective accumulators.

Properties

  • public int freshCapacity { get; }
    Returns the last sampled fresh water capacity (m_LastFreshCapacity). This value is updated in OnUpdate at the system's interval.

  • public int freshConsumption { get; }
    Returns the last sampled fresh water consumption (m_LastFreshConsumption).

  • public int fulfilledFreshConsumption { get; }
    Returns the last sampled fulfilled fresh consumption (m_LastFulfilledFreshConsumption).

  • public int sewageCapacity { get; }
    Returns the last sampled sewage capacity (m_LastSewageCapacity).

  • public int sewageConsumption { get; }
    Returns the last sampled sewage consumption (m_LastSewageConsumption).

  • public int fulfilledSewageConsumption { get; }
    Returns the last sampled fulfilled sewage consumption (m_LastFulfilledSewageConsumption).

Constructors

  • public WaterStatisticsSystem()
    Default constructor. The actual set-up of queries, type handles and native accumulators happens in OnCreate. The constructor is preserved for serialization/compatibility.

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
    Returns 128. The system intends to run/refresh its cached statistics every 128 ticks (or the engine's scale for update intervals).

  • public override int GetUpdateOffset(SystemUpdatePhase phase)
    Returns 63. Used to offset update scheduling relative to other systems.

  • protected override void OnCreate()
    Initializes entity queries and allocates Persistent NativePerThreadSumInt accumulators:

  • Creates m_PumpGroup, m_OutletGroup, m_ConsumerGroup queries (read-only component types, excluding Temp and Deleted).
  • Allocates m_FreshCapacity, m_SewageCapacity, m_Consumption, m_FulfilledFreshConsumption, m_FulfilledSewageConsumption with Allocator.Persistent.

  • protected override void OnDestroy()
    Disposes the persistent NativePerThreadSumInt accumulators and calls base.OnDestroy.

  • public void Serialize<TWriter>(TWriter writer) where TWriter : IWriter
    Writes the cached m_Last* integer fields to the writer. Used for saving the system state.

  • public void Deserialize<TReader>(TReader reader) where TReader : IReader
    Reads and restores m_Last* integer fields from the reader. Used for loading saved state.

  • public void SetDefaults(Context context)
    Resets all cached m_Last* fields to zero. Called to initialize default state.

  • protected override void OnUpdate()
    Main update logic: copies current counters from the NativePerThreadSumInt accumulators into the m_Last* cached fields, resets the accumulators to zero, then schedules three parallel IJobChunk jobs (if respective entity queries are non-empty):

  • CountPumpCapacityJob populates m_FreshCapacity.
  • CountOutletCapacityJob populates m_SewageCapacity.
  • CountWaterConsumptionJob populates m_Consumption, m_FulfilledFreshConsumption, m_FulfilledSewageConsumption. The jobs are scheduled with component type handles obtained from __TypeHandle via InternalCompilerInterface. The system combines job dependencies into base.Dependency.

Gotchas: - The implementation sets both m_LastFreshConsumption and m_LastSewageConsumption from m_Consumption.Count (the same accumulator). This looks like a copy-paste mistake in the original code — m_LastSewageConsumption may be intended to come from a separate sewage-specific accumulator, but currently it mirrors the general m_Consumption value.

  • protected override void OnCreateForCompiler()
    Called by generated code paths to assign queries and component type handles. Calls __AssignQueries and __TypeHandle.__AssignHandles.

  • private void __AssignQueries(ref SystemState state)
    Compiler helper; currently contains a placeholder creation/dispose of an EntityQueryBuilder (no runtime query assignment beyond the ones created in OnCreate). Present to satisfy compiler-generated code patterns.

  • TypeHandle.__AssignHandles(ref SystemState state)
    Assigns ComponentTypeHandle instances for WaterPumpingStation, SewageOutlet and WaterConsumer via state.GetComponentTypeHandle(isReadOnly: true). Used when scheduling jobs.

Usage Example

// Example: read last cached water stats from another system or mod component.
// (Exact retrieval API depends on your DOTS / runtime; adjust to your version.)

var world = World.DefaultGameObjectInjectionWorld;
if (world != null)
{
    var stats = world.GetExistingSystemManaged<Game.Simulation.WaterStatisticsSystem>();
    if (stats != null)
    {
        int freshCap = stats.freshCapacity;
        int freshConsumption = stats.freshConsumption;
        int fulfilledFresh = stats.fulfilledFreshConsumption;
        Debug.Log($"Fresh capacity: {freshCap}, Wanted: {freshConsumption}, Fulfilled: {fulfilledFresh}");
    }
}

Additional notes: - The system is Burst- and job-friendly: the counting work is parallelized via IJobChunk and uses NativePerThreadSumInt to avoid contention. - The serialized state only includes the cached m_Last* integers; transient per-frame accumulators are not serialized. - If you rely on sewage-specific consumption values, be aware of the potential bug where m_LastSewageConsumption is populated from the same accumulator as fresh consumption. Consider verifying or patching if needed.