MultiView — merge multi-player Flashback replays
MultiView is a Fabric add-on for Flashback. Each player records their own POV with Flashback; MultiView fuses those recordings into one unified replay that behaves as if a single omniscient observer had captured the whole session.
- ✅ Every chunk explored by any POV is included
- ✅ Every recording player is visible at the same time
- ✅ Every entity and event seen by at least one POV is kept
- ✅ Free camera or Spectate Player on the merged replay
- ✅ Tick-perfect time alignment, atomic rollback on failure
Who is this for?
- Content creators — SMP recaps, PvP tournaments, machinima with multi-angle coverage from a single replay file.
- Server staff — multi-angle review of incidents, anti-cheat investigations from every involved player's POV.
- Cinematographers — free camera through a multiplayer scene with no information loss.
How to merge two replays
- Each player records their POV with Flashback during the same session.
- Drop the resulting
.zipfiles into<gameDir>/flashback/replays/. - Launch Minecraft with Flashback + MultiView installed.
- Click the camera icon → Select Replay.
- Tick the checkbox to the right of each replay (minimum two).
- Click Merge N Replays in the top-right corner.
- The merged replay
merged_<timestamp>.zipappears in the list once the progress screen finishes.
Compatibility
| Minecraft | Flashback | MultiView |
|---|---|---|
| 1.21.9 / 1.21.10 | 0.39.x | 0.3.2+mc1.21.9 |
| 1.21.11 | 0.39.4 | 0.3.2+mc1.21.11 |
| 26.1 / 26.1.1 / 26.1.2 | 0.40.0 | 0.3.2+mc26.1 |
Requires Fabric API. Java 21 on 1.21.x, Java 25 on 26.1+.
Features
- N-way merge — works from 2 up to many POVs.
- Tick-perfect alignment via
ClientboundSetTimePacketwith metadata fallback. - Cross-source deduplication — chunks (SHA-256 128-bit content hash), player info, system chat by visible text, entity moves.
- Multi-dimension — secondary POV dimension changes preserved as markers.
- Aggregated markers from every POV on a single timeline.
- Atomic write —
.partfile + atomic rename; a failed merge never destroys an existing replay. - Bounded memory — LRU-capped chat dedup, cryptographic chunk hashing, safe on multi-hour sessions.
- i18n — French and English.
Known limitations
- Secondary POVs appear as regular player entities (Flashback only supports one local player; the camera follows the first POV to start recording).
- 4+ POV merges may produce minor visual artefacts in zones where conflicting chunk versions overlap.
- Full technical limitations and roadmap in
SPEC.md.
Links
License
MIT — free to use, modify and redistribute. Flashback remains under its proprietary license by Moulberry; MultiView is a fully independent add-on and does not redistribute any Flashback code.
How to Install MultiView - Flashback Addon (Mod)
MultiView - Flashback Addon by Zeffut is verified for Fabric across Minecraft versions 1.21.10, 1.21.11, 1.21.9, 26.1, 26.1.1, 26.1.2, 26.2, 26.3 (latest release: 0.5.0+mc26.3, file size: 3.6 MB). Follow the steps below to install it safely from ModCraft.tv:
- Click the Download button above and select your Minecraft version (1.21.10, 1.21.11, 1.21.9, 26.1, 26.1.1, 26.1.2, 26.2, 26.3) and platform (Fabric).
- Make sure you have the compatible loader or environment installed for Fabric.
- Move the downloaded MultiView - Flashback Addon file into your Minecraft
.minecraft/modsfolder and launch the game.
All Versions
+ Add Version| Name | Game version | Platforms | Published | Downloads | Actions |
|---|---|---|---|---|---|
| 26d ago | 1 | ||||
| 2mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 |
- Stable Minecraft 26.3 support with Flashback 0.43.4.
- Pins and verifies the Flashback 0.43.4 artifact used for the 26.3 build.
- Includes replay merge improvements and background update support.
- Stable Minecraft 26.2 support with Flashback 0.43.2.
- The 26.2 build pins and verifies the Flashback 0.43.2 artifact before compilation.
- Includes the tested MultiView replay merge improvements and background update support.
### Added
- Silent background auto-update.** MultiView now keeps itself — and other Zeffut Modrinth mods present in your
mods/folder — up to date automatically. On startup it hashes the local jars, asks Modrinth for the latest build matching your Minecraft version and loader, downloads verified updates, and swaps them in at game shutdown (a detached helper finishes the swap if a jar is still locked, e.g. on Windows). It runs entirely in the background. Opt-out withauto_update: falseinconfig/multiview-telemetry.jsonor-Dautoupdate.enabled=false; scope it with theupdate_owner,update_all, andupdate_excludesettings.
### Changed
- Multi-row selection** replaces the per-replay checkboxes: left-click replay rows to build the merge set (selected rows are highlighted), double-click still opens a replay, and a single selection keeps Flashback's Open/Edit/Delete buttons working.
- Removed the first-run telemetry chat message. Telemetry stays anonymous and opt-out via
/mv telemetry off(and-Dmultiview.telemetry=false).
### Fixed
- The **Merge** button no longer overlaps Flashback's search/sort row and resizes responsively with the window.
- The **Merge** button is correctly greyed out when the selected replays are not from the same recording moment (derived from the immutable replay file name, not the file last-modified time) and for empty (0-tick) replays.
### Added
- Silent background auto-update.** MultiView now keeps itself — and other Zeffut Modrinth mods present in your
mods/folder — up to date automatically. On startup it hashes the local jars, asks Modrinth for the latest build matching your Minecraft version and loader, downloads verified updates, and swaps them in at game shutdown (a detached helper finishes the swap if a jar is still locked, e.g. on Windows). It runs entirely in the background. Opt-out withauto_update: falseinconfig/multiview-telemetry.jsonor-Dautoupdate.enabled=false; scope it with theupdate_owner,update_all, andupdate_excludesettings.
### Changed
- Multi-row selection** replaces the per-replay checkboxes: left-click replay rows to build the merge set (selected rows are highlighted), double-click still opens a replay, and a single selection keeps Flashback's Open/Edit/Delete buttons working.
- Removed the first-run telemetry chat message. Telemetry stays anonymous and opt-out via
/mv telemetry off(and-Dmultiview.telemetry=false).
### Fixed
- The **Merge** button no longer overlaps Flashback's search/sort row and resizes responsively with the window.
- The **Merge** button is correctly greyed out when the selected replays are not from the same recording moment (derived from the immutable replay file name, not the file last-modified time) and for empty (0-tick) replays.
### Added
- Silent background auto-update.** MultiView now keeps itself — and other Zeffut Modrinth mods present in your
mods/folder — up to date automatically. On startup it hashes the local jars, asks Modrinth for the latest build matching your Minecraft version and loader, downloads verified updates, and swaps them in at game shutdown (a detached helper finishes the swap if a jar is still locked, e.g. on Windows). It runs entirely in the background. Opt-out withauto_update: falseinconfig/multiview-telemetry.jsonor-Dautoupdate.enabled=false; scope it with theupdate_owner,update_all, andupdate_excludesettings.
### Changed
- Multi-row selection** replaces the per-replay checkboxes: left-click replay rows to build the merge set (selected rows are highlighted), double-click still opens a replay, and a single selection keeps Flashback's Open/Edit/Delete buttons working.
- Removed the first-run telemetry chat message. Telemetry stays anonymous and opt-out via
/mv telemetry off(and-Dmultiview.telemetry=false).
### Fixed
- The **Merge** button no longer overlaps Flashback's search/sort row and resizes responsively with the window.
- The **Merge** button is correctly greyed out when the selected replays are not from the same recording moment (derived from the immutable replay file name, not the file last-modified time) and for empty (0-tick) replays.
Adds an **anonymous, opt-out** telemetry layer (PostHog, EU servers) so the mod can be improved based on real usage: merge metrics (counts, durations, sizes, outcomes, per-phase timings), feature/command/UI usage, runtime versions, and **sanitized** error reports. No player names/UUIDs, world/server names, file paths, or replay contents are ever sent — an anonymous random ID is used.
Disable any time with
/mv telemetry off (or /mv telemetry status), the JVM flag -Dmultiview.telemetry=false, and it is auto-disabled in dev environments. See the README "Telemetry & privacy" section.### Fixed
- Cross-version first-run notice (chat API differs between MC 1.21.x and 26.1). All targets — 1.21.11, 1.21.9/1.21.10, 26.1 — build and pass the merge regression suite.
Adds an **anonymous, opt-out** telemetry layer (PostHog, EU servers) so the mod can be improved based on real usage: merge metrics (counts, durations, sizes, outcomes, per-phase timings), feature/command/UI usage, runtime versions, and **sanitized** error reports. No player names/UUIDs, world/server names, file paths, or replay contents are ever sent — an anonymous random ID is used.
Disable any time with
/mv telemetry off (or /mv telemetry status), the JVM flag -Dmultiview.telemetry=false, and it is auto-disabled in dev environments. See the README "Telemetry & privacy" section.### Fixed
- Cross-version first-run notice (chat API differs between MC 1.21.x and 26.1). All targets — 1.21.11, 1.21.9/1.21.10, 26.1 — build and pass the merge regression suite.
Adds an **anonymous, opt-out** telemetry layer (PostHog, EU servers) so the mod can be improved based on real usage: merge metrics (counts, durations, sizes, outcomes, per-phase timings), feature/command/UI usage, runtime versions, and **sanitized** error reports. No player names/UUIDs, world/server names, file paths, or replay contents are ever sent — an anonymous random ID is used.
Disable any time with
/mv telemetry off (or /mv telemetry status), the JVM flag -Dmultiview.telemetry=false, and it is auto-disabled in dev environments. See the README "Telemetry & privacy" section.### Fixed
- Cross-version first-run notice (chat API differs between MC 1.21.x and 26.1). All targets — 1.21.11, 1.21.9/1.21.10, 26.1 — build and pass the merge regression suite.
Multi-agent audit pass surfaced 35 findings across security, correctness, cross-version compatibility, and the merge algorithm itself. This beta closes the 2 CRITICAL and 10 HIGH-severity items. **Marked as a beta until the deferred follow-ups land and the mod has more real-world validation.**
### Fixed — CRITICAL
- MoveEntities entity-id remap** (the underlying cause of GitHub issue #1 for overlapping merges): the bulk-tick
MoveEntitiesaction is now decoded, everyVarInt entityIdis remapped throughsafeRemap, and the new bytes are re-emitted. Previously secondary sources' local ids collided with the primary's global namespace, producing the "frozen mobs / default rotations / missing equipment" symptoms. SET_ENTITY_LINKwire format**: read/writeint32instead ofVarInt(which mis-decoded any id above 127). Sentinel for "no holder" treated as<= 0to cover both legacy (-1) and modern (0) encodings — leashes no longer randomly attach to the wrong entity.
### Fixed — HIGH (security)
- Path traversal guard in
FlashbackReader.open: every segment path is normalised and confined to the replay folder. - Zip-bomb entry-count cap (65 536 entries per source) on top of the existing 5 GB byte cap.
OverlapValidatorrefuses to probe replays whose first segment exceeds 256 MB (OOM guard).
### Fixed — HIGH (correctness)
- PIU bulk re-emit no longer fires on mid-segment intercalation (5-arg overload bug closed).
copyPrimarySnapshotForTickusesFileChannel.mapinstead ofFiles.readAllBytes, avoiding OOM on long replays.HURT_ANIMATIONandPLAYER_COMBAT_KILLreclassifiedEGO → ENTITYso their entity id is remapped through the global namespace.
### Fixed — HIGH (cross-version)
fabric.mod.jsonjavadependency is now templated: 1.21.x jars declare>= 21, the 26.1.x jar declares>= 25. Previously the 26.1 jar advertised>= 21and crashed at classload on JDK 21 instead of failing cleanly via Fabric.addRenderableWidgetreflection on 26.1+ iteratesScreen.class.getDeclaredMethods()and binds to the first overload accepting ourButton— resilient to method-rename churn.
### Fixed — i18n
- English users no longer see French progress labels:
MergeOrchestratoremitsmultiview.merge_progress.phase.*translation keys and the screen picksComponent.translatablevsComponent.literalbased on the"multiview."prefix.
### Deferred to follow-up
EntityMergerUUID-overwrite race andsafeRemapphantom-ID race (H8, H9) — real but carry regression risk; separate focused session.SOUND_ENTITY/LEVEL_EVENTremap (H7) — non-trivial wire format.MergeOrchestratorrefactor (still ≥ 1300 lines).
Multi-agent audit pass surfaced 35 findings across security, correctness, cross-version compatibility, and the merge algorithm itself. This beta closes the 2 CRITICAL and 10 HIGH-severity items. **Marked as a beta until the deferred follow-ups land and the mod has more real-world validation.**
### Fixed — CRITICAL
- MoveEntities entity-id remap** (the underlying cause of GitHub issue #1 for overlapping merges): the bulk-tick
MoveEntitiesaction is now decoded, everyVarInt entityIdis remapped throughsafeRemap, and the new bytes are re-emitted. Previously secondary sources' local ids collided with the primary's global namespace, producing the "frozen mobs / default rotations / missing equipment" symptoms. SET_ENTITY_LINKwire format**: read/writeint32instead ofVarInt(which mis-decoded any id above 127). Sentinel for "no holder" treated as<= 0to cover both legacy (-1) and modern (0) encodings — leashes no longer randomly attach to the wrong entity.
### Fixed — HIGH (security)
- Path traversal guard in
FlashbackReader.open: every segment path is normalised and confined to the replay folder. - Zip-bomb entry-count cap (65 536 entries per source) on top of the existing 5 GB byte cap.
OverlapValidatorrefuses to probe replays whose first segment exceeds 256 MB (OOM guard).
### Fixed — HIGH (correctness)
- PIU bulk re-emit no longer fires on mid-segment intercalation (5-arg overload bug closed).
copyPrimarySnapshotForTickusesFileChannel.mapinstead ofFiles.readAllBytes, avoiding OOM on long replays.HURT_ANIMATIONandPLAYER_COMBAT_KILLreclassifiedEGO → ENTITYso their entity id is remapped through the global namespace.
### Fixed — HIGH (cross-version)
fabric.mod.jsonjavadependency is now templated: 1.21.x jars declare>= 21, the 26.1.x jar declares>= 25. Previously the 26.1 jar advertised>= 21and crashed at classload on JDK 21 instead of failing cleanly via Fabric.addRenderableWidgetreflection on 26.1+ iteratesScreen.class.getDeclaredMethods()and binds to the first overload accepting ourButton— resilient to method-rename churn.
### Fixed — i18n
- English users no longer see French progress labels:
MergeOrchestratoremitsmultiview.merge_progress.phase.*translation keys and the screen picksComponent.translatablevsComponent.literalbased on the"multiview."prefix.
### Deferred to follow-up
EntityMergerUUID-overwrite race andsafeRemapphantom-ID race (H8, H9) — real but carry regression risk; separate focused session.SOUND_ENTITY/LEVEL_EVENTremap (H7) — non-trivial wire format.MergeOrchestratorrefactor (still ≥ 1300 lines).
Multi-agent audit pass surfaced 35 findings across security, correctness, cross-version compatibility, and the merge algorithm itself. This beta closes the 2 CRITICAL and 10 HIGH-severity items. **Marked as a beta until the deferred follow-ups land and the mod has more real-world validation.**
### Fixed — CRITICAL
- MoveEntities entity-id remap** (the underlying cause of GitHub issue #1 for overlapping merges): the bulk-tick
MoveEntitiesaction is now decoded, everyVarInt entityIdis remapped throughsafeRemap, and the new bytes are re-emitted. Previously secondary sources' local ids collided with the primary's global namespace, producing the "frozen mobs / default rotations / missing equipment" symptoms. SET_ENTITY_LINKwire format**: read/writeint32instead ofVarInt(which mis-decoded any id above 127). Sentinel for "no holder" treated as<= 0to cover both legacy (-1) and modern (0) encodings — leashes no longer randomly attach to the wrong entity.
### Fixed — HIGH (security)
- Path traversal guard in
FlashbackReader.open: every segment path is normalised and confined to the replay folder. - Zip-bomb entry-count cap (65 536 entries per source) on top of the existing 5 GB byte cap.
OverlapValidatorrefuses to probe replays whose first segment exceeds 256 MB (OOM guard).
### Fixed — HIGH (correctness)
- PIU bulk re-emit no longer fires on mid-segment intercalation (5-arg overload bug closed).
copyPrimarySnapshotForTickusesFileChannel.mapinstead ofFiles.readAllBytes, avoiding OOM on long replays.HURT_ANIMATIONandPLAYER_COMBAT_KILLreclassifiedEGO → ENTITYso their entity id is remapped through the global namespace.
### Fixed — HIGH (cross-version)
fabric.mod.jsonjavadependency is now templated: 1.21.x jars declare>= 21, the 26.1.x jar declares>= 25. Previously the 26.1 jar advertised>= 21and crashed at classload on JDK 21 instead of failing cleanly via Fabric.addRenderableWidgetreflection on 26.1+ iteratesScreen.class.getDeclaredMethods()and binds to the first overload accepting ourButton— resilient to method-rename churn.
### Fixed — i18n
- English users no longer see French progress labels:
MergeOrchestratoremitsmultiview.merge_progress.phase.*translation keys and the screen picksComponent.translatablevsComponent.literalbased on the"multiview."prefix.
### Deferred to follow-up
EntityMergerUUID-overwrite race andsafeRemapphantom-ID race (H8, H9) — real but carry regression risk; separate focused session.SOUND_ENTITY/LEVEL_EVENTremap (H7) — non-trivial wire format.MergeOrchestratorrefactor (still ≥ 1300 lines).
Hard block on merges that would silently produce broken output.
### Added
OverlapValidator** — pre-merge guard that probes each selected replay for itsClientboundSetTimePacketanchor, computes its server-gameTime interval ([start, start + totalTicks]), and checks every pair for non-empty intersection. If any pair is disjoint, the Merge button stays disabled and a localised tooltip explains why. Wired into bothMergeUi-classic(1.21.x) andMergeUi-modern(26.1+).multiview.button.merge_selected.no_overlapi18n key inen_us.jsonandfr_fr.json.
### Fixed
- Validator transparently mounts
.flashbackzip files viaFileSystems.newFileSystem(...)instead of expecting a pre-extracted folder — matches the on-disk layout Flashback actually produces.
### Why
A real user case surfaced the bug: someone ran a merge across two
.flashback files recorded 11 days apart. The merge succeeded but produced visually broken output — entities vanished, others stuck with default rotations and no equipment. Root cause: server-side entity IDs are local to each recording client and there is no UUID-based matching for non-player entities, so any merge of non-overlapping POVs guarantees cross-source ID collisions. The fix is defensive: refuse upfront rather than emit silent garbage.### Internals
- Validation is memoised per selection (
Map<Set<Path>, Result>) so checkbox toggles stay responsive. - Returns
UNKNOWN(notNO_OVERLAP) when an anchor is missing or the file cannot be read — we never block what we cannot verify.
Hard block on merges that would silently produce broken output.
### Added
OverlapValidator** — pre-merge guard that probes each selected replay for itsClientboundSetTimePacketanchor, computes its server-gameTime interval ([start, start + totalTicks]), and checks every pair for non-empty intersection. If any pair is disjoint, the Merge button stays disabled and a localised tooltip explains why. Wired into bothMergeUi-classic(1.21.x) andMergeUi-modern(26.1+).multiview.button.merge_selected.no_overlapi18n key inen_us.jsonandfr_fr.json.
### Fixed
- Validator transparently mounts
.flashbackzip files viaFileSystems.newFileSystem(...)instead of expecting a pre-extracted folder — matches the on-disk layout Flashback actually produces.
### Why
A real user case surfaced the bug: someone ran a merge across two
.flashback files recorded 11 days apart. The merge succeeded but produced visually broken output — entities vanished, others stuck with default rotations and no equipment. Root cause: server-side entity IDs are local to each recording client and there is no UUID-based matching for non-player entities, so any merge of non-overlapping POVs guarantees cross-source ID collisions. The fix is defensive: refuse upfront rather than emit silent garbage.### Internals
- Validation is memoised per selection (
Map<Set<Path>, Result>) so checkbox toggles stay responsive. - Returns
UNKNOWN(notNO_OVERLAP) when an anchor is missing or the file cannot be read — we never block what we cannot verify.
Hard block on merges that would silently produce broken output.
### Added
OverlapValidator** — pre-merge guard that probes each selected replay for itsClientboundSetTimePacketanchor, computes its server-gameTime interval ([start, start + totalTicks]), and checks every pair for non-empty intersection. If any pair is disjoint, the Merge button stays disabled and a localised tooltip explains why. Wired into bothMergeUi-classic(1.21.x) andMergeUi-modern(26.1+).multiview.button.merge_selected.no_overlapi18n key inen_us.jsonandfr_fr.json.
### Fixed
- Validator transparently mounts
.flashbackzip files viaFileSystems.newFileSystem(...)instead of expecting a pre-extracted folder — matches the on-disk layout Flashback actually produces.
### Why
A real user case surfaced the bug: someone ran a merge across two
.flashback files recorded 11 days apart. The merge succeeded but produced visually broken output — entities vanished, others stuck with default rotations and no equipment. Root cause: server-side entity IDs are local to each recording client and there is no UUID-based matching for non-player entities, so any merge of non-overlapping POVs guarantees cross-source ID collisions. The fix is defensive: refuse upfront rather than emit silent garbage.### Internals
- Validation is memoised per selection (
Map<Set<Path>, Result>) so checkbox toggles stay responsive. - Returns
UNKNOWN(notNO_OVERLAP) when an anchor is missing or the file cannot be read — we never block what we cannot verify.
### New
- Cancel button** on the merge progress screen. Clicking it interrupts the worker thread; the running merge aborts cleanly, the partial
.partfile and temporary extract dirs are removed, and the user lands back on *Select Replay* with nothing damaged. - Estimated time remaining** in the progress text — e.g.
Streaming merge... tick 12345 / 50000 — ETA 1m 27s. Recomputed every 10 000 packets from the elapsed wall-clock time. No estimate is shown for the first few seconds (avoids "ETA 99h" jitter on a cold start). - Richer merge-report.json**: each merged replay now carries a
mergedAtISO-8601 timestamp, the producingmultiviewVersion, and the absolute source path of every input replay. Useful for debugging "which file actually went into this merge".
### Behaviour
- No change to merge output bytes for a given input set.
- Cancellation propagates via thread interrupt + a periodic
Thread.interrupted()poll inside the streaming loop, so a cancel takes effect within roughly one packet batch (~10 ms in practice). - The progress screen now shows two bottom buttons side-by-side: **Cancel** (active during the merge) and **Back** (active only after success / failure / cancel).
### Compatibility
Same MC matrix as 0.3.3: 1.21.9 / 1.21.10 / 1.21.11 / 26.1 / 26.1.1 / 26.1.2. The new UI elements are present on both the classic and modern UI variants.