Game.TouristLeaveSystem
Assembly: Game (approx.; part of the game's managed assemblies)
Namespace: Game.Simulation
Type: class
Base: GameSystemBase
Summary:
The TouristLeaveSystem is a simulation system that periodically evaluates TouristHousehold entities and makes tourists "leave the city" (move away) when certain conditions are met. It schedules a Burst-compiled IJobChunk (TouristLeaveJob) that runs in parallel over the relevant entity chunks. The job checks whether the chunk's update frame matches the system's scheduled update frame, inspects lodging and money resources for each tourist household, and issues a move-away command and a TriggerAction (TriggerType.TouristLeftCity) when tourists cannot stay or cannot pay. The system uses the EndFrameBarrier to produce entity commands and the TriggerSystem to enqueue triggers. It reads the normalized time from TimeSystem to apply different thresholds.
Fields
-
private EntityQuery m_TouristHouseholdGroup
Stores the query used to select TouristHousehold entities that are eligible for processing (excludes households marked as MovingAway, Created, Deleted, or Temp). -
private SimulationSystem m_SimulationSystem
Reference to the SimulationSystem used to access the current frame index. -
private EndFrameBarrier m_EndFrameBarrier
Used to create an EntityCommandBuffer. Commands (e.g., HouseholdMoveAway) are recorded to this barrier so they are performed at the appropriate synchronization point. -
private TriggerSystem m_TriggerSystem
Used to create an action buffer (NativeQueue/trigger buffer) for enqueuing TriggerAction items (e.g., TouristLeftCity). -
private TimeSystem m_TimeSystem
Provides normalizedTime used by the job to decide when tourists should leave based on in-game day progression. -
private TypeHandle __TypeHandle
Internal struct holding ECS type handles (entity, component, buffer, shared-component and component lookup handles) used to build the job's type accessors. -
private struct TouristLeaveJob
(nested)
Burst-compiled IJobChunk that implements the core logic. It contains handles: - EntityTypeHandle m_EntityType
- ComponentTypeHandle
m_HouseholdType - BufferTypeHandle
m_ResourcesType - SharedComponentTypeHandle
m_UpdateFrameType - ComponentLookup
m_LodgingProviders
and writers: - NativeQueue
.ParallelWriter m_TriggerBuffer -
EntityCommandBuffer.ParallelWriter m_CommandBuffer
plus m_UpdateFrameIndex and m_Time. -
private struct TypeHandle
(nested)
Holds and assigns the various type handles required by the job (EntityTypeHandle, TouristHousehold ComponentTypeHandle, UpdateFrame SharedComponentTypeHandle, Resources BufferTypeHandle, LodgingProvider ComponentLookup).
Properties
- None (the system exposes no public properties)
Constructors
public TouristLeaveSystem()
Default constructor. The system is annotated with Preserve attributes on lifecycle methods; creation is handled by the ECS world setup.
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
Returns 512. This system uses a coarse update interval; the OnUpdate computes an update frame using SimulationUtils.GetUpdateFrameWithInterval with a sub-interval of 16 to stagger processing across frames. -
[Preserve] protected override void OnCreate()
Initializes system references and the entity query: - Gets SimulationSystem, EndFrameBarrier, TriggerSystem, and TimeSystem from the World.
- Builds an EntityQuery selecting TouristHousehold components and excluding MovingAway, Created, Deleted, and Temp.
-
Calls RequireForUpdate(m_TouristHouseholdGroup) so the system runs only when matching entities exist.
-
[Preserve] protected override void OnUpdate()
Creates and schedules the TouristLeaveJob: - Computes the update frame index with SimulationUtils.GetUpdateFrameWithInterval using the system frameIndex and GetUpdateInterval.
- Fills jobData with type handles, component lookups, trigger and command buffers (parallel writers), the update frame index, and the TimeSystem.normalizedTime.
- Schedules the job in parallel with JobChunkExtensions.ScheduleParallel.
-
Adds the job handle to the EndFrameBarrier and to the TriggerSystem producers to ensure proper dependency chaining.
-
private void __AssignQueries(ref SystemState state)
Compiler helper used during OnCreateForCompiler to create any required queries (here it creates and disposes an EntityQueryBuilder; actual query creation is done in OnCreate). -
protected override void OnCreateForCompiler()
Compiler helper that assigns queries and type handles for use by generated/compiled code paths. -
private struct TypeHandle.__AssignHandles(ref SystemState state)
Assigns all ECS type and buffer handles (EntityTypeHandle, TouristHousehold ComponentTypeHandle, UpdateFrame SharedComponentTypeHandle, Resources BufferTypeHandle, LodgingProvider ComponentLookup) from the provided SystemState. This method is marked AggressiveInlining for performance. -
private struct TouristLeaveJob.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
The job's Execute method logic: - Skips chunk if its UpdateFrame shared component index doesn't match m_UpdateFrameIndex.
- Obtains arrays/accessors: Entity[] for chunk, TouristHousehold[] component array, BufferAccessor
. - For each entity in chunk:
- Determines if household is staying in a hotel by checking m_LodgingProviders.HasComponent(household.m_Hotel).
- If staying in hotel, reads hotel price and household money (Resources buffer).
- Applies two conditions to decide a move-away:
- If not staying in a hotel and m_Time > 0.8f => leave.
- Or if staying in a hotel but household money < hotel price and m_Time > 0.7f => leave.
- If condition met:
- Calls CitizenUtils.HouseholdMoveAway using the command buffer (parallel writer).
- Enqueues a TriggerAction(TriggerType.TouristLeftCity, Entity.Null, entity, Entity.Null) to the trigger buffer.
- The job is Burst-compiled and runs in parallel across chunks.
Notes: - The system leverages parallel EntityCommandBuffer and Trigger buffers with the appropriate job dependencies added to EndFrameBarrier and TriggerSystem to ensure correctness. - The thresholds use normalizedTime and are intentionally different for hotel and non-hotel cases (0.7 vs 0.8), likely to give hotel guests extra time to pay.
Usage Example
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// The real system sets up its EntityQuery and system references automatically.
// Example: require TouristHousehold entities to activate the system.
m_TouristHouseholdGroup = GetEntityQuery(
ComponentType.ReadWrite<TouristHousehold>(),
ComponentType.Exclude<MovingAway>(),
ComponentType.Exclude<Created>(),
ComponentType.Exclude<Deleted>(),
ComponentType.Exclude<Temp>()
);
RequireForUpdate(m_TouristHouseholdGroup);
}
Additional notes: - The system is intended for modders to understand and potentially adapt or hook into tourist departure logic. If modifying, take care with the scheduling interval, the shared UpdateFrame filtering, and the parallel writers (ECS job safety and dependency management).