Documentation / Tile Tick Core RPG / Programmer

Interaction Pipeline

How context actions become validated server-authoritative interactions, including custom action IDs and handlers.

Interactions are an intent pipeline: the client chooses a stable action ID and target, the server owns approach/range/staleness validation, and a registered handler executes only after the request remains valid.

Two layers you will see

LayerKey typesPurpose
Local/content contextIContextActionProvider, ContextAction, WorldObjectInteractableBuild the actions a player can see/select.
Server executionInteractionActionId, ServerInteractionPipeline, IServerInteractionHandlerValidate network intent, approach target, revalidate, execute authoritatively.

Stable action IDs

InteractionActionId is string-backed on purpose. Built-ins include core.attack, core.talk_to, core.open_shop, core.open_bank, core.pick_up, core.use_object, door actions, and skill-specific IDs. Custom IDs should be lowercase, namespaced, and stable once shipped.

using GreenCloakGames.TileTickRPGCore.Multiplayer.Contracts.Interaction;

public static class MyInteractionIds
{
    public static readonly InteractionActionId HarvestCrystal =
        new InteractionActionId("mygame.harvest_crystal");
}

Custom server handler shape

using GreenCloakGames.TileTickRPGCore.Multiplayer.Contracts.Interaction;
using GreenCloakGames.TileTickRPGCore.Multiplayer.NGO;
using GreenCloakGames.TileTickRPGCore.Multiplayer.NGO.Interaction;

public sealed class HarvestCrystalHandler : IServerInteractionHandler
{
    public InteractionActionId ActionId => MyInteractionIds.HarvestCrystal;

    public bool CanBegin(NetworkPlayer requester, INetworkInteractable target,
        out InteractionRejectionReason reason)
    {
        // Only action-specific checks belong here.
        // Ownership, target existence, interactability and approach are pipeline concerns.
        reason = InteractionRejectionReason.None;
        return true;
    }

    public InteractionResult Execute(NetworkPlayer requester, INetworkInteractable target)
    {
        // Mutate authoritative gameplay state here or call a shared service.
        return new InteractionResult
        {
            Status = InteractionResultStatus.Completed,
            Reason = InteractionRejectionReason.None,
            ActionIdValue = ActionId.Value
        };
    }
}

The pipeline deliberately owns shared concerns so handlers stay small. Do not reimplement generic ownership, approach, cancellation, or stale-request logic inside every action.

Local world object handlers

IWorldObjectActionHandler remains a useful content/runtime seam with CanExecute(RPGUnitBrain) and Execute(RPGUnitBrain). In networked gameplay, make sure the actual mutation is reached through the authoritative server path rather than directly from a client context menu.

Interaction flow

IContextActionProvider exposes action
Owner selects action
Network request carries stable action + target identity
ServerInteractionPipeline validates
Approach movement if required
Revalidate target/action/range
IServerInteractionHandler.Execute
Owner receives InteractionResult
Replicated gameplay state updates presentation