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.