Skip to content

Game.FlowUtils

Assembly:
Game (likely Assembly-CSharp.dll)

Namespace:
Game.Simulation

Type:
static class

Base:
System.Object

Summary:
Utility helpers used by the simulation to compute resource consumption and to calculate a renter consumption multiplier based on citizen education and building level. Intended to be called from simulation systems that manage supply/demand and renter behavior. The methods operate on primitive types and ECS buffer/component lookups, so they are designed to be called from within Unity Entities systems or similar simulation code.


Fields

  • This static class declares no instance or static fields.
    {{ This class contains only static methods and no stored state. Methods operate on parameters passed in by reference (for totals, or through ECS lookups/buffers). }}

Properties

  • This static class declares no properties.
    {{ There are no properties exposed by FlowUtils. All functionality is provided via static methods. }}

Constructors

  • This static class has no explicit constructors.
    {{ As a static class, FlowUtils can't be instantiated and has no instance constructors. }}

Methods

  • public static int ConsumeFromTotal(int demand, ref int totalSupply, ref int totalDemand)
    {{ Summary: Consumes an amount from totalSupply according to the provided demand and adjusts totalSupply and totalDemand accordingly.

Behavior: - If demand <= 0 the method returns 0 and does no modification. - Otherwise it computes an amount to consume (num) based on current totals and clamps it to a lower and upper bound before subtracting it from totalSupply and reducing totalDemand by demand. - The algorithm: - lowerBound = totalSupply - (totalDemand - demand) - upperBound = totalSupply - num2 = totalDemand * 100 / demand - num = clamp(totalSupply * 100 / num2, lowerBound, upperBound) - totalSupply -= num - totalDemand -= demand - Returns the consumed amount (num).

Parameters: - demand: the demand to satisfy (int). - ref totalSupply: reference to an integer containing the current total supply. It will be reduced by the consumed amount. - ref totalDemand: reference to an integer containing the current total demand. It will be reduced by the provided demand.

Return value: - The actual amount consumed from totalSupply (int). Can be 0 if demand <= 0.

Notes / Edge cases: - The method performs integer math; division truncates toward zero. - If demand is 0 or negative, no changes are made and 0 is returned. - The computation of num2 (totalDemand * 100 / demand) can divide by zero only if demand == 0, which is already guarded by the initial check. - The clamping ensures the consumed amount does not reduce supply below what was reserved for other unmet demands. - Because integer arithmetic is used, rounding can produce slightly non-intuitive results; be mindful when using small numbers.

Performance: - Very cheap CPU-wise — only integer math and a clamp. Suitable for tight loops in simulation.

Usage: - Typical usage is within a flow or distribution system that iterates over different consumers and wants to proportionally consume available supply while tracking remaining demand. }}

  • public static float GetRenterConsumptionMultiplier(Entity prefab, DynamicBuffer<Renter> renterBuffer, ref BufferLookup<HouseholdCitizen> householdCitizens, ref BufferLookup<Employee> employees, ref ComponentLookup<Citizen> citizens, ref ComponentLookup<SpawnableBuildingData> spawnableDatas)
    {{ Summary: Computes a multiplier for renter consumption based on the education level of renters associated with the given building/prefab and the building's spawnable level. The multiplier scales consumption (presumably of goods/services) according to average education versus building level.

Behavior: - Iterates through the provided renterBuffer (each entry is a Renter entity reference). - For each renter entity: - If a HouseholdCitizen buffer exists on that renter entity, iterate its HouseholdCitizen entries and, for each, try to get the Citizen component to sum education levels. - Otherwise (if no household buffer), attempt to get an Employee buffer on the renter entity and iterate Employee entries to sum education levels from their Citizen components. - Track the number of citizen entries counted (num) and the sum of their education levels (num2). - If at least one citizen was counted: - Try to get the SpawnableBuildingData component for the prefab. If present, use component.m_Level (cast to float); otherwise default to 5f. - Return multiplier = 5f * (float)num / (buildingLevel + 0.5f * (num2 / (float)num)) - If no citizens were counted, return 0f.

Parameters: - prefab: an Entity that identifies the building/prefab whose level may influence the multiplier. - renterBuffer: DynamicBuffer containing renters associated with the building. - ref BufferLookup householdCitizens: accessor to lookup HouseholdCitizen buffers for renter entities. - ref BufferLookup employees: accessor to lookup Employee buffers for renter entities. - ref ComponentLookup citizens: accessor to read Citizen components (to obtain education level). - ref ComponentLookup spawnableDatas: accessor to read spawnable building data for the prefab entity.

Return value: - A float multiplier used to scale renter consumption. 0f when there are no associated citizens.

Notes / Interpretation: - The formula balances the count of citizens, their average education, and the building level. Higher counts increase the multiplier; higher building level or higher average education reduce the multiplier denominator (via the added term), effectively lowering consumption per capita compared to a low-level building with low education. - The default building level fallback is 5f if SpawnableBuildingData is missing. - The method relies on ECS lookups and buffer reads; it must be used in contexts where BufferLookup/ComponentLookup are valid (i.e., inside systems with proper access modes). - The method accesses component data by TryGetBuffer / TryGetComponent patterns — be mindful of read/write access and job safety if invoked from multithreaded Jobs or Burst contexts.

Performance: - Potentially expensive if renterBuffer or nested buffers are large. Each renter can require multiple buffer enumerations and component lookups. - If used per-frame for many buildings, prefer batching or caching where possible, or restrict use to systems with appropriate parallelization and scheduling.

Usage considerations: - Ensure ComponentLookup and BufferLookup are created with correct read permissions and updated dependency handling in systems. - Do not call from contexts that don't provide these lookups (e.g., pure static contexts without ECS system world access). }}

Usage Example

// Example 1: Using ConsumeFromTotal
int totalSupply = 1000;
int totalDemand = 400;
int demand = 150;
int consumed = FlowUtils.ConsumeFromTotal(demand, ref totalSupply, ref totalDemand);
// consumed is the amount taken from totalSupply to satisfy `demand`.
// totalSupply and totalDemand are updated accordingly.

// Example 2: Using GetRenterConsumptionMultiplier inside a System (pseudocode)
public partial struct MyConsumptionSystem : ISystem
{
    BufferLookup<HouseholdCitizen> householdCitizens;
    BufferLookup<Employee> employees;
    ComponentLookup<Citizen> citizens;
    ComponentLookup<SpawnableBuildingData> spawnableDatas;

    [BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        // Initialize lookups with appropriate access (read-only where possible)
        householdCitizens = state.GetBufferLookup<HouseholdCitizen>(true);
        employees = state.GetBufferLookup<Employee>(true);
        citizens = state.GetComponentLookup<Citizen>(true);
        spawnableDatas = state.GetComponentLookup<SpawnableBuildingData>(true);

        // For each building entity with a renter buffer:
        Entities.WithAll<SomeBuildingTag>().ForEach(
            (Entity prefabEntity, DynamicBuffer<Renter> renters) =>
            {
                float multiplier = FlowUtils.GetRenterConsumptionMultiplier(
                    prefabEntity, renters, ref householdCitizens, ref employees, ref citizens, ref spawnableDatas);
                // Use multiplier to scale consumption for this building
            }).Schedule();
    }
}

{{ Additional tips for modders: - Because GetRenterConsumptionMultiplier walks ECS buffers and component lookups, ensure lookups are created with the proper read/write flags and updated each frame. If you call this from a Job, pass the lookups into the job and honor job safety rules. - If you need deterministic rounding or float behavior, consider converting integer math to float and explicitly controlling rounding where required. - Unit-test these helpers in isolation by creating small ECS worlds or mocks of the involved buffers/components. - If you observe performance hotspots, profile and consider caching spawnable building levels or precomputing education aggregates when citizens change instead of recomputing each frame for every building. }}