When a packet arrives at a Terbin server,Documentation Index
Fetch the complete documentation index at: https://mintlify.com/FarlandsModdingTeam/TerbinProyect/llms.txt
Use this file to discover all available pages before exploring further.
TerbinCommunicator calls the OnRecive event, which (in a typical setup) calls TerbinExecutableManager.DispatchAsync. The dispatcher looks up the packet’s IdArray action key in a ConcurrentDictionary and invokes every handler registered for that key. This wiring is done entirely through reflection by scanning for methods decorated with [TerbinExecutable].
The [TerbinExecutable] Attribute
static method that should handle an incoming packet. The attribute accepts the action key as:
params byte[]— pass raw byte literals directly.params object[]— pass enum values; they are converted tobyteinternally viaSerialineitor.CastToByte.
Bytes
0–9 correspond to CodeTerbinProtocol values and are reserved for internal protocol operations (Stop, Response, Load, Prolong, Solicit, ExceptionAlert). Do not use action keys that begin with bytes in this range for application handlers.Handler Signature — TerbinExecutableDelegate
The dispatcher enforces a strict method signature. Any method that does not match is silently skipped during assembly scanning:
Header pHead— the packet header carryingIdRequest,OrderRequest,Status, andIdMemory.byte[] pParameters— the fully reassembled payload (fragments already merged by the time this is called).CancellationToken pToken— the per-action cancellation token; check it before starting long work.- Return
Task<InfoResponse?>— return a non-nullInfoResponseto send a reply, ornullfor fire-and-forget handlers.
TerbinExecutableHelper.IsFirmParameters and IsFirmReturn validate these constraints during registration.
Action Keys and ByteArrayKey
The dispatcher stores handlers in a ConcurrentDictionary<IEquatable<IEnumerable<byte>>, List<TerbinExecutableDelegate>>. The key type used is ByteArrayKey — a read-only struct that wraps a byte[] and implements content-based equality and hashing:
new ByteArrayKey(new byte[] { 250, 30 }) and new ByteArrayKey(new byte[] { 250, 30 }) are treated as the same dictionary key, regardless of array reference. IdArray implicitly converts to and from ByteArrayKey.
For application services the typical pattern is two bytes: (byte)CodeServices.X and (byte)CodeServicesSection.Y, giving a flat two-byte key space:
Registering Handlers
TerbinExecutor.Register(Assembly) — Preferred
static methods carrying [TerbinExecutable], validates their signature, creates a Func<Header, byte[], CancellationToken, Task<InfoResponse?>> delegate, and calls TerbinExecutableManager.Register for each attribute. Call this once at startup:
Manual TerbinExecutableManager.Register
TerbinExecutableManager.Unregister
true if the key existed.
TerbinExecutableManager — Static Façade
TerbinExecutableManager is a process-wide static singleton backed by an ExecutableDispatcher instance. All calls delegate to the internal dispatcher:
ExecutableDispatcher Internals
ExecutableDispatcher is the concrete class that TerbinExecutableManager wraps:
CancellationTokenSource stored in _activeExecutionsByAction. This CTS is passed to every handler invocation for that key, enabling action-level cancellation.
DispatchAsync Flow
Action Lookup
Looks up
pActions in _handlers. If not found, releases any memory slot (TerbinMemoryHelper.TryReleaseMemory) and returns InfoResponse.Create(pHead.IdRequest, CodeStatus.ActionNotFound).Status Routing
Inspects
pHead.Status:Execute— proceed normally (this is the common fast path).CheckExecution— returnInfoResponse.CreateSuccesimmediately, without invoking handlers. This is the fragmentation preflight handshake.CancelByAction— cancel the CTS for this action and return success orActionNotInitiated.CancelByRequest— reserved for future per-request cancellation.
Handler Invocation
Retrieves the CTS from
_activeExecutionsByAction and passes its token to TerbinExecutableHelper.ExecutionList, which starts all handlers concurrently and returns the first non-null InfoResponse?.CheckExecution Handshake
Before streaming fragments for a large payload, the sender calls Communicate with CodeStatus.CheckExecution. The dispatcher returns immediately with CodeStatus.Succes (handler exists) or CodeStatus.ActionNotFound (handler missing). This prevents wasting a memory slot on an action that will never be dispatched.
Cancellation
Send a packet withCodeStatus.CancelByAction to the same action key to interrupt its handler. The dispatcher calls _activeExecutionsByAction[key].Cancel(), which propagates to the CancellationToken that was passed to the handler:
pToken.IsCancellationRequested at checkpoints: