Replays

The replay module continuously records what happens on a server and freezes the last seconds when a report comes in. Staff then watch the scene in-game (as a spectator with re-enacted players) or in the dashboard's 3D player – without having to teleport there after the report first.

Note

License: replay needs an EternalSystem license. Free in the base by default are core, punishments, reports and lobby; which modules are free can change – the dashboard shows locked modules grayed out.

Enabling

  • Module key: replay, requires reports. See Modules & Presets.
  • Enable it on every game server where recording should happen. The recording is made on the reported player's server.
  • For the browser player and the report flow in the dashboard: api.enabled: true and api.shared-secret in plugins/Eternal/config.yml.
  • server-name in config.yml must match the server name in the proxy (for cloud services e.g. Lobby-1). Only then can the proxy find the server where the replay is stored.
  • The Eternal jar on the proxy must be up to date – the proxy forwards recordings and spectators to the correct server.

ProtocolLib

ProtocolLib is optional (softdepend):

with ProtocolLibwithout
Re-enacted players in-gamereal player NPCs with the recorded skin and walking animationarmor stands with a player head
Chest lids in-gameopen/closeno animation
Browser playerfully usable either way

How recording works

  1. The recorder always runs and keeps a sliding window in memory for every online player: movement, hits, chat, block changes, item drops, item use, container use, inventory snapshots.
  2. A report freezes the last retention-seconds of the reported player and the players within sight, and then keeps recording.
  3. The recording ends when a mod claims/closes the report, or after max-followup-seconds. It is then saved as a file.
  4. In addition, a world snapshot of the surroundings is saved (blocks, chest contents, sign texts).
  5. Every saved recording is uploaded as JSON to the REST API and is available in the dashboard.

config.yml

replay:
  # Seconds back in time that are frozen on a report (~180 KB per player at 20 Hz)
  retention-seconds: 60
  # Ticks between movement frames: 1 = 20 Hz, 2 = 10 Hz, 4 = 5 Hz
  frame-interval-ticks: 1
  # Ticks between inventory snapshots (100 = 5 s)
  inventory-snapshot-ticks: 100
  # maximum follow-up recording time after the report
  max-followup-seconds: 600
  # World snapshot for the web player
  world-capture:
    enabled: true
    chunks: 16   # chunks in every direction around the reported player (0 = old block box)
    radius: 64   # blocks horizontally around the reported player
    up: 32
    down: 16
KeyDefaultMinimumNote
retention-seconds6010 sMore seconds = more RAM per online player
frame-interval-ticks11On full servers, 2 saves half
inventory-snapshot-ticks10020
max-followup-seconds60060 s
world-capture.chunks16–View distance in the web player (16 chunks = 256 blocks), at most 32
world-capture.radius / up / down64 / 32 / 16–Only with chunks: 0 (old box), at most approx. 2.5 million blocks in total
Tip

Existing config.yml files are not adjusted automatically. If you still have the old values 32/24/12 for world-capture, raise them by hand.

When freezing, the server copies the chunk snapshots of the loaded chunks around the scene plus chest contents and sign texts on the main thread; processing and compression happen asynchronously. Per chunk only what can be seen is stored – from the highest point down to the lowest ground of the neighbouring chunks (sea floor and forest floor included) – so 16 chunks stay at one or two MB. How far the surroundings reach depends on what is loaded: with a server view distance of 16 or more (task field Sichtweite) the full 16 chunks.

Storage location and retention

LocationContents
plugins/Eternal/replays/<id>.dat.gzRecording (gzip, binary format) on the game server
plugins/Eternal/replays/index.txtIndex of recordings (no database needed)
replays.directory in api.yml (default replays)Web copies for the browser player, plus a row in eternal_replays

There is no age-based deletion. Recordings are deleted when

  • a report is closed without a ban (server file and web copy),
  • a ban is lifted via the dashboard (all replays of the reports for this ban).

A mute from a report keeps the replay. So the folder grows with the number of bans – clean up old files by hand if needed.

Watching in-game

CommandPermissionDescription
/replay or /replay statuseternal.replay.debugRecorder state: active buffers, events in RAM
/replay list [Anzahl]eternal.replay.rewatchLatest recordings ([Anzahl] = count, default 10, max. 100)
/replay reports [Anzahl]eternal.replay.rewatchReport recordings only
/replay play <id>eternal.replay.rewatchPlay a recording
/replay exiteternal.replay.rewatchLeave playback

More convenient: click TP on the report in the dashboard. If the mod is on a different server, the proxy sends them to the server with the recording, and the replay starts there.

During playback, the viewer is in spectator mode and has this hotbar:

SlotItemFunction
1EmeraldPlay / pause
2Arrow10 s back
3ChestInventory of the nearest player
4Clay ballSlower (−0.25)
5MapReplay info in chat
6SlimeballFaster (+0.25)
8Spectral arrow10 s forward
9BarrierLeave the replay

Right-clicking a container in the replay shows its contents at the current replay time (read only) – never the real chest.

Note

After a server switch, the replay only starts once the mod's inventory sync has finished. While a mod is watching a replay, their inventory is not saved – their real inventory is unchanged afterwards.

Watching in the browser (3D player)

Pages in the dashboard:

PagePermissionContents
Moderation → Replays (/replays)eternal.replay.rewatchList of all uploaded recordings
Report → Replay im Browser ("Replay in browser", /replays/report/<Report-ID>)eternal.replay.rewatchRecording for the report
Ban → Replay (/replays/ban/<Bann-ID>)eternal.replay.rewatchRecording for the ban
Mein Konto ("My account") → Replays zu deinen Banns ("Replays of your bans")eternal.replay.ownBanned players see the recording of their own ban

A player only sees a replay if they are the main subject and the report resulted in a ban. Open reports stay internal to staff.

Controls

Camera modes (buttons on the left or keys):

  • Folgen ("Follow", default): the camera orbits behind the selected player. Drag the mouse = rotate, mouse wheel = zoom.
  • Ego ("First person", V): through the player's eyes, with their viewing direction – good for aim and reach checks.
  • Frei ("Free", F): spectator flight with WASD, space/E up, Shift/Q down, Ctrl faster, mouse wheel = flight speed. Left-click captures the mouse (Esc releases), right-click drag = look around without capturing.
KeyFunction
Space / KPlay / pause
← / →±5 s (with Shift ±1 s)
, / .One tick back / forward
↑ / ↓Speed (⅛× to 8×)
1–9Follow a player
TabNext player

Double-click a player = follow. The timeline has markers (blue chat, red hit, yellow block, purple drop) – clicking one jumps there. On the right runs the event feed; per player, Inventar ("Inventory") shows the latest snapshot up to the current time. Clicking a block shows its name and coordinates, for containers the contents (double chest = 54 slots), for signs the text.

Rendered are real vanilla block models with lighting, chests, shulkers, beds, signs, heads and banners, as well as the worn armor. The dashboard serves the Minecraft textures itself (folder mc/ in the build). Skins come from the recording, otherwise from mc-heads.net. Recordings without a world snapshot show a ground grid.

Live view

Under Cloud › Betrieb › Live-Ansicht (permission eternal.web.live) you watch a server live – in the same 3D player as replays, about half a second behind (the buffer keeps movement smooth):

  • Start at a world's spawn or directly at a player. Player pages show a Live zusehen ("watch live") button for online players.
  • Camera: Frei (free: WASD, space/shift up/down, click captures the mouse, wheel = speed), Folgen (follow, third person) or Ego (through the player's eyes). Double-click a player to follow; "Auf dem Server" jumps to players out of view.
  • Phone / tablet: controls like Minecraft Bedrock – a D-pad bottom left (slide your thumb between two arrows to go diagonal, tap the centre to toggle sprint), fly up/down bottom right, swipe on the view to look around. Camera, player and chat panels fold behind the buttons at the top centre.
  • Fullscreen: button at the top centre of the view. Real fullscreen on Android and desktop (landscape on phones where allowed); on iPhone the view fills the whole page – Safari does not let pages hide its bars. With no bars at all: in Safari Share → "Add to Home Screen" and open the dashboard from the Eternal icon (log in once more there, the home-screen app has its own storage).
  • View distance 16 chunks: the surroundings arrive chunk by chunk, nearest first (complete after a few seconds, about 1–2 MB). When the camera moves on, missing chunks follow and far ones are dropped; Umgebung reloads everything. If nobody is there, the server loads those chunks itself for a moment; never-visited ones are generated by Paper only near the camera (4 chunks).
  • Streamed: every player within 256 blocks of the camera (10 times a second), block changes and the world's chat.
  • Opening chests: click (tap on a phone) a chest, barrel, furnace, hopper … to see its contents right now – the server reads them at that moment (double chests whole). Signs show their text.
  • World choice: the server's main world is always first and preselected.
  • In-game the viewer is never visible – no figure, no tab list entry.
  • Vanished players (/vanish) and players without privacy consent are never streamed.
  • Requires the Eternal plugin with API connection (api.enabled); the replay module does not have to be on. Surroundings need 1.13+, players work on every version.
  • Load: without viewers every server checks with the API briefly every 2 s; every 250 ms while someone watches.

Map

Cloud › Karte (/cloud/map) is the live view from above – 3D like Google Earth. In the live view the camera button Karte switches the same way.

  • Controls: drag = pan, right mouse = rotate/tilt, wheel = zoom to the cursor. On phones: two fingers zoom (pinch), turn (twist) and tilt (both up/down) – the view angle only ever with two fingers. One finger pans from above (view angle 70°–90°, 90° = straight down) and turns when flatter than 70°. Double tap zooms in. The camera stays at least 5 blocks above the ground or 1 block above trees and buildings.
  • Every player of the world shows live – within 200 blocks of the camera as a 3D figure with skin, farther away as a head with the name (also far outside the loaded area). The list on the left jumps to a player.
  • Click / tap a player: name, coordinates, health, food, level and game mode, plus Verfolgen (follow – the map stays on the player), Hinzoomen (zoom in), 3D (back to the normal live view behind the player), Profil (profile) and Teleport (with eternal.web.tracking.teleport: you in-game to them, otherwise /tppos to the clipboard).
  • Whole map: around the point you look at stands the full 3D area (16 chunks in every direction). Around it the map shows the whole world as terrain (coarser farther away). Looking down steeply and from 1000 blocks above the highest point below it is one even map in the colours of a Minecraft map with height shading, like Google Maps (not generated = dark). Below 800 blocks or flatter than 70° it is the normal look with sky and block colours (the real 3D blocks up to 400 blocks above the terrain), in between a transition; the height above the terrain shows bottom left.
  • Every server keeps that terrain itself (feature task:map-tiles): on the first start it captures each world once completely – every chunk that exists on disk, throttled, never generating new ones, pausing while TPS are below 18; a restart continues. After that it pregenerates terrain nobody has visited yet in the background (like Chunky, ring by ring from the centre): config.yml → map.pregenerate-radius (default 1000 blocks around the world border centre or spawn, never past the border, 0 = off), map.pregenerate-excluded for exceptions. Farm and plot worlds are pregenerated; the main world fills through the players (map.pregenerate-main-world: true adds it), nether and end only with map.pregenerate-nether-end: true. Below map.pregenerate-min-free-gb (default 5) of free disk space pregeneration pauses. Empty void worlds are detected and skipped. After a farm world reset its map is deleted and the new world captured afresh. On Paper asynchronous, throttled while players are online, pausing below 18 TPS; on Spigot only while nobody is online. It costs time and disk space: 1000 blocks are ~16,000 chunks (about 1 GB) per world, 10,000 blocks ~1.5 million chunks – many hours and tens of GB. Older versions defaulted to 10,000; the update switches that to 1000. The dashboard only ever loads what is in sight (coarser far away). And live: when players load and leave chunks and a few seconds after building, breaking or explosions. Where nobody is, the last state stays. Nether: without the roof – the map shows the floor below the bedrock ceiling (like other map mods' cave mode: solid rock is cut at height 120), lit with ambient light instead of sky. Saved every 10 s in the database (regions of 32×32 chunks).
  • Vanished players and players without consent are not shown.

Permissions

PermissionDefault levelPurpose
eternal.replay.rewatchTeam/replay list, reports, play, exit and all replays in the dashboard
eternal.replay.debugAdmin/replay status
eternal.replay.ownAllReplay of your own ban in the dashboard

Common pitfalls

  • „Kein Replay: Modul replay ist auf … nicht aktiv — Live-TP“ ("No replay: module replay is not active on … — live TP") – the module is off on the reported player's server. The mod is teleported live.
  • „Der Spieler war zu lange offline — Replay nicht verfügbar“ ("The player was offline too long — replay not available") – nothing was left in the buffer.
  • Replay starts on the wrong server – server-name does not match the proxy name.
  • No replay in the dashboard – api.enabled is off or the secret does not match internal.shared-secret in api.yml; the upload then fails.
  • High RAM usage – lower retention-seconds or set frame-interval-ticks: 2.
  • Missing blocks in the web player – the area was outside world-capture or the chunks were not loaded.