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 densityint m_FreeShelterCapacity
— available shelter capacity for homeless (abandoned/park)-
int m_TotalShelterCapacity
— total shelter capacity This struct implements IAccumulableand 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.