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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user