From 9f025de27d01c78846573092787856f89e86fed6 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 3 Apr 2023 19:29:37 +0100 Subject: [PATCH] Addressed feedback --- common/src/rtsim.rs | 4 ++ rtsim/src/ai/mod.rs | 10 ++-- rtsim/src/data/nature.rs | 6 ++- rtsim/src/data/npc.rs | 2 +- rtsim/src/rule/npc_ai.rs | 39 +++++++++------ server/src/lib.rs | 18 ------- server/src/rtsim/mod.rs | 6 +-- server/src/sys/agent.rs | 31 +----------- .../sys/agent/behavior_tree/interaction.rs | 49 ------------------- server/src/sys/terrain.rs | 2 - 10 files changed, 41 insertions(+), 126 deletions(-) diff --git a/common/src/rtsim.rs b/common/src/rtsim.rs index e2dc656221..638667435c 100644 --- a/common/src/rtsim.rs +++ b/common/src/rtsim.rs @@ -227,6 +227,8 @@ pub enum NpcAction { Say(Cow<'static, str>), } +// Note: the `serde(name = "...")` is to minimise the length of field +// identifiers for the sake of rtsim persistence #[derive(Copy, Clone, Debug, Serialize, Deserialize, enum_map::Enum)] pub enum ChunkResource { #[serde(rename = "0")] @@ -253,6 +255,8 @@ pub enum ChunkResource { Ore, // Iron, copper, etc. } +// Note: the `serde(name = "...")` is to minimise the length of field +// identifiers for the sake of rtsim persistence #[derive(Clone, Debug, Serialize, Deserialize)] pub enum Profession { #[serde(rename = "0")] diff --git a/rtsim/src/ai/mod.rs b/rtsim/src/ai/mod.rs index 9bf321728e..9995e2b546 100644 --- a/rtsim/src/ai/mod.rs +++ b/rtsim/src/ai/mod.rs @@ -528,15 +528,15 @@ where /// /// The inner function will be run every tick to decide on an action. When an /// action is chosen, it will be performed until completed unless a different -/// action is chosen in a subsequent tick. [`watch`] is very unfocussed and will -/// happily switch between actions rapidly between ticks if conditions change. -/// If you want something that tends to commit to actions until they are -/// completed, see [`choose`]. +/// action of the same or higher priority is chosen in a subsequent tick. +/// [`watch`] is very unfocussed and will happily switch between actions +/// rapidly between ticks if conditions change. If you want something that +/// tends to commit to actions until they are completed, see [`choose`]. /// /// # Example /// /// ```ignore -/// choose(|ctx| { +/// watch(|ctx| { /// if ctx.npc.is_being_attacked() { /// urgent(combat()) // If we're in danger, do something! /// } else if ctx.npc.is_hungry() { diff --git a/rtsim/src/data/nature.rs b/rtsim/src/data/nature.rs index c94ca5fae9..0e4b39f4f7 100644 --- a/rtsim/src/data/nature.rs +++ b/rtsim/src/data/nature.rs @@ -42,8 +42,10 @@ pub struct Chunk { /// this chunk. /// /// 0.0 => None of the resources generated by terrain generation should be - /// present 1.0 => All of the resources generated by terrain generation - /// should be present + /// present + /// + /// 1.0 => All of the resources generated by terrain generation should be + /// present /// /// It's important to understand this this number does not represent the /// total amount of a resource present in a chunk, nor is it even diff --git a/rtsim/src/data/npc.rs b/rtsim/src/data/npc.rs index 4ff70046f8..23e4fcd902 100644 --- a/rtsim/src/data/npc.rs +++ b/rtsim/src/data/npc.rs @@ -83,8 +83,8 @@ pub struct Brain { #[derive(Serialize, Deserialize)] pub struct Npc { // Persisted state - /// Represents the location of the NPC. pub seed: u32, + /// Represents the location of the NPC. pub wpos: Vec3, pub body: comp::Body, diff --git a/rtsim/src/rule/npc_ai.rs b/rtsim/src/rule/npc_ai.rs index 056ea5aee2..8cab657361 100644 --- a/rtsim/src/rule/npc_ai.rs +++ b/rtsim/src/rule/npc_ai.rs @@ -310,7 +310,7 @@ fn goto_2d(wpos2d: Vec2, speed_factor: f32, goal_dist: f32) -> impl Action }) } -fn traverse_points(mut next_point: F) -> impl Action +fn traverse_points(mut next_point: F, speed_factor: f32) -> impl Action where F: FnMut(&mut NpcCtx) -> Option> + Send + Sync + 'static, { @@ -333,33 +333,40 @@ where if let Some(path) = path_site(wpos, site_exit, site, ctx.index) { Some(itertools::Either::Left( - seq(path.into_iter().map(|wpos| goto_2d(wpos, 1.0, 8.0))) - .then(goto_2d(site_exit, 1.0, 8.0)), + seq(path.into_iter().map(|wpos| goto_2d(wpos, 1.0, 8.0))).then(goto_2d( + site_exit, + speed_factor, + 8.0, + )), )) } else { - Some(itertools::Either::Right(goto_2d(site_exit, 1.0, 8.0))) + Some(itertools::Either::Right(goto_2d( + site_exit, + speed_factor, + 8.0, + ))) } } else { - Some(itertools::Either::Right(goto_2d(wpos, 1.0, 8.0))) + Some(itertools::Either::Right(goto_2d(wpos, speed_factor, 8.0))) } }) } /// Try to travel to a site. Where practical, paths will be taken. -fn travel_to_point(wpos: Vec2) -> impl Action { +fn travel_to_point(wpos: Vec2, speed_factor: f32) -> impl Action { now(move |ctx| { const WAYPOINT: f32 = 48.0; let start = ctx.npc.wpos.xy(); let diff = wpos - start; let n = (diff.magnitude() / WAYPOINT).max(1.0); let mut points = (1..n as usize + 1).map(move |i| start + diff * (i as f32 / n)); - traverse_points(move |_| points.next()) + traverse_points(move |_| points.next(), speed_factor) }) .debug(|| "travel to point") } /// Try to travel to a site. Where practical, paths will be taken. -fn travel_to_site(tgt_site: SiteId) -> impl Action { +fn travel_to_site(tgt_site: SiteId, speed_factor: f32) -> impl Action { now(move |ctx| { let sites = &ctx.state.data().sites; @@ -397,7 +404,7 @@ fn travel_to_site(tgt_site: SiteId) -> impl Action { } else { None } - }) + }, speed_factor) .boxed() // For every track in the path we discovered between the sites... @@ -438,7 +445,7 @@ fn travel_to_site(tgt_site: SiteId) -> impl Action { // .boxed() } else if let Some(site) = sites.get(tgt_site) { // If all else fails, just walk toward the target site in a straight line - travel_to_point(site.wpos.map(|e| e as f32 + 0.5)).boxed() + travel_to_point(site.wpos.map(|e| e as f32 + 0.5), speed_factor).boxed() } else { // If we can't find a way to get to the site at all, there's nothing more to be done finish().boxed() @@ -512,7 +519,7 @@ fn adventure() -> impl Action { .unwrap_or_default(); // Travel to the site important(just(move |ctx| ctx.controller.say(format!("I've spent enough time here, onward to {}!", site_name))) - .then(travel_to_site(tgt_site)) + .then(travel_to_site(tgt_site, 0.6)) // Stop for a few minutes .then(villager(tgt_site).repeat().stop_if(timeout(wait_time))) .map(|_| ()) @@ -572,7 +579,7 @@ fn villager(visiting_site: SiteId) -> impl Action { } else if ctx.npc.current_site != Some(visiting_site) { let npc_home = ctx.npc.home; // Travel to the site we're supposed to be in - return urgent(travel_to_site(visiting_site).debug(move || { + return urgent(travel_to_site(visiting_site, 1.0).debug(move || { if npc_home == Some(visiting_site) { "travel home".to_string() } else { @@ -602,7 +609,7 @@ fn villager(visiting_site: SiteId) -> impl Action { }) { just(|ctx| ctx.controller.say("It's dark, time to go home")) - .then(travel_to_point(house_wpos)) + .then(travel_to_point(house_wpos, 0.65)) .debug(|| "walk to house") .then(socialize().repeat().debug(|| "wait in house")) .stop_if(|ctx| DayPeriod::from(ctx.time_of_day.0).is_light()) @@ -621,7 +628,7 @@ fn villager(visiting_site: SiteId) -> impl Action { { if let Some(forest_wpos) = find_forest(ctx) { return casual( - travel_to_point(forest_wpos) + travel_to_point(forest_wpos, 0.5) .debug(|| "walk to forest") .then({ let wait_time = thread_rng().gen_range(10.0..30.0); @@ -636,7 +643,7 @@ fn villager(visiting_site: SiteId) -> impl Action { if let Some(forest_wpos) = find_forest(ctx) { return casual( just(|ctx| ctx.controller.say("Time to go hunting!")) - .then(travel_to_point(forest_wpos)) + .then(travel_to_point(forest_wpos, 0.75)) .debug(|| "walk to forest") .then({ let wait_time = thread_rng().gen_range(30.0..60.0); @@ -685,7 +692,7 @@ fn villager(visiting_site: SiteId) -> impl Action { }) { // Walk to the plaza... - travel_to_point(plaza_wpos) + travel_to_point(plaza_wpos, 0.5) .debug(|| "walk to plaza") // ...then wait for some time before moving on .then({ diff --git a/server/src/lib.rs b/server/src/lib.rs index c79365524d..96b8baee2f 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -549,17 +549,6 @@ impl Server { let connection_handler = ConnectionHandler::new(network, &runtime); - // Initiate real-time world simulation - /* - #[cfg(feature = "worldgen")] - { - rtsim::init(&mut state, &world, index.as_index_ref()); - weather::init(&mut state, &world); - } - #[cfg(not(feature = "worldgen"))] - rtsim::init(&mut state); - */ - // Init rtsim, loading it from disk if possible #[cfg(feature = "worldgen")] { @@ -738,13 +727,6 @@ impl Server { add_local_systems(dispatcher_builder); sys::msg::add_server_systems(dispatcher_builder); sys::add_server_systems(dispatcher_builder); - /* - #[cfg(feature = "worldgen")] - { - rtsim::add_server_systems(dispatcher_builder); - weather::add_server_systems(dispatcher_builder); - } - */ #[cfg(feature = "worldgen")] { rtsim::add_server_systems(dispatcher_builder); diff --git a/server/src/rtsim/mod.rs b/server/src/rtsim/mod.rs index d9f5d8db63..5202769c42 100644 --- a/server/src/rtsim/mod.rs +++ b/server/src/rtsim/mod.rs @@ -22,7 +22,7 @@ use std::{ path::PathBuf, time::Instant, }; -use tracing::{debug, error, info, warn}; +use tracing::{debug, error, info, trace, warn}; use vek::*; use world::{IndexRef, World}; @@ -175,10 +175,10 @@ impl RtSim { } pub fn save(&mut self, /* slowjob_pool: &SlowJobPool, */ wait_until_finished: bool) { - info!("Saving rtsim data..."); + debug!("Saving rtsim data..."); let file_path = self.file_path.clone(); let data = self.state.data().clone(); - debug!("Starting rtsim data save job..."); + trace!("Starting rtsim data save job..."); // TODO: Use slow job // slowjob_pool.spawn("RTSIM_SAVE", move || { let handle = std::thread::spawn(move || { diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index ec85a61727..5151fbea23 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -29,7 +29,6 @@ impl<'a> System<'a> for Sys { Read<'a, EventBus>, WriteStorage<'a, Agent>, WriteStorage<'a, Controller>, - //WriteExpect<'a, RtSim>, ); const NAME: &'static str = "agent"; @@ -38,9 +37,8 @@ impl<'a> System<'a> for Sys { fn run( job: &mut Job, - (read_data, event_bus, mut agents, mut controllers /* mut rtsim */): Self::SystemData, + (read_data, event_bus, mut agents, mut controllers): Self::SystemData, ) { - //let rtsim = &mut *rtsim; job.cpu_stats.measure(ParMode::Rayon); ( @@ -187,12 +185,6 @@ impl<'a> System<'a> for Sys { can_fly: moving_body.map_or(false, |b| b.fly_thrust().is_some()), }; let health_fraction = health.map_or(1.0, Health::fraction); - /* - let rtsim_entity = read_data - .rtsim_entities - .get(entity) - .and_then(|rtsim_ent| rtsim.get_entity(rtsim_ent.0)); - */ if traversal_config.can_fly && matches!(moving_body, Some(Body::Ship(_))) { // hack (kinda): Never turn off flight airships @@ -255,7 +247,6 @@ impl<'a> System<'a> for Sys { // inputs. let mut behavior_data = BehaviorData { agent, - // rtsim_entity, agent_data: data, read_data: &read_data, event_emitter: &mut event_emitter, @@ -269,25 +260,5 @@ impl<'a> System<'a> for Sys { debug_assert!(controller.inputs.look_dir.map(|e| !e.is_nan()).reduce_and()); }, ); - /* - for (agent, rtsim_entity) in (&mut agents, &read_data.rtsim_entities).join() { - // Entity must be loaded in as it has an agent component :) - // React to all events in the controller - for event in core::mem::take(&mut agent.rtsim_controller.events) { - match event { - RtSimEvent::AddMemory(memory) => { - rtsim.insert_entity_memory(rtsim_entity.0, memory.clone()); - }, - RtSimEvent::ForgetEnemy(name) => { - rtsim.forget_entity_enemy(rtsim_entity.0, &name); - }, - RtSimEvent::SetMood(memory) => { - rtsim.set_entity_mood(rtsim_entity.0, memory.clone()); - }, - RtSimEvent::PrintMemories => {}, - } - } - } - */ } } diff --git a/server/src/sys/agent/behavior_tree/interaction.rs b/server/src/sys/agent/behavior_tree/interaction.rs index 567758d4f1..0aaf20d73f 100644 --- a/server/src/sys/agent/behavior_tree/interaction.rs +++ b/server/src/sys/agent/behavior_tree/interaction.rs @@ -244,55 +244,6 @@ pub fn handle_inbox_talk(bdata: &mut BehaviorData) -> bool { }, Subject::Mood => { // TODO: Reimplement in rtsim2 - /* - if let Some(rtsim_entity) = &bdata.rtsim_entity { - if !rtsim_entity.brain.remembers_mood() { - // TODO: the following code will need a rework to - // implement more mood contexts - // This require that town NPCs becomes rtsim_entities to - // work fully. - match rand::random::() % 3 { - 0 => agent.rtsim_controller.events.push( - RtSimEvent::SetMood(Memory { - item: MemoryItem::Mood { - state: MoodState::Good( - MoodContext::GoodWeather, - ), - }, - time_to_forget: read_data.time.0 + 21200.0, - }), - ), - 1 => agent.rtsim_controller.events.push( - RtSimEvent::SetMood(Memory { - item: MemoryItem::Mood { - state: MoodState::Neutral( - MoodContext::EverydayLife, - ), - }, - time_to_forget: read_data.time.0 + 21200.0, - }), - ), - 2 => agent.rtsim_controller.events.push( - RtSimEvent::SetMood(Memory { - item: MemoryItem::Mood { - state: MoodState::Bad( - MoodContext::GoodWeather, - ), - }, - time_to_forget: read_data.time.0 + 86400.0, - }), - ), - _ => {}, // will never happen - } - } - if let Some(memory) = rtsim_entity.brain.get_mood() { - let msg = match &memory.item { - MemoryItem::Mood { state } => state.describe(), - _ => "".to_string(), - }; - agent_data.chat_npc(msg, event_emitter); - } - }*/ }, Subject::Location(location) => { if let Some(tgt_pos) = read_data.positions.get(target) { diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index c4deb96978..bfe2c5fb9b 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -74,7 +74,6 @@ impl<'a> System<'a> for Sys { WriteExpect<'a, TerrainGrid>, Write<'a, TerrainChanges>, Write<'a, Vec>, - //WriteExpect<'a, RtSim>, RtSimData<'a>, TerrainPersistenceData<'a>, WriteStorage<'a, Pos>, @@ -107,7 +106,6 @@ impl<'a> System<'a> for Sys { mut terrain, mut terrain_changes, mut chunk_requests, - //mut rtsim, mut rtsim, mut _terrain_persistence, mut positions,