String literals in benilla-ui, -world and -formats carry no record numbers (#299)
Part of #92, for `benilla-ui`, `benilla-world` and `benilla-formats`. - 88 string literals drop private record and bug numbers, the dates of private incidents, and the workspace's name for the maintainer. They are assert and panic texts, log and printout lines, the `--` comments of the Lua prelude and of test fixtures, and one Lua assert. Each keeps its fact in its own words. - Two test names lose their numbers: `burning_steppes_lava_builds_a_magma_surface_at_the_reported_pin` and `join_channel_by_name_answers_the_row_custom_and_nil_legs`. - A test-only event, `B271_PROBE`, is now `ERROR_PROBE` in the two crates that register and fire it. A fixture's error text in `benilla-app`'s `ui_script` tests drops its bug number, together with the assertion that reads it. - Doc comments that named a client function by a disassembler's label (`FUN_0068a830`) now give its address, in `benilla-formats`, `benilla-assets` and one `benilla-app` file. - Every literal change keeps each literal's line count, proven with comments stripped and every literal masked. The two renamed tests differ only in their names. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed by
GitHub
co-authored by
Claude Opus 5.5
parent
0092ad574d
commit
fe16ed14b3
@@ -90,9 +90,9 @@ fn error_message_is_the_installed_handler_and_the_host_channel_stays_sighted() {
|
||||
"reported"
|
||||
);
|
||||
// An engine-caught error still lands in `errors()`; the dispatch adds the dialog on top.
|
||||
s.run("BrokenProbe = CreateFrame('Frame') BrokenProbe:RegisterEvent('B271_PROBE') BrokenProbe:SetScript('OnEvent', function() error('fault') end)")
|
||||
s.run("BrokenProbe = CreateFrame('Frame') BrokenProbe:RegisterEvent('ERROR_PROBE') BrokenProbe:SetScript('OnEvent', function() error('fault') end)")
|
||||
.unwrap();
|
||||
s.fire_event("B271_PROBE", vec![]);
|
||||
s.fire_event("ERROR_PROBE", vec![]);
|
||||
assert!(
|
||||
s.errors().iter().any(|e| e.contains("fault")),
|
||||
"engine-caught errors stay on the host channel: {:?}",
|
||||
|
||||
@@ -542,7 +542,7 @@ fn an_addon_error_while_entering_world_reports_on_screen_and_the_sibling_loads()
|
||||
let dir = tmp.join("benilla-config/AddOns/AaBroken");
|
||||
std::fs::create_dir_all(&dir).expect("broken addon dir");
|
||||
std::fs::write(dir.join("AaBroken.toc"), "## Interface: 11200\nboom.lua\n").expect("toc");
|
||||
std::fs::write(dir.join("boom.lua"), "error('B271: file-scope boom')\n").expect("lua");
|
||||
std::fs::write(dir.join("boom.lua"), "error('file-scope boom')\n").expect("lua");
|
||||
let mut world = booted_world();
|
||||
|
||||
log_in_as(&mut world, "Onehunter", 1);
|
||||
@@ -569,7 +569,7 @@ fn an_addon_error_while_entering_world_reports_on_screen_and_the_sibling_loads()
|
||||
.expect("eval")
|
||||
.unwrap_or_default();
|
||||
assert!(
|
||||
shown.contains("B271: file-scope boom"),
|
||||
shown.contains("file-scope boom"),
|
||||
"the dialog names the actual error, got: {shown:?}"
|
||||
);
|
||||
drop(script);
|
||||
|
||||
@@ -238,7 +238,7 @@ pub(super) fn build_nodes(
|
||||
Some((map_id, ui, resolved))
|
||||
}
|
||||
|
||||
/// The message an `SMSG_ACTIVATETAXIREPLY` code shows: the reference's handler (`FUN_005ed1e0`)
|
||||
/// The message an `SMSG_ACTIVATETAXIREPLY` code shows: the reference's handler (`0x5ed1e0`)
|
||||
/// closes the map on 0, shows `[0x85fedc + 4*code]` through `DisplayError` (`0x496720`) for
|
||||
/// 1-12, and does nothing from 13 up. The message row picks the surface, the yellow info line for
|
||||
/// seven of the twelve, and the sound: `ERR_TAXINOTENOUGHMONEY` speaks line `0x36`.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! The WMO interior minimap tile grid: how one group's footprint splits into the
|
||||
//! `<wmo>_<group>_<X>_<Y>.blp` tiles the client streams inside a building (tile producer
|
||||
//! `0x6a5270`). Each tile is a power-of-two texel square clamped to 32..256 px at 0.5 yd a texel,
|
||||
//! and both roundings go up: the round-to-int (`FUN_0073fdf5`) runs round-toward-+∞, so the edge
|
||||
//! and both roundings go up: the round-to-int (`0x73fdf5`) runs round-toward-+∞, so the edge
|
||||
//! is `2^ceil(log2(extent·2))` px and the count `ceil(extent / 128)`.
|
||||
|
||||
/// World yards per minimap texel (`0xca7ebc`).
|
||||
|
||||
@@ -94,7 +94,7 @@ fn anim_time() -> f32 {
|
||||
return w.anim.w * globals.time;
|
||||
}
|
||||
|
||||
// The 24 fps flip, 30 frames over 1.25 s (`FUN_0068aac0`), floored to a whole frame.
|
||||
// The 24 fps flip, 30 frames over 1.25 s (`0x68aac0`), floored to a whole frame.
|
||||
fn frame_layer() -> i32 {
|
||||
return i32(floor(anim_time() * 24.0) % max(w.anim.y, 1.0));
|
||||
}
|
||||
@@ -153,7 +153,7 @@ fn vertex(in: Vertex) -> LiquidVsOut {
|
||||
|
||||
// ── The ADT depth swatch ─────────────────────────────────────────────────────────────────────
|
||||
//
|
||||
// `FUN_0068a830` fills an 8×64 texture, each row the same across its 8 columns, with an exact
|
||||
// `0x68a830` fills an 8×64 texture, each row the same across its 8 columns, with an exact
|
||||
// byte-space integer accumulator, `row(i) = c0 + floor(i * (c1 - c0) / 64)` for i = 0..63, so
|
||||
// row 63 stops short of the deep endpoint. On the ocean (selector 0) the last row's HSV value is
|
||||
// scaled by 0.9 (`0x68aa13`, `[0x8102ec]`), which `floor(0.9 * byte)` reproduces within 1/255,
|
||||
@@ -210,8 +210,8 @@ fn fragment(in: LiquidVsOut) -> @location(0) vec4<f32> {
|
||||
}
|
||||
|
||||
// V, from the authored depth byte CPU-side: clamp(byte/42) on river/lake (LUT `0xc81768`,
|
||||
// `FUN_0068d790`, saturating near 5 yd), clamp(byte/255) on ocean (LUT `0xc7fcd8`,
|
||||
// `FUN_0068d690`), both built in `FUN_0068c4c0`. One V indexes colour and alpha alike.
|
||||
// `0x68d790`, saturating near 5 yd), clamp(byte/255) on ocean (LUT `0xc7fcd8`,
|
||||
// `0x68d690`), both built in `0x68c4c0`. One V indexes colour and alpha alike.
|
||||
let depth = clamp(in.depth, 0.0, 1.0);
|
||||
var shallow = wow_light.water_river[0];
|
||||
var deep = wow_light.water_river[1];
|
||||
|
||||
@@ -196,7 +196,7 @@ fn mcnk_cell_anchor(P: vec3<f32>) -> vec3<f32> {
|
||||
}
|
||||
|
||||
#ifdef WOW_MERGED_FADE
|
||||
// The doodad fade curve (`FUN_00683f80`, in sync with `model_fade::doodad_fade_alpha`): alpha =
|
||||
// The doodad fade curve (`0x683f80`, in sync with `model_fade::doodad_fade_alpha`): alpha =
|
||||
// 1 − (d − start)/range, d = horizontal distance − radius, over a size-bucketed band.
|
||||
fn merged_fade_alpha(radius: f32, horiz_dist: f32) -> f32 {
|
||||
if (radius > 7.0) {
|
||||
@@ -574,7 +574,7 @@ fn fragment(in: WowVsOut, @builtin(front_facing) is_front: bool) -> WowFragOut {
|
||||
// `wow_normalize`: an authored zero normal reaches here on the unskinned lane.
|
||||
let n_m2 = wow_normalize(pbr_input.world_normal);
|
||||
// Bevy negates `world_normal` on back faces of double-sided materials (foliage, every WMO
|
||||
// face); the reference never enables GL_LIGHT_MODEL_TWO_SIDE (`FUN_0059ce30`), so undo it.
|
||||
// face); the reference never enables GL_LIGHT_MODEL_TWO_SIDE (`0x59ce30`), so undo it.
|
||||
let n_lit = select(-n_m2, n_m2, is_front);
|
||||
let ndotl = max(dot(n_lit, L), 0.0);
|
||||
let lit_nl = clamp(wow_light.light_ambient.rgb + wow_light.light_diffuse.rgb * ndotl, vec3<f32>(0.0), vec3<f32>(1.0));
|
||||
|
||||
@@ -22,8 +22,8 @@ fn type_name(ty: i32) -> &'static str {
|
||||
char_proc_type::TINT => "TINT (body RGB)",
|
||||
char_proc_type::ALPHA => "ALPHA (body translucency)",
|
||||
char_proc_type::ANIM_RATE => "ANIM_RATE (body anim playback rate — 0 freezes the pose)",
|
||||
char_proc_type::CHAIN_CHANNEL => "CHAIN (beam; the channel-stage key — 0955)",
|
||||
char_proc_type::CHAIN_CAST => "CHAIN (beam; the cast-stage key — 0955)",
|
||||
char_proc_type::CHAIN_CHANNEL => "CHAIN (beam; the channel-stage key)",
|
||||
char_proc_type::CHAIN_CAST => "CHAIN (beam; the cast-stage key)",
|
||||
char_proc_type::WEAPON_TRAIL => "TRAIL (weapon swing ribbon, $WTB→$WTT)",
|
||||
_ => "(unmodelled)",
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ pub fn darkpropscan(chain: &mut Chain, prefix: Option<&str>) -> Result<()> {
|
||||
"{roots_scanned} root(s), {modds_total} MODD(s): {zero_colour} carry colour #000000; \
|
||||
of those, interior-ONLY = {} — {black} BLACK (no MOLR light in range), {dim} dim \
|
||||
(a fixture light reaches them). RESCUED by exterior-wins: {rescued} (an interior group \
|
||||
names them first, an exterior group also names them — sky-lit, decision 0969).",
|
||||
names them first, an exterior group also names them — sky-lit).",
|
||||
black + dim,
|
||||
);
|
||||
if !by_model.is_empty() {
|
||||
|
||||
@@ -1418,7 +1418,7 @@ pub fn fxuvscan(chain: &mut Chain, prefix: Option<&str>) -> Result<()> {
|
||||
);
|
||||
println!(
|
||||
" {anim_models} model(s) / {anim_batches} batch(es) carry a keyed TEXTURE TRANSFORM — \
|
||||
the channel the spell-effect lane has run since 2282 and the entity lane since 2295"
|
||||
the channel the spell-effect lane and the entity lane both run"
|
||||
);
|
||||
println!(" {:<10} {:>8} {:>9}", "", "identity", "first-key");
|
||||
for c in FxClass::ALL {
|
||||
@@ -1438,8 +1438,8 @@ pub fn fxuvscan(chain: &mut Chain, prefix: Option<&str>) -> Result<()> {
|
||||
);
|
||||
println!(
|
||||
" the two columns are the two frozen states a non-running lane can be in: `identity` \
|
||||
is a material built with `play_uv = false` (the AUTHORED UVs — what the spell-effect \
|
||||
lane drew before 2282 and the entity lane before 2295), `first-key` what the same \
|
||||
is a material built with `play_uv = false` (the AUTHORED UVs, drawn \
|
||||
untransformed), `first-key` what the same \
|
||||
batch becomes on a lane that seeds `uv_anim.sample(0.0)` and never ticks it. \
|
||||
{seed_disagrees} batch(es) are classified differently by the two — read the per-batch \
|
||||
lines for which."
|
||||
@@ -1679,7 +1679,7 @@ impl EntityReach {
|
||||
parts.push(format!("bone pile {}", self.bones.join(",")));
|
||||
}
|
||||
if self.also_fx {
|
||||
parts.push("ALSO a spell-visual model (2282's lane runs its transform)".to_string());
|
||||
parts.push("ALSO a spell-visual model (whose lane runs its transform)".to_string());
|
||||
}
|
||||
parts.join(" · ")
|
||||
}
|
||||
@@ -1897,11 +1897,11 @@ impl UvClock {
|
||||
match self {
|
||||
Self::Gseq => {
|
||||
"every live loop rides a GLOBAL SEQUENCE — a free-running clock, so one shared \
|
||||
material uniform is faithful (0136 choice 1)"
|
||||
material uniform is faithful"
|
||||
}
|
||||
Self::Band => {
|
||||
"every live loop rides its SEQUENCE BAND — the instance's own play head, which a \
|
||||
shared uniform cannot serve (2282's per-instance lane)"
|
||||
shared uniform cannot serve (a per-instance lane can)"
|
||||
}
|
||||
Self::Mixed => "the batch's channels disagree: some global-sequence, some band",
|
||||
Self::Hold => {
|
||||
@@ -2315,7 +2315,7 @@ pub fn entityuvscan(chain: &mut Chain, prefix: Option<&str>) -> Result<()> {
|
||||
);
|
||||
println!(
|
||||
" {anim_models} model(s) / {anim_batches} batch(es) carry a keyed TEXTURE TRANSFORM — the \
|
||||
channel `entity_variants` seeds and registers since 2295 ({no_uvs} more are keyed but \
|
||||
channel `entity_variants` seeds and registers ({no_uvs} more are keyed but \
|
||||
carry no UVs to transform)"
|
||||
);
|
||||
println!(
|
||||
|
||||
@@ -244,7 +244,7 @@ pub fn goanimscan(chain: &mut Chain) -> Result<()> {
|
||||
" arming a LOOPING band on a transition (motion) substate: {looping_motion} \
|
||||
({looping_motion_sensitive} of them state-SENSITIVE, i.e. the transition is a clip the \
|
||||
rest pose isn't) — the completion advance is the only thing that ends these; read \
|
||||
as \"should this clip repeat?\" they swing for ever (decision 1151)"
|
||||
as \"should this clip repeat?\" they swing for ever"
|
||||
);
|
||||
println!(
|
||||
" authoring a non-empty replay range on a reachable substate: {multi_replay} — R > 1 \
|
||||
@@ -644,8 +644,8 @@ pub fn soundeventscan(chain: &mut Chain, prefix: Option<&str>) -> Result<()> {
|
||||
eprintln!(
|
||||
"{scanned} models with sequences scanned; {carriers} carry a $DSL/$DSO/$SND marker, \
|
||||
{hostless} of them on the Static tier (no anim-root entity exists to hang an emitter \
|
||||
on today); {rest_gated} carry the marker on a REST-posed sequence — the class benilla's rig gate \
|
||||
(decision 0130) never arms, so the marker is unreachable through an AnimationPlayer."
|
||||
on today); {rest_gated} carry the marker on a REST-posed sequence — the class \
|
||||
benilla's rig gate never arms, so the marker is unreachable through an AnimationPlayer."
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -209,8 +209,8 @@ pub fn skyboxscan(chain: &mut Chain) -> Result<()> {
|
||||
both halves matter — but this census establishes only 'flag implies MOSB'."
|
||||
);
|
||||
println!(
|
||||
" It does NOT say WHICH group the renderer tests, and reading it as if it did is the \
|
||||
mistake decision 0767 made (superseded by 0773). The actual law: 0x40000 is tested \
|
||||
" It does NOT say WHICH group the renderer tests, and reading it as if it did is a \
|
||||
mistake. The actual law: 0x40000 is tested \
|
||||
inside the portal flood (0x6b42e0 in 0x6b41c0) on the group being VISITED, never on the \
|
||||
group the camera stands in — so the predicate is 'any FLOOD-REACHED group carries the \
|
||||
bit, and the root names a MOSB'. Stratholme's King's Square is the counter-example that \
|
||||
|
||||
@@ -31,7 +31,7 @@ fn main() {
|
||||
}
|
||||
// `Chain::read` names a delete-marked path in its error message.
|
||||
Err(e) if e.to_string().contains("deleted from patch chain") => {
|
||||
eprintln!("{e} — the client does not load this path (see decision 0246)");
|
||||
eprintln!("{e} — the client does not load this path");
|
||||
std::process::exit(2);
|
||||
}
|
||||
Err(e) => {
|
||||
|
||||
@@ -577,7 +577,7 @@ mod tests {
|
||||
);
|
||||
assert!(
|
||||
!set.contains(&2),
|
||||
"goblin male does NOT show geoset 2 — the white topknot of B11"
|
||||
"goblin male does NOT show geoset 2 — the white topknot"
|
||||
);
|
||||
// Race 9 ships only sex-0 rows, so the goblin female keeps the region base, the same scalp.
|
||||
let f = cg.visible_geosets(9, 1, 0, 0, &EquipGeosets::default());
|
||||
|
||||
@@ -959,7 +959,7 @@ mod tests {
|
||||
// The tauren bear value seen live: h = 2.083 × 1.35.
|
||||
assert!(
|
||||
(h(2289, 1.35) - 2.083 * 1.35).abs() < 5e-3,
|
||||
"tauren bear form-derived h should reproduce 0695's observed 2.812"
|
||||
"tauren bear form-derived h should reproduce the 2.812 seen live"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -862,7 +862,7 @@ mod tests {
|
||||
assert!(
|
||||
lo >= 120,
|
||||
"level {} ({}x{}) {class} texels reach luma {lo} — a Mod2x streak sampling \
|
||||
this level darkens the scene (B358)",
|
||||
this level darkens the scene",
|
||||
s.level,
|
||||
s.width,
|
||||
s.height
|
||||
|
||||
@@ -14,7 +14,7 @@ pub(super) const IB_CLOUD_SUN: u32 = 10;
|
||||
pub(super) const IB_CLOUD_SLOPE: u32 = 11;
|
||||
pub(super) const IB_CLOUD_GBASE: u32 = 12;
|
||||
/// The water-surface tint rows, ocean 14/15 and river/lake 16/17 (shallow, deep): the reference's
|
||||
/// swatch builder `FUN_0068a830` lerps them raw (`gWorldLight+0xe0..+0xec`), not the sky gradient.
|
||||
/// swatch builder `0x68a830` lerps them raw (`gWorldLight+0xe0..+0xec`), not the sky gradient.
|
||||
pub(super) const IB_OCEAN_SHALLOW: u32 = 14;
|
||||
pub(super) const IB_OCEAN_DEEP: u32 = 15;
|
||||
pub(super) const IB_RIVER_SHALLOW: u32 = 16;
|
||||
@@ -31,7 +31,7 @@ pub(super) const FB_CLOUD_DENSITY: u32 = 3;
|
||||
pub(super) const LP_GLOW: usize = 4;
|
||||
|
||||
/// `LightParams.dbc` field of the highlightSky flag, record byte `+0x04`: an int 0/1 the sky-dome
|
||||
/// fold `FUN_006d0f50` reads to gate the dawn/dusk azimuthal warp. Stored as 0.0/1.0.
|
||||
/// fold `0x6d0f50` reads to gate the dawn/dusk azimuthal warp. Stored as 0.0/1.0.
|
||||
pub(super) const LP_HIGHLIGHT: usize = 1;
|
||||
|
||||
/// `LightParams.dbc` field of lightSkyboxID, record byte `+0x08`: the `LightSkybox.dbc` model that
|
||||
@@ -41,7 +41,7 @@ pub(super) const LP_HIGHLIGHT: usize = 1;
|
||||
pub(super) const LP_SKYBOX: usize = 2;
|
||||
|
||||
/// `LightParams.dbc` fields 5 to 8, after the glow: the water-blend alphas, the depth-alpha
|
||||
/// endpoints of the swatch (`swatch.a = lerp(shallow, deep, V)`, read by `FUN_006b6b60`).
|
||||
/// endpoints of the swatch (`swatch.a = lerp(shallow, deep, V)`, read by `0x6b6b60`).
|
||||
pub(super) const LP_WATER_SHALLOW_ALPHA: usize = 5;
|
||||
pub(super) const LP_WATER_DEEP_ALPHA: usize = 6;
|
||||
pub(super) const LP_OCEAN_SHALLOW_ALPHA: usize = 7;
|
||||
@@ -72,7 +72,7 @@ pub struct Atmosphere {
|
||||
pub ambient: [f32; 3],
|
||||
/// The five sky-dome gradient stops, zenith to horizon (`SkyColor0..4`); all five are used.
|
||||
pub sky: [[f32; 3]; 5],
|
||||
/// River/lake tint `[shallow, deep]`, IntBand rows 16/17 raw, lerped by depth (`FUN_0068a830`).
|
||||
/// River/lake tint `[shallow, deep]`, IntBand rows 16/17 raw, lerped by depth (`0x68a830`).
|
||||
pub water_river: [[f32; 3]; 2],
|
||||
/// Ocean tint `[shallow, deep]`, IntBand rows 14/15 raw, from the same builder.
|
||||
pub water_ocean: [[f32; 3]; 2],
|
||||
@@ -83,7 +83,7 @@ pub struct Atmosphere {
|
||||
/// The FFXGlow composite weight, `LightParams.glow`, raw 0..1: the composite is
|
||||
/// `scene + glow·bloom²`, and the reference quantises glow to `floor(glow·255)/255`.
|
||||
pub glow: f32,
|
||||
/// `LightParams.highlightSky` as 0.0/1.0, scaling the dawn/dusk dome warp (`FUN_006d0f50`).
|
||||
/// `LightParams.highlightSky` as 0.0/1.0, scaling the dawn/dusk dome warp (`0x6d0f50`).
|
||||
pub highlight_sky: f32,
|
||||
/// Cloud density `C`, FloatBand sub 3: the coverage threshold is `T = trunc((1 − C)·255)`.
|
||||
pub cloud_density: f32,
|
||||
|
||||
@@ -328,7 +328,7 @@ mod tests {
|
||||
/// Open-world lava is MCLQ magma: the pin, `.go xyz -7845.99 -1065.50 123.60 0` in Burning
|
||||
/// Steppes (tile 33_46), stands on it.
|
||||
#[test]
|
||||
fn b21_burning_steppes_lava_builds_a_magma_surface_at_the_reported_pin() {
|
||||
fn burning_steppes_lava_builds_a_magma_surface_at_the_reported_pin() {
|
||||
let data = crate::wow_data_or_skip!();
|
||||
let mut chain = crate::open_chain(&data).expect("open chain");
|
||||
let meshes = tile_liquids(&mut chain, "Azeroth", 33, 46);
|
||||
|
||||
@@ -873,7 +873,7 @@ mod tests {
|
||||
);
|
||||
assert!(
|
||||
subs.iter().all(|s| !s.welded_billboard),
|
||||
"…so no batch of it asks a lane to skin anything (decision 0841)"
|
||||
"…so no batch of it asks a lane to skin anything"
|
||||
);
|
||||
let bytes = chain.read_file(path).expect("read the m2");
|
||||
assert!(
|
||||
|
||||
@@ -917,8 +917,8 @@ fn real_prospecting_effect_is_absent_from_5875() {
|
||||
crate::SPELL_EFFECT_PROSPECTING,
|
||||
"spell {} carries SPELL_EFFECT_PROSPECTING in effect slot {i} — `0x495d60`'s \
|
||||
third leg is reachable now, so cast-fail reasons 0x84 PROSPECT_NEED_MORE and \
|
||||
0x90 MIN_SKILL can raise and `ui_action::cast_fail` owes them argument arms \
|
||||
(decision 2292)",
|
||||
0x90 MIN_SKILL can raise and `ui_action::cast_fail` owes them \
|
||||
argument arms",
|
||||
u32_at(r, 0).unwrap_or(0)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ fn touches_map_matches_the_paths_map_set() {
|
||||
}
|
||||
assert!(
|
||||
any_cross_map,
|
||||
"no golden path crosses continents — the 0455 spare predicate has nothing to spare"
|
||||
"no golden path crosses continents — the worldport spare predicate has nothing to spare"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ mod tests {
|
||||
.count();
|
||||
assert_eq!(
|
||||
live, 0,
|
||||
"an annoyed line resolved — 1815's dormancy is over"
|
||||
"an annoyed line resolved — the column is no longer dormant"
|
||||
);
|
||||
// The control: the ordinary column is mostly live, so the sweep above tests the data.
|
||||
let normal_live = cat
|
||||
|
||||
@@ -801,7 +801,7 @@ fn reads_authentic_atmosphere_from_light_dbc() {
|
||||
};
|
||||
assert!(
|
||||
(a.fog_end - 500.0).abs() < 1.0,
|
||||
"clear fog_end should be 500 yd (raw 18000/36, decision 0324), got {}",
|
||||
"clear fog_end should be 500 yd (raw 18000/36), got {}",
|
||||
a.fog_end
|
||||
);
|
||||
assert!(
|
||||
@@ -849,7 +849,7 @@ fn reads_elwynn_storm_fog_endpoints() {
|
||||
let s = cat.sample(0, [-8949.95, -132.49, 83.5], 1440, true);
|
||||
assert!(
|
||||
(s.fog_end - 277.8).abs() < 1.0,
|
||||
"storm fog_end should be ~278 yd (raw 10000/36, decision 0324), got {}",
|
||||
"storm fog_end should be ~278 yd (raw 10000/36), got {}",
|
||||
s.fog_end
|
||||
);
|
||||
assert!(
|
||||
|
||||
@@ -30,7 +30,7 @@ fn stand_box_z_is_the_bubble_anchor_height_and_not_the_attachment() {
|
||||
assert!(
|
||||
(b.stand_box_z - attach_z).abs() > 0.02,
|
||||
"{path}: stand_box_z {:.4} must not be the posed-attachment height {attach_z} — those \
|
||||
are the two mechanisms 1406 separated",
|
||||
are two separate mechanisms",
|
||||
b.stand_box_z
|
||||
);
|
||||
assert!(
|
||||
|
||||
@@ -37,7 +37,7 @@ fn the_rookery_egg_keys_its_hatch_in_despawn_not_in_the_state_family() {
|
||||
let hatch = seq(DESPAWN);
|
||||
assert!(
|
||||
(2.0..3.5).contains(&hatch.duration),
|
||||
"157 Despawn is a multi-second play (got {}s) — the whole of what B140 reported missing",
|
||||
"157 Despawn is a multi-second play (got {}s) — the egg's whole hatch",
|
||||
hatch.duration
|
||||
);
|
||||
assert!(
|
||||
|
||||
@@ -71,6 +71,6 @@ fn the_lava_bubble_keys_its_whole_uv_flipbook_in_variation_one() {
|
||||
|
||||
assert!(
|
||||
subs.iter().all(|s| s.uv_anim.is_none()),
|
||||
"the slot-0 bake yields nothing on any batch — the frozen sprite B98 reported"
|
||||
"the slot-0 bake yields nothing on any batch — read alone, the sprite freezes"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -552,7 +552,7 @@ mod command_tests {
|
||||
|
||||
/// The row, custom-channel and nil legs, and that 0 is truthy.
|
||||
#[test]
|
||||
fn join_channel_by_name_answers_the_three_legs_of_1908() {
|
||||
fn join_channel_by_name_answers_the_row_custom_and_nil_legs() {
|
||||
let mut s = UiScript::new().unwrap();
|
||||
s.set_zone_channel_catalog(catalog());
|
||||
s.run(
|
||||
|
||||
@@ -496,7 +496,7 @@ fn alt_arrow_key_mode_is_the_flag_and_the_engine_core_no_longer_swallows_moves()
|
||||
|
||||
assert!(
|
||||
s.eval::<bool>("return E.SetIgnoreArrows == nil").unwrap(),
|
||||
"5875 has no SetIgnoreArrows — publishing it was decision 1189's error"
|
||||
"5875 has no SetIgnoreArrows — an EditBox must not publish it"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
|
||||
@@ -916,7 +916,7 @@ mod addon_persistence_tests {
|
||||
assert_eq!(
|
||||
bound.1,
|
||||
vec!["CTRL-X".to_string()],
|
||||
"the stored chord came back — this is the assertion 1192 §4 could not make"
|
||||
"the stored chord came back, though the seed ran before the addon registered"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -674,10 +674,10 @@ mod tests {
|
||||
r#"
|
||||
-- 5.0 varargs: the implicit `arg` table, the form all of 1.12 FrameXML uses.
|
||||
local function count(...) local n = 0 for i = 1, arg.n do n = n + arg[i] end return n end
|
||||
-- the iterator-less generic-for (1215)
|
||||
-- the iterator-less generic-for
|
||||
local sum = 0
|
||||
for k, v in { 3, 4 } do sum = sum + v end
|
||||
-- a table constructor with 5.0's compat semicolon (1315)
|
||||
-- a table constructor with 5.0's compat semicolon
|
||||
local t = { a = 1; b = 2; }
|
||||
-- nesting long strings (LUA_COMPAT_LSTR = 2)
|
||||
local s2 = [[outer [[inner]] outer]]
|
||||
@@ -748,7 +748,7 @@ mod tests {
|
||||
)
|
||||
.unwrap(),
|
||||
"0,1,2,3,4,-2,",
|
||||
"the keyring (-2) is LAST — this is the director's Bagnon grid"
|
||||
"the keyring (-2) is LAST — the order Bagnon's grid shows"
|
||||
);
|
||||
// The order the fields are written in does not change it.
|
||||
assert_eq!(
|
||||
|
||||
@@ -125,12 +125,12 @@ const WOW_STDLIB: &str = r#"
|
||||
-- ── the bare string family ─────────────────────────────────────────────────────────────────────
|
||||
-- Every name here is present in the REAL 1.12 client's global table — the in-world `_G` captured
|
||||
-- from the running reference client (19,572 entries), which is the
|
||||
-- authority this file now answers to (decision 1189).
|
||||
-- authority this file answers to.
|
||||
--
|
||||
-- 1187 also installed `strmatch`, `strrev`, `gmatch`, `strlenutf8` and `strcmputf8i` from
|
||||
-- Blizzard's *Era* enumeration, to get a Classic Era addon further. **None of them exist in
|
||||
-- `strmatch`, `strrev`, `gmatch`, `strlenutf8` and `strcmputf8i` come from Blizzard's *Era*
|
||||
-- enumeration, which a Classic Era addon may reach for. **None of them exist in
|
||||
-- 1.12** — `string.match`/`gmatch` are Lua 5.1 additions the 5.0 client never had — and Era is
|
||||
-- not our target. They are gone; adding a global the client does not have is how an addon that
|
||||
-- not our target. They stay out; adding a global the client does not have is how an addon that
|
||||
-- feature-detects gets sent down a path we cannot honour.
|
||||
strlen = string.len
|
||||
strsub = string.sub
|
||||
@@ -143,7 +143,7 @@ strchar = string.char
|
||||
gsub = string.gsub
|
||||
tinsert = table.insert
|
||||
tremove = table.remove
|
||||
-- `getn`, `sort`, `foreach` and `foreachi` are bound by `lua50` (decision 1194), which owns the
|
||||
-- `getn`, `sort`, `foreach` and `foreachi` are bound by `lua50`, which owns the
|
||||
-- 5.0 shapes of `table.getn`/`setn` and must not be shadowed by a second implementation here.
|
||||
|
||||
-- ── the bare math aliases (the same 1.12 global family; the reference FrameXML uses them
|
||||
@@ -155,7 +155,7 @@ abs = math.abs
|
||||
max = math.max
|
||||
min = math.min
|
||||
sqrt = math.sqrt
|
||||
mod = math.mod -- 5.0's name for fmod; `math.fmod` is removed by `lua50` (decision 1194)
|
||||
mod = math.mod -- 5.0's name for fmod; `math.fmod` is removed by `lua50`
|
||||
random = math.random
|
||||
-- `randomseed` is an ENGINE global in 1.12 exactly like `random` beside it (the captured `_G` types
|
||||
-- both `function engine`), and it is the half that was missing: `IgniteStatus` calls it at file
|
||||
@@ -174,7 +174,7 @@ function cos(d) return math.cos(math.rad(d)) end
|
||||
rad = math.rad
|
||||
deg = math.deg
|
||||
-- The rest of the bare math family, each verified present in the real 1.12 client's global
|
||||
-- table (decision 1189's captured `_G`; 1187 had reached for Blizzard's Era enumeration).
|
||||
-- table (the captured `_G`).
|
||||
-- `tan` and the inverses follow sin/cos into DEGREES — same family, same convention; that is
|
||||
-- consistent-with the verified sin/cos finding rather than separately byte-verified, and it is
|
||||
-- the convention every addon rotation helper assumes (`atan2` returning degrees is why
|
||||
@@ -196,7 +196,7 @@ ldexp = math.ldexp
|
||||
-- `debuginfo`, `debugload`, `debugprint`, `debugdump`, `debugbreak` and `debugtimestamp` are
|
||||
-- **byte-identical `xor eax,eax; ret` stubs** — three bytes, no `call`, no memory write. They
|
||||
-- cannot print, log, write or set a global, and they return ZERO Lua values. So these are not
|
||||
-- no-ops we invented under a real name (the "absent capability" class 1203 named); they are the
|
||||
-- no-ops we invented under a real name (an "absent capability"); they are the
|
||||
-- reference's own no-ops, transcribed.
|
||||
--
|
||||
-- That is what lets `BasicControls.xml` stop guarding its `debuginfo()` call and transcribe
|
||||
@@ -220,7 +220,7 @@ do
|
||||
function debugprofilestop() return (GetTime() - profileStart) * 1000 end
|
||||
end
|
||||
|
||||
-- ── the error handler (decision 1195) ──────────────────────────────────────────────────────────
|
||||
-- ── the error handler ──────────────────────────────────────────────────────────────────────────
|
||||
-- `seterrorhandler(f)` / `geterrorhandler()` are ENGINE globals in 1.12 (the captured `_G` says
|
||||
-- so), and `_ERRORMESSAGE` — the default handler they start out holding — is FrameXML's. That
|
||||
-- split is why the pair lives here and the default is a plain function rather than a Rust binding:
|
||||
@@ -249,7 +249,7 @@ function GetLocale() return "enUS" end
|
||||
__benilla_now = 0.0
|
||||
function GetTime() return __benilla_now end
|
||||
|
||||
-- ── The zone-text family (decisions 0203 phase 1 + 0287).
|
||||
-- ── The zone-text family.
|
||||
-- The app pushes the host globals on an area change (the same shape as
|
||||
-- GetTime) and fires MINIMAP_ZONE_CHANGED / the ZONE_CHANGED family; these getters just read the
|
||||
-- cached slots, like the real bindings (0x48a0a0/c0/e0/100 read BSS caches). GetZoneText = the
|
||||
@@ -273,7 +273,7 @@ function GetZonePVPInfo()
|
||||
if t == "" then t = nil end
|
||||
if f == "" then f = nil end
|
||||
-- isArena is 1/nil, never a Lua boolean: the reference's third slot is `(nil) | (number)`
|
||||
-- like every other 1.12 predicate (decision 2118).
|
||||
-- like every other 1.12 predicate.
|
||||
return t, f, __benilla_pvp_arena and 1 or nil
|
||||
end
|
||||
|
||||
@@ -291,7 +291,7 @@ function GetGameTime() return __benilla_game_hour, __benilla_game_minute end
|
||||
-- `reference/1.12-globals.tsv`, from the stock chain, and from every registrar table), and the
|
||||
-- reason they were kept — that the vanilla addon ecosystem assumes them — did not survive being
|
||||
-- checked: the corpus callers are multi-client addons whose vanilla paths raise on a real 1.12
|
||||
-- client too, or that define the name themselves under their own namespace (decision 2146).
|
||||
-- client too, or that define the name themselves under their own namespace.
|
||||
-- An addon reaching for one of these is reaching for a later client's API, and it should find
|
||||
-- what it would find there: nothing.
|
||||
|
||||
@@ -300,9 +300,9 @@ do
|
||||
-- `_find`/`_sub` are captured for the same reason `_format` is: this wrapper runs on every
|
||||
-- `format` call in the UI and must not follow an addon's later replacement of `string.*`.
|
||||
-- They are CALLS and not method syntax because 1.12 installs no string metatable, so
|
||||
-- `fmt:find(...)` — which this used to be written as — raises there (decision 2101's
|
||||
-- left-open item, closed in `lua50::install`). No chunk of ours may use what the reference's
|
||||
-- VM cannot resolve; the parser enforces that for the grammar, and this is its runtime twin.
|
||||
-- `fmt:find(...)` raises there, and here too (`lua50::install` removes the metatable). No
|
||||
-- chunk of ours may use what the reference's VM cannot resolve; the parser enforces that
|
||||
-- for the grammar, and this is its runtime twin.
|
||||
local _format, _find, _sub, _len = string.format, string.find, string.sub, string.len
|
||||
local CONV = "diouxXeEfgGqscp" -- Lua 5.1 conversion letters
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ fn end_to_end_two_frame_tree_extracts_in_zkey_order() {
|
||||
parent:SetPoint("TOPLEFT", 0, 0) -- anchored to the screen root
|
||||
parent:SetWidth(400); parent:SetHeight(300)
|
||||
-- SetAllPoints on each region: a templateless Lua region gets NO implicit anchor
|
||||
-- (decision 1310 — rect-less, never drawn), so real addon code anchors it, and so do we.
|
||||
-- (it is rect-less, never drawn), so real addon code anchors it, and so do we.
|
||||
local pbg = parent:CreateTexture(nil, "BACKGROUND")
|
||||
pbg:SetTexture("Interface\\Parent.blp")
|
||||
pbg:SetAllPoints()
|
||||
|
||||
@@ -17,7 +17,7 @@ fn enable_mouse_gates_hit_testing() {
|
||||
local b = CreateFrame("Frame", "B")
|
||||
b:SetPoint("BOTTOMLEFT", 0, 0); b:SetWidth(800); b:SetHeight(600); b:EnableMouse(false)
|
||||
b:SetScript("OnEnter", function(self) who = self:GetName() end)
|
||||
-- 1/nil, not a boolean (1830): this is the exact comparison shape that inverts, so the
|
||||
-- 1/nil, not a boolean: this is the exact comparison shape that inverts, so the
|
||||
-- test asserts it rather than leaning on truthiness.
|
||||
assert(a:IsMouseEnabled() == 1 and b:IsMouseEnabled() == nil)
|
||||
"#,
|
||||
|
||||
@@ -476,7 +476,7 @@ fn a_retargeted_anchor_follows_its_new_target() {
|
||||
assert!(
|
||||
(after_move - 310.0).abs() < 0.01,
|
||||
"moving the NEW target must move the plate (310), not leave it at {after_move} — the \
|
||||
retarget's edge patch dropped the new edge and the node is under-dirtied (decision 1625)"
|
||||
retarget's edge patch dropped the new edge and the node is under-dirtied"
|
||||
);
|
||||
|
||||
s.run(r#"a:SetPoint("TOPLEFT", nil, "TOPLEFT", 0, -50)"#)
|
||||
|
||||
@@ -160,13 +160,13 @@ fn a_chosen_error_handler_hears_engine_caught_errors_and_the_default_does_not_du
|
||||
s.set_screen_size(1024.0, 768.0);
|
||||
s.run(
|
||||
"local f = CreateFrame('Frame') \
|
||||
f:RegisterEvent('B271_PROBE') \
|
||||
f:RegisterEvent('ERROR_PROBE') \
|
||||
f:SetScript('OnEvent', function() error('boom from a handler') end)",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// With the stdlib default handler, recognised by identity, the dispatch adds nothing.
|
||||
s.fire_event("B271_PROBE", vec![]);
|
||||
s.fire_event("ERROR_PROBE", vec![]);
|
||||
s.dispatch_script_errors_to_handler();
|
||||
let errors = s.take_errors();
|
||||
assert_eq!(
|
||||
@@ -178,7 +178,7 @@ fn a_chosen_error_handler_hears_engine_caught_errors_and_the_default_does_not_du
|
||||
// A chosen handler gets the message, and the host channel still records it.
|
||||
s.run("caught = {} seterrorhandler(function(msg) table.insert(caught, msg) end)")
|
||||
.unwrap();
|
||||
s.fire_event("B271_PROBE", vec![]);
|
||||
s.fire_event("ERROR_PROBE", vec![]);
|
||||
s.dispatch_script_errors_to_handler();
|
||||
assert!(
|
||||
s.eval::<String>("return caught[1]")
|
||||
@@ -243,11 +243,11 @@ fn an_error_handler_that_errors_does_not_recurse() {
|
||||
s.run(
|
||||
"seterrorhandler(function() error('the handler is broken too') end) \
|
||||
local f = CreateFrame('Frame') \
|
||||
f:RegisterEvent('B271_PROBE') \
|
||||
f:RegisterEvent('ERROR_PROBE') \
|
||||
f:SetScript('OnEvent', function() error('original fault') end)",
|
||||
)
|
||||
.unwrap();
|
||||
s.fire_event("B271_PROBE", vec![]);
|
||||
s.fire_event("ERROR_PROBE", vec![]);
|
||||
s.dispatch_script_errors_to_handler();
|
||||
let errors = s.take_errors();
|
||||
assert!(
|
||||
|
||||
@@ -197,7 +197,7 @@ fn the_cooldown_machine_runs_on_the_two_handlers() {
|
||||
s.tick(1.0);
|
||||
s.run(&format!(
|
||||
r#"
|
||||
-- Cooldown.lua, 1.12.1 (the stock file, transcribed for the test — decision 1602).
|
||||
-- Cooldown.lua, 1.12.1 (the stock file, transcribed for the test).
|
||||
function CooldownFrame_SetTimer(this, start, duration, enable)
|
||||
if ( start > 0 and duration > 0 and enable > 0) then
|
||||
this.start = start;
|
||||
|
||||
@@ -375,7 +375,7 @@ fn a_hovered_plate_emits_no_glow_quad() {
|
||||
.collect();
|
||||
assert!(
|
||||
!paths.iter().any(|p| p.contains("Nameplate-Glow")),
|
||||
"the hovered plate's glow must not be painted (0184); quads were {paths:?}"
|
||||
"the hovered plate's glow must not be painted; quads were {paths:?}"
|
||||
);
|
||||
assert!(
|
||||
paths.iter().any(|p| p.contains("Nameplate-Border")),
|
||||
|
||||
@@ -65,5 +65,5 @@ fn every_shape_c_colour_position_takes_nil_as_zero_and_never_raises() {
|
||||
|
||||
// `FontString:SetTextColor 0x79d9c0`.
|
||||
s.run("FS:SetTextColor(nil, nil, nil)")
|
||||
.expect("the sibling 1973 already fixed");
|
||||
.expect("FontString:SetTextColor is shape C on r/g/b");
|
||||
}
|
||||
|
||||
@@ -83,9 +83,9 @@ fn our_globals_stay_inside_the_1_12_surface() {
|
||||
unlisted.is_empty(),
|
||||
"benilla exposes {} global(s) the 1.12.1 client does not, and they are not listed as \
|
||||
exceptions:\n {}\n\n\
|
||||
1.12 is the target (decision 1188). Either give it its 1.12 spelling, or add it to \
|
||||
`allowed_beyond_1_12` in this file WITH the reason it has to stay — an unexplained \
|
||||
superset is what 1189 had to roll back.",
|
||||
1.12 is the target. Either give it its 1.12 spelling, or add it to \
|
||||
`allowed_beyond_1_12` in this file WITH the reason it has to stay — an addon that \
|
||||
feature-detects an unexplained superset takes a path we cannot honour.",
|
||||
unlisted.len(),
|
||||
unlisted.join(" ")
|
||||
);
|
||||
|
||||
@@ -89,7 +89,7 @@ fn scroll_child_top_tracks_vertical_scroll_unclamped_then_restores_on_clear() {
|
||||
child:SetWidth(300); child:SetHeight(600)
|
||||
local marker = child:CreateTexture(nil, "ARTWORK")
|
||||
marker:SetTexture("marker:child")
|
||||
marker:SetAllPoints() -- templateless Lua regions carry no implicit anchor (decision 1310)
|
||||
marker:SetAllPoints() -- templateless Lua regions carry no implicit anchor
|
||||
|
||||
frame:SetScrollChild(child)
|
||||
"#,
|
||||
@@ -481,7 +481,7 @@ fn hit_test_denies_a_button_clipped_out_and_admits_it_once_scrolled_into_view()
|
||||
local frame = CreateFrame("ScrollFrame", "SF")
|
||||
frame:SetPoint("TOPLEFT", 0, -100) -- top 500
|
||||
frame:SetWidth(300); frame:SetHeight(200) -- bottom 300
|
||||
frame:EnableMouse(false) -- isolate the button's own clip-gated hit (§5's subject)
|
||||
frame:EnableMouse(false) -- isolate the button's own clip-gated hit
|
||||
|
||||
local child = CreateFrame("Frame", "Child")
|
||||
child:SetWidth(300); child:SetHeight(600)
|
||||
|
||||
@@ -246,7 +246,7 @@ fn a_slider_does_not_answer_the_buttons_enable_trio() {
|
||||
end
|
||||
-- The Button's own predicate is the NUMBER 1 / the NUMBER 0, never a Lua boolean — its
|
||||
-- false leg is 0 rather than nil, settled per body at `0x7800b0`'s `setne`+`fild`
|
||||
-- (decision 2118's `binding_abi::flag` doc).
|
||||
-- (`binding_abi::flag`'s doc).
|
||||
assert(b:IsEnabled() == 1, "1, not true")
|
||||
b:Disable()
|
||||
assert(b:IsEnabled() == 0, "0, not false and not nil")
|
||||
|
||||
@@ -57,7 +57,7 @@ fn stdlib_aliases_and_helpers() {
|
||||
tremove(t, 1)
|
||||
assert(t[1] == 20)
|
||||
|
||||
-- and the six 2.0 names that are NOT here (decision 2146)
|
||||
-- and the six 2.0 names that are NOT here
|
||||
assert(wipe == nil and tostringall == nil)
|
||||
assert(strsplit == nil and strjoin == nil and strconcat == nil and strtrim == nil)
|
||||
"#,
|
||||
@@ -256,7 +256,7 @@ fn the_rest_of_the_bare_globals() {
|
||||
-- string family
|
||||
assert(strbyte("A") == 65 and strchar(65) == "A")
|
||||
|
||||
-- and the Era-only names 1187 added are GONE (decision 1189): the 5.0 client has no
|
||||
-- and the Era-only names are NOT here either: the 5.0 client has no
|
||||
-- string.match/gmatch, and claiming otherwise misleads an addon that feature-detects.
|
||||
assert(strmatch == nil and gmatch == nil and strrev == nil)
|
||||
assert(strlenutf8 == nil and strcmputf8i == nil)
|
||||
@@ -290,10 +290,10 @@ fn the_lua_5_0_dialect_vanilla_addons_are_written_in_runs_here() {
|
||||
local n, first, second = varargs("a", "b")
|
||||
assert(n == 2 and first == "a" and second == "b")
|
||||
|
||||
-- The edge that used to be here is gone (decision 2101). `arg` was synthesized only for
|
||||
-- a vararg function that did NOT also mention `...` in its body, so mixing the two
|
||||
-- spellings in one function left `arg` nil. `...` as a value is no longer in the grammar
|
||||
-- at all, so nothing can clear the flag and EVERY vararg function has its `arg`.
|
||||
-- 5.1's parser synthesizes `arg` only for a vararg function that does NOT also mention
|
||||
-- `...` in its body, so mixing the two spellings in one function would leave `arg` nil.
|
||||
-- `...` as a value is not in this grammar at all, so nothing can clear the flag and
|
||||
-- EVERY vararg function has its `arg`.
|
||||
local function fixed_and_varargs(a, ...) return a, arg.n, arg[1] end
|
||||
local a, n, first = fixed_and_varargs("a", "b", "c")
|
||||
assert(a == "a" and n == 2 and first == "b")
|
||||
@@ -303,7 +303,7 @@ fn the_lua_5_0_dialect_vanilla_addons_are_written_in_runs_here() {
|
||||
assert(string.gfind ~= nil) -- 5.1 renamed this to string.gmatch
|
||||
assert(math.mod(7, 3) == 1)
|
||||
-- ...and the 5.1 OPERATORS 5.0 lacks are not in the grammar: `%`, `#`, and `...` as a
|
||||
-- value all fail to compile, exactly as they do on the 1.12 client (2101).
|
||||
-- value all fail to compile, exactly as they do on the 1.12 client.
|
||||
assert(loadstring("return 7 % 3") == nil)
|
||||
assert(loadstring("return #({1})") == nil)
|
||||
assert(loadstring("return function(...) return ... end") == nil)
|
||||
|
||||
@@ -47,7 +47,7 @@ fn taxi_snapshot_surfaces_and_intents_drain() {
|
||||
assert(GetNumRoutes(1) == 0 and GetNumRoutes(2) == 1)
|
||||
assert(math.abs(TaxiGetSrcX(2, 1) - 0.5) < 1e-6)
|
||||
assert(math.abs(TaxiGetDestY(2, 1) - 0.8) < 1e-6)
|
||||
assert(UnitOnTaxi("player") == nil) -- 1/nil, never a boolean (2043)
|
||||
assert(UnitOnTaxi("player") == nil) -- 1/nil, never a boolean
|
||||
|
||||
TakeTaxiNode(2)
|
||||
CloseTaxiMap()
|
||||
|
||||
@@ -342,7 +342,7 @@ fn set_inventory_item_renders_full_outside_compare() {
|
||||
-- exactly there.
|
||||
-- Counted through the implicit vararg table's `n` — 5.0's own answer, and the only one
|
||||
-- this VM has (`select` is 5.1's base library, not a 1.12 global). NOT `table.getn` on a
|
||||
-- captured table: 5.0's `luaL_getn` counts rawgeti to the first nil (decision 2102), so
|
||||
-- captured table: 5.0's `luaL_getn` counts rawgeti to the first nil, so
|
||||
-- `{ f() }` where f answers `1, nil, 0` measures ONE — a hole, not a short return.
|
||||
local function count(...) return arg.n end
|
||||
assert(count(tt:SetInventoryItem("player", 16)) == 3,
|
||||
|
||||
@@ -51,7 +51,7 @@ fn item_line_law_and_red_requirements() {
|
||||
"[ONPROC] Ravager",
|
||||
"\"A wicked axe of the Scarlet Crusade.\"",
|
||||
],
|
||||
"the verified line order (0276)"
|
||||
"the reference's line order"
|
||||
);
|
||||
assert_eq!(lines[0].1, [0.0, 0.439, 0.867, 1.0], "rare-blue name");
|
||||
let class_line = &lines[10];
|
||||
|
||||
@@ -164,7 +164,7 @@ fn tracking_hover_renders_gold_name_over_white_description() {
|
||||
matches!(&q.content, QuadContent::Text { text: Some(t), color: Some(c), .. }
|
||||
if t == "Finding Minerals." && (c[1] - 1.0).abs() < 1e-6 && (c[2] - 1.0).abs() < 1e-6)
|
||||
});
|
||||
assert!(gold_name, "the tracking name line is GOLD (director A/B)");
|
||||
assert!(gold_name, "the tracking name line is GOLD");
|
||||
assert!(white_desc, "the description is the aura-variant white");
|
||||
assert!(s.take_errors().is_empty());
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ fn a_pending_name_titles_unknownobject_and_the_answer_replaces_it() {
|
||||
s.run(
|
||||
r#"
|
||||
UNKNOWNOBJECT = "Unknown"
|
||||
assert(UnitName("player") == nil, "the binding's own fast path still pushes nil (2002)")
|
||||
assert(UnitName("player") == nil, "the binding's own fast path still pushes nil")
|
||||
assert(TT:SetUnit("player") == 1)
|
||||
assert(TTTextLeft1:GetText() == UNKNOWNOBJECT,
|
||||
"the builder has no player fast path, got " .. tostring(TTTextLeft1:GetText()))
|
||||
|
||||
@@ -176,7 +176,7 @@ fn the_trigger_is_the_effective_visibility_transition_not_the_show_call() {
|
||||
level(&mut s, "Dialog"),
|
||||
1,
|
||||
"a Show that moves no effective visibility raises nothing — the 1 is not a raise, it is \
|
||||
SetParent's own level := Holder(0)+1 (decision 1323's re-level law)"
|
||||
SetParent's own level := Holder(0)+1 (its re-level law)"
|
||||
);
|
||||
assert_eq!(level(&mut s, "Board"), 5, "and compacts nothing");
|
||||
|
||||
|
||||
@@ -332,9 +332,9 @@ fn our_widget_methods_stay_inside_the_1_12_surface() {
|
||||
assert!(
|
||||
beyond.is_empty(),
|
||||
"benilla answers these on a class the 1.12 client does not register them on:\n{}\n\n\
|
||||
1.12 is the target (decision 1188). Either remove it, give it its 1.12 spelling, or add \
|
||||
the row to ALLOWED_BEYOND WITH the reason it has to stay — an unexplained superset is \
|
||||
what 1189 had to roll back, and an addon that feature-detects one takes a path we cannot \
|
||||
1.12 is the target. Either remove it, give it its 1.12 spelling, or add \
|
||||
the row to ALLOWED_BEYOND WITH the reason it has to stay — an addon that \
|
||||
feature-detects an unexplained superset takes a path we cannot \
|
||||
honour.",
|
||||
as_rows(&beyond)
|
||||
);
|
||||
|
||||
@@ -349,7 +349,7 @@ fn worldmap_current_zone_and_player_feed() {
|
||||
.unwrap();
|
||||
assert!(
|
||||
(px - 0.1).abs() < 1e-6 && (py - 0.2).abs() < 1e-6,
|
||||
"a party slot reads its own projection (B320)"
|
||||
"a party slot reads its own projection"
|
||||
);
|
||||
for token in ["party2", "party5", "party0", "raid1", "nonsense"] {
|
||||
assert_eq!(
|
||||
|
||||
@@ -1804,7 +1804,7 @@ fn the_player_record_outlives_every_snapshot() {
|
||||
assert_eq!(
|
||||
s.eval::<String>(r#"return UnitRace("player")"#).unwrap(),
|
||||
"Night Elf",
|
||||
"the same holds for the other three fields of the record (2263)"
|
||||
"the same holds for the other three fields of the record"
|
||||
);
|
||||
assert_eq!(
|
||||
s.eval::<String>(r#"local _, t = UnitClass("player"); return t"#)
|
||||
|
||||
@@ -512,7 +512,7 @@ mod liquid_trace_mask {
|
||||
assert!(
|
||||
control > 5.0,
|
||||
"the positive control must reproduce the regression — half a millimetre of settle \
|
||||
should swing 2170's camera by yards, got {control}"
|
||||
should swing the uncorrected camera by yards, got {control}"
|
||||
);
|
||||
// The corridor, across a swimmer's whole pitch range.
|
||||
for pitch_deg in [-25.0f32, -10.0, -2.0, -0.5, 0.0, 0.5, 2.0, 10.0, 25.0] {
|
||||
@@ -576,8 +576,8 @@ mod liquid_trace_mask {
|
||||
);
|
||||
assert!(
|
||||
on.is_some_and(|d| d > 2.95),
|
||||
"and it stops ON the plane, not a probe radius short of it — the water leg is a ray \
|
||||
(decision 2185), which is what makes the corridor's 2/9 yd of clearance a clearance"
|
||||
"and it stops ON the plane, not a probe radius short of it — the water leg is a ray, \
|
||||
which is what makes the corridor's 2/9 yd of clearance a clearance"
|
||||
);
|
||||
assert_eq!(
|
||||
descend_camera(&mut app, false),
|
||||
|
||||
@@ -332,7 +332,7 @@ fn gate_doodad_anim(
|
||||
// One log line per session, the first frame any host exists.
|
||||
if !*logged && !hosts.is_empty() {
|
||||
*logged = true;
|
||||
info!("doodad anim: first host armed (decision 0130 phase 1)");
|
||||
info!("doodad anim: first host armed");
|
||||
}
|
||||
let now = time.elapsed_secs();
|
||||
let world_cam = cam.single().ok();
|
||||
|
||||
@@ -817,7 +817,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
(verdict.liquid, verdict.liquid_hidden),
|
||||
(1, 1),
|
||||
"and the cull must have REACHED it — (0, 0) here is the pre-1652 defect, which \
|
||||
"and the cull must have REACHED it — (0, 0) here is a cull that skipped it, which \
|
||||
leaves the surface `Inherited` and looks identical on screen to being admitted"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1309,7 +1309,7 @@ mod tests {
|
||||
assert_ne!(
|
||||
tag,
|
||||
crate::mesh_tag::probe_bits(slot),
|
||||
"the payload must not force a mid-ramp part opaque (the pre-0755 write)"
|
||||
"the payload must not force a mid-ramp part opaque (a bare `probe_bits` write)"
|
||||
);
|
||||
let material = world
|
||||
.get::<MeshMaterial3d<WowModelMaterial>>(part)
|
||||
|
||||
@@ -222,10 +222,10 @@ fn uldaman_is_not_submerged_in_a_mushroom_caves_pool() {
|
||||
.filter_map(|w| w.surface_z_at(feet[0], feet[1]))
|
||||
.filter(|z| *z > feet[2])
|
||||
.min_by(f32::total_cmp)
|
||||
.expect("the mushroom cave's pool is what B85 reported");
|
||||
.expect("the mushroom cave's pool is over this XY");
|
||||
assert!(
|
||||
(reported - 399.64).abs() < 0.05,
|
||||
"the surface B85 reported (got {reported})"
|
||||
"the mushroom cave pool's surface (got {reported})"
|
||||
);
|
||||
assert!(reported - feet[2] > 185.0, "…and 186 yd overhead");
|
||||
|
||||
@@ -324,7 +324,7 @@ fn the_rogues_quarter_is_not_under_tirisfals_lake() {
|
||||
assert!(
|
||||
(unscoped.surface_z - 32.93).abs() < 0.05
|
||||
&& (unscoped.surface_z - feet[2] - 95.19).abs() < 0.05,
|
||||
"the surface B60 reported (got {})",
|
||||
"Tirisfal's lake surface, 95 yd up (got {})",
|
||||
unscoped.surface_z
|
||||
);
|
||||
// Inside Undercity, none of its 38 liquid groups covers this XY.
|
||||
|
||||
@@ -572,7 +572,7 @@ mod tests {
|
||||
assert!(
|
||||
e.contains::<crate::exterior_cull::ExteriorScene>(),
|
||||
"an open-world liquid surface is exterior scene — untagged, the window cull never \
|
||||
queries it and the lake draws through a sealed ceiling (the director's report)"
|
||||
queries it and the lake draws through a sealed ceiling"
|
||||
);
|
||||
assert!(
|
||||
e.contains::<LiquidSurface>(),
|
||||
|
||||
@@ -58,7 +58,7 @@ fn route_quit_through_window_close(_main_thread: bevy::ecs::system::NonSendMarke
|
||||
if rerouted == 0 {
|
||||
warn!(
|
||||
"mac_quit: no Quit item bound to terminate: — Cmd+Q may bypass the shutdown tail \
|
||||
and lose this session's settings (1528)"
|
||||
and lose this session's settings"
|
||||
);
|
||||
} else {
|
||||
info!("mac_quit: Cmd+Q routed through the window close ({rerouted} item(s))");
|
||||
|
||||
@@ -260,7 +260,7 @@ impl EffectQuads {
|
||||
self.cleared_this_frame,
|
||||
"effect-stream write before `begin_effect_frame`: this draw is about to be erased. \
|
||||
The producing system needs `.after(crate::particles::buffer::begin_effect_frame)` \
|
||||
(see `EffectQuads::cleared_this_frame` — this is B161's failure mode)."
|
||||
(see `EffectQuads::cleared_this_frame`)."
|
||||
);
|
||||
let end = self.verts.len() as u32;
|
||||
if end > start {
|
||||
|
||||
@@ -863,8 +863,8 @@ mod tests {
|
||||
assert!(
|
||||
worst_route_over_bias > 0.5,
|
||||
"cam-relative route divergence stayed far inside the bias \
|
||||
(worst {worst_route_over_bias:.2}× across the sweep) — 0781's premise would be \
|
||||
unfounded"
|
||||
(worst {worst_route_over_bias:.2}× across the sweep) — a decal would not need its \
|
||||
receiver's matrix"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -924,19 +924,19 @@ mod tests {
|
||||
}
|
||||
}
|
||||
eprintln!(
|
||||
"bake residual worst: {worst_over_old:.3}x the 0781-era 4096 margin, \
|
||||
{worst_over_retired_ring:.3}x the 8192 the ring rode until 1817, \
|
||||
"bake residual worst: {worst_over_old:.3}x the old 4096 margin, \
|
||||
{worst_over_retired_ring:.3}x the retired 8192 ring bias, \
|
||||
{worst_over_new:.3}x Rung::DECAL_RASTER"
|
||||
);
|
||||
assert!(
|
||||
worst_over_old > 0.5,
|
||||
"the 3-ulp residual stayed far inside the 0781-era 4096 margin \
|
||||
"the 3-ulp residual stayed far inside the old 4096 margin \
|
||||
(worst {worst_over_old:.2}×) — the resize's premise would be unfounded"
|
||||
);
|
||||
assert!(
|
||||
worst_over_retired_ring > 1.0,
|
||||
"the 3-ulp residual fits inside the retired +8192 (worst {worst_over_retired_ring:.2}×) \
|
||||
— then the ring and reticle were NOT under-biased and 1817's raise wants re-arguing"
|
||||
— then the ring and reticle were NOT under-biased and their raise wants re-arguing"
|
||||
);
|
||||
assert!(
|
||||
worst_over_new < 0.5,
|
||||
|
||||
@@ -1274,7 +1274,7 @@ mod tests {
|
||||
assert!(scene_frozen(Some((false, false)), false, false));
|
||||
assert!(
|
||||
!scene_frozen(Some((false, true)), false, false),
|
||||
"…and a throttled camera is awake (1559)"
|
||||
"…and a throttled camera is awake"
|
||||
);
|
||||
// A world-lane emitter has no booth camera; the owner still reaches it.
|
||||
assert!(!scene_frozen(None, false, false));
|
||||
@@ -1340,7 +1340,7 @@ mod tests {
|
||||
follow_fraction(&plain, 30.0),
|
||||
0.0,
|
||||
"no 0x4000: no per-frame term at any speed — ride-vs-trail is the storage space, not \
|
||||
a correction (1585)"
|
||||
a correction"
|
||||
);
|
||||
let riding = benilla_formats::ParticleEmitterDef {
|
||||
flags: 0x0011, // the carried torch, Club_1H_Torch_A_01.m2
|
||||
|
||||
@@ -529,7 +529,7 @@ mod tests {
|
||||
assert!(
|
||||
abs_j > 3e-4,
|
||||
"the absolute route spends a world-scale ULP per frame — got {abs_j:.3e} yd. If this \
|
||||
ever fails, decision 0974's premise has stopped holding here (or the rig above has \
|
||||
ever fails, the rig-relative rebase has lost its reason here (or the rig above has \
|
||||
drifted into missing the large world axis again) — re-derive before deleting."
|
||||
);
|
||||
assert!(
|
||||
|
||||
@@ -1220,12 +1220,12 @@ mod tests {
|
||||
assert_eq!(
|
||||
crate::mat_anim_table::region_offset() - rig_origin_region_offset(),
|
||||
rig_origin_region_bytes(),
|
||||
"the mat-anim table follows the origin table (decision 1381)"
|
||||
"the mat-anim table follows the origin table"
|
||||
);
|
||||
assert_eq!(
|
||||
crate::straddle::region_offset() - crate::mat_anim_table::region_offset(),
|
||||
crate::mat_anim_table::region_bytes(),
|
||||
"the straddle clip table follows the mat-anim table (decision 2188)"
|
||||
"the straddle clip table follows the mat-anim table"
|
||||
);
|
||||
assert_eq!(
|
||||
palette_region_offset() - crate::straddle::region_offset(),
|
||||
|
||||
@@ -213,7 +213,7 @@ mod tests {
|
||||
.resource::<RigPalettes>()
|
||||
.row_placement(slot, 1)
|
||||
.expect("written");
|
||||
assert_eq!(origin, AT, "still measured from the HOST's frame (1609)");
|
||||
assert_eq!(origin, AT, "still measured from the HOST's frame");
|
||||
assert!(
|
||||
row1.distance(row0) > 0.3,
|
||||
"row 1 must carry the prop's own pose, not a copy of row 0 ({row0:?} vs {row1:?})"
|
||||
|
||||
@@ -647,7 +647,7 @@ impl Plugin for StaticGxPlugin {
|
||||
if !enabled() {
|
||||
return;
|
||||
}
|
||||
info!("static-gx: ARMED (default since 1434; WOW_STATIC_GX=0 opts out) — the retained static-world pass (1429–1434)");
|
||||
info!("static-gx: ARMED (default; WOW_STATIC_GX=0 opts out) — retained static-world pass");
|
||||
app.init_resource::<StaticGx>().add_systems(
|
||||
PostUpdate,
|
||||
// Bake, scene walk, publish; after `CheckVisibility`, which is load-bearing. A spawned
|
||||
|
||||
@@ -478,7 +478,7 @@ mod tests {
|
||||
// Without the walls nothing stops the body within the 5 yd it walks.
|
||||
assert!(
|
||||
run_east(false, walking).is_none(),
|
||||
"B129 itself — the terrain here does not stop a body, which is why the flag has to"
|
||||
"the pin itself — the terrain here does not stop a body, which is why the flag has to"
|
||||
);
|
||||
// With them, the capsule's leading surface stops at the chunk boundary.
|
||||
let d = run_east(true, walking).expect("the impassable chunk's fence stops the body");
|
||||
|
||||
@@ -129,6 +129,6 @@ mod tests {
|
||||
.join()
|
||||
.unwrap();
|
||||
assert_eq!(parent, Some(QosClass::UserInteractive as u32));
|
||||
assert_eq!(child, Some(0x15), "QoS inherited — 1109's premise changed");
|
||||
assert_eq!(child, Some(0x15), "QoS inherited — PromotingSource is moot");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -593,7 +593,7 @@ mod msaa_tests {
|
||||
};
|
||||
assert_eq!(apple.clamp(4), 4, "a count it offers is untouched");
|
||||
assert_eq!(apple.clamp(3), 2, "down to the nearest offered, never up");
|
||||
assert_eq!(apple.clamp(8), 4, "the 2026-08-26 render-thread kill");
|
||||
assert_eq!(apple.clamp(8), 4, "unoffered 8x panics the render thread");
|
||||
assert_eq!(apple.clamp(16), 4);
|
||||
assert_eq!(apple.clamp(1), 1);
|
||||
|
||||
|
||||
@@ -257,6 +257,6 @@ fn the_far_band_is_a_fog_hull_not_a_fogged_surface() {
|
||||
assert!(
|
||||
!src.contains("w.fog_params.x") && !src.contains("w.fog_params.y"),
|
||||
"wdl.wgsl: the hull reads the SCENE fog distances again — the 33 yd overlap goes partly \
|
||||
white at low view distances (the band decision 1521 closed)"
|
||||
white at low view distances"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -474,12 +474,12 @@ mod tests {
|
||||
let flat = ahead_share(7.0, Quat::IDENTITY);
|
||||
eprintln!(
|
||||
"snow arrivals ahead of the player: standing {standing:.3}, \
|
||||
running tilted {tilted:.3}, running flat (the B233 shape) {flat:.3}"
|
||||
running tilted {tilted:.3}, running flat (untilted slab) {flat:.3}"
|
||||
);
|
||||
assert!(
|
||||
flat < 0.10,
|
||||
"the untilted slab is supposed to reproduce B233 (nearly nothing arrives ahead of a \
|
||||
runner); got {flat:.3} — if this rose, the symptom's cause moved"
|
||||
"the untilted slab is supposed to reproduce the symptom (nearly nothing arrives \
|
||||
ahead of a runner); got {flat:.3} — if this rose, the symptom's cause moved"
|
||||
);
|
||||
assert!(
|
||||
tilted > 0.25,
|
||||
|
||||
@@ -475,7 +475,7 @@ fn world_point_light_probe() {
|
||||
let lane = match light {
|
||||
None => "exterior-on-terrain (sun + MCSH intensity)".to_string(),
|
||||
Some(c) if c.outdoor => format!(
|
||||
"exterior-on-wmo g{:02} depth {:.1} (forced lit 2.5 — the skip-shadow bit, 0480)",
|
||||
"exterior-on-wmo g{:02} depth {:.1} (forced lit 2.5 — the skip-shadow bit)",
|
||||
c.group, c.depth
|
||||
),
|
||||
Some(c) => match footprint_sample(model, probe_local) {
|
||||
|
||||
@@ -616,8 +616,8 @@ fn wmo_outside_audit() {
|
||||
|
||||
assert_eq!(
|
||||
shell_culled, 0,
|
||||
"{shell_culled} open-air cameras culled the building's exterior shell — the director's \
|
||||
\"wrongly not visible from the outside\""
|
||||
"{shell_culled} open-air cameras culled the building's exterior shell, so it is \
|
||||
wrongly not visible from the outside"
|
||||
);
|
||||
assert!(
|
||||
inside_violations.is_empty(),
|
||||
|
||||
@@ -557,7 +557,7 @@ fn shadowfang_courtyard_leaves_the_far_room_on_the_scene_fog() {
|
||||
);
|
||||
assert!(
|
||||
!pvs.interior_fog[61],
|
||||
"B335: the room two exterior-lit courtyards away must inherit the SCENE fog, not this \
|
||||
"the room two exterior-lit courtyards away must inherit the SCENE fog, not this \
|
||||
building's MFOG teal"
|
||||
);
|
||||
assert!(
|
||||
@@ -667,7 +667,7 @@ fn shadowfang_sees_true_interiors_that_are_off_the_fog_chain() {
|
||||
);
|
||||
assert!(
|
||||
!pvs.interior_fog[13],
|
||||
"…and its room is off the chain, so the fog it takes is the SCENE's (1792 §5's fix)"
|
||||
"…and its room is off the chain, so the fog it takes is the SCENE's"
|
||||
);
|
||||
assert_eq!(
|
||||
attach_room(61),
|
||||
@@ -679,11 +679,11 @@ fn shadowfang_sees_true_interiors_that_are_off_the_fog_chain() {
|
||||
off_chain,
|
||||
vec![1, 2, 13, 68],
|
||||
"four true-interior rooms are in frame across the courtyards and none is on the chain: \
|
||||
this is the population a unit's fog gate has to answer for. It was three until 1853 — \
|
||||
g68 sits behind an exterior group no portal joins to the seed's half of the graph, so it \
|
||||
arrives only once Pass 2 WALKS ON from the window that admits that group instead of \
|
||||
merely marking it. The gate's verdict on all four is identical; what changed is how many \
|
||||
rooms the cull lets the director see at once"
|
||||
this is the population a unit's fog gate has to answer for. The fourth, g68, sits \
|
||||
behind an exterior group no portal joins to the seed's half of the graph, so it \
|
||||
arrives only because Pass 2 WALKS ON from the window that admits that group instead of \
|
||||
merely marking it. The gate's verdict on all four is identical; the walk decides only \
|
||||
how many rooms the cull lets the player see at once"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1256,11 +1256,11 @@ mod tests {
|
||||
assert!(
|
||||
!pvs.visible[3],
|
||||
"a portal-disconnected shell 30 yd off the doorway's axis is culled: no window shows \
|
||||
it, and drawing it is exactly the over-draw 1826 removed"
|
||||
it, and drawing it would be pure over-draw"
|
||||
);
|
||||
assert!(
|
||||
pvs.visible[4],
|
||||
"1853: an admitted shell is FLOODED FROM, not merely marked — g4 is an interior behind \
|
||||
"an admitted shell is FLOODED FROM, not merely marked — g4 is an interior behind \
|
||||
g2 with no edge to the seed's half of the graph, so the walk through g2's own back \
|
||||
door is its only route into the PVS (`0x6b3d39 call 0x6b41c0`). A marking Pass 2 \
|
||||
leaves it culled, which from a Darnassus shop is most of the city"
|
||||
|
||||
@@ -188,7 +188,7 @@ fn report_check(exit: AppExit) -> AppExit {
|
||||
}
|
||||
println!(
|
||||
"WORLDVIEW_CHECK {} fault(s) — a game concept is wired into the engine, or an engine \
|
||||
fact is parked on the game side. Decision 1160.",
|
||||
fact is parked on the game side.",
|
||||
faults.len()
|
||||
);
|
||||
// A run with no install (`WOW_DATA=`) faults for a different reason, so it says which.
|
||||
@@ -196,7 +196,7 @@ fn report_check(exit: AppExit) -> AppExit {
|
||||
println!(
|
||||
"WORLDVIEW_CHECK ran with NO INSTALL: a fault here is a system taking a resource that \
|
||||
only exists when there is client data as a hard `Res`/`ResMut`. Take it as `Option` \
|
||||
and return, or insert it ahead of the no-data bail. Decision 1451."
|
||||
and return, or insert it ahead of the no-data bail."
|
||||
);
|
||||
}
|
||||
AppExit::error()
|
||||
|
||||
Reference in New Issue
Block a user