Skip to content

💰 Currency – Authority

Namespace: RevGaming.RevFramework.Currency.Authority

⚠️ Not a multiplayer framework.
This folder provides the authority hooks for the Currency system — not replication, prediction, rollback, or reconciliation.

You supply those via your chosen netcode (NGO, Fusion, Mirror, custom).

These components are used by the Currency stack (via the AuthorityCurrencyService decorator) to decide who is allowed to mutate a wallet.

✅ Works in single-player and multiplayer
✅ Netcode-agnostic
✅ One tiny interface: ICurrencyAuthority
❌ No networking logic included


Purpose

  • Gate wallet mutations (Credit, Debit, SetBalance, Transfer).
  • Allow you to express “who is allowed to change this wallet?” in your game rules.
  • Stay minimal, deterministic, and free of netcode dependencies.
  • Provide safe resolution + caching without hidden global state or singletons.

Authority answers yes/no only.
How state is replicated is always your responsibility.


Components & API

ICurrencyAuthority

The minimal authority contract:

public interface ICurrencyAuthority
{
    bool HasAuthority(GameObject owner, CurrencyId currency, CurOpKind kind);
    bool HasAuthorityTransfer(GameObject from, GameObject to, CurrencyId currency);
}

You implement this interface on any component that defines who may mutate which wallet.

Common placements: - On the wallet owner (recommended and fastest) - On a scene-level manager - On a netcode authority object (server, host, deterministic owner)


CurrencyAuthority (static resolver)

Scene-scoped resolver + cache.

Automatically refreshed on: - Scene load - Scene unload - Active scene change - Domain reload

Resolution order (first match wins):

  1. Scene cache (fast path)
  2. Local component on the context GameObject
  3. Parent transforms
  4. Scene roots (includes inactive)
  5. Global scan (last resort; cached per scene and typically runs at most once)

Key methods:

public static ICurrencyAuthority Resolve(MonoBehaviour ctx);
public static ICurrencyAuthority Resolve(Component c);
public static ICurrencyAuthority Resolve(GameObject go);

public static void Invalidate();
public static void Invalidate(Scene scene);

The resolver only returns usable implementations: - Enabled behaviours - Active in hierarchy - Or non-Behaviour implementations


CurrencyAuthorityBinder (Local / single-player)

A simple built-in binder for single-player or local development:

[AddComponentMenu("RevFramework/Currency/Authority/Currency Authority Binder (Local)")]
public sealed class CurrencyAuthorityBinder : MonoBehaviour, ICurrencyAuthority
{
    public bool alwaysTrue = true;

    public bool HasAuthority(GameObject owner, CurrencyId id, CurOpKind kind)
        => alwaysTrue && owner;

    public bool HasAuthorityTransfer(GameObject from, GameObject to, CurrencyId id)
        => alwaysTrue && from && to;
}

Attach this to your scene or owner to allow all local mutations.

For multiplayer, replace this with your own netcode-specific binder.


How Currency uses authority

Authority is enforced via the AuthorityCurrencyService decorator.

Added during composition:

svc = CurrencyFactories.WithAuthority(inner, context);

Behaviour

  • If a binder exists and denies → returns CurOpCode.Unauthorized
  • If no binder is found → returns CurOpCode.Unauthorized
  • When the authority decorator is composed but no binder is discoverable, all currency mutations are blocked until an ICurrencyAuthority implementation is present.
  • Authority is checked for all mutations, including audit-aware overloads
  • Authority is enforced only for mutating operations (Credit, Debit, SetBalance, Transfer). Read operations (GetBalance, EnsureWallet) are not gated.

If you want permissive behaviour, add a binder that always returns true (the default local binder).

Typically only one binder is needed per wallet owner. If multiple binders exist, the resolver returns the first valid one found (local → parents → scene → global). Placement therefore matters.


Typical stacks

Single-player (explicit authority)

SceneCurrencyService → Caps → Audit → Authority (Local Binder)

Multiplayer

SceneCurrencyService → Caps → Audit → Authority → Idempotency → Batch

(RequireEscrow may also be present depending on policy.)


Quick Start

Single-player

Add the local binder:

svc = CurrencyFactories.WithCapsAuditAuthority(inner, policy, this);

This enables permissive authority for all mutations.


Multiplayer

  1. Implement an ICurrencyAuthority binder for your server/owner rules.
  2. Attach it to the appropriate GameObject (owner or server object).
  3. Compose the authority decorator:
    svc = CurrencyFactories.WithCapsAuditAuthority(inner, policy, this);
    
  4. Run mutations on the authority side (e.g. server).
  5. Replicate balances using your netcode’s sync layer.

If authority denies:

CurOpResult.Code == CurOpCode.Unauthorized

Example authority rules (not shipped)

  • NGO
    HasAuthority = NetworkObject.IsServer || NetworkObject.IsOwner

  • Mirror
    Uses NetworkIdentity.hasAuthority or a server-authoritative model.

  • Fusion
    Checks state/input authority depending on your simulation setup.

These are examples only. You decide the rules.


FAQs

Where should the binder live?
On the wallet owner. Parents/scene/global are fallbacks.

Do I need to call Invalidate()?
Only if you dynamically add/remove binders at runtime. Scene hooks handle normal cases.

Why am I getting Unauthorized?
No authority binder was found, or your binder returned false.

Can I register multiple binders?
The resolver returns the first valid one. Placement matters.

Does Currency replicate balances?
No. You must replicate balances yourself.


Troubleshooting

  • Unauthorized → Run the mutation on the authority side, or add a permissive binder.
  • Client not receiving changes → Replication is missing.

  • Core — composition helpers (WithAuthority, WithCapsAuditAuthority)
  • InternalAuthorityCurrencyService decorator
  • Policies — optional escrow enforcement per currency
  • Adapters — inventory-backed currency implementations

Support stance

Authority hooks are runtime utilities, not a full networking solution.

RevFramework does not provide: - Replication - Prediction - Rollback - Reconciliation

Bring your own netcode.