You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<strong>A deterministic replay engine for SCP:SL rounds.</strong>
16
+
<strong>A deterministic replay engine for SCP:SL rounds</strong>
19
17
</p>
20
18
21
19
<palign="center">
22
-
<em>What vanishes from the server should still remain readable in time.</em>
20
+
<em>Rounds should remain replayable after they end</em>
23
21
</p>
24
22
25
-
> A multiplayer round should not disappear the moment it ends.
26
-
27
23
---
28
24
29
25
## Overview
30
26
31
27
Causality-0 is a LabAPI-based replay plugin for SCP: Secret Laboratory.
32
-
It records server-side player state into a deterministic timeline, serializes it as a `.c0`replay file, and later reconstructs that round in-game with dummy actors, preserved timing, and seed-aware playback rules.
28
+
It records server-side round state into a deterministic timeline, stores it as a `.c0`binary replay, and reconstructs that round in-game with dummy actors, preserved timing, world-state restoration, and seed-aware playback rules.
33
29
34
-
It is built less as a spectacle system and more as a way to leave a round behind in a form that can still be revisited.
30
+
The project is focused on reproducibility rather than cinematic approximation.
31
+
Whenever possible, playback restores recorded results directly instead of re-simulating fragile live runtime behavior.
35
32
36
33
---
37
34
38
-
## Current architecture
35
+
## Current capabilities
39
36
40
-
### ⏱️ Deterministic timeline
37
+
### Deterministic timeline playback
41
38
42
-
Replay time is driven by frame index and step size instead of wall-clock drift.
43
-
That keeps:
39
+
Replay time is driven by frame index and per-file FPS metadata.
40
+
That keeps actor movement, interactions, projectiles, and optional voice packets aligned to the same timeline.
44
41
45
-
- actor movement
46
-
- voice packets
47
-
- interaction events
48
-
- projectile motion
42
+
### Actor lifecycle support
49
43
50
-
bound to the same timeline.
44
+
The replay pipeline now supports:
51
45
52
-
### 🧟 Native actor playback
46
+
- players who join after recording started
47
+
- players who leave or disconnect before round end
48
+
- role changes during the round
49
+
- death lifecycle events
50
+
- delayed dummy spawning based on track start frame
51
+
- playback despawn on recorded leave
53
52
54
-
The project does not treat replay as pure transform theater.
55
-
Where possible, it reuses native SCP:SL systems so movement, state, and side effects stay closer to the game’s own rules.
53
+
### World-state persistence
56
54
57
-
### 💾 `.c0` binary protocol
55
+
The replay format now persists world state beyond actor tracks.
56
+
Current world reconstruction covers:
58
57
59
-
Current replay protocol version is **V9**.
58
+
- map pickups present at recording start
59
+
- pickup create and remove events
60
+
- pickup movement persistence
61
+
- locker and chamber contents
62
+
- locker/chamber open state restoration on load
60
63
61
-
It stores:
64
+
### Projectile persistence
62
65
63
-
| Field | Notes |
64
-
| --- | --- |
65
-
| Map seed | Used to validate world correctness |
66
-
| Replay FPS | Embedded in the file for playback speed |
67
-
| Actor frames | Position, rotation, item state, stats |
68
-
| Audio packets | Timestamped raw voice payloads |
69
-
| Interaction frames | Door interaction timing |
70
-
| Lifecycle events | Role changes and death events |
66
+
Projectile tracks are now written into `.c0` files together with owner information.
67
+
Loaded replays can restore projectile playback without relying on the original live runtime state.
68
+
69
+
### Deterministic door playback
71
70
72
-
### 🌍 Seed-aware playback
71
+
Door replay now restores the recorded interaction result directly.
72
+
It no longer depends on re-running live permission checks during playback, which improves stability and avoids common pass-through issues.
73
73
74
-
Replay is world-sensitive.
75
-
If the replay seed does not match the current map, playback can be blocked or the next round can be scheduled to regenerate with the replay seed.
74
+
### Optional voice recording
76
75
77
-
### ♻️ Lifecycle event stream
76
+
Voice packet capture is available but now configurable.
77
+
Voice playback still works for replays that already contain saved audio data.
78
78
79
-
An actor track no longer means a single uninterrupted life.
80
-
The replay format now supports:
79
+
### Seed-aware replay loading
81
80
82
-
- role changes
83
-
- death events
84
-
- spectator phases
85
-
- later respawn / reassignment playback
81
+
Replay files embed the recording map seed.
82
+
If the loaded replay seed does not match the current round seed, the plugin can force a restart so the replay can be loaded on the correct map seed next round.
86
83
87
84
---
88
85
89
-
## Replay lifecycle
90
-
91
-
```mermaid
92
-
flowchart LR
93
-
A[Live round] --> B[Record frames and events]
94
-
B --> C[Deterministic timeline]
95
-
C --> D[Serialize .c0]
96
-
D --> E[Load replay]
97
-
E --> F{Seed matches?}
98
-
F -- No --> G[Schedule restart with replay seed]
99
-
F -- Yes --> H[Spawn dummy actors]
100
-
G --> H
101
-
H --> I[Apply lifecycle and movement]
102
-
I --> J[Replay items voice doors projectiles]
103
-
```
86
+
## `.c0` protocol
87
+
88
+
Current replay protocol version is **V13**.
89
+
90
+
It currently stores:
91
+
92
+
| Field | Notes |
93
+
| --- | --- |
94
+
| Map seed | Used to validate world correctness |
95
+
| Replay FPS | Saved in the file and restored on load |
96
+
| Actor tracks | Position, view rotation, movement state, held item, stats |
97
+
| Audio packets | Optional raw voice payloads with timestamps |
98
+
| Interaction frames | Door interaction timing and result |
99
+
| Lifecycle events | Role changes, death, leave/disconnect |
100
+
| World pickups | Initial world pickup snapshot |
101
+
| Pickup ops | Add, move, remove |
102
+
| Locker states | Chamber contents and open state |
103
+
| Locker ops | Recorded locker interaction results |
104
+
| Projectile tracks | Projectile frames and owner id |
104
105
105
106
---
106
107
107
108
## What is currently recorded
108
109
109
-
- player position and rotation
110
+
- player position and view rotation
110
111
- movement state and grounded state
111
-
- held item and firearm attachments
112
-
- shooting and reloading intent
113
-
- usable item start / cancel intent
114
-
- health and armor-like values
115
-
- voice packets
116
-
- door interaction timing
117
-
- projectile tracks
118
-
- role-change events
119
-
- death events
112
+
- held item and firearm attachment code
113
+
- shooting and reload intent
114
+
- usable item start and cancel intent
115
+
- HP and AHP-like values
116
+
- optional raw voice packets
117
+
- door interaction timing and result
118
+
- late join and leave lifecycle changes
119
+
- projectile tracks and owner ids
120
+
- world pickups and pickup movement
121
+
- locker/chamber contents and state
122
+
- role changes and death lifecycle events
120
123
121
124
---
122
125
@@ -142,46 +145,90 @@ c0 play
142
145
143
146
### Behavior notes
144
147
145
-
-`load` reads `.c0` metadata, including seed and replay FPS
146
-
- old replay files fall back to a compatibility FPS path
147
-
- playback is blocked if actors are missing
148
-
- playback can be blocked or deferred if the current map seed does not match the replay seed
148
+
-`start` begins a new recording from the current state
149
+
-`save` writes the current replay into `CausalityRecords/<name>.c0`
150
+
-`load` reads seed and FPS metadata before playback
151
+
-`load` rebuilds world state when the replay seed matches the current round
152
+
- if the replay seed does not match the current round, the plugin schedules a restart with the replay seed
153
+
-`play` starts deterministic playback of the loaded or recorded timeline
154
+
-`spawn` can still be used for manual dummy spawning workflows
155
+
156
+
---
157
+
158
+
## Configuration
159
+
160
+
The plugin now supports configuration through `config.yml` in the LabAPI plugin config directory.
161
+
162
+
Current config entries:
163
+
164
+
```yml
165
+
default_record_fps: 60
166
+
record_voice: false
167
+
```
168
+
169
+
### Current config behavior
170
+
171
+
- `default_record_fps`
172
+
- sets the default FPS for new recordings
173
+
- affects new recordings only
174
+
- does not change the FPS embedded in existing replay files
175
+
176
+
- `record_voice`
177
+
- enables or disables saving player voice packets during new recordings
178
+
- when disabled, replay files still record all non-voice data normally
179
+
- loading and playing older voice-enabled replays still works
0 commit comments