Table of Contents

Class HotkeySystemRuntimeData

Namespace
FishMMO.Server.Implementation.World.SceneServer
Assembly
FishMMO.Server.dll

Runtime data container for hotkey ingress protection and pending hotkey persistence.

public class HotkeySystemRuntimeData : RuntimeDataContainer, IRuntimeDataContainer<INetworkManagerWrapper, ServerManager, NetworkConnection, IRuntimeDataContainer>, IServerComponent<INetworkManagerWrapper, ServerManager, NetworkConnection, IRuntimeDataContainer>, IHotkeySystemRuntimeData, IRuntimeDataContainer, IServerComponent
Inheritance
HotkeySystemRuntimeData
Implements
Inherited Members

Properties

IngressGuard

Ingress guard for debouncing and rate-limiting hotkey operation requests.

public IngressGuard IngressGuard { get; }

Property Value

IngressGuard

Methods

Clear()

Clears the ingress guard and any staged hotkey writes.

public override void Clear()

DrainHotkeyWrites(List<KeyValuePair<long, HotkeyData[]>>)

Moves every staged snapshot into destination and empties the stage.

public bool DrainHotkeyWrites(List<KeyValuePair<long, HotkeyData[]>> destination)

Parameters

destination List<KeyValuePair<long, HotkeyData[]>>

List to receive the staged snapshots.

Returns

bool

True if anything was drained.

InitializeOnce()

Initializes the hotkey system runtime data, creating the ingress guard.

public override ServerComponentInitializationStatus InitializeOnce()

Returns

ServerComponentInitializationStatus

NextHotkeyVersion()

Produces the next strictly-increasing persistence version for a hotkey row.

public long NextHotkeyVersion()

Returns

long

A monotonic version value.

Remarks

The hotkey upsert is gated WHERE EXCLUDED.version > character_hotkey.version, so a write only lands if it carries a strictly larger version than whatever is already in the row. Nothing in the runtime tracked a hotkey version at all — the load path reads the column and discards it — so the version has to be derived rather than remembered.

DateTime.UtcNow.Ticks supplies that: it is larger than every version any previous session wrote, and the running maximum below keeps it strictly increasing even when two writes land inside one tick of clock resolution. It is deliberately NOT long.MaxValue — the item layer's per-slot poisoning bug (audit CRIT-2) is exactly what happens when a "make sure this write wins" sentinel is stamped into a version column: the row becomes permanently unwritable.

OnDeinitialize()

Deinitializes the runtime data, clearing ingress guard state.

protected override void OnDeinitialize()

StageHotkeyWrite(long, IReadOnlyList<HotkeyData>)

Records the character's current hotkey bar as the next thing to be written to the database, replacing any earlier unwritten snapshot for that character.

public void StageHotkeyWrite(long characterID, IReadOnlyList<HotkeyData> hotkeys)

Parameters

characterID long

The character whose bar changed.

hotkeys IReadOnlyList<HotkeyData>

The character's live hotkey list. Copied, not retained.

Remarks

Coalescing by character is deliberate. Dragging one ability along a twelve-slot bar produces a dozen accepted requests in a couple of seconds, and each one would otherwise be its own round trip to Postgres. Only the newest snapshot can be correct, so keeping only the newest is both cheaper and more accurate.

TryDrainHotkeyWrite(long, out HotkeyData[])

Removes and returns the staged snapshot for one character, if any.

public bool TryDrainHotkeyWrite(long characterID, out HotkeyData[] hotkeys)

Parameters

characterID long

The character to drain.

hotkeys HotkeyData[]

The staged snapshot.

Returns

bool

True if a snapshot was staged for that character.