Skip to content

Game.Simulation.CountResidentialPropertySystem

Assembly:
Namespace: Game.Simulation

Type: class

Base: GameSystemBase, IDefaultSerializable, ISerializable

Summary:
CountResidentialPropertySystem is a game simulation system that scans building entities and accumulates residential property counts and shelter capacities. It gathers totals and available (free) counts split by zone density (Low/Medium/High) and also tracks homeless shelter capacity for abandoned buildings and parks. The system uses a NativeAccumulator to aggregate results from a Burst-compiled IJobChunk (CountResidentialPropertyJob) scheduled in parallel. The aggregated values are exposed via a small ResidentialPropertyData struct and several debug watch properties. The system updates on a fixed interval (GetUpdateInterval returns 16) and supports serialization for save/load compatibility.


Fields

  • private NativeAccumulator<ResidentialPropertyData> m_ResidentialPropertyData
    Stores the parallel accumulator used by the scheduled job to aggregate ResidentialPropertyData across chunks. Persistent allocator is used; disposed on system destroy.

  • private ResidentialPropertyData m_LastResidentialPropertyData
    Holds the last snapshot of aggregated residential property data (result retrieved from m_ResidentialPropertyData each update). Returned by GetResidentialPropertyData().

  • private EntityQuery m_ResidentialPropertyQuery
    EntityQuery used to select building entities relevant to counting (buildings + residential property, excluding condemned/destroyed/deleted/temp). Required for the system to run.

  • private TypeHandle __TypeHandle
    Generated container holding ComponentTypeHandle/BufferTypeHandle/ComponentLookup handles used by the job. Assigned in OnCreateForCompiler.

  • (Nested struct) public struct ResidentialPropertyData
    Contains the accumulated counts:

  • int3 m_FreeProperties — free/residential properties per zone density (x=Low, y=Medium, z=High)
  • int3 m_TotalProperties — total residential properties per density
  • int m_FreeShelterCapacity — available shelter capacity for homeless (abandoned/park)
  • int m_TotalShelterCapacity — total shelter capacity This struct implements IAccumulable and custom serialization/deserialization.

  • (Nested job) private struct CountResidentialPropertyJob : IJobChunk
    Burst-compiled job executed in parallel over building chunks. It reads prefab refs, renter buffers, building/spawnable/zone/household component lookups and computes a ResidentialPropertyData per chunk which it accumulates into the NativeAccumulator.

Properties

  • public int3 FreeProperties { get; }
    Debug-watchable property returning m_LastResidentialPropertyData.m_FreeProperties (free/residential properties by density).

  • public int3 TotalProperties { get; }
    Debug-watchable property returning m_LastResidentialPropertyData.m_TotalProperties (total residential properties by density).

  • public int FreeShelterCapacity { get; }
    Debug-watchable property returning m_LastResidentialPropertyData.m_FreeShelterCapacity (available shelter/homeless capacity).

  • public int TotalShelterCapacity { get; }
    Debug-watchable property returning m_LastResidentialPropertyData.m_TotalShelterCapacity (total shelter/homeless capacity).

Constructors

  • public CountResidentialPropertySystem()
    Default constructor. The system uses [Preserve] on lifecycle methods; constructor itself performs no special initialization beyond base constructor.

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
    Returns the update interval in frames for the system. Implementation returns 16, so the system runs every 16 frames.

  • public ResidentialPropertyData GetResidentialPropertyData()
    Returns the last aggregated ResidentialPropertyData snapshot (m_LastResidentialPropertyData). Use this to read totals/free counts collected by the last run.

  • protected override void OnCreate()
    Initializes the EntityQuery (m_ResidentialPropertyQuery) that selects buildings to be scanned and creates the NativeAccumulator (m_ResidentialPropertyData) with Allocator.Persistent. Calls RequireForUpdate(m_ResidentialPropertyQuery) so the system only runs when relevant entities exist.

  • protected override void OnDestroy()
    Disposes the NativeAccumulator and calls base.OnDestroy().

  • public void SetDefaults(Context context)
    Resets m_LastResidentialPropertyData to default and clears the NativeAccumulator. Called to set system defaults (e.g., at new game or when resetting state).

  • protected override void OnUpdate()
    Core runtime behaviour:

  • Copies the last result from the accumulator to m_LastResidentialPropertyData and clears the accumulator.
  • Constructs a CountResidentialPropertyJob, populating all ComponentTypeHandle/BufferTypeHandle/ComponentLookup fields by querying the __TypeHandle via InternalCompilerInterface.
  • Schedules the job with ScheduleParallel against m_ResidentialPropertyQuery and stores the JobHandle into base.Dependency.

  • public void Serialize<TWriter>(TWriter writer) where TWriter : IWriter
    Serializes m_LastResidentialPropertyData to the writer for savegame persistence.

  • public void Deserialize<TReader>(TReader reader) where TReader : IReader
    Deserializes m_LastResidentialPropertyData when loading a save, with a version check (reads if reader.context.version >= Version.homelessFix).

  • private void __AssignQueries(ref SystemState state)
    Compiler-generated helper; currently only creates/disposes a temporary EntityQueryBuilder. Used by OnCreateForCompiler.

  • protected override void OnCreateForCompiler()
    Compiler helper that assigns query handles and type handles (calls __AssignQueries and __TypeHandle.__AssignHandles).

  • private struct TypeHandle.__AssignHandles(ref SystemState state)
    Assigns ComponentTypeHandle/BufferTypeHandle/ComponentLookup fields used by the job (called from OnCreateForCompiler).

  • (CountResidentialPropertyJob.Execute) public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
    Job logic executed per chunk:

  • If chunk has Abandoned or Park components: accumulates shelter homeless capacity via BuildingUtils.GetShelterHomelessCapacity and computes free shelter capacity by counting renters linked to households.
  • Otherwise, iterates prefabs in chunk. For each prefab with BuildingPropertyData and a residential zone prefab, it determines zone density (Low/Medium/High) and number of residential properties, counts renters that are households, and increments TotalProperties and FreeProperties (for on-market properties) for the appropriate density channel.
  • Finally accumulates the per-chunk ResidentialPropertyData into the NativeAccumulator via m_ResidentialPropertyData.Accumulate(value).

Usage Example

// Example: reading the last counted residential property data from game code:
// (assumes access to the World/System retrieval method used by the modding environment)

var system = World.DefaultGameObjectInjectionWorld.GetExistingSystemManaged<Game.Simulation.CountResidentialPropertySystem>();
if (system != null)
{
    var data = system.GetResidentialPropertyData();
    int3 free = data.m_FreeProperties;       // x=Low, y=Medium, z=High
    int3 total = data.m_TotalProperties;
    int freeShelter = data.m_FreeShelterCapacity;
    int totalShelter = data.m_TotalShelterCapacity;

    // Use values to update UI, metrics, or balance logic.
}

Notes: - The system is designed to be batch-friendly and uses Burst/IJobChunk and parallel accumulation to scale across many building entities. - ResidentialPropertyData serialization includes compatibility/version checks for homeless/shelter fields. Ensure save compatibility if you modify the struct or serialization logic.