Skip to content

Game.Simulation.MailAccumulationSystem

Assembly: Assembly‑CSharp
Namespace: Game.Simulation

Type: class

Base: GameSystemBase

Summary:
MailAccumulationSystem is a simulation system responsible for accumulating mail for buildings (MailProducer components), computing mail-related efficiency penalties, and creating PostVanRequest service requests when accumulated mail exceeds configured thresholds. The system runs on a fixed update interval (64 simulation frames), iterates building entities in chunks using a parallel IJobChunk (MailAccumulationJob), and issues structural changes through an EndFrameBarrier command buffer. It reads configuration data (PostConfigurationData, MailAccumulationData, BuildingEfficiencyParameterData) and various prefab/instance data to determine accumulation rates and whether collection is required.


Fields

  • private const uint UPDATE_INTERVAL = 64u
    Used to determine the system's update cadence. The system runs every 64 simulation frames.

  • private SimulationSystem m_SimulationSystem
    Reference to the SimulationSystem used to obtain the global frameIndex for computing the per-interval update frame index.

  • private EndFrameBarrier m_EndFrameBarrier
    EndFrameBarrier system used to create an EntityCommandBuffer.ParallelWriter to enqueue entity/create/component operations from the scheduled job.

  • private EntityQuery m_MailProducerQuery
    Query selecting entities relevant to this system (at least MailProducer component). Used for scheduling the MailAccumulationJob.

  • private EntityArchetype m_PostVanRequestArchetype
    Archetype used when creating new PostVanRequest (service request) entities (contains ServiceRequest, PostVanRequest, RequestGroup components).

  • private TypeHandle __TypeHandle
    Generated TypeHandle struct instance that stores Component/Buffer/SharedComponent/Lookup handles used by jobs and assigned during OnCreateForCompiler.

  • private EntityQuery __query_890676534_0
    Generated EntityQuery for PostConfigurationData (singleton) used in OnUpdate.

  • private EntityQuery __query_890676534_1
    Generated EntityQuery for BuildingEfficiencyParameterData (singleton) used in OnUpdate.

(Also contains the nested MailAccumulationJob and TypeHandle types used internally by the system.)

Properties

  • (none exposed by this system)
    This system does not declare public properties; it exposes behavior via System methods and scheduled jobs.

Constructors

  • public MailAccumulationSystem()
    Default constructor. Initialization of system state happens in OnCreate / OnCreateForCompiler rather than in the constructor.

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
    Returns the update interval used by the system. Implementation returns 64 (frames) so the system runs every 64 simulation frames.

  • protected override void OnCreate()
    Initializes the system: obtains references to SimulationSystem and EndFrameBarrier, defines the MailProducer entity query (excludes Deleted / Destroyed / Temp), creates the archetype for PostVanRequest entities, registers required singletons (PostConfigurationData, BuildingEfficiencyParameterData) and mail producer query requirement (RequireForUpdate). Also contains an assert check used by the game code.

  • protected override void OnUpdate()
    Main scheduling logic. Retrieves the PostConfigurationData singleton and checks whether the post service prefab is locked. If not locked:

  • Computes an updateFrameIndex from SimulationSystem.frameIndex / 64 & 0xF.
  • Constructs and schedules the MailAccumulationJob in parallel over m_MailProducerQuery, providing component handles, lookups, buffers, random seed, archetype and configuration singletons, and an EntityCommandBuffer.ParallelWriter from m_EndFrameBarrier.
  • Adds the job handle to m_EndFrameBarrier and sets base.Dependency accordingly.

  • private void __AssignQueries(ref SystemState state)
    Generated helper that builds the internal queries used to fetch PostConfigurationData and BuildingEfficiencyParameterData singletons (using IncludeSystems option).

  • protected override void OnCreateForCompiler()
    Generated method used during compilation to assign the queries and type handles (calls __AssignQueries and __TypeHandle.__AssignHandles).

  • Nested type: MailAccumulationJob : IJobChunk (BurstCompile)
    This is the chunk job that performs the per-building accumulation logic in parallel. Key behavior:

  • Filters chunks by UpdateFrame shared component index matching computed m_UpdateFrameIndex so buildings are processed in staggered frames.
  • For each entity in the chunk:
    • Obtains base accumulation rate for the building's prefab (via GetBaseAccumulationRate): reads either SpawnableBuildingData → ZonePrefab or ServiceObjectData → Service to look up MailAccumulationData. The MailAccumulationData provides m_AccumulationRate (float2) and m_RequireCollect flag.
    • If accumulation rate is non-zero, multiplies by number of residents + workers associated with the building (either from a Renter buffer or Household/Employee buffers) to produce per-building accumulation.
    • Uses a Random seed and MathUtils.RoundToIntRandom to produce integer mail increments scaled by an aggregate multiplier (num = 0.28444445f).
    • Updates the MailProducer component's m_SendingMail and receivingMail values, clamped by m_PostConfigurationData.m_MaxMailAccumulation.
    • Calls RequestPostVanIfNeeded to create a PostVanRequest entity (using the m_PostVanRequestArchetype and command buffer) when accumulation meets or exceeds the configured m_MailAccumulationTolerance, taking into account whether the building requires collection (deliver-only vs collect+deliver).
    • If the receiving-mail crossed the accumulation tolerance threshold (changed from below to above or vice-versa), marks related subobjects' batches as updated by adding BatchesUpdated to subobject entities (QuantityUpdated).
    • Updates Efficiency buffer entries with an EfficiencyFactor.Mail factor computed by GetMailEfficiencyFactor if Efficiency buffers exist.
  • Helper methods inside the job:
    • QuantityUpdated(jobIndex, buildingEntity): if subobjects buffer exists, marks each subobject entity with BatchesUpdated (via command buffer) if the subobject has a Quantity component.
    • GetCitizenCounts(DynamicBuffer, out residentCount, out workerCount): aggregates counts from Renter buffers.
    • GetCitizenCounts(Entity, out residentCount, out workerCount): reads HouseholdCitizen and Employee buffers from component lookups to count residents/workers.
    • GetBaseAccumulationRate(Entity prefab, out bool requireCollect): inspects SpawnableBuildingData or ServiceObjectData to find a MailAccumulationData entry and returns its accumulation rate and whether collection is required.
    • RequestPostVanIfNeeded(jobIndex, entity, ref MailProducer producer, bool requireCollect): checks accumulated mail vs m_PostConfigurationData.m_MailAccumulationTolerance and, if needed, creates a PostVanRequest entity with appropriate flags (Deliver, BuildingTarget, optionally Collect) and a RequestGroup.
    • GetMailEfficiencyFactor(MailProducer producer): computes an efficiency multiplier (<= 1) based on the larger of sending/receiving mail, applying a penalty curve configured by BuildingEfficiencyParameterData.m_MailEfficiencyPenalty and m_NegligibleMail.
  • The job uses many read-only lookups and handles (PrefabRef, Renter buffer, SpawnableBuildingData, MailAccumulationData, ServiceObjectData, household/employee buffers, subobject buffer lookup) and writes MailProducer and Efficiency buffers as needed.

  • (Generated) explicit IJobChunk.Execute implementation that forwards to the typed Execute method.

Usage Example

// The system is automatically created/updated by the game's ECS world.
// Example: what OnUpdate schedules internally (simplified excerpt)
//
// In OnUpdate(), MailAccumulationSystem fetches singletons and schedules
// the MailAccumulationJob in parallel. The job updates MailProducer
// components and enqueues PostVanRequest entities via the EndFrameBarrier
// command buffer.

[Preserve]
protected override void OnUpdate()
{
    PostConfigurationData postConfig = /* fetched singleton */;
    if (!EntityManager.HasEnabledComponent<Locked>(postConfig.m_PostServicePrefab))
    {
        uint updateFrameIndex = (m_SimulationSystem.frameIndex / 64u) & 0xF;
        var job = new MailAccumulationJob {
            m_UpdateFrameIndex = updateFrameIndex,
            m_PostConfigurationData = postConfig,
            m_EfficiencyParameters = /* fetched singleton */,
            m_CommandBuffer = m_EndFrameBarrier.CreateCommandBuffer().AsParallelWriter(),
            /* other type handles and lookups */
        };
        JobHandle handle = JobChunkExtensions.ScheduleParallel(job, m_MailProducerQuery, Dependency);
        m_EndFrameBarrier.AddJobHandleForProducer(handle);
        Dependency = handle;
    }
}

Notes / Tips: - This system is data-driven: configure mail behavior via MailAccumulationData (per-zone or service) and PostConfigurationData (global thresholds). - It uses a shared UpdateFrame index to stagger per-building processing across frames; altering update interval will change workload distribution. - Because the system creates PostVanRequest entities via the command buffer, changes happen at end-of-frame; the EndFrameBarrier ensures ordering with other systems that consume requests.