diff --git a/docs/BOURBON_SYNC.md b/docs/BOURBON_SYNC.md new file mode 100644 index 00000000..66e55a03 --- /dev/null +++ b/docs/BOURBON_SYNC.md @@ -0,0 +1,176 @@ +# Bourbon sync — tripleslash/benilla-bourbon + +[benilla-bourbon](https://github.com/tripleslash/benilla-bourbon) is a **sibling** fork, not an +ancestor: it descends from [samwhosung/benilla](https://github.com/samwhosung/benilla) as this tree +does, by way of its own work rather than the Everwood graphics fork. It is not a configured remote; +fetch it by URL into its own ref namespace: + +``` +git fetch --no-tags https://github.com/tripleslash/benilla-bourbon.git 'refs/heads/*:refs/bourbon/*' +``` + +`docs/UPSTREAM_SYNC.md` covers the other direction, samwhosung's own `main`. + +## What it is, measured + +Measured **2026-10-26** at bourbon `b91c12e5`. + +The published repository has **one branch, no tags, and the fork's entire work in a single squash +commit** (`b91c12e5`, "benilla-bourbon: the fork's work on top of upstream benilla") sitting on +samwhosung's `359eff416`. There is no per-change history to walk, so nothing can be cherry-picked +from it: a pick is the whole fork or nothing. + +| | | +|---|---| +| merge base with this tree | `2af91704` (2026-10-12), the same base as our upstream sync | +| bourbon since that base | **290** — 289 of samwhosung's, then the one squash | +| ours since that base | 1013 | +| the squash commit | **1,662 files, 1,139,563 insertions, 14,733 deletions** | +| files a full merge conflicts in | **685** (348 `benilla-app`, 218 `benilla-ui`, 44 `benilla-world`, 26 `benilla-formats`, 21 `benilla-protocol`, 11 `benilla-assets`) | +| its base against samwhosung's head | 60 commits behind `6354cd98`, so it does not carry the Linux-audio or dismount-crash fixes this tree picked | + +Where the squash's lines are: + +| Area | Added | Files | +|---|---|---| +| `third_party/` (vendored wgpu 29, five Bevy crates, pfQuest) | 1,019,610 | 633 | +| `crates/benilla-world` (**the renderer**) | 53,749 | 203 | +| `crates/benilla-app` | 24,934 | 422 | +| `crates/benilla-ui` | 6,602 | 206 | +| `crates/benilla-formats` | 6,438 | 49 | +| `web/` + `crates/wenilla*` + `crates/benilla-pack*` (the browser build) | 12,714 | 49 | +| `crates/benilla-assets` | 5,579 | 23 | +| docs, scripts, CI, root | 8,320 | 42 | + +The exported folder `benilla-bourbon-main/` beside this checkout was verified byte-identical to +that commit's tree (`git archive | diff -r --brief`: zero differences). + +## The renderer is an engine move, not a file copy + +This is the thing to understand before any of it is planned. + +| | this tree | bourbon | +|---|---|---| +| Bevy | **0.18.1** | **0.19.1** | +| wgpu | **27** (registry) | **29.0.4**, vendored and patched | +| vendored Bevy crates | none | `bevy_ecs`, `bevy_render`, `bevy_tasks`, `bevy_platform`, `bevy_winit` | +| files implementing a render-graph `Node` | **14** (40 `ViewNode` references, 14 `add_render_graph_node` calls) | **0** | + +samwhosung's `main` is on Bevy 0.18.1 and wgpu 27 at both `359eff416` and his head `6354cd98`, so +the 0.19.1 move is bourbon's own and lives inside that one squash commit. + +Bevy 0.19 made the render graph **systems**: bourbon's passes are `add_systems(Render, …)` ordered +by `RenderSystems::*`, and it has no `Node` implementation anywhere. Ours are graph nodes. The two +renderers are written against incompatible architectures, so taking bourbon's means moving this +tree to Bevy 0.19.1 and converting the 14 node files — of which 10 are *our own* graphics +(`post/bloom`, `post/grading`, `post/sun_shafts`, `ssao`, `volumetric_fog`, `volumetric_light`, +`opaque2d`, `liquid/scene_depth`, `static_gx/torch_depth`, `ui_gamma`) and 4 are shared or +instruments (`ffx_glow`, `static_gx/render`, `capture/depth_probe`, `perf/gpu`). + +Bourbon's own `crates/benilla-world/src/modern/HOOKS.md` records that the modern lighting model +*did* run on Bevy 0.18 behind a workaround (`modern::tick_heal`, for a `PostUpdate` specialization +panic that 0.19 removed), so it is not inherently 0.19-only — but the published tree is the 0.19 +state and there is no earlier snapshot to take, since the repository has one branch and one commit. + +The vendored libraries are mostly *not* a native requirement: the wgpu patch is "WebGPU backend +only", and `bevy_tasks`/`bevy_platform`/`async-executor`/`event-listener`/`parking`/`web-task` are +all browser threading. `bevy_render` mixes browser work with a few general changes +(`RenderAsset::DEFERRABLE`, Skip cameras keeping their view attachments, mesh slabs destroyed when +let go). + +## Turtle WoW 1.18.1 does not apply to this install + +Bourbon's 1.18.1 support switches the client onto a **Turtle data layer** when a realm advertises +the version tag. Two measurements say it cannot fire here: + +* **It is web-only.** `benilla_formats::layers::turtle_available()` is false on native in bourbon's + own tree; `flavor::playable()` refuses a Turtle realm there, and `flavor::turtle()` is documented + "Always false on native, which has no layer." The layer is a `/data-turtle` container the browser + build streams. +* **This chain is not Turtle's.** OctoWoW ships no `patch-T`; it ships `patch-1`…`patch-5` and + `patch-A`…`patch-Q` of its own. It is Turtle-*derived*, not Turtle. + +What is worth having out of that programme is the **content and protocol fixes inside it**, which +are not gated on the layer. Four of those landed (below); the rest are either already in this tree +or welded to upstream's deferred→inline campaign, the same wall `docs/UPSTREAM_SYNC.md` describes. + +## What each tree holds that the other does not + +File sets, taken at `44c0b126` before this sync's own commits: ours 1,955 tracked files, bourbon's +2,990; 1,616 shared, **339 only ours**, 1,374 only theirs. + +**Only ours**, and nothing in bourbon answers for it: + +* **the whole addon-compat layer** — `crates/benilla-ui/src/script/compat/` is 63 files, 58 of + them ClassicAPI namespaces, plus `superwow.rs`, `unitxp.rs`, `nampower.rs` and + `vanilla_helpers.rs`. + Bourbon has **no** SuperWoW, nampower, ClassicAPI, UnitXP_SP3, VanillaUtils or VanillaHelpers + surface at all — not one mention outside an unrelated `UnitXP` (the stock XP getter). See + `docs/ADDON_COMPAT.md`. +* the login programme this realm needs: `autologin.rs`, `credential.rs`, `challenges.rs`, and the + `char_create/`, `char_select/`, `realm_select/`, `login/` and `glue/` screens. +* the nampower cast queue: `spell/np_press.rs`, `spell/queue.rs`. +* the instruments: `ui_script/{chunk_cache,cost_report,flash_trace,spell_rec,unit_rec}.rs`, + `script/{verb,tick,event,raise}_prof.rs`, `gpu_errors.rs`, `world/sys_timing.rs`. +* the reference tables under `reference/` (`1.12-shapes.tsv`, the event and global catalogs) and + the generators that build them. +* this fork's own graphics: 18 files in `benilla-world`, ~30 in `benilla-app`, six + `benilla-assets` shaders, five `benilla-formats` modules, and `Optional/sky-and-grading/`. + +**Only theirs** is the renderer, the browser build, the vendored libraries, the BENPACK container +and the Turtle layer. + +Bourbon's `FORK.md` credits **pkuzic's Everwood graphics fork** for foliage wind, rain on surfaces, +lava light, the sky gradient, the preset ladder and the lamp-halo technique, and "the benilla-twow +and benilla-octo forks" for Turtle WoW fixes — so part of this fork's line is already inside it. + +## What landed + +Each was measured against this install's own `Data/` chain before and after, independently of the +reader being changed. + +| Fix | Measured here | +|---|---| +| An encrypted or single-unit MPQ entry reads | 6 encrypted `(listfile)`s and 2 encrypted content files; `Patch-Q.mpq`'s 93 single-unit files, 92 of them `ITEM\TextureComponents\` armour art that is the winning copy | +| A BLP level past the file ends the chain | 316 copies declare one; 34 within the mip count; all 34 shadowed today, so nothing decodes differently — the layering stops being load-bearing | +| A group WMO's MOGP runs to EOF | 7 of 7,795 group files parsed to an empty group, now 0: six Shadowmoon Slagpit groups and a Westfall house, all winning copies | +| A creature-skin record fills its slot only where it holds a path | 26 records in 17 models bake a real `.blp` (the Crab, Scorpion, Crocodile, Thunder Lizard and RavenLord mounts, the WC2 Death Knight, the Wizard Frog…); 55 more carry unprintable leftovers, all in shadowed copies | + +The single-unit half of the first is this tree's own: bourbon still refuses those. + +## What was refused, and why + +| Taken from bourbon | Why not | +|---|---| +| the MPQ nameless read (`entries`, `read_block`, `name_key`, `is_encrypted`) | exists for its BENPACK container builder; this tree has no counterpart, so it would be dead API | +| `benilla_blp::dimensions` | the same — a packer and HD-upscale helper | +| ADT `MODF` placement bounds | its only consumer is the provisional-collider streamer (`terrain_stream::provisional`), which this tree does not have | +| M2 `tex_coords2` + `stage_coord`'s UV-set-1 path | needs a second UV attribute through the model pipeline and its shaders. Real, and it fixes the OctoWoW HD pack's `UI_MainMenu.m2` pillar swirls — but it is renderer work, so it belongs to the renderer decision | +| M2 `texture_unit_lookup_past` | parsed but never read, even by bourbon's own `stage_coord`, which answers `Some(stage)` past the table | +| `Billboard::carriers` | part of the rigged-billboard programme (`0x714260`), which is renderer work | +| `m2_ready`, `redress_body_atlas`, the `BodyAtlas::Pending` lane | browser build: a synchronous read on the page thread is the thing they exist to avoid | +| `benilla-protocol/src/auth.rs` | almost entirely the async/`ReadExactAsync` conversion for WebSocket login | +| the Turtle flavour switch (`flavor.rs`, `layers.rs`, the `DataLoad` rerun) | web-only in bourbon, and this chain has no `patch-T` to mount | +| **bourbon's junk-creature-skin fix as written** | it drops the embedded-name fallback outright. Measured here that removes the skin from 17 models; the new corpus test fails exactly that way. The diagnosis is right and the patch is not, so this tree took the diagnosis and guarded the fallback instead | +| `baked_npc_url` through `texture_url` (the extensionless bake name) | already in this tree: `benilla_formats::baked_atlas_path` appends `.blp` | +| `UnitCanAssist`, `GetBattlefieldStatus`, the unit-reaction and aura-duration fidelity fixes | already in this tree, with tests. On the UI and API side this fork is ahead — 1013 commits against their 290, plus the compat layer | + +## The decision this leaves + +Taking bourbon's renderer is a **re-baseline onto a tree that has none of the addon-compat work**, +plus a Bevy 0.18 → 0.19 engine move, plus re-picking samwhosung's last 60 commits. Three shapes, in +rising order of what they cost and what they deliver: + +1. **Re-baseline onto bourbon** — make its tree the base and re-apply what is only ours. The 339 + only-ours files carry the compat layer, which is self-contained behind `install(lua)` call sites + and ports by copying. What does *not* survive is this fork's 1013 commits of edits inside shared + files, which have to be re-identified from the test suite. Buys: the renderer as its author + wrote it, the browser build, 289 upstream commits, Bevy 0.19. +2. **Merge bourbon in** — 685 conflicting files to resolve by hand, and the render architecture + still has to be converted. Keeps every shared-file fix. This is the shape with the highest risk + of the failure mode the last sync hit (`docs/UPSTREAM_SYNC.md`, "what went wrong"). +3. **Port the renderer onto Bevy 0.18** — rewrite 54k lines from systems back onto graph nodes. + That is reimplementing his renderer, not taking it. + +Nothing here decides between them: the renderer is what the player sees, and only a play-test of +the result can judge it.