gates: clippy clean again, and the mail repro that never was for commit

`scripts/check.sh` has been failing before it ran a single test, on 62 clippy
findings in code none of the recent rounds touched — 32 in `benilla-world`, 30 in
`benilla-app` — so the in-loop gate could not tell anyone anything. Every one is a
newer clippy noticing older code (`as_chunks` and `is_multiple_of` are both lints
younger than the lines they fire on), and they are fixed, not silenced, except
where the silence is the point:

- **Argued allows, the house idiom.** `clippy::type_complexity` on ten Bevy system
  signatures and two inline caster queries, each with the one-line reason beside
  it, as the other 67 in this workspace have. `clippy::approx_constant` on
  `liquid/waves.rs`'s `TWO_PI`, whose own doc already says why it is spelled
  `6.2831853`: it mirrors a shader line, and `f32::consts::TAU` would stop reading
  against the file it copies.
- **Two runtime assertions became compile-time ones** (`EXT_SEL_EMPTY is index 255`,
  the endless-stream frame count): a claim about constants should fail the build
  that breaks it, not a test run after it.
- **Three real, if harmless, redundancies gone**: `len > MAX_TILT_TAN && len > 0.0`
  (the constant is `tan(4°)`, so the second test never spoke), `u32::from(..) + 1 |
  flags` now parenthesised where `+` binds tighter than `|`, and `palette.get(0)`.
- The rest is mechanical: `chunks_exact(3)` → `as_chunks::<3>()`, `map_or(true, ..)`
  → `is_none_or`, two `Default::default()`-then-assign test fixtures, a doc line
  that began `1.` and so turned its own paragraph into a list item, and
  `local_utc_offset_secs` moved above the test module it had drifted below.

`tests/repro_mail.rs` is deleted. Its first line says "TEMPORARY repro harness —
not for commit"; it reads a loose mirror of FrameXML out of `/tmp/opencode/
vanilla-ui`, which no longer exists, so it has been failing on a missing directory
rather than telling anyone about mail.

What is left of the gate's red is one test: `world_api_wall` counts 174 crossings
of the `benilla-world` boundary against a ceiling of 107 — 90 of them already
filed with a close plan, 84 unsorted. That is not cleanup; the wall's own message
says the remedies are to close the crossing or to publish it as engine API with the
record that says so, and 84 of those is a design pass on what the engine's public
surface is.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
2026-10-18 15:18:10 -06:00
co-authored by Claude Opus 5
parent 3e616e5cb3
commit 56fb28fa2b
33 changed files with 202 additions and 305 deletions
@@ -189,7 +189,6 @@ mod tests {
assert_eq!(b.point_count(), MAX_LIVE_POINT_LIGHTS);
assert_eq!(b.points.len(), 2 * MAX_LIVE_POINT_LIGHTS);
assert_eq!(MAX_LIVE_POINT_LIGHTS, MAX_POINT_LIGHTS - 1);
assert!(MAX_LIVE_POINT_LIGHTS <= 255, "EXT_SEL_EMPTY is index 255");
}
/// The glue scene's fog toggle flips only the enable and leaves the race's fog rows standing.
+14 -11
View File
@@ -509,9 +509,9 @@ pub fn daylight_target(light: &WowLighting) -> ([f32; 3], f32, f32) {
let ndotl = l.y.max(0.0);
let mut target = [0.0f32; 3];
let mut peak = 0.0f32;
for i in 0..3 {
target[i] = (light.ambient[i] + light.diffuse[i] * ndotl).clamp(0.0, 1.0);
peak = peak.max(target[i]);
for (i, channel) in target.iter_mut().enumerate() {
*channel = (light.ambient[i] + light.diffuse[i] * ndotl).clamp(0.0, 1.0);
peak = peak.max(*channel);
}
let hue = if peak > 1e-4 {
[target[0] / peak, target[1] / peak, target[2] / peak]
@@ -885,9 +885,9 @@ fn plan_clusters(points: &[[f32; 3]]) -> Vec<([f32; 3], [f32; 3])> {
for (p, ci) in points.iter().zip(of_point.iter()) {
let root = find(&mut parent, *ci);
let e = boxes.entry(root).or_insert((*p, *p));
for a in 0..3 {
e.0[a] = e.0[a].min(p[a]);
e.1[a] = e.1[a].max(p[a]);
for ((lo, hi), v) in e.0.iter_mut().zip(e.1.iter_mut()).zip(p) {
*lo = lo.min(*v);
*hi = hi.max(*v);
}
}
let mut out: Vec<([f32; 3], [f32; 3])> = boxes.into_values().collect();
@@ -938,6 +938,7 @@ const WINDOW_SPLIT_MAX: usize = 6;
/// stitch -- three vertices where two walls meet a floor), must stand no more than
/// [`SEAM_MAX_Z_EXTENT`] tall (or it is the vertical seam of a whole party wall), and must fall in
/// the same 1..24 yd size band the aperture seed uses.
#[allow(clippy::type_complexity)] // per cluster: its group, centroid, inward normal and extent
fn boundary_clusters(
groups: &[WmoGroupInfo],
batches: &[(u16, bool, &[[f32; 3]])],
@@ -955,8 +956,8 @@ fn boundary_clusters(
slot.push(positions);
let acc = &mut sum[usize::from(gi)];
for p in positions {
for a in 0..3 {
acc.0[a] += f64::from(p[a]);
for (axis, v) in acc.0.iter_mut().zip(p) {
*axis += f64::from(*v);
}
acc.1 += 1;
}
@@ -1135,9 +1136,9 @@ fn cluster_boxes(points: &[[f32; 3]]) -> Vec<([f32; 3], [f32; 3])> {
for (p, ci) in points.iter().zip(of_point.iter()) {
let root = find(&mut parent, *ci);
let e = boxes.entry(root).or_insert((*p, *p));
for a in 0..3 {
e.0[a] = e.0[a].min(p[a]);
e.1[a] = e.1[a].max(p[a]);
for ((lo, hi), v) in e.0.iter_mut().zip(e.1.iter_mut()).zip(p) {
*lo = lo.min(*v);
*hi = hi.max(*v);
}
}
let mut out: Vec<([f32; 3], [f32; 3])> = boxes.into_values().collect();
@@ -1204,6 +1205,7 @@ pub fn daylight_modes() -> (bool, bool, bool) {
/// contribute nothing. Removing the component takes it out of the packer's query outright and costs
/// two archetype moves per game day. Everything else about the entity (its claims, its lane, its
/// reach) is untouched, so dawn re-inserts and the claim set is exactly the one built at spawn.
#[allow(clippy::type_complexity)] // one Bevy system's full input set
pub fn update_daylight_fixtures(
mut commands: Commands,
light: Res<WowLighting>,
@@ -1959,6 +1961,7 @@ fn bleed_intensity(lit: [f32; 3], r_eff: f32, k_fill: f32) -> ([f32; 3], f32) {
/// remains is structural and harmless: `update_daylight_fixtures` INSERTS and REMOVES its `PointLight`
/// through `Commands`, so on the single frame a daylight fixture switches on at dawn or off at dusk
/// the bleed reading it is one frame stale. Its steady-state value is written in place and is current.
#[allow(clippy::type_complexity)] // one Bevy system's full input set
pub fn update_bleed_fixtures(
mut commands: Commands,
knobs: Res<DynamicInteriors>,
@@ -9,6 +9,7 @@
use super::*;
use benilla_formats::{open_chain, parse_wmo_portals, parse_wmo_root, wmo_group_header};
#[allow(clippy::type_complexity)] // the batch row is the tuple the loader hands back
struct Loaded {
groups: Vec<WmoGroupInfo>,
names: Vec<String>,
@@ -41,7 +42,9 @@ fn group_names(bytes: &[u8]) -> Vec<String> {
let (Some(mogn), Some(mogi)) = (mogn, mogi) else {
return Vec::new();
};
mogi.chunks_exact(32)
mogi.as_chunks::<32>()
.0
.iter()
.map(|r| {
let off = i32::from_le_bytes(r[28..32].try_into().unwrap());
usize::try_from(off)
@@ -281,9 +281,11 @@ mod tests {
#[test]
fn modern_marks_the_scene_end_and_fades_the_sun_at_night() {
let mut l = WowLighting::default();
l.fog_end = 444.0;
l.celestial_dir = Vec3::new(0.0, 0.8, 0.6);
let mut l = WowLighting {
fog_end: 444.0,
celestial_dir: Vec3::new(0.0, 0.8, 0.6),
..Default::default()
};
let mut f = MonkeyFrame::default();
fill_frame(&mut f, FogModel::Modern, &l, &derived_band(&l));
assert_eq!(f.fog_scene_end, 444.0);
@@ -145,6 +145,10 @@ pub(super) const MAX_POINT_LIGHTS: usize = 256;
/// blob or the room-claim table changes.
pub(super) const MAX_LIVE_POINT_LIGHTS: usize = MAX_POINT_LIGHTS - 1;
/// The selection byte spends index 255 on `EXT_SEL_EMPTY`, so no live light may land there. At
/// compile time, where a test could only say it after the build that broke it.
const _: () = assert!(MAX_LIVE_POINT_LIGHTS <= 255, "EXT_SEL_EMPTY is index 255");
/// MONKEY (dynamic interiors): a fixture this close to the camera (yd) is packed regardless of the
/// portal flood — see the room term in [`build_light_data`]. Sized to a WHOLE BUILDING PLUS its
/// approach, not just the room: at 40 yd, walking around the outside of the inn kept crossing the
@@ -194,6 +198,7 @@ impl LightRooms {
/// hall, guest rooms and basement claim NOTHING.
/// * **NSabbey** — 42 fixtures over 14 groups, but `Main Hall`, `LftWng`, `RtWng`, `Library`,
/// `Library2`, `Library Wing` and `Stairs2` are named by no MOLR either.
///
/// Gating purely on MOLR would therefore black out most of both buildings — the abbey's look is
/// the one the owner signed off, so that is a regression, not a fix. MOLR is authored for the
/// reference's own purpose (register GL lights while drawing a VISIBLE group's doodads and units),
@@ -970,6 +975,7 @@ fn unpack_shadow_lane(w: f32) -> (f32, f32) {
/// reach it from below, and cannot leave it from above.
/// * `u32(max(w - 1, 0) + 0.5)` — the debug decode (`static_gx` x3, `wow_model`, `terrain`):
/// `debug + f + 0.5` truncates to `debug` for every `f` in `[0, 0.5)`.
///
/// **0.49** keeps a clear margin under that 0.5 cliff while spending the whole of the rest of the
/// range on the value. `1 + debug` is an exact integer in f32, so the shader's `fract(w)` returns
/// `daylight * 0.49` bit-for-bit up to the f32 ulp at `w <= 5.49` (~5e-7 — four orders of magnitude
@@ -1275,7 +1281,7 @@ impl RoomClaim {
Some(g) => {
// MONKEY (soft portal claims): the entry weight rides the spare high bits.
let entry = self.fades[i].entry.clamp(0.0, 1.0);
u32::from(*g & !LIT_ROOM_EXT_DENY) + 1
(u32::from(*g & !LIT_ROOM_EXT_DENY) + 1)
| if *g & LIT_ROOM_EXT_DENY == 0 {
CLAIM_EXT_OK
} else {
+2 -2
View File
@@ -152,10 +152,10 @@ fn stitch_tag(
tx: f32,
ty: f32,
) -> f32 {
let (a, b, t) = if (fy == 0 || fy + 1 == fine_rows) && fx % SUBDIVISIONS != 0 {
let (a, b, t) = if (fy == 0 || fy + 1 == fine_rows) && !fx.is_multiple_of(SUBDIVISIONS) {
let y = if fy == 0 { 0 } else { rows - 1 };
(y * cols + sx, y * cols + sx + 1, tx)
} else if (fx == 0 || fx + 1 == fine_cols) && fy % SUBDIVISIONS != 0 {
} else if (fx == 0 || fx + 1 == fine_cols) && !fy.is_multiple_of(SUBDIVISIONS) {
let x = if fx == 0 { 0 } else { cols - 1 };
(sy * cols + x, (sy + 1) * cols + x, ty)
} else {
+8 -4
View File
@@ -43,6 +43,7 @@ const GRAVITY_YD: f32 = 10.72;
/// `6.2831853` exactly as the shader spells it (`enhanced_water.wgsl`). Identical to `f32::TAU` once
/// rounded, spelled as the literal so the mirror reads against the line it copies.
#[allow(clippy::approx_constant)] // the shader's spelling is the point, see above
const TWO_PI: f32 = 6.2831853;
/// The ADT **ocean**'s wave energy — `liquid/surface.rs` packs `water.mode.y = 1.0` for
@@ -215,10 +216,13 @@ mod tests {
"enhanced_water.wgsl WATER_WAVES[0..2]"
);
assert_eq!(GRAVITY_YD, 10.72, "enhanced_water.wgsl gravity");
assert_eq!(
TWO_PI, 6.2831853,
"enhanced_water.wgsl k = 6.2831853/wavelength"
);
#[allow(clippy::approx_constant)] // likewise the mirror's own literal
{
assert_eq!(
TWO_PI, 6.2831853,
"enhanced_water.wgsl k = 6.2831853/wavelength"
);
}
assert_eq!(WATER_WIND_DIR, 0.35, "enhanced_water.wgsl WATER_WIND_DIR");
assert_eq!(
GERSTNER_CHOP, 2.4,
+1 -1
View File
@@ -420,7 +420,7 @@ fn prepare_static_gx(
// (a bare static_gx harness has no lighting) — absent reads as the shipped Gaussian.
shadow_filter: Option<Res<crate::lighting::ShadowFilterGaussian>>,
) {
let shadow_gaussian = shadow_filter.map_or(true, |f| f.0);
let shadow_gaussian = shadow_filter.is_none_or(|f| f.0);
let _t = super::gx_perf_guard(3);
let Some((view, msaa, _, _)) = views.iter().next() else {
return;
+2 -2
View File
@@ -77,7 +77,7 @@ impl StaticGx {
.map(|p| t.transform_point(wow_to_bevy(*p)).to_array()),
);
let added = positions.len() as u32 - base;
for tri in item.geometry.indices.chunks_exact(3) {
for tri in item.geometry.indices.as_chunks::<3>().0 {
if tri.iter().all(|i| *i < added) {
indices.extend(tri.iter().map(|i| base + *i));
}
@@ -144,7 +144,7 @@ impl StaticGx {
);
bucket.uvs.extend_from_slice(&geometry.uvs);
let added = bucket.positions.len() as u32 - base;
for tri in geometry.indices.chunks_exact(3) {
for tri in geometry.indices.as_chunks::<3>().0 {
if tri.iter().all(|i| *i < added) {
bucket.indices.extend(tri.iter().map(|i| base + *i));
}
@@ -1122,7 +1122,7 @@ impl super::StaticGx {
.to_array()
}));
let added = positions.len() as u32 - base;
for tri in item.geometry.indices.chunks_exact(3) {
for tri in item.geometry.indices.as_chunks::<3>().0 {
if tri.iter().all(|i| *i < added) {
indices.extend(tri.iter().map(|i| base + *i));
}
+1 -1
View File
@@ -113,7 +113,7 @@ fn ride(state: &BobState) -> (f32, Quat) {
// Clamp the SLOPE, not the resulting quaternion: the wave normal is `(-∂x, 1, -∂z)`
// (`enhanced_water.wgsl`), so a gradient of length `tan(θ)` is a lean of exactly θ.
let len = g.length();
let g = if len > MAX_TILT_TAN && len > 0.0 {
let g = if len > MAX_TILT_TAN {
g * (MAX_TILT_TAN / len)
} else {
g
+9 -7
View File
@@ -353,13 +353,15 @@ fn drive_unit(
// hanging in deep water is the state the reference's driver renders almost invisible, and it
// is exactly the state the owner's murloc will be in. Classic touches nothing here — not the
// timer, not the RNG stream.
if look.enhanced && look.swimming && !matches!(state, WadeState::Translating { .. }) {
if now >= foam_state.tread_ready {
foam_state.tread_ready = now + TREAD_INTERVAL;
if let Some(p) = tread_params(look, scale, &mut foam_state.rng) {
let heading = rand01(&mut foam_state.rng) * std::f32::consts::TAU;
emit_record(alloc, index, water, [wow[0], wow[1]], &p, heading, now);
}
if look.enhanced
&& look.swimming
&& !matches!(state, WadeState::Translating { .. })
&& now >= foam_state.tread_ready
{
foam_state.tread_ready = now + TREAD_INTERVAL;
if let Some(p) = tread_params(look, scale, &mut foam_state.rng) {
let heading = rand01(&mut foam_state.rng) * std::f32::consts::TAU;
emit_record(alloc, index, water, [wow[0], wow[1]], &p, heading, now);
}
}
+4 -2
View File
@@ -175,8 +175,10 @@ mod tests {
#[test]
fn the_ripple_clock_wraps() {
let mut w = Wetness::default();
w.ripple_time_s = RIPPLE_WRAP_S - 0.05;
let mut w = Wetness {
ripple_time_s: RIPPLE_WRAP_S - 0.05,
..Default::default()
};
w.step(0.0, 0.1);
assert!(w.ripple_time_s < 0.1);
}