fix(simulation): Clippy cleanup and CI enforcement (#635)

Fix all Clippy warnings across the server codebase (2411 insertions, 1341
deletions). Raise type-complexity-threshold to 750 and too-many-arguments
to 12 in .clippy.toml for idiomatic Bevy ECS system signatures. The server
now passes `cargo clippy -- --deny warnings` cleanly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-17 10:33:15 +01:00
co-authored by Claude Opus 4.6
parent 7f7706442a
commit aa79dd97e7
84 changed files with 2409 additions and 1339 deletions
+109 -88
View File
@@ -22,7 +22,6 @@ use crate::simulation::rng::SimRng;
use crate::simulation::time::SimulationTime;
use crate::storyteller::EngagementRecord;
/// Display duration for monologue text on client (seconds).
const DISPLAY_DURATION: f32 = 5.0;
@@ -89,10 +88,7 @@ const HEAR_SOUND_LINES: &[(&str, &str)] = &[
/// Fire when the player overhears an NPC-to-NPC conversation (D-078).
/// Future: move to content pools with trigger="witness_interaction".
const WITNESS_INTERACTION_LINES: &[(&str, &str)] = &[
(
"witness_01",
"Interesting. Wonder what that was about.",
),
("witness_01", "Interesting. Wonder what that was about."),
("witness_02", "I should remember what they just said."),
("witness_03", "They didn't know I was listening."),
];
@@ -102,10 +98,7 @@ const WITNESS_INTERACTION_LINES: &[(&str, &str)] = &[
/// Future: move to content pools with trigger="post_conversation".
const POST_CONVERSATION_LINES: &[(&str, &str)] = &[
("post_conv_01", "More questions than answers."),
(
"post_conv_02",
"I'll have to think about what they said.",
),
("post_conv_02", "I'll have to think about what they said."),
(
"post_conv_03",
"Something about that exchange didn't sit right.",
@@ -384,7 +377,10 @@ fn select_hardcoded_fallback(trigger: &str, rng: &mut impl Rng) -> (String, Stri
"witness_interaction" => WITNESS_INTERACTION_LINES,
"post_conversation" => POST_CONVERSATION_LINES,
unknown => {
tracing::warn!("select_hardcoded_fallback: unrecognized trigger '{}', using observe_npc", unknown);
tracing::warn!(
"select_hardcoded_fallback: unrecognized trigger '{}', using observe_npc",
unknown
);
OBSERVE_NPC_LINES
}
};
@@ -469,7 +465,10 @@ pub fn trigger_event_monologue(
.unwrap_or(false)
{
Some("hear_sound")
} else if conv_buffer_opt.map(|b| !b.events.is_empty()).unwrap_or(false) {
} else if conv_buffer_opt
.map(|b| !b.events.is_empty())
.unwrap_or(false)
{
Some("witness_interaction")
} else if !post_conv_npcs.is_empty() {
Some("post_conversation")
@@ -1425,15 +1424,16 @@ mod tests {
let mut world = setup_event_world();
let player = spawn_event_player(&mut world);
world.resource_mut::<SoundEventQueue>().events.push(
SoundEvent::at(
world
.resource_mut::<SoundEventQueue>()
.events
.push(SoundEvent::at(
&TilePosition::new(12, 10, 0), // distance 2 from player at (10,10)
SoundEventKind::Machinery,
0.8,
crate::knowledge::types::SoundRange::Medium,
None,
),
);
));
run_event_system(&mut world);
@@ -1450,15 +1450,16 @@ mod tests {
let mut world = setup_event_world();
let _player = spawn_event_player(&mut world);
world.resource_mut::<SoundEventQueue>().events.push(
SoundEvent::at(
world
.resource_mut::<SoundEventQueue>()
.events
.push(SoundEvent::at(
&TilePosition::new(11, 10, 0),
SoundEventKind::Footstep,
0.5,
crate::knowledge::types::SoundRange::Close,
None,
),
);
));
run_event_system(&mut world);
@@ -1476,15 +1477,16 @@ mod tests {
let _player = spawn_event_player(&mut world);
// Machinery sound at distance 20 with Close range (3 tiles)
world.resource_mut::<SoundEventQueue>().events.push(
SoundEvent::at(
world
.resource_mut::<SoundEventQueue>()
.events
.push(SoundEvent::at(
&TilePosition::new(30, 10, 0), // distance 20 from (10,10)
SoundEventKind::Machinery,
0.8,
crate::knowledge::types::SoundRange::Close,
None,
),
);
));
run_event_system(&mut world);
@@ -1551,12 +1553,11 @@ mod tests {
let npc = world.spawn_empty().id();
// Pre-fill buffer (another system wrote first)
world.get_mut::<MonologueBuffer>(player).unwrap().event =
Some(MonologueEvent {
id: "existing".to_string(),
text: "Already have something.".to_string(),
duration_seconds: 5.0,
});
world.get_mut::<MonologueBuffer>(player).unwrap().event = Some(MonologueEvent {
id: "existing".to_string(),
text: "Already have something.".to_string(),
duration_seconds: 5.0,
});
world.resource_mut::<PostConversationQueue>().push(npc);
@@ -1579,12 +1580,11 @@ mod tests {
let player = spawn_event_player(&mut world);
// Pre-fill buffer
world.get_mut::<MonologueBuffer>(player).unwrap().event =
Some(MonologueEvent {
id: "prior_line".to_string(),
text: "I was already thinking.".to_string(),
duration_seconds: 5.0,
});
world.get_mut::<MonologueBuffer>(player).unwrap().event = Some(MonologueEvent {
id: "prior_line".to_string(),
text: "I was already thinking.".to_string(),
duration_seconds: 5.0,
});
// Push observation event that would normally fire
world
@@ -1625,15 +1625,16 @@ mod tests {
observer: player,
});
world.resource_mut::<SoundEventQueue>().events.push(
SoundEvent::at(
world
.resource_mut::<SoundEventQueue>()
.events
.push(SoundEvent::at(
&TilePosition::new(11, 10, 0),
SoundEventKind::Machinery,
0.8,
crate::knowledge::types::SoundRange::Medium,
None,
),
);
));
run_event_system(&mut world);
@@ -1650,15 +1651,16 @@ mod tests {
let player = spawn_event_player(&mut world);
// Sound event
world.resource_mut::<SoundEventQueue>().events.push(
SoundEvent::at(
world
.resource_mut::<SoundEventQueue>()
.events
.push(SoundEvent::at(
&TilePosition::new(11, 10, 0),
SoundEventKind::Alert,
1.0,
crate::knowledge::types::SoundRange::Medium,
None,
),
);
));
// Conversation event
world
@@ -1739,15 +1741,16 @@ mod tests {
let mut world = setup_event_world();
let player = spawn_event_player(&mut world);
world.resource_mut::<SoundEventQueue>().events.push(
SoundEvent::at(
world
.resource_mut::<SoundEventQueue>()
.events
.push(SoundEvent::at(
&TilePosition::new(10, 11, 0), // distance 1
SoundEventKind::Alert,
1.0,
crate::knowledge::types::SoundRange::Long,
None,
),
);
));
run_event_system(&mut world);
@@ -1764,15 +1767,16 @@ mod tests {
let _player = spawn_event_player(&mut world);
// Sound on z=1, player on z=0
world.resource_mut::<SoundEventQueue>().events.push(
SoundEvent::at(
world
.resource_mut::<SoundEventQueue>()
.events
.push(SoundEvent::at(
&TilePosition::new(10, 11, 1), // same xy but different z
SoundEventKind::Machinery,
0.8,
crate::knowledge::types::SoundRange::Medium,
None,
),
);
));
run_event_system(&mut world);
@@ -1814,15 +1818,16 @@ mod tests {
let _player = spawn_event_player(&mut world);
// Voice sound in range — should NOT trigger (routine background noise)
world.resource_mut::<SoundEventQueue>().events.push(
SoundEvent::at(
world
.resource_mut::<SoundEventQueue>()
.events
.push(SoundEvent::at(
&TilePosition::new(11, 10, 0), // distance 1
SoundEventKind::Voice,
0.7,
crate::knowledge::types::SoundRange::Medium,
None,
),
);
));
run_event_system(&mut world);
@@ -1840,15 +1845,16 @@ mod tests {
let _player = spawn_event_player(&mut world);
// Ambient sound in range — should NOT trigger (background atmosphere)
world.resource_mut::<SoundEventQueue>().events.push(
SoundEvent::at(
world
.resource_mut::<SoundEventQueue>()
.events
.push(SoundEvent::at(
&TilePosition::new(10, 12, 0), // distance 2
SoundEventKind::Ambient,
0.9,
crate::knowledge::types::SoundRange::Long,
None,
),
);
));
run_event_system(&mut world);
@@ -1899,12 +1905,14 @@ mod tests {
}
fn spawn_contradiction_player(world: &mut bevy_ecs::world::World) -> bevy_ecs::entity::Entity {
world.spawn((
PlayerCharacter,
TilePosition::new(0, 0, 0),
MonologueState::default(),
MonologueBuffer::default(),
)).id()
world
.spawn((
PlayerCharacter,
TilePosition::new(0, 0, 0),
MonologueState::default(),
MonologueBuffer::default(),
))
.id()
}
#[test]
@@ -1966,11 +1974,14 @@ mod tests {
let player = spawn_contradiction_player(&mut world);
// Pre-fill buffer with a higher-priority monologue
world.get_mut::<MonologueBuffer>(player).unwrap().set(MonologueEvent {
id: "prior_event".to_string(),
text: "Something already fired.".to_string(),
duration_seconds: 5.0,
});
world
.get_mut::<MonologueBuffer>(player)
.unwrap()
.set(MonologueEvent {
id: "prior_event".to_string(),
text: "Something already fired.".to_string(),
duration_seconds: 5.0,
});
world.resource_mut::<ContradictionDetectedQueue>().push(
crate::knowledge::ContradictionDetectedEvent {
@@ -1995,7 +2006,10 @@ mod tests {
// Buffer should still have the prior event
let buf = world.get::<MonologueBuffer>(player).unwrap();
let event = buf.event.as_ref().unwrap();
assert_eq!(event.id, "prior_event", "prior monologue should not be overridden");
assert_eq!(
event.id, "prior_event",
"prior monologue should not be overridden"
);
// Queue should have been drained regardless
assert!(
@@ -2049,15 +2063,15 @@ mod tests {
// Tick T3: process_contradiction_monologue fires monologue with Sera/Kael names
//
// Tests the full D-083 event chain end-to-end.
use crate::knowledge::{
EntityRegistry, KnowledgeGraph, KnowledgeEventQueue, KnowledgeEventType,
};
use crate::knowledge::events::{process_knowledge_events, KnowledgeEvent};
use crate::knowledge::registry::StableEntityId;
use crate::knowledge::types::{
EntityKnowledge, KnowledgeConfidence, KnowledgeSource, KnowledgeState,
RelationshipState, StableId,
};
use crate::knowledge::{
EntityRegistry, KnowledgeEventQueue, KnowledgeEventType, KnowledgeGraph,
};
use std::collections::BTreeMap;
let mut world = bevy_ecs::world::World::new();
@@ -2070,10 +2084,9 @@ mod tests {
// Spawn NPCs with NpcName components
let sera_entity = world.spawn(NpcName("Sera".to_string())).id();
let kael_entity = world.spawn((
NpcName("Kael".to_string()),
TilePosition::new(10, 10, 0),
)).id();
let kael_entity = world
.spawn((NpcName("Kael".to_string()), TilePosition::new(10, 10, 0)))
.id();
let sera_sid = registry.register(sera_entity);
let kael_sid = registry.register(kael_entity);
@@ -2100,14 +2113,16 @@ mod tests {
},
);
let player = world.spawn((
PlayerCharacter,
TilePosition::new(0, 0, 0),
MonologueState::default(),
MonologueBuffer::default(),
player_kg,
StableEntityId(StableId(999)),
)).id();
let player = world
.spawn((
PlayerCharacter,
TilePosition::new(0, 0, 0),
MonologueState::default(),
MonologueBuffer::default(),
player_kg,
StableEntityId(StableId(999)),
))
.id();
registry.register(player);
world.insert_resource(registry);
@@ -2156,13 +2171,19 @@ mod tests {
{
// Drain to inspect event contents, then re-push for the monologue consumer.
let mut events = world.resource_mut::<ContradictionDetectedQueue>().drain();
assert_eq!(events.len(), 1, "should have exactly one contradiction event");
assert_eq!(
events.len(),
1,
"should have exactly one contradiction event"
);
let event = &events[0];
assert_eq!(event.source_display_name, "Sera");
assert_eq!(event.subject_display_name, "Kael");
// Re-push so process_contradiction_monologue can consume it on T3.
let event = events.remove(0);
world.resource_mut::<ContradictionDetectedQueue>().push(event);
world
.resource_mut::<ContradictionDetectedQueue>()
.push(event);
}
// Tick T3: Run process_contradiction_monologue