Skip to main content

Event Snapshots

Verification boundary

This page describes the committed source guideline. It skips certifying revision-sensitive RuneLite UI, packet, or in-game outcomes; treat those as live-client verification pending unless the page records direct evidence.

com.n3plugins.sdk.events exposes passive recent-event snapshots for callers requiring observation without owning RuneLite event-bus wiring. PacketUtils registers SdkEvents with RuneLite's event bus during suite startup and unregisters it during shutdown.

note

This provides passive observation, not polling or an action surface. Consumers read bounded recent snapshots. They do not click, walk, attack, or mutate game state through these APIs.

SdkEvents

SdkEvents.xpGained().forEach(event ->
log.debug("{} gained {}", event.getSkill(), event.getGainedXp()));

List<NpcLifecycleEvent> bankers = SdkEvents.npcSpawns().stream()
.filter(event -> "Banker".equals(event.getName()))
.collect(Collectors.toList());

Methods:

  • xpGained() - recent XpGainedEvent snapshots.
  • inventoryDeltas() - recent InventoryDeltaEvent snapshots.
  • inventoryDeltaCursor() - latest monotonic inventory-delta sequence.
  • inventoryDeltasAfter(cursor) - immutable ordered InventoryDeltaBatch with a safe next cursor and explicit retention-gap detection.
  • npcSpawns() - recent NPC lifecycle snapshots where isSpawned() returns true.
  • npcDespawns() - recent NPC lifecycle snapshots where isSpawned() returns false.
  • npcLifecycle() - recent NPC spawn and despawn snapshots.
  • animationChanges() - recent AnimationChangeEvent snapshots.
  • projectileMovements() - recent ProjectileMovementEvent snapshots.
  • clear() - clears retained snapshots and tracker baselines.
  • trackerForTesting() - exposes the shared tracker for focused tests.

PacketUtils runtime wiring owns register(eventBus, client) and unregister(eventBus). Ordinary SDK consumers must not register their own suite-level tracker.

Snapshot Types

All event snapshot types include client tick and wall-clock timestamp through the shared SdkEventSnapshot base.

  • XpGainedEvent - skill, previous XP, current XP, gained XP, real level, and boosted level.
  • InventoryDeltaEvent - monotonic sequence, container id, slot, item id, previous quantity, current quantity, and delta quantity. Slot replacement emits removal before addition.
  • NpcLifecycleEvent - spawn/despawn flag, NPC id, NPC index, name, world location, and local location.
  • AnimationChangeEvent - actor name, animation id, world location, and local location.
  • ProjectileMovementEvent - projectile id, source world point, target world point, target local point, target z, source actor name, and target actor name.

Ownership Detail

SdkEventTracker provides the RuneLite event-bus subscriber behind SdkEvents. It records bounded recent snapshots with a default capacity of 128 per event kind. It remains public for focused tests and explicit runtime ownership, but normal callers must consume the static SdkEvents facade.

Cursor consumers must persist InventoryDeltaBatch.getNextCursor() exactly once per observation cycle. isGapDetected() means output may have been lost and requires snapshot resynchronization; it is never a successful transfer postcondition. Login, hop, and connection-loss states invalidate current-session inventory, equipment, and bank knowledge and clear retained item deltas. The sequence itself is not reset, preventing an old cursor from accidentally matching a later session. Unknown containers remain distinct from known-empty containers.

Semantic Simulation Foundation

The same package contains the generic foundation for semantic event simulation. EventEnvelope<T> carries a stable payload, deterministic sequence and tick metadata, source provenance, and optional scenario/correlation metadata. Transport-specific event classes remain observations rather than the recorded scenario model.

dispatch.StimulusDispatcher routes an envelope to the first supporting StimulusHandler using an explicit DispatchMode. It prevents re-accepting the same event ID in one session. scenario.ScenarioRunner operates tick-driven: it dispatches once, then evaluates state verification on later ticks. It never treats posting an event as proof that the target processed it.

Dispatch Sub-package (sdk.events.dispatch)

ClassRole
StimulusDispatcherRoutes an EventEnvelope to the first matching StimulusHandler; deduplicates by event ID per session.
StimulusHandlerHandler interface with supports(envelope) and handle(envelope, context).
DispatchModeExplicit enum: SYNC, ASYNC, or DRY_RUN.
DispatchContextCarries dispatcher metadata, mode, and session state into handlers.
DispatchResultOutcome of dispatch: HANDLED, NO_HANDLER, DUPLICATE, or error.

Scenario Sub-package (sdk.events.scenario)

ClassRole
ScenarioImmutable sequence of ScenarioStep entries, each with an envelope and optional verification conditions.
ScenarioStepOne dispatch-then-verify unit: envelope + List<VerificationCondition>.
ScenarioRunnerTick-driven executor: dispatches a step once, then evaluates verification on subsequent ticks.
ScenarioResultAggregated pass/fail outcome with per-step VerificationResult entries.

Verification Sub-package (sdk.events.verify)

ClassRole
VerificationConditionFunctional predicate evaluated after dispatch to confirm expected state.
VerificationResultPer-condition outcome: PASSED, FAILED, or SKIPPED, with an optional message.

Replay Sub-package (sdk.events.replay)

EventReplayService replays a recorded EventTimeline (ordered list of EventEnvelope entries with inter-event delays) through the StimulusDispatcher. ReplayPolicy configures timing fidelity, error handling, and whether to skip or abort on handler failures. ReplayResult reports the timeline completion status, per-envelope outcomes, and elapsed wall-clock time.

Packet Transport Sub-package (sdk.events.packet)

PacketReplayHandler provides a StimulusHandler specialized for packet-debug replay scenarios. PacketReplayStimulus wraps packet-trace payload data into an EventEnvelope. PacketReplayTransport bridges packet replay envelopes into the dispatcher without requiring a live packet connection.

Event Lab UI (sdk.events.ui)

EventLabController provides a thin controller for an offline Event Lab view. Target-plugin mutation handlers and full Swing views remain future scope. The controller exposes the replay/scenario/dispatch wiring for test harness and developer tool integration.

State Fixtures (sdk.events.fixture)

ClassRole
StateFixtureServiceManages named StateSnapshot fixtures for deterministic scenario setup.
StateSnapshotImmutable capture of relevant state fields for fixture comparison.
StateTransactionAtomic apply/rollback of state changes during scenario execution.

Fixtures allow offline tests and cloud agents to set up known state before running scenarios without requiring a live RuneLite client.

OSRS-TCG Integration (sdk.integration.osrstcg)

OsrsTcgCapabilities defines the guarded capability surface for OSRS Trading Card Game plugin-message interop. OsrsTcgPluginMessageClient implements a thin PluginMessage-based communication client. OsrsTcgPluginMessageTransport bridges TCG events into the event dispatch system.

note

The OSRS-TCG integration provides a development-interop guideline surface. It skips carrying OSRS-TCG implementation dependencies or exposing TCG-specific game mutations through the n3 SDK.

Break Handlers run active-only.