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.TryStart — LockpickingService 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.
- IInteractionRunner — TryStart, 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.