From a78ad8de79a091f9806c4215843216c55e34f2d4 Mon Sep 17 00:00:00 2001 From: crabman Date: Sat, 2 Mar 2024 19:54:51 +0000 Subject: [PATCH 1/2] revive test-server --- server/src/events/entity_manipulation.rs | 39 ++++++++------ server/src/events/invite.rs | 6 ++- server/src/lib.rs | 12 +++-- server/src/lod.rs | 2 +- server/src/sys/msg/character_screen.rs | 67 +++++++++++------------- server/src/sys/terrain.rs | 17 +++--- server/src/sys/terrain_sync.rs | 9 +++- server/src/test_world.rs | 18 +++++-- 8 files changed, 95 insertions(+), 75 deletions(-) diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index eaa031e871..12e7546c96 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -1,3 +1,5 @@ +#[cfg(not(feature = "worldgen"))] +use crate::test_world::{IndexOwned, World}; use crate::{ client::Client, comp::{ @@ -67,7 +69,8 @@ use specs::{ use std::{collections::HashMap, iter, sync::Arc, time::Duration}; use tracing::{debug, warn}; use vek::{Vec2, Vec3}; -use world::World; +#[cfg(feature = "worldgen")] +use world::{IndexOwned, World}; use super::{event_dispatch, ServerEvent}; @@ -286,6 +289,7 @@ fn handle_exp_gain( #[derive(SystemData)] pub struct DestroyEventData<'a> { entities: Entities<'a>, + #[cfg(feature = "worldgen")] rtsim: WriteExpect<'a, RtSim>, id_maps: Read<'a, IdMaps>, msm: ReadExpect<'a, MaterialStatManifest>, @@ -293,7 +297,7 @@ pub struct DestroyEventData<'a> { time: Read<'a, Time>, program_time: ReadExpect<'a, ProgramTime>, world: ReadExpect<'a, Arc>, - index: ReadExpect<'a, world::IndexOwned>, + index: ReadExpect<'a, IndexOwned>, areas_container: Read<'a, AreasContainer>, outcomes: Read<'a, EventBus>, create_item_drop: Read<'a, EventBus>, @@ -725,23 +729,24 @@ impl ServerEvent for DestroyEvent { }; let actor = entity_as_actor(ev.entity); + #[cfg(feature = "worldgen")] if let Some(actor) = actor { data.rtsim.hook_rtsim_actor_death( - &data.world, - data.index.as_index_ref(), - actor, - data.positions.get(ev.entity).map(|p| p.0), - ev.cause - .by - .as_ref() - .and_then( - |(DamageContributor::Solo(entity_uid) - | DamageContributor::Group { entity_uid, .. })| { - data.id_maps.uid_entity(*entity_uid) - }, - ) - .and_then(entity_as_actor), - ); + &data.world, + data.index.as_index_ref(), + actor, + data.positions.get(ev.entity).map(|p| p.0), + ev.cause + .by + .as_ref() + .and_then( + |(DamageContributor::Solo(entity_uid) + | DamageContributor::Group { entity_uid, .. })| { + data.id_maps.uid_entity(*entity_uid) + }, + ) + .and_then(entity_as_actor), + ); } if should_delete { diff --git a/server/src/events/invite.rs b/server/src/events/invite.rs index 89acc101d2..bf2a46533b 100644 --- a/server/src/events/invite.rs +++ b/server/src/events/invite.rs @@ -3,6 +3,8 @@ use super::{ group_manip::{self, update_map_markers}, ServerEvent, }; +#[cfg(not(feature = "worldgen"))] +use crate::test_world::IndexOwned; use crate::{client::Client, Settings}; use common::{ comp::{ @@ -24,6 +26,8 @@ use specs::{ }; use std::time::{Duration, Instant}; use tracing::{error, warn}; +#[cfg(feature = "worldgen")] +use world::IndexOwned; /// Time before invite times out const INVITE_TIMEOUT_DUR: Duration = Duration::from_secs(31); @@ -222,7 +226,7 @@ pub struct InviteResponseData<'a> { entities: Entities<'a>, group_manager: Write<'a, GroupManager>, trades: Write<'a, Trades>, - index: ReadExpect<'a, world::IndexOwned>, + index: ReadExpect<'a, IndexOwned>, id_maps: Read<'a, IdMaps>, invites: WriteStorage<'a, Invite>, pending_invites: WriteStorage<'a, PendingInvites>, diff --git a/server/src/lib.rs b/server/src/lib.rs index f2a914de28..c17585ca4f 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -308,7 +308,7 @@ impl Server { #[cfg(feature = "worldgen")] let map = world.get_map_data(index.as_index_ref(), &pools); #[cfg(not(feature = "worldgen"))] - let map = WorldMapMsg { + let map = common_net::msg::WorldMapMsg { dimensions_lg: Vec2::zero(), max_height: 1.0, rgba: Grid::new(Vec2::new(1, 1), 1), @@ -320,16 +320,18 @@ impl Server { default_chunk: Arc::new(world.generate_oob_chunk()), }; + #[cfg(feature = "worldgen")] + let map_size_lg = world.sim().map_size_lg(); + #[cfg(not(feature = "worldgen"))] + let map_size_lg = world.map_size_lg(); + let lod = lod::Lod::from_world(&world, index.as_index_ref(), &pools); report_stage(ServerInitStage::StartingSystems); let mut state = State::server( Arc::clone(&pools), - #[cfg(feature = "worldgen")] - world.sim().map_size_lg(), - #[cfg(not(feature = "worldgen"))] - common::terrain::map::MapSizeLg::new(Vec2::one()).unwrap(), + map_size_lg, Arc::clone(&map.default_chunk), |dispatcher_builder| { add_local_systems(dispatcher_builder); diff --git a/server/src/lod.rs b/server/src/lod.rs index 60e0c57461..0dd2966030 100644 --- a/server/src/lod.rs +++ b/server/src/lod.rs @@ -37,7 +37,7 @@ impl Lod { } #[cfg(not(feature = "worldgen"))] - pub fn from_world(world: &World, index: IndexRef, _threadpool: &rayon::ThreadPool) -> Self { + pub fn from_world(_world: &World, _index: IndexRef, _threadpool: &rayon::ThreadPool) -> Self { Self::default() } diff --git a/server/src/sys/msg/character_screen.rs b/server/src/sys/msg/character_screen.rs index 4ea0812412..fb4e34ce33 100644 --- a/server/src/sys/msg/character_screen.rs +++ b/server/src/sys/msg/character_screen.rs @@ -174,6 +174,37 @@ impl Sys { alias )))?; } else if let Some(player) = players.get(entity) { + #[cfg(feature = "worldgen")] + let waypoint = start_site.and_then(|site_idx| { + // TODO: This corresponds to the ID generation logic in + // `world/src/lib.rs`. Really, we should have + // a way to consistently refer to sites, but that's a job for rtsim2 + // and the site changes that it will require. Until then, this code is + // very hacky. + world + .civs() + .sites + .iter() + .find(|(_, site)| site.site_tmp.map(|i| i.id()) == Some(site_idx)) + .map(Some) + .unwrap_or_else(|| { + error!( + "Tried to create character with starting site index {}, but \ + such a site does not exist", + site_idx + ); + None + }) + .map(|(_, site)| { + let wpos2d = TerrainChunkSize::center_wpos(site.center); + Waypoint::new( + world.find_accessible_pos(index.as_index_ref(), wpos2d, false), + time, + ) + }) + }); + #[cfg(not(feature = "worldgen"))] + let waypoint = Some(Waypoint::new(world.get_center().with_z(10).as_(), time)); if let Err(error) = character_creator::create_character( entity, player.uuid().to_string(), @@ -182,41 +213,7 @@ impl Sys { offhand.clone(), body, character_updater, - #[cfg(feature = "worldgen")] - start_site.and_then(|site_idx| { - // TODO: This corresponds to the ID generation logic in - // `world/src/lib.rs`. Really, we should have - // a way to consistently refer to sites, but that's a job for rtsim2 - // and the site changes that it will require. Until then, this code is - // very hacky. - world - .civs() - .sites - .iter() - .find(|(_, site)| site.site_tmp.map(|i| i.id()) == Some(site_idx)) - .map(Some) - .unwrap_or_else(|| { - error!( - "Tried to create character with starting site index {}, \ - but such a site does not exist", - site_idx - ); - None - }) - .map(|(_, site)| { - let wpos2d = TerrainChunkSize::center_wpos(site.center); - Waypoint::new( - world.find_accessible_pos( - index.as_index_ref(), - wpos2d, - false, - ), - time, - ) - }) - }), - #[cfg(not(feature = "worldgen"))] - None, + waypoint, ) { debug!( ?error, diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index dca05b74b0..9247b492aa 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -254,8 +254,12 @@ impl<'a> System<'a> for Sys { } let max_view_distance = server_settings.max_view_distance.unwrap_or(u32::MAX); + #[cfg(feature = "worldgen")] + let world_size = world.sim().get_size(); + #[cfg(not(feature = "worldgen"))] + let world_size = world.map_size_lg().chunks().map(u32::from); let (presences_position_entities, presences_positions) = prepare_player_presences( - &world, + world_size, max_view_distance, &entities, &positions, @@ -688,7 +692,7 @@ fn prepare_for_vd_check( } pub fn prepare_player_presences<'a, P>( - world: &World, + world_size: Vec2, max_view_distance: u32, entities: &Entities<'a>, positions: P, @@ -704,14 +708,7 @@ where let world_aabr_in_chunks = Aabr { min: Vec2::zero(), // NOTE: Cast is correct because chunk coordinates must fit in an i32 (actually, i16). - #[cfg(feature = "worldgen")] - max: world - .sim() - .get_size() - .map(|x| x.saturating_sub(1)) - .as_::(), - #[cfg(not(feature = "worldgen"))] - max: Vec2::one(), + max: world_size.map(|x| x.saturating_sub(1)).as_::(), }; let (mut presences_positions_entities, mut presences_positions): (Vec<_>, Vec<_>) = diff --git a/server/src/sys/terrain_sync.rs b/server/src/sys/terrain_sync.rs index 74606e50d6..a42b0ad07c 100644 --- a/server/src/sys/terrain_sync.rs +++ b/server/src/sys/terrain_sync.rs @@ -1,3 +1,5 @@ +#[cfg(not(feature = "worldgen"))] +use crate::test_world::World; use crate::{chunk_serialize::ChunkSendEntry, client::Client, Settings}; use common::{ comp::{Pos, Presence}, @@ -9,7 +11,7 @@ use common_state::TerrainChanges; use rayon::prelude::*; use specs::{Entities, Join, Read, ReadExpect, ReadStorage}; use std::sync::Arc; -use world::World; +#[cfg(feature = "worldgen")] use world::World; /// This systems sends new chunks to clients as well as changes to existing /// chunks @@ -46,8 +48,11 @@ impl<'a> System<'a> for Sys { ) { let max_view_distance = server_settings.max_view_distance.unwrap_or(u32::MAX); #[cfg(feature = "worldgen")] + let world_size = world.sim().get_size(); + #[cfg(not(feature = "worldgen"))] + let world_size = world.map_size_lg().chunks().as_(); let (presences_position_entities, _) = super::terrain::prepare_player_presences( - &world, + world_size, max_view_distance, &entities, &positions, diff --git a/server/src/test_world.rs b/server/src/test_world.rs index eaaf930a6e..24a4a3424c 100644 --- a/server/src/test_world.rs +++ b/server/src/test_world.rs @@ -14,7 +14,7 @@ use std::time::Duration; use vek::*; const DEFAULT_WORLD_CHUNKS_LG: MapSizeLg = - if let Ok(map_size_lg) = MapSizeLg::new(Vec2 { x: 1, y: 1 }) { + if let Ok(map_size_lg) = MapSizeLg::new(Vec2 { x: 8, y: 8 }) { map_size_lg } else { panic!("Default world chunk size does not satisfy required invariants."); @@ -51,7 +51,8 @@ impl World { _index: IndexRef, chunk_pos: Vec2, _rtsim_resources: Option>, - _should_continue: impl FnMut() -> bool, + // TODO: misleading name + mut _should_continue: impl FnMut() -> bool, _time: Option<(TimeOfDay, Calendar)>, ) -> Result<(TerrainChunk, ChunkSupplement), ()> { let (x, y) = chunk_pos.map(|e| e.to_le_bytes()).into_tuple(); @@ -66,7 +67,7 @@ impl World { Ok(( TerrainChunk::new( - 256 + if rng.gen::() < 64 { height } else { 0 }, + if rng.gen::() < 64 { height } else { 0 }, Block::new(BlockKind::Grass, Rgb::new(11, 102, 35)), Block::air(SpriteKind::Empty), TerrainChunkMeta::void(), @@ -75,5 +76,14 @@ impl World { )) } - pub fn get_location_name(&self, _index: IndexRef, _wpos2d: Vec2) -> Option { None } + pub fn get_center(&self) -> Vec2 { + // FIXME: Assumes that TerrainChunkSize::RECT_SIZE.x == + // TerrainChunkSize::RECT_SIZE.y + DEFAULT_WORLD_CHUNKS_LG.chunks().as_::() / 2 * TerrainChunkSize::RECT_SIZE.x as u32 + } + + pub fn get_location_name(&self, _index: IndexRef, _wpos2d: Vec2) -> Option { + // Test world has no locations + None + } } From e6a9d4434f8f1628c959df0b1216e7949f3b1bba Mon Sep 17 00:00:00 2001 From: crabman Date: Wed, 6 Mar 2024 12:47:30 +0000 Subject: [PATCH 2/2] fix test-server compile warnings --- .gitlab/scripts/code-quality.sh | 5 +- server-cli/src/cli.rs | 1 + server-cli/src/main.rs | 5 +- server/src/chunk_generator.rs | 6 +- server/src/cmd.rs | 52 +++++-- server/src/events/entity_manipulation.rs | 21 ++- server/src/events/information.rs | 5 +- server/src/events/invite.rs | 8 +- server/src/events/mounting.rs | 11 +- server/src/events/trade.rs | 5 + server/src/lib.rs | 15 +- server/src/state_ext.rs | 15 +- server/src/sys/msg/character_screen.rs | 106 +++++++------- server/src/sys/terrain.rs | 169 ++++++++++------------- server/src/sys/terrain_sync.rs | 2 - server/src/test_world.rs | 11 +- server/src/weather/mod.rs | 1 + 17 files changed, 229 insertions(+), 209 deletions(-) diff --git a/.gitlab/scripts/code-quality.sh b/.gitlab/scripts/code-quality.sh index d610acc878..b305e9dd0a 100755 --- a/.gitlab/scripts/code-quality.sh +++ b/.gitlab/scripts/code-quality.sh @@ -4,7 +4,7 @@ time cargo clippy \ --all-targets \ --locked \ - --features="bin_cmd_doc_gen,bin_compression,bin_csv,bin_graphviz,bin_bot,bin_asset_migrate,asset_tweak,bin,stat" \ + --features="bin_cmd_doc_gen,bin_compression,bin_csv,bin_graphviz,bin_bot,bin_asset_migrate,asset_tweak,bin,stat,cli" \ -- -D warnings && # Ensure that the veloren-voxygen default-publish feature builds as it excludes some default features @@ -13,4 +13,7 @@ time cargo clippy -p \ --no-default-features \ --features="default-publish" \ -- -D warnings && + +# Ensure that test-server compiles +time cargo clippy --locked --bin veloren-server-cli --no-default-features -F simd -- -D warnings && time cargo fmt --all -- --check diff --git a/server-cli/src/cli.rs b/server-cli/src/cli.rs index 1a88e8df00..2dad16a398 100644 --- a/server-cli/src/cli.rs +++ b/server-cli/src/cli.rs @@ -60,6 +60,7 @@ pub enum Message { }, /// Loads up the chunks at map center and adds a entity that mimics a /// player to keep them from despawning + #[cfg(feature = "worldgen")] LoadArea { /// View distance of the loaded area view_distance: u32, diff --git a/server-cli/src/main.rs b/server-cli/src/main.rs index 960613a978..14ad41a090 100644 --- a/server-cli/src/main.rs +++ b/server-cli/src/main.rs @@ -208,6 +208,7 @@ fn main() -> io::Result<()> { let protocols_and_addresses = server_settings.gameserver_protocols.clone(); let web_port = &settings.web_address.port(); // Create server + #[cfg_attr(not(feature = "worldgen"), allow(unused_mut))] let mut server = Server::new( server_settings, editable_settings, @@ -263,8 +264,8 @@ fn main() -> io::Result<()> { "Server is ready to accept connections." ); + #[cfg(feature = "worldgen")] if let Some(bench) = bench { - #[cfg(feature = "worldgen")] server.create_centered_persister(bench.view_distance); } @@ -367,8 +368,8 @@ fn server_loop( }) => { server.remove_admin(&username); }, + #[cfg(feature = "worldgen")] Message::LoadArea { view_distance } => { - #[cfg(feature = "worldgen")] server.create_centered_persister(view_distance); }, Message::SqlLogMode { mode } => { diff --git a/server/src/chunk_generator.rs b/server/src/chunk_generator.rs index c76eb6b75e..812d426108 100644 --- a/server/src/chunk_generator.rs +++ b/server/src/chunk_generator.rs @@ -1,6 +1,8 @@ +use crate::metrics::ChunkGenMetrics; +#[cfg(feature = "worldgen")] +use crate::rtsim::RtSim; #[cfg(not(feature = "worldgen"))] use crate::test_world::{IndexOwned, World}; -use crate::{metrics::ChunkGenMetrics, rtsim::RtSim}; use common::{ calendar::Calendar, generation::ChunkSupplement, resources::TimeOfDay, slowjob::SlowJobPool, terrain::TerrainChunk, @@ -45,7 +47,7 @@ impl ChunkGenerator { slowjob_pool: &SlowJobPool, world: Arc, #[cfg(feature = "worldgen")] rtsim: &RtSim, - #[cfg(not(feature = "worldgen"))] rtsim: &(), + #[cfg(not(feature = "worldgen"))] _rtsim: &(), index: IndexOwned, time: (TimeOfDay, Calendar), ) { diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 3db6bfaf0c..ac8a887813 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -1,6 +1,8 @@ //! # Implementing new commands. //! To implement a new command provide a handler function //! in [do_command]. +#[cfg(feature = "worldgen")] +use crate::weather::WeatherJob; use crate::{ client::Client, location::Locations, @@ -10,7 +12,6 @@ use crate::{ SettingError, WhitelistInfo, WhitelistRecord, }, sys::terrain::SpawnEntityData, - weather::WeatherJob, wiring, wiring::OutputFormula, Server, Settings, StateExt, @@ -54,13 +55,15 @@ use common::{ resources::{BattleMode, PlayerPhysicsSettings, ProgramTime, Secs, Time, TimeOfDay, TimeScale}, rtsim::{Actor, Role}, spiral::Spiral2d, - terrain::{Block, BlockKind, CoordinateConversions, SpriteKind, TerrainChunkSize}, + terrain::{Block, BlockKind, CoordinateConversions, SpriteKind}, tether::Tethered, uid::Uid, vol::ReadVol, - weather, CachedSpatialGrid, Damage, DamageKind, DamageSource, Explosion, GroupTarget, - LoadoutBuilder, RadiusEffect, + CachedSpatialGrid, Damage, DamageKind, DamageSource, Explosion, GroupTarget, LoadoutBuilder, + RadiusEffect, }; +#[cfg(feature = "worldgen")] +use common::{terrain::TerrainChunkSize, weather}; use common_net::{ msg::{DisconnectReason, Notification, PlayerListUpdate, ServerGeneral}, sync::WorldSyncExt, @@ -74,6 +77,7 @@ use specs::{storage::StorageEntry, Builder, Entity as EcsEntity, Join, LendJoin, use std::{fmt::Write, num::NonZeroU32, ops::DerefMut, str::FromStr, sync::Arc, time::Duration}; use vek::*; use wiring::{Circuit, Wire, WireNode, WiringAction, WiringActionEffect, WiringElement}; +#[cfg(feature = "worldgen")] use world::util::{Sampler, LOCALITY}; use common::comp::Alignment; @@ -929,8 +933,20 @@ fn handle_goto( } } +#[cfg(not(feature = "worldgen"))] +fn handle_site( + _server: &mut Server, + _client: EcsEntity, + _target: EcsEntity, + _args: Vec, + _action: &ServerChatCommand, +) -> CmdResult<()> { + Err("Unsupported without worldgen enabled".into()) +} + /// TODO: Add autocompletion if possible (might require modifying enum to handle /// dynamic values). +#[cfg(feature = "worldgen")] fn handle_site( server: &mut Server, _client: EcsEntity, @@ -938,7 +954,6 @@ fn handle_site( args: Vec, action: &ServerChatCommand, ) -> CmdResult<()> { - #[cfg(feature = "worldgen")] if let (Some(dest_name), dismount_volume) = parse_cmd_args!(args, String, bool) { let site = server .world @@ -964,9 +979,6 @@ fn handle_site( } else { Err(Content::Plain(action.help_string())) } - - #[cfg(not(feature = "worldgen"))] - Ok(()) } fn handle_respawn( @@ -3475,9 +3487,9 @@ fn handle_join_faction( #[cfg(not(feature = "worldgen"))] fn handle_debug_column( - server: &mut Server, - client: EcsEntity, - target: EcsEntity, + _server: &mut Server, + _client: EcsEntity, + _target: EcsEntity, _args: Vec, _action: &ServerChatCommand, ) -> CmdResult<()> { @@ -3569,9 +3581,9 @@ cliff_height {:?} "#, #[cfg(not(feature = "worldgen"))] fn handle_debug_ways( - server: &mut Server, - client: EcsEntity, - target: EcsEntity, + _server: &mut Server, + _client: EcsEntity, + _target: EcsEntity, _args: Vec, _action: &ServerChatCommand, ) -> CmdResult<()> { @@ -4728,6 +4740,18 @@ fn handle_delete_location( } } +#[cfg(not(feature = "worldgen"))] +fn handle_weather_zone( + _server: &mut Server, + _client: EcsEntity, + _target: EcsEntity, + _args: Vec, + _action: &ServerChatCommand, +) -> CmdResult<()> { + Err("Unsupported without worldgen enabled".into()) +} + +#[cfg(feature = "worldgen")] fn handle_weather_zone( server: &mut Server, client: EcsEntity, diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 12e7546c96..a54ef0e60c 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -1,5 +1,5 @@ -#[cfg(not(feature = "worldgen"))] -use crate::test_world::{IndexOwned, World}; +#[cfg(feature = "worldgen")] +use crate::rtsim::RtSim; use crate::{ client::Client, comp::{ @@ -11,11 +11,12 @@ use crate::{ error, events::entity_creation::handle_create_npc, pet::tame_pet, - rtsim::RtSim, state_ext::StateExt, sys::terrain::{NpcData, SpawnEntityData, SAFE_ZONE_RADIUS}, Server, Settings, SpawnPoint, }; +#[cfg(feature = "worldgen")] +use common::rtsim::{Actor, RtSimEntity}; use common::{ combat, combat::{AttackSource, DamageContributor}, @@ -48,7 +49,6 @@ use common::{ mounting::{Rider, VolumeRider}, outcome::{HealthChangeInfo, Outcome}, resources::{ProgramTime, Secs, Time}, - rtsim::{Actor, RtSimEntity}, spiral::Spiral2d, states::utils::StageSection, terrain::{Block, BlockKind, TerrainGrid}, @@ -62,11 +62,14 @@ use common_net::{msg::ServerGeneral, sync::WorldSyncExt}; use common_state::{AreasContainer, BlockChange, NoDurabilityArea}; use hashbrown::HashSet; use rand::Rng; +#[cfg(feature = "worldgen")] +use specs::WriteExpect; use specs::{ shred, DispatcherBuilder, Entities, Entity as EcsEntity, Entity, Join, LendJoin, Read, - ReadExpect, ReadStorage, SystemData, WorldExt, Write, WriteExpect, WriteStorage, + ReadExpect, ReadStorage, SystemData, WorldExt, Write, WriteStorage, }; -use std::{collections::HashMap, iter, sync::Arc, time::Duration}; +#[cfg(feature = "worldgen")] use std::sync::Arc; +use std::{collections::HashMap, iter, time::Duration}; use tracing::{debug, warn}; use vek::{Vec2, Vec3}; #[cfg(feature = "worldgen")] @@ -296,7 +299,9 @@ pub struct DestroyEventData<'a> { ability_map: ReadExpect<'a, AbilityMap>, time: Read<'a, Time>, program_time: ReadExpect<'a, ProgramTime>, + #[cfg(feature = "worldgen")] world: ReadExpect<'a, Arc>, + #[cfg(feature = "worldgen")] index: ReadExpect<'a, IndexOwned>, areas_container: Read<'a, AreasContainer>, outcomes: Read<'a, EventBus>, @@ -323,7 +328,9 @@ pub struct DestroyEventData<'a> { alignments: ReadStorage<'a, Alignment>, stats: ReadStorage<'a, Stats>, agents: ReadStorage<'a, Agent>, + #[cfg(feature = "worldgen")] rtsim_entities: ReadStorage<'a, RtSimEntity>, + #[cfg(feature = "worldgen")] presences: ReadStorage<'a, Presence>, } @@ -716,6 +723,7 @@ impl ServerEvent for DestroyEvent { } } + #[cfg(feature = "worldgen")] let entity_as_actor = |entity| { if let Some(rtsim_entity) = data.rtsim_entities.get(entity).copied() { Some(Actor::Npc(rtsim_entity.0)) @@ -727,6 +735,7 @@ impl ServerEvent for DestroyEvent { None } }; + #[cfg(feature = "worldgen")] let actor = entity_as_actor(ev.entity); #[cfg(feature = "worldgen")] diff --git a/server/src/events/information.rs b/server/src/events/information.rs index b5e742d46c..261fc61ecd 100644 --- a/server/src/events/information.rs +++ b/server/src/events/information.rs @@ -3,8 +3,11 @@ use common::event::RequestSiteInfoEvent; use common_net::msg::{world_msg::EconomyInfo, ServerGeneral}; #[cfg(feature = "plugins")] use common_state::plugin::PluginMgr; -use specs::{DispatcherBuilder, ReadExpect, ReadStorage}; +#[cfg(feature = "worldgen")] +use specs::ReadExpect; +use specs::{DispatcherBuilder, ReadStorage}; use std::collections::HashMap; +#[cfg(feature = "worldgen")] use world::IndexOwned; use super::{event_dispatch, ServerEvent}; diff --git a/server/src/events/invite.rs b/server/src/events/invite.rs index bf2a46533b..903fbee9f3 100644 --- a/server/src/events/invite.rs +++ b/server/src/events/invite.rs @@ -3,8 +3,6 @@ use super::{ group_manip::{self, update_map_markers}, ServerEvent, }; -#[cfg(not(feature = "worldgen"))] -use crate::test_world::IndexOwned; use crate::{client::Client, Settings}; use common::{ comp::{ @@ -20,9 +18,10 @@ use common::{ uid::{IdMaps, Uid}, }; use common_net::msg::{InviteAnswer, ServerGeneral}; +#[cfg(feature = "worldgen")] +use specs::ReadExpect; use specs::{ - shred, DispatcherBuilder, Entities, Entity, Read, ReadExpect, ReadStorage, SystemData, Write, - WriteStorage, + shred, DispatcherBuilder, Entities, Entity, Read, ReadStorage, SystemData, Write, WriteStorage, }; use std::time::{Duration, Instant}; use tracing::{error, warn}; @@ -226,6 +225,7 @@ pub struct InviteResponseData<'a> { entities: Entities<'a>, group_manager: Write<'a, GroupManager>, trades: Write<'a, Trades>, + #[cfg(feature = "worldgen")] index: ReadExpect<'a, IndexOwned>, id_maps: Read<'a, IdMaps>, invites: WriteStorage<'a, Invite>, diff --git a/server/src/events/mounting.rs b/server/src/events/mounting.rs index d427646605..e0f8cccdba 100644 --- a/server/src/events/mounting.rs +++ b/server/src/events/mounting.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +#[cfg(feature = "worldgen")] use std::sync::Arc; use common::{ comp::{self, pet::is_mountable}, @@ -6,12 +6,15 @@ use common::{ event::{MountEvent, MountVolumeEvent, UnmountEvent}, link::Is, mounting::{Mounting, Rider, VolumeMounting, VolumeRider}, - rtsim::RtSimEntity, - uid::{IdMaps, Uid}, + uid::Uid, }; +#[cfg(feature = "worldgen")] +use common::{rtsim::RtSimEntity, uid::IdMaps}; use specs::WorldExt; -use crate::{rtsim::RtSim, state_ext::StateExt, Server}; +#[cfg(feature = "worldgen")] +use crate::rtsim::RtSim; +use crate::{state_ext::StateExt, Server}; pub fn within_mounting_range( player_position: Option<&comp::Pos>, diff --git a/server/src/events/trade.rs b/server/src/events/trade.rs index b7a9a95297..72b96f4fb4 100644 --- a/server/src/events/trade.rs +++ b/server/src/events/trade.rs @@ -18,6 +18,7 @@ use hashbrown::{hash_map::Entry, HashMap}; use specs::{world::WorldExt, Entity as EcsEntity}; use std::{cmp::Ordering, num::NonZeroU32}; use tracing::{error, trace}; +#[cfg(feature = "worldgen")] use world::IndexOwned; pub fn notify_agent_simple( @@ -30,6 +31,7 @@ pub fn notify_agent_simple( } } +#[cfg(feature = "worldgen")] fn notify_agent_prices( mut agents: specs::WriteStorage, index: &IndexOwned, @@ -104,7 +106,10 @@ pub(super) fn handle_process_trade_action( } else { let mut entities: [Option; 2] = [None, None]; let mut inventories: [Option; 2] = [None, None]; + #[cfg(feature = "worldgen")] let mut prices = None; + #[cfg(not(feature = "worldgen"))] + let prices = None; let agents = server.state.ecs().read_storage::(); // sadly there is no map and collect on arrays for i in 0..2 { diff --git a/server/src/lib.rs b/server/src/lib.rs index c17585ca4f..332b2275d6 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -41,7 +41,7 @@ pub mod sys; pub mod terrain_persistence; #[cfg(not(feature = "worldgen"))] mod test_world; -mod weather; +#[cfg(feature = "worldgen")] mod weather; pub mod wiring; @@ -73,6 +73,8 @@ use crate::{ use censor::Censor; #[cfg(not(feature = "worldgen"))] use common::grid::Grid; +#[cfg(feature = "worldgen")] +use common::terrain::TerrainChunkSize; use common::{ assets::AssetExt, calendar::Calendar, @@ -90,7 +92,7 @@ use common::{ rtsim::RtSimEntity, shared_server_config::ServerConstants, slowjob::SlowJobPool, - terrain::{TerrainChunk, TerrainChunkSize}, + terrain::TerrainChunk, vol::RectRasterableVol, }; use common_base::prof_span; @@ -117,15 +119,12 @@ use std::{ sync::Arc, time::{Duration, Instant}, }; +#[cfg(not(feature = "worldgen"))] +use test_world::{IndexOwned, World}; use tokio::runtime::Runtime; use tracing::{debug, error, info, trace, warn}; use vek::*; pub use world::{civ::WorldCivStage, sim::WorldSimStage, WorldGenerateStage}; -#[cfg(not(feature = "worldgen"))] -use { - common_net::msg::WorldMapMsg, - test_world::{IndexOwned, World}, -}; use crate::{ persistence::{DatabaseSettings, SqlLogMode}, @@ -496,7 +495,7 @@ impl Server { #[cfg(feature = "worldgen")] let size = world.sim().get_size(); #[cfg(not(feature = "worldgen"))] - let size = Vec2::new(40, 40); + let size = world.map_size_lg().chunks().map(u32::from); let world_size = size.map(|e| e as i32) * TerrainChunk::RECT_SIZE.map(|e| e as i32); let world_aabb = Aabb { diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs index 0ddbee71fa..49c1b05e00 100644 --- a/server/src/state_ext.rs +++ b/server/src/state_ext.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "worldgen")] +use crate::rtsim::RtSim; use crate::{ automod::AutoMod, chat::ChatExporter, @@ -6,13 +8,13 @@ use crate::{ persistence::PersistedComponents, pet::restore_pet, presence::RepositionOnChunkLoad, - rtsim::RtSim, settings::Settings, sys::sentinel::DeletedEntities, wiring, BattleModeBuffer, SpawnPoint, }; +#[cfg(feature = "worldgen")] +use common::{calendar::Calendar, resources::TimeOfDay, slowjob::SlowJobPool}; use common::{ - calendar::Calendar, character::CharacterId, combat, combat::DamageContributor, @@ -26,9 +28,8 @@ use common::{ effect::Effect, link::{Is, Link, LinkHandle}, mounting::{Mounting, Rider, VolumeMounting, VolumeRider}, - resources::{Secs, Time, TimeOfDay}, + resources::{Secs, Time}, rtsim::{Actor, RtSimEntity}, - slowjob::SlowJobPool, tether::Tethered, uid::{IdMaps, Uid}, util::Dir, @@ -111,6 +112,7 @@ pub trait StateExt { /// Queues chunk generation in the view distance of the persister, this /// entity must be built before those chunks are received (the builder /// borrows the ecs world so that is kind of impossible in practice) + #[cfg(feature = "worldgen")] fn create_persister( &mut self, pos: comp::Pos, @@ -546,6 +548,7 @@ impl StateExt for State { /// Queues chunk generation in the view distance of the persister, this /// entity must be built before those chunks are received (the builder /// borrows the ecs world so that is kind of impossible in practice) + #[cfg(feature = "worldgen")] fn create_persister( &mut self, pos: comp::Pos, @@ -559,10 +562,7 @@ impl StateExt for State { { let ecs = self.ecs(); let slow_jobs = ecs.write_resource::(); - #[cfg(feature = "worldgen")] let rtsim = ecs.read_resource::(); - #[cfg(not(feature = "worldgen"))] - let rtsim = (); let mut chunk_generator = ecs.write_resource::(); let chunk_pos = self.terrain().pos_key(pos.0.map(|e| e as i32)); @@ -580,7 +580,6 @@ impl StateExt for State { * TerrainChunkSize::RECT_SIZE.x as f64 }) .for_each(|chunk_key| { - #[cfg(feature = "worldgen")] { let time = (*ecs.read_resource::(), (*ecs.read_resource::()).clone()); chunk_generator.generate_chunk(None, chunk_key, &slow_jobs, Arc::clone(world), &rtsim, index.clone(), time); diff --git a/server/src/sys/msg/character_screen.rs b/server/src/sys/msg/character_screen.rs index fb4e34ce33..1bdc6ff775 100644 --- a/server/src/sys/msg/character_screen.rs +++ b/server/src/sys/msg/character_screen.rs @@ -1,5 +1,5 @@ #[cfg(not(feature = "worldgen"))] -use crate::test_world::{IndexOwned, World}; +use crate::test_world::World; #[cfg(feature = "worldgen")] use world::{IndexOwned, World}; @@ -10,6 +10,8 @@ use crate::{ persistence::{character_loader::CharacterLoader, character_updater::CharacterUpdater}, EditableSettings, }; +#[cfg(feature = "worldgen")] +use common::terrain::TerrainChunkSize; use common::{ comp::{Admin, AdminRole, ChatType, Player, Presence, Waypoint}, event::{ @@ -18,14 +20,15 @@ use common::{ }, event_emitters, resources::Time, - terrain::TerrainChunkSize, uid::Uid, }; use common_ecs::{Job, Origin, Phase, System}; use common_net::msg::{ClientGeneral, ServerGeneral}; -use specs::{Entities, Join, ReadExpect, ReadStorage, WriteExpect, WriteStorage}; +use specs::{ + shred, Entities, Join, ReadExpect, ReadStorage, SystemData, WriteExpect, WriteStorage, +}; use std::sync::{atomic::Ordering, Arc}; -use tracing::{debug, error}; +use tracing::debug; event_emitters! { struct Events[Emitters] { @@ -54,7 +57,7 @@ impl Sys { automod: &AutoMod, msg: ClientGeneral, time: Time, - index: &ReadExpect<'_, IndexOwned>, + #[cfg(feature = "worldgen")] index: &ReadExpect<'_, IndexOwned>, world: &ReadExpect<'_, Arc>, ) -> Result<(), crate::error::Error> { let mut send_join_messages = || -> Result<(), crate::error::Error> { @@ -165,7 +168,10 @@ impl Sys { mainhand, offhand, body, + #[cfg(feature = "worldgen")] start_site, + #[cfg(not(feature = "worldgen"))] + start_site: _, } => { if censor.check(&alias) { debug!(?alias, "denied alias as it contained a banned word"); @@ -188,7 +194,7 @@ impl Sys { .find(|(_, site)| site.site_tmp.map(|i| i.id()) == Some(site_idx)) .map(Some) .unwrap_or_else(|| { - error!( + tracing::error!( "Tried to create character with starting site index {}, but \ such a site does not exist", site_idx @@ -272,73 +278,59 @@ impl Sys { } } +#[derive(SystemData)] +pub struct Data<'a> { + entities: Entities<'a>, + events: Events<'a>, + character_loader: ReadExpect<'a, CharacterLoader>, + character_updater: WriteExpect<'a, CharacterUpdater>, + uids: ReadStorage<'a, Uid>, + clients: WriteStorage<'a, Client>, + players: ReadStorage<'a, Player>, + admins: ReadStorage<'a, Admin>, + presences: ReadStorage<'a, Presence>, + editable_settings: ReadExpect<'a, EditableSettings>, + censor: ReadExpect<'a, Arc>, + automod: ReadExpect<'a, AutoMod>, + time: ReadExpect<'a, Time>, + #[cfg(feature = "worldgen")] + index: ReadExpect<'a, IndexOwned>, + world: ReadExpect<'a, Arc>, +} + /// This system will handle new messages from clients #[derive(Default)] pub struct Sys; impl<'a> System<'a> for Sys { - type SystemData = ( - Entities<'a>, - Events<'a>, - ReadExpect<'a, CharacterLoader>, - WriteExpect<'a, CharacterUpdater>, - ReadStorage<'a, Uid>, - WriteStorage<'a, Client>, - ReadStorage<'a, Player>, - ReadStorage<'a, Admin>, - ReadStorage<'a, Presence>, - ReadExpect<'a, EditableSettings>, - ReadExpect<'a, Arc>, - ReadExpect<'a, AutoMod>, - ReadExpect<'a, Time>, - ReadExpect<'a, IndexOwned>, - ReadExpect<'a, Arc>, - ); + type SystemData = Data<'a>; const NAME: &'static str = "msg::character_screen"; const ORIGIN: Origin = Origin::Server; const PHASE: Phase = Phase::Create; - fn run( - _job: &mut Job, - ( - entities, - events, - character_loader, - mut character_updater, - uids, - mut clients, - players, - admins, - presences, - editable_settings, - censor, - automod, - time, - index, - world, - ): Self::SystemData, - ) { - let mut emitters = events.get_emitters(); + fn run(_job: &mut Job, mut data: Self::SystemData) { + let mut emitters = data.events.get_emitters(); - for (entity, client) in (&entities, &mut clients).join() { + for (entity, client) in (&data.entities, &mut data.clients).join() { let _ = super::try_recv_all(client, 1, |client, msg| { Self::handle_client_character_screen_msg( &mut emitters, entity, client, - &character_loader, - &mut character_updater, - &uids, - &players, - &admins, - &presences, - &editable_settings, - &censor, - &automod, + &data.character_loader, + &mut data.character_updater, + &data.uids, + &data.players, + &data.admins, + &data.presences, + &data.editable_settings, + &data.censor, + &data.automod, msg, - *time, - &index, - &world, + *data.time, + #[cfg(feature = "worldgen")] + &data.index, + &data.world, ) }); } diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index 9247b492aa..b32ae4d70c 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -6,9 +6,10 @@ use tracing::error; #[cfg(feature = "worldgen")] use world::{IndexOwned, World}; +#[cfg(feature = "worldgen")] use crate::rtsim; use crate::{ chunk_generator::ChunkGenerator, chunk_serialize::ChunkSendEntry, client::Client, - presence::RepositionOnChunkLoad, rtsim, settings::Settings, ChunkRequest, Tick, + presence::RepositionOnChunkLoad, settings::Settings, ChunkRequest, Tick, }; use common::{ calendar::Calendar, @@ -35,8 +36,8 @@ use core::cmp::Reverse; use itertools::Itertools; use rayon::{iter::Either, prelude::*}; use specs::{ - storage::GenericReadStorage, Entities, Entity, Join, LendJoin, ParJoin, Read, ReadExpect, - ReadStorage, Write, WriteExpect, WriteStorage, + shred, storage::GenericReadStorage, Entities, Entity, Join, LendJoin, ParJoin, Read, + ReadExpect, ReadStorage, SystemData, Write, WriteExpect, WriteStorage, }; use std::{f32::consts::TAU, sync::Arc}; use vek::*; @@ -60,6 +61,34 @@ event_emitters! { } } +#[derive(SystemData)] +pub struct Data<'a> { + events: Events<'a>, + tick: Read<'a, Tick>, + server_settings: Read<'a, Settings>, + time_of_day: Read<'a, TimeOfDay>, + calendar: Read<'a, Calendar>, + slow_jobs: ReadExpect<'a, SlowJobPool>, + index: ReadExpect<'a, IndexOwned>, + world: ReadExpect<'a, Arc>, + chunk_send_bus: ReadExpect<'a, EventBus>, + chunk_generator: WriteExpect<'a, ChunkGenerator>, + terrain: WriteExpect<'a, TerrainGrid>, + terrain_changes: Write<'a, TerrainChanges>, + chunk_requests: Write<'a, Vec>, + rtsim: RtSimData<'a>, + #[cfg(feature = "persistent_world")] + terrain_persistence: TerrainPersistenceData<'a>, + positions: WriteStorage<'a, Pos>, + presences: ReadStorage<'a, Presence>, + clients: ReadStorage<'a, Client>, + entities: Entities<'a>, + reposition_on_load: WriteStorage<'a, RepositionOnChunkLoad>, + forced_updates: WriteStorage<'a, ForceUpdate>, + waypoints: WriteStorage<'a, Waypoint>, + time: ReadExpect<'a, Time>, +} + /// This system will handle loading generated chunks and unloading /// unneeded chunks. /// 1. Inserts newly generated chunks into the TerrainGrid @@ -70,80 +99,29 @@ event_emitters! { pub struct Sys; impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] - type SystemData = ( - Events<'a>, - Read<'a, Tick>, - Read<'a, Settings>, - Read<'a, TimeOfDay>, - Read<'a, Calendar>, - ReadExpect<'a, SlowJobPool>, - ReadExpect<'a, IndexOwned>, - ReadExpect<'a, Arc>, - ReadExpect<'a, EventBus>, - WriteExpect<'a, ChunkGenerator>, - WriteExpect<'a, TerrainGrid>, - Write<'a, TerrainChanges>, - Write<'a, Vec>, - RtSimData<'a>, - TerrainPersistenceData<'a>, - WriteStorage<'a, Pos>, - ReadStorage<'a, Presence>, - ReadStorage<'a, Client>, - Entities<'a>, - WriteStorage<'a, RepositionOnChunkLoad>, - WriteStorage<'a, ForceUpdate>, - WriteStorage<'a, Waypoint>, - ReadExpect<'a, Time>, - ); + type SystemData = Data<'a>; const NAME: &'static str = "terrain"; const ORIGIN: Origin = Origin::Server; const PHASE: Phase = Phase::Create; - fn run( - _job: &mut Job, - ( - events, - tick, - server_settings, - time_of_day, - calendar, - slow_jobs, - index, - world, - chunk_send_bus, - mut chunk_generator, - mut terrain, - mut terrain_changes, - mut chunk_requests, - mut rtsim, - mut _terrain_persistence, - mut positions, - presences, - clients, - entities, - mut reposition_on_load, - mut force_update, - mut waypoints, - time, - ): Self::SystemData, - ) { - let mut emitters = events.get_emitters(); + fn run(_job: &mut Job, mut data: Self::SystemData) { + let mut emitters = data.events.get_emitters(); // Generate requested chunks // // Submit requests for chunks right before receiving finished chunks so that we // don't create duplicate work for chunks that just finished but are not // yet added to the terrain. - chunk_requests.drain(..).for_each(|request| { - chunk_generator.generate_chunk( + data.chunk_requests.drain(..).for_each(|request| { + data.chunk_generator.generate_chunk( Some(request.entity), request.key, - &slow_jobs, - Arc::clone(&world), - &rtsim, - index.clone(), - (*time_of_day, calendar.clone()), + &data.slow_jobs, + Arc::clone(&data.world), + &data.rtsim, + data.index.clone(), + (*data.time_of_day, data.calendar.clone()), ) }); @@ -151,12 +129,12 @@ impl<'a> System<'a> for Sys { // Fetch any generated `TerrainChunk`s and insert them into the terrain. // Also, send the chunk data to anybody that is close by. let mut new_chunks = Vec::new(); - 'insert_terrain_chunks: while let Some((key, res)) = chunk_generator.recv_new_chunk() { + 'insert_terrain_chunks: while let Some((key, res)) = data.chunk_generator.recv_new_chunk() { #[allow(unused_mut)] let (mut chunk, supplement) = match res { Ok((chunk, supplement)) => (chunk, supplement), Err(Some(entity)) => { - if let Some(client) = clients.get(entity) { + if let Some(client) = data.clients.get(entity) { client.send_fallible(ServerGeneral::TerrainChunkUpdate { key, chunk: Err(()), @@ -171,7 +149,7 @@ impl<'a> System<'a> for Sys { // Apply changes from terrain persistence to this chunk #[cfg(feature = "persistent_world")] - if let Some(terrain_persistence) = _terrain_persistence.as_mut() { + if let Some(terrain_persistence) = data.terrain_persistence.as_mut() { terrain_persistence.apply_changes(key, &mut chunk); } @@ -183,19 +161,20 @@ impl<'a> System<'a> for Sys { // TODO: code duplication for chunk insertion between here and state.rs // Insert the chunk into terrain changes - if terrain.insert(key, chunk).is_some() { - terrain_changes.modified_chunks.insert(key); + if data.terrain.insert(key, chunk).is_some() { + data.terrain_changes.modified_chunks.insert(key); } else { - terrain_changes.new_chunks.insert(key); + data.terrain_changes.new_chunks.insert(key); #[cfg(feature = "worldgen")] - rtsim.hook_load_chunk(key, supplement.rtsim_max_resources); + data.rtsim + .hook_load_chunk(key, supplement.rtsim_max_resources); } // Handle chunk supplement for entity in supplement.entities { // Check this because it's a common source of weird bugs assert!( - terrain + data.terrain .pos_key(entity.pos.map(|e| e.floor() as i32)) .map2(key, |e, tgt| (e - tgt).abs() <= 1) .reduce_and(), @@ -223,7 +202,7 @@ impl<'a> System<'a> for Sys { // TODO: Consider putting this in another system since this forces us to take // positions by write rather than read access. - let repositioned = (&entities, &mut positions, (&mut force_update).maybe(), &reposition_on_load) + let repositioned = (&data.entities, &mut data.positions, (&mut data.forced_updates).maybe(), &data.reposition_on_load) // TODO: Consider using par_bridge() because Rayon has very poor work splitting for // sparse joins. .par_join() @@ -234,11 +213,11 @@ impl<'a> System<'a> for Sys { // If an entity is marked as needing repositioning once the chunk loads (e.g. // from having just logged in), reposition them. let chunk_pos = TerrainGrid::chunk_key(entity_pos); - let chunk = terrain.get_key(chunk_pos)?; + let chunk = data.terrain.get_key(chunk_pos)?; let new_pos = if reposition.needs_ground { - terrain.try_find_ground(entity_pos) + data.terrain.try_find_ground(entity_pos) } else { - terrain.try_find_space(entity_pos) + data.terrain.try_find_space(entity_pos) }.map(|x| x.as_::()).unwrap_or_else(|| chunk.find_accessible_pos(entity_pos.xy(), false)); pos.0 = new_pos; force_update.map(|force_update| force_update.update()); @@ -247,30 +226,30 @@ impl<'a> System<'a> for Sys { .collect::>(); for (entity, new_pos) in repositioned { - if let Some(waypoint) = waypoints.get_mut(entity) { - *waypoint = Waypoint::new(new_pos, *time); + if let Some(waypoint) = data.waypoints.get_mut(entity) { + *waypoint = Waypoint::new(new_pos, *data.time); } - reposition_on_load.remove(entity); + data.reposition_on_load.remove(entity); } - let max_view_distance = server_settings.max_view_distance.unwrap_or(u32::MAX); + let max_view_distance = data.server_settings.max_view_distance.unwrap_or(u32::MAX); #[cfg(feature = "worldgen")] - let world_size = world.sim().get_size(); + let world_size = data.world.sim().get_size(); #[cfg(not(feature = "worldgen"))] - let world_size = world.map_size_lg().chunks().map(u32::from); + let world_size = data.world.map_size_lg().chunks().map(u32::from); let (presences_position_entities, presences_positions) = prepare_player_presences( world_size, max_view_distance, - &entities, - &positions, - &presences, - &clients, + &data.entities, + &data.positions, + &data.presences, + &data.clients, ); let real_max_view_distance = convert_to_loaded_vd(u32::MAX, max_view_distance); // Send the chunks to all nearby players. new_chunks.par_iter().for_each_init( - || chunk_send_bus.emitter(), + || data.chunk_send_bus.emitter(), |chunk_send_emitter, chunk_key| { // We only have to check players inside the maximum view distance of the server // of our own position. @@ -311,19 +290,19 @@ impl<'a> System<'a> for Sys { }, ); - let tick = (tick.0 % 16) as i32; + let tick = (data.tick.0 % 16) as i32; // Remove chunks that are too far from players. // // Note that all chunks involved here (both terrain chunks and pending chunks) // are guaranteed in bounds. This simplifies the rest of the logic // here. - let chunks_to_remove = terrain + let chunks_to_remove = data.terrain .par_keys() .copied() // There may be lots of pending chunks, so don't check them all. This should be okay // as long as we're maintaining a reasonable tick rate. - .chain(chunk_generator.par_pending_chunks()) + .chain(data.chunk_generator.par_pending_chunks()) // Don't check every chunk every tick (spread over 16 ticks) // // TODO: Investigate whether we can add support for performing this filtering directly @@ -370,26 +349,26 @@ impl<'a> System<'a> for Sys { .filter_map(|key| { // Register the unloading of this chunk from terrain persistence #[cfg(feature = "persistent_world")] - if let Some(terrain_persistence) = _terrain_persistence.as_mut() { + if let Some(terrain_persistence) = data.terrain_persistence.as_mut() { terrain_persistence.unload_chunk(key); } - chunk_generator.cancel_if_pending(key); + data.chunk_generator.cancel_if_pending(key); // If you want to trigger any behaivour on unload, do it in `Server::tick` by // reading `TerrainChanges::removed_chunks` since chunks can also be removed // using eg. /reload_chunks // TODO: code duplication for chunk insertion between here and state.rs - terrain.remove(key).map(|chunk| { - terrain_changes.removed_chunks.insert(key); + data.terrain.remove(key).map(|chunk| { + data.terrain_changes.removed_chunks.insert(key); chunk }) }) .collect::>(); if !chunks_to_remove.is_empty() { // Drop chunks in a background thread. - slow_jobs.spawn("CHUNK_DROP", move || { + data.slow_jobs.spawn("CHUNK_DROP", move || { drop(chunks_to_remove); }); } diff --git a/server/src/sys/terrain_sync.rs b/server/src/sys/terrain_sync.rs index a42b0ad07c..a79ddd123f 100644 --- a/server/src/sys/terrain_sync.rs +++ b/server/src/sys/terrain_sync.rs @@ -59,8 +59,6 @@ impl<'a> System<'a> for Sys { &presences, &clients, ); - #[cfg(not(feature = "worldgen"))] - let presences_position_entities: Vec<((vek::Vec2, i32), specs::Entity)> = Vec::new(); let real_max_view_distance = super::terrain::convert_to_loaded_vd(u32::MAX, max_view_distance); diff --git a/server/src/test_world.rs b/server/src/test_world.rs index 24a4a3424c..a966bcb32b 100644 --- a/server/src/test_world.rs +++ b/server/src/test_world.rs @@ -1,12 +1,12 @@ use common::{ calendar::Calendar, - generation::{ChunkSupplement, EntityInfo}, + generation::ChunkSupplement, resources::TimeOfDay, rtsim::ChunkResource, terrain::{ Block, BlockKind, MapSizeLg, SpriteKind, TerrainChunk, TerrainChunkMeta, TerrainChunkSize, }, - vol::{ReadVol, RectVolSize, WriteVol}, + vol::RectVolSize, }; use enum_map::EnumMap; use rand::{prelude::*, rngs::SmallRng}; @@ -26,6 +26,7 @@ pub struct World; pub struct IndexOwned; #[derive(Clone, Copy)] +#[allow(dead_code)] pub struct IndexRef<'a>(&'a IndexOwned); impl IndexOwned { @@ -39,7 +40,7 @@ impl IndexOwned { impl World { pub fn generate(_seed: u32) -> (Self, IndexOwned) { (Self, IndexOwned) } - pub fn tick(&self, dt: Duration) {} + pub fn tick(&self, _dt: Duration) {} #[inline(always)] pub const fn map_size_lg(&self) -> MapSizeLg { DEFAULT_WORLD_CHUNKS_LG } @@ -63,7 +64,7 @@ impl World { ]); let height = rng.gen::() % 8; - let mut supplement = ChunkSupplement::default(); + let supplement = ChunkSupplement::default(); Ok(( TerrainChunk::new( @@ -79,7 +80,7 @@ impl World { pub fn get_center(&self) -> Vec2 { // FIXME: Assumes that TerrainChunkSize::RECT_SIZE.x == // TerrainChunkSize::RECT_SIZE.y - DEFAULT_WORLD_CHUNKS_LG.chunks().as_::() / 2 * TerrainChunkSize::RECT_SIZE.x as u32 + DEFAULT_WORLD_CHUNKS_LG.chunks().as_::() / 2 * TerrainChunkSize::RECT_SIZE.x } pub fn get_location_name(&self, _index: IndexRef, _wpos2d: Vec2) -> Option { diff --git a/server/src/weather/mod.rs b/server/src/weather/mod.rs index 710a9cc8fa..ea90dfb474 100644 --- a/server/src/weather/mod.rs +++ b/server/src/weather/mod.rs @@ -10,6 +10,7 @@ pub use tick::WeatherJob; /// How often the weather is updated, in seconds const WEATHER_DT: f32 = 5.0; +#[cfg(feature = "worldgen")] pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { dispatch::(dispatch_builder, &[]); }