Economy – Model¶
This folder contains the value types, enums, and shared helpers that form the foundation of the Economy subsystem.
These types are public and stable — safe to depend on in gameplay code, UI, analytics, tests, and integrations.
They contain minimal shared logic (e.g., result helpers and canonical sourceId building),
plus data contracts shared across all economy flows.
Value types¶
ChargeLine¶
Represents a single money line.
- Fields:
(currencyId, amount) idis trimmed and normalised to lowercase.- Validity is expressed via
IsValid(idnon-empty andamount > 0). - Used in
PriceBundle.money.
ChargeLine normalizes id casing on construction to keep identifiers consistent.
ItemLine¶
Represents a single item line.
- Fields:
(guid, quantity) guidis typically anItemDefinitionGUID or item key.- Validity is expressed via
IsValid(guidnon-empty andquantity > 0). - Used in
PriceBundle.items.
PriceBundle¶
Bundle of optional money and/or item lines.
- Structure:
IReadOnlyList<ChargeLine> moneyIReadOnlyList<ItemLine> items- Helper factory methods:
MoneyOnly(moneyLines)ItemsOnly(itemLines)- Used for all economy flows (shop, reward, crafting, sell, etc.).
PriceBundledoes not clone or freeze the provided lists; callers must treat list contents as read-only by contract.
A PriceBundle may contain:
- Money only
- Items only
- Both money and items
Results¶
EcoOpResult¶
Represents the outcome of an economy operation.
Fields¶
Success—boolCode—EcoOpCodeMessage— optional string
Features¶
- Factory helpers:
Ok()Fail()InvalidArgs()ServiceMissing()NoSpace()- …and others
- Deconstruction support:
var (ok, code, message) = result; - No implicit
boolconversion:if (result.Success) { /* success */ } // or: if (result.IsOk) { /* success */ } - Equality and hashing support
Use EcoOpResult for all branching logic — Economy never throws for normal failure paths.
EcoOpCode¶
Standardised result codes shared across all Economy services.
OkInvalidArgsServiceMissingContainerMissingResolverMissingInsufficientFundsNoSpaceNotOwnedPolicyBlockedOverflowEscrowUnavailableUnknownError
These codes unify behaviour across:
- Currency-backed ledgers
- Inventory-backed item stores
- Shop, Crafting, and Reward services
EcoOpResultComparers¶
Reusable comparers for EcoOpResult.
ByCode— compares onlySuccessandCode, ignoringMessage.
Useful for:
- Unit tests
- Dictionaries / sets
- Deduplicating results where text is not relevant
Reasons & sources¶
EcoReasons¶
Canonical reason strings used for telemetry and auditing.
Reason groups include:
- Economy / Money
EconomyPayEconomyGrantEconomyPayRollback-
EconomyGrantRollback -
Shop
ShopBuyShopSellShopRefund-
Rollback variants
-
Crafting
CraftCraftRefund-
CraftRollbackItems -
Rewards
Reward
Using canonical reasons prevents analytics fragmentation.
EcoSource¶
Builder for canonical sourceId strings.
- Combines vendor and request identifiers:
(vendor: "VendorA", request: "abc") → "VendorA|rid:abc"- Sanitises delimiters and trims whitespace.
- Applies length caps to keep analytics keys bounded.
- Used by currency operations that support correlation.
Validation & policies¶
DebitValidationMode¶
Controls validation behaviour when computing effective debits under a policy.
- Strict — invalid lines cause immediate failure.
- SkipInvalid — invalid lines are ignored (appropriate for previews / UI).
Note:
DebitValidationModeis an internal implementation detail used by built-in policy computation.
LedgerPreflightMode¶
Controls UX preflight behaviour for IValueLedger.CanPay().
- Strict — UI disables when policy would adjust the nominal debit.
- PolicyApproved — UI enables when policy approves and the wallet covers the effective debit.
This affects UX only.
Authoritative mutations always go through Pay() / Grant().
Usage guidelines¶
- Use
PriceBundleto represent all costs, payouts, and recipes. - Inspect
EcoOpResultfor branching in gameplay logic. - Pass canonical
reasonandsourceIdvalues for consistent telemetry. - Use
EcoOpResultComparers.ByCodewhen messages are not relevant.
Stability¶
- All public types in this folder are stable and safe to depend on.
- Behaviour is consistent across minor versions.
- New result codes or helpers may be added, but existing semantics are preserved.