Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions mac-patcher/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
venv/
__pycache__/
*.pyc
*.bak
*.bak-*
scan_bundles_*.out
74 changes: 74 additions & 0 deletions mac-patcher/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# mac-patcher

Python patcher that injects Mac-compatibility fallbacks into a SWL TTS save
file. Works around the TTS Unity 6 (Berserk) shader bug where vanilla
AssetBundle Projectors (range rulers, cohesion halos, movement templates,
deployment zones, silhouettes) render as a magenta rectangle on macOS
because the custom shader bundled by Allen White (Dicewrench) fails to load
under Unity 6 Metal.

## What it does

For each affected object script in a `TS_Save_N.json`:

- **Cohesion / Range / Maximum Move / Deployment / Silhouette**: routes the
visualization through a Mac-friendly path (vector lines + decal PNGs)
built into the Global script. The vanilla bundle path stays available
for per-seat opt-in (see "Mac TTS U6 Patch" floating panel).

- **SIL button**: renames `click_function = "toggleSilhouettes"` to
`"macToggleSil"` + injects a forwarder. Empirically the engine silently
swallows the original click_function name in Mac mode (the button plays
its sound/animation but the function is never invoked). The rename
bypasses the issue entirely.

- **clearSilhouette nil guard**: upstream `clearSilhouette()` derefs
`removeAttachments()[1]` which is nil when `silhouetteState` is true but
the physical silhouette attachment has been lost across save reloads.
Patched to guard the nil case + reset state in onload.

- **Order Token Speed/Move button overrides**: inlines vanilla bodies of
`changeSpeed1/2/3` and `moveForward/Backwards/Left/Right` to capture
the clicking player's color (`macActivePlayerForMove`) for per-seat
routing. Inlined rather than wrapped because the List Builder copies the
block to Command Token Custom_Models which lack the vanilla
Order_Token function bodies (wrap+call_orig would crash with "attempt
to call a nil value").

## Usage

```bash
# Setup once
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

# Patch a save
python3 patch_save_for_mac.py <vanilla_save.json> <output_path.json> [--reload]
```

The patcher also mirrors the patched save into
`~/Library/Tabletop Simulator/Saves/TS_Save_N.json` (next free slot, or the
existing `SWL BETA - MAC PATCH` slot if present) so TTS picks it up in
Games -> Save & Load.

`--reload` hot-pushes the patched scripts to a running TTS instance via the
External Editor API (no need to restart TTS).

## Idempotence

All patches are idempotent: a re-run on an already-patched save strips the
previous Mac patch block from Global (via marker regex) and re-injects
fresh. Per-object wrappers are also stripped before re-injection.

## Files

- `patch_save_for_mac.py` - main patcher
- `scan_bundles.py` - UnityPy scanner for the local TTS bundle cache
- `extract_projector_specs.py` - dump Projector material properties from a
bundle (used to discover the `_Arc` shader keyword for firing arc lines)
- `generate_overlay_assets.py` - regenerate the range/cohesion/etc. PNG
decals from authoritative SWL geometry
- `inspect_*.py` - debug helpers
- `retro-*.md` - retrospective notes on each subsystem rewrite
- `SHADER_INVENTORY.md` - list of custom shaders in the vanilla bundles
59 changes: 59 additions & 0 deletions mac-patcher/SHADER_INVENTORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# SW Legion TTS Mod — Shader Inventory

Scan effectué le 2026-05-07 sur `~/Library/Tabletop Simulator/Mods/Assetbundles/` (40 bundles `.unity3d`).
Outil : UnityPy 1.25.0, script `scan_bundles.py`. Output brut : `scan_bundles_2026-05-07.out`.

## TL;DR
**9 shaders custom distincts**, **tous embarqués dans le `.unity3d` qui les utilise**. Donc :
- L'astuce "Always Included Shaders" du player TTS est **non-applicable** : ces shaders ne sont pas chargés depuis le pool du player, ils vivent dans les bundles.
- Le bug magenta vient du fait que le bytecode/code source de ces shaders custom ne fonctionne plus correctement sous Unity 6 + Metal sur Mac.
- Les overlays magenta listés par Martin (cohésion, range, deployment, movement) correspondent **exactement** aux 4 shaders `BucketheadBits/Projector/*`.

## Inventaire complet (par catégorie)

### Shaders Projector (overlays affectés par le bug magenta)
| Shader | Materials | Bundles |
|---|---|---|
| `BucketheadBits/Projector/Movement` | `ProjectorMaterial_27mm_speed1_single`, `ProjectorMaterial_27mm_speed2_single`, `ProjectorMaterial_50mm_speed2_single` | 3 |
| `BucketheadBits/Projector/Deployment` | `Projector_Deployment_Blue` (×2), `Projector_Deployment_Red` (×2) | 4 |
| `BucketheadBits/Projector/Range` | `ProjectorMaterial_25mm_token`, `ProjectorMaterial_27mm`, `ProjectorMaterial_50mm` | 3 |
| `BucketheadBits/Projector/Cohesion` | `Cohesion_27mm` | 1 |

→ 11 materials projector au total, 4 shaders distincts à porter en priorité.

### Outils / autres custom
| Shader | Materials | Bundles |
|---|---|---|
| `BucketheadBits/MoveTool` | `Speed1`, `Speed2` | 2 |
| `BucketheadBits/Tokens/Lambert Channel Mask` | `unitIDtoken_1` à `unitIDtoken_10` | 10 |
| `BucketheadBits/Silhouette` | `BucketheadBits_Silhouette` | 1 |
| `BucketheadBits/Units/Color Replacer` | `Ewok_SharedMat` | 1 |
| `DWD/LightenSkybox` | `Skybox` | 1 |

→ Le shader `Tokens/Lambert Channel Mask` correspond aux 10 unitIDtokens loggés en console par TTS lors du bug : "Shader didn't load correctly for AssetBundle material unitIDtoken_X". Donc ce shader est **explicitement confirmé cassé**.

## Auteurs
- Préfixe **`BucketheadBits/`** sur 8/9 shaders → ancien contributeur "Buckethead". Aucun repo GitHub public trouvé sous ce handle. Possible que ce soit un handle alternatif de Tieren (crédité ailleurs comme "original mod creator").
- Préfixe **`DWD/`** sur 1 shader (LightenSkybox) → autre auteur, juste un tint skybox.

## Implications pour la conversation avec Ben

1. **L'angle "Always Included Shaders" n'est pas la bonne piste** pour ce bug, parce que les shaders custom sont embarqués dans les bundles. Si Ben a essayé cette piste, c'est cohérent que ça n'ait rien donné.

2. **Le scope minimum réaliste** : porter / remplacer ces 9 shaders sous Unity 6 (compilation Metal-compatible). Soit en partant des sources s'il les a, soit en réécrivant des équivalents stock.

3. **Materials = 11 projectors + 10 tokens + 4 outils + 1 skybox = 26 materials affectés au total** dans 27 bundles différents. Volumétrie raisonnable si les shaders sont swappable d'un coup.

4. **Type technique des shaders** :
- Les `Projector/*` sont des shaders Unity Projector (transparent, projection avec bandes alternées) — historiquement tricky à porter Metal.
- Le `Tokens/Lambert Channel Mask` est un shader de coloration par canaux (R/G/B/A) — utilisé pour appliquer la couleur du joueur sur un mesh à canaux. Classique mais codé custom.
- Les autres (MoveTool, Silhouette, Color Replacer, LightenSkybox) sont des shaders d'effets simples.

## Sources non-trouvées
- Aucun repo public sous `swlegion`, `swlegion-dev`, `matanlurey`, `halestom15`, `Buckethead` ne contient les sources Unity de ces shaders.
- Le projet Unity vit donc en privé sur la machine d'un contributeur (probablement Decaf ou Ben).

## Prochaine étape
Attendre Ben pour confirmer si les sources sont disponibles. Cet inventaire répond déjà partiellement à ses questions 1 et 2 :
- Q1 ("custom shaders updated or just retargeted ?") : on sait maintenant exactement ce qu'il faut updater.
- Q2 ("which shaders are referenced ?") : liste complète ci-dessus.
Loading
Loading