What the second player actually saw: four panel entries and no nameplates
A second player's four `/errors` entries, all from one session, none of them a
fault in the two addons he was reporting:
1. `FloatingChatFrame.xml: SetScript("OnInputLanguageChanged") unsupported`.
Ours. The slot is real 1.12 and the *realm's own* FrameXML sets it on
`ChatFrameEditBox`, so every player met a red error on every login for a
line none of them wrote. `SCRIPT_KINDS` now accepts it and never fires it,
which is also what the reference does — a client with no IME never fires it
either. The rule the old test stated is unchanged and restated: a 1.12 slot
benilla neither fires nor finds in a shipped file still raises.
2. `bindings.xml: root element is <Bindings>, not <Ui>; tolerated`. Every
`Bindings.xml` in the corpus has that root and `bindings_xml` reads it
correctly. No longer said.
3. `bindings.xml: Unknown frame type: Binding`, counted 69. Faithful — the
reference logs the same line (`0x871124`) for every row while `0x51f400`
registers them separately — and ours registers them too:
AlternativeClassicActionBars' 69 bindings all answer `GetBinding`. Now a
trace, so the terminal keeps it and the panel does not.
4. `SetOwner: unknown anchor 'BOTTOMRIGHT' on owner 'WorldFrame'`, counted 292.
The hunt for that caller ended a while ago: it is `Shop_ProcessEntries` in
the realm's own `Turtle_ShopUI`, off the player's patch chain, and the
reference accepts an unknown anchorType silently (mode 0, ANCHOR_LEFT), as
we do. The diagnostic has done its job; it is now host-log-once
(`Model::warn_host_only_once`) and not retained.
The panel is where someone looks to find what is broken in *their* interface.
A line that is faithful, or names a file they cannot reach, crowds out the ones
that are theirs.
----
A second player sent a video: Options → Nameplates with all six boxes ticked,
the V binding set, and no plates at all — while the overhead *names* drew fine.
`VPlateMode::default().range_sq` was `0.0`, and the gate is
`distance_squared > range_sq`. Zero is not "no cull"; it is "cull everything, at
any distance". `NameplateRange` is a registered CVar with default `"80"`, and a
registered default is not written to `config.toml`, so no `CvarChanged` ever
fired and the field never left its derived value.
This is the trap the paragraph three fields above already documents, and which
`occlusion` and `spread` were fixed by writing their registered defaults into
`Default`; `range_sq` was left behind. It stayed hidden because
`NameConfig::default()` — the overhead names — already carried `80.0 * 80.0`, so
names drew and only plates were missing, which reads as a nameplate-addon
problem rather than an engine one. It could not be reproduced here either:
grom's own `config.toml` carries `NP_NameplateDistance = "62"`, which seeds the
same field through the other observer arm.
`the_plate_range_default_agrees_with_its_registered_cvar` now pins the default
to `registered_pairs()`'s row and pins the plate and the name culls to each
other, since a disagreement between those two is what made this read as
somebody else's bug.
It also answers the other half of his report. The gate `continue`s before the
plate is seated at all, so with `range_sq` at 0 no plate frame ever exists —
and UnitPlates works by adopting the plate frames under WorldFrame. One bug,
both symptoms: "nameplates will not turn on" and "UnitPlates does nothing" are
the same line.
And a packaging answer that comes before both, for UnitPlates specifically:
GitHub's "Download ZIP" unpacks `Redbu11dev/UnitPlates` as `UnitPlates-main`
with `UnitPlates.toc` inside it. The client looks for `<Folder>/<Folder>.toc`,
so the addon never loads — here or on the real client. The harness says it in
as many words: "no manifest under other-addons/UnitPlates-main — is that an
addon folder?". It has to be renamed `UnitPlates`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
@@ -140,10 +140,15 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
// in TurtleWoW's own `Interface\FrameXML\Turtle_ShopUI`, off the
|
||||
// player's patch chain: not an addon, not ours, nothing the player
|
||||
// can fix, and our mode-0 fallback already matches the reference. 283
|
||||
// identical lines a session bury every other warning in the log; the
|
||||
// first is still the whole diagnostic, and the retained row's `count`
|
||||
// keeps the true total for `BenillaScriptLogFrame`.
|
||||
model.record_warning_once(format!(
|
||||
// identical lines a session bury every other warning in the log.
|
||||
//
|
||||
// And `warn_host_only_once`, not `record_warning_once`: the retained
|
||||
// row showed up in the player's own `/errors` panel as one entry
|
||||
// counted 292 times, next to the faults that *are* theirs, for a call
|
||||
// the reference itself accepts silently (see the mode-0 note above)
|
||||
// from a file off their patch chain. The terminal and the session log
|
||||
// still carry the full diagnostic, once.
|
||||
model.warn_host_only_once(format!(
|
||||
"SetOwner: unknown anchor '{other}' on owner '{owner_name}' \
|
||||
from {site} (mode 0, ANCHOR_LEFT)"
|
||||
));
|
||||
@@ -512,10 +517,15 @@ mod tests {
|
||||
}
|
||||
|
||||
/// The hunt is over, so the repeats are noise: one terminal line per distinct `(anchor, owner,
|
||||
/// site)`, while the retained log still counts every occurrence. The caller the diagnostic
|
||||
/// found is `Shop_ProcessEntries` in TurtleWoW's own `Interface\FrameXML\Turtle_ShopUI` — off
|
||||
/// the player's patch chain, so nothing in the session can stop it calling, and 283 copies of
|
||||
/// one unfixable warning bury every other line in the log.
|
||||
/// site)`, and **nothing retained**. The caller the diagnostic found is `Shop_ProcessEntries`
|
||||
/// in TurtleWoW's own `Interface\FrameXML\Turtle_ShopUI` — off the player's patch chain, so
|
||||
/// nothing in the session can stop it calling, and 283 copies of one unfixable warning bury
|
||||
/// every other line in the log.
|
||||
///
|
||||
/// It stopped being retained when a second player's `/errors` opened on four entries and one
|
||||
/// of them was this, counted 292 times, for a call the reference itself accepts silently
|
||||
/// (the mode-0 note on `SetOwner` above). A panel someone reads to find what is broken in
|
||||
/// their own interface must not lead with the one line that is not theirs.
|
||||
#[test]
|
||||
fn a_repeated_unknown_anchor_reaches_the_host_once_and_the_retained_row_counts_them_all() {
|
||||
let mut s = UiScript::new().unwrap();
|
||||
@@ -541,14 +551,12 @@ mod tests {
|
||||
host[0].contains("on owner 'NoisyHost'") && host[0].contains("ShopProcessEntries"),
|
||||
"the one line kept must still name the owner and the call site: {host:#?}"
|
||||
);
|
||||
let row = s
|
||||
.diagnostics()
|
||||
.into_iter()
|
||||
.find(|d| d.message.contains("unknown anchor 'BOTTOMRIGHT'"))
|
||||
.expect("the warning is retained for the player's log");
|
||||
assert_eq!(
|
||||
row.count, 283,
|
||||
"…and nothing is lost: the retained row carries the true total"
|
||||
assert!(
|
||||
!s.diagnostics()
|
||||
.into_iter()
|
||||
.any(|d| d.message.contains("unknown anchor 'BOTTOMRIGHT'")),
|
||||
"…and the player's retained log takes none of it: the session log has the line, and \
|
||||
`/errors` is for faults the player can act on"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user