Skip to content

Game.Zones.LotSizeJobs

Assembly: Game
Namespace: Game.Zones

Type: public static class

Base: System.Object

Summary:
LotSizeJobs provides Burst-compiled worker jobs used by the zoning system to discover and update vacant lot sizes inside blocks, and to collect updated world bounds for later processing. The main work is done by UpdateLotSizeJob (IJobParallelForDefer) which scans block cell buffers to locate contiguous vacant lots, computes lot heights and flags, and writes VacantLot buffers (or removes them) via an EntityCommandBuffer. UpdateBoundsJob drains a concurrent bounds queue into a NativeList for further processing. The code is optimized for Unity DOTS: it uses BufferLookup / ComponentLookup, NativeArray temporaries, a NativeQuadTree search to sample neighboring blocks, and Burst compilation.


Fields

  • public NativeArray<CellCheckHelpers.SortedEntity> m_Blocks
    Used as the parallel loop input for UpdateLotSizeJob: contains sorted block entities to process.

  • public ZonePrefabs m_ZonePrefabs
    ReadOnly mapping of ZoneType -> prefab Entity used to look up zone-specific data.

  • public ComponentLookup<Block> m_BlockData
    ReadOnly component lookup for Block component (block geometry / size / direction / position).

  • public ComponentLookup<ValidArea> m_ValidAreaData
    ReadOnly lookup containing the valid horizontal ranges inside a block to consider when finding lots.

  • public ComponentLookup<BuildOrder> m_BuildOrderData
    ReadOnly lookup used to determine build orders and compatibility between adjacent blocks.

  • public ComponentLookup<Updated> m_UpdatedData
    ReadOnly flag lookup used to avoid re-enqueuing bounds when an entity was already marked updated.

  • public ComponentLookup<ZoneData> m_ZoneData
    ReadOnly lookup for zone-specific flags (e.g., SupportNarrow).

  • public BufferLookup<Cell> m_Cells
    ReadOnly buffer lookup for the Cell buffer per block (grid of per-cell state used to detect occupancy, roadside, heights, etc.).

  • public NativeQuadTree<Entity, Bounds2> m_SearchTree
    ReadOnly spatial index used by the iterator to find neighboring blocks whose cells must be sampled when expanding areas.

  • public BufferLookup<VacantLot> m_VacantLots
    NativeDisableParallelForRestriction: optional buffer to store resulting VacantLot entries per block. The job adds/removes this buffer via the EntityCommandBuffer when necessary.

  • public EntityCommandBuffer.ParallelWriter m_CommandBuffer
    Parallel E.C.B. used to add/remove components and add buffer elements for VacantLot and Updated.

  • public NativeQueue<Bounds2>.ParallelWriter m_BoundsQueue
    Concurrent queue used to enqueue block bounds that need to be reprocessed later (drained by UpdateBoundsJob).

Notes: - These fields refer to members inside UpdateLotSizeJob. The static LotSizeJobs container has no instance fields; it only exposes the nested job structs.

Iterator (private nested inside UpdateLotSizeJob) — important internal fields used when expanding the sampling area: - m_Entity, m_Block, m_ValidArea, m_BuildOrder, m_Bounds, m_Quad, m_BlockData, m_ValidAreaData, m_BuildOrderData, m_CellData, m_Cells
Its Iterate/Intersect implementations are used by the NativeQuadTree to accumulate cell data from neighboring blocks into a temporary NativeArray when ExpandArea is used.

Properties

  • None on the static container. The jobs use public fields (DOTS-style) rather than properties to provide data.

Constructors

  • No explicit constructors on LotSizeJobs (static container). The nested job structs are plain value types and use default initialization — populate their public fields before scheduling.

Methods

  • public void Execute(int index) — UpdateLotSizeJob.Execute (IJobParallelForDefer)
    Main worker that runs per-block (per entry in m_Blocks). For the block at m_Blocks[index].m_Entity it:
  • Reads Block, ValidArea, BuildOrder and the Cell buffer.
  • Iterates horizontally across the valid area to find contiguous empty (vacant) regions.
  • Optionally expands the sampled area (ExpandArea) when the valid area touches block edges to consider neighboring blocks.
  • Computes lot depth/width constraints, heights (FindHeight), and road-facing flags to generate VacantLot entries.
  • Adds a VacantLot buffer to the entity via m_CommandBuffer if needed, populates it, or removes the component if no vacant lots exist.
  • Adds Updated component and enqueues the block bounds into m_BoundsQueue if the block was not already marked Updated.

  • private void FindHeight(Block block, NativeArray<Cell> cells, int2 min, int2 max, ref int height)
    Scans cells in rectangle [min, max) and reduces height to the minimum cell height found. Clamps min/max to block size.

  • private void FindDepth(Block block, NativeArray<Cell> cells, ref int2 min, ref int2 max, ZoneType zone)
    Computes the vertical extent (depth) for a candidate lot starting at min.x; sets max.y to the first row that is blocked/occupied or a different zone. Applies a cap and reduces very deep areas.

  • private void ExpandRight(Block block, NativeArray<Cell> cells, ref int2 min, ref int2 max, ZoneType zone)
    Extends the candidate region to the right until encountering a blocked/occupied cell or differing zone.

  • private void ExpandLeft(Block block, NativeArray<Cell> cells, ref int2 min, ref int2 max, ZoneType zone)
    Similar to ExpandRight but extends leftwards.

  • private void WidthReductionLeft(Block block, ref int2 min, ref int2 max, int sizeOffset)
    Adjusts min.x (left bound) to avoid extremely narrow or wrapping lot results when an expanded sample area is used; contains heuristics to choose a better lot split.

  • private void WidthReductionRight(Block block, ref int2 min, ref int2 max, int sizeOffset)
    Mirrors WidthReductionLeft for the right side.

  • private NativeArray<Cell> ExpandArea(Entity entity, Block block, ValidArea validArea, BuildOrder buildOrder, NativeArray<Cell> cells, out int2 expandedOffset, out Block expandedBlock)
    When a candidate lot touches the edges of the valid area, creates a temporary expandedBlock and a NativeArray large enough to include neighboring block cell data. Populates the temporary array with the local block cells, then uses a NativeQuadTree iterator to collect cell samples from adjacent blocks (using the Iterator nested type). Returns the created NativeArray (Allocator.Temp) — caller must Dispose() it.

  • public void Execute() — UpdateBoundsJob.Execute (IJob)
    Drains m_BoundsQueue (NativeQueue) and appends its entries to m_BoundsList (NativeList). Ensures capacity before adding. Lightweight job meant to be scheduled after UpdateLotSizeJob producers have enqueued bounds.

Important behavioral/implementation notes: - Both job structs are annotated with [BurstCompile] for performance. - UpdateLotSizeJob is IJobParallelForDefer — it expects a deferred-length schedule driven by the m_Blocks array, enabling dynamic parallelism for variable block counts. - The UpdateLotSizeJob uses temporary NativeArray when an expanded sampling region is needed; those temporaries must be disposed before job completion — the code disposes them inside Execute. - m_VacantLots BufferLookup is accessed conditionally (HasBuffer), and the job uses the EntityCommandBuffer to create buffers or add/remove components safely in parallel. - Many bitwise checks on Cell.m_State are used to determine road edges, blocked or occupied cells, and to derive road-facing flags for lots.

Usage Example

Example scheduling pattern (illustrative; variable names/types should match your systems):

// Prepare job inputs (these must be valid and alive for the job lifetime)
var updateJob = new LotSizeJobs.UpdateLotSizeJob
{
    m_Blocks = blocksNativeArray,                       // NativeArray<CellCheckHelpers.SortedEntity>
    m_ZonePrefabs = zonePrefabs,
    m_BlockData = blockLookup,
    m_ValidAreaData = validAreaLookup,
    m_BuildOrderData = buildOrderLookup,
    m_UpdatedData = updatedLookup,
    m_ZoneData = zoneDataLookup,
    m_Cells = cellBufferLookup,
    m_SearchTree = searchTree,
    m_VacantLots = vacantLotBufferLookup,               // BufferLookup<VacantLot>
    m_CommandBuffer = commandBuffer.AsParallelWriter(), // EntityCommandBuffer.ParallelWriter
    m_BoundsQueue = boundsQueue.AsParallelWriter()      // NativeQueue<Bounds2>.ParallelWriter
};

// Schedule the work (deferred parallel for)
var handle = updateJob.Schedule(m_Blocks.Length, 64, dependency);

// Drain bounds queue into list (single-threaded job) after above
var boundsJob = new LotSizeJobs.UpdateBoundsJob
{
    m_BoundsQueue = boundsQueue,
    m_BoundsList = boundsList
};
var finalHandle = boundsJob.Schedule(handle);

// Use finalHandle as the next dependency

Notes for modders: - This job interacts directly with ECS ComponentLookup/BufferLookup and uses an EntityCommandBuffer for structural changes: follow DOTS rules — create/populate/lookups in the same system and ensure lifetimes are correct. - Expanding areas may temporarily allocate a NativeArray with Allocator.Temp inside the job; this is safe because allocation and disposal occur entirely within Execute. - The algorithm applies several heuristics for splitting long lots and handling narrow-support flags (ZoneFlags.SupportNarrow). If you change zone flags, size limits, or cell-state semantics, adjust the related heuristics (WidthReduction*, FindDepth, lot width thresholds). - If you add new CellFlags or ZoneType semantics, update the checks where cell.m_State and cell.m_Zone are evaluated.

If you want, I can generate a focused doc for the nested UpdateLotSizeJob struct only (with full member signatures and more examples of scheduling in a DOTS System), or produce a UML-like member list.