Экран входа MoonWell и синхронизация с Benilla 0.3.1 #15
Reference in New Issue
Block a user
Delete Branch "login-screen"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Новый экран входа MoonWell: отдельная 3D-сцена лунного колодца, вода с отражением и рябью, падающие листья, лесное окружение, освещающий сцену висп и музыка Song of the Falling Stars. Автоматический вход из лаунчера показывает локализованные этапы со спиннером и выдерживает время показа сцены. Сохранены ручной вход, ruRU, выбор реалма, переключение интерфейса и исходный протокол авторизации.
Интегрированы 17 изменений Benilla от
d9c64230доe5651f0d, включая порядок прозрачных моделей, анимацию idle, вход в мир, шрифты nameplate и Lua. Сохранены графические расширения MoonWell. Версия workspace — 0.3.1.Снимок upstream:
e5651f0ddd. Изменения применены трёхсторонним слиянием от ранее синхронизированного снимкаd9c64230: предыдущая синхронизация попала в main через squash, поэтому обычный merge-base был устаревшим.Проверено на Windows x64:
Ограничения: в workspace-прогоне пропущены 37 проверок внешних аддонов/роликов, в прогоне без dev — 32 проверки внешних аддонов. Тестовая учётная запись не задана, live login/logout не выполнялся. Запуск проверялся без звука. Нативный ввод через инструмент автоматизации в этой сессии не подтвердился также у предыдущего релиза; интерактивная проверка не засчитывается.
`TargetUnit("npc")`, `AssistUnit("npc")` and `SpellTargetUnit("npc")` did nothing with a merchant, gossip or quest window open: the app's unit-token resolver answered nobody for `npc`. In 1.12.1 the resolver (`0x515970`) matches `npc` as a whole token (`0x515bec`, an unbounded compare, so `npctarget` stays unknown) and takes the interaction NPC's guid `[0xb4e2d0]`, which `0x4930d0` writes when the window opens. `npc` now resolves to the held unit `InteractNpc` names. Tests cover the three verbs, a closed window and a streamed-out NPC, and `/script TargetUnit("npc")` typed into the stock chat box. Fixes #707 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>`PLAYER_LOGIN` fired at the end of the UI load, before the player existed: its handlers saw `UnitExists("player")` nil and level, health and XP 0, at every login and `/reload`. Ace2's `OnEnable` runs there. In 1.12.1 the load only arms a one-shot (`0x49011d`). The world-enter cascade fires `PLAYER_LOGIN` if armed (`0x49094b`), then `PLAYER_ENTERING_WORLD` (`0x49096a`), inside a sound-suppression bracket (`0x4908d5`–`0x490a56`). It runs from the player's own create (`0x5deb60`), or on `/reload` from the load (`0x490168`) with the player still in the world. A worldport re-arms nothing. Now the load arms it, and the unit feed fires both, silenced, once the player is seated. A `/reload` loads under the live player and no longer plays the target-select sound. Tests cover login, worldport and reload; they fail without the fix. Fixes #189 Fixes #191 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>bevy/dynamic_linkingin crates/benilla-app (#853) 45da0a0850Lua bindings now read their arguments the way the 1.12.1 client does: - Numeric strings parse as Storm's `SStrToInt` (`0x64ac60`) and `SStrToFloat` (`0x64aaa0`). That covers channel keys, `GetNumber` and `item:` fields. - Flag arguments go through `GetBoolOrDefault` (`0x6f1c10`) with each site's default. That is about 40 bindings, `SetChecked()` and `ShowHelm()` among them. - Colour channels take numeric strings (`lua_tonumber`), and alphas are `isnumber`-gated: no raise, 1.0 by default. A three-argument `SetVertexColor` keeps the current alpha (`0x79ae0a`). So action-bar rings dimmed by a drag stay dimmed, as in 1.12.1. - `SetTexture("1")` takes the colour form. MessageFrame channels follow `0x795590`. - `LoggingChat`/`LoggingCombat` return the flag. Binding-level tests use the reference's values. Fixes #135 Fixes #144 Fixes #160 Fixes #161 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>1.12.1's MSG_MOVE_TELEPORT_ACK handler (0x603f90) reaches none of the loading screen's raises: 0x406800 is entered only from SMSG_TRANSFER_PENDING (0x401900), the glue EnterWorld (0x46b6f1) and 0x407de0. benilla raised the cover on a same-map snap twice over: the "focus not resident" backstop on the snap frame, and a >=100 yd relocation raise. The relocation raise goes, and the backstop stays off while a snap's settle hold is up; the body is held over the destination as before. Verified live against the local realm (map 0, Gmagent): .tele ironforge from Northshire (~3960 yd) and back covered 50 and 93 frames (0-916 ms, 0-1680 ms) before, 0 and 0 after; cross-map .tele valley and back still raise the cover ("worldport"). New tests in loading_screen.rs fail on the old code at the snap frame. benilla-app and benilla-world lib tests green, install-reading tests green with BENILLA_REQUIRE_DATA=1 (the addon corpus is absent on this machine). Built on macOS (arm64). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>In 1.12.1, `TargetByName` (`0x489d60`), `TargetUnit` (`0x4899d0`) and `ClearTarget` (`0x489ff0`) commit through `SetSelection` (`0x493540`) before they return, so the next line of the chunk reads the new target. benilla queued them, so `UnitName("target")` on the next line read the old unit. The bindings now update the `"target"` view and the resolver's guid at once. They rank over a per-frame candidate feed that shares the app scan's candidate test and rank. A pick `SetSelection` refuses (not selectable, `0x4935ee`) leaves the view alone. The unit feed re-pushes the committed selection the next frame. A full tie goes to the lower guid, written as a deviation. Tests: the chunk reads the pick; namesake ties, refused picks and the re-push, in benilla-ui and through the app's real feed. Supersedes #1225, whose branch GitHub would not let us push to. Co-authored-by: kalistoking <148718830+kalistoking@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>Splitting a quest item's stack could flash its objective line ("Wolf Pelt: 4/5"). The toast rode a per-frame diff of the bag count, and a split dips it for a frame: vmangos sends the shrunk source and the new stack's create at once, and the slot naming the new stack later, in the batched update (`Player.cpp:11100`, `10316`–`10327`). 1.12.1 toasts an item objective only from `SMSG_QUESTUPDATE_ADD_ITEM` (`0x5e5ad0`, case 0x19a). It walks the log to the first quest needing the item, and `0x5dd060` shows `ERR_QUEST_ADD_ITEM_SII` with min(held + added, need), then `QUEST_WATCH_UPDATE`. An uncached quest record defers the pair to its arrival (`0x5dd180`). Item lines now toast from that packet alone; kill and complete toasts are unchanged. Tests replay a split's update sequence (no toast) and a pickup (one toast); both fail without the change. Fixes #916 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>Texture paint answered and drew unlike 1.12.1: `SetTexture("")` and non-string names answered nil, a missing file cleared desaturation, `SetTexCoord()` and an unknown `SetBlendMode` passed quietly, a failing bar path still installed a bar, and DISABLE, ALPHAKEY and MOD drew as BLEND. 1.12.1's load (`0x770200`) writes the shader slot only for a file that loads (`0x7702c0`); the binding answers 1 for a null name (`0x79bdae`). The submit draws a coloured DISABLE or ALPHAKEY texture as BLEND (`0x76fb82`); ALPHAKEY alpha-tests at 224/255 and MOD multiplies the destination (DESTCOLOR, ZERO, `0x80a1fc`). Now one texture load serves every setter, the usage lines raise, the shader draws each mode with a MOD pipeline of its own, and a new test validates the UI shader with naga. The stock UI draws as before. Fixes #1425 Fixes #1864 Fixes #1863 Fixes #1521 Fixes #1556 Fixes #1550 Fixes #1559 Fixes #1555 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>feed_party and feed_units share FieldEventPushes with no order between them. When the party feed ran first, TargetFrame's RAID_TARGET_UPDATE handler read GetRaidTargetIndex("target") off the previous snapshot, so a new mark showed over the mob but not on the target frame until the target changed. A UnitSnapshots set holds feed_units, and the party feed runs after it. the_party_feed_runs_after_the_unit_snapshots reads the order off the declared graph; it fails on the tree before this change. Verified: cargo fmt --check, clippy -D warnings, cargo test -p benilla-app --lib (5093 passed). Live on a vmangos server, a build with this change shows raid marks set in a raid on the target frame. Built on macOS only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>A level-60 character entered the world with the XP bar shown instead of the max-level bar. The stock watch bar sets the XP bar from `UnitLevel("player")` on `UPDATE_FACTION` (`ReputationFrame.lua:161-244`). The server sends the faction list before the player's create, and benilla's only login signals came from that first push, before `"player"` was seated, so the bar read level 0 and stayed shown. 1.12.1 rebuilds the list in the world-enter cascade (`0x4909d3` calls `0x4d5430`), after `PLAYER_ENTERING_WORLD`, and that rebuild's sort signals `UPDATE_FACTION` (`0x4d55de` → `0x4d5db0`); the rebuild does nothing without a player (`0x4d5453`). benilla now runs that rebuild in the cascade, and the first push into a VM is silent. A test drives the server's order: level 60 hides the XP bar and shows the max-level art, level 59 the reverse. Fixes #1973 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>In 1.12.1 a verb's effect applies inside the call, whether from a click, `OnUpdate` or an event handler. Here, calls from `OnUpdate` and handlers queued until the next lend, so `TargetByName(name)` then `UnitName("target")` read the old target. - Every system that runs Lua lends the call host around its body, in one ordered VM pass; the cross-entry queue is gone. - Seams that changed units through `Commands` queue unit edits, flushed ahead of their readers, so sync points stay at 54 (main: 53). - Late drains apply before the paint; a CVar or follow ask lands the same frame. - The actionable ambiguity ceiling falls from 3079 to 1750. Tests: an `OnUpdate` cast and a handler's cast arm inside the call, three same-frame drains, and a census that each schedule flushes after every edit user. Lua run inside an engine turn still waits for the turn's end. Part of #1993 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>The console commands and CVar behaviours 1.12.1 has, and Lua's local time. - `date` and `time` use the local zone, `time{}` by `_mktime`'s sum (`0x740811`, `0x740836`); screenshots and the logon challenge's bias follow. - In fullscreen `GetCVar("gxResolution")` answers the screen's own size; the windowed size is what is saved. - The twelve world commands (`0x66f6c0`), with `showDetailDoodads` gating the clutter and `waterRipples` the wakes. - `quit`, `ver`, `setmap`, `showplayer` (`0x6400e0`, `0x4049e0`) and `SkySunGlare` (`0x6d1dc0`). - `ffx`, `ffxGlow`, `ffxDeath` and `ffxRectangle` print enabled or disabled (`0x6cde30`). - `widescreen` 0 gives the four 4:3 modes and a 4:3 portrait aspect. Tests pin each address. Built on macOS; Linux and Windows compiled. Fixes #2231 Fixes #2232 Fixes #1628 Fixes #1641 Fixes #1667 Fixes #2098 Fixes #1687 Fixes #1665 Part of #1577 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>The unit getters read the live object, as 1.12.1 does (`UnitHealth` reads `+0x40`, `0x5174d0`), through a new call-host member, `UnitLive`. - **What reads live:** 21 getters read their field off the unit's object as of the listener's own packet. These include health and power, level, dead and ghost, tapped, charmed, combat, PvP and sex. Getters that read no object field skip the lookup. With no host lent, the snapshot answers. - **One shared reader:** a single trait reads both paths, so they can't drift. A test pins 39 getters × 6 tokens equal. - **A visible fix:** `TargetUnit("party1")` then `UnitHealth("target")` in one chunk now reads the new target's health, where it read 0. - **Cost:** about 80 ns per call. The raid update storm is within 1% of main. `GuidIndex` hashes with foldhash. Part of #2217 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>The stat and player-field getters answered from a copy pushed at the frame's end. So a `UNIT_STATS`, `PLAYER_XP_UPDATE` or `PLAYER_MONEY` listener read the frame's last packet, not its own. 1.12.1's getters read the object inside the call: for example `UnitStat` at `0x518600`, `GetMoney` at `+0xf70` (`0x518160`), and dodge, block and parry at `+0xe5c`/`+0xe58`/`+0xe60`. Twenty-five getters now read live through the lent call host, among them `UnitStat`, resistances, armor, damage, attack power, defense, the avoidance chances, money, XP and rest. The snapshot and the live read share one derivation. Worn weapons resolve through the per-packet views. With no player held, the getters answer 0 or nil, as the reference does. Tests: live against snapshot for every getter across four tokens, gear and buffs included; each listener reading its own packet's value. Cost: `UnitStat('player')` takes 344 ns live, against 261 ns from the snapshot. Part of #2217 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>`UnitBuff`, `UnitDebuff` and the tooltip's `SetUnitBuff`/`SetUnitDebuff` answered from a list pushed per frame. So a chunk that changed its target and then read `UnitDebuff("target")` saw the old target's auras. A listener whose later packet charmed us also saw a stale gate. 1.12.1 reads the unit object inside the call (`0x519500`, `0x5198f0`). That covers the aura slots, the flags nibble, applications and level; the gate is unit flags bit 27, `CanAssist` and our charmer (`0x5195f1`). A member out of view answers from the roster record, read by guid at the call. These getters now read live through the call host, through one derivation shared with the snapshot. `GetPlayerBuff*` stays as it is: it reads client state rebuilt per packet. Tests: live against snapshot across seven tokens with stacked, Magic, Curse and hidden auras, and the three cases that fail on main. Cost: about 50 ns per call. Part of #2217 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>The `target` and `npc` tokens read guids pushed into the VM at frame end. A target whose object the server released was torn down by a frame-end system, after later packets' listeners. In 1.12.1 the tokens read the target and npc globals at the call (`0x515a86`, `0x515c00`). The release (`CGUnit_C::Release 0x5fbb60`) ends a target in place (`0x5fbbe5`), except a group member's, whose guid stays (`0x5fbbcd`). Now both tokens read live through the call host, and the npc is the raw interaction guid. For a game object, `UnitName("npc")` names it (`0x5f8100`) and `UnitExists` is nil. The teardown runs inside the release on a new lane. A reconnect clears the old selection. Tests: a live target and npc, a game-object quest giver's name, the release firing `PLAYER_TARGET_CHANGED` between two packets' events, and a reconnect. All fail on main. Part of #2217 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>Fifteen UI API fixes. - **Text and names.** FontString text, buttons, tooltips, names and bubbles apply the `|1`/`|2` grammar escapes (`0x7716f0`). Rank names count code points. - **Raid.** The raid roster selection stores the member's guid, survives a /reload, and clears at world login. - **World states.** Each world-state packet fires WORLD_MAP_UPDATE then UPDATE_WORLD_STATES at its place. - **Events.** DISPLAY_SIZE_CHANGED fires below scale 0.64. UPDATE_CHAT_COLOR carries the caller's name. - **CVars.** Four refuse what 1.12.1 refuses, and anisotropic and ErrorLevel print its console lines. - **Calls.** GuildSetLeaderByName("target") sends no name. Repair costs read by row position. Quest reward slots count to the first empty one. OfferPetition checks its eight guards. - **Glue and errors.** The glue VM has the file calls. Widget methods share one wrong-receiver text. Fixes #2507 Fixes #2557 Fixes #2559 Fixes #2567 Fixes #2568 Fixes #2581 Fixes #2588 Fixes #2593 Fixes #2599 Fixes #2606 Fixes #2615 Fixes #2623 Fixes #2630 Fixes #2687 Fixes #2688 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>Bag and item reads now answer as of the listener's own packet, not the frame's end, and the logout reads what 1.12.1 has there. - The bag getters read the player's bags, the bank and the keyring live. Item and container writes go into the view log, so a listener sees its packet's slots, stacks and bags. - The loot close's two unlocks fire at its packet (`0x48f2bd`, `0x4c1d36`). A wrong-bag refusal names the bag its packet found (`0x5e3a1e` → `0x5ede00`). - At logout the object manager goes before PLAYER_LOGOUT fires (`0x46771e`, `0x490c2a`). The inventory getters then answer nothing with no active player (`0x4944a0` → `0x4c8c56`). `UnitName("player")` keeps the character's name. - The item tooltip feed follows record changes by cursor. The suffix template is copied after the frame's Lua. Each change has a test that fails without it. flip_readiness falls to 92 rows. Fixes #2725 Refs #2168 Refs #2217 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>A mouse command run from a key binding or a handler picked and clicked only after the record's walk returned. So a body `CameraOrSelectOrMoveStart(); CameraOrSelectOrMoveStop(); print(UnitName("target"))` printed the old target. In 1.12.1 `ArmClick` picks inside the Start's call (`0x5141ae` → `0x514810` → `0x481f00`), at the cursor stored from the last mouse event (`0x481f1d`), and the Stop dispatches inside its own. The records' walk now lends a tracer beside the call host, so an arm picks inside its call at its record's cursor: one trace per arm, and no new schedule ambiguity. The pick traces the world alone (`0x481190`), never a nameplate. The GameObject pick set is now one resource, kept every frame ahead of the input. Tests cover a key body, an `OnClick` body, the target event in the handler, a key-armed pick under a plate, and a chest clicked by mouse and by key. Fixes #2749 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>Spell and aura tooltips, `SpellCanTargetUnit` and the `"mouseover"` getters read a copy pushed once a frame. A listener inside a packet saw the last frame's values, and `GetRaidTargetIndex("mouseover")` was always nil. Reference: the setters build the view at the call (`0x52e610`, `0x52f880`). `SpellCanTargetUnit` reads the unit and range at the call (`0x6e6d00` → `0x6e6460`). A reagent's record answer rebuilds a shown spell tooltip (`0x52f820`). Changed: - the setters build through the call host; - the frame feed and its re-push machinery are gone; - targeting and the mouseover read live; - a reagent's answer rebuilds the shown tooltip. The hover's guard rows cite the cache callbacks that rebuild it inside packets. Tests: a trainer listener's `SetSpell` reads its own packet's cost. Also covered: `SpellCanTargetUnit` out of range, the mouseover mark, the reagent rebuild, and the pet and aura views. Part of #2168. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>SetCVar ran its change callback and its effect in the frame's later sync, and SetView, SaveView and ResetView queued their camera writes for a drain. A script that read the effect on its next line saw the old value. Reference: `CVar::Set` (`0x63df50`) runs the row's callback inside the call (`0x63df7d`), and a refusal drops the set. CVAR_UPDATE follows from `SetCVar` (`0x488cad`). SetView writes `cameraView` in its call (`0x512f17`), and SaveView writes its view there too (`0x50fa09`). Changed: - the 23 callbacks, once observers, are plain functions the host runs in the call; - the knobs they write became host state, with their readers ordered around the VM pass; - `drain_view_requests` is gone. Tests: SetCVar("deselectOnClick","0"), then a click on empty world on the chunk's next line, keeps the target. A view verb's CVar reads on the next line. Part of #2202. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>Five group, guild and spell-target defects in the Lua API. - The looking-for-group reply (`0x4e8dc0`) filled nothing and `UPDATE_LFG_LIST` never fired. The list now fills with the reference's caps (50 records, name 0x30, comment 0x80) and signals once its quest titles are known. Deviation: a login starts with an empty list, where 1.12.1's getters read leftover memory. - `SMSG_GROUP_CANCEL` reads the name it drops and fires `PARTY_INVITE_CANCEL` (`0x5e6770`, `0x48f440`). - `GuildSetMOTD("")` sends no string (`0x48b2c1`-`0x48b2da`). - `SpellCanTargetUnit` passes a unit on any arm (`0x6e6460`). A unit or corpse click that leaves bits in the word holds the spell, and the send carries the mask its binds gathered (`0xceac5c`, `0x7e4e10`). Each new wire body has a byte-exact golden, and each fix has a unit test. Fixes #2583 Fixes #2569 Fixes #2609 Fixes #2133 Closes #2666 (fixed by #2691) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>A release bump changes only `[workspace.package] version` in `Cargo.toml` and the lock's entries for the workspace's own crates. The gates' memo counted only docs as unread, so the 0.3.0 bump would have rerun the whole chain on a tree whose parent had just passed it. No gate reads the version: it reaches only the launchers' `env!("CARGO_PKG_VERSION")`, and the build-id tests pass their own strings. `docs_only_delta` now also keeps the verdict when `Cargo.toml` and `Cargo.lock` differ in nothing but those version lines, compared with each file's workspace versions blanked. Checked on history: the 0.3.0 bump keeps the verdict; a code commit, a dependency version in the lock, a changed edition, and the bump together with its parent's code each rerun. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>An edit box always drew its text left-aligned: `SetJustifyH("RIGHT")` or `("CENTER")` moved only the `OnCursorChanged` x. In 1.12.1 the box's `SetJustifyH` writes the box's own font (`0x797a17`, `+0x324`) through the shared setter `0x79fc20`, which pushes the change to the label linked to that font (`0x779c27`). `SetMultiLine` cuts off only the label's vertical bits (`0x77a509`, `0x77a599`), so the horizontal justify draws. The box's font now exists with its label, justified `LEFT` as the constructor leaves it (`0x779bd2`). The four justify methods act on that font, the label no longer pins H, and the caret reads the label's justify. The separate justify word on the box is gone. Test: `the_text_draws_by_the_boxs_justify_h_and_its_own_justify_v` checks the drawn H follows `SetJustifyH` while V stays the box's own. Without the fix, RIGHT draws LEFT. Fixes #2977 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>e5651f0dи сохранить расширения MoonWell 1b4b6e4de6