Table of Contents

Class ServerBehaviour

Namespace
FishMMO.Server.Implementation
Assembly
FishMMO.Server.dll

Base class for all server-side behaviours in the FishMMO server architecture. Provides registration, initialization, and lifecycle management for server behaviours.

public abstract class ServerBehaviour : ScriptableObject, IServerBehaviour<INetworkManagerWrapper, ServerManager, NetworkConnection, IServerBehaviour>, IServerBehaviour, IServerComponent<INetworkManagerWrapper, ServerManager, NetworkConnection, IServerBehaviour>, IServerComponent
Inheritance
Object
ScriptableObject
ServerBehaviour
Implements
IServerBehaviour<INetworkManagerWrapper, ServerManager, NetworkConnection, IServerBehaviour>
IServerComponent<INetworkManagerWrapper, ServerManager, NetworkConnection, IServerBehaviour>
Derived
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

Properties

Initialized

Indicates whether this behaviour has been initialized.

public bool Initialized { get; }

Property Value

bool

Server

Reference to the server instance associated with this behaviour.

public IServer<INetworkManagerWrapper, NetworkConnection, IServerBehaviour> Server { get; }

Property Value

IServer<INetworkManagerWrapper, NetworkConnection, IServerBehaviour>

ServerManager

Reference to the server manager instance associated with this behaviour.

public ServerManager ServerManager { get; }

Property Value

ServerManager

Methods

Deinitialize()

Deinitializes this behaviour, calling OnDeinitialize and clearing references.

public void Deinitialize()

DisconnectWithNotice(NetworkConnection, DisconnectNoticeReason, bool)

Closes conn after telling it why.

protected void DisconnectWithNotice(NetworkConnection conn, DisconnectNoticeReason reason, bool terminal = false)

Parameters

conn NetworkConnection

Connection to close.

reason DisconnectNoticeReason

What to tell the client.

terminal bool

True when reconnecting cannot help, so the client abandons its retry loop instead of spending it on an outcome that cannot change. See Terminal.

Remarks

Use this instead of NetworkConnection.Kick for any disconnect the server decides on. FishNet does not deliver a kick reason to the client, so a plain kick drops the player back at the login screen with nothing to go on — unable to tell a transient routing hiccup from a character they will never be able to log in to.

Disconnect(false) rather than Kick is load-bearing: Kick stops the transport immediately and throws away everything still queued for this tick, including the notice written on the line above. Disconnect(false) flushes the tick first, marks the connection invalid so nothing further is sent or received on it, and closes roughly 100ms later — so the notice arrives and the connection is still shut out of the server just as promptly.

DrainMainThreadQueue<TQueue>(int, bool)

Drain the specified main-thread queue for this server behaviour.

protected void DrainMainThreadQueue<TQueue>(int maxActions, bool drainAll) where TQueue : class, IMainThreadQueueData

Parameters

maxActions int
drainAll bool

Type Parameters

TQueue

EndInFlightRequest<TRuntime>(NetworkConnection, Action<TRuntime>)

Generic helper to release an in-flight slot from a runtime data container. Caller supplies an action that performs the remove/cleanup on the runtime data.

protected void EndInFlightRequest<TRuntime>(NetworkConnection conn, Action<TRuntime> onEnd) where TRuntime : class, IRuntimeDataContainer

Parameters

conn NetworkConnection
onEnd Action<TRuntime>

Type Parameters

TRuntime

EnqueuePersistence(Func<Task>, long, string)

Enqueues persistence work through the async worker. If the bounded channel is full, runs the work directly on the thread pool as a fallback to prevent data loss.

Use this instead of TryEnqueueAsyncWork(Func<Task>, long, string) for post-processing persistence where in-memory state has already been committed and the database write must not be silently dropped.

protected bool EnqueuePersistence(Func<Task> work, long entityKey = 0, string callerName = null)

Parameters

work Func<Task>
entityKey long
callerName string

Returns

bool

true if enqueued normally; false if the fallback path was used.

InitializeOnce()

Called once to initialize the behaviour. Must be implemented by derived classes.

public abstract ServerComponentInitializationStatus InitializeOnce()

Returns

ServerComponentInitializationStatus

Remarks

Behaviours that need to await I/O (database registration, for example) must override InitializeOnceAsync(CancellationToken) instead of blocking in here. The Unity main thread must never block on I/O: it is the thread that drains async continuations, so blocking it can deadlock startup before the transport ever binds.

InitializeOnceAsync(CancellationToken)

Asynchronous initialization hook. The default implementation simply runs the synchronous InitializeOnce(), so behaviours with no I/O need not change.

public virtual Task<ServerComponentInitializationStatus> InitializeOnceAsync(CancellationToken cancellationToken)

Parameters

cancellationToken CancellationToken

Cancelled when the server shuts down mid-startup.

Returns

Task<ServerComponentInitializationStatus>

The initialization status.

Remarks

Overrides are invoked on the Unity main thread. Awaiting without ConfigureAwait(false) resumes on the main thread, so Unity APIs remain safe to touch after an await.

OnDeinitialize()

Called when the behaviour is being deinitialized. Must be implemented by derived classes.

public abstract void OnDeinitialize()

OnLateUpdate(float)

Called by the Server's LateUpdate to provide mutable data and perform per-frame logic. Performs a guard check to ensure the behaviour is initialized and the server reference is valid, then delegates to OnUpdate(float) for subclass-specific logic.

public void OnLateUpdate(float deltaTime)

Parameters

deltaTime float

Time elapsed since last frame.

OnRemoteConnectionStopped(NetworkConnection)

Called when a remote connection stops. Override in derived classes to perform per-connection cleanup (e.g. clearing in-flight requests, caches, queue entries). Systems must call SubscribeToConnectionEvents() in InitializeOnce() and UnsubscribeFromConnectionEvents() in OnDeinitialize() to use this.

protected virtual void OnRemoteConnectionStopped(NetworkConnection conn)

Parameters

conn NetworkConnection

OnUpdate(float)

Override this method in derived classes that need per-frame updates. Guaranteed to run only when the behaviour is initialized and Server is non-null.

protected virtual void OnUpdate(float deltaTime)

Parameters

deltaTime float

Time elapsed since last frame.

SendServerBusy(NetworkConnection)

Sends a ServerBusyBroadcast to the connection, informing the client that the server cannot process the request right now. Uses Unreliable channel to avoid amplifying server-side send-queue pressure.

protected void SendServerBusy(NetworkConnection conn)

Parameters

conn NetworkConnection

SubscribeToConnectionEvents()

Subscribes to FishNet.Managing.Server.ServerManager.OnRemoteConnectionState and dispatches disconnect events to OnRemoteConnectionStopped(NetworkConnection).

protected void SubscribeToConnectionEvents()

TryBeginInFlightRequest<TRuntime>(NetworkConnection, Func<TRuntime, bool>)

Generic helper to attempt acquiring an in-flight slot from a runtime data container. Caller supplies a lambda that performs the actual add (e.g. runtimeData.InFlightRequests.TryAdd(conn.ClientId, 0)).

protected bool TryBeginInFlightRequest<TRuntime>(NetworkConnection conn, Func<TRuntime, bool> tryAdd) where TRuntime : class, IRuntimeDataContainer

Parameters

conn NetworkConnection
tryAdd Func<TRuntime, bool>

Returns

bool

Type Parameters

TRuntime

TryEnqueueAsyncWork(Func<Task>, NetworkConnection, long, string)

Enqueues async work and sends ServerBusyBroadcast to the client on failure. Use this for broadcast handlers where the client expects a response.

protected bool TryEnqueueAsyncWork(Func<Task> work, NetworkConnection conn, long entityKey = 0, string callerName = null)

Parameters

work Func<Task>

The async work to enqueue.

conn NetworkConnection

The client connection to notify on failure.

entityKey long

Optional entity key for consistent hashing.

callerName string

Caller name for diagnostics.

Returns

bool

True if the work was enqueued successfully.

TryEnqueueAsyncWork(Func<Task>, long, string)

Enqueue a unit of asynchronous work to the centralized AsyncWorker. Returns false when rejected. Logs warnings using the concrete behaviour name for diagnostics.

protected bool TryEnqueueAsyncWork(Func<Task> work, long entityKey = 0, string callerName = null)

Parameters

work Func<Task>
entityKey long
callerName string

Returns

bool

TryEnqueueGuardedAsyncWork(Func<Task>, Action<long>, long, long, string)

Enqueues async work that guarantees an ingress guard is released (via releaseGuard) when the work completes, even if it throws.

protected bool TryEnqueueGuardedAsyncWork(Func<Task> work, Action<long> releaseGuard, long guardKey, long entityKey = 0, string callerName = null)

Parameters

work Func<Task>
releaseGuard Action<long>
guardKey long
entityKey long
callerName string

Returns

bool

TryEnqueueMainThread<TQueue>(Action)

Enqueue an action to the specified main-thread queue.

protected bool TryEnqueueMainThread<TQueue>(Action action) where TQueue : class, IMainThreadQueueData

Parameters

action Action

Returns

bool

Type Parameters

TQueue

TryGetDbService<T>(out T)

Attempts to resolve a database service from the server's database service registry. Encapsulates the null-check on Server.Database.ServiceRegistry and the TryGet call.

protected bool TryGetDbService<T>(out T service) where T : class

Parameters

service T

Returns

bool

Type Parameters

T

UnsubscribeFromConnectionEvents()

Unsubscribes from FishNet.Managing.Server.ServerManager.OnRemoteConnectionState.

protected void UnsubscribeFromConnectionEvents()