Skip to content

Generated reference. This page mirrors Code/Interaction/README.md, this module's source-of-truth documentation (Standards/02_DOCUMENTATION_STANDARDS.md §1). Edit it there, not here -- this file is regenerated on every docs build and any local edit is silently overwritten.

Interaction

Purpose. One framework for every timed, cancellable player action, replacing the original's per-feature hand-rolled timer.Conditional uses. See Documentation/Architecture/10_INTERACTION_FRAMEWORK.md.

Responsibilities. - InteractionRequest / InteractionTarget / IInteractionCondition / InteractionOutcome / InteractionStartResult — the engine-agnostic shape of "a timed action with conditions and a completion effect." See 10_INTERACTION_FRAMEWORK.md §1. - IInteractionRunner / InteractionRunner — the state machine: at most one running interaction per character, ticked to completion or cancelled by a failing condition. A zero-duration request completes synchronously inside TryStart, never occupying the actor's busy slot — see 10_INTERACTION_FRAMEWORK.md §2.1. - The standard conditions library — StillInRange, StillAlive, StillHasItem, TargetUnchanged, NotInterrupted. See 10_INTERACTION_FRAMEWORK.md §5. - InteractionComponent — the per-character replication surface: ticks its own character's entry in IInteractionRunner each frame and mirrors Progress/IsBusy into [Sync] properties. See 10_INTERACTION_FRAMEWORK.md §4. - InteractionModule — registers IInteractionRunner.

Not responsible for. - Any specific verb ("lockpick", "search", "use"). "There is no central verb registry to keep in sync" — see 10_INTERACTION_FRAMEWORK.md §6. This module has no RPC entry point of its own; a verb's owning module (Items, a future property/lockpicking system) builds its own [Rpc.Host] method that constructs an InteractionRequest and calls IInteractionRunner.TryStartLockpickingService in 10_INTERACTION_FRAMEWORK.md §3 is that pattern illustrated, not a type this module ships. - Position, aliveness, item possession, or generic target-state queries — every standard condition (StillInRange, StillAlive, StillHasItem, TargetUnchanged, NotInterrupted) takes a Func<> delegate for the thing it checks, rather than resolving it internally. StillHasItem in particular does not reference IInventory/ItemId (Inventory/Items) directly — doing so would make Interaction depend on Inventory, which already depends on Items, which depends on Interaction for InteractionRequest: a cycle. A caller in Items or Inventory supplies () => inventory.Find(itemId) is not null instead. The other three take delegates because the systems that would supply real answers (a live GameObject.Transform, a health/incapacitation system, a generic "did the target's state change" hook) either aren't reachable from this engine-agnostic module or don't exist yet. See each condition's own file. - Items' reconciliation: ItemBehaviour.CreateUseInteraction (Code/Items/ItemBehaviour.cs) builds InteractionRequests using this framework, but this module has no reference back to Items — the dependency runs one way (Items → Interaction → Character), matching how Inventory already depends on Items without a cycle.

Dependencies. Core (IServiceRegistry, IServiceResolver, IGameLog), Character (Character, CharacterId), the S&box engine (Component, [Sync]) for InteractionComponent.

Public API. - InteractionRequest, InteractionTarget, InteractionTargetKind, IInteractionCondition, InteractionOutcome, InteractionStartResult. - IInteractionRunnerTryStart, Cancel, IsBusy, Progress, Tick. - StillInRange, StillAlive, StillHasItem, TargetUnchanged, NotInterrupted. - InteractionComponent.

Events published. None — an interaction's own OnComplete is the effect; nothing here needs to broadcast that one happened. A verb's owning module publishes its own event from OnComplete if other modules need to react (e.g. a future ItemUsed).

Persistence. None. A running interaction does not survive a disconnect or restart — an acceptable loss for a search/lockpick/equip-length action; see "Future improvements" if this changes.

Future improvements. - StillInRange/StillAlive/TargetUnchanged/NotInterrupted's delegate-based design is meant to be filled in for real once a position/Transform convention, a health system (Needs/Crime, Milestone 7), and a generic target-state hook exist — the conditions themselves do not need to change, only what callers pass them. - No RPC surface exists yet for any real verb (item use, lockpicking) — the first module that needs one builds it, following §3's illustrated pattern. - Interactions do not persist across a disconnect/reconnect. If a verb ever needs that (a long crafting action, say), this is where it would be added — not by making every verb handle it independently.