Skip to content

Game.Simulation.BatteryAISystem

Assembly: Assembly-CSharp (typical for Cities: Skylines 2 game code)
Namespace: Game.Simulation

Type: class (System)

Base: GameSystemBase

Summary:
BatteryAISystem is a Unity ECS system responsible for updating building batteries and related emergency generator behaviour each simulation tick (scheduled infrequently via GetUpdateInterval). It schedules a Burst-compiled IJobChunk (BatteryTickJob) that iterates over battery entities, updates stored energy, updates charge/discharge electricity flow edges, manages battery-empty notifications (via IconCommandSystem), and computes emergency generator production based on installed upgrades and resource availability. The system depends on a singleton ElectricityParameterData for notification prefab references and uses multiple ComponentLookup handles to read and write component data in the job.


Fields

  • private EntityQuery m_BatteryQuery
    Query that selects entities representing batteries that should be processed. It requires components: Game.Buildings.Battery, ElectricityBuildingConnection, PrefabRef and excludes Temp and Deleted. The system requires this query for update.

  • private EntityQuery m_SettingsQuery
    Query for retrieving the ElectricityParameterData singleton resource used for notifications and parameters.

  • private IconCommandSystem m_IconCommandSystem
    Reference to the IconCommandSystem instance used to produce or remove icon notifications (for example when a battery becomes empty).

  • private TypeHandle __TypeHandle
    Internal holder for component / buffer / entity type handles used when creating the job and performing lookups. It contains prepared handles (EntityTypeHandle, ComponentTypeHandle, BufferTypeHandle, ComponentLookup instances) and a helper to assign them from the SystemState.

Properties

  • (none public)
    This system exposes no public properties. All working data is set up internally and the execution is driven by the ECS update lifecycle.

Constructors

  • public BatteryAISystem()
    Default constructor. No explicit initialization beyond what GameSystemBase and the ECS runtime perform. The system's main initialization occurs in OnCreate where queries and the IconCommandSystem are retrieved/created.

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
    Returns the update interval for the system. This system returns 128 — meaning it runs every 128 simulation ticks (or equivalent scheduling granularity used by the game's system manager). Use this to understand how frequently battery logic is processed.

  • public override int GetUpdateOffset(SystemUpdatePhase phase)
    Returns the update offset for the system. This system returns 0.

  • [Preserve] protected override void OnCreate()
    Creates/initializes runtime data: obtains the IconCommandSystem from the World, constructs the m_BatteryQuery (batteries with electricity connections and prefab references, excluding Temp/Deleted), and the m_SettingsQuery to grab ElectricityParameterData. Calls RequireForUpdate(m_BatteryQuery) to prevent the system from running when there are no matching entities.

  • [Preserve] protected override void OnUpdate()
    Builds and schedules the BatteryTickJob (Burst-compiled) using handles acquired from the internal TypeHandle and the SystemState. The job is scheduled in parallel via JobChunkExtensions.ScheduleParallel and the resulting dependency is attached to base.Dependency. The IconCommandSystem command buffer writer is registered with the IconCommandSystem so icon add/remove commands performed in the job are applied safely.

Key actions performed by the scheduled job: - Iterate each entity matched by m_BatteryQuery. - Read prefab data (BatteryData and optionally EmergencyGeneratorData via installed upgrades). - Calculate current efficiency and last flow by comparing the charge and discharge ElectricityFlowEdge flows. - Clamp and update stored energy and capacity fields on the Battery component. - Add or remove a battery-empty notification icon using m_IconCommandBuffer when stored energy crosses zero. - If the entity has EmergencyGenerator component(s) (via installed upgrades), compute generator production based on activation thresholds and resource availability; update ServiceUsage for upgrades that consume resources. - Update discharge and charge ElectricityFlowEdge capacities based on battery stored energy, efficiency and componentData.m_PowerOutput.

  • private void __AssignQueries(ref SystemState state)
    Internal helper invoked by OnCreateForCompiler. In this compiled form it simply ensures entity queries are in place (no-op aside from an EntityQueryBuilder disposal in the decompiled code). In normal code generation it would be used to initialize query definitions.

  • protected override void OnCreateForCompiler()
    Compiler-time helper; calls __AssignQueries and assigns handles in the internal TypeHandle for the SystemState so the system's handle fields are initialized correctly before runtime use.

  • (Nested) [BurstCompile] private struct BatteryTickJob : IJobChunk
    Burst-compiled job that contains all per-chunk logic for battery updates. Important members:

  • Read-only handles: EntityTypeHandle, PrefabRef, ElectricityBuildingConnection, Efficiency buffer, InstalledUpgrade buffer.
  • Read/write handles: Game.Buildings.Battery, Game.Buildings.EmergencyGenerator.
  • ComponentLookup fields used for reading lookups at job time: PrefabRef, BatteryData, EmergencyGeneratorData, ResourceConsumer, ServiceUsage (writeable), ElectricityFlowEdge (writeable).
  • IconCommandBuffer m_IconCommandBuffer for adding/removing notifications.
  • ElectricityParameterData m_ElectricityParameterData for notification prefab references and other parameters.
  • Execute(...) iterates each entity in the chunk and implements the logic described in OnUpdate summary above.
  • HasResources(Entity upgrade) helper used by the job to check if an installed upgrade with a ResourceConsumer has available resources (m_ResourceAvailability > 0). If the upgrade has no ResourceConsumer component the method returns true.

Notes about the job's logic: - It expects both m_ChargeEdge and m_DischargeEdge in ElectricityBuildingConnection to be non-null; otherwise it logs an error and skips that entity. - It reads and potentially modifies ElectricityFlowEdge entries to set charge/discharge capacities. - Emergency generator production is constrained by componentData.capacityTicks (battery capacity in ticks) and checks activation bounds defined by EmergencyGeneratorData.m_ActivationThreshold. - ServiceUsage.m_Usage is set proportionally to generator production for upgrades that consume resources and are active.

  • (Nested) private struct TypeHandle
    Contains the component and buffer type handles plus ComponentLookup fields used by OnUpdate to populate the job struct. It provides the method __AssignHandles(ref SystemState state) to retrieve and store the appropriate handles (GetEntityTypeHandle, GetComponentTypeHandle, GetBufferTypeHandle, GetComponentLookup, etc.). This is the mechanism used by the compiled system to prepare thread-safe handles for job scheduling.

Usage Example

// Example: ensure ElectricityParameterData singleton is present before BatteryAISystem runs.
// This is a minimal example to show the system's dependency on that singleton.
// In real mod code you would populate m_BatteryEmptyNotificationPrefab with a real prefab entity.

[Preserve]
public class SetupElectricityParametersSystem : GameSystemBase
{
    protected override void OnCreate()
    {
        base.OnCreate();

        // Create a singleton entity that BatteryAISystem will read
        Entity settingsEntity = EntityManager.CreateEntity();
        EntityManager.AddComponentData(settingsEntity, new ElectricityParameterData
        {
            // m_BatteryEmptyNotificationPrefab = some prefab Entity (set appropriately by game code)
        });
    }
}

Notes and implementation tips: - BatteryAISystem is scheduled infrequently (GetUpdateInterval = 128). If you change simulation parameters related to battery behaviour, be aware of this cadence. - The core per-entity logic runs inside a Burst IJobChunk — avoid introducing managed objects or non-Burst-compatible code in similar jobs. - Icon notifications are emitted/removed via IconCommandBuffer produced from IconCommandSystem; ensure that any custom notifications you supply have valid prefab entities. - When adding or modifying installed upgrades or battery prefab data, update BatteryData and EmergencyGeneratorData accordingly; the job expects capacityTicks, m_Capacity and m_PowerOutput fields to be present and meaningful.