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:
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user