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