All Mods Resource Packs Data Packs Shaders Modpacks Plugins
MultiView - Flashback Addon

MultiView - Flashback Addon

by Zeffut • Downloads: 0 • Followers: 0
Description
Gallery
Changelog
Versions

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

  1. Each player records their POV with Flashback during the same session.
  2. Drop the resulting .zip files into <gameDir>/flashback/replays/.
  3. Launch Minecraft with Flashback + MultiView installed.
  4. Click the camera icon → Select Replay.
  5. Tick the checkbox to the right of each replay (minimum two).
  6. Click Merge N Replays in the top-right corner.
  7. The merged replay merged_<timestamp>.zip appears 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 ClientboundSetTimePacket with 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 — .part file + 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.

All Versions

+ Add Version
Name Game version Platforms Published Downloads Actions
26.3
Fabric
25d ago 1
26.2
Fabric
2mo ago 1
26.1.x
Fabric
5mo ago 1
1.21.x
Fabric
5mo ago 1
1.21.11
Fabric
5mo ago 1
26.1.x
Fabric
5mo ago 1
1.21.x
Fabric
5mo ago 1
1.21.11
Fabric
5mo ago 1
26.1.x
Fabric
5mo ago 1
1.21.x
Fabric
5mo ago 1
1.21.11
Fabric
5mo ago 1
26.1.x
Fabric
5mo ago 1
1.21.x
Fabric
5mo ago 1
1.21.11
Fabric
5mo ago 1
26.1.x
Fabric
5mo ago 1
1.21.x
Fabric
5mo ago 1
1.21.11
Fabric
5mo ago 1
26.1.x
Fabric
5mo ago 1
1.21.x
Fabric
5mo ago 1
1.21.11
Fabric
5mo ago 1
26.1.x
Fabric
5mo ago 1
1.21.x
Fabric
5mo ago 1
1.21.11
Fabric
5mo ago 1
26.1.x
Fabric
6mo ago 1
1.21.x
Fabric
6mo ago 1
1.21.11
Fabric
6mo ago 1
26.1.x
Fabric
6mo ago 1
1.21.x
Fabric
6mo ago 1
1.21.11
Fabric
6mo ago 1
1.21.11
Fabric
6mo ago 1
## 0.5.0

  • 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.
## 0.5.0

  • 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.
## 0.5.0-beta.1

### 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 with auto_update: false in config/multiview-telemetry.json or -Dautoupdate.enabled=false; scope it with the update_owner, update_all, and update_exclude settings.

### 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.

## 0.5.0-beta.1

### 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 with auto_update: false in config/multiview-telemetry.json or -Dautoupdate.enabled=false; scope it with the update_owner, update_all, and update_exclude settings.

### 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.

## 0.5.0-beta.1

### 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 with auto_update: false in config/multiview-telemetry.json or -Dautoupdate.enabled=false; scope it with the update_owner, update_all, and update_exclude settings.

### 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.

## 0.4.1-beta.1 — anonymous telemetry

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.
## 0.4.1-beta.1 — anonymous telemetry

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.
## 0.4.1-beta.1 — anonymous telemetry

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.
## 0.4.0-beta.1 — audit-driven beta

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 MoveEntities action is now decoded, every VarInt entityId is remapped through safeRemap, 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_LINK wire format**: read/write int32 instead of VarInt (which mis-decoded any id above 127). Sentinel for "no holder" treated as <= 0 to 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.
  • OverlapValidator refuses 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).
  • copyPrimarySnapshotForTick uses FileChannel.map instead of Files.readAllBytes, avoiding OOM on long replays.
  • HURT_ANIMATION and PLAYER_COMBAT_KILL reclassified EGO → ENTITY so their entity id is remapped through the global namespace.

### Fixed — HIGH (cross-version)

  • fabric.mod.json java dependency is now templated: 1.21.x jars declare >= 21, the 26.1.x jar declares >= 25. Previously the 26.1 jar advertised >= 21 and crashed at classload on JDK 21 instead of failing cleanly via Fabric.
  • addRenderableWidget reflection on 26.1+ iterates Screen.class.getDeclaredMethods() and binds to the first overload accepting our Button — resilient to method-rename churn.

### Fixed — i18n

  • English users no longer see French progress labels: MergeOrchestrator emits multiview.merge_progress.phase.* translation keys and the screen picks Component.translatable vs Component.literal based on the "multiview." prefix.

### Deferred to follow-up

  • EntityMerger UUID-overwrite race and safeRemap phantom-ID race (H8, H9) — real but carry regression risk; separate focused session.
  • SOUND_ENTITY / LEVEL_EVENT remap (H7) — non-trivial wire format.
  • MergeOrchestrator refactor (still ≥ 1300 lines).

## 0.4.0-beta.1 — audit-driven beta

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 MoveEntities action is now decoded, every VarInt entityId is remapped through safeRemap, 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_LINK wire format**: read/write int32 instead of VarInt (which mis-decoded any id above 127). Sentinel for "no holder" treated as <= 0 to 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.
  • OverlapValidator refuses 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).
  • copyPrimarySnapshotForTick uses FileChannel.map instead of Files.readAllBytes, avoiding OOM on long replays.
  • HURT_ANIMATION and PLAYER_COMBAT_KILL reclassified EGO → ENTITY so their entity id is remapped through the global namespace.

### Fixed — HIGH (cross-version)

  • fabric.mod.json java dependency is now templated: 1.21.x jars declare >= 21, the 26.1.x jar declares >= 25. Previously the 26.1 jar advertised >= 21 and crashed at classload on JDK 21 instead of failing cleanly via Fabric.
  • addRenderableWidget reflection on 26.1+ iterates Screen.class.getDeclaredMethods() and binds to the first overload accepting our Button — resilient to method-rename churn.

### Fixed — i18n

  • English users no longer see French progress labels: MergeOrchestrator emits multiview.merge_progress.phase.* translation keys and the screen picks Component.translatable vs Component.literal based on the "multiview." prefix.

### Deferred to follow-up

  • EntityMerger UUID-overwrite race and safeRemap phantom-ID race (H8, H9) — real but carry regression risk; separate focused session.
  • SOUND_ENTITY / LEVEL_EVENT remap (H7) — non-trivial wire format.
  • MergeOrchestrator refactor (still ≥ 1300 lines).

## 0.4.0-beta.1 — audit-driven beta

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 MoveEntities action is now decoded, every VarInt entityId is remapped through safeRemap, 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_LINK wire format**: read/write int32 instead of VarInt (which mis-decoded any id above 127). Sentinel for "no holder" treated as <= 0 to 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.
  • OverlapValidator refuses 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).
  • copyPrimarySnapshotForTick uses FileChannel.map instead of Files.readAllBytes, avoiding OOM on long replays.
  • HURT_ANIMATION and PLAYER_COMBAT_KILL reclassified EGO → ENTITY so their entity id is remapped through the global namespace.

### Fixed — HIGH (cross-version)

  • fabric.mod.json java dependency is now templated: 1.21.x jars declare >= 21, the 26.1.x jar declares >= 25. Previously the 26.1 jar advertised >= 21 and crashed at classload on JDK 21 instead of failing cleanly via Fabric.
  • addRenderableWidget reflection on 26.1+ iterates Screen.class.getDeclaredMethods() and binds to the first overload accepting our Button — resilient to method-rename churn.

### Fixed — i18n

  • English users no longer see French progress labels: MergeOrchestrator emits multiview.merge_progress.phase.* translation keys and the screen picks Component.translatable vs Component.literal based on the "multiview." prefix.

### Deferred to follow-up

  • EntityMerger UUID-overwrite race and safeRemap phantom-ID race (H8, H9) — real but carry regression risk; separate focused session.
  • SOUND_ENTITY / LEVEL_EVENT remap (H7) — non-trivial wire format.
  • MergeOrchestrator refactor (still ≥ 1300 lines).

## [0.3.5] — 2026-05-19

Hard block on merges that would silently produce broken output.

### Added

  • OverlapValidator** — pre-merge guard that probes each selected replay for its ClientboundSetTimePacket anchor, 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 both MergeUi-classic (1.21.x) and MergeUi-modern (26.1+).
  • multiview.button.merge_selected.no_overlap i18n key in en_us.json and fr_fr.json.

### Fixed

  • Validator transparently mounts .flashback zip files via FileSystems.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 (not NO_OVERLAP) when an anchor is missing or the file cannot be read — we never block what we cannot verify.

## [0.3.5] — 2026-05-19

Hard block on merges that would silently produce broken output.

### Added

  • OverlapValidator** — pre-merge guard that probes each selected replay for its ClientboundSetTimePacket anchor, 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 both MergeUi-classic (1.21.x) and MergeUi-modern (26.1+).
  • multiview.button.merge_selected.no_overlap i18n key in en_us.json and fr_fr.json.

### Fixed

  • Validator transparently mounts .flashback zip files via FileSystems.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 (not NO_OVERLAP) when an anchor is missing or the file cannot be read — we never block what we cannot verify.

## [0.3.5] — 2026-05-19

Hard block on merges that would silently produce broken output.

### Added

  • OverlapValidator** — pre-merge guard that probes each selected replay for its ClientboundSetTimePacket anchor, 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 both MergeUi-classic (1.21.x) and MergeUi-modern (26.1+).
  • multiview.button.merge_selected.no_overlap i18n key in en_us.json and fr_fr.json.

### Fixed

  • Validator transparently mounts .flashback zip files via FileSystems.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 (not NO_OVERLAP) when an anchor is missing or the file cannot be read — we never block what we cannot verify.

## 0.3.4 — Cancel button, ETA and richer merge-report.json

### New

  • Cancel button** on the merge progress screen. Clicking it interrupts the worker thread; the running merge aborts cleanly, the partial .part file 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 mergedAt ISO-8601 timestamp, the producing multiviewVersion, 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.

## 0.3.4 — Cancel button, ETA and richer merge-report.json

### New

  • Cancel button** on the merge progress screen. Clicking it interrupts the worker thread; the running merge aborts cleanly, the partial .part file 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 mergedAt ISO-8601 timestamp, the producing multiviewVersion, 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.

## 0.3.4 — Cancel button, ETA and richer merge-report.json

### New

  • Cancel button** on the merge progress screen. Clicking it interrupts the worker thread; the running merge aborts cleanly, the partial .part file 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 mergedAt ISO-8601 timestamp, the producing multiviewVersion, 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.

## 0.3.3 — Fix overlay never showing on MC 26.1

### Bug fix

In 0.3.2 the overlay UI was supposed to light up on MC 26.1.x, but the runtime probe in MultiViewMod.onInitializeClient was looking up net.minecraft.client.gui.GuiGraphics, which doesn't exist on 26.1 (Mojang renamed the class to GuiGraphicsExtractor). The probe failed, the UI was skipped, and the chat-only fallback kicked in — exactly the state we were trying to leave behind.

0.3.3 drops the rendering-class probe and instead loads fr.zeffut.multiview.ui.MergeUi directly via reflection. The class is naturally version-gated by its imports (1.21.x build imports GuiGraphics, 26.1+ build imports GuiGraphicsExtractor), so a successful Class.forName is sufficient to know that the UI can render on the current runtime.

Verified by launching MC 26.1.1 + Fabric Loader 0.19.2 + Flashback 0.40.0 with the produced jar: the log now reads [MultiView] MergeUi registered (Phase 5 — per-replay checkboxes, MC 26.1+ variant) instead of UI disabled on this MC version (ClassNotFoundException).

### What this means

If you tried 0.3.2 on MC 26.1 and the merge button never appeared in *Select Replay*, this is the version that fixes it. No new bugs, no behavior change on 1.21.x.

## 0.3.3 — Fix overlay never showing on MC 26.1

### Bug fix

In 0.3.2 the overlay UI was supposed to light up on MC 26.1.x, but the runtime probe in MultiViewMod.onInitializeClient was looking up net.minecraft.client.gui.GuiGraphics, which doesn't exist on 26.1 (Mojang renamed the class to GuiGraphicsExtractor). The probe failed, the UI was skipped, and the chat-only fallback kicked in — exactly the state we were trying to leave behind.

0.3.3 drops the rendering-class probe and instead loads fr.zeffut.multiview.ui.MergeUi directly via reflection. The class is naturally version-gated by its imports (1.21.x build imports GuiGraphics, 26.1+ build imports GuiGraphicsExtractor), so a successful Class.forName is sufficient to know that the UI can render on the current runtime.

Verified by launching MC 26.1.1 + Fabric Loader 0.19.2 + Flashback 0.40.0 with the produced jar: the log now reads [MultiView] MergeUi registered (Phase 5 — per-replay checkboxes, MC 26.1+ variant) instead of UI disabled on this MC version (ClassNotFoundException).

### What this means

If you tried 0.3.2 on MC 26.1 and the merge button never appeared in *Select Replay*, this is the version that fixes it. No new bugs, no behavior change on 1.21.x.

## 0.3.3 — Fix overlay never showing on MC 26.1

### Bug fix

In 0.3.2 the overlay UI was supposed to light up on MC 26.1.x, but the runtime probe in MultiViewMod.onInitializeClient was looking up net.minecraft.client.gui.GuiGraphics, which doesn't exist on 26.1 (Mojang renamed the class to GuiGraphicsExtractor). The probe failed, the UI was skipped, and the chat-only fallback kicked in — exactly the state we were trying to leave behind.

0.3.3 drops the rendering-class probe and instead loads fr.zeffut.multiview.ui.MergeUi directly via reflection. The class is naturally version-gated by its imports (1.21.x build imports GuiGraphics, 26.1+ build imports GuiGraphicsExtractor), so a successful Class.forName is sufficient to know that the UI can render on the current runtime.

Verified by launching MC 26.1.1 + Fabric Loader 0.19.2 + Flashback 0.40.0 with the produced jar: the log now reads [MultiView] MergeUi registered (Phase 5 — per-replay checkboxes, MC 26.1+ variant) instead of UI disabled on this MC version (ClassNotFoundException).

### What this means

If you tried 0.3.2 on MC 26.1 and the merge button never appeared in *Select Replay*, this is the version that fixes it. No new bugs, no behavior change on 1.21.x.

## 0.3.2 — Full overlay UI on MC 26.1+

The merge UI is now available on **every supported Minecraft version**, including 26.1.x.

### What changed

  • MC 26.1+ overlay**: per-replay checkboxes and the "Merge N Replays" button now appear in Flashback's *Select Replay* screen on MC 26.1, 26.1.1 and 26.1.2 — same UX as on 1.21.x. No more chat-only fallback.
  • Dual UI source roots**: the project now ships a src/main/java-classic (1.21.x: GuiGraphics, Screen.render, drawCenteredString) and a src/main/java-modern (26.1+: GuiGraphicsExtractor, extractRenderState, text(font, …)). Build pipeline selects the correct one automatically from the no_intermediate flag.
  • Internals: button attachment on 26.1 uses reflection on Screen.addRenderableWidget (Fabric API removed Screens.getButtons). Mouse-click handling uses the new MouseButtonEvent record.

### Backport / migration notes

Nothing for users — drop in the new jar and the merge UI lights up.

For developers: a new MC release can be supported by either patching the matching java-classic/java-modern folder, or adding a third root if the rendering API shifts again.

### Full 0.3.1 → 0.3.2 changes

Only the UI subsystem; merge core, security guards, CI workflow disable, and all 16 audit fixes from 0.3.1 are unchanged.

## 0.3.2 — Full overlay UI on MC 26.1+

The merge UI is now available on **every supported Minecraft version**, including 26.1.x.

### What changed

  • MC 26.1+ overlay**: per-replay checkboxes and the "Merge N Replays" button now appear in Flashback's *Select Replay* screen on MC 26.1, 26.1.1 and 26.1.2 — same UX as on 1.21.x. No more chat-only fallback.
  • Dual UI source roots**: the project now ships a src/main/java-classic (1.21.x: GuiGraphics, Screen.render, drawCenteredString) and a src/main/java-modern (26.1+: GuiGraphicsExtractor, extractRenderState, text(font, …)). Build pipeline selects the correct one automatically from the no_intermediate flag.
  • Internals: button attachment on 26.1 uses reflection on Screen.addRenderableWidget (Fabric API removed Screens.getButtons). Mouse-click handling uses the new MouseButtonEvent record.

### Backport / migration notes

Nothing for users — drop in the new jar and the merge UI lights up.

For developers: a new MC release can be supported by either patching the matching java-classic/java-modern folder, or adding a third root if the rendering API shifts again.

### Full 0.3.1 → 0.3.2 changes

Only the UI subsystem; merge core, security guards, CI workflow disable, and all 16 audit fixes from 0.3.1 are unchanged.

## 0.3.2 — Full overlay UI on MC 26.1+

The merge UI is now available on **every supported Minecraft version**, including 26.1.x.

### What changed

  • MC 26.1+ overlay**: per-replay checkboxes and the "Merge N Replays" button now appear in Flashback's *Select Replay* screen on MC 26.1, 26.1.1 and 26.1.2 — same UX as on 1.21.x. No more chat-only fallback.
  • Dual UI source roots**: the project now ships a src/main/java-classic (1.21.x: GuiGraphics, Screen.render, drawCenteredString) and a src/main/java-modern (26.1+: GuiGraphicsExtractor, extractRenderState, text(font, …)). Build pipeline selects the correct one automatically from the no_intermediate flag.
  • Internals: button attachment on 26.1 uses reflection on Screen.addRenderableWidget (Fabric API removed Screens.getButtons). Mouse-click handling uses the new MouseButtonEvent record.

### Backport / migration notes

Nothing for users — drop in the new jar and the merge UI lights up.

For developers: a new MC release can be supported by either patching the matching java-classic/java-modern folder, or adding a third root if the rendering API shifts again.

### Full 0.3.1 → 0.3.2 changes

Only the UI subsystem; merge core, security guards, CI workflow disable, and all 16 audit fixes from 0.3.1 are unchanged.

## 0.3.1 — Security & robustness pass

Multi-agent audit identified 16 bugs across the merge core, security boundary, threading, and build pipeline. All fixed in this release.

  • Security (path traversal & I/O)**
  • /mv inspect and /mv merge now validate replay paths via Path.toRealPath() against the Flashback replay root — symlink-based traversal blocked.
  • Atomic-move TOCTOU window closed: re-check destination existence right before the final rename.
  • Source replays with totalTicks <= 0 are rejected at open time.

  • Correctness / memory**
  • Chunk dedup migrated from CRC32C (32 bits) to SHA-256 prefix (128 bits). CRC32C had a ~1-in-256k birthday collision on long replays. Held in a ThreadLocal<MessageDigest> to avoid per-call alloc.
  • chatRecentChatText now a bounded LRU (10k entries) — long sessions no longer risk OOM.
  • streamMerge outer try/finally with a writer holder so the active SegmentWriter is always closed on the snapshot-copy phase.
  • TimelineAligner guards against Integer.MAX_VALUE overflow on both per-source offsets and merged total ticks (loud failure vs silent negative timeline).
  • Malformed marker keys in metadata.json no longer abort the merge.

  • UI / threading**
  • All client.execute callbacks in the merge flow now check client.screen == progressScreen — no more callbacks firing on the wrong screen if the user navigates away.
  • Reflection failures on Flashback internals (renamed fields) now log WARN instead of being silently swallowed.
  • Back-button callback null-checks Minecraft instance.
  • MC 26.1 compatibility: probe Class.forName("GuiGraphics") up-front instead of registering and crashing later.

  • Build / CI**
  • build-version.sh propagates gradlew failure explicitly.
  • multi-version-build.yml step uses set -e + explicit exit 1.

No new features, no API changes. Drop-in replacement for 0.3.0.


  • MC 26.1 notes**: UI checkboxes are disabled on MC 26.1+ (rendering API renamed). Use /mv merge <source1> <source2> <output> via chat instead. Built against unobfuscated MC 26.1.2 client (mojmap-native, no remap).
## 0.3.1 — Security & robustness pass

Multi-agent audit identified 16 bugs across the merge core, security boundary, threading, and build pipeline. All fixed in this release.

  • Security (path traversal & I/O)**
  • /mv inspect and /mv merge now validate replay paths via Path.toRealPath() against the Flashback replay root — symlink-based traversal blocked.
  • Atomic-move TOCTOU window closed: re-check destination existence right before the final rename.
  • Source replays with totalTicks <= 0 are rejected at open time.

  • Correctness / memory**
  • Chunk dedup migrated from CRC32C (32 bits) to SHA-256 prefix (128 bits). CRC32C had a ~1-in-256k birthday collision on long replays. Held in a ThreadLocal<MessageDigest> to avoid per-call alloc.
  • chatRecentChatText now a bounded LRU (10k entries) — long sessions no longer risk OOM.
  • streamMerge outer try/finally with a writer holder so the active SegmentWriter is always closed on the snapshot-copy phase.
  • TimelineAligner guards against Integer.MAX_VALUE overflow on both per-source offsets and merged total ticks (loud failure vs silent negative timeline).
  • Malformed marker keys in metadata.json no longer abort the merge.

  • UI / threading**
  • All client.execute callbacks in the merge flow now check client.screen == progressScreen — no more callbacks firing on the wrong screen if the user navigates away.
  • Reflection failures on Flashback internals (renamed fields) now log WARN instead of being silently swallowed.
  • Back-button callback null-checks Minecraft instance.
  • MC 26.1 compatibility: probe Class.forName("GuiGraphics") up-front instead of registering and crashing later.

  • Build / CI**
  • build-version.sh propagates gradlew failure explicitly.
  • multi-version-build.yml step uses set -e + explicit exit 1.

No new features, no API changes. Drop-in replacement for 0.3.0.

## 0.3.1 — Security & robustness pass

Multi-agent audit identified 16 bugs across the merge core, security boundary, threading, and build pipeline. All fixed in this release.

  • Security (path traversal & I/O)**
  • /mv inspect and /mv merge now validate replay paths via Path.toRealPath() against the Flashback replay root — symlink-based traversal blocked.
  • Atomic-move TOCTOU window closed: re-check destination existence right before the final rename.
  • Source replays with totalTicks <= 0 are rejected at open time.

  • Correctness / memory**
  • Chunk dedup migrated from CRC32C (32 bits) to SHA-256 prefix (128 bits). CRC32C had a ~1-in-256k birthday collision on long replays. Held in a ThreadLocal<MessageDigest> to avoid per-call alloc.
  • chatRecentChatText now a bounded LRU (10k entries) — long sessions no longer risk OOM.
  • streamMerge outer try/finally with a writer holder so the active SegmentWriter is always closed on the snapshot-copy phase.
  • TimelineAligner guards against Integer.MAX_VALUE overflow on both per-source offsets and merged total ticks (loud failure vs silent negative timeline).
  • Malformed marker keys in metadata.json no longer abort the merge.

  • UI / threading**
  • All client.execute callbacks in the merge flow now check client.screen == progressScreen — no more callbacks firing on the wrong screen if the user navigates away.
  • Reflection failures on Flashback internals (renamed fields) now log WARN instead of being silently swallowed.
  • Back-button callback null-checks Minecraft instance.
  • MC 26.1 compatibility: probe Class.forName("GuiGraphics") up-front instead of registering and crashing later.

  • Build / CI**
  • build-version.sh propagates gradlew failure explicitly.
  • multi-version-build.yml step uses set -e + explicit exit 1.

No new features, no API changes. Drop-in replacement for 0.3.0.

Built with Mojang Mappings native namespace — works because MC 26.1+ ships unobfuscated bytecode.

## Runtime tested
Loaded successfully on MC 26.1.1 + Fabric Loader 0.19.2 alongside 167 other mods (Sodium, Iris, Distant Horizons, Flashback 0.40.0, full Fabric API 0.148.2+26.1.2, etc.).

``
[INFO]: MultiView loaded — addon pour Flashback, merge de replays multi-joueurs.
[INFO]: [MultiView] MergeUi registered.
``

## Features
  • Merge multiple Flashback replays into one
  • Cross-source player entity dedup (UUID-level)
  • LWW world state reconciliation (115K+ block overwrites/0 conflicts in production tests)
  • Global packet dedup (chat, sounds, particles)
  • Multi-world support
  • Per-replay checkbox UI in Flashback's replay selection screen
  • /multiview merge slash command

## Requires
  • Fabric Loader >=0.15.0
  • Fabric API
  • Flashback 0.40.0+
  • Java 21+ (MC 26.1 needs Java 25 runtime)

Merge engine is byte-identical to the 1.21.x release — same merge orchestrator validated against real multiplayer replay data (4 POV / 2h37 / 27,581 entities merged / 0 conflicts).
Built with Mojang Mappings + Loom 1.15 stack for MC 1.21.9 / 1.21.10 (with native Flashback 0.39.4 variant).

Validated end-to-end via autonomous test harness — record + merge + playback all pass on native 1.21.10 sources. Same merge code path as 1.21.11 (byte-identical stats on shared input data).
Built with Mojang Mappings + Loom 1.15 stack. Validated end-to-end:
  • Unit tests pass
  • Headless merge test on real multiplayer replays (27581 entities merged by UUID, 115481 LWW block overwrites, 83056 packets deduplicated, 189624 ticks over 4 POV sources)
  • Runtime client test with real multiplayer data: 0 crashes, 0 errors
  • Multi-version regression suite validates merge determinism across supported MC versions
[0.2.0] MultiView 0.2.0 by Zeffut on Apr 24, 2026
Download
## 0.2.0 Changes

### Critical fixes

  • Missing chunks fixed**: PlayerRespawnS2CPacket and GameJoinS2CPacket routed to EGO (primary-only). Previously, secondary sources were dragging the client into their dimension, silently dropping primary chunks.
  • Entity dedup re-enabled**: runtime registry access working. No more duplicate entities.
  • Secondary POV always visible**: synthesized PlayerInfoUpdate(ADD_PLAYER) + AddEntity(PLAYER) for each secondary source. Position tracked via accurate_player_position and PLAYER_POSITION translated into TeleportEntity.
  • WORLD LWW re-enabled**: BlockUpdate / SectionBlocksUpdate arbitrated through WorldStateMerger. No more block flickers on break/place.

### Other improvements

  • SET_CHUNK_CACHE_CENTER / RADIUS / SIMULATION_DISTANCE classified as EGO (primary-only)
  • Flashback action accurate_player_position_optional routed to LOCAL_PLAYER (primary-only)
  • Markers (Changed Dimension, etc.) aggregated from all sources
  • Output split into 6000-tick segments with rich snapshot in every cN.flashback
  • FORGET_LEVEL_CHUNK + REMOVE_ENTITIES filtered primary-only
  • LEVEL_CHUNK_WITH_LIGHT deduplicated by content hash
  • UI: per-replay checkboxes (replaces the global multi-select toggle)
  • Progress bar with percentage + phase text
  • Auto-refresh replay list after merge
  • Shorter merge filenames: merged_<timestamp>.zip

### Known limitations

  • 4+ POV merging: functional, with occasional visual imperfections possible
  • Multiple dimensions: camera follows primary only

### Tests: 127 passing

Full CHANGELOG: https://github.com/Zeffut/MultiView/blob/main/CHANGELOG.md
MultiView - Flashback Addon Icon
Download MultiView - Flashback Addon
Select game version
Select platform