Skip to content

Game.CommercialFindPropertySystem

Assembly: Assembly-CSharp.dll (game's main assembly)
Namespace: Game.Simulation

Type: class

Base: GameSystemBase

Summary:
CommercialFindPropertySystem is a game simulation system responsible for matching commercial companies (service/commerce providers) to free commercial properties (buildings on the market). It runs periodically (GetUpdateInterval returns 16 ticks) and schedules a parallel job (PropertyUtils.CompanyFindPropertyJob) that evaluates available properties for companies that are seeking property. The system queries the world for companies seeking service properties, free market properties, economy parameters, and zone preferences; it uses ResourceSystem and PropertyProcessingSystem to obtain prefab/resource data and to enqueue rent actions. The evaluation uses land value, zone preferences, resource availabilities and industrial process economics to compute a suitability score for each property.


Fields

  • private EntityQuery m_CommerceQuery
    Contains entities representing commercial/service companies that can seek properties. The query selects entities with ServiceAvailable, ResourceSeller, CompanyData, PropertySeeker and PrefabRef (and excludes temporary/deleted/created), and is required for the system to update.

  • private EntityQuery m_FreePropertyQuery
    Query for properties (PropertyOnMarket + CommercialProperty) currently available on the market. Excludes buildings that are Abandoned, Condemned, Destroyed, Deleted or Temp.

  • private EntityQuery m_EconomyParameterQuery
    Query used to access singleton EconomyParameterData used during evaluation/weighting.

  • private EntityQuery m_ZonePreferenceQuery
    Query used to access singleton ZonePreferenceData for zone-based scoring.

  • private ResourceSystem m_ResourceSystem
    Reference to the global ResourceSystem (used to read resource prefabs and register readers for job dependencies).

  • private PropertyProcessingSystem m_PropertyProcessingSystem
    Reference to PropertyProcessingSystem used to get the rent action queue writer and to register writers for dependencies.

  • private EndFrameBarrier m_EndFrameBarrier
    Command buffer barrier used to create an IJobParallelFor-compatible command buffer for enqueueing structural changes (rent actions, property assignment) produced by the job.

  • private TypeHandle __TypeHandle
    Compiler-generated struct storing ComponentTypeHandle / ComponentLookup / BufferLookup instances that are resolved in OnCreateForCompiler. Used by the job to access component data safely.

Properties

  • (none public)
    This system exposes no public properties. It uses internal queries and references to other systems and exposes functionality only via its scheduled job and the static Evaluate method.

Constructors

  • public CommercialFindPropertySystem()
    Default constructor. The system performs its runtime initialization in OnCreate rather than in the constructor.

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
    Returns 16. The system is configured to run every 16 simulation ticks (as implemented here). The argument indicates the update phase and can be used when scheduling phase-specific behaviour.

  • [Preserve] protected override void OnCreate()
    Creates required queries and resolves references to systems:

  • Retrieves EndFrameBarrier, ResourceSystem and PropertyProcessingSystem from the world.
  • Builds EntityQueries (m_CommerceQuery, m_FreePropertyQuery, m_EconomyParameterQuery, m_ZonePreferenceQuery).
  • Calls RequireForUpdate for m_CommerceQuery and m_EconomyParameterQuery to make the system active only when relevant data exists.
  • Also prepares compiler type handles in OnCreateForCompiler (setup done via __TypeHandle in generated code path).

  • [Preserve] protected override void OnUpdate()
    Main scheduling method. Behavior:

  • If there are any commerce entities (m_CommerceQuery.CalculateEntityCount() > 0) it prepares and schedules PropertyUtils.CompanyFindPropertyJob.
  • The job is provided:
    • Component type handles (entity, prefab, seeker, company data, etc.) via InternalCompilerInterface.GetComponentTypeHandle / GetEntityTypeHandle.
    • Free property lists: m_FreePropertyQuery.ToEntityListAsync and ToComponentDataListAsync produce lists of property entities and their PrefabRef components asynchronously (outJobHandle/outJobHandle2).
    • ComponentLookup and BufferLookup references (building data, property data, resource availability buffers, renters, etc.).
    • Singletons: EconomyParameterData and ZonePreferenceData obtained from respective queries.
    • Resource prefabs from m_ResourceSystem.GetPrefabs().
    • Flags like m_Commercial = true.
    • Writers: RentActionQueue (from PropertyProcessingSystem.GetRentActionQueue(out deps).AsParallelWriter()) and a parallel command buffer from m_EndFrameBarrier.
  • The job is scheduled via JobChunkExtensions.ScheduleParallel with combined dependencies (free property async lists, rent queue deps, plus existing base.Dependency).
  • Finally it:
    • Registers the returned JobHandle with the EndFrameBarrier (m_EndFrameBarrier.AddJobHandleForProducer).
    • Calls m_ResourceSystem.AddPrefabsReader(base.Dependency) to register the system as a reader of resource prefabs for dependency tracking.
    • Calls m_PropertyProcessingSystem.AddWriter(base.Dependency) to register as a writer to the property-processing queues.

Note: The job is executed in parallel and performs most decision logic off the main thread. All structural changes are done via the parallel command buffer and queued rent actions.

  • public static float Evaluate(Entity company, Entity property, ref ServiceCompanyData service, ref IndustrialProcessData process, ref PropertySeeker propertySeeker, ComponentLookup<Building> buildings, ComponentLookup<PrefabRef> prefabFromEntity, ComponentLookup<BuildingData> buildingDatas, BufferLookup<ResourceAvailability> availabilities, ComponentLookup<LandValue> landValues, ResourcePrefabs resourcePrefabs, ComponentLookup<ResourceData> resourceDatas, ComponentLookup<BuildingPropertyData> propertyDatas, ComponentLookup<SpawnableBuildingData> spawnableDatas, BufferLookup<Renter> renterBuffers, ComponentLookup<CommercialCompany> companies, ref ZonePreferenceData preferences)
    Static evaluation helper that returns a float score (higher is better), or -1f to indicate the property is unsuitable. Key logic:
  • Verifies the property entity has a Building component; otherwise returns -1.
  • Reads the property's prefab and building property data.
  • Iterates current renters of the property; if any renter entity is a commercial company, returns -1 (can't rent to another commercial company).
  • Computes a base score (initially 500) then:
    • Gathers availability buffer from the building's road edge and land value if available.
    • Uses ZoneEvaluationUtils.GetCommercialScore to compute a zone/availability/land-value influenced commercial score (considers building space multiplier and spawnable level and whether the process output is Lodging).
    • If the industrial process consumes a resource that has limited availability (AvailableResource != Count), compute a penalty based on input weight, market price and availability, subtracting from the score.
  • Returns computed score, or -1f for invalid cases.

This method is useful for unit tests or for single-threaded evaluation of a pairing, and encapsulates the scoring rules used by the job.

  • [MethodImpl(MethodImplOptions.AggressiveInlining)] private void __AssignQueries(ref SystemState state)
    Compiler helper that sets up EntityQueryBuilder during code-gen. Not intended for modder calls.

  • protected override void OnCreateForCompiler()
    Compiler-time helper that calls __AssignQueries and __TypeHandle.__AssignHandles to initialize type handles / lookups used by the job. This is part of the generated glue to allow the scheduled job to use component handles safely.

Usage Example

// Example: how the system sets up and schedules the property-finding job (simplified).
[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    // Acquire required systems and create queries (done in actual system)
    m_EndFrameBarrier = World.GetOrCreateSystemManaged<EndFrameBarrier>();
    m_ResourceSystem = World.GetOrCreateSystemManaged<ResourceSystem>();
    m_PropertyProcessingSystem = World.GetOrCreateSystemManaged<PropertyProcessingSystem>();

    // Build queries used by the system
    m_CommerceQuery = GetEntityQuery(ComponentType.ReadWrite<ServiceAvailable>(),
                                     ComponentType.ReadWrite<ResourceSeller>(),
                                     ComponentType.ReadWrite<CompanyData>(),
                                     ComponentType.ReadWrite<PropertySeeker>(),
                                     ComponentType.ReadOnly<PrefabRef>(),
                                     ComponentType.Exclude<Deleted>(),
                                     ComponentType.Exclude<Temp>(),
                                     ComponentType.Exclude<Created>());

    m_FreePropertyQuery = GetEntityQuery(ComponentType.ReadWrite<PropertyOnMarket>(),
                                        ComponentType.ReadWrite<CommercialProperty>(),
                                        ComponentType.ReadOnly<PrefabRef>(),
                                        ComponentType.Exclude<Abandoned>(),
                                        ComponentType.Exclude<Condemned>(),
                                        ComponentType.Exclude<Destroyed>(),
                                        ComponentType.Exclude<Deleted>(),
                                        ComponentType.Exclude<Temp>());

    RequireForUpdate(m_CommerceQuery);
    RequireForUpdate(m_EconomyParameterQuery);
}

// Example: call Evaluate directly from simple debug code (single-threaded).
// Note: providing all required ComponentLookup/BufferLookup etc. is non-trivial in user code,
// so prefer inspecting system behavior, or reusing its job logic in a custom system.

Notes and modding guidance - The matchmaking happens inside a parallel job (PropertyUtils.CompanyFindPropertyJob) — to modify matching behaviour you can: - Reimplement a similar job in your own system and schedule it at a different interval (or replace the system with a custom one). - Hook into PropertyProcessingSystem's rent action queue to intercept or modify final rent actions. - If you need to change the scoring logic, copy/adapt the Evaluate algorithm or patch calls to ZoneEvaluationUtils / EconomyUtils functions used here. - Be careful with threading: the job uses ComponentLookups, BufferLookups and a parallel command buffer. Do not access UnityEngine objects from the job. Use the same patterns (AsParallelWriter, AddJobHandleForProducer, AddPrefabsReader/AddWriter) to keep dependency tracking correct. - Performance considerations: the system gathers all free properties and processes them asynchronously in bulk. Changing queries or adding heavy per-entity work may increase CPU usage; prefer low-cost evaluations or spread workload across frames.

If you want, I can produce a focused snippet showing how to read the system from a Mod and inspect the last scheduled job, or sketch how to replicate/evolve the Evaluate logic in a custom system.