subtr-actor-player
v0.3.1
Published
Replay player library for subtr-actor Rocket League replay workflows
Maintainers
Readme
subtr-actor-player
subtr-actor-player is the reusable replay player library package for this repository.
Installation
npm install subtr-actor-player threethree is a peer dependency. The player also depends on the low-level
@colonelpanic8/subtr-actor bindings package.
It provides:
- a typed replay normalization layer on top of
get_replay_frames_data() - worker-backed replay loading with optional progress callbacks
- a built-in replay loading overlay helper for DOM consumers
- a
ReplayPlayerclass with imperative playback and camera APIs - a
ReplayPlaylistPlayerwrapper for back-to-back clip playback across replays - a plugin host for optional scene and UI extensions
- state snapshots and change subscriptions so callers can build their own controls
The player exposes camera state as data, not fixed UI assumptions. The built-in camera API is a free camera when no player is attached and an attached chase camera with tunable distance scaling when a player is selected.
Transient replay semantics are exposed the same way. ReplayPlayerState and
ReplayPlaylistPlayerState include activeMetadata, which is currently used
for semantic kickoff countdown data ({ kind: "kickoff-countdown", ... })
without imposing any built-in overlay or styling.
The package does not assume any specific UI. The demo app under js/example/
is the reference consumer in this repository.
Replay loading follows the same model. The library exposes:
loadReplayFromBytes(bytes, { useWorker, onProgress, reportEveryNFrames })createReplayLoadOverlay(container, options)formatReplayLoadProgress(progress)
So callers can choose between the built-in DOM overlay or their own status/progress UI while consuming the same ReplayLoadProgress events.
Optional replay extensions can be installed through ReplayPlayerOptions.plugins
or at runtime with ReplayPlayer.addPlugin(...). Plugins receive:
- a setup/teardown lifecycle with access to the player, replay, scene, and container
- state-change hooks for DOM/HUD style integrations
- per-frame render hooks with interpolated frame timing and player sample context
This keeps optional features such as scoreboards, scrubbers, and scene overlays out of the core playback engine while still giving them a first-class API.
The package ships with reusable UI plugins:
createBallchasingOverlayPlugin()for Ballchasing-style floating player labels, floating boost bars, and side team boost HUDscreateBoostPadOverlayPlugin()for in-stadium standard Soccar boost pad availability markers driven by replay pad eventscreateTimelineOverlayPlugin()for a bottom-docked replay scrubber with integrated play/pause, time readouts, clickable event markers, configurable replay markers (defaulting to goals/saves), and caller-supplied custom events
Timeline markers can be tuned per consumer. For example, to include demolishes:
createTimelineOverlayPlugin({
replayEventKinds: ["goal", "save", "demo"],
});For full control, replayEvents can override the built-in replay marker source,
and events can append additional caller-defined markers.
If you need to add markers later, keep a reference to the plugin instance:
const timeline = createTimelineOverlayPlugin();
const detachShots = timeline.addEventSource(({ replay }) =>
replay.timelineEvents.filter((event) => event.kind === "shot")
);
timeline.refreshEvents();
detachShots();addEventSource() is additive, removeEventSource() removes a previously added
source, and refreshEvents() rebuilds markers when a source's output depends on
external mutable state.
For multi-replay workflows, the playlist layer is intentionally generic. Each
PlaylistItem specifies a replay source, a start bound, an end bound, and
optional label/meta, while ReplayPlaylistPlayer handles replay loading,
bound resolution, configurable replay-source prefetching, and clip-to-clip
transitions.
Preloading is controlled with preloadPolicy. Built-in modes are:
{ kind: "none" }{ kind: "all" }{ kind: "adjacent", ahead, behind? }{ kind: "custom", pick(context) }
Policies operate on unique replay sources rather than raw playlist items, so a run of multiple clips from the same replay only triggers one replay preload.
The package also includes lightweight manifest helpers for disk-backed playlist workflows:
loadPlaylistManifestFromFile(file)parsePlaylistManifest(value)resolvePlaylistItemsFromManifest(manifest, resolveReplaySource)
Development
npm --prefix js/player install
npm --prefix js/player run check
npm --prefix js/player run build
npm --prefix js/player run smoke:installThe build regenerates the local WASM bindings in js/pkg/ before bundling the
library, emits declaration files, and produces the npm artifact in dist/.
