Files
benilla-octo/crates
Sam SungandClaude Opus 5.5 44fb6e5e43 spell tooltip feed: each pushed view records what it read, and a change of the player's state rebuilds only the views that read it (#650)
Every spell-tooltip invalidation rebuilt every view the feed had ever pushed. The remembered set only grows: the book, every talent rank and trainer service, and every aura ever seen. So in a long session each of these frame-hitched for 1.5 to 4 ms:
- a crit or dodge change;
- a worn-slot change;
- a target swap while auto-attacking;
- a spell-modifier packet;
- a reagent cast.

The reference builds a tooltip at the hover (`0x52e610`) and keeps nothing. benilla pushes views ahead of the hover, so it has to know what each view was built from.

Each pushed view now records, as it is built, the inputs it read: the `$z` home area, the form line, the worn slots the equipped-item search reads, and so on. Each record sits at the line that reads the input.

The inputs:
- the `$z` home area;
- the form line (a spell with `Stances`);
- the worn slots the equipped-item search reads, each slot's item, template and broken state, and the disarm flag;
- the chance line's percentage (`Effect[0]` 20, 22, 23, 78);
- the combat reach the range cell reads;
- the skill lines the `$`-tokens scale by, the spell's own and those of each spell it cross-references;
- the modifier family-flag bits of the spell and of those it cross-references;
- the reagents it lists;
- the player's level, base mana, max health and max power where the cost or cast cell reads them;
- the ranged attack time the cooldown cell pads by.

The feed diffs those inputs frame to frame and rebuilds only the views whose recorded reads intersect what moved. A class-family change still rebuilds everything, and the pet's own inputs still rebuild the pet views.

The feed moves out of `ui_tooltip/mod.rs` into `spell_feed.rs` (the builder and the system) and `spell_deps.rs` (the records and the diff). `TokenContext::home_area` becomes a closure, so a `$z` read is recorded exactly.

Measured in release on the real data with 2,000 remembered ids, per forced change:
- crit or dodge: 3.3 ms → 26-38 µs;
- one worn slot: 3.5 ms → ~100 µs;
- one modifier cell: 3.5 ms → ~60 µs;
- all 64 modifier bits: 3.5 ms → ~0.6 ms;
- reach: 3.3 ms → 1.3 ms, still high because the range cell also pads ranged rows by reach (#643);
- a quiet frame: unchanged.

The bench is `ui_tooltip/bench.rs`, `#[ignore]`d.

Tests:
- `deps_tests.rs`, the safety net, builds all 22,357 real views. For each input it moves the input alone and fails on any view that changed without having recorded it, naming the spell and the input.
- It also moves everything each view did not record at once, from both sides.
- It pokes every player-store field (and every pet-store field for the pet views) to discover reads mechanically.
- It enumerates the equipment slot states the item search distinguishes.
- `feed_tests.rs` drives `feed_spell_tooltips` itself. A dodge change re-pushes only the dodge chance-line view, and a modifier cell only its family's views.

Fixes #535

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 01:22:18 +07:00
..