Table of Contents

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
Object
ScriptableObject
InteractableSystem
Implements
IServerBehaviour<INetworkManagerWrapper, ServerManager, NetworkConnection, IServerBehaviour>
IServerComponent<INetworkManagerWrapper, ServerManager, NetworkConnection, IServerBehaviour>
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.name
Object.hideFlags

Remarks

The corpse is the authority throughout. The client sends a scene object ID and a slot index and nothing else — never an item ID, a template, or an amount — so the worst a forged request can do is name a slot that is empty or a corpse it has no rights to, both of which are refused here.

Fields

DialogueLeaveChoiceIndex

Choice index meaning "leave the conversation" rather than "take choice N".

public const int DialogueLeaveChoiceIndex = -1

Field Value

int

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

character IPlayerCharacter

The 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

abilityController IAbilityController

Ability controller receiving the new ability.

abilityTemplate AbilityTemplate

Base ability template used for creation.

abilityEvents List<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 void LearnAbilityEvent<T>(NetworkConnection conn, IPlayerCharacter character, T template) where T : AbilityEvent

Parameters

conn NetworkConnection

Client connection to notify.

character IPlayerCharacter

Character learning the ability event.

template T

Ability event template to learn.

Type Parameters

T

Concrete ability event type.

LearnAbilityTemplate<T>(NetworkConnection, IPlayerCharacter, T)

Learns a base ability template and synchronizes the result to the client.

public void LearnAbilityTemplate<T>(NetworkConnection conn, IPlayerCharacter character, T template) where T : BaseAbilityTemplate

Parameters

conn NetworkConnection

Client connection to notify.

character IPlayerCharacter

Character learning the ability.

template T

Ability template to learn.

Type Parameters

T

Concrete 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

character IPlayerCharacter

Interacting player character.

interactable IInteractable

Interacted 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

conn NetworkConnection

Requesting client connection.

msg AbilityCraftBroadcast

Ability crafting request payload.

channel Channel

Transport channel used by FishNet.

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

conn NetworkConnection

Requesting client connection.

msg DungeonFinderCreateBroadcast

Which entrance, which difficulty, and whether to list it.

channel Channel

Transport 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

conn NetworkConnection

Requesting client connection.

msg DungeonFinderJoinBroadcast

Which entrance and which instance.

channel Channel

Transport 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

conn NetworkConnection

Requesting client connection.

msg DungeonFinderListBroadcast

Which entrance and which difficulty.

channel Channel

Transport 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.

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

deltaTime float

Time elapsed since the last frame.

SendNewItemBroadcast<T>(T, ICharacter, IInventoryController, Item)

Attempts to add items to a characters inventory controller and broadcasts the update to the client. DB persistence is fire-and-forget async.

public bool SendNewItemBroadcast<T>(T conn, ICharacter character, IInventoryController inventoryController, Item newItem)

Parameters

conn T
character ICharacter
inventoryController IInventoryController
newItem Item

Returns

bool

Type Parameters

T

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

character IPlayerCharacter

The player character starting the dialogue.

sceneObject ISceneObject

The scene object hosting the interactable.

dialogue IDialogueInteractable

The 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

character IPlayerCharacter

The player character starting the dialogue.

template DialogueTemplate

The dialogue template to use.

interactable IInteractable

The 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.