Class InteractableSystem
- Namespace
- FishMMO.Server.Implementation.World.SceneServer.Interactable
- Assembly
- FishMMO.Server.dll
Server-authoritative dialogue session management. Tracks active dialogue sessions per character, validates client choices, evaluates ECA conditions/actions, and maintains per-character choice bitmasks. All dictionaries are bounded to prevent unbounded memory growth.
[CreateAssetMenu(fileName = "InteractableSystem", menuName = "FishMMO/Server/SceneServer/Interactable System", order = 1)]
[RequiresDataContainer(typeof(InteractableSystemMainThreadQueueData))]
[RequiresDataContainer(typeof(InteractableSystemRuntimeData))]
[RequiresDataContainer(typeof(AsyncWorkerData))]
public class InteractableSystem : ServerBehaviour, IServerBehaviour<INetworkManagerWrapper, ServerManager, NetworkConnection, IServerBehaviour>, IServerComponent<INetworkManagerWrapper, ServerManager, NetworkConnection, IServerBehaviour>, IInteractableSystem, IServerBehaviour, IServerComponent
- Inheritance
-
ObjectScriptableObjectInteractableSystem
- Implements
- Inherited Members
-
ScriptableObject.SetDirty()ScriptableObject.CreateInstance<T>()Object.GetEntityId()Object.GetInstanceID()Object.GetHashCode()Object.InstantiateAsync<T>(T)Object.InstantiateAsync<T>(T, Transform)Object.InstantiateAsync<T>(T, Vector3, Quaternion)Object.InstantiateAsync<T>(T, Transform, Vector3, Quaternion)Object.Instantiate(Object, Vector3, Quaternion)Object.Instantiate(Object, Vector3, Quaternion, Transform)Object.Instantiate(Object)Object.Instantiate(Object, Scene)Object.Instantiate<T>(T, InstantiateParameters)Object.Instantiate<T>(T, Vector3, Quaternion, InstantiateParameters)Object.Instantiate(Object, Transform)Object.Instantiate<T>(T)Object.Instantiate<T>(T, Vector3, Quaternion)Object.Instantiate<T>(T, Vector3, Quaternion, Transform)Object.Instantiate<T>(T, Transform)Object.Destroy(Object)Object.DestroyImmediate(Object)Object.DontDestroyOnLoad(Object)Object.DestroyObject(Object)Object.FindObjectsOfType<T>()Object.FindObjectsByType<T>(FindObjectsSortMode)Object.FindObjectsByType<T>(FindObjectsInactive, FindObjectsSortMode)Object.FindObjectOfType<T>()Object.FindFirstObjectByType<T>()Object.FindAnyObjectByType<T>()Object.FindFirstObjectByType<T>(FindObjectsInactive)Object.FindAnyObjectByType<T>(FindObjectsInactive)Object.FindObjectsByType<T>()Object.FindObjectsByType<T>(FindObjectsInactive)Object.ToString()Object.nameObject.hideFlags
Remarks
Everything the dungeon group finder established carries over unchanged: the queue table,
the per-server pump, the heartbeat, the leash to the board, the panel-close rule, and the
single transaction that forms a match. What differs is the unit of play — a match of N
teams rather than one party — and that a party may queue together. Team assignment is
written into the match rows by TryFormArenaMatchAsync(long, string, int, int, int, int, DateTime, int, ArenaRatingSource, ArenaComposeOptions, CancellationToken);
running the match is the coordinator's job, in InteractableSystem.ArenaMatch.cs.
Pre-made parties. The leader presses Queue as Party. Every member must be connected to this scene server, standing within the leash of the same board, free of instances and live matches, and the party must fit on one team of the format. Then every member gets a queue row carrying the party id, all or none, and each member's own entry on this server with the board as its leash. A member who walks off or closes their panel leaves alone; the rest stay queued as a smaller pre-made.
Fields
DialogueLeaveChoiceIndex
Choice index meaning "leave the conversation" rather than "take choice N".
public const int DialogueLeaveChoiceIndex = -1
Field Value
Remarks
A dialogue node whose choices are all filtered out — every one already taken, or every one's conditions unmet — leaves the client with no buttons at all, and the panel has no close of its own. Escaping out of it left the session open on the server, so the next interaction with anything was validated against a node the player had walked away from. This gives the client a way to say so. It reuses DialogueChoiceBroadcast rather than adding a message, because everything the leave path needs to validate — the session, the node, the range — is already carried on it.
Methods
EndDialogueSession(IPlayerCharacter)
Ends the dialogue session for the specified character without sending a broadcast.
public void EndDialogueSession(IPlayerCharacter character)
Parameters
characterIPlayerCharacterThe player character whose session to end.
InitializeOnce()
Initializes the InteractableSystem: validates dependencies, registers all network broadcast handlers, subscribes to dialogue events, and clamps configuration values.
public override ServerComponentInitializationStatus InitializeOnce()
Returns
- ServerComponentInitializationStatus
Initialization status indicating success or failure.
LearnAbility(IAbilityController, AbilityTemplate, List<int>)
Creates and learns a new crafted ability, then schedules asynchronous persistence.
public Ability LearnAbility(IAbilityController abilityController, AbilityTemplate abilityTemplate, List<int> abilityEvents)
Parameters
abilityControllerIAbilityControllerAbility controller receiving the new ability.
abilityTemplateAbilityTemplateBase ability template used for creation.
abilityEventsList<int>Selected ability event identifiers to attach.
Returns
- Ability
The created ability instance.
LearnAbilityEvent<T>(NetworkConnection, IPlayerCharacter, T)
Learns an ability event template and synchronizes the result to the client.
public MerchantPurchaseFailure LearnAbilityEvent<T>(NetworkConnection conn, IPlayerCharacter character, T template) where T : AbilityEvent
Parameters
connNetworkConnectionClient connection to notify.
characterIPlayerCharacterCharacter learning the ability event.
templateTAbility event template to learn.
Returns
- MerchantPurchaseFailure
Why the learn was refused, or None.
Type Parameters
TConcrete ability event type.
LearnAbilityTemplate<T>(NetworkConnection, IPlayerCharacter, T)
Learns a base ability template and synchronizes the result to the client.
public MerchantPurchaseFailure LearnAbilityTemplate<T>(NetworkConnection conn, IPlayerCharacter character, T template) where T : BaseAbilityTemplate
Parameters
connNetworkConnectionClient connection to notify.
characterIPlayerCharacterCharacter learning the ability.
templateTAbility template to learn.
Returns
- MerchantPurchaseFailure
Why the learn was refused, or None.
Type Parameters
TConcrete base ability template type.
OnDeinitialize()
Deinitializes the InteractableSystem: drains queued actions, clears ingress guards, unregisters network broadcast handlers, unsubscribes from dialogue events, and clears dialogue session state.
public override void OnDeinitialize()
OnInteractNPC(IPlayerCharacter, IInteractable)
Updates an NPC to face the interacting character and enter idle state.
public void OnInteractNPC(IPlayerCharacter character, IInteractable interactable)
Parameters
characterIPlayerCharacterInteracting player character.
interactableIInteractableInteracted NPC object.
OnServerAbilityCraftBroadcastReceived(NetworkConnection, AbilityCraftBroadcast, Channel)
Handles an incoming ability crafting request and validates cost, ownership, and selected events.
public void OnServerAbilityCraftBroadcastReceived(NetworkConnection conn, AbilityCraftBroadcast msg, Channel channel)
Parameters
connNetworkConnectionRequesting client connection.
msgAbilityCraftBroadcastAbility crafting request payload.
channelChannelTransport channel used by FishNet.
OnServerArenaHistoryRequestReceived(NetworkConnection, ArenaHistoryRequestBroadcast, Channel)
The player's recent matches, for the board.
public void OnServerArenaHistoryRequestReceived(NetworkConnection conn, ArenaHistoryRequestBroadcast msg, Channel channel)
Parameters
connNetworkConnectionmsgArenaHistoryRequestBroadcastchannelChannel
OnServerArenaLeaderboardRequestReceived(NetworkConnection, ArenaLeaderboardRequestBroadcast, Channel)
The season leaderboard, for the board.
public void OnServerArenaLeaderboardRequestReceived(NetworkConnection conn, ArenaLeaderboardRequestBroadcast msg, Channel channel)
Parameters
connNetworkConnectionmsgArenaLeaderboardRequestBroadcastchannelChannel
OnServerArenaProfileRequestReceived(NetworkConnection, ArenaProfileRequestBroadcast, Channel)
The player's season standing and queue lock, for the board.
public void OnServerArenaProfileRequestReceived(NetworkConnection conn, ArenaProfileRequestBroadcast msg, Channel channel)
Parameters
connNetworkConnectionmsgArenaProfileRequestBroadcastchannelChannel
OnServerArenaQueueBroadcastReceived(NetworkConnection, ArenaQueueBroadcast, Channel)
Handles a request to queue for an arena, alone or as a party.
public void OnServerArenaQueueBroadcastReceived(NetworkConnection conn, ArenaQueueBroadcast msg, Channel channel)
Parameters
connNetworkConnectionmsgArenaQueueBroadcastchannelChannel
OnServerDungeonFinderCreateBroadcastReceived(NetworkConnection, DungeonFinderCreateBroadcast, Channel)
Handles a request to open a new instance of a dungeon.
public void OnServerDungeonFinderCreateBroadcastReceived(NetworkConnection conn, DungeonFinderCreateBroadcast msg, Channel channel)
Parameters
connNetworkConnectionRequesting client connection.
msgDungeonFinderCreateBroadcastWhich entrance, which difficulty, and whether to list it.
channelChannelTransport channel used by FishNet.
OnServerDungeonFinderJoinBroadcastReceived(NetworkConnection, DungeonFinderJoinBroadcast, Channel)
Handles a request to join an instance somebody else has opened.
public void OnServerDungeonFinderJoinBroadcastReceived(NetworkConnection conn, DungeonFinderJoinBroadcast msg, Channel channel)
Parameters
connNetworkConnectionRequesting client connection.
msgDungeonFinderJoinBroadcastWhich entrance and which instance.
channelChannelTransport channel used by FishNet.
OnServerDungeonFinderListBroadcastReceived(NetworkConnection, DungeonFinderListBroadcast, Channel)
Answers a client browsing the instances joinable at one difficulty.
public void OnServerDungeonFinderListBroadcastReceived(NetworkConnection conn, DungeonFinderListBroadcast msg, Channel channel)
Parameters
connNetworkConnectionRequesting client connection.
msgDungeonFinderListBroadcastWhich entrance and which difficulty.
channelChannelTransport channel used by FishNet.
Remarks
Every exit sends a DungeonFinderListResultBroadcast, including the refusals and the empty lists. The panel disables its list and its Refresh button while a request is outstanding — the guard that stops the button being held down — so a handler that returned silently would leave the panel inert for the rest of its life.
Not gated on character state. Reading a list is not a move, and a player in combat who cannot see the list can see it by walking ten metres away; refusing would hide information rather than prevent an action.
OnServerGroupFinderLeaveBroadcastReceived(NetworkConnection, GroupFinderLeaveBroadcast, Channel)
Handles a request to leave the queue.
public void OnServerGroupFinderLeaveBroadcastReceived(NetworkConnection conn, GroupFinderLeaveBroadcast msg, Channel channel)
Parameters
connNetworkConnectionmsgGroupFinderLeaveBroadcastchannelChannel
Remarks
Refused once matched. The group has formed and this character is already in its party; backing out now would leave a party with a member who never arrives. The client hides its Leave control at that point, so reaching this is a race with the pump, not a click.
OnServerGroupFinderQueueBroadcastReceived(NetworkConnection, GroupFinderQueueBroadcast, Channel)
Handles a request to be found a group for one dungeon at one difficulty.
public void OnServerGroupFinderQueueBroadcastReceived(NetworkConnection conn, GroupFinderQueueBroadcast msg, Channel channel)
Parameters
connNetworkConnectionmsgGroupFinderQueueBroadcastchannelChannel
Remarks
Validated like the finder's other requests — the player must be standing at the entrance — but not gated on character state, because joining a queue is not a move. The move comes later, from the pump, and is gated then.
OnUpdate(float)
Called every frame. Drains a bounded number of queued main-thread actions and sweeps stale debounce entries.
protected override void OnUpdate(float deltaTime)
Parameters
deltaTimefloatTime elapsed since the last frame.
SendNewItemBroadcast<T>(T, ICharacter, IInventoryController, Item)
Grants an item to a character's inventory through the inventory system's grant funnel: placed, broadcast to the owner, persisted, identity assigned.
public bool SendNewItemBroadcast<T>(T conn, ICharacter character, IInventoryController inventoryController, Item newItem)
Parameters
connTcharacterICharacterinventoryControllerIInventoryControllernewItemItem
Returns
Type Parameters
T
Remarks
The body that used to live here — place, broadcast, persist — is now
CharacterInventorySystem.TryGrantItem, because it was one of three copies (the
quest and achievement systems had their own) and only this one handed the item its
database identity. A server without an inventory system refuses the grant rather than
persisting without a write-back: an item that never learns its id is an item that cannot
be equipped, used or moved, and the caller's own fallback (put it back on the corpse,
refund the purchase) is the better outcome.
StartDialogueSession(IPlayerCharacter, ISceneObject, IDialogueInteractable)
Starts a new dialogue session for the character from an interactable interaction. Evaluates the start node's conditions and sends DialogueStartBroadcast to the client.
public void StartDialogueSession(IPlayerCharacter character, ISceneObject sceneObject, IDialogueInteractable dialogue)
Parameters
characterIPlayerCharacterThe player character starting the dialogue.
sceneObjectISceneObjectThe scene object hosting the interactable.
dialogueIDialogueInteractableThe dialogue interactable.
StartECADialogueSession(IPlayerCharacter, DialogueTemplate, IInteractable)
Starts a new dialogue session triggered by an ECA action.
public void StartECADialogueSession(IPlayerCharacter character, DialogueTemplate template, IInteractable interactable = null)
Parameters
characterIPlayerCharacterThe player character starting the dialogue.
templateDialogueTemplateThe dialogue template to use.
interactableIInteractableThe interactable the dialogue is anchored to, or null.
Remarks
interactable is what anchors the conversation to a place in the
world. Every dialogue in the game reaches the server through this method — the
interactable-typed StartDialogueSession(IPlayerCharacter, ISceneObject, IDialogueInteractable) overload has no callers — so when
this passed a hard-coded 0 for the scene object ID, every session was
unanchored and the choice handler's range check was dead code for all of them. A player
could open a conversation, walk to the far side of the zone, and keep taking choices —
including any that hand out items or currency.