From 8c5320d20f766c642c402ff28bb5b0cc398bdf27 Mon Sep 17 00:00:00 2001 From: S Handley Date: Fri, 20 Dec 2019 04:04:05 +0000 Subject: [PATCH 01/51] Update title music and temporarily remove attack sfx - Updated title music with a version provided by aeronic which fades out more gracefully - Removed attack SFX as it was included in the movement processing, but will return later as part of a similar chunk of code which processes combat sfx independent of movement. --- .../audio/soundtrack/veloren_title_tune-3.ogg | 3 - .../audio/soundtrack/veloren_title_tune.ogg | 3 + voxygen/src/audio/sfx/event_mapper.rs | 120 +++--------------- voxygen/src/menu/main/mod.rs | 2 +- 4 files changed, 23 insertions(+), 105 deletions(-) delete mode 100644 assets/voxygen/audio/soundtrack/veloren_title_tune-3.ogg create mode 100644 assets/voxygen/audio/soundtrack/veloren_title_tune.ogg diff --git a/assets/voxygen/audio/soundtrack/veloren_title_tune-3.ogg b/assets/voxygen/audio/soundtrack/veloren_title_tune-3.ogg deleted file mode 100644 index 6dc81427cb..0000000000 --- a/assets/voxygen/audio/soundtrack/veloren_title_tune-3.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8aaf0657c2f87c0850dbee612dd5848046876872d9ee04f1bb19203c5d264cad -size 2813669 diff --git a/assets/voxygen/audio/soundtrack/veloren_title_tune.ogg b/assets/voxygen/audio/soundtrack/veloren_title_tune.ogg new file mode 100644 index 0000000000..e82338c902 --- /dev/null +++ b/assets/voxygen/audio/soundtrack/veloren_title_tune.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:beafff717eb70b2dbfa0273f8b51a0dbeced8fab9479179328a73127609f989b +size 2589963 diff --git a/voxygen/src/audio/sfx/event_mapper.rs b/voxygen/src/audio/sfx/event_mapper.rs index 8524f04fc8..69baaa6b93 100644 --- a/voxygen/src/audio/sfx/event_mapper.rs +++ b/voxygen/src/audio/sfx/event_mapper.rs @@ -4,7 +4,7 @@ use crate::audio::sfx::{SfxTriggerItem, SfxTriggers}; use client::Client; use common::{ - comp::{ActionState, Body, CharacterState, ItemKind, MovementState, Pos, Stats}, + comp::{ActionState, Body, CharacterState, MovementState, Pos}, event::{EventBus, SfxEvent, SfxEventItem}, }; use hashbrown::HashMap; @@ -38,11 +38,10 @@ impl SfxEventMapper { .get(client.entity()) .map_or(Vec3::zero(), |pos| pos.0); - for (entity, pos, body, stats, character) in ( + for (entity, pos, body, character) in ( &ecs.entities(), &ecs.read_storage::(), &ecs.read_storage::(), - &ecs.read_storage::(), ecs.read_storage::().maybe(), ) .join() @@ -50,7 +49,7 @@ impl SfxEventMapper { (e_pos.0.distance_squared(player_position)) < SFX_DIST_LIMIT_SQR }) { - if let (pos, body, Some(character), stats) = (pos, body, character, stats) { + if let Some(character) = character { let state = self .event_history .entry(entity) @@ -60,11 +59,10 @@ impl SfxEventMapper { }); let mapped_event = match body { - Body::Humanoid(_) => { - Self::map_character_event(character, state.event.clone(), stats) - } + Body::Humanoid(_) => Self::map_movement_event(character, state.event.clone()), Body::QuadrupedMedium(_) => { - Self::map_quadriped_event(character, state.event.clone(), stats) + // TODO: Quadriped running sfx + SfxEvent::Idle } _ => SfxEvent::Idle, }; @@ -129,60 +127,26 @@ impl SfxEventMapper { /// however that list does not provide enough resolution to target specific entity events, such /// as opening or closing the glider. These methods translate those entity states with some additional /// data into more specific `SfxEvent`'s which we attach sounds to - fn map_quadriped_event( - current_event: &CharacterState, - previous_event: SfxEvent, - stats: &Stats, - ) -> SfxEvent { - match ( - current_event.movement, - current_event.action, - previous_event, - stats, - ) { - (_, ActionState::Attack { .. }, _, stats) => match stats.name.as_ref() { - "Wolf" => SfxEvent::AttackWolf, - _ => SfxEvent::Idle, - }, - _ => SfxEvent::Idle, - } - } - - fn map_character_event( - current_event: &CharacterState, - previous_event: SfxEvent, - stats: &Stats, - ) -> SfxEvent { - match ( - current_event.movement, - current_event.action, - previous_event, - stats, - ) { - (_, ActionState::Roll { .. }, ..) => SfxEvent::Roll, + fn map_movement_event(current_event: &CharacterState, previous_event: SfxEvent) -> SfxEvent { + match (current_event.movement, current_event.action, previous_event) { + (_, ActionState::Roll { .. }, _) => SfxEvent::Roll, (MovementState::Climb, ..) => SfxEvent::Climb, (MovementState::Swim, ..) => SfxEvent::Swim, (MovementState::Run, ..) => SfxEvent::Run, - (MovementState::Fall, _, previous_event, _) => { + (MovementState::Fall, _, previous_event) => { if previous_event != SfxEvent::Glide { SfxEvent::Fall } else { SfxEvent::GliderClose } } - (MovementState::Glide, _, previous_event, ..) => { + (MovementState::Glide, _, previous_event) => { if previous_event != SfxEvent::GliderOpen && previous_event != SfxEvent::Glide { SfxEvent::GliderOpen } else { SfxEvent::Glide } } - (_, ActionState::Attack { .. }, _, stats) => { - match &stats.equipment.main.as_ref().map(|i| &i.kind) { - Some(ItemKind::Tool { kind, .. }) => SfxEvent::Attack(*kind), - _ => SfxEvent::Idle, - } - } _ => SfxEvent::Idle, } } @@ -192,8 +156,7 @@ impl SfxEventMapper { mod tests { use super::*; use common::{ - assets, - comp::{item::Tool, ActionState, MovementState, Stats}, + comp::{ActionState, MovementState}, event::SfxEvent, }; use std::time::{Duration, Instant}; @@ -269,15 +232,12 @@ mod tests { #[test] fn maps_idle() { - let stats = Stats::new(String::from("Test"), None); - - let result = SfxEventMapper::map_character_event( + let result = SfxEventMapper::map_movement_event( &CharacterState { movement: MovementState::Stand, action: ActionState::Idle, }, SfxEvent::Idle, - &stats, ); assert_eq!(result, SfxEvent::Idle); @@ -285,15 +245,12 @@ mod tests { #[test] fn maps_run() { - let stats = Stats::new(String::from("Test"), None); - - let result = SfxEventMapper::map_character_event( + let result = SfxEventMapper::map_movement_event( &CharacterState { movement: MovementState::Run, action: ActionState::Idle, }, SfxEvent::Idle, - &stats, ); assert_eq!(result, SfxEvent::Run); @@ -301,9 +258,7 @@ mod tests { #[test] fn maps_roll() { - let stats = Stats::new(String::from("Test"), None); - - let result = SfxEventMapper::map_character_event( + let result = SfxEventMapper::map_movement_event( &CharacterState { action: ActionState::Roll { time_left: Duration::new(1, 0), @@ -312,7 +267,6 @@ mod tests { movement: MovementState::Run, }, SfxEvent::Run, - &stats, ); assert_eq!(result, SfxEvent::Roll); @@ -320,15 +274,12 @@ mod tests { #[test] fn maps_fall() { - let stats = Stats::new(String::from("Test"), None); - - let result = SfxEventMapper::map_character_event( + let result = SfxEventMapper::map_movement_event( &CharacterState { movement: MovementState::Fall, action: ActionState::Idle, }, SfxEvent::Idle, - &stats, ); assert_eq!(result, SfxEvent::Fall); @@ -336,15 +287,12 @@ mod tests { #[test] fn maps_glider_open() { - let stats = Stats::new(String::from("Test"), None); - - let result = SfxEventMapper::map_character_event( + let result = SfxEventMapper::map_movement_event( &CharacterState { movement: MovementState::Glide, action: ActionState::Idle, }, SfxEvent::Jump, - &stats, ); assert_eq!(result, SfxEvent::GliderOpen); @@ -352,15 +300,12 @@ mod tests { #[test] fn maps_glide() { - let stats = Stats::new(String::from("Test"), None); - - let result = SfxEventMapper::map_character_event( + let result = SfxEventMapper::map_movement_event( &CharacterState { movement: MovementState::Glide, action: ActionState::Idle, }, SfxEvent::Glide, - &stats, ); assert_eq!(result, SfxEvent::Glide); @@ -368,41 +313,14 @@ mod tests { #[test] fn maps_glider_close() { - let stats = Stats::new(String::from("Test"), None); - - let result = SfxEventMapper::map_character_event( + let result = SfxEventMapper::map_movement_event( &CharacterState { movement: MovementState::Fall, action: ActionState::Idle, }, SfxEvent::Glide, - &stats, ); assert_eq!(result, SfxEvent::GliderClose); } - - #[test] - fn maps_attack() { - let stats = Stats::new( - String::from("Test"), - Some(assets::load_expect_cloned( - "common.items.weapons.starter_sword", - )), - ); - - let result = SfxEventMapper::map_character_event( - &CharacterState { - movement: MovementState::Stand, - action: ActionState::Attack { - time_left: Duration::new(1, 0), - applied: true, - }, - }, - SfxEvent::Idle, - &stats, - ); - - assert_eq!(result, SfxEvent::Attack(Tool::Sword)); - } } diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 6605a06218..f972819a3b 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -45,7 +45,7 @@ impl PlayState for MainMenuState { if self.title_music_channel.is_none() && global_state.settings.audio.audio_on { self.title_music_channel = global_state .audio - .play_music("voxygen.audio.soundtrack.veloren_title_tune-3"); + .play_music("voxygen.audio.soundtrack.veloren_title_tune"); } // Reset singleplayer server if it was running already From 0d919a9dc6b8cfc4bdcba726d771c5070049c749 Mon Sep 17 00:00:00 2001 From: Songtronix Date: Sat, 23 Nov 2019 15:34:03 +0100 Subject: [PATCH 02/51] improve(log): adjust verbosity of some logging fix: settings do not log due to logging being initialized to late --- server/src/lib.rs | 9 +++-- voxygen/src/logging.rs | 55 +++++++++++++++++++++++++++++ voxygen/src/main.rs | 76 ++++++++-------------------------------- world/src/sim/erosion.rs | 22 ++++++------ world/src/sim/mod.rs | 2 +- 5 files changed, 85 insertions(+), 79 deletions(-) create mode 100644 voxygen/src/logging.rs diff --git a/server/src/lib.rs b/server/src/lib.rs index 3ce446fed5..41eaeb78d6 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -30,7 +30,7 @@ use common::{ terrain::{block::Block, TerrainChunkSize, TerrainGrid}, vol::{ReadVol, RectVolSize, Vox}, }; -use log::{debug, trace}; +use log::debug; use metrics::ServerMetrics; use rand::Rng; use specs::{join::Join, world::EntityBuilder as EcsEntityBuilder, Builder, Entity as EcsEntity}; @@ -178,8 +178,7 @@ impl Server { .expect("Failed to initialize server metrics submodule."), server_settings: settings.clone(), }; - debug!("created veloren server"); - trace!("server configuration: {:?}", &settings); + debug!("created veloren server with: {:?}", &settings); Ok(this) } @@ -973,7 +972,7 @@ impl Server { .with(client) .build(); // Return the state of the current world (all of the components that Sphynx tracks). - log::info!("Starting initial sync with client."); + log::debug!("Starting initial sync with client."); self.state .ecs() .write_storage::() @@ -985,7 +984,7 @@ impl Server { server_info: self.server_info.clone(), // world_map: (WORLD_SIZE/*, self.world.sim().get_map()*/), }); - log::info!("Done initial sync with client."); + log::debug!("Done initial sync with client."); frontend_events.push(Event::ClientConnected { entity }); } diff --git a/voxygen/src/logging.rs b/voxygen/src/logging.rs new file mode 100644 index 0000000000..6420df83f5 --- /dev/null +++ b/voxygen/src/logging.rs @@ -0,0 +1,55 @@ +use fern::colors::{Color, ColoredLevelConfig}; + +pub fn init(term_log_level: log::LevelFilter, file_log_level: log::LevelFilter) { + let colors = ColoredLevelConfig::new() + .error(Color::Red) + .warn(Color::Yellow) + .info(Color::Cyan) + .debug(Color::Green) + .trace(Color::BrightBlack); + + let base = fern::Dispatch::new() + .level_for("dot_vox::parser", log::LevelFilter::Warn) + .level_for("gfx_device_gl::factory", log::LevelFilter::Warn) + .level_for("veloren_voxygen::discord", log::LevelFilter::Warn) + .level_for("uvth", log::LevelFilter::Warn) + .level_for("tiny_http", log::LevelFilter::Warn); + + let time = chrono::offset::Utc::now(); + + let file_cfg = fern::Dispatch::new() + .level(file_log_level) + .format(|out, message, record| { + out.finish(format_args!( + "{}[{}:{}][{}] {}", + chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), + record.target(), + record + .line() + .map(|x| x.to_string()) + .unwrap_or("X".to_string()), + record.level(), + message + )) + }) + .chain( + fern::log_file(&format!("voxygen-{}.log", time.format("%Y-%m-%d-%H"))) + .expect("Failed to create log file!"), + ); + + let stdout_cfg = fern::Dispatch::new() + .level(term_log_level) + .format(move |out, message, record| { + out.finish(format_args!( + "[{}] {}", + colors.color(record.level()), + message + )) + }) + .chain(std::io::stdout()); + + base.chain(file_cfg) + .chain(stdout_cfg) + .apply() + .expect("Failed to setup logging!"); +} diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index 2d6ff274e3..d8817b27db 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -19,6 +19,7 @@ pub mod audio; pub mod error; pub mod hud; pub mod key_state; +mod logging; pub mod menu; pub mod mesh; pub mod render; @@ -33,9 +34,7 @@ pub mod window; pub use crate::error::Error; use crate::{audio::AudioFrontend, menu::main::MainMenuState, settings::Settings, window::Window}; -use log::{self, debug, error, info}; - -use fern::colors::{Color, ColoredLevelConfig}; +use log::{self, debug, error}; use std::{mem, panic, str::FromStr}; /// A type used to store state that is shared between all play states. @@ -97,6 +96,16 @@ lazy_static! { } fn main() { + // Initialize logging. + let term_log_level = std::env::var_os("VOXYGEN_LOG") + .and_then(|env| env.to_str().map(|s| s.to_owned())) + .and_then(|s| log::LevelFilter::from_str(&s).ok()) + .unwrap_or(log::LevelFilter::Warn); + + // TODO: Use another environment variable for this? + let file_log_level = log::LevelFilter::Debug; + logging::init(term_log_level, file_log_level); + // Load the settings let settings = Settings::load(); // Save settings to add new fields or create the file if it is not already there @@ -126,63 +135,6 @@ fn main() { let settings = &global_state.settings; - // Initialize logging. - let term_log_level = std::env::var_os("VOXYGEN_LOG") - .and_then(|env| env.to_str().map(|s| s.to_owned())) - .and_then(|s| log::LevelFilter::from_str(&s).ok()) - .unwrap_or(log::LevelFilter::Warn); - - let colors = ColoredLevelConfig::new() - .error(Color::Red) - .warn(Color::Yellow) - .info(Color::Cyan) - .debug(Color::Green) - .trace(Color::BrightBlack); - - let base = fern::Dispatch::new() - .level_for("dot_vox::parser", log::LevelFilter::Warn) - .level_for("gfx_device_gl::factory", log::LevelFilter::Warn) - .level_for("veloren_voxygen::discord", log::LevelFilter::Warn); - // TODO: Filter tracing better such that our own tracing gets seen more easily - - let time = chrono::offset::Utc::now(); - - let file_cfg = fern::Dispatch::new() - .level(log::LevelFilter::Trace) - .format(|out, message, record| { - out.finish(format_args!( - "{}[{}:{}][{}] {}", - chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), - record.target(), - record - .line() - .map(|x| x.to_string()) - .unwrap_or("X".to_string()), - record.level(), - message - )) - }) - .chain( - fern::log_file(&format!("voxygen-{}.log", time.format("%Y-%m-%d-%H"))) - .expect("Failed to create log file!"), - ); - - let stdout_cfg = fern::Dispatch::new() - .level(term_log_level) - .format(move |out, message, record| { - out.finish(format_args!( - "[{}] {}", - colors.color(record.level()), - message - )) - }) - .chain(std::io::stdout()); - - base.chain(file_cfg) - .chain(stdout_cfg) - .apply() - .expect("Failed to setup logging!"); - // Set up panic handler to relay swish panic messages to the user let settings_clone = settings.clone(); let default_hook = panic::take_hook(); @@ -261,7 +213,7 @@ fn main() { let mut states: Vec> = vec![Box::new(MainMenuState::new(&mut global_state))]; states .last() - .map(|current_state| info!("Started game with state '{}'", current_state.name())); + .map(|current_state| debug!("Started game with state '{}'", current_state.name())); // What's going on here? // --------------------- @@ -279,7 +231,7 @@ fn main() { match state_result { PlayStateResult::Shutdown => { direction = Direction::Backwards; - info!("Shutting down all states..."); + debug!("Shutting down all states..."); while states.last().is_some() { states.pop().map(|old_state| { debug!("Popped state '{}'.", old_state.name()); diff --git a/world/src/sim/erosion.rs b/world/src/sim/erosion.rs index 4845033236..b4af42878e 100644 --- a/world/src/sim/erosion.rs +++ b/world/src/sim/erosion.rs @@ -579,22 +579,22 @@ fn erode( uplift: impl Fn(usize) -> f32, is_ocean: impl Fn(usize) -> bool + Sync, ) { - log::info!("Done draining..."); + log::debug!("Done draining..."); let mmaxh = 1.0; let k = erosion_base as f64 + 2.244 / mmaxh as f64 * max_uplift as f64; let ((dh, indirection, newh, area), max_slope) = rayon::join( || { let mut dh = downhill(h, |posi| is_ocean(posi)); - log::info!("Computed downhill..."); + log::debug!("Computed downhill..."); let (boundary_len, indirection, newh) = get_lakes(&h, &mut dh); - log::info!("Got lakes..."); + log::debug!("Got lakes..."); let area = get_drainage(&newh, &dh, boundary_len); - log::info!("Got flux..."); + log::debug!("Got flux..."); (dh, indirection, newh, area) }, || { let max_slope = get_max_slope(h, rock_strength_nz); - log::info!("Got max slopes..."); + log::debug!("Got max slopes..."); max_slope }, ); @@ -669,7 +669,7 @@ fn erode( } maxh = h[posi].max(maxh); } - log::info!( + log::debug!( "Done eroding (max height: {:?}) (avg height: {:?}) (avg slope: {:?})", maxh, if nland == 0 { @@ -841,7 +841,7 @@ pub fn get_lakes(h: &[f32], downhill: &mut [isize]) -> (usize, Box<[i32]>, Box<[ } assert_eq!(newh.len(), downhill.len()); - log::info!("Old lake roots: {:?}", lake_roots.len()); + log::debug!("Old lake roots: {:?}", lake_roots.len()); let newh = newh.into_boxed_slice(); // Now, we know that the sum of all the indirection nodes will be the same as the number of @@ -1067,7 +1067,7 @@ pub fn get_lakes(h: &[f32], downhill: &mut [isize]) -> (usize, Box<[i32]>, Box<[ } // println!("I am a pass: {:?}", (uniform_idx_as_vec2(chunk_idx as usize), uniform_idx_as_vec2(neighbor_idx as usize))); } - log::info!("Total lakes: {:?}", pass_flows_sorted.len()); + log::debug!("Total lakes: {:?}", pass_flows_sorted.len()); // Perform the bfs once again. let mut newh = Vec::with_capacity(downhill.len()); @@ -1130,17 +1130,17 @@ pub fn do_erosion( .cloned() .map(|e| e as f64) .sum::(); - log::info!("Sum uplifts: {:?}", sum_uplift); + log::debug!("Sum uplifts: {:?}", sum_uplift); let max_uplift = uplift .into_par_iter() .cloned() .max_by(|a, b| a.partial_cmp(&b).unwrap()) .unwrap(); - log::info!("Max uplift: {:?}", max_uplift); + log::debug!("Max uplift: {:?}", max_uplift); let mut h = oldh_; for i in 0..n { - log::info!("Erosion iteration #{:?}", i); + log::debug!("Erosion iteration #{:?}", i); erode( &mut h, erosion_base, diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index d18281b334..ce7a484676 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -1083,7 +1083,7 @@ impl SimChunk { ); */ } if river_slope.abs() >= 1.0 && cross_section.x >= 1.0 { - log::info!( + log::debug!( "Big waterfall! Pos area: {:?}, River data: {:?}, slope: {:?}", wposf, river, From 9141cc07d05231f9db3d50670169b19a23c67d86 Mon Sep 17 00:00:00 2001 From: Songtronix Date: Sun, 24 Nov 2019 17:22:15 +0100 Subject: [PATCH 03/51] feat(env): configurable verbosity of log file via VOXYGEN_FILE_LOG environment variable --- voxygen/src/main.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index d8817b27db..da6a80261e 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -102,8 +102,11 @@ fn main() { .and_then(|s| log::LevelFilter::from_str(&s).ok()) .unwrap_or(log::LevelFilter::Warn); - // TODO: Use another environment variable for this? - let file_log_level = log::LevelFilter::Debug; + let file_log_level = std::env::var_os("VOXYGEN_FILE_LOG") + .and_then(|env| env.to_str().map(|s| s.to_owned())) + .and_then(|s| log::LevelFilter::from_str(&s).ok()) + .unwrap_or(log::LevelFilter::Debug); + logging::init(term_log_level, file_log_level); // Load the settings From b03e4ac261a8a1630577fb4b327cbc45c76c7398 Mon Sep 17 00:00:00 2001 From: Songtronix Date: Wed, 18 Dec 2019 20:35:17 +0100 Subject: [PATCH 04/51] feat(log): configurable creation of log file additionally allows to ignore any errors with the log file furthermore prints out full log file path to the user incase of a panic --- voxygen/src/logging.rs | 58 +++++++++++++++++++++++++++-------------- voxygen/src/main.rs | 19 +++++++++----- voxygen/src/settings.rs | 14 +++++++--- 3 files changed, 60 insertions(+), 31 deletions(-) diff --git a/voxygen/src/logging.rs b/voxygen/src/logging.rs index 6420df83f5..78b9587eea 100644 --- a/voxygen/src/logging.rs +++ b/voxygen/src/logging.rs @@ -1,6 +1,12 @@ use fern::colors::{Color, ColoredLevelConfig}; -pub fn init(term_log_level: log::LevelFilter, file_log_level: log::LevelFilter) { +use crate::settings::Settings; + +pub fn init( + settings: &Settings, + term_log_level: log::LevelFilter, + file_log_level: log::LevelFilter, +) { let colors = ColoredLevelConfig::new() .error(Color::Red) .warn(Color::Yellow) @@ -8,7 +14,7 @@ pub fn init(term_log_level: log::LevelFilter, file_log_level: log::LevelFilter) .debug(Color::Green) .trace(Color::BrightBlack); - let base = fern::Dispatch::new() + let mut base = fern::Dispatch::new() .level_for("dot_vox::parser", log::LevelFilter::Warn) .level_for("gfx_device_gl::factory", log::LevelFilter::Warn) .level_for("veloren_voxygen::discord", log::LevelFilter::Warn) @@ -17,25 +23,35 @@ pub fn init(term_log_level: log::LevelFilter, file_log_level: log::LevelFilter) let time = chrono::offset::Utc::now(); - let file_cfg = fern::Dispatch::new() - .level(file_log_level) - .format(|out, message, record| { - out.finish(format_args!( - "{}[{}:{}][{}] {}", - chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), - record.target(), - record - .line() - .map(|x| x.to_string()) - .unwrap_or("X".to_string()), - record.level(), - message - )) - }) - .chain( + let mut file_cfg = + fern::Dispatch::new() + .level(file_log_level) + .format(|out, message, record| { + out.finish(format_args!( + "{}[{}:{}][{}] {}", + chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), + record.target(), + record + .line() + .map(|x| x.to_string()) + .unwrap_or("X".to_string()), + record.level(), + message + )) + }); + + // Based on settings ignore errors incase log file can't be created + if !settings.log.ignore_errors { + file_cfg = file_cfg.chain( fern::log_file(&format!("voxygen-{}.log", time.format("%Y-%m-%d-%H"))) .expect("Failed to create log file!"), ); + } else { + if let Ok(log_file) = fern::log_file(&format!("voxygen-{}.log", time.format("%Y-%m-%d-%H"))) + { + file_cfg = file_cfg.chain(log_file); + } + } let stdout_cfg = fern::Dispatch::new() .level(term_log_level) @@ -48,8 +64,10 @@ pub fn init(term_log_level: log::LevelFilter, file_log_level: log::LevelFilter) }) .chain(std::io::stdout()); - base.chain(file_cfg) - .chain(stdout_cfg) + if settings.log.log_to_file { + base = base.chain(file_cfg); + } + base.chain(stdout_cfg) .apply() .expect("Failed to setup logging!"); } diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index da6a80261e..6ebdfc38a6 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -34,7 +34,7 @@ pub mod window; pub use crate::error::Error; use crate::{audio::AudioFrontend, menu::main::MainMenuState, settings::Settings, window::Window}; -use log::{self, debug, error}; +use log::{debug, error}; use std::{mem, panic, str::FromStr}; /// A type used to store state that is shared between all play states. @@ -107,10 +107,13 @@ fn main() { .and_then(|s| log::LevelFilter::from_str(&s).ok()) .unwrap_or(log::LevelFilter::Debug); - logging::init(term_log_level, file_log_level); - // Load the settings + // Note: This won't log anything due to it being called before ``logging::init``. + // The issue is we need to read a setting to decide whether we create a log file or not. let settings = Settings::load(); + + logging::init(&settings, term_log_level, file_log_level); + // Save settings to add new fields or create the file if it is not already there if let Err(err) = settings.save_to_file() { panic!("Failed to save settings: {:?}", err); @@ -136,10 +139,7 @@ fn main() { info_message: None, }; - let settings = &global_state.settings; - // Set up panic handler to relay swish panic messages to the user - let settings_clone = settings.clone(); let default_hook = panic::take_hook(); panic::set_hook(Box::new(move |panic_info| { let panic_info_payload = panic_info.payload(); @@ -186,7 +186,12 @@ fn main() { \n\ Panic Payload: {:?}\n\ PanicInfo: {}", - settings_clone.log.file, reason, panic_info, + // TODO: Verify that this works + Settings::get_settings_path() + .join("voxygen-.log") + .display(), + reason, + panic_info, ); error!( diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index 85028412ec..24672153dd 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -151,17 +151,23 @@ impl Default for NetworkingSettings { } } -/// `Log` stores the name to the log file. +/// `Log` stores whether we should create a log file #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(default)] pub struct Log { - pub file: PathBuf, + // Whether to create a log file or not. + // Default is to create one. + pub log_to_file: bool, + // Should we ignore errors if we are unable to create the log file + // Default is to panic if log file can't be created. + pub ignore_errors: bool, } impl Default for Log { fn default() -> Self { Self { - file: "voxygen.log".into(), + log_to_file: true, + ignore_errors: false, } } } @@ -290,7 +296,7 @@ impl Settings { Ok(()) } - fn get_settings_path() -> PathBuf { + pub fn get_settings_path() -> PathBuf { if let Some(val) = std::env::var_os("VOXYGEN_CONFIG") { let settings = PathBuf::from(val).join("settings.ron"); if settings.exists() || settings.parent().map(|x| x.exists()).unwrap_or(false) { From f070c139e9aa6e8612879067e5a7899faadf4175 Mon Sep 17 00:00:00 2001 From: Songtronix Date: Fri, 20 Dec 2019 15:59:50 +0100 Subject: [PATCH 05/51] change(log): only print out log file errors, no panic --- voxygen/src/logging.rs | 21 ++++++++++----------- voxygen/src/settings.rs | 8 +------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/voxygen/src/logging.rs b/voxygen/src/logging.rs index 78b9587eea..48fb256e95 100644 --- a/voxygen/src/logging.rs +++ b/voxygen/src/logging.rs @@ -40,17 +40,12 @@ pub fn init( )) }); - // Based on settings ignore errors incase log file can't be created - if !settings.log.ignore_errors { - file_cfg = file_cfg.chain( - fern::log_file(&format!("voxygen-{}.log", time.format("%Y-%m-%d-%H"))) - .expect("Failed to create log file!"), - ); - } else { - if let Ok(log_file) = fern::log_file(&format!("voxygen-{}.log", time.format("%Y-%m-%d-%H"))) - { - file_cfg = file_cfg.chain(log_file); - } + // Try to create the log file. + // Incase of it failing we simply print it out to the console. + let mut log_file_created = Ok(()); + match fern::log_file(&format!("voxygen-{}.log", time.format("%Y-%m-%d-%H"))) { + Ok(log_file) => file_cfg = file_cfg.chain(log_file), + Err(e) => log_file_created = Err(e), } let stdout_cfg = fern::Dispatch::new() @@ -70,4 +65,8 @@ pub fn init( base.chain(stdout_cfg) .apply() .expect("Failed to setup logging!"); + + if let Err(e) = log_file_created { + log::error!("Failed to create log file! {}", e); + } } diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index 24672153dd..e2a567f174 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -158,17 +158,11 @@ pub struct Log { // Whether to create a log file or not. // Default is to create one. pub log_to_file: bool, - // Should we ignore errors if we are unable to create the log file - // Default is to panic if log file can't be created. - pub ignore_errors: bool, } impl Default for Log { fn default() -> Self { - Self { - log_to_file: true, - ignore_errors: false, - } + Self { log_to_file: true } } } From 609e0f23bfc8a5328b329f95741550059749f98d Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 3 Nov 2019 19:57:36 -0500 Subject: [PATCH 06/51] Stop global syncing of entity creation --- Cargo.lock | 244 ++++++++++++++------------ client/src/lib.rs | 13 +- common/Cargo.toml | 3 +- common/src/comp/projectile.rs | 1 + common/src/lib.rs | 3 + common/src/msg/ecs_packet.rs | 82 ++++++++- common/src/msg/server.rs | 4 +- common/src/state.rs | 122 ++++--------- common/src/sys/mod.rs | 11 +- common/src/sys/mount.rs | 76 ++++++++ common/src/sys/stats.rs | 1 + server/Cargo.toml | 2 + server/src/cmd.rs | 3 +- server/src/lib.rs | 39 +++-- server/src/sys/entity_sync.rs | 99 +++++++---- server/src/sys/mod.rs | 10 +- server/src/sys/sentinel.rs | 309 +++++++++++++++++++++++++++++++++ server/src/sys/subscription.rs | 11 +- 18 files changed, 771 insertions(+), 262 deletions(-) create mode 100644 common/src/sys/mount.rs create mode 100644 server/src/sys/sentinel.rs diff --git a/Cargo.lock b/Cargo.lock index 0cfd0c3b4f..040d359b08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,7 +79,7 @@ name = "approx" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -169,7 +169,7 @@ version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -217,7 +217,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", "cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "clang-sys 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -237,7 +237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -368,8 +368,11 @@ dependencies = [ [[package]] name = "cast" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "cc" @@ -394,7 +397,7 @@ dependencies = [ [[package]] name = "cfg-if" -version = "0.1.10" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -417,12 +420,11 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -600,7 +602,7 @@ dependencies = [ "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smithay-clipboard 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smithay-clipboard 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "wayland-client 0.23.6 (registry+https://github.com/rust-lang/crates.io-index)", "x11-clipboard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -658,7 +660,7 @@ dependencies = [ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -668,7 +670,7 @@ name = "crc32fast" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -677,20 +679,20 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -700,8 +702,8 @@ name = "criterion-plot" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -720,7 +722,7 @@ name = "crossbeam" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -772,7 +774,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -785,7 +787,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -798,7 +800,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -811,7 +813,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -826,6 +828,14 @@ dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-queue" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-utils" version = "0.5.0" @@ -836,7 +846,7 @@ name = "crossbeam-utils" version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -846,7 +856,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -903,7 +913,7 @@ name = "directories" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -922,7 +932,7 @@ name = "dirs-sys" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1009,7 +1019,7 @@ name = "euc" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "vek 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", + "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1018,7 +1028,7 @@ version = "0.19.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1056,7 +1066,7 @@ name = "fern" version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1066,7 +1076,7 @@ name = "filetime" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1215,7 +1225,7 @@ name = "getrandom" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1532,7 +1542,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atom 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1560,7 +1570,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1573,8 +1583,8 @@ dependencies = [ "jpeg-decoder 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "png 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "png 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tiff 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1628,7 +1638,7 @@ dependencies = [ [[package]] name = "itertools" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1645,7 +1655,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1716,7 +1726,7 @@ name = "line_drawing" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1754,7 +1764,7 @@ name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1859,7 +1869,7 @@ name = "minifb" version = "0.13.0" source = "git+https://github.com/emoon/rust_minifb.git#bac71b297920c1f7ab5d6e384673d3ae5cc7d46d" dependencies = [ - "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", "orbclient 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1886,9 +1896,10 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.19" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1908,7 +1919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.20 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1961,7 +1972,7 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1973,7 +1984,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2028,7 +2039,7 @@ dependencies = [ "inotify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.20 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2041,7 +2052,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2054,7 +2065,7 @@ dependencies = [ "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2064,7 +2075,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2073,7 +2084,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2092,7 +2103,7 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2102,7 +2113,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2113,7 +2124,7 @@ dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2121,12 +2132,12 @@ name = "num-traits" version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2189,7 +2200,7 @@ name = "ordered-float" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2297,7 +2308,7 @@ name = "parking_lot_core" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2395,7 +2406,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "png" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2422,7 +2433,7 @@ name = "pretty_env_logger" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2466,7 +2477,7 @@ name = "prometheus" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2723,22 +2734,22 @@ dependencies = [ [[package]] name = "rayon" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon-core" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2854,7 +2865,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "deflate 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "multipart 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2862,7 +2873,7 @@ dependencies = [ "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2912,23 +2923,23 @@ name = "rusttype" version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rusttype 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rusttype 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rusttype" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "stb_truetype 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stb_truetype 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2990,7 +3001,7 @@ name = "sdl2-sys" version = "0.32.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3027,7 +3038,7 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.41" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3062,7 +3073,7 @@ dependencies = [ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3109,6 +3120,11 @@ dependencies = [ "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "smallvec" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "smithay-client-toolkit" version = "0.4.6" @@ -3142,7 +3158,7 @@ dependencies = [ [[package]] name = "smithay-clipboard" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3161,7 +3177,7 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "nonzero_signed 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "shred 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "shred-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3181,7 +3197,6 @@ dependencies = [ [[package]] name = "sphynx" version = "0.1.0" -source = "git+https://gitlab.com/veloren/sphynx.git?rev=ac4adf54d181339a789907acd27f61fe81daa455#ac4adf54d181339a789907acd27f61fe81daa455" dependencies = [ "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3206,7 +3221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "stb_truetype" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3383,7 +3398,7 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3402,7 +3417,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3414,7 +3429,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3461,10 +3476,10 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3519,7 +3534,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "vek" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3551,7 +3566,7 @@ dependencies = [ "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", "uvth 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "vek 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", + "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "veloren-common 0.4.0", ] @@ -3571,27 +3586,27 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-compress 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.20 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "notify 5.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", "specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git)", - "sphynx 0.1.0 (git+https://gitlab.com/veloren/sphynx.git?rev=ac4adf54d181339a789907acd27f61fe81daa455)", - "vek 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", + "sphynx 0.1.0", + "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "veloren-server" version = "0.4.0" dependencies = [ - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3606,10 +3621,12 @@ dependencies = [ "scan_fmt 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "shred 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "shred-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", "specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git)", "uvth 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "vek 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", + "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "veloren-common 0.4.0", "veloren-world 0.4.0", ] @@ -3629,7 +3646,7 @@ name = "veloren-voxygen" version = "0.4.0" dependencies = [ "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "conrod_core 0.63.0 (git+https://gitlab.com/veloren/conrod.git)", "conrod_winit 0.63.0 (git+https://gitlab.com/veloren/conrod.git)", "cpal 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3660,7 +3677,7 @@ dependencies = [ "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", - "vek 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", + "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "veloren-client 0.4.0", "veloren-common 0.4.0", "veloren-server 0.4.0", @@ -3683,11 +3700,11 @@ dependencies = [ "ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "roots 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "vek 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", + "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "veloren-common 0.4.0", ] @@ -3995,14 +4012,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum c_vec 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f8a318911dce53b5f1ca6539c44f5342c632269f0fa7ea3e35f32458c27a7c30" "checksum cairo-rs 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a110f269c2fd382df5fe8bd46dfa5f1b83608aa717fecb6e7a28c08c202f0e13" "checksum cairo-sys-rs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0395175ecba60accac076a02c31d143b9dcd9d5eb5316d7163a3273803b765c7" -"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" +"checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" "checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8" "checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c" "checksum cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d" -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "55e7ec0b74fe5897894cbc207092c577e87c52f8a59e8ca8d97ef37551f60a49" "checksum chashmap 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff41a3c2c1e39921b9003de14bf0439c7b63a9039637c291e1a64925d8ddfa45" -"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" +"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" "checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" "checksum clang-sys 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "611ec2e3a7623afd8a8c0d027887b6b55759d894abbf5fe11b9dc11b50d5b49a" "checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853" @@ -4042,6 +4059,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" "checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700" "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" @@ -4127,7 +4145,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" "checksum instant 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c346c299e3fe8ef94dc10c2c0253d858a69aac1245157a3bf4125915d528caf" "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -"checksum itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "87fa75c9dea7b07be3138c49abbb83fd4bea199b5cdc76f9804458edc5da0d6e" +"checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jpeg-decoder 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "c1aae18ffeeae409c6622c3b6a7ee49792a7e5a062eea1b135fbb74e301792ba" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" @@ -4161,7 +4179,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum minifb 0.13.0 (git+https://github.com/emoon/rust_minifb.git)" = "" "checksum minimp3 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "542e9bed56860c5070a09939eee0e2df6f8f73f60304ddf56d620947e7017239" "checksum minimp3-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c109ae05c00ad6e3a53fab101e2f234545bdd010f0fffd399355efaf70817817" -"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" +"checksum mio 0.6.20 (registry+https://github.com/rust-lang/crates.io-index)" = "72f4261ee7ab03cd36dc99eea4db8be6e83e4164da470e0c84f6726d6c605855" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a785740271256c230f57462d3b83e52f998433a7062fc18f96d5999474a9f915" @@ -4184,7 +4202,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" "checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -"checksum num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "443c53b3c3531dfcbfa499d8893944db78474ad7a1d87fa2d94d1a2231693ac6" +"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" "checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" "checksum objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" "checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" @@ -4215,7 +4233,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum piston-viewport 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d96dd995f7dabe6d57cda668ec0fda39d6fe6e1e0b23f772582f383f2013611" "checksum pistoncore-input 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c612ce242c7bac8e96426a0ca34275fd980af440f0cca7c6c0e840ef8a4052f" "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" -"checksum png 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8422b27bb2c013dd97b9aef69e161ce262236f49aaf46a0489011c8ff0264602" +"checksum png 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f00ec9242f8e01119e83117dbadf34c5228ac2f1c4ddcd92bffa340d52291de" "checksum portpicker 0.1.0 (git+https://github.com/wusyong/portpicker-rs?branch=fix_ipv6)" = "" "checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" "checksum pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "717ee476b1690853d222af4634056d830b5197ffd747726a9a1eee6da9f49074" @@ -4251,8 +4269,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e18c91676f670f6f0312764c759405f13afb98d5d73819840cf72a518487bff" "checksum raw-window-handle 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9db80d08d3ed847ce4fb3def46de0af4bfb6155bd09bd6eaf28b5ac72541c1f1" -"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" -"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" +"checksum rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43739f8831493b276363637423d3622d4bd6394ab6f0a9c4a552e208aeb7fddd" +"checksum rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8bf17de6f23b05473c437eb958b9c850bfc8af0961fe17b4cc92d5a627b4791" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" @@ -4272,7 +4290,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum rusttype 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "310942406a39981bed7e12b09182a221a29e0990f3e7e0c971f131922ed135d5" -"checksum rusttype 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6fa38506b5cbf2fb67f915e2725cb5012f1b9a785b0ab55c4733acda5f6554ef" +"checksum rusttype 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "14a911032fb5791ccbeec9f28fdcb9bf0983b81f227bafdfd227c658d0731c8a" "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" "checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" @@ -4286,7 +4304,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4b39bd9b0b087684013a792c59e3e07a46a01d2322518d8a1104641a0b1be0" "checksum serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "ca13fc1a832f793322228923fbb3aba9f3f44444898f835d31ad1b74fa0a2bf8" -"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" +"checksum serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "1a3351dcbc1f067e2c92ab7c3c1f288ad1a4cffc470b5aaddb4c2e0a3ae80043" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum shared_library 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" @@ -4297,16 +4315,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum slice-deque 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffddf594f5f597f63533d897427a570dbaa9feabaaa06595b74b71b7014507d7" "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" +"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" "checksum smithay-client-toolkit 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2ccb8c57049b2a34d2cc2b203fa785020ba0129d31920ef0d317430adaf748fa" "checksum smithay-client-toolkit 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "93960e8975909fcb14cc755de93af2149d8b8f4eb368315537d40cfd0f324054" -"checksum smithay-clipboard 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "315c3f4417d365483dcbaed9ba6488d9f176e43d83f3e1d581050f1c93869e3d" +"checksum smithay-clipboard 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9667a262ef7a9ff1c55a7e665cd3d36f9bc2809f94167b1fb3fc31423a83f8c0" "checksum specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "de65613ada4338aa7ba71eca60eca24c60483433eec0077bc4f33cfc31f4bdf0" "checksum specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git)" = "" -"checksum sphynx 0.1.0 (git+https://gitlab.com/veloren/sphynx.git?rev=ac4adf54d181339a789907acd27f61fe81daa455)" = "" "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" -"checksum stb_truetype 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "824210d6fb52cbc3ad2545270ead6860c7311aa5450642b078da4515937b6f7a" +"checksum stb_truetype 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f77b6b07e862c66a9f3e62a07588fee67cd90a9135a2b942409f195507b4fb51" "checksum stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum sum_type 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da5b4a0c9f3c7c8e891e445a7c776627e208e8bba23ab680798066dd283e6a15" @@ -4336,7 +4354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "09c8070a9942f5e7cfccd93f490fdebd230ee3c3c9f107cb25bad5351ef671cf" +"checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf" "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" @@ -4345,7 +4363,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" "checksum uvth 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e59a167890d173eb0fcd7a1b99b84dc05c521ae8d76599130b8e19bef287abbf" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum vek 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2bb887880c4eb92359ae9abea055ddf60bfade4603bf9534f3c62c2707cb306b" +"checksum vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "1eb3ca8ea588deba055424cc1a79a830428b2f6c270b8d8f91946f660fa4d8ee" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" diff --git a/client/src/lib.rs b/client/src/lib.rs index ce8fb7182d..b97f7f31a8 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -14,6 +14,7 @@ use common::{ ServerError, ServerInfo, ServerMsg, MAX_BYTES_CHAT_MSG, }, net::PostBox, + sphynx::WorldSyncExt, state::{State, Uid}, terrain::{block::Block, TerrainChunk, TerrainChunkSize}, vol::RectVolSize, @@ -94,7 +95,8 @@ impl Client { ); } - let state = State::from_state_package(ecs_state); + let mut state = State::default(); + state.ecs_mut().apply_state_package(ecs_state); let entity = state .ecs() .entity_from_uid(entity_uid) @@ -550,7 +552,14 @@ impl Client { } } ServerMsg::EcsSync(sync_package) => { - self.state.ecs_mut().sync_with_package(sync_package) + self.state.ecs_mut().apply_sync_package(sync_package) + } + ServerMsg::EcsResSync(res_sync_package) => self + .state + .ecs_mut() + .apply_res_sync_package(res_sync_package), + ServerMsg::CreateEntity(entity_package) => { + self.state.ecs_mut().apply_entity_package(entity_package) } ServerMsg::DeleteEntity(entity) => { if let Some(entity) = self.state.ecs().entity_from_uid(entity) { diff --git a/common/Cargo.toml b/common/Cargo.toml index 5e4dcbc571..e8a7c0ed41 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -5,7 +5,8 @@ authors = ["Joshua Barretto ", "Maciej Ćwięka , pub hit_wall: Vec, pub hit_entity: Vec, diff --git a/common/src/lib.rs b/common/src/lib.rs index eab693848d..0fbe6c554d 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -7,6 +7,9 @@ extern crate serde_derive; #[macro_use] extern crate log; +// Re-export sphynx +pub use sphynx; + pub mod assets; pub mod astar; pub mod clock; diff --git a/common/src/msg/ecs_packet.rs b/common/src/msg/ecs_packet.rs index 70f24e228c..e6ad0b6149 100644 --- a/common/src/msg/ecs_packet.rs +++ b/common/src/msg/ecs_packet.rs @@ -1,20 +1,28 @@ use crate::{comp, state}; use serde_derive::{Deserialize, Serialize}; +use sphynx::sum_type; use std::marker::PhantomData; // Automatically derive From for EcsResPacket // for each variant EcsResPacket::T(T). -sphynx::sum_type! { +sum_type! { #[derive(Clone, Debug, Serialize, Deserialize)] pub enum EcsResPacket { Time(state::Time), TimeOfDay(state::TimeOfDay), } } -impl sphynx::ResPacket for EcsResPacket {} +impl sphynx::ResPacket for EcsResPacket { + fn apply(self, world: &specs::World) { + match self { + EcsResPacket::Time(time) => sphynx::handle_res_update(time, world), + EcsResPacket::TimeOfDay(time_of_day) => sphynx::handle_res_update(time_of_day, world), + } + } +} // Automatically derive From for EcsCompPacket // for each variant EcsCompPacket::T(T.) -sphynx::sum_type! { +sum_type! { #[derive(Clone, Debug, Serialize, Deserialize)] pub enum EcsCompPacket { Pos(comp::Pos), @@ -37,7 +45,7 @@ sphynx::sum_type! { } // Automatically derive From for EcsCompPhantom // for each variant EcsCompPhantom::T(PhantomData). -sphynx::sum_type! { +sum_type! { #[derive(Clone, Debug, Serialize, Deserialize)] pub enum EcsCompPhantom { Pos(PhantomData), @@ -60,4 +68,70 @@ sphynx::sum_type! { } impl sphynx::CompPacket for EcsCompPacket { type Phantom = EcsCompPhantom; + fn apply_insert(self, entity: specs::Entity, world: &specs::World) { + match self { + EcsCompPacket::Pos(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::Vel(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::Ori(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::Body(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::Player(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::CanBuild(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::Stats(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::LightEmitter(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::Item(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::Scale(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::MountState(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::Mounting(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::Mass(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::Projectile(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::Gravity(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::Sticky(comp) => sphynx::handle_insert(comp, entity, world), + } + } + fn apply_modify(self, entity: specs::Entity, world: &specs::World) { + match self { + EcsCompPacket::Pos(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::Vel(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::Ori(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::Body(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::Player(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::CanBuild(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::Stats(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::LightEmitter(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::Item(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::Scale(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::MountState(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::Mounting(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::Mass(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::Projectile(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::Gravity(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::Sticky(comp) => sphynx::handle_modify(comp, entity, world), + } + } + fn apply_remove(phantom: Self::Phantom, entity: specs::Entity, world: &specs::World) { + match phantom { + EcsCompPhantom::Pos(_) => sphynx::handle_remove::(entity, world), + EcsCompPhantom::Vel(_) => sphynx::handle_remove::(entity, world), + EcsCompPhantom::Ori(_) => sphynx::handle_remove::(entity, world), + EcsCompPhantom::Body(_) => sphynx::handle_remove::(entity, world), + EcsCompPhantom::Player(_) => sphynx::handle_remove::(entity, world), + EcsCompPhantom::CanBuild(_) => sphynx::handle_remove::(entity, world), + EcsCompPhantom::Stats(_) => sphynx::handle_remove::(entity, world), + EcsCompPhantom::LightEmitter(_) => { + sphynx::handle_remove::(entity, world) + } + EcsCompPhantom::Item(_) => sphynx::handle_remove::(entity, world), + EcsCompPhantom::Scale(_) => sphynx::handle_remove::(entity, world), + EcsCompPhantom::MountState(_) => { + sphynx::handle_remove::(entity, world) + } + EcsCompPhantom::Mounting(_) => sphynx::handle_remove::(entity, world), + EcsCompPhantom::Mass(_) => sphynx::handle_remove::(entity, world), + EcsCompPhantom::Projectile(_) => { + sphynx::handle_remove::(entity, world) + } + EcsCompPhantom::Gravity(_) => sphynx::handle_remove::(entity, world), + EcsCompPhantom::Sticky(_) => sphynx::handle_remove::(entity, world), + } + } } diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index cbf1d9ac8a..dc8ccd8c1c 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -40,7 +40,9 @@ pub enum ServerMsg { message: String, }, SetPlayerEntity(u64), - EcsSync(sphynx::SyncPackage), + EcsSync(sphynx::SyncPackage), + EcsResSync(sphynx::ResSyncPackage), + CreateEntity(sphynx::EntityPackage), DeleteEntity(u64), EntityPos { entity: u64, diff --git a/common/src/state.rs b/common/src/state.rs index 9a3b5cd9ee..1d62d3419b 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -4,7 +4,6 @@ pub use sphynx::Uid; use crate::{ comp, event::{EventBus, LocalEvent, ServerEvent, SfxEventItem}, - msg::{EcsCompPacket, EcsResPacket}, region::RegionMap, sys, terrain::{Block, TerrainChunk, TerrainGrid}, @@ -14,12 +13,11 @@ use hashbrown::{HashMap, HashSet}; use rayon::{ThreadPool, ThreadPoolBuilder}; use serde_derive::{Deserialize, Serialize}; use specs::{ - saveload::Marker, shred::{Fetch, FetchMut}, storage::{MaskedStorage as EcsMaskedStorage, Storage as EcsStorage}, - Component, DispatcherBuilder, Entity as EcsEntity, Join, + Component, DispatcherBuilder, Entity as EcsEntity, }; -use sphynx; +use sphynx::WorldSyncExt; use std::{sync::Arc, time::Duration}; use vek::*; @@ -89,7 +87,7 @@ impl TerrainChanges { /// A type used to represent game state stored on both the client and the server. This includes /// things like entity components, terrain data, and global states like weather, time of day, etc. pub struct State { - ecs: sphynx::World, + ecs: specs::World, // Avoid lifetime annotation by storing a thread pool instead of the whole dispatcher thread_pool: Arc, } @@ -98,15 +96,15 @@ impl Default for State { /// Create a new `State`. fn default() -> Self { Self { - ecs: sphynx::World::new(specs::World::new(), Self::setup_sphynx_world), + ecs: Self::setup_ecs_world(), thread_pool: Arc::new(ThreadPoolBuilder::new().build().unwrap()), } } } impl State { - /// Create a new `State` from an ECS state package. - pub fn from_state_package( + // Create a new `State` from an ECS state package. + /*pub fn from_state_package( state_package: sphynx::StatePackage, ) -> Self { Self { @@ -117,25 +115,28 @@ impl State { ), thread_pool: Arc::new(ThreadPoolBuilder::new().build().unwrap()), } - } + }*/ - // Create a new Sphynx ECS world. + /// Creates ecs world and registers all the common components and resources // TODO: Split up registering into server and client (e.g. move EventBus to the server) - fn setup_sphynx_world(ecs: &mut sphynx::World) { + fn setup_ecs_world() -> specs::World { + let mut ecs = specs::World::new(); + // Uids for sync + ecs.register_sync_marker(); // Register server -> all clients synced components. - ecs.register_synced::(); - ecs.register_synced::(); - ecs.register_synced::(); - ecs.register_synced::(); - ecs.register_synced::(); - ecs.register_synced::(); - ecs.register_synced::(); - ecs.register_synced::(); - ecs.register_synced::(); - ecs.register_synced::(); - ecs.register_synced::(); - ecs.register_synced::(); - ecs.register_synced::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); // Register components send from clients -> server ecs.register::(); @@ -151,6 +152,7 @@ impl State { ecs.register::(); // Register server-local components + // TODO: only register on the server ecs.register::>(); ecs.register::>(); ecs.register::>(); @@ -163,10 +165,10 @@ impl State { ecs.register::(); // Register synced resources used by the ECS. - ecs.insert_synced(TimeOfDay(0.0)); + ecs.add_resource(Time(0.0)); + ecs.add_resource(TimeOfDay(0.0)); // Register unsynced resources used by the ECS. - ecs.add_resource(Time(0.0)); ecs.add_resource(DeltaTime(0.0)); ecs.add_resource(TerrainGrid::new().unwrap()); ecs.add_resource(BlockChange::default()); @@ -175,6 +177,8 @@ impl State { ecs.add_resource(EventBus::::default()); ecs.add_resource(EventBus::::default()); ecs.add_resource(RegionMap::new()); + + ecs } /// Register a component with the state's ECS. @@ -207,12 +211,12 @@ impl State { } /// Get a reference to the internal ECS world. - pub fn ecs(&self) -> &sphynx::World { + pub fn ecs(&self) -> &specs::World { &self.ecs } /// Get a mutable reference to the internal ECS world. - pub fn ecs_mut(&mut self) -> &mut sphynx::World { + pub fn ecs_mut(&mut self) -> &mut specs::World { &mut self.ecs } @@ -319,68 +323,6 @@ impl State { // Beyond a delta time of MAX_DELTA_TIME, start lagging to avoid skipping important physics events. self.ecs.write_resource::().0 = dt.as_secs_f32().min(MAX_DELTA_TIME); - // Mounted entities. We handle this here because we need access to the Uid registry and I - // forgot how to access that within a system. Anyhow, here goes. - for (entity, mount_state) in ( - &self.ecs.entities(), - &mut self.ecs.write_storage::(), - ) - .join() - { - match mount_state { - comp::MountState::Unmounted => {} - comp::MountState::MountedBy(mounter) => { - if let Some((controller, mounter)) = - self.ecs.entity_from_uid(mounter.id()).and_then(|mounter| { - self.ecs - .read_storage::() - .get(mounter) - .cloned() - .map(|x| (x, mounter)) - }) - { - let pos = self.ecs.read_storage::().get(entity).copied(); - let ori = self.ecs.read_storage::().get(entity).copied(); - let vel = self.ecs.read_storage::().get(entity).copied(); - if let (Some(pos), Some(ori), Some(vel)) = (pos, ori, vel) { - let _ = self - .ecs - .write_storage() - .insert(mounter, comp::Pos(pos.0 + Vec3::unit_z() * 1.0)); - let _ = self.ecs.write_storage().insert(mounter, ori); - let _ = self.ecs.write_storage().insert(mounter, vel); - } - let _ = self - .ecs - .write_storage::() - .insert(entity, controller); - } else { - *mount_state = comp::MountState::Unmounted; - } - } - } - } - - let mut to_unmount = Vec::new(); - for (entity, comp::Mounting(mountee)) in ( - &self.ecs.entities(), - &self.ecs.read_storage::(), - ) - .join() - { - if self - .ecs - .entity_from_uid(mountee.id()) - .filter(|mountee| self.ecs.is_alive(*mountee)) - .is_none() - { - to_unmount.push(entity); - } - } - for entity in to_unmount { - self.ecs.write_storage::().remove(entity); - } - // Run RegionMap tick to update entity region occupancy self.ecs.write_resource::().tick( self.ecs.read_storage::(), diff --git a/common/src/sys/mod.rs b/common/src/sys/mod.rs index f9f154c82d..8006c20abc 100644 --- a/common/src/sys/mod.rs +++ b/common/src/sys/mod.rs @@ -2,6 +2,7 @@ pub mod agent; mod cleanup; pub mod combat; pub mod controller; +mod mount; pub mod movement; pub mod phys; mod projectile; @@ -13,6 +14,7 @@ use specs::DispatcherBuilder; // System names const AGENT_SYS: &str = "agent_sys"; const CONTROLLER_SYS: &str = "controller_sys"; +const MOUNT_SYS: &str = "mount_sys"; const PHYS_SYS: &str = "phys_sys"; const MOVEMENT_SYS: &str = "movement_sys"; const PROJECTILE_SYS: &str = "projectile_sys"; @@ -23,13 +25,20 @@ const CLEANUP_SYS: &str = "cleanup_sys"; pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) { dispatch_builder.add(agent::Sys, AGENT_SYS, &[]); dispatch_builder.add(controller::Sys, CONTROLLER_SYS, &[AGENT_SYS]); + dispatch_builder.add(mount::Sys, MOUNT_SYS, &[CONTROLLER_SYS]); dispatch_builder.add(movement::Sys, MOVEMENT_SYS, &[]); dispatch_builder.add(combat::Sys, COMBAT_SYS, &[CONTROLLER_SYS]); dispatch_builder.add(stats::Sys, STATS_SYS, &[COMBAT_SYS]); dispatch_builder.add( phys::Sys, PHYS_SYS, - &[CONTROLLER_SYS, MOVEMENT_SYS, COMBAT_SYS, STATS_SYS], + &[ + CONTROLLER_SYS, + MOUNT_SYS, + MOVEMENT_SYS, + COMBAT_SYS, + STATS_SYS, + ], ); dispatch_builder.add(projectile::Sys, PROJECTILE_SYS, &[PHYS_SYS]); dispatch_builder.add(cleanup::Sys, CLEANUP_SYS, &[PHYS_SYS]); diff --git a/common/src/sys/mount.rs b/common/src/sys/mount.rs new file mode 100644 index 0000000000..0d992f57b4 --- /dev/null +++ b/common/src/sys/mount.rs @@ -0,0 +1,76 @@ +use crate::comp::{Controller, MountState, Mounting, Ori, Pos, Vel}; +use specs::{ + saveload::{Marker, MarkerAllocator}, + Entities, Join, Read, System, WriteStorage, +}; +use sphynx::UidAllocator; +use vek::*; + +/// This system is responsible for controlling mounts +pub struct Sys; +impl<'a> System<'a> for Sys { + type SystemData = ( + Read<'a, UidAllocator>, + Entities<'a>, + WriteStorage<'a, Controller>, + WriteStorage<'a, MountState>, + WriteStorage<'a, Mounting>, + WriteStorage<'a, Pos>, + WriteStorage<'a, Vel>, + WriteStorage<'a, Ori>, + ); + + fn run( + &mut self, + ( + uid_allocator, + entities, + mut controllers, + mut mount_state, + mut mountings, + mut positions, + mut velocities, + mut orientations, + ): Self::SystemData, + ) { + // Mounted entities. + for (entity, mut mount_states) in (&entities, &mut mount_state.restrict_mut()).join() { + match mount_states.get_unchecked() { + MountState::Unmounted => {} + MountState::MountedBy(mounter_uid) => { + if let Some((controller, mounter)) = uid_allocator + .retrieve_entity_internal(mounter_uid.id()) + .and_then(|mounter| controllers.get(mounter).cloned().map(|x| (x, mounter))) + { + // TODO: consider joining on these? (remember we can use .maybe()) + let pos = positions.get(entity).copied(); + let ori = orientations.get(entity).copied(); + let vel = velocities.get(entity).copied(); + if let (Some(pos), Some(ori), Some(vel)) = (pos, ori, vel) { + let _ = positions.insert(mounter, Pos(pos.0 + Vec3::unit_z() * 1.0)); + let _ = orientations.insert(mounter, ori); + let _ = velocities.insert(mounter, vel); + } + let _ = controllers.insert(entity, controller); + } else { + *(mount_states.get_mut_unchecked()) = MountState::Unmounted; + } + } + } + } + + let mut to_unmount = Vec::new(); + for (entity, Mounting(mountee_uid)) in (&entities, &mountings).join() { + if uid_allocator + .retrieve_entity_internal(mountee_uid.id()) + .filter(|mountee| entities.is_alive(*mountee)) + .is_none() + { + to_unmount.push(entity); + } + } + for entity in to_unmount { + mountings.remove(entity); + } + } +} diff --git a/common/src/sys/stats.rs b/common/src/sys/stats.rs index 448bb375a0..5de672a84b 100644 --- a/common/src/sys/stats.rs +++ b/common/src/sys/stats.rs @@ -23,6 +23,7 @@ impl<'a> System<'a> for Sys { ) { let mut server_event_emitter = server_event_bus.emitter(); + // Mutates all stats every tick causing the server to resend this component for every entity every tick for (entity, mut stat) in (&entities, &mut stats).join() { if stat.should_die() && !stat.is_dead { server_event_emitter.emit(ServerEvent::Destroy { diff --git a/server/Cargo.toml b/server/Cargo.toml index c379db4c90..3bb82317f0 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -12,6 +12,8 @@ specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git" } log = "0.4.8" specs = "0.14.2" +shred-derive = "0.5.0" +shred = "0.7.0" vek = "0.9.9" uvth = "3.1.1" lazy_static = "1.4.0" diff --git a/server/src/cmd.rs b/server/src/cmd.rs index a38a1126fe..df4b46882e 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -10,6 +10,7 @@ use common::{ msg::ServerMsg, npc::{get_npc_name, NpcKind}, pathfinding::WorldPath, + sphynx::WorldSyncExt, state::TimeOfDay, terrain::{Block, BlockKind, TerrainChunkSize}, vol::RectVolSize, @@ -1117,7 +1118,7 @@ fn handle_remove_lights( let size = to_delete.len(); for entity in to_delete { - let _ = server.state.ecs_mut().delete_entity_synced(entity); + let _ = server.state.ecs_mut().delete_entity(entity); } server.notify_client( diff --git a/server/src/lib.rs b/server/src/lib.rs index 41eaeb78d6..1e0034b621 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -19,6 +19,7 @@ use crate::{ chunk_generator::ChunkGenerator, client::{Client, RegionSubscription}, cmd::CHAT_COMMANDS, + sys::sentinel::{TrackedComps, TrackedResources}, }; use common::{ assets, comp, @@ -26,6 +27,7 @@ use common::{ event::{EventBus, ServerEvent}, msg::{ClientMsg, ClientState, ServerError, ServerInfo, ServerMsg}, net::PostOffice, + sphynx::WorldSyncExt, state::{BlockChange, State, TimeOfDay, Uid}, terrain::{block::Block, TerrainChunkSize, TerrainGrid}, vol::{ReadVol, RectVolSize, Vox}, @@ -33,7 +35,9 @@ use common::{ use log::debug; use metrics::ServerMetrics; use rand::Rng; -use specs::{join::Join, world::EntityBuilder as EcsEntityBuilder, Builder, Entity as EcsEntity}; +use specs::{ + join::Join, world::EntityBuilder as EcsEntityBuilder, Builder, Entity as EcsEntity, SystemData, +}; use std::{ i32, sync::Arc, @@ -90,11 +94,12 @@ impl Server { state.ecs_mut().add_resource(AuthProvider::new()); state.ecs_mut().add_resource(Tick(0)); state.ecs_mut().add_resource(ChunkGenerator::new()); - // System timers + // System timers for performance monitoring state .ecs_mut() .add_resource(sys::EntitySyncTimer::default()); state.ecs_mut().add_resource(sys::MessageTimer::default()); + state.ecs_mut().add_resource(sys::SentinelTimer::default()); state .ecs_mut() .add_resource(sys::SubscriptionTimer::default()); @@ -158,6 +163,9 @@ impl Server { // Set starting time for the server. state.ecs_mut().write_resource::().0 = settings.start_time; + // Register trackers + sys::sentinel::register_trackers(&mut state.ecs_mut()); + let this = Self { state, world: Arc::new(world), @@ -449,7 +457,7 @@ impl Server { }; if let Some(item_entity) = item_entity { - let _ = state.ecs_mut().delete_entity_synced(item_entity); + let _ = state.ecs_mut().delete_entity(item_entity); } state.write_component(entity, comp::InventoryUpdate); @@ -605,8 +613,8 @@ impl Server { { let not_mounting_yet = if let Some(comp::MountState::Unmounted) = state .ecs() - .write_storage::() - .get_mut(mountee) + .read_storage::() + .get(mountee) .cloned() { true @@ -738,7 +746,7 @@ impl Server { } ServerEvent::ClientDisconnect(entity) => { - if let Err(err) = state.ecs_mut().delete_entity_synced(entity) { + if let Err(err) = state.ecs_mut().delete_entity(entity) { debug!("Failed to delete disconnected client: {:?}", err); } @@ -756,7 +764,7 @@ impl Server { // TODO: is this needed? if let Some(entity) = todo_remove { - let _ = state.ecs_mut().delete_entity_synced(entity); + let _ = state.ecs_mut().delete_entity(entity); } } @@ -832,11 +840,6 @@ impl Server { let before_tick_6 = Instant::now(); // 6) Synchronise clients with the new state of the world. - // TODO: Remove sphynx - // Sync 'logical' state using Sphynx. - let sync_package = self.state.ecs_mut().next_sync_package(); - self.state - .notify_registered_clients(ServerMsg::EcsSync(sync_package)); // Remove NPCs that are outside the view distances of all players // This is done by removing NPCs in unloaded chunks @@ -853,7 +856,7 @@ impl Server { .collect::>() }; for entity in to_delete { - let _ = self.state.ecs_mut().delete_entity_synced(entity); + let _ = self.state.ecs_mut().delete_entity(entity); } let before_tick_7 = Instant::now(); @@ -864,6 +867,7 @@ impl Server { .read_resource::() .nanos as i64; let message_nanos = self.state.ecs().read_resource::().nanos as i64; + let sentinel_nanos = self.state.ecs().read_resource::().nanos as i64; let subscription_nanos = self .state .ecs() @@ -877,6 +881,7 @@ impl Server { let terrain_nanos = self.state.ecs().read_resource::().nanos as i64; let total_sys_nanos = entity_sync_nanos + message_nanos + + sentinel_nanos + subscription_nanos + terrain_sync_nanos + terrain_nanos; @@ -979,7 +984,13 @@ impl Server { .get_mut(entity) .unwrap() .notify(ServerMsg::InitialSync { - ecs_state: self.state.ecs().gen_state_package(), + ecs_state: TrackedResources::fetch(&self.state.ecs().res) + .state_package() + // Send client their entity + .with_entity( + TrackedComps::fetch(&self.state.ecs().res) + .create_entity_package(entity), + ), entity_uid: self.state.ecs().uid_from_entity(entity).unwrap().into(), // Can't fail. server_info: self.server_info.clone(), // world_map: (WORLD_SIZE/*, self.world.sim().get_map()*/), diff --git a/server/src/sys/entity_sync.rs b/server/src/sys/entity_sync.rs index a0d79fcb91..7d9dc40307 100644 --- a/server/src/sys/entity_sync.rs +++ b/server/src/sys/entity_sync.rs @@ -1,4 +1,7 @@ -use super::SysTimer; +use super::{ + sentinel::{ReadTrackers, TrackedComps, TrackedResources}, + SysTimer, +}; use crate::{ client::{Client, RegionSubscription}, Tick, @@ -35,6 +38,9 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, Client>, WriteStorage<'a, ForceUpdate>, WriteStorage<'a, InventoryUpdate>, + TrackedComps<'a>, + ReadTrackers<'a>, + TrackedResources<'a>, ); fn run( @@ -58,6 +64,9 @@ impl<'a> System<'a> for Sys { mut clients, mut force_updates, mut inventory_updates, + tracked_comps, + read_trackers, + tracked_resources, ): Self::SystemData, ) { timer.start(); @@ -105,14 +114,18 @@ impl<'a> System<'a> for Sys { }) }) { + let create_msg = ServerMsg::CreateEntity( + tracked_comps.create_entity_package(entity), + ); for (client, regions, client_entity, _) in &mut subscribers { if maybe_key .as_ref() .map(|key| !regions.contains(key)) .unwrap_or(true) + // Client doesn't need to know about itself && *client_entity != entity - // Client doesn't need to know about itself { + client.notify(create_msg.clone()); send_initial_unsynced_components( client, uid, @@ -142,39 +155,52 @@ impl<'a> System<'a> for Sys { } } - let mut send_msg = - |msg: ServerMsg, entity: EcsEntity, pos: Pos, force_update, throttle: bool| { - for (client, _, client_entity, client_pos) in &mut subscribers { - match force_update { - None if client_entity == &entity => {} - _ => { - let distance_sq = client_pos.0.distance_squared(pos.0); + // Sync tracked components + let sync_msg = ServerMsg::EcsSync( + read_trackers.create_sync_package(&tracked_comps, region.entities()), + ); + for (client, _, _, _) in &mut subscribers { + client.notify(sync_msg.clone()); + } - // Throttle update rate based on distance to player - // TODO: more entities will be farther away so it could be more - // efficient to reverse the order of these checks - let update = if !throttle || distance_sq < 100.0f32.powi(2) { - true // Closer than 100.0 blocks - } else if distance_sq < 150.0f32.powi(2) { - (tick + entity.id() as u64) % 2 == 0 - } else if distance_sq < 200.0f32.powi(2) { - (tick + entity.id() as u64) % 4 == 0 - } else if distance_sq < 250.0f32.powi(2) { - (tick + entity.id() as u64) % 8 == 0 - } else if distance_sq < 300.0f32.powi(2) { - (tick + entity.id() as u64) % 16 == 0 - } else { - (tick + entity.id() as u64) % 32 == 0 - }; - - if update { - client.notify(msg.clone()); - } - } + let mut send_msg = |msg: ServerMsg, + entity: EcsEntity, + pos: Pos, + force_update: Option<&ForceUpdate>, + throttle: bool| { + for (client, _, client_entity, client_pos) in &mut subscribers { + let update = if client_entity == &entity && force_update.is_none() { + // Don't send client physics update about itself + false + } else if !throttle { + // Update rate not thottled by distance + true + } else { + // Throttle update rate based on distance to client + let distance_sq = client_pos.0.distance_squared(pos.0); + // More entities farther away so checks start there + if distance_sq > 300.0f32.powi(2) { + (tick + entity.id() as u64) % 32 == 0 + } else if distance_sq > 250.0f32.powi(2) { + (tick + entity.id() as u64) % 16 == 0 + } else if distance_sq > 200.0f32.powi(2) { + (tick + entity.id() as u64) % 8 == 0 + } else if distance_sq > 150.0f32.powi(2) { + (tick + entity.id() as u64) % 4 == 0 + } else if distance_sq > 100.0f32.powi(2) { + (tick + entity.id() as u64) % 2 == 0 + } else { + true // Closer than 100 blocks } - } - }; + }; + if update { + client.notify(msg.clone()); + } + } + }; + + // Sync physics components for (_, entity, &uid, &pos, maybe_vel, maybe_ori, character_state, force_update) in ( region.entities(), &entities, @@ -257,6 +283,8 @@ impl<'a> System<'a> for Sys { } } + // TODO: Sync clients that don't have a position? + // Sync inventories for (client, inventory, _) in (&mut clients, &inventories, &inventory_updates).join() { client.notify(ServerMsg::InventoryUpdate(inventory.clone())); @@ -266,6 +294,13 @@ impl<'a> System<'a> for Sys { force_updates.clear(); inventory_updates.clear(); + // Sync resources + // TODO: doesn't really belong in this system + let res_msg = ServerMsg::EcsResSync(tracked_resources.create_res_sync_package()); + for client in (&mut clients).join() { + client.notify(res_msg.clone()); + } + timer.end(); } } diff --git a/server/src/sys/mod.rs b/server/src/sys/mod.rs index bbdadac329..28b3ac5842 100644 --- a/server/src/sys/mod.rs +++ b/server/src/sys/mod.rs @@ -1,5 +1,6 @@ pub mod entity_sync; pub mod message; +pub mod sentinel; pub mod subscription; pub mod terrain; pub mod terrain_sync; @@ -9,20 +10,27 @@ use std::{marker::PhantomData, time::Instant}; pub type EntitySyncTimer = SysTimer; pub type MessageTimer = SysTimer; +pub type SentinelTimer = SysTimer; pub type SubscriptionTimer = SysTimer; pub type TerrainTimer = SysTimer; pub type TerrainSyncTimer = SysTimer; // System names const ENTITY_SYNC_SYS: &str = "server_entity_sync_sys"; +const SENTINEL_SYS: &str = "sentinel_sys"; const SUBSCRIPTION_SYS: &str = "server_subscription_sys"; const TERRAIN_SYNC_SYS: &str = "server_terrain_sync_sys"; const TERRAIN_SYS: &str = "server_terrain_sys"; const MESSAGE_SYS: &str = "server_message_sys"; pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { + dispatch_builder.add(sentinel::Sys, SENTINEL_SYS, &[]); dispatch_builder.add(subscription::Sys, SUBSCRIPTION_SYS, &[]); - dispatch_builder.add(entity_sync::Sys, ENTITY_SYNC_SYS, &[SUBSCRIPTION_SYS]); + dispatch_builder.add( + entity_sync::Sys, + ENTITY_SYNC_SYS, + &[SUBSCRIPTION_SYS, SENTINEL_SYS], + ); dispatch_builder.add(terrain_sync::Sys, TERRAIN_SYS, &[]); dispatch_builder.add(terrain::Sys, TERRAIN_SYNC_SYS, &[TERRAIN_SYS]); dispatch_builder.add(message::Sys, MESSAGE_SYS, &[]); diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs new file mode 100644 index 0000000000..d9abdbabdf --- /dev/null +++ b/server/src/sys/sentinel.rs @@ -0,0 +1,309 @@ +use super::SysTimer; +use common::{ + comp::{ + Body, CanBuild, Gravity, Item, LightEmitter, Mass, MountState, Mounting, Player, + Projectile, Scale, Stats, Sticky, + }, + msg::{EcsCompPacket, EcsResPacket}, + sphynx::{ + self, EntityPackage, ResSyncPackage, StatePackage, SyncPackage, UpdateTracker, WorldSyncExt, + }, + state::{Time, TimeOfDay, Uid}, +}; +use shred_derive::SystemData; +use specs::{ + Entity as EcsEntity, Join, ReadExpect, ReadStorage, System, World, Write, WriteExpect, +}; +use std::ops::Deref; + +/// Always watching +/// This system will monitor specific components for insertion, removal, and modification +pub struct Sys; +impl<'a> System<'a> for Sys { + type SystemData = ( + Write<'a, SysTimer>, + TrackedComps<'a>, + WriteTrackers<'a>, + ); + + fn run(&mut self, (mut timer, comps, mut trackers): Self::SystemData) { + timer.start(); + + record_changes(&comps, &mut trackers); + + timer.end(); + } +} + +// Probably more difficult than it needs to be :p +#[derive(SystemData)] +pub struct TrackedComps<'a> { + uid: ReadStorage<'a, Uid>, + body: ReadStorage<'a, Body>, + player: ReadStorage<'a, Player>, + stats: ReadStorage<'a, Stats>, + can_build: ReadStorage<'a, CanBuild>, + light_emitter: ReadStorage<'a, LightEmitter>, + item: ReadStorage<'a, Item>, + scale: ReadStorage<'a, Scale>, + mounting: ReadStorage<'a, Mounting>, + mount_state: ReadStorage<'a, MountState>, + mass: ReadStorage<'a, Mass>, + sticky: ReadStorage<'a, Sticky>, + gravity: ReadStorage<'a, Gravity>, + projectile: ReadStorage<'a, Projectile>, +} +impl<'a> TrackedComps<'a> { + pub fn create_entity_package(&self, entity: EcsEntity) -> EntityPackage { + let uid = self + .uid + .get(entity) + .copied() + .expect("No uid to create an entity package") + .0; + let mut packets = Vec::new(); + self.body + .get(entity) + .copied() + .map(|c| packets.push(c.into())); + self.player + .get(entity) + .cloned() + .map(|c| packets.push(c.into())); + self.stats + .get(entity) + .cloned() + .map(|c| packets.push(c.into())); + self.can_build + .get(entity) + .cloned() + .map(|c| packets.push(c.into())); + self.light_emitter + .get(entity) + .copied() + .map(|c| packets.push(c.into())); + self.item + .get(entity) + .cloned() + .map(|c| packets.push(c.into())); + self.scale + .get(entity) + .copied() + .map(|c| packets.push(c.into())); + self.mounting + .get(entity) + .cloned() + .map(|c| packets.push(c.into())); + self.mount_state + .get(entity) + .cloned() + .map(|c| packets.push(c.into())); + self.mass + .get(entity) + .copied() + .map(|c| packets.push(c.into())); + self.sticky + .get(entity) + .copied() + .map(|c| packets.push(c.into())); + self.gravity + .get(entity) + .copied() + .map(|c| packets.push(c.into())); + self.projectile + .get(entity) + .cloned() + .map(|c| packets.push(c.into())); + + EntityPackage(uid, packets) + } +} +#[derive(SystemData)] +pub struct ReadTrackers<'a> { + uid: ReadExpect<'a, UpdateTracker>, + body: ReadExpect<'a, UpdateTracker>, + player: ReadExpect<'a, UpdateTracker>, + stats: ReadExpect<'a, UpdateTracker>, + can_build: ReadExpect<'a, UpdateTracker>, + light_emitter: ReadExpect<'a, UpdateTracker>, + item: ReadExpect<'a, UpdateTracker>, + scale: ReadExpect<'a, UpdateTracker>, + mounting: ReadExpect<'a, UpdateTracker>, + mount_state: ReadExpect<'a, UpdateTracker>, + mass: ReadExpect<'a, UpdateTracker>, + sticky: ReadExpect<'a, UpdateTracker>, + gravity: ReadExpect<'a, UpdateTracker>, + projectile: ReadExpect<'a, UpdateTracker>, +} +impl<'a> ReadTrackers<'a> { + pub fn create_sync_package( + &self, + comps: &TrackedComps, + filter: impl Join + Copy, + ) -> SyncPackage { + SyncPackage::new(&comps.uid, &self.uid, filter) + .with_component( + &comps.uid, + &self.uid, + self.body.deref(), + &comps.body, + filter, + ) + .with_component( + &comps.uid, + &self.uid, + self.player.deref(), + &comps.player, + filter, + ) + .with_component( + &comps.uid, + &self.uid, + self.stats.deref(), + &comps.stats, + filter, + ) + .with_component( + &comps.uid, + &self.uid, + self.can_build.deref(), + &comps.can_build, + filter, + ) + .with_component( + &comps.uid, + &self.uid, + self.light_emitter.deref(), + &comps.light_emitter, + filter, + ) + .with_component( + &comps.uid, + &self.uid, + self.item.deref(), + &comps.item, + filter, + ) + .with_component( + &comps.uid, + &self.uid, + self.scale.deref(), + &comps.scale, + filter, + ) + .with_component( + &comps.uid, + &self.uid, + self.mounting.deref(), + &comps.mounting, + filter, + ) + .with_component( + &comps.uid, + &self.uid, + self.mount_state.deref(), + &comps.mount_state, + filter, + ) + .with_component( + &comps.uid, + &self.uid, + self.mass.deref(), + &comps.mass, + filter, + ) + .with_component( + &comps.uid, + &self.uid, + self.sticky.deref(), + &comps.sticky, + filter, + ) + .with_component( + &comps.uid, + &self.uid, + self.gravity.deref(), + &comps.gravity, + filter, + ) + .with_component( + &comps.uid, + &self.uid, + self.projectile.deref(), + &comps.projectile, + filter, + ) + } +} + +#[derive(SystemData)] +pub struct WriteTrackers<'a> { + uid: WriteExpect<'a, UpdateTracker>, + body: WriteExpect<'a, UpdateTracker>, + player: WriteExpect<'a, UpdateTracker>, + stats: WriteExpect<'a, UpdateTracker>, + can_build: WriteExpect<'a, UpdateTracker>, + light_emitter: WriteExpect<'a, UpdateTracker>, + item: WriteExpect<'a, UpdateTracker>, + scale: WriteExpect<'a, UpdateTracker>, + mounting: WriteExpect<'a, UpdateTracker>, + mount_state: WriteExpect<'a, UpdateTracker>, + mass: WriteExpect<'a, UpdateTracker>, + sticky: WriteExpect<'a, UpdateTracker>, + gravity: WriteExpect<'a, UpdateTracker>, + projectile: WriteExpect<'a, UpdateTracker>, +} + +fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) { + // Update trackers + trackers.uid.record_changes(&comps.uid); + trackers.body.record_changes(&comps.body); + trackers.player.record_changes(&comps.player); + trackers.stats.record_changes(&comps.stats); + trackers.can_build.record_changes(&comps.can_build); + trackers.light_emitter.record_changes(&comps.light_emitter); + trackers.item.record_changes(&comps.item); + trackers.scale.record_changes(&comps.scale); + trackers.mounting.record_changes(&comps.mounting); + trackers.mount_state.record_changes(&comps.mount_state); + trackers.mass.record_changes(&comps.mass); + trackers.sticky.record_changes(&comps.sticky); + trackers.gravity.record_changes(&comps.gravity); + trackers.projectile.record_changes(&comps.projectile); +} + +pub fn register_trackers(world: &mut World) { + world.register_tracker::(); + world.register_tracker::(); + world.register_tracker::(); + world.register_tracker::(); + world.register_tracker::(); + world.register_tracker::(); + world.register_tracker::(); + world.register_tracker::(); + world.register_tracker::(); + world.register_tracker::(); + world.register_tracker::(); + world.register_tracker::(); + world.register_tracker::(); + world.register_tracker::(); +} + +#[derive(SystemData)] +pub struct TrackedResources<'a> { + time: ReadExpect<'a, Time>, + time_of_day: ReadExpect<'a, TimeOfDay>, +} +impl<'a> TrackedResources<'a> { + pub fn create_res_sync_package(&self) -> ResSyncPackage { + ResSyncPackage::new() + .with_res(self.time.deref()) + .with_res(self.time_of_day.deref()) + } + /// Create state package with resources included + pub fn state_package(&self) -> StatePackage { + StatePackage::new() + .with_res(self.time.deref()) + .with_res(self.time_of_day.deref()) + } +} diff --git a/server/src/sys/subscription.rs b/server/src/sys/subscription.rs index 88e574959e..0a5f0891dd 100644 --- a/server/src/sys/subscription.rs +++ b/server/src/sys/subscription.rs @@ -1,4 +1,4 @@ -use super::SysTimer; +use super::{sentinel::TrackedComps, SysTimer}; use crate::client::{self, Client, RegionSubscription}; use common::{ comp::{CharacterState, Ori, Player, Pos, Vel}, @@ -26,6 +26,7 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Player>, WriteStorage<'a, Client>, WriteStorage<'a, RegionSubscription>, + TrackedComps<'a>, ); fn run( @@ -42,6 +43,7 @@ impl<'a> System<'a> for Sys { players, mut clients, mut subscriptions, + tracked_comps, ): Self::SystemData, ) { timer.start(); @@ -142,7 +144,7 @@ impl<'a> System<'a> for Sys { // Send client intial info about the entities in this region if subscription.regions.insert(key) { if let Some(region) = region_map.get(key) { - for (uid, pos, vel, ori, character_state, _, _) in ( + for (uid, pos, vel, ori, character_state, _, entity) in ( &uids, &positions, velocities.maybe(), @@ -154,6 +156,11 @@ impl<'a> System<'a> for Sys { .join() .filter(|(_, _, _, _, _, _, e)| *e != client_entity) { + // Send message to create entity and tracked components + client.notify(ServerMsg::CreateEntity( + tracked_comps.create_entity_package(entity), + )); + // Send message to create physics components super::entity_sync::send_initial_unsynced_components( client, uid, From 71cce03f293def79a0710d3b3501bb9962b0f3cd Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 24 Nov 2019 15:12:03 -0500 Subject: [PATCH 07/51] Move sync code into common submodule --- Cargo.lock | 12 +-- client/src/lib.rs | 4 +- common/Cargo.toml | 3 +- common/src/comp/controller.rs | 2 +- common/src/comp/phys.rs | 2 +- common/src/comp/projectile.rs | 3 +- common/src/comp/stats.rs | 2 +- common/src/event.rs | 3 +- common/src/lib.rs | 4 +- common/src/msg/ecs_packet.rs | 112 ++++++++++----------- common/src/msg/server.rs | 10 +- common/src/state.rs | 19 +--- common/src/sync/mod.rs | 14 +++ common/src/sync/packet.rs | 167 +++++++++++++++++++++++++++++++ common/src/sync/sync_ext.rs | 178 +++++++++++++++++++++++++++++++++ common/src/sync/track.rs | 144 ++++++++++++++++++++++++++ common/src/sync/uid.rs | 88 ++++++++++++++++ common/src/sys/combat.rs | 3 +- common/src/sys/controller.rs | 2 +- common/src/sys/mount.rs | 6 +- common/src/sys/movement.rs | 4 +- common/src/sys/phys.rs | 2 +- server/src/cmd.rs | 2 +- server/src/lib.rs | 6 +- server/src/sys/entity_sync.rs | 6 +- server/src/sys/sentinel.rs | 9 +- server/src/sys/subscription.rs | 2 +- 27 files changed, 684 insertions(+), 125 deletions(-) create mode 100644 common/src/sync/mod.rs create mode 100644 common/src/sync/packet.rs create mode 100644 common/src/sync/sync_ext.rs create mode 100644 common/src/sync/track.rs create mode 100644 common/src/sync/uid.rs diff --git a/Cargo.lock b/Cargo.lock index 040d359b08..a945449cd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3194,16 +3194,6 @@ dependencies = [ "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "sphynx" -version = "0.1.0" -dependencies = [ - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sum_type 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "spin" version = "0.5.2" @@ -3598,7 +3588,7 @@ dependencies = [ "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", "specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git)", - "sphynx 0.1.0", + "sum_type 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/client/src/lib.rs b/client/src/lib.rs index b97f7f31a8..b59571a1f0 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -14,8 +14,8 @@ use common::{ ServerError, ServerInfo, ServerMsg, MAX_BYTES_CHAT_MSG, }, net::PostBox, - sphynx::WorldSyncExt, - state::{State, Uid}, + state::State, + sync::{Uid, WorldSyncExt}, terrain::{block::Block, TerrainChunk, TerrainChunkSize}, vol::RectVolSize, ChatType, diff --git a/common/Cargo.toml b/common/Cargo.toml index e8a7c0ed41..08f6ca603c 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -5,8 +5,6 @@ authors = ["Joshua Barretto ", "Maciej Ćwięka for EcsResPacket // for each variant EcsResPacket::T(T). @@ -12,11 +12,11 @@ sum_type! { TimeOfDay(state::TimeOfDay), } } -impl sphynx::ResPacket for EcsResPacket { +impl sync::ResPacket for EcsResPacket { fn apply(self, world: &specs::World) { match self { - EcsResPacket::Time(time) => sphynx::handle_res_update(time, world), - EcsResPacket::TimeOfDay(time_of_day) => sphynx::handle_res_update(time_of_day, world), + EcsResPacket::Time(time) => sync::handle_res_update(time, world), + EcsResPacket::TimeOfDay(time_of_day) => sync::handle_res_update(time_of_day, world), } } } @@ -66,72 +66,68 @@ sum_type! { Sticky(PhantomData), } } -impl sphynx::CompPacket for EcsCompPacket { +impl sync::CompPacket for EcsCompPacket { type Phantom = EcsCompPhantom; fn apply_insert(self, entity: specs::Entity, world: &specs::World) { match self { - EcsCompPacket::Pos(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::Vel(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::Ori(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::Body(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::Player(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::CanBuild(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::Stats(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::LightEmitter(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::Item(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::Scale(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::MountState(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::Mounting(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::Mass(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::Projectile(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::Gravity(comp) => sphynx::handle_insert(comp, entity, world), - EcsCompPacket::Sticky(comp) => sphynx::handle_insert(comp, entity, world), + EcsCompPacket::Pos(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::Vel(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::Ori(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::Body(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::Player(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::CanBuild(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::Stats(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::Item(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::Scale(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::MountState(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::Mounting(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::Mass(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::Projectile(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::Gravity(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::Sticky(comp) => sync::handle_insert(comp, entity, world), } } fn apply_modify(self, entity: specs::Entity, world: &specs::World) { match self { - EcsCompPacket::Pos(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::Vel(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::Ori(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::Body(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::Player(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::CanBuild(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::Stats(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::LightEmitter(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::Item(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::Scale(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::MountState(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::Mounting(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::Mass(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::Projectile(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::Gravity(comp) => sphynx::handle_modify(comp, entity, world), - EcsCompPacket::Sticky(comp) => sphynx::handle_modify(comp, entity, world), + EcsCompPacket::Pos(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::Vel(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::Ori(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::Body(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::Player(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::CanBuild(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::Stats(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::Item(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::Scale(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::MountState(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::Mounting(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::Mass(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::Projectile(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::Gravity(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::Sticky(comp) => sync::handle_modify(comp, entity, world), } } fn apply_remove(phantom: Self::Phantom, entity: specs::Entity, world: &specs::World) { match phantom { - EcsCompPhantom::Pos(_) => sphynx::handle_remove::(entity, world), - EcsCompPhantom::Vel(_) => sphynx::handle_remove::(entity, world), - EcsCompPhantom::Ori(_) => sphynx::handle_remove::(entity, world), - EcsCompPhantom::Body(_) => sphynx::handle_remove::(entity, world), - EcsCompPhantom::Player(_) => sphynx::handle_remove::(entity, world), - EcsCompPhantom::CanBuild(_) => sphynx::handle_remove::(entity, world), - EcsCompPhantom::Stats(_) => sphynx::handle_remove::(entity, world), + EcsCompPhantom::Pos(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::Vel(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::Ori(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::Body(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::Player(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::CanBuild(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::Stats(_) => sync::handle_remove::(entity, world), EcsCompPhantom::LightEmitter(_) => { - sphynx::handle_remove::(entity, world) + sync::handle_remove::(entity, world) } - EcsCompPhantom::Item(_) => sphynx::handle_remove::(entity, world), - EcsCompPhantom::Scale(_) => sphynx::handle_remove::(entity, world), - EcsCompPhantom::MountState(_) => { - sphynx::handle_remove::(entity, world) - } - EcsCompPhantom::Mounting(_) => sphynx::handle_remove::(entity, world), - EcsCompPhantom::Mass(_) => sphynx::handle_remove::(entity, world), - EcsCompPhantom::Projectile(_) => { - sphynx::handle_remove::(entity, world) - } - EcsCompPhantom::Gravity(_) => sphynx::handle_remove::(entity, world), - EcsCompPhantom::Sticky(_) => sphynx::handle_remove::(entity, world), + EcsCompPhantom::Item(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::Scale(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::MountState(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::Mounting(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::Mass(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::Projectile(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::Gravity(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::Sticky(_) => sync::handle_remove::(entity, world), } } } diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index dc8ccd8c1c..90bc785ddb 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -1,6 +1,6 @@ use super::{ClientState, EcsCompPacket, EcsResPacket}; use crate::{ - comp, + comp, sync, terrain::{Block, TerrainChunk}, ChatType, }; @@ -26,7 +26,7 @@ pub struct ServerInfo { #[derive(Debug, Clone, Serialize, Deserialize)] pub enum ServerMsg { InitialSync { - ecs_state: sphynx::StatePackage, + ecs_state: sync::StatePackage, entity_uid: u64, server_info: ServerInfo, // world_map: Vec2, /*, Vec)*/ @@ -40,9 +40,9 @@ pub enum ServerMsg { message: String, }, SetPlayerEntity(u64), - EcsSync(sphynx::SyncPackage), - EcsResSync(sphynx::ResSyncPackage), - CreateEntity(sphynx::EntityPackage), + EcsSync(sync::SyncPackage), + EcsResSync(sync::ResSyncPackage), + CreateEntity(sync::EntityPackage), DeleteEntity(u64), EntityPos { entity: u64, diff --git a/common/src/state.rs b/common/src/state.rs index 1d62d3419b..dbc9becad1 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -1,10 +1,8 @@ -// Reexports -pub use sphynx::Uid; - use crate::{ comp, event::{EventBus, LocalEvent, ServerEvent, SfxEventItem}, region::RegionMap, + sync::WorldSyncExt, sys, terrain::{Block, TerrainChunk, TerrainGrid}, vol::WriteVol, @@ -17,7 +15,6 @@ use specs::{ storage::{MaskedStorage as EcsMaskedStorage, Storage as EcsStorage}, Component, DispatcherBuilder, Entity as EcsEntity, }; -use sphynx::WorldSyncExt; use std::{sync::Arc, time::Duration}; use vek::*; @@ -103,20 +100,6 @@ impl Default for State { } impl State { - // Create a new `State` from an ECS state package. - /*pub fn from_state_package( - state_package: sphynx::StatePackage, - ) -> Self { - Self { - ecs: sphynx::World::from_state_package( - specs::World::new(), - Self::setup_sphynx_world, - state_package, - ), - thread_pool: Arc::new(ThreadPoolBuilder::new().build().unwrap()), - } - }*/ - /// Creates ecs world and registers all the common components and resources // TODO: Split up registering into server and client (e.g. move EventBus to the server) fn setup_ecs_world() -> specs::World { diff --git a/common/src/sync/mod.rs b/common/src/sync/mod.rs new file mode 100644 index 0000000000..d26ad789fd --- /dev/null +++ b/common/src/sync/mod.rs @@ -0,0 +1,14 @@ +// Note: Currently only one-way sync is supported until a usecase for two-way sync arises +mod packet; +mod sync_ext; +mod track; +mod uid; + +// Reexports +pub use packet::{ + handle_insert, handle_modify, handle_remove, handle_res_update, CompPacket, EntityPackage, + ResPacket, ResSyncPackage, StatePackage, SyncPackage, +}; +pub use sync_ext::WorldSyncExt; +pub use track::{Tracker, UpdateTracker}; +pub use uid::{Uid, UidAllocator}; diff --git a/common/src/sync/packet.rs b/common/src/sync/packet.rs new file mode 100644 index 0000000000..b3cf45bf3c --- /dev/null +++ b/common/src/sync/packet.rs @@ -0,0 +1,167 @@ +use super::{ + track::{Tracker, UpdateTracker}, + uid::Uid, +}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use specs::{shred::Resource, Component, Entity, Join, ReadStorage, World}; +use std::{ + convert::{TryFrom, TryInto}, + fmt::Debug, + marker::PhantomData, +}; + +pub trait CompPacket: Clone + Debug + Send + 'static { + type Phantom: Clone + Debug + Serialize + DeserializeOwned; + + fn apply_insert(self, entity: Entity, world: &World); + fn apply_modify(self, entity: Entity, world: &World); + fn apply_remove(phantom: Self::Phantom, entity: Entity, world: &World); +} + +pub trait ResPacket: Clone + Debug + Send + 'static { + fn apply(self, world: &World); +} + +/// Useful for implementing CompPacket trait +pub fn handle_insert(comp: C, entity: Entity, world: &World) { + let _ = world.write_storage::().insert(entity, comp); +} +/// Useful for implementing CompPacket trait +pub fn handle_modify(comp: C, entity: Entity, world: &World) { + let _ = world + .write_storage::() + .get_mut(entity) + .map(|c| *c = comp); +} +/// Useful for implementing CompPacket trait +pub fn handle_remove(entity: Entity, world: &World) { + let _ = world.write_storage::().remove(entity); +} +/// Useful for implementing ResPacket trait +pub fn handle_res_update(res: R, world: &World) { + *world.write_resource::() = res; +} + +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] +pub enum CompUpdateKind { + Inserted(P), + Modified(P), + Removed(P::Phantom), +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct EntityPackage(pub u64, pub Vec

); + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct StatePackage { + pub entities: Vec>, + pub resources: Vec, +} + +impl Default for StatePackage { + fn default() -> Self { + Self { + entities: Vec::new(), + resources: Vec::new(), + } + } +} + +impl StatePackage { + pub fn new() -> Self { + Self::default() + } + pub fn with_entities( + mut self, + mut entities: Vec>, + ) -> Self { + self.entities.append(&mut entities); + self + } + pub fn with_entity(mut self, entry: EntityPackage

) -> Self { + self.entities.push(entry); + self + } + pub fn with_res(mut self, res: &C) -> Self + where + R: From, + { + self.resources.push(R::from(res.clone())); + self + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct SyncPackage { + pub comp_updates: Vec<(u64, CompUpdateKind

)>, + pub created_entities: Vec, + pub deleted_entities: Vec, +} +impl SyncPackage

{ + pub fn new<'a>( + uids: &ReadStorage<'a, Uid>, + uid_tracker: &UpdateTracker, + filter: impl Join + Copy, + ) -> Self { + // Add created and deleted entities + let created_entities = (uids, filter, uid_tracker.inserted()) + .join() + .map(|(uid, _, _)| (*uid).into()) + .collect(); + // TODO: handle modified uid? + //created_entities.append(&mut (uids, filter, uid_tracker.inserted()).join().map(|(uid, _, _)| uid).collect()); + let deleted_entities = (uids, filter, uid_tracker.removed()) + .join() + .map(|(uid, _, _)| (*uid).into()) + .collect(); + + Self { + comp_updates: Vec::new(), + created_entities, + deleted_entities, + } + } + pub fn with_component<'a, C: Component + Clone + Send + Sync>( + mut self, + uids: &ReadStorage<'a, Uid>, + uid_tracker: &UpdateTracker, + tracker: &impl Tracker, + storage: &ReadStorage<'a, C>, + filter: impl Join + Copy, + ) -> Self + where + P: From, + C: TryFrom

, + P::Phantom: From>, + P::Phantom: TryInto>, + C::Storage: specs::storage::Tracked, + { + tracker.get_updates_for( + uids, + storage, + // Don't include updates for deleted entities + (filter, &!uid_tracker.removed()), + &mut self.comp_updates, + ); + self + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct ResSyncPackage { + pub resources: Vec, +} +impl ResSyncPackage { + pub fn new() -> Self { + Self { + resources: Vec::new(), + } + } + pub fn with_res(mut self, res: &C) -> Self + where + R: From, + { + self.resources.push(R::from(res.clone())); + self + } +} diff --git a/common/src/sync/sync_ext.rs b/common/src/sync/sync_ext.rs new file mode 100644 index 0000000000..a375667111 --- /dev/null +++ b/common/src/sync/sync_ext.rs @@ -0,0 +1,178 @@ +use super::{ + packet::{ + CompPacket, CompUpdateKind, EntityPackage, ResPacket, ResSyncPackage, StatePackage, + SyncPackage, + }, + track::UpdateTracker, + uid::{Uid, UidAllocator}, +}; +use specs::{ + saveload::{MarkedBuilder, MarkerAllocator}, + world::Builder, +}; + +pub trait WorldSyncExt { + fn register_sync_marker(&mut self); + fn register_synced(&mut self) + where + C::Storage: Default + specs::storage::Tracked; + fn register_tracker(&mut self) + where + C::Storage: Default + specs::storage::Tracked; + fn create_entity_synced(&mut self) -> specs::EntityBuilder; + fn uid_from_entity(&self, entity: specs::Entity) -> Option; + fn entity_from_uid(&self, uid: u64) -> Option; + fn apply_entity_package(&mut self, entity_package: EntityPackage

); + fn apply_state_package( + &mut self, + state_package: StatePackage, + ); + fn apply_sync_package(&mut self, package: SyncPackage

); + fn apply_res_sync_package(&mut self, package: ResSyncPackage); +} + +impl WorldSyncExt for specs::World { + fn register_sync_marker(&mut self) { + self.register_synced::(); + + self.add_resource(UidAllocator::new()); + } + fn register_synced(&mut self) + where + // P: From, + // C: TryFrom, + // P::Phantom: From>, + // P::Phantom: TryInto>, + C::Storage: Default + specs::storage::Tracked, + { + self.register::(); + self.register_tracker::(); + } + fn register_tracker(&mut self) + where + // P: From, + // C: TryFrom, + // P::Phantom: From>, + // P::Phantom: TryInto>, + C::Storage: Default + specs::storage::Tracked, + { + let tracker = UpdateTracker::::new(self); + self.add_resource(tracker); + } + + /*fn insert_synced(&mut self, res: C) + //where + // R: From, + // C: TryFrom, + { + self.add_resource::(res); + + self.res_trackers.insert(ResUpdateTracker::::new()); + }*/ + + fn create_entity_synced(&mut self) -> specs::EntityBuilder { + self.create_entity().marked::() + } + + /// Get the UID of an entity + fn uid_from_entity(&self, entity: specs::Entity) -> Option { + self.read_storage::().get(entity).copied() + } + + /// Get the UID of an entity + fn entity_from_uid(&self, uid: u64) -> Option { + self.read_resource::() + .retrieve_entity_internal(uid) + } + + fn apply_entity_package(&mut self, entity_package: EntityPackage

) { + let EntityPackage(entity_uid, packets) = entity_package; + + let entity = create_entity_with_uid(self, entity_uid); + for packet in packets { + packet.apply_insert(entity, self) + } + } + + fn apply_state_package( + &mut self, + state_package: StatePackage, + ) { + let StatePackage { + entities, + resources, + } = state_package; + + // Apply state package resources + for res_packet in resources { + res_packet.apply(self); + } + + // Apply state package entities + for entity_package in entities { + self.apply_entity_package(entity_package); + } + + // Initialize entities + //specs_world.maintain(); + } + + fn apply_sync_package(&mut self, package: SyncPackage

) { + // Take ownership of the fields + let SyncPackage { + comp_updates, + created_entities, + deleted_entities, + } = package; + + // Attempt to create entities + for entity_uid in created_entities { + create_entity_with_uid(self, entity_uid); + } + + // Update components + for (entity_uid, update) in comp_updates { + if let Some(entity) = self + .read_resource::() + .retrieve_entity_internal(entity_uid) + { + match update { + CompUpdateKind::Inserted(packet) => { + packet.apply_insert(entity, self); + } + CompUpdateKind::Modified(packet) => { + packet.apply_modify(entity, self); + } + CompUpdateKind::Removed(phantom) => { + P::apply_remove(phantom, entity, self); + } + } + } + } + + // Attempt to delete entities that were marked for deletion + for entity_uid in deleted_entities { + let entity = self + .read_resource::() + .retrieve_entity_internal(entity_uid); + if let Some(entity) = entity { + let _ = self.delete_entity(entity); + } + } + } + fn apply_res_sync_package(&mut self, package: ResSyncPackage) { + // Update resources + for res_packet in package.resources { + res_packet.apply(self); + } + } +} + +// Private utilities +fn create_entity_with_uid(specs_world: &mut specs::World, entity_uid: u64) -> specs::Entity { + let existing_entity = specs_world + .read_resource::() + .retrieve_entity_internal(entity_uid); + + existing_entity.unwrap_or_else(|| specs_world.create_entity_synced().build()) +} diff --git a/common/src/sync/track.rs b/common/src/sync/track.rs new file mode 100644 index 0000000000..2f27551b83 --- /dev/null +++ b/common/src/sync/track.rs @@ -0,0 +1,144 @@ +use super::{ + packet::{CompPacket, CompUpdateKind}, + uid::Uid, +}; +use specs::{BitSet, Component, Entity, Join, ReadStorage, World}; +use std::{ + convert::{TryFrom, TryInto}, + marker::PhantomData, +}; + +pub trait Tracker: Send + 'static +where + P: From, + C: TryFrom

, + P::Phantom: From>, + P::Phantom: TryInto>, + C::Storage: specs::storage::Tracked, +{ + fn add_packet_for<'a>( + &self, + storage: &specs::ReadStorage<'a, C>, + entity: specs::Entity, + packets: &mut Vec

, + ); + fn get_updates_for<'a>( + &self, + uids: &specs::ReadStorage<'a, Uid>, + storage: &specs::ReadStorage<'a, C>, + filter: impl Join + Copy, + buf: &mut Vec<(u64, CompUpdateKind

)>, + ); +} + +pub struct UpdateTracker { + reader_id: specs::ReaderId, + inserted: BitSet, + modified: BitSet, + removed: BitSet, + phantom: PhantomData, +} +impl UpdateTracker +where + C::Storage: specs::storage::Tracked, +{ + pub fn new(specs_world: &mut World) -> Self { + Self { + reader_id: specs_world.write_storage::().register_reader(), + inserted: BitSet::new(), + modified: BitSet::new(), + removed: BitSet::new(), + phantom: PhantomData, + } + } + pub fn inserted(&self) -> &BitSet { + &self.inserted + } + pub fn modified(&self) -> &BitSet { + &self.modified + } + pub fn removed(&self) -> &BitSet { + &self.removed + } + pub fn record_changes<'a>(&mut self, storage: &specs::ReadStorage<'a, C>) { + self.inserted.clear(); + self.modified.clear(); + self.removed.clear(); + + for event in storage.channel().read(&mut self.reader_id) { + match event { + specs::storage::ComponentEvent::Inserted(id) => { + // If previously removed/modified we don't need to know that anymore + self.removed.remove(*id); + self.modified.remove(*id); + self.inserted.add(*id); + } + specs::storage::ComponentEvent::Modified(id) => { + // We don't care about modification if the component was just added or was + // removed + if !self.removed.contains(*id) && !self.inserted.contains(*id) { + self.modified.add(*id); + } + } + specs::storage::ComponentEvent::Removed(id) => { + // Don't need to know that it was inserted/modified if it was subsequently removed + self.inserted.remove(*id); + self.modified.remove(*id); + self.removed.add(*id); + } + }; + } + } +} + +impl Tracker for UpdateTracker +where + P: From, + C: TryFrom

, + P::Phantom: From>, + P::Phantom: TryInto>, + C::Storage: specs::storage::Tracked, +{ + fn add_packet_for<'a>( + &self, + storage: &ReadStorage<'a, C>, + entity: Entity, + packets: &mut Vec

, + ) { + if let Some(comp) = storage.get(entity) { + packets.push(P::from(comp.clone())); + } + } + + fn get_updates_for<'a>( + &self, + uids: &specs::ReadStorage<'a, Uid>, + storage: &specs::ReadStorage<'a, C>, + entity_filter: impl Join + Copy, + buf: &mut Vec<(u64, CompUpdateKind

)>, + ) { + // Generate inserted updates + for (uid, comp, _, _) in (uids, storage, &self.inserted, entity_filter).join() { + buf.push(( + (*uid).into(), + CompUpdateKind::Inserted(P::from(comp.clone())), + )); + } + + // Generate modified updates + for (uid, comp, _, _) in (uids, storage, &self.modified, entity_filter).join() { + buf.push(( + (*uid).into(), + CompUpdateKind::Modified(P::from(comp.clone())), + )); + } + + // Generate removed updates + for (uid, _, _) in (uids, &self.removed, entity_filter).join() { + buf.push(( + (*uid).into(), + CompUpdateKind::Removed(P::Phantom::from(PhantomData::)), + )); + } + } +} diff --git a/common/src/sync/uid.rs b/common/src/sync/uid.rs new file mode 100644 index 0000000000..e7dc31b241 --- /dev/null +++ b/common/src/sync/uid.rs @@ -0,0 +1,88 @@ +use serde_derive::{Deserialize, Serialize}; +use specs::{ + saveload::{Marker, MarkerAllocator}, + world::EntitiesRes, + Component, Entity, FlaggedStorage, Join, ReadStorage, VecStorage, +}; +use std::{collections::HashMap, fmt, u64}; + +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +pub struct Uid(pub u64); + +impl Into for Uid { + fn into(self) -> u64 { + self.0 + } +} + +impl From for Uid { + fn from(uid: u64) -> Self { + Self(uid) + } +} + +impl fmt::Display for Uid { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl Component for Uid { + type Storage = FlaggedStorage>; +} + +impl Marker for Uid { + type Identifier = u64; + type Allocator = UidAllocator; + + fn id(&self) -> u64 { + self.0 + } + + fn update(&mut self, update: Self) { + assert_eq!(self.0, update.0); + } +} + +pub struct UidAllocator { + index: u64, + mapping: HashMap, +} + +impl UidAllocator { + pub fn new() -> Self { + Self { + index: 0, + mapping: HashMap::new(), + } + } +} + +impl Default for UidAllocator { + fn default() -> Self { + Self::new() + } +} + +impl MarkerAllocator for UidAllocator { + fn allocate(&mut self, entity: Entity, id: Option) -> Uid { + let id = id.unwrap_or_else(|| { + let id = self.index; + self.index += 1; + self.mapping.insert(id, entity); + id + }); + Uid(id) + } + + fn retrieve_entity_internal(&self, id: u64) -> Option { + self.mapping.get(&id).cloned() + } + + fn maintain(&mut self, entities: &EntitiesRes, storage: &ReadStorage) { + self.mapping = (entities, storage) + .join() + .map(|(e, m)| (m.id(), e)) + .collect(); + } +} diff --git a/common/src/sys/combat.rs b/common/src/sys/combat.rs index 6a23de568f..7ee73e4bfa 100644 --- a/common/src/sys/combat.rs +++ b/common/src/sys/combat.rs @@ -4,7 +4,8 @@ use crate::{ Ori, Pos, Stats, }, event::{EventBus, LocalEvent, ServerEvent}, - state::{DeltaTime, Uid}, + state::DeltaTime, + sync::Uid, }; use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage}; use std::time::Duration; diff --git a/common/src/sys/controller.rs b/common/src/sys/controller.rs index 3894d1b325..999ebbba4a 100644 --- a/common/src/sys/controller.rs +++ b/common/src/sys/controller.rs @@ -7,12 +7,12 @@ use crate::{ }, event::{Emitter, EventBus, LocalEvent, ServerEvent}, state::DeltaTime, + sync::{Uid, UidAllocator}, }; use specs::{ saveload::{Marker, MarkerAllocator}, Entities, Entity, Join, Read, ReadStorage, System, WriteStorage, }; -use sphynx::{Uid, UidAllocator}; use std::time::Duration; use vek::*; diff --git a/common/src/sys/mount.rs b/common/src/sys/mount.rs index 0d992f57b4..741ee9212d 100644 --- a/common/src/sys/mount.rs +++ b/common/src/sys/mount.rs @@ -1,9 +1,11 @@ -use crate::comp::{Controller, MountState, Mounting, Ori, Pos, Vel}; +use crate::{ + comp::{Controller, MountState, Mounting, Ori, Pos, Vel}, + sync::UidAllocator, +}; use specs::{ saveload::{Marker, MarkerAllocator}, Entities, Join, Read, System, WriteStorage, }; -use sphynx::UidAllocator; use vek::*; /// This system is responsible for controlling mounts diff --git a/common/src/sys/movement.rs b/common/src/sys/movement.rs index 6bd3b797ee..dcec8bac24 100644 --- a/common/src/sys/movement.rs +++ b/common/src/sys/movement.rs @@ -5,10 +5,10 @@ use crate::{ }, event::{EventBus, ServerEvent}, state::DeltaTime, + sync::Uid, terrain::TerrainGrid, }; -use specs::prelude::*; -use sphynx::Uid; +use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage}; use std::time::Duration; use vek::*; diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index 401d1631f1..d0a9f133a9 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -3,11 +3,11 @@ use { comp::{Body, Gravity, Mass, Mounting, Ori, PhysicsState, Pos, Scale, Sticky, Vel}, event::{EventBus, ServerEvent}, state::DeltaTime, + sync::Uid, terrain::{Block, TerrainGrid}, vol::ReadVol, }, specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage}, - sphynx::Uid, vek::*, }; diff --git a/server/src/cmd.rs b/server/src/cmd.rs index df4b46882e..b3303cac21 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -10,8 +10,8 @@ use common::{ msg::ServerMsg, npc::{get_npc_name, NpcKind}, pathfinding::WorldPath, - sphynx::WorldSyncExt, state::TimeOfDay, + sync::WorldSyncExt, terrain::{Block, BlockKind, TerrainChunkSize}, vol::RectVolSize, }; diff --git a/server/src/lib.rs b/server/src/lib.rs index 1e0034b621..7e2f5729d0 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -27,8 +27,8 @@ use common::{ event::{EventBus, ServerEvent}, msg::{ClientMsg, ClientState, ServerError, ServerInfo, ServerMsg}, net::PostOffice, - sphynx::WorldSyncExt, - state::{BlockChange, State, TimeOfDay, Uid}, + state::{BlockChange, State, TimeOfDay}, + sync::{Uid, WorldSyncExt}, terrain::{block::Block, TerrainChunkSize, TerrainGrid}, vol::{ReadVol, RectVolSize, Vox}, }; @@ -899,7 +899,7 @@ impl Server { .set((before_tick_6 - before_handle_events).as_nanos() as i64); self.metrics .tick_time - .with_label_values(&["sphynx sync"]) + .with_label_values(&["entity deletion"]) .set((before_tick_7 - before_tick_6).as_nanos() as i64); self.metrics .tick_time diff --git a/server/src/sys/entity_sync.rs b/server/src/sys/entity_sync.rs index 7d9dc40307..05611359b6 100644 --- a/server/src/sys/entity_sync.rs +++ b/server/src/sys/entity_sync.rs @@ -10,7 +10,7 @@ use common::{ comp::{CharacterState, ForceUpdate, Inventory, InventoryUpdate, Last, Ori, Pos, Vel}, msg::ServerMsg, region::{Event as RegionEvent, RegionMap}, - state::Uid, + sync::Uid, }; use specs::{ Entities, Entity as EcsEntity, Join, Read, ReadExpect, ReadStorage, System, Write, WriteStorage, @@ -77,8 +77,8 @@ impl<'a> System<'a> for Sys { // 2. Iterate through region subscribers (ie clients) // - Collect a list of entity ids for clients who are subscribed to this region (hash calc to check each) // 3. Iterate through events from that region - // - For each entity left event, iterate through the client list and check if they are subscribed to the destination (hash calc per subscribed client per entity left event) - // - Do something with entity entered events when sphynx is removed?? + // - For each entity entered event, iterate through the client list and check if they are subscribed to the source (hash calc per subscribed client per entity event), if not subscribed to the source send a entity creation message to that client + // - For each entity left event, iterate through the client list and check if they are subscribed to the destination (hash calc per subscribed client per entity event) // 4. Iterate through entities in that region // 5. Inform clients of the component changes for that entity // - Throttle update rate base on distance to each client diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs index d9abdbabdf..a3a0f3ba33 100644 --- a/server/src/sys/sentinel.rs +++ b/server/src/sys/sentinel.rs @@ -5,10 +5,11 @@ use common::{ Projectile, Scale, Stats, Sticky, }, msg::{EcsCompPacket, EcsResPacket}, - sphynx::{ - self, EntityPackage, ResSyncPackage, StatePackage, SyncPackage, UpdateTracker, WorldSyncExt, + state::{Time, TimeOfDay}, + sync::{ + CompPacket, EntityPackage, ResSyncPackage, StatePackage, SyncPackage, Uid, UpdateTracker, + WorldSyncExt, }, - state::{Time, TimeOfDay, Uid}, }; use shred_derive::SystemData; use specs::{ @@ -301,7 +302,7 @@ impl<'a> TrackedResources<'a> { .with_res(self.time_of_day.deref()) } /// Create state package with resources included - pub fn state_package(&self) -> StatePackage { + pub fn state_package(&self) -> StatePackage { StatePackage::new() .with_res(self.time.deref()) .with_res(self.time_of_day.deref()) diff --git a/server/src/sys/subscription.rs b/server/src/sys/subscription.rs index 0a5f0891dd..d4617fd499 100644 --- a/server/src/sys/subscription.rs +++ b/server/src/sys/subscription.rs @@ -4,7 +4,7 @@ use common::{ comp::{CharacterState, Ori, Player, Pos, Vel}, msg::ServerMsg, region::{region_in_vd, regions_in_vd, Event as RegionEvent, RegionMap}, - state::Uid, + sync::Uid, terrain::TerrainChunkSize, vol::RectVolSize, }; From e49cafafbfb39078ed190049496eb2deb470edda Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 29 Nov 2019 01:04:37 -0500 Subject: [PATCH 08/51] Actually send deletion messages --- Cargo.toml | 2 +- client/src/lib.rs | 13 ++- common/src/msg/ecs_packet.rs | 15 --- common/src/region.rs | 59 ++++++++-- common/src/state.rs | 2 +- common/src/sync/packet.rs | 28 ++--- common/src/sync/sync_ext.rs | 52 ++++----- common/src/sync/track.rs | 1 + common/src/sync/uid.rs | 8 +- server/src/cmd.rs | 5 +- server/src/lib.rs | 199 ++++++++++++++------------------- server/src/sys/entity_sync.rs | 46 +++++++- server/src/sys/message.rs | 12 +- server/src/sys/sentinel.rs | 187 +++++++++++++------------------ server/src/sys/subscription.rs | 116 +++++++++++++++++-- voxygen/src/hud/mod.rs | 11 +- world/src/sim/mod.rs | 2 +- 17 files changed, 440 insertions(+), 318 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4c463c2db7..9abd786022 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ opt-level = 2 overflow-checks = true debug-assertions = true panic = "abort" -debug = false +# debug = false codegen-units = 8 lto = false incremental = true diff --git a/client/src/lib.rs b/client/src/lib.rs index b59571a1f0..c1e0a5c365 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -562,10 +562,15 @@ impl Client { self.state.ecs_mut().apply_entity_package(entity_package) } ServerMsg::DeleteEntity(entity) => { - if let Some(entity) = self.state.ecs().entity_from_uid(entity) { - if entity != self.entity { - let _ = self.state.ecs_mut().delete_entity(entity); - } + if self + .state + .read_component_cloned::(self.entity) + .map(|u| u.into()) + != Some(entity) + { + self.state + .ecs_mut() + .delete_entity_and_clear_from_uid_allocator(entity); } } ServerMsg::EntityPos { entity, pos } => { diff --git a/common/src/msg/ecs_packet.rs b/common/src/msg/ecs_packet.rs index 83f1adef10..28964041ab 100644 --- a/common/src/msg/ecs_packet.rs +++ b/common/src/msg/ecs_packet.rs @@ -25,9 +25,6 @@ impl sync::ResPacket for EcsResPacket { sum_type! { #[derive(Clone, Debug, Serialize, Deserialize)] pub enum EcsCompPacket { - Pos(comp::Pos), - Vel(comp::Vel), - Ori(comp::Ori), Body(comp::Body), Player(comp::Player), CanBuild(comp::CanBuild), @@ -48,9 +45,6 @@ sum_type! { sum_type! { #[derive(Clone, Debug, Serialize, Deserialize)] pub enum EcsCompPhantom { - Pos(PhantomData), - Vel(PhantomData), - Ori(PhantomData), Body(PhantomData), Player(PhantomData), CanBuild(PhantomData), @@ -70,9 +64,6 @@ impl sync::CompPacket for EcsCompPacket { type Phantom = EcsCompPhantom; fn apply_insert(self, entity: specs::Entity, world: &specs::World) { match self { - EcsCompPacket::Pos(comp) => sync::handle_insert(comp, entity, world), - EcsCompPacket::Vel(comp) => sync::handle_insert(comp, entity, world), - EcsCompPacket::Ori(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Body(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Player(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::CanBuild(comp) => sync::handle_insert(comp, entity, world), @@ -90,9 +81,6 @@ impl sync::CompPacket for EcsCompPacket { } fn apply_modify(self, entity: specs::Entity, world: &specs::World) { match self { - EcsCompPacket::Pos(comp) => sync::handle_modify(comp, entity, world), - EcsCompPacket::Vel(comp) => sync::handle_modify(comp, entity, world), - EcsCompPacket::Ori(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Body(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Player(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::CanBuild(comp) => sync::handle_modify(comp, entity, world), @@ -110,9 +98,6 @@ impl sync::CompPacket for EcsCompPacket { } fn apply_remove(phantom: Self::Phantom, entity: specs::Entity, world: &specs::World) { match phantom { - EcsCompPhantom::Pos(_) => sync::handle_remove::(entity, world), - EcsCompPhantom::Vel(_) => sync::handle_remove::(entity, world), - EcsCompPhantom::Ori(_) => sync::handle_remove::(entity, world), EcsCompPhantom::Body(_) => sync::handle_remove::(entity, world), EcsCompPhantom::Player(_) => sync::handle_remove::(entity, world), EcsCompPhantom::CanBuild(_) => sync::handle_remove::(entity, world), diff --git a/common/src/region.rs b/common/src/region.rs index de8e5a526d..acf4aa04fa 100644 --- a/common/src/region.rs +++ b/common/src/region.rs @@ -104,6 +104,16 @@ impl RegionMap { // TODO special case large entities pub fn tick(&mut self, pos: ReadStorage, vel: ReadStorage, entities: Entities) { self.tick += 1; + // Clear events within each region + for i in 0..self.regions.len() { + self.regions + .get_index_mut(i) + .map(|(_, v)| v) + .unwrap() + .events + .clear(); + } + // Add any untracked entites for (pos, id) in (&pos, &entities, !&self.tracked_entities) .join() @@ -118,14 +128,6 @@ impl RegionMap { let mut regions_to_remove = Vec::new(); for i in 0..self.regions.len() { - // Clear events within each region - self.regions - .get_index_mut(i) - .map(|(_, v)| v) - .unwrap() - .events - .clear(); - for (maybe_pos, _maybe_vel, id) in ( pos.maybe(), vel.maybe(), @@ -215,6 +217,47 @@ impl RegionMap { pub fn key_pos(key: Vec2) -> Vec2 { key.map(|e| e << REGION_LOG2) } + /// Finds the region where a given entity is located using a given position to speed up the search + pub fn find_region(&self, entity: specs::Entity, pos: Vec3) -> Option> { + let id = entity.id(); + // Compute key for most likely region + let key = Self::pos_key(pos.map(|e| e as i32)); + // Get region + if let Some(region) = self.regions.get(&key) { + if region.entities().contains(id) { + return Some(key); + } else { + // Check neighbors + for i in 0..8 { + if let Some(idx) = region.neighbors[i] { + let (key, region) = self.regions.get_index(idx).unwrap(); + if region.entities().contains(id) { + return Some(*key); + } + } + } + } + } else { + // Check neighbors + for i in 0..8 { + let key = key + NEIGHBOR_OFFSETS[i]; + if let Some(region) = self.regions.get(&key) { + if region.entities().contains(id) { + return Some(key); + } + } + } + } + + // Scan though all regions + for (key, region) in self.iter() { + if region.entities().contains(id) { + return Some(key); + } + } + + None + } fn key_index(&self, key: Vec2) -> Option { self.regions.get_full(&key).map(|(i, _, _)| i) } diff --git a/common/src/state.rs b/common/src/state.rs index dbc9becad1..a2120e60c6 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -148,10 +148,10 @@ impl State { ecs.register::(); // Register synced resources used by the ECS. - ecs.add_resource(Time(0.0)); ecs.add_resource(TimeOfDay(0.0)); // Register unsynced resources used by the ECS. + ecs.add_resource(Time(0.0)); ecs.add_resource(DeltaTime(0.0)); ecs.add_resource(TerrainGrid::new().unwrap()); ecs.add_resource(BlockChange::default()); diff --git a/common/src/sync/packet.rs b/common/src/sync/packet.rs index b3cf45bf3c..f12d409960 100644 --- a/common/src/sync/packet.rs +++ b/common/src/sync/packet.rs @@ -2,6 +2,7 @@ use super::{ track::{Tracker, UpdateTracker}, uid::Uid, }; +use log::error; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use specs::{shred::Resource, Component, Entity, Join, ReadStorage, World}; use std::{ @@ -24,7 +25,9 @@ pub trait ResPacket: Clone + Debug + Send + 'static { /// Useful for implementing CompPacket trait pub fn handle_insert(comp: C, entity: Entity, world: &World) { - let _ = world.write_storage::().insert(entity, comp); + if let Err(err) = world.write_storage::().insert(entity, comp) { + error!("Error inserting component: {:?}", err); + }; } /// Useful for implementing CompPacket trait pub fn handle_modify(comp: C, entity: Entity, world: &World) { @@ -102,6 +105,7 @@ impl SyncPackage

{ uids: &ReadStorage<'a, Uid>, uid_tracker: &UpdateTracker, filter: impl Join + Copy, + deleted_entities: Vec, ) -> Self { // Add created and deleted entities let created_entities = (uids, filter, uid_tracker.inserted()) @@ -110,10 +114,15 @@ impl SyncPackage

{ .collect(); // TODO: handle modified uid? //created_entities.append(&mut (uids, filter, uid_tracker.inserted()).join().map(|(uid, _, _)| uid).collect()); - let deleted_entities = (uids, filter, uid_tracker.removed()) - .join() - .map(|(uid, _, _)| (*uid).into()) - .collect(); + // let deleted_entities = (uids.maybe(), filter, uid_tracker.removed()) + // .join() + // Why doesn't this panic?? + // .map(|(uid, _, _)| Into::::into(*uid.unwrap())) + // .collect::>(); + //let len = deleted_entities.len(); + //if len > 0 { + // println!("deleted {} in sync message", len); + // } Self { comp_updates: Vec::new(), @@ -124,7 +133,6 @@ impl SyncPackage

{ pub fn with_component<'a, C: Component + Clone + Send + Sync>( mut self, uids: &ReadStorage<'a, Uid>, - uid_tracker: &UpdateTracker, tracker: &impl Tracker, storage: &ReadStorage<'a, C>, filter: impl Join + Copy, @@ -136,13 +144,7 @@ impl SyncPackage

{ P::Phantom: TryInto>, C::Storage: specs::storage::Tracked, { - tracker.get_updates_for( - uids, - storage, - // Don't include updates for deleted entities - (filter, &!uid_tracker.removed()), - &mut self.comp_updates, - ); + tracker.get_updates_for(uids, storage, filter, &mut self.comp_updates); self } } diff --git a/common/src/sync/sync_ext.rs b/common/src/sync/sync_ext.rs index a375667111..1033f666cb 100644 --- a/common/src/sync/sync_ext.rs +++ b/common/src/sync/sync_ext.rs @@ -6,6 +6,7 @@ use super::{ track::UpdateTracker, uid::{Uid, UidAllocator}, }; +use log::error; use specs::{ saveload::{MarkedBuilder, MarkerAllocator}, world::Builder, @@ -20,6 +21,7 @@ pub trait WorldSyncExt { where C::Storage: Default + specs::storage::Tracked; fn create_entity_synced(&mut self) -> specs::EntityBuilder; + fn delete_entity_and_clear_from_uid_allocator(&mut self, uid: u64); fn uid_from_entity(&self, entity: specs::Entity) -> Option; fn entity_from_uid(&self, uid: u64) -> Option; fn apply_entity_package(&mut self, entity_package: EntityPackage

); @@ -35,14 +37,11 @@ impl WorldSyncExt for specs::World { fn register_sync_marker(&mut self) { self.register_synced::(); + // TODO: Consider only having allocator server side for now self.add_resource(UidAllocator::new()); } fn register_synced(&mut self) where - // P: From, - // C: TryFrom, - // P::Phantom: From>, - // P::Phantom: TryInto>, C::Storage: Default + specs::storage::Tracked, { self.register::(); @@ -50,26 +49,12 @@ impl WorldSyncExt for specs::World { } fn register_tracker(&mut self) where - // P: From, - // C: TryFrom, - // P::Phantom: From>, - // P::Phantom: TryInto>, C::Storage: Default + specs::storage::Tracked, { let tracker = UpdateTracker::::new(self); self.add_resource(tracker); } - /*fn insert_synced(&mut self, res: C) - //where - // R: From, - // C: TryFrom, - { - self.add_resource::(res); - - self.res_trackers.insert(ResUpdateTracker::::new()); - }*/ - fn create_entity_synced(&mut self) -> specs::EntityBuilder { self.create_entity().marked::() } @@ -94,6 +79,16 @@ impl WorldSyncExt for specs::World { } } + fn delete_entity_and_clear_from_uid_allocator(&mut self, uid: u64) { + // Clear from uid allocator + let maybe_entity = self.write_resource::().remove_entity(uid); + if let Some(entity) = maybe_entity { + if let Err(err) = self.delete_entity(entity) { + error!("Failed to delete entity: {:?}", err); + } + } + } + fn apply_state_package( &mut self, state_package: StatePackage, @@ -114,7 +109,7 @@ impl WorldSyncExt for specs::World { } // Initialize entities - //specs_world.maintain(); + //self.maintain(); } fn apply_sync_package(&mut self, package: SyncPackage

) { @@ -152,12 +147,7 @@ impl WorldSyncExt for specs::World { // Attempt to delete entities that were marked for deletion for entity_uid in deleted_entities { - let entity = self - .read_resource::() - .retrieve_entity_internal(entity_uid); - if let Some(entity) = entity { - let _ = self.delete_entity(entity); - } + self.delete_entity_and_clear_from_uid_allocator(entity_uid); } } fn apply_res_sync_package(&mut self, package: ResSyncPackage) { @@ -174,5 +164,15 @@ fn create_entity_with_uid(specs_world: &mut specs::World, entity_uid: u64) -> sp .read_resource::() .retrieve_entity_internal(entity_uid); - existing_entity.unwrap_or_else(|| specs_world.create_entity_synced().build()) + match existing_entity { + Some(entity) => entity, + None => { + let entity_builder = specs_world.create_entity(); + let uid = entity_builder + .world + .write_resource::() + .allocate(entity_builder.entity, Some(entity_uid)); + entity_builder.with(uid).build() + } + } } diff --git a/common/src/sync/track.rs b/common/src/sync/track.rs index 2f27551b83..f1137f5d28 100644 --- a/common/src/sync/track.rs +++ b/common/src/sync/track.rs @@ -76,6 +76,7 @@ where specs::storage::ComponentEvent::Modified(id) => { // We don't care about modification if the component was just added or was // removed + // Could potentially remove since this should theoretically never occur... if !self.removed.contains(*id) && !self.inserted.contains(*id) { self.modified.add(*id); } diff --git a/common/src/sync/uid.rs b/common/src/sync/uid.rs index e7dc31b241..87f69e87ed 100644 --- a/common/src/sync/uid.rs +++ b/common/src/sync/uid.rs @@ -56,6 +56,10 @@ impl UidAllocator { mapping: HashMap::new(), } } + // Useful for when a single entity is deleted because it doesn't reconstruct the entire hashmap + pub fn remove_entity(&mut self, id: u64) -> Option { + self.mapping.remove(&id) + } } impl Default for UidAllocator { @@ -69,14 +73,14 @@ impl MarkerAllocator for UidAllocator { let id = id.unwrap_or_else(|| { let id = self.index; self.index += 1; - self.mapping.insert(id, entity); id }); + self.mapping.insert(id, entity); Uid(id) } fn retrieve_entity_internal(&self, id: u64) -> Option { - self.mapping.get(&id).cloned() + self.mapping.get(&id).copied() } fn maintain(&mut self, entities: &EntitiesRes, storage: &ReadStorage) { diff --git a/server/src/cmd.rs b/server/src/cmd.rs index b3303cac21..22606d8ee2 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -21,6 +21,7 @@ use vek::*; use world::util::Sampler; use lazy_static::lazy_static; +use log::error; use scan_fmt::{scan_fmt, scan_fmt_some}; /// Struct representing a command that a user can run from server chat. @@ -1118,7 +1119,9 @@ fn handle_remove_lights( let size = to_delete.len(); for entity in to_delete { - let _ = server.state.ecs_mut().delete_entity(entity); + if let Err(err) = server.state.delete_entity_recorded(entity) { + error!("Failed to delete light: {:?}", err); + } } server.notify_client( diff --git a/server/src/lib.rs b/server/src/lib.rs index 7e2f5729d0..d49d4345b3 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -19,7 +19,7 @@ use crate::{ chunk_generator::ChunkGenerator, client::{Client, RegionSubscription}, cmd::CHAT_COMMANDS, - sys::sentinel::{TrackedComps, TrackedResources}, + sys::sentinel::{DeletedEntities, TrackedComps, TrackedResources}, }; use common::{ assets, comp, @@ -32,7 +32,7 @@ use common::{ terrain::{block::Block, TerrainChunkSize, TerrainGrid}, vol::{ReadVol, RectVolSize, Vox}, }; -use log::debug; +use log::{debug, error}; use metrics::ServerMetrics; use rand::Rng; use specs::{ @@ -166,6 +166,8 @@ impl Server { // Register trackers sys::sentinel::register_trackers(&mut state.ecs_mut()); + state.ecs_mut().add_resource(DeletedEntities::default()); + let this = Self { state, world: Arc::new(world), @@ -309,8 +311,6 @@ impl Server { let server_settings = &self.server_settings; - let mut todo_remove = None; - match event { ServerEvent::Explosion { pos, radius } => { const RAYS: usize = 500; @@ -380,19 +380,20 @@ impl Server { } ServerEvent::Destroy { entity, cause } => { - let ecs = state.ecs(); // Chat message - if let Some(player) = ecs.read_storage::().get(entity) { + if let Some(player) = state.ecs().read_storage::().get(entity) { let msg = if let comp::HealthSource::Attack { by } = cause { - ecs.entity_from_uid(by.into()).and_then(|attacker| { - ecs.read_storage::().get(attacker).map( - |attacker_alias| { + state.ecs().entity_from_uid(by.into()).and_then(|attacker| { + state + .ecs() + .read_storage::() + .get(attacker) + .map(|attacker_alias| { format!( "{} was killed by {}", &player.alias, &attacker_alias.alias ) - }, - ) + }) }) } else { None @@ -402,28 +403,44 @@ impl Server { state.notify_registered_clients(ServerMsg::kill(msg)); } - // Give EXP to the killer if entity had stats - let mut stats = ecs.write_storage::(); - - if let Some(entity_stats) = stats.get(entity).cloned() { - if let comp::HealthSource::Attack { by } = cause { - ecs.entity_from_uid(by.into()).map(|attacker| { - if let Some(attacker_stats) = stats.get_mut(attacker) { - // TODO: Discuss whether we should give EXP by Player Killing or not. - attacker_stats - .exp - .change_by((entity_stats.level.level() * 10) as i64); - } - }); + { + // Give EXP to the killer if entity had stats + let mut stats = state.ecs().write_storage::(); + if let Some(entity_stats) = stats.get(entity).cloned() { + if let comp::HealthSource::Attack { by } = cause { + state.ecs().entity_from_uid(by.into()).map(|attacker| { + if let Some(attacker_stats) = stats.get_mut(attacker) { + // TODO: Discuss whether we should give EXP by Player Killing or not. + attacker_stats + .exp + .change_by((entity_stats.level.level() * 10) as i64); + } + }); + } } } - if let Some(client) = ecs.write_storage::().get_mut(entity) { - let _ = ecs.write_storage().insert(entity, comp::Vel(Vec3::zero())); - let _ = ecs.write_storage().insert(entity, comp::ForceUpdate); + // This sucks + let mut remove = false; + + if let Some(client) = state.ecs().write_storage::().get_mut(entity) { + let _ = state + .ecs() + .write_storage() + .insert(entity, comp::Vel(Vec3::zero())); + let _ = state + .ecs() + .write_storage() + .insert(entity, comp::ForceUpdate); client.force_state(ClientState::Dead); } else { - todo_remove = Some(entity.clone()); + remove = true; + } + + if remove { + if let Err(err) = state.delete_entity_recorded(entity) { + error!("Failed to delete destroyed entity: {:?}", err); + } } } @@ -457,7 +474,9 @@ impl Server { }; if let Some(item_entity) = item_entity { - let _ = state.ecs_mut().delete_entity(item_entity); + if let Err(err) = state.delete_entity_recorded(item_entity) { + error!("Failed to delete picked up item entity: {:?}", err); + } } state.write_component(entity, comp::InventoryUpdate); @@ -728,7 +747,7 @@ impl Server { main, &server_settings, ); - Self::initialize_region_subscription(state, entity); + sys::subscription::initialize_region_subscription(state.ecs(), entity); } ServerEvent::CreateNpc { @@ -746,8 +765,8 @@ impl Server { } ServerEvent::ClientDisconnect(entity) => { - if let Err(err) = state.ecs_mut().delete_entity(entity) { - debug!("Failed to delete disconnected client: {:?}", err); + if let Err(err) = state.delete_entity_recorded(entity) { + error!("Failed to delete disconnected client: {:?}", err); } frontend_events.push(Event::ClientDisconnected { entity }); @@ -761,11 +780,6 @@ impl Server { chat_commands.push((entity, cmd)); } } - - // TODO: is this needed? - if let Some(entity) = todo_remove { - let _ = state.ecs_mut().delete_entity(entity); - } } // Generate requested chunks. @@ -825,7 +839,7 @@ impl Server { frontend_events.append(&mut self.handle_new_connections()?); let before_tick_4 = Instant::now(); - // 4) Tick the client's LocalState. + // 4) Tick the server's LocalState. self.state.tick(dt, sys::add_server_systems); let before_handle_events = Instant::now(); @@ -856,7 +870,9 @@ impl Server { .collect::>() }; for entity in to_delete { - let _ = self.state.ecs_mut().delete_entity(entity); + if let Err(err) = self.state.delete_entity_recorded(entity) { + error!("Failed to delete agent outside the terrain: {:?}", err); + } } let before_tick_7 = Instant::now(); @@ -1004,83 +1020,6 @@ impl Server { Ok(frontend_events) } - /// Initialize region subscription - fn initialize_region_subscription(state: &mut State, entity: specs::Entity) { - let mut subscription = None; - - if let (Some(client_pos), Some(client_vd), Some(client)) = ( - state.ecs().read_storage::().get(entity), - state - .ecs() - .read_storage::() - .get(entity) - .map(|pl| pl.view_distance) - .and_then(|v| v), - state.ecs().write_storage::().get_mut(entity), - ) { - use common::region::RegionMap; - - let fuzzy_chunk = (Vec2::::from(client_pos.0)) - .map2(TerrainChunkSize::RECT_SIZE, |e, sz| e as i32 / sz as i32); - let chunk_size = TerrainChunkSize::RECT_SIZE.reduce_max() as f32; - let regions = common::region::regions_in_vd( - client_pos.0, - (client_vd as f32 * chunk_size) as f32 - + (client::CHUNK_FUZZ as f32 + chunk_size) * 2.0f32.sqrt(), - ); - - for (_, region) in state - .ecs() - .read_resource::() - .iter() - .filter(|(key, _)| regions.contains(key)) - { - // Sync physics of all entities in this region - for (&uid, &pos, vel, ori, character_state, _) in ( - &state.ecs().read_storage::(), - &state.ecs().read_storage::(), // We assume all these entities have a position - state.ecs().read_storage::().maybe(), - state.ecs().read_storage::().maybe(), - state.ecs().read_storage::().maybe(), - region.entities(), - ) - .join() - { - client.notify(ServerMsg::EntityPos { - entity: uid.into(), - pos, - }); - if let Some(vel) = vel.copied() { - client.notify(ServerMsg::EntityVel { - entity: uid.into(), - vel, - }); - } - if let Some(ori) = ori.copied() { - client.notify(ServerMsg::EntityOri { - entity: uid.into(), - ori, - }); - } - if let Some(character_state) = character_state.copied() { - client.notify(ServerMsg::EntityCharacterState { - entity: uid.into(), - character_state, - }); - } - } - } - - subscription = Some(RegionSubscription { - fuzzy_chunk, - regions, - }); - } - if let Some(subscription) = subscription { - state.write_component(entity, subscription); - } - } - pub fn notify_client(&self, entity: EcsEntity, msg: ServerMsg) { if let Some(client) = self.state.ecs().write_storage::().get_mut(entity) { client.notify(msg) @@ -1142,6 +1081,10 @@ trait StateExt { stats: comp::Stats, body: comp::Body, ) -> EcsEntityBuilder; + fn delete_entity_recorded( + &mut self, + entity: EcsEntity, + ) -> Result<(), specs::error::WrongGeneration>; } impl StateExt for State { @@ -1202,4 +1145,28 @@ impl StateExt for State { client.notify(msg.clone()) } } + + fn delete_entity_recorded( + &mut self, + entity: EcsEntity, + ) -> Result<(), specs::error::WrongGeneration> { + let (maybe_uid, maybe_pos) = ( + self.ecs().read_storage::().get(entity).copied(), + self.ecs().read_storage::().get(entity).copied(), + ); + let res = self.ecs_mut().delete_entity(entity); + if res.is_ok() { + if let (Some(uid), Some(pos)) = (maybe_uid, maybe_pos) { + let region_key = self + .ecs() + .read_resource::() + .find_region(entity, pos.0) + .expect("Failed to find region containing entity during entity deletion"); + self.ecs() + .write_resource::() + .record_deleted_entity(uid, region_key); + } + } + res + } } diff --git a/server/src/sys/entity_sync.rs b/server/src/sys/entity_sync.rs index 05611359b6..7bb94fb3a5 100644 --- a/server/src/sys/entity_sync.rs +++ b/server/src/sys/entity_sync.rs @@ -1,5 +1,5 @@ use super::{ - sentinel::{ReadTrackers, TrackedComps, TrackedResources}, + sentinel::{DeletedEntities, ReadTrackers, TrackedComps, TrackedResources}, SysTimer, }; use crate::{ @@ -38,6 +38,7 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, Client>, WriteStorage<'a, ForceUpdate>, WriteStorage<'a, InventoryUpdate>, + Write<'a, DeletedEntities>, TrackedComps<'a>, ReadTrackers<'a>, TrackedResources<'a>, @@ -64,8 +65,9 @@ impl<'a> System<'a> for Sys { mut clients, mut force_updates, mut inventory_updates, + mut deleted_entities, tracked_comps, - read_trackers, + trackers, tracked_resources, ): Self::SystemData, ) { @@ -86,6 +88,8 @@ impl<'a> System<'a> for Sys { // Sync physics // via iterating through regions for (key, region) in region_map.iter() { + // Assemble subscriber list for this region by iterating through clients and checking + // if they are subscribed to this region let mut subscribers = (&mut clients, &entities, &subscriptions, &positions) .join() .filter_map(|(client, entity, subscription, pos)| { @@ -100,6 +104,10 @@ impl<'a> System<'a> for Sys { for event in region.events() { match event { RegionEvent::Entered(id, maybe_key) => { + // Don't process newly created entities here (redundant network messages) + if trackers.uid.inserted().contains(*id) { + continue; + } let entity = entities.entity(*id); if let Some((uid, pos, vel, ori, character_state)) = uids.get(entity).and_then(|uid| { @@ -156,8 +164,15 @@ impl<'a> System<'a> for Sys { } // Sync tracked components + // Get deleted entities in this region from DeletedEntities let sync_msg = ServerMsg::EcsSync( - read_trackers.create_sync_package(&tracked_comps, region.entities()), + trackers.create_sync_package( + &tracked_comps, + region.entities(), + deleted_entities + .take_deleted_in_region(key) + .unwrap_or_else(|| Vec::new()), + ), ); for (client, _, _, _) in &mut subscribers { client.notify(sync_msg.clone()); @@ -169,9 +184,9 @@ impl<'a> System<'a> for Sys { force_update: Option<&ForceUpdate>, throttle: bool| { for (client, _, client_entity, client_pos) in &mut subscribers { - let update = if client_entity == &entity && force_update.is_none() { - // Don't send client physics update about itself - false + let update = if client_entity == &entity { + // Don't send client physics updates about itself unless force update is set + force_update.is_some() } else if !throttle { // Update rate not thottled by distance true @@ -283,6 +298,25 @@ impl<'a> System<'a> for Sys { } } + // Handle entity deletion in regions that don't exist in RegionMap (theoretically none) + for (region_key, deleted) in deleted_entities.take_remaining_deleted() { + for client in + (&mut clients, &subscriptions) + .join() + .filter_map(|(client, subscription)| { + if client.is_ingame() && subscription.regions.contains(®ion_key) { + Some(client) + } else { + None + } + }) + { + for uid in &deleted { + client.notify(ServerMsg::DeleteEntity(*uid)); + } + } + } + // TODO: Sync clients that don't have a position? // Sync inventories diff --git a/server/src/sys/message.rs b/server/src/sys/message.rs index e4cdde00b2..6537e4e01a 100644 --- a/server/src/sys/message.rs +++ b/server/src/sys/message.rs @@ -1,7 +1,7 @@ use super::SysTimer; use crate::{auth_provider::AuthProvider, client::Client, CLIENT_TIMEOUT}; use common::{ - comp::{Admin, Body, CanBuild, Controller, Ori, Player, Pos, Vel}, + comp::{Admin, Body, CanBuild, Controller, ForceUpdate, Ori, Player, Pos, Vel}, event::{EventBus, ServerEvent}, msg::{validate_chat_msg, ChatMsgValidationError, MAX_BYTES_CHAT_MSG}, msg::{ClientMsg, ClientState, RequestStateError, ServerMsg}, @@ -25,6 +25,7 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Body>, ReadStorage<'a, CanBuild>, ReadStorage<'a, Admin>, + ReadStorage<'a, ForceUpdate>, WriteExpect<'a, AuthProvider>, Write<'a, BlockChange>, WriteStorage<'a, Pos>, @@ -46,6 +47,7 @@ impl<'a> System<'a> for Sys { bodies, can_build, admins, + force_updates, mut accounts, mut block_changes, mut positions, @@ -218,9 +220,11 @@ impl<'a> System<'a> for Sys { }, ClientMsg::PlayerPhysics { pos, vel, ori } => match client.client_state { ClientState::Character => { - let _ = positions.insert(entity, pos); - let _ = velocities.insert(entity, vel); - let _ = orientations.insert(entity, ori); + if force_updates.get(entity).is_none() { + let _ = positions.insert(entity, pos); + let _ = velocities.insert(entity, vel); + let _ = orientations.insert(entity, ori); + } } // Only characters can send positions. _ => client.error_state(RequestStateError::Impossible), diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs index a3a0f3ba33..381f567ea7 100644 --- a/server/src/sys/sentinel.rs +++ b/server/src/sys/sentinel.rs @@ -5,17 +5,19 @@ use common::{ Projectile, Scale, Stats, Sticky, }, msg::{EcsCompPacket, EcsResPacket}, - state::{Time, TimeOfDay}, + state::TimeOfDay, sync::{ CompPacket, EntityPackage, ResSyncPackage, StatePackage, SyncPackage, Uid, UpdateTracker, WorldSyncExt, }, }; +use hashbrown::HashMap; use shred_derive::SystemData; use specs::{ Entity as EcsEntity, Join, ReadExpect, ReadStorage, System, World, Write, WriteExpect, }; use std::ops::Deref; +use vek::*; /// Always watching /// This system will monitor specific components for insertion, removal, and modification @@ -39,20 +41,20 @@ impl<'a> System<'a> for Sys { // Probably more difficult than it needs to be :p #[derive(SystemData)] pub struct TrackedComps<'a> { - uid: ReadStorage<'a, Uid>, - body: ReadStorage<'a, Body>, - player: ReadStorage<'a, Player>, - stats: ReadStorage<'a, Stats>, - can_build: ReadStorage<'a, CanBuild>, - light_emitter: ReadStorage<'a, LightEmitter>, - item: ReadStorage<'a, Item>, - scale: ReadStorage<'a, Scale>, - mounting: ReadStorage<'a, Mounting>, - mount_state: ReadStorage<'a, MountState>, - mass: ReadStorage<'a, Mass>, - sticky: ReadStorage<'a, Sticky>, - gravity: ReadStorage<'a, Gravity>, - projectile: ReadStorage<'a, Projectile>, + pub uid: ReadStorage<'a, Uid>, + pub body: ReadStorage<'a, Body>, + pub player: ReadStorage<'a, Player>, + pub stats: ReadStorage<'a, Stats>, + pub can_build: ReadStorage<'a, CanBuild>, + pub light_emitter: ReadStorage<'a, LightEmitter>, + pub item: ReadStorage<'a, Item>, + pub scale: ReadStorage<'a, Scale>, + pub mounting: ReadStorage<'a, Mounting>, + pub mount_state: ReadStorage<'a, MountState>, + pub mass: ReadStorage<'a, Mass>, + pub sticky: ReadStorage<'a, Sticky>, + pub gravity: ReadStorage<'a, Gravity>, + pub projectile: ReadStorage<'a, Projectile>, } impl<'a> TrackedComps<'a> { pub fn create_entity_package(&self, entity: EcsEntity) -> EntityPackage { @@ -121,115 +123,53 @@ impl<'a> TrackedComps<'a> { } #[derive(SystemData)] pub struct ReadTrackers<'a> { - uid: ReadExpect<'a, UpdateTracker>, - body: ReadExpect<'a, UpdateTracker>, - player: ReadExpect<'a, UpdateTracker>, - stats: ReadExpect<'a, UpdateTracker>, - can_build: ReadExpect<'a, UpdateTracker>, - light_emitter: ReadExpect<'a, UpdateTracker>, - item: ReadExpect<'a, UpdateTracker>, - scale: ReadExpect<'a, UpdateTracker>, - mounting: ReadExpect<'a, UpdateTracker>, - mount_state: ReadExpect<'a, UpdateTracker>, - mass: ReadExpect<'a, UpdateTracker>, - sticky: ReadExpect<'a, UpdateTracker>, - gravity: ReadExpect<'a, UpdateTracker>, - projectile: ReadExpect<'a, UpdateTracker>, + pub uid: ReadExpect<'a, UpdateTracker>, + pub body: ReadExpect<'a, UpdateTracker>, + pub player: ReadExpect<'a, UpdateTracker>, + pub stats: ReadExpect<'a, UpdateTracker>, + pub can_build: ReadExpect<'a, UpdateTracker>, + pub light_emitter: ReadExpect<'a, UpdateTracker>, + pub item: ReadExpect<'a, UpdateTracker>, + pub scale: ReadExpect<'a, UpdateTracker>, + pub mounting: ReadExpect<'a, UpdateTracker>, + pub mount_state: ReadExpect<'a, UpdateTracker>, + pub mass: ReadExpect<'a, UpdateTracker>, + pub sticky: ReadExpect<'a, UpdateTracker>, + pub gravity: ReadExpect<'a, UpdateTracker>, + pub projectile: ReadExpect<'a, UpdateTracker>, } impl<'a> ReadTrackers<'a> { pub fn create_sync_package( &self, comps: &TrackedComps, filter: impl Join + Copy, + deleted_entities: Vec, ) -> SyncPackage { - SyncPackage::new(&comps.uid, &self.uid, filter) + SyncPackage::new(&comps.uid, &self.uid, filter, deleted_entities) + .with_component(&comps.uid, self.body.deref(), &comps.body, filter) + .with_component(&comps.uid, self.player.deref(), &comps.player, filter) + .with_component(&comps.uid, self.stats.deref(), &comps.stats, filter) + .with_component(&comps.uid, self.can_build.deref(), &comps.can_build, filter) .with_component( &comps.uid, - &self.uid, - self.body.deref(), - &comps.body, - filter, - ) - .with_component( - &comps.uid, - &self.uid, - self.player.deref(), - &comps.player, - filter, - ) - .with_component( - &comps.uid, - &self.uid, - self.stats.deref(), - &comps.stats, - filter, - ) - .with_component( - &comps.uid, - &self.uid, - self.can_build.deref(), - &comps.can_build, - filter, - ) - .with_component( - &comps.uid, - &self.uid, self.light_emitter.deref(), &comps.light_emitter, filter, ) + .with_component(&comps.uid, self.item.deref(), &comps.item, filter) + .with_component(&comps.uid, self.scale.deref(), &comps.scale, filter) + .with_component(&comps.uid, self.mounting.deref(), &comps.mounting, filter) .with_component( &comps.uid, - &self.uid, - self.item.deref(), - &comps.item, - filter, - ) - .with_component( - &comps.uid, - &self.uid, - self.scale.deref(), - &comps.scale, - filter, - ) - .with_component( - &comps.uid, - &self.uid, - self.mounting.deref(), - &comps.mounting, - filter, - ) - .with_component( - &comps.uid, - &self.uid, self.mount_state.deref(), &comps.mount_state, filter, ) + .with_component(&comps.uid, self.mass.deref(), &comps.mass, filter) + .with_component(&comps.uid, self.sticky.deref(), &comps.sticky, filter) + .with_component(&comps.uid, self.gravity.deref(), &comps.gravity, filter) .with_component( &comps.uid, - &self.uid, - self.mass.deref(), - &comps.mass, - filter, - ) - .with_component( - &comps.uid, - &self.uid, - self.sticky.deref(), - &comps.sticky, - filter, - ) - .with_component( - &comps.uid, - &self.uid, - self.gravity.deref(), - &comps.gravity, - filter, - ) - .with_component( - &comps.uid, - &self.uid, self.projectile.deref(), &comps.projectile, filter, @@ -292,19 +232,46 @@ pub fn register_trackers(world: &mut World) { #[derive(SystemData)] pub struct TrackedResources<'a> { - time: ReadExpect<'a, Time>, time_of_day: ReadExpect<'a, TimeOfDay>, } impl<'a> TrackedResources<'a> { pub fn create_res_sync_package(&self) -> ResSyncPackage { - ResSyncPackage::new() - .with_res(self.time.deref()) - .with_res(self.time_of_day.deref()) + ResSyncPackage::new().with_res(self.time_of_day.deref()) } /// Create state package with resources included pub fn state_package(&self) -> StatePackage { - StatePackage::new() - .with_res(self.time.deref()) - .with_res(self.time_of_day.deref()) + StatePackage::new().with_res(self.time_of_day.deref()) + } +} + +/// Deleted entities grouped by region +pub struct DeletedEntities { + map: HashMap, Vec>, +} + +impl Default for DeletedEntities { + fn default() -> Self { + Self { + map: HashMap::new(), + } + } +} + +impl DeletedEntities { + pub fn record_deleted_entity(&mut self, uid: Uid, region_key: Vec2) { + self.map + .entry(region_key) + .or_insert(Vec::new()) + .push(uid.into()); + } + pub fn take_deleted_in_region(&mut self, key: Vec2) -> Option> { + self.map.remove(&key) + } + pub fn get_deleted_in_region(&mut self, key: Vec2) -> Option<&Vec> { + self.map.get(&key) + } + pub fn take_remaining_deleted(&mut self) -> Vec<(Vec2, Vec)> { + // TODO: don't allocate + self.map.drain().collect() } } diff --git a/server/src/sys/subscription.rs b/server/src/sys/subscription.rs index d4617fd499..a37d4057b7 100644 --- a/server/src/sys/subscription.rs +++ b/server/src/sys/subscription.rs @@ -1,4 +1,7 @@ -use super::{sentinel::TrackedComps, SysTimer}; +use super::{ + sentinel::{DeletedEntities, TrackedComps}, + SysTimer, +}; use crate::client::{self, Client, RegionSubscription}; use common::{ comp::{CharacterState, Ori, Player, Pos, Vel}, @@ -8,7 +11,10 @@ use common::{ terrain::TerrainChunkSize, vol::RectVolSize, }; -use specs::{Entities, Join, ReadExpect, ReadStorage, System, Write, WriteStorage}; +use log::{debug, error}; +use specs::{ + Entities, Join, ReadExpect, ReadStorage, System, SystemData, World, Write, WriteStorage, +}; use vek::*; /// This system will update region subscriptions based on client positions @@ -26,6 +32,7 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Player>, WriteStorage<'a, Client>, WriteStorage<'a, RegionSubscription>, + Write<'a, DeletedEntities>, TrackedComps<'a>, ); @@ -43,6 +50,7 @@ impl<'a> System<'a> for Sys { players, mut clients, mut subscriptions, + mut deleted_entities, tracked_comps, ): Self::SystemData, ) { @@ -68,8 +76,15 @@ impl<'a> System<'a> for Sys { &entities, ) .join() - .filter_map(|(c, s, pos, player, e)| player.view_distance.map(|v| (c, s, pos, v, e))) + .filter_map(|(client, s, pos, player, e)| { + if client.is_ingame() { + player.view_distance.map(|v| (client, s, pos, v, e)) + } else { + None + } + }) { + // Calculate current chunk let chunk = (Vec2::::from(pos.0)) .map2(TerrainChunkSize::RECT_SIZE, |e, sz| e as i32 / sz as i32); // Only update regions when moving to a new chunk @@ -87,7 +102,7 @@ impl<'a> System<'a> for Sys { .reduce_or() { // Update current chunk - subscription.fuzzy_chunk = (Vec2::::from(pos.0)) + subscription.fuzzy_chunk = dbg!(Vec2::::from(pos.0)) .map2(TerrainChunkSize::RECT_SIZE, |e, sz| e as i32 / sz as i32); // Use the largest side length as our chunk size let chunk_size = TerrainChunkSize::RECT_SIZE.reduce_max() as f32; @@ -108,19 +123,24 @@ impl<'a> System<'a> for Sys { // Iterate through regions to remove for key in regions_to_remove.drain(..) { - // Remove region from this clients set of subscribed regions + // Remove region from this client's set of subscribed regions subscription.regions.remove(&key); // Tell the client to delete the entities in that region if it exists in the RegionMap if let Some(region) = region_map.get(key) { - // Process entity left events since they won't be processed during phsyics sync because this region is no longer subscribed to + // Process entity left events since they won't be processed during entity sync because this region is no longer subscribed to + // TODO: consider changing system ordering?? for event in region.events() { match event { RegionEvent::Entered(_, _) => {} // These don't need to be processed because this region is being thrown out anyway RegionEvent::Left(id, maybe_key) => { // Lookup UID for entity + // Doesn't overlap with entity deletion in sync packages + // because the uid would not be available if the entity was + // deleted if let Some(&uid) = uids.get(entities.entity(*id)) { if !maybe_key .as_ref() + // Don't need to check that this isn't also in the regions to remove since the entity will be removed when we get to that one .map(|key| subscription.regions.contains(key)) .unwrap_or(false) { @@ -130,10 +150,19 @@ impl<'a> System<'a> for Sys { } } } + // Tell client to delete entities in the region for (&uid, _) in (&uids, region.entities()).join() { - client.notify(ServerMsg::DeleteEntity(uid.into())) + client.notify(ServerMsg::DeleteEntity(uid.into())); } } + // Send deleted entities since they won't be processed for this client in entity sync + for uid in deleted_entities + .get_deleted_in_region(key) + .iter() + .flat_map(|v| v.iter()) + { + client.notify(ServerMsg::DeleteEntity(*uid)); + } } for key in regions_in_vd( @@ -141,8 +170,10 @@ impl<'a> System<'a> for Sys { (vd as f32 * chunk_size) + (client::CHUNK_FUZZ as f32 + chunk_size) * 2.0f32.sqrt(), ) { - // Send client intial info about the entities in this region - if subscription.regions.insert(key) { + // Send client intial info about the entities in this region if it was not + // already within the set of subscribed regions + if subscription.regions.insert(key.clone()) { + let mut counter = 0; if let Some(region) = region_map.get(key) { for (uid, pos, vel, ori, character_state, _, entity) in ( &uids, @@ -156,6 +187,7 @@ impl<'a> System<'a> for Sys { .join() .filter(|(_, _, _, _, _, _, e)| *e != client_entity) { + counter += 1; // Send message to create entity and tracked components client.notify(ServerMsg::CreateEntity( tracked_comps.create_entity_package(entity), @@ -179,3 +211,69 @@ impl<'a> System<'a> for Sys { timer.end(); } } + +/// Initialize region subscription +pub fn initialize_region_subscription(world: &World, entity: specs::Entity) { + if let (Some(client_pos), Some(client_vd), Some(client)) = ( + world.read_storage::().get(entity), + world + .read_storage::() + .get(entity) + .map(|pl| pl.view_distance) + .and_then(|v| v), + world.write_storage::().get_mut(entity), + ) { + let fuzzy_chunk = (Vec2::::from(client_pos.0)) + .map2(TerrainChunkSize::RECT_SIZE, |e, sz| e as i32 / sz as i32); + let chunk_size = TerrainChunkSize::RECT_SIZE.reduce_max() as f32; + let regions = common::region::regions_in_vd( + client_pos.0, + (client_vd as f32 * chunk_size) as f32 + + (client::CHUNK_FUZZ as f32 + chunk_size) * 2.0f32.sqrt(), + ); + + let region_map = world.read_resource::(); + let tracked_comps = TrackedComps::fetch(&world.res); + for key in ®ions { + if let Some(region) = region_map.get(*key) { + for (uid, pos, vel, ori, character_state, _, entity) in ( + &tracked_comps.uid, + &world.read_storage::(), // We assume all these entities have a position + world.read_storage::().maybe(), + world.read_storage::().maybe(), + world.read_storage::().maybe(), + region.entities(), + &world.entities(), + ) + .join() + { + // Send message to create entity and tracked components + client.notify(ServerMsg::CreateEntity( + tracked_comps.create_entity_package(entity), + )); + // Send message to create physics components + super::entity_sync::send_initial_unsynced_components( + client, + uid, + pos, + vel, + ori, + character_state, + ); + } + } + } + + if let Err(err) = world.write_storage().insert( + entity, + RegionSubscription { + fuzzy_chunk, + regions, + }, + ) { + error!("Failed to insert region subscription component: {:?}", err); + } + } else { + debug!("Failed to initialize region subcription. Couldn't retrieve all the neccesary components on the provided entity"); + } +} diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 3c4308356e..da4b978067 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -112,6 +112,7 @@ widget_ids! { velocity, loaded_distance, time, + entity_count, // Game Version version, @@ -872,11 +873,19 @@ impl Hud { .font_id(self.fonts.cyri) .font_size(14) .set(self.ids.time, ui_widgets); + // Number of entities + let entity_count = client.state().ecs().entities().join().count(); + Text::new(&format!("Entity count: {}", entity_count)) + .color(TEXT_COLOR) + .down_from(self.ids.time, 5.0) + .font_id(self.fonts.cyri) + .font_size(14) + .set(self.ids.entity_count, ui_widgets); // Help Window Text::new("Press 'F1' to show Keybindings") .color(TEXT_COLOR) - .down_from(self.ids.time, 5.0) + .down_from(self.ids.entity_count, 5.0) .font_id(self.fonts.cyri) .font_size(14) .set(self.ids.help_info, ui_widgets); diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index ce7a484676..2ade596ad0 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -324,7 +324,7 @@ impl WorldSim { let logistic_cdf = |x: f64| (x / logistic_2_base).tanh() * 0.5 + 0.5; let erosion_pow = 2.0; - let n_steps = 100; + let n_steps = 7; let erosion_factor = |x: f64| logistic_cdf(erosion_pow * logit(x)); let alt = do_erosion( 0.0, From c3ac251fa81fa384b012f51a425bbc1efb3497c4 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 30 Nov 2019 00:33:17 -0500 Subject: [PATCH 09/51] Stop syncing Projectile component to the client --- common/src/msg/ecs_packet.rs | 20 ++++++---- common/src/state.rs | 4 +- common/src/sync/packet.rs | 11 ------ common/src/sys/phys.rs | 3 +- server/src/sys/sentinel.rs | 68 ++++++++++++++++------------------ server/src/sys/subscription.rs | 4 +- 6 files changed, 49 insertions(+), 61 deletions(-) diff --git a/common/src/msg/ecs_packet.rs b/common/src/msg/ecs_packet.rs index 28964041ab..4dd487de70 100644 --- a/common/src/msg/ecs_packet.rs +++ b/common/src/msg/ecs_packet.rs @@ -3,19 +3,25 @@ use serde_derive::{Deserialize, Serialize}; use std::marker::PhantomData; use sum_type::sum_type; +// TODO: remove me +#[derive(Clone, Debug, Serialize, Deserialize)] +pub enum MustHaveMoreThanOneVariant {} + // Automatically derive From for EcsResPacket // for each variant EcsResPacket::T(T). sum_type! { #[derive(Clone, Debug, Serialize, Deserialize)] pub enum EcsResPacket { - Time(state::Time), + //Time(state::Time), + MustHaveMoreThanOneVariant(MustHaveMoreThanOneVariant), TimeOfDay(state::TimeOfDay), } } impl sync::ResPacket for EcsResPacket { fn apply(self, world: &specs::World) { match self { - EcsResPacket::Time(time) => sync::handle_res_update(time, world), + //EcsResPacket::Time(time) => sync::handle_res_update(time, world), + EcsResPacket::MustHaveMoreThanOneVariant(_) => unimplemented!(), EcsResPacket::TimeOfDay(time_of_day) => sync::handle_res_update(time_of_day, world), } } @@ -35,7 +41,7 @@ sum_type! { MountState(comp::MountState), Mounting(comp::Mounting), Mass(comp::Mass), - Projectile(comp::Projectile), + //Projectile(comp::Projectile), Gravity(comp::Gravity), Sticky(comp::Sticky), } @@ -55,7 +61,7 @@ sum_type! { MountState(PhantomData), Mounting(PhantomData), Mass(PhantomData), - Projectile(PhantomData), + //Projectile(PhantomData), Gravity(PhantomData), Sticky(PhantomData), } @@ -74,7 +80,7 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPacket::MountState(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Mounting(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Mass(comp) => sync::handle_insert(comp, entity, world), - EcsCompPacket::Projectile(comp) => sync::handle_insert(comp, entity, world), + //EcsCompPacket::Projectile(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Gravity(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Sticky(comp) => sync::handle_insert(comp, entity, world), } @@ -91,7 +97,7 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPacket::MountState(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Mounting(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Mass(comp) => sync::handle_modify(comp, entity, world), - EcsCompPacket::Projectile(comp) => sync::handle_modify(comp, entity, world), + //EcsCompPacket::Projectile(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Gravity(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Sticky(comp) => sync::handle_modify(comp, entity, world), } @@ -110,7 +116,7 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPhantom::MountState(_) => sync::handle_remove::(entity, world), EcsCompPhantom::Mounting(_) => sync::handle_remove::(entity, world), EcsCompPhantom::Mass(_) => sync::handle_remove::(entity, world), - EcsCompPhantom::Projectile(_) => sync::handle_remove::(entity, world), + //EcsCompPhantom::Projectile(_) => sync::handle_remove::(entity, world), EcsCompPhantom::Gravity(_) => sync::handle_remove::(entity, world), EcsCompPhantom::Sticky(_) => sync::handle_remove::(entity, world), } diff --git a/common/src/state.rs b/common/src/state.rs index a2120e60c6..af8ac3841b 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -119,7 +119,6 @@ impl State { ecs.register::(); ecs.register::(); ecs.register::(); - ecs.register::(); // Register components send from clients -> server ecs.register::(); @@ -143,9 +142,9 @@ impl State { ecs.register::(); ecs.register::(); ecs.register::(); - ecs.register::(); ecs.register::(); ecs.register::(); + ecs.register::(); // Register synced resources used by the ECS. ecs.add_resource(TimeOfDay(0.0)); @@ -156,6 +155,7 @@ impl State { ecs.add_resource(TerrainGrid::new().unwrap()); ecs.add_resource(BlockChange::default()); ecs.add_resource(TerrainChanges::default()); + // TODO: only register on the server ecs.add_resource(EventBus::::default()); ecs.add_resource(EventBus::::default()); ecs.add_resource(EventBus::::default()); diff --git a/common/src/sync/packet.rs b/common/src/sync/packet.rs index f12d409960..08c1d339e8 100644 --- a/common/src/sync/packet.rs +++ b/common/src/sync/packet.rs @@ -112,17 +112,6 @@ impl SyncPackage

{ .join() .map(|(uid, _, _)| (*uid).into()) .collect(); - // TODO: handle modified uid? - //created_entities.append(&mut (uids, filter, uid_tracker.inserted()).join().map(|(uid, _, _)| uid).collect()); - // let deleted_entities = (uids.maybe(), filter, uid_tracker.removed()) - // .join() - // Why doesn't this panic?? - // .map(|(uid, _, _)| Into::::into(*uid.unwrap())) - // .collect::>(); - //let len = deleted_entities.len(); - //if len > 0 { - // println!("deleted {} in sync message", len); - // } Self { comp_updates: Vec::new(), diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index d0a9f133a9..4b1b89d62b 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -342,13 +342,14 @@ impl<'a> System<'a> for Sys { } // Apply pushback - for (pos, scale, mass, vel, _, _, physics) in ( + for (pos, scale, mass, vel, _, _, _, physics) in ( &positions, scales.maybe(), masses.maybe(), &mut velocities, &bodies, !&mountings, + !&stickies, // Can't push stickies around &mut physics_states, ) .join() diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs index 381f567ea7..bb59f42edf 100644 --- a/server/src/sys/sentinel.rs +++ b/server/src/sys/sentinel.rs @@ -1,8 +1,8 @@ use super::SysTimer; use common::{ comp::{ - Body, CanBuild, Gravity, Item, LightEmitter, Mass, MountState, Mounting, Player, - Projectile, Scale, Stats, Sticky, + Body, CanBuild, Gravity, Item, LightEmitter, Mass, MountState, Mounting, Player, Scale, + Stats, Sticky, }, msg::{EcsCompPacket, EcsResPacket}, state::TimeOfDay, @@ -16,7 +16,6 @@ use shred_derive::SystemData; use specs::{ Entity as EcsEntity, Join, ReadExpect, ReadStorage, System, World, Write, WriteExpect, }; -use std::ops::Deref; use vek::*; /// Always watching @@ -54,7 +53,7 @@ pub struct TrackedComps<'a> { pub mass: ReadStorage<'a, Mass>, pub sticky: ReadStorage<'a, Sticky>, pub gravity: ReadStorage<'a, Gravity>, - pub projectile: ReadStorage<'a, Projectile>, + //pub projectile: ReadStorage<'a, Projectile>, } impl<'a> TrackedComps<'a> { pub fn create_entity_package(&self, entity: EcsEntity) -> EntityPackage { @@ -113,10 +112,10 @@ impl<'a> TrackedComps<'a> { .get(entity) .copied() .map(|c| packets.push(c.into())); - self.projectile - .get(entity) - .cloned() - .map(|c| packets.push(c.into())); + //self.projectile + // .get(entity) + // .cloned() + // .map(|c| packets.push(c.into())); EntityPackage(uid, packets) } @@ -136,7 +135,7 @@ pub struct ReadTrackers<'a> { pub mass: ReadExpect<'a, UpdateTracker>, pub sticky: ReadExpect<'a, UpdateTracker>, pub gravity: ReadExpect<'a, UpdateTracker>, - pub projectile: ReadExpect<'a, UpdateTracker>, + //pub projectile: ReadExpect<'a, UpdateTracker>, } impl<'a> ReadTrackers<'a> { pub fn create_sync_package( @@ -146,34 +145,29 @@ impl<'a> ReadTrackers<'a> { deleted_entities: Vec, ) -> SyncPackage { SyncPackage::new(&comps.uid, &self.uid, filter, deleted_entities) - .with_component(&comps.uid, self.body.deref(), &comps.body, filter) - .with_component(&comps.uid, self.player.deref(), &comps.player, filter) - .with_component(&comps.uid, self.stats.deref(), &comps.stats, filter) - .with_component(&comps.uid, self.can_build.deref(), &comps.can_build, filter) + .with_component(&comps.uid, &*self.body, &comps.body, filter) + .with_component(&comps.uid, &*self.player, &comps.player, filter) + .with_component(&comps.uid, &*self.stats, &comps.stats, filter) + .with_component(&comps.uid, &*self.can_build, &comps.can_build, filter) .with_component( &comps.uid, - self.light_emitter.deref(), + &*self.light_emitter, &comps.light_emitter, filter, ) - .with_component(&comps.uid, self.item.deref(), &comps.item, filter) - .with_component(&comps.uid, self.scale.deref(), &comps.scale, filter) - .with_component(&comps.uid, self.mounting.deref(), &comps.mounting, filter) - .with_component( - &comps.uid, - self.mount_state.deref(), - &comps.mount_state, - filter, - ) - .with_component(&comps.uid, self.mass.deref(), &comps.mass, filter) - .with_component(&comps.uid, self.sticky.deref(), &comps.sticky, filter) - .with_component(&comps.uid, self.gravity.deref(), &comps.gravity, filter) - .with_component( - &comps.uid, - self.projectile.deref(), - &comps.projectile, - filter, - ) + .with_component(&comps.uid, &*self.item, &comps.item, filter) + .with_component(&comps.uid, &*self.scale, &comps.scale, filter) + .with_component(&comps.uid, &*self.mounting, &comps.mounting, filter) + .with_component(&comps.uid, &*self.mount_state, &comps.mount_state, filter) + .with_component(&comps.uid, &*self.mass, &comps.mass, filter) + .with_component(&comps.uid, &*self.sticky, &comps.sticky, filter) + .with_component(&comps.uid, &*self.gravity, &comps.gravity, filter) + //.with_component( + // &comps.uid, + // self.projectile.deref(), + // &comps.projectile, + // filter, + //) } } @@ -192,7 +186,7 @@ pub struct WriteTrackers<'a> { mass: WriteExpect<'a, UpdateTracker>, sticky: WriteExpect<'a, UpdateTracker>, gravity: WriteExpect<'a, UpdateTracker>, - projectile: WriteExpect<'a, UpdateTracker>, + //projectile: WriteExpect<'a, UpdateTracker>, } fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) { @@ -210,7 +204,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) { trackers.mass.record_changes(&comps.mass); trackers.sticky.record_changes(&comps.sticky); trackers.gravity.record_changes(&comps.gravity); - trackers.projectile.record_changes(&comps.projectile); + //trackers.projectile.record_changes(&comps.projectile); } pub fn register_trackers(world: &mut World) { @@ -227,7 +221,7 @@ pub fn register_trackers(world: &mut World) { world.register_tracker::(); world.register_tracker::(); world.register_tracker::(); - world.register_tracker::(); + //world.register_tracker::(); } #[derive(SystemData)] @@ -236,11 +230,11 @@ pub struct TrackedResources<'a> { } impl<'a> TrackedResources<'a> { pub fn create_res_sync_package(&self) -> ResSyncPackage { - ResSyncPackage::new().with_res(self.time_of_day.deref()) + ResSyncPackage::new().with_res(&*self.time_of_day) } /// Create state package with resources included pub fn state_package(&self) -> StatePackage { - StatePackage::new().with_res(self.time_of_day.deref()) + StatePackage::new().with_res(&*self.time_of_day) } } diff --git a/server/src/sys/subscription.rs b/server/src/sys/subscription.rs index a37d4057b7..ef6cc59659 100644 --- a/server/src/sys/subscription.rs +++ b/server/src/sys/subscription.rs @@ -102,7 +102,7 @@ impl<'a> System<'a> for Sys { .reduce_or() { // Update current chunk - subscription.fuzzy_chunk = dbg!(Vec2::::from(pos.0)) + subscription.fuzzy_chunk = Vec2::::from(pos.0) .map2(TerrainChunkSize::RECT_SIZE, |e, sz| e as i32 / sz as i32); // Use the largest side length as our chunk size let chunk_size = TerrainChunkSize::RECT_SIZE.reduce_max() as f32; @@ -173,7 +173,6 @@ impl<'a> System<'a> for Sys { // Send client intial info about the entities in this region if it was not // already within the set of subscribed regions if subscription.regions.insert(key.clone()) { - let mut counter = 0; if let Some(region) = region_map.get(key) { for (uid, pos, vel, ori, character_state, _, entity) in ( &uids, @@ -187,7 +186,6 @@ impl<'a> System<'a> for Sys { .join() .filter(|(_, _, _, _, _, _, e)| *e != client_entity) { - counter += 1; // Send message to create entity and tracked components client.notify(ServerMsg::CreateEntity( tracked_comps.create_entity_package(entity), From d341073a44d0f89f6812328acf4540c65e539107 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 30 Nov 2019 01:41:20 -0500 Subject: [PATCH 10/51] Upgrade to specs 0.15.1 --- Cargo.lock | 198 ++++------------------- client/Cargo.toml | 2 +- client/src/lib.rs | 2 +- common/Cargo.toml | 6 +- common/src/region.rs | 3 +- common/src/state.rs | 24 +-- common/src/sync/packet.rs | 2 +- common/src/sync/sync_ext.rs | 5 +- common/src/sync/track.rs | 2 +- server/Cargo.toml | 8 +- server/src/cmd.rs | 2 +- server/src/lib.rs | 37 ++--- server/src/sys/sentinel.rs | 4 +- server/src/sys/subscription.rs | 5 +- voxygen/Cargo.toml | 2 +- voxygen/src/audio/sfx/event_mapper.rs | 2 +- voxygen/src/audio/sfx/mod.rs | 1 + voxygen/src/hud/map.rs | 1 + voxygen/src/hud/minimap.rs | 1 + voxygen/src/hud/mod.rs | 2 +- voxygen/src/hud/social.rs | 2 +- voxygen/src/menu/char_selection/scene.rs | 1 + voxygen/src/scene/figure/mod.rs | 2 +- voxygen/src/scene/mod.rs | 2 +- voxygen/src/session.rs | 2 +- 25 files changed, 83 insertions(+), 235 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a945449cd7..ea89d274a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -706,17 +706,6 @@ dependencies = [ "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam" version = "0.7.2" @@ -730,18 +719,6 @@ dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-channel" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-channel" version = "0.3.9" @@ -750,15 +727,6 @@ dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-deque" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-deque" version = "0.7.2" @@ -768,32 +736,6 @@ dependencies = [ "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-epoch" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-epoch" version = "0.7.2" @@ -836,11 +778,6 @@ dependencies = [ "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-utils" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "crossbeam-utils" version = "0.6.6" @@ -1151,14 +1088,6 @@ name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "gdk" version = "0.8.0" @@ -1538,7 +1467,7 @@ dependencies = [ [[package]] name = "hibitset" -version = "0.5.4" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atom 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1734,15 +1663,6 @@ name = "linked-hash-map" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "lock_api" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "lock_api" version = "0.3.1" @@ -1832,11 +1752,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "memoffset" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "memoffset" version = "0.5.3" @@ -2019,11 +1934,6 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "nonzero_signed" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "notify" version = "5.0.0-pre.1" @@ -2219,14 +2129,6 @@ dependencies = [ "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "owning_ref" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "pango" version = "0.4.0" @@ -2261,15 +2163,6 @@ dependencies = [ "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parking_lot" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot" version = "0.9.0" @@ -2291,18 +2184,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parking_lot_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot_core" version = "0.6.2" @@ -2973,11 +2854,6 @@ name = "scoped_threadpool" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "scopeguard" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "scopeguard" version = "1.0.0" @@ -3067,19 +2943,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "shred" -version = "0.7.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "shred-derive 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "shred-derive" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3167,31 +3044,28 @@ dependencies = [ [[package]] name = "specs" -version = "0.14.3" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "derivative 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hibitset 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "nonzero_signed 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "shred 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "shred-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "shred 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)", "shrev 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tuple_utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tuple_utils 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "specs-idvs" version = "0.1.0" -source = "git+https://gitlab.com/veloren/specs-idvs.git#4ce792042f951a29874954582234836c0eccaed6" +source = "git+https://gitlab.com/veloren/specs-idvs.git?branch=imbris/specs-15#55547cdf1358c667ac8a7d4c79857143bde2843c" dependencies = [ - "hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hibitset 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3432,7 +3306,7 @@ dependencies = [ [[package]] name = "tuple_utils" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3554,7 +3428,7 @@ dependencies = [ "image 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", + "specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", "uvth 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "veloren-common 0.4.0", @@ -3570,7 +3444,6 @@ dependencies = [ "dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "find_folder 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3586,8 +3459,8 @@ dependencies = [ "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", - "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", - "specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git)", + "specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git?branch=imbris/specs-15)", "sum_type 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3599,7 +3472,6 @@ dependencies = [ "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "portpicker 0.1.0 (git+https://github.com/wusyong/portpicker-rs?branch=fix_ipv6)", @@ -3611,10 +3483,8 @@ dependencies = [ "scan_fmt 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "shred 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "shred-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", - "specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git)", + "specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git?branch=imbris/specs-15)", "uvth 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "veloren-common 0.4.0", @@ -3666,7 +3536,7 @@ dependencies = [ "rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", + "specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "veloren-client 0.4.0", "veloren-common 0.4.0", @@ -4038,19 +3908,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "938703e165481c8d612ea3479ac8342e5615185db37765162e762ec3523e2fc6" "checksum criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eccdc6ce8bbe352ca89025bee672aa6d24f4eb8c53e3a8b5d1bc58011da072a2" -"checksum crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7408247b1b87f480890f28b670c5f8d9a8a4274833433fe74dc0dfd46d33650" "checksum crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2d818a4990769aac0c7ff1360e233ef3a41adcb009ebb2036bf6915eb0f6b23c" -"checksum crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b85741761b7f160bc5e7e0c14986ef685b7f8bf9b7ad081c60c604bb4649827" "checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" -"checksum crossbeam-deque 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7792c4a9b5a4222f654e3728a3dd945aacc24d2c3a1a096ed265d80e4929cb9a" "checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" -"checksum crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30fecfcac6abfef8771151f8be4abc9e4edc112c2bcb233314cafde2680536e9" -"checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8" "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" "checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700" -"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" "checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" @@ -4088,7 +3952,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" "checksum gdk 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd30051ff3d908ff2fc7e5776ffe1c699821e043809f294c3a61004f11d6c3a9" "checksum gdk-pixbuf 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2d2199eba47ebcb9977ce28179649bdd59305ef465c4e6f9b65aaa41c24e6b5" "checksum gdk-pixbuf-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df6a3b73e04fafc07f5ebc083f1096a773412e627828e1103a55e921f81187d8" @@ -4123,7 +3986,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum gzip-header 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0131feb3d3bb2a5a238d8a4d09f6353b7ebfdc52e77bccbf4ea6eaa751dde639" "checksum hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" "checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" -"checksum hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6527bc88f32e0d3926c7572874b2bf17a19b36978aacd0aacf75f7d27a5992d0" +"checksum hibitset 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "47e7292fd9f7fe89fa35c98048f2d0a69b79ed243604234d18f6f8a1aa6f408d" "checksum hound 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" @@ -4149,7 +4012,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" "checksum line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" -"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" @@ -4162,7 +4024,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mime_guess 1.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0d977de9ee851a0b16e932979515c0f3da82403183879811bc97d50bd9cc50f7" @@ -4181,7 +4042,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum noise 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "337525774dd8a197b613a01ea88058ef0ed023e5ed1e4b7e93de478e1f2bf770" "checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" -"checksum nonzero_signed 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "02783a0482333b0d3f5f5411b8fb60454a596696da041da0470ac9ef3e6e37d8" "checksum notify 5.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d742ae493f34bd2e20ec2f3c1276fc1981343a8efd7ef12bca4368d0303bed50" "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" "checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" @@ -4202,14 +4062,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518" "checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum pango 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45374801e224373c3c0393cd48073c81093494c8735721e81d1dbaa4096b2767" "checksum pango-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94039b3921a4af4058a3e4335e5d15099101f298a92f5afc40bab3a3027594a1" "checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" -"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" -"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" @@ -4286,7 +4143,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum scan_fmt 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "faf737f37ca340201889b5f48ecde47f233e9da3cbf3d04be27883adac39b4da" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" -"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum sdl2 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d051a07231e303f5f719da78cb6f7394f6d5b54f733aef5b0b447804a83edd7b" "checksum sdl2-sys 0.32.6 (registry+https://github.com/rust-lang/crates.io-index)" = "34e71125077d297d57e4c1acfe8981b5bdfbf5a20e7b589abfdcb33bf1127f86" @@ -4298,8 +4154,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum shared_library 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" -"checksum shred 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6ea122e6133568144fcfb5888737d4ac776ebc959f989dd65b907136ac22bfed" -"checksum shred-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fcf34e5e5302d3024aba7afc291f6d1ca7573ed035d3c0796976ba3f10691a1" +"checksum shred 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "92472b9bafafbcba21935c6444d924e5332742f6778c49504a49a97eaeff6ccc" +"checksum shred-derive 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c245c03fd923292ae18e01eadf65606fdc995c175433104ef3eee956db7c2d7" "checksum shrev 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5752e017e03af9d735b4b069f53b7a7fd90fefafa04d8bd0c25581b0bff437f" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" @@ -4309,8 +4165,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum smithay-client-toolkit 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2ccb8c57049b2a34d2cc2b203fa785020ba0129d31920ef0d317430adaf748fa" "checksum smithay-client-toolkit 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "93960e8975909fcb14cc755de93af2149d8b8f4eb368315537d40cfd0f324054" "checksum smithay-clipboard 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9667a262ef7a9ff1c55a7e665cd3d36f9bc2809f94167b1fb3fc31423a83f8c0" -"checksum specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "de65613ada4338aa7ba71eca60eca24c60483433eec0077bc4f33cfc31f4bdf0" -"checksum specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git)" = "" +"checksum specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4943fde8c5d3d14c3d19d2a4c7abbd7b626c270a19e6cd35252294a48feb698c" +"checksum specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git?branch=imbris/specs-15)" = "" "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" @@ -4339,7 +4195,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tiny_http 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1661fa0a44c95d01604bd05c66732a446c657efb62b5164a7a083a3b552b4951" "checksum tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4574b75faccaacddb9b284faecdf0b544b80b6b294f3d062d325c5726a209c20" "checksum toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01d1404644c8b12b16bfcffa4322403a91a451584daaaa7c28d3152e6cbc98cf" -"checksum tuple_utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbfecd7bb8f0a3e96b3b31c46af2677a55a588767c0091f484601424fcb20e7e" +"checksum tuple_utils 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44834418e2c5b16f47bedf35c28e148db099187dd5feee6367fb2525863af4f1" "checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" "checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" diff --git a/client/Cargo.toml b/client/Cargo.toml index 2dcb26563e..4f9509c1ec 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -12,6 +12,6 @@ uvth = "3.1.1" image = "0.22.3" num_cpus = "1.10.1" log = "0.4.8" -specs = "0.14.2" +specs = "0.15.1" vek = { version = "0.9.9", features = ["serde"] } hashbrown = { version = "0.6.2", features = ["serde", "nightly"] } diff --git a/client/src/lib.rs b/client/src/lib.rs index c1e0a5c365..c6eab89d3b 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -5,7 +5,7 @@ pub mod error; // Reexports pub use crate::error::Error; -pub use specs::{join::Join, saveload::Marker, Entity as EcsEntity, ReadStorage}; +pub use specs::{join::Join, saveload::Marker, Entity as EcsEntity, ReadStorage, WorldExt}; use common::{ comp::{self, ControlEvent, Controller, ControllerInputs, InventoryManip}, diff --git a/common/Cargo.toml b/common/Cargo.toml index 08f6ca603c..ccd3b901ce 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -5,9 +5,9 @@ authors = ["Joshua Barretto ", "Maciej ĆwiÄ™ka (); // Register synced resources used by the ECS. - ecs.add_resource(TimeOfDay(0.0)); + ecs.insert(TimeOfDay(0.0)); // Register unsynced resources used by the ECS. - ecs.add_resource(Time(0.0)); - ecs.add_resource(DeltaTime(0.0)); - ecs.add_resource(TerrainGrid::new().unwrap()); - ecs.add_resource(BlockChange::default()); - ecs.add_resource(TerrainChanges::default()); + ecs.insert(Time(0.0)); + ecs.insert(DeltaTime(0.0)); + ecs.insert(TerrainGrid::new().unwrap()); + ecs.insert(BlockChange::default()); + ecs.insert(TerrainChanges::default()); // TODO: only register on the server - ecs.add_resource(EventBus::::default()); - ecs.add_resource(EventBus::::default()); - ecs.add_resource(EventBus::::default()); - ecs.add_resource(RegionMap::new()); + ecs.insert(EventBus::::default()); + ecs.insert(EventBus::::default()); + ecs.insert(EventBus::::default()); + ecs.insert(RegionMap::new()); ecs } @@ -320,7 +320,7 @@ impl State { // TODO: Consider alternative ways to do this add_foreign_systems(&mut dispatch_builder); // This dispatches all the systems in parallel. - dispatch_builder.build().dispatch(&self.ecs.res); + dispatch_builder.build().dispatch(&self.ecs); self.ecs.maintain(); diff --git a/common/src/sync/packet.rs b/common/src/sync/packet.rs index 08c1d339e8..dbad6ea228 100644 --- a/common/src/sync/packet.rs +++ b/common/src/sync/packet.rs @@ -4,7 +4,7 @@ use super::{ }; use log::error; use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use specs::{shred::Resource, Component, Entity, Join, ReadStorage, World}; +use specs::{shred::Resource, Component, Entity, Join, ReadStorage, World, WorldExt}; use std::{ convert::{TryFrom, TryInto}, fmt::Debug, diff --git a/common/src/sync/sync_ext.rs b/common/src/sync/sync_ext.rs index 1033f666cb..ac2da7675f 100644 --- a/common/src/sync/sync_ext.rs +++ b/common/src/sync/sync_ext.rs @@ -10,6 +10,7 @@ use log::error; use specs::{ saveload::{MarkedBuilder, MarkerAllocator}, world::Builder, + WorldExt, }; pub trait WorldSyncExt { @@ -38,7 +39,7 @@ impl WorldSyncExt for specs::World { self.register_synced::(); // TODO: Consider only having allocator server side for now - self.add_resource(UidAllocator::new()); + self.insert(UidAllocator::new()); } fn register_synced(&mut self) where @@ -52,7 +53,7 @@ impl WorldSyncExt for specs::World { C::Storage: Default + specs::storage::Tracked, { let tracker = UpdateTracker::::new(self); - self.add_resource(tracker); + self.insert(tracker); } fn create_entity_synced(&mut self) -> specs::EntityBuilder { diff --git a/common/src/sync/track.rs b/common/src/sync/track.rs index f1137f5d28..e5aaa65357 100644 --- a/common/src/sync/track.rs +++ b/common/src/sync/track.rs @@ -2,7 +2,7 @@ use super::{ packet::{CompPacket, CompUpdateKind}, uid::Uid, }; -use specs::{BitSet, Component, Entity, Join, ReadStorage, World}; +use specs::{BitSet, Component, Entity, Join, ReadStorage, World, WorldExt}; use std::{ convert::{TryFrom, TryInto}, marker::PhantomData, diff --git a/server/Cargo.toml b/server/Cargo.toml index 3bb82317f0..d5234f894c 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -8,12 +8,10 @@ edition = "2018" common = { package = "veloren-common", path = "../common" } world = { package = "veloren-world", path = "../world" } -specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git" } +specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", branch = "imbris/specs-15"} log = "0.4.8" -specs = "0.14.2" -shred-derive = "0.5.0" -shred = "0.7.0" +specs = { version = "0.15.1", features = ["shred-derive"] } vek = "0.9.9" uvth = "3.1.1" lazy_static = "1.4.0" @@ -29,5 +27,3 @@ prometheus = "0.7" prometheus-static-metric = "0.2" rouille = "3.0.0" portpicker = { git = "https://github.com/wusyong/portpicker-rs", branch = "fix_ipv6" } -# TODO: remove when upgrading to specs 0.15 -hibitset = "0.5.3" diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 22606d8ee2..cca446f1a9 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -16,7 +16,7 @@ use common::{ vol::RectVolSize, }; use rand::Rng; -use specs::{Builder, Entity as EcsEntity, Join}; +use specs::{Builder, Entity as EcsEntity, Join, WorldExt}; use vek::*; use world::util::Sampler; diff --git a/server/src/lib.rs b/server/src/lib.rs index d49d4345b3..8f4d79985f 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -37,6 +37,7 @@ use metrics::ServerMetrics; use rand::Rng; use specs::{ join::Join, world::EntityBuilder as EcsEntityBuilder, Builder, Entity as EcsEntity, SystemData, + WorldExt, }; use std::{ i32, @@ -87,26 +88,18 @@ impl Server { /// Create a new `Server` pub fn new(settings: ServerSettings) -> Result { let mut state = State::default(); - state - .ecs_mut() - .add_resource(EventBus::::default()); + state.ecs_mut().insert(EventBus::::default()); // TODO: anything but this - state.ecs_mut().add_resource(AuthProvider::new()); - state.ecs_mut().add_resource(Tick(0)); - state.ecs_mut().add_resource(ChunkGenerator::new()); + state.ecs_mut().insert(AuthProvider::new()); + state.ecs_mut().insert(Tick(0)); + state.ecs_mut().insert(ChunkGenerator::new()); // System timers for performance monitoring - state - .ecs_mut() - .add_resource(sys::EntitySyncTimer::default()); - state.ecs_mut().add_resource(sys::MessageTimer::default()); - state.ecs_mut().add_resource(sys::SentinelTimer::default()); - state - .ecs_mut() - .add_resource(sys::SubscriptionTimer::default()); - state - .ecs_mut() - .add_resource(sys::TerrainSyncTimer::default()); - state.ecs_mut().add_resource(sys::TerrainTimer::default()); + state.ecs_mut().insert(sys::EntitySyncTimer::default()); + state.ecs_mut().insert(sys::MessageTimer::default()); + state.ecs_mut().insert(sys::SentinelTimer::default()); + state.ecs_mut().insert(sys::SubscriptionTimer::default()); + state.ecs_mut().insert(sys::TerrainSyncTimer::default()); + state.ecs_mut().insert(sys::TerrainTimer::default()); // Server-only components state.ecs_mut().register::(); state.ecs_mut().register::(); @@ -158,7 +151,7 @@ impl Server { }; // set the spawn point we calculated above - state.ecs_mut().add_resource(SpawnPoint(spawn_point)); + state.ecs_mut().insert(SpawnPoint(spawn_point)); // Set starting time for the server. state.ecs_mut().write_resource::().0 = settings.start_time; @@ -166,7 +159,7 @@ impl Server { // Register trackers sys::sentinel::register_trackers(&mut state.ecs_mut()); - state.ecs_mut().add_resource(DeletedEntities::default()); + state.ecs_mut().insert(DeletedEntities::default()); let this = Self { state, @@ -1000,11 +993,11 @@ impl Server { .get_mut(entity) .unwrap() .notify(ServerMsg::InitialSync { - ecs_state: TrackedResources::fetch(&self.state.ecs().res) + ecs_state: TrackedResources::fetch(&self.state.ecs()) .state_package() // Send client their entity .with_entity( - TrackedComps::fetch(&self.state.ecs().res) + TrackedComps::fetch(&self.state.ecs()) .create_entity_package(entity), ), entity_uid: self.state.ecs().uid_from_entity(entity).unwrap().into(), // Can't fail. diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs index bb59f42edf..31acac56b3 100644 --- a/server/src/sys/sentinel.rs +++ b/server/src/sys/sentinel.rs @@ -12,9 +12,9 @@ use common::{ }, }; use hashbrown::HashMap; -use shred_derive::SystemData; use specs::{ - Entity as EcsEntity, Join, ReadExpect, ReadStorage, System, World, Write, WriteExpect, + shred::ResourceId, Entity as EcsEntity, Join, ReadExpect, ReadStorage, System, SystemData, + World, Write, WriteExpect, }; use vek::*; diff --git a/server/src/sys/subscription.rs b/server/src/sys/subscription.rs index ef6cc59659..f11eaeeafb 100644 --- a/server/src/sys/subscription.rs +++ b/server/src/sys/subscription.rs @@ -13,7 +13,8 @@ use common::{ }; use log::{debug, error}; use specs::{ - Entities, Join, ReadExpect, ReadStorage, System, SystemData, World, Write, WriteStorage, + Entities, Join, ReadExpect, ReadStorage, System, SystemData, World, WorldExt, Write, + WriteStorage, }; use vek::*; @@ -231,7 +232,7 @@ pub fn initialize_region_subscription(world: &World, entity: specs::Entity) { ); let region_map = world.read_resource::(); - let tracked_comps = TrackedComps::fetch(&world.res); + let tracked_comps = TrackedComps::fetch(world); for key in ®ions { if let Some(region) = region_map.get(*key) { for (uid, pos, vel, ori, character_state, _, entity) in ( diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 896b6b7283..daa6fbfd66 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -27,7 +27,7 @@ conrod_winit = { git = "https://gitlab.com/veloren/conrod.git" } euc = "0.3.0" # ECS -specs = "0.14.2" +specs = "0.15.1" # Mathematics vek = { version = "0.9.9", features = ["serde"] } diff --git a/voxygen/src/audio/sfx/event_mapper.rs b/voxygen/src/audio/sfx/event_mapper.rs index 69baaa6b93..9a6f7c3d92 100644 --- a/voxygen/src/audio/sfx/event_mapper.rs +++ b/voxygen/src/audio/sfx/event_mapper.rs @@ -8,7 +8,7 @@ use common::{ event::{EventBus, SfxEvent, SfxEventItem}, }; use hashbrown::HashMap; -use specs::{Entity as EcsEntity, Join}; +use specs::{Entity as EcsEntity, Join, WorldExt}; use std::time::{Duration, Instant}; use vek::*; diff --git a/voxygen/src/audio/sfx/mod.rs b/voxygen/src/audio/sfx/mod.rs index a4007ccfa0..52ab02614c 100644 --- a/voxygen/src/audio/sfx/mod.rs +++ b/voxygen/src/audio/sfx/mod.rs @@ -9,6 +9,7 @@ use common::{ event::{EventBus, SfxEvent, SfxEventItem}, }; use serde::Deserialize; +use specs::WorldExt; use vek::*; #[derive(Deserialize)] diff --git a/voxygen/src/hud/map.rs b/voxygen/src/hud/map.rs index 0af0330e8b..885a69f319 100644 --- a/voxygen/src/hud/map.rs +++ b/voxygen/src/hud/map.rs @@ -7,6 +7,7 @@ use conrod_core::{ widget::{self, Button, Image, Rectangle, Text}, widget_ids, Colorable, Positionable, Sizeable, Widget, WidgetCommon, }; +use specs::WorldExt; use vek::*; widget_ids! { diff --git a/voxygen/src/hud/minimap.rs b/voxygen/src/hud/minimap.rs index 09893c2eba..be1e34ad2c 100644 --- a/voxygen/src/hud/minimap.rs +++ b/voxygen/src/hud/minimap.rs @@ -7,6 +7,7 @@ use conrod_core::{ widget::{self, Button, Image, Rectangle, Text}, widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon, }; +use specs::WorldExt; use std::time::{Duration, Instant}; use vek::*; diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index da4b978067..7da5038331 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -49,7 +49,7 @@ use conrod_core::{ widget::{self, Button, Image, Rectangle, Text}, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, }; -use specs::Join; +use specs::{Join, WorldExt}; use std::collections::VecDeque; use vek::*; diff --git a/voxygen/src/hud/social.rs b/voxygen/src/hud/social.rs index 14be88343c..b57ab9226c 100644 --- a/voxygen/src/hud/social.rs +++ b/voxygen/src/hud/social.rs @@ -7,7 +7,7 @@ use conrod_core::{ widget_ids, /*, Color*/ Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; -use specs::Join; +use specs::{Join, WorldExt}; use client::{self, Client}; diff --git a/voxygen/src/menu/char_selection/scene.rs b/voxygen/src/menu/char_selection/scene.rs index 4b2c99bfcc..906e60c0a4 100644 --- a/voxygen/src/menu/char_selection/scene.rs +++ b/voxygen/src/menu/char_selection/scene.rs @@ -21,6 +21,7 @@ use common::{ terrain::BlockKind, }; use log::error; +use specs::WorldExt; use vek::*; struct Skybox { diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index ddecd67043..b5e33ee35d 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -26,7 +26,7 @@ use common::{ }; use hashbrown::HashMap; use log::trace; -use specs::{Entity as EcsEntity, Join}; +use specs::{Entity as EcsEntity, Join, WorldExt}; use vek::*; const DAMAGE_FADE_COEFFICIENT: f64 = 5.0; diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index a98e30c436..d43450806d 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -22,7 +22,7 @@ use common::{ terrain::{BlockKind, TerrainChunk}, vol::ReadVol, }; -use specs::Join; +use specs::{Join, WorldExt}; use vek::*; // TODO: Don't hard-code this. diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 6d7151d65f..2ff3286fd0 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -17,7 +17,7 @@ use common::{ ChatType, }; use log::error; -use specs::Join; +use specs::{Join, WorldExt}; use std::{cell::RefCell, rc::Rc, time::Duration}; use vek::*; From 8f7323f41b66fa93c0406771a4016062c17415cb Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 1 Dec 2019 16:54:21 -0500 Subject: [PATCH 11/51] Stop syncing health change timer updates --- Cargo.lock | 2 +- common/Cargo.toml | 2 +- common/src/sys/phys.rs | 5 ++++- common/src/sys/stats.rs | 25 ++++++++++++++++++++----- server/src/lib.rs | 15 +++++++++++---- server/src/sys/mod.rs | 4 ++-- 6 files changed, 39 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea89d274a5..0b821910f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3062,7 +3062,7 @@ dependencies = [ [[package]] name = "specs-idvs" version = "0.1.0" -source = "git+https://gitlab.com/veloren/specs-idvs.git?branch=imbris/specs-15#55547cdf1358c667ac8a7d4c79857143bde2843c" +source = "git+https://gitlab.com/veloren/specs-idvs.git?branch=imbris/specs-15#f049bf725f2a690d01ea8a83da49c7ebf8d8ea2a" dependencies = [ "hibitset 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/common/Cargo.toml b/common/Cargo.toml index ccd3b901ce..8362c5ce84 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", branch = "imbris/specs-15" } -specs = { version = "0.15.1", features = ["serde", "nightly"] } +specs = { version = "0.15.1", features = ["serde", "nightly", "storage-event-control"] } vek = { version = "0.9.9", features = ["serde"] } dot_vox = "4.0.0" image = "0.22.3" diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index 4b1b89d62b..ad9e5170ec 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -349,10 +349,13 @@ impl<'a> System<'a> for Sys { &mut velocities, &bodies, !&mountings, - !&stickies, // Can't push stickies around + stickies.maybe(), &mut physics_states, ) .join() + .filter(|(_, _, _, _, _, _, sticky, physics)| { + sticky.is_none() || (physics.on_wall.is_none() && !physics.on_ground) + }) { physics.touch_entity = None; diff --git a/common/src/sys/stats.rs b/common/src/sys/stats.rs index 5de672a84b..f8aa9e281b 100644 --- a/common/src/sys/stats.rs +++ b/common/src/sys/stats.rs @@ -23,9 +23,25 @@ impl<'a> System<'a> for Sys { ) { let mut server_event_emitter = server_event_bus.emitter(); + // Increment last change timer + stats.set_event_emission(false); // avoid unnecessary syncing + for stat in (&mut stats).join() { + stat.health.last_change.0 += f64::from(dt.0); + } + stats.set_event_emission(true); + // Mutates all stats every tick causing the server to resend this component for every entity every tick - for (entity, mut stat) in (&entities, &mut stats).join() { - if stat.should_die() && !stat.is_dead { + for (entity, mut stats) in (&entities, &mut stats.restrict_mut()).join() { + let (set_dead, level_up) = { + let stat = stats.get_unchecked(); + ( + stat.should_die() && !stat.is_dead, + stat.exp.current() >= stat.exp.maximum(), + ) + }; + + if set_dead { + let stat = stats.get_mut_unchecked(); server_event_emitter.emit(ServerEvent::Destroy { entity, cause: stat.health.last_change.1.cause, @@ -34,9 +50,8 @@ impl<'a> System<'a> for Sys { stat.is_dead = true; } - stat.health.last_change.0 += f64::from(dt.0); - - if stat.exp.current() >= stat.exp.maximum() { + if level_up { + let stat = stats.get_mut_unchecked(); while stat.exp.current() >= stat.exp.maximum() { stat.exp.change_by(-(stat.exp.maximum() as i64)); stat.exp.change_maximum_by(25); diff --git a/server/src/lib.rs b/server/src/lib.rs index 8f4d79985f..571866eb98 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -36,8 +36,8 @@ use log::{debug, error}; use metrics::ServerMetrics; use rand::Rng; use specs::{ - join::Join, world::EntityBuilder as EcsEntityBuilder, Builder, Entity as EcsEntity, SystemData, - WorldExt, + join::Join, world::EntityBuilder as EcsEntityBuilder, Builder, Entity as EcsEntity, RunNow, + SystemData, WorldExt, }; use std::{ i32, @@ -831,7 +831,11 @@ impl Server { // 3) Handle inputs from clients frontend_events.append(&mut self.handle_new_connections()?); + // Run message recieving sys before the systems in common for decreased latency (e.g. run before controller system) + sys::message::Sys.run_now(&self.state.ecs()); + let before_tick_4 = Instant::now(); + // 4) Tick the server's LocalState. self.state.tick(dt, sys::add_server_systems); @@ -897,11 +901,14 @@ impl Server { self.metrics .tick_time .with_label_values(&["input"]) - .set((before_tick_4 - before_tick_1).as_nanos() as i64); + .set((before_tick_4 - before_tick_1).as_nanos() as i64 - message_nanos); self.metrics .tick_time .with_label_values(&["state tick"]) - .set((before_handle_events - before_tick_4).as_nanos() as i64 - total_sys_nanos); + .set( + (before_handle_events - before_tick_4).as_nanos() as i64 + - (total_sys_nanos - message_nanos), + ); self.metrics .tick_time .with_label_values(&["handle server events"]) diff --git a/server/src/sys/mod.rs b/server/src/sys/mod.rs index 28b3ac5842..cfb30c7479 100644 --- a/server/src/sys/mod.rs +++ b/server/src/sys/mod.rs @@ -21,9 +21,10 @@ const SENTINEL_SYS: &str = "sentinel_sys"; const SUBSCRIPTION_SYS: &str = "server_subscription_sys"; const TERRAIN_SYNC_SYS: &str = "server_terrain_sync_sys"; const TERRAIN_SYS: &str = "server_terrain_sys"; -const MESSAGE_SYS: &str = "server_message_sys"; +//const MESSAGE_SYS: &str = "server_message_sys"; pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { + // TODO: makes some of these dependent on systems in common like the phys system dispatch_builder.add(sentinel::Sys, SENTINEL_SYS, &[]); dispatch_builder.add(subscription::Sys, SUBSCRIPTION_SYS, &[]); dispatch_builder.add( @@ -33,7 +34,6 @@ pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { ); dispatch_builder.add(terrain_sync::Sys, TERRAIN_SYS, &[]); dispatch_builder.add(terrain::Sys, TERRAIN_SYNC_SYS, &[TERRAIN_SYS]); - dispatch_builder.add(message::Sys, MESSAGE_SYS, &[]); } /// Used to keep track of how much time each system takes From bfaa18e010cd05ff056e9367841b7f9f6b031734 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 1 Dec 2019 18:40:05 -0500 Subject: [PATCH 12/51] Fix NaN in agent sys, stop pushback from turning player around, account for Scale in melee attack hit detection --- Cargo.toml | 2 +- common/src/sys/agent.rs | 16 ++++++++-------- common/src/sys/combat.rs | 29 ++++++++++++++++++++--------- common/src/sys/movement.rs | 4 ++-- common/src/sys/phys.rs | 1 + 5 files changed, 32 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9abd786022..4c463c2db7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ opt-level = 2 overflow-checks = true debug-assertions = true panic = "abort" -# debug = false +debug = false codegen-units = 8 lto = false incremental = true diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index c2bcbe1c2a..ef768e2a9d 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -1,6 +1,5 @@ use crate::comp::{ - Agent, CharacterState, Controller, ControllerInputs, MountState, MovementState::Glide, Pos, - Stats, + Agent, CharacterState, Controller, MountState, MovementState::Glide, Pos, Stats, }; use crate::pathfinding::WorldPath; use crate::terrain::TerrainGrid; @@ -60,7 +59,7 @@ impl<'a> System<'a> for Sys { controller.reset(); - let mut inputs = ControllerInputs::default(); + let mut inputs = &mut controller.inputs; match agent { Agent::Traveler { path } => { @@ -147,10 +146,10 @@ impl<'a> System<'a> for Sys { let dist = Vec2::::from(target_pos.0 - pos.0).magnitude(); if target_stats.is_dead { choose_new = true; - } else if dist < MIN_ATTACK_DIST - && dist > 0.001 - && rand::random::() < 0.3 - { + } else if dist < 0.001 { + // TODO: move back? (probably can only happen when entities are at a + // different z-level due to repulsion) + } else if dist < MIN_ATTACK_DIST { // Fight (and slowly move closer) inputs.move_dir = Vec2::::from(target_pos.0 - pos.0).normalized() * 0.01; @@ -203,7 +202,8 @@ impl<'a> System<'a> for Sys { } } - controller.inputs = inputs; + debug_assert!(inputs.move_dir.map(|e| !e.is_nan()).reduce_and()); + debug_assert!(inputs.look_dir.map(|e| !e.is_nan()).reduce_and()); } } } diff --git a/common/src/sys/combat.rs b/common/src/sys/combat.rs index 7ee73e4bfa..807ca96945 100644 --- a/common/src/sys/combat.rs +++ b/common/src/sys/combat.rs @@ -1,7 +1,7 @@ use crate::{ comp::{ ActionState::*, CharacterState, Controller, HealthChange, HealthSource, Item, ItemKind, - Ori, Pos, Stats, + Ori, Pos, Scale, Stats, }, event::{EventBus, LocalEvent, ServerEvent}, state::DeltaTime, @@ -13,7 +13,8 @@ use vek::*; const BLOCK_EFFICIENCY: f32 = 0.9; -const ATTACK_RANGE: f32 = 4.0; +const ATTACK_RANGE: f32 = 3.5; +const ATTACK_ANGLE: f32 = 45.0; const BLOCK_ANGLE: f32 = 180.0; /// This system is responsible for handling accepted inputs like moving or attacking @@ -27,6 +28,7 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Uid>, ReadStorage<'a, Pos>, ReadStorage<'a, Ori>, + ReadStorage<'a, Scale>, ReadStorage<'a, Controller>, WriteStorage<'a, CharacterState>, WriteStorage<'a, Stats>, @@ -42,6 +44,7 @@ impl<'a> System<'a> for Sys { uids, positions, orientations, + scales, controllers, mut character_states, stats, @@ -51,11 +54,12 @@ impl<'a> System<'a> for Sys { let mut _local_emitter = local_bus.emitter(); // Attacks - for (entity, uid, pos, ori, _, stat) in ( + for (entity, uid, pos, ori, scale_maybe, _, stat) in ( &entities, &uids, &positions, &orientations, + scales.maybe(), &controllers, &stats, ) @@ -92,11 +96,12 @@ impl<'a> System<'a> for Sys { if deal_damage { if let Some(Attack { .. }) = &character_states.get(entity).map(|c| c.action) { // Go through all other entities - for (b, uid_b, pos_b, ori_b, character_b, stat_b) in ( + for (b, uid_b, pos_b, ori_b, scale_b_maybe, character_b, stat_b) in ( &entities, &uids, &positions, &orientations, + scales.maybe(), &character_states, &stats, ) @@ -107,12 +112,18 @@ impl<'a> System<'a> for Sys { let pos_b2: Vec2 = Vec2::from(pos_b.0); let ori2 = Vec2::from(ori.0); + // Scales + let scale = scale_maybe.map_or(1.0, |s| s.0); + let scale_b = scale_b_maybe.map_or(1.0, |s| s.0); + // TODO: don't do this here + let rad_b = 0.5 * scale_b; + // Check if it is a hit if entity != b && !stat_b.is_dead - && pos.0.distance_squared(pos_b.0) < ATTACK_RANGE.powi(2) - // TODO: Use size instead of 1.0 - && ori2.angle_between(pos_b2 - pos2) < (2.0 / pos2.distance(pos_b2)).atan() + // Spherical wedge shaped attack field + && pos.0.distance_squared(pos_b.0) < (rad_b + scale * ATTACK_RANGE).powi(2) + && ori2.angle_between(pos_b2 - pos2) < ATTACK_ANGLE.to_radians() / 2.0 + (rad_b / pos2.distance(pos_b2)).atan() { // Weapon gives base damage let mut dmg = if let Some(ItemKind::Tool { power, .. }) = @@ -125,8 +136,8 @@ impl<'a> System<'a> for Sys { // Block if character_b.action.is_block() - && ori_b.0.angle_between(pos.0 - pos_b.0).to_degrees() - < BLOCK_ANGLE / 2.0 + && ori_b.0.angle_between(pos.0 - pos_b.0) + < BLOCK_ANGLE.to_radians() / 2.0 { dmg = (dmg as f32 * (1.0 - BLOCK_EFFICIENCY)) as i32 } diff --git a/common/src/sys/movement.rs b/common/src/sys/movement.rs index dcec8bac24..f0f157b9ce 100644 --- a/common/src/sys/movement.rs +++ b/common/src/sys/movement.rs @@ -173,10 +173,10 @@ impl<'a> System<'a> for Sys { if Vec2::::from(wall_dir).magnitude_squared() > 0.001 { Vec2::from(wall_dir).normalized() } else { - Vec2::from(vel.0) + Vec2::from(inputs.move_dir) } } else { - Vec2::from(vel.0) + Vec2::from(inputs.move_dir) }; if ori_dir.magnitude_squared() > 0.0001 diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index ad9e5170ec..67689495b4 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -102,6 +102,7 @@ impl<'a> System<'a> for Sys { let scale = scale.map(|s| s.0).unwrap_or(1.0); // Basic collision with terrain + // TODO: rename this, not just the player entity let player_rad = 0.3 * scale; // half-width of the player's AABB let player_height = 1.5 * scale; From 5813f626d1d136bb730ca5d3500b1eeb84a8c314 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 1 Dec 2019 20:26:31 -0500 Subject: [PATCH 13/51] cleanup --- Cargo.lock | 9 ++++----- common/Cargo.toml | 2 +- common/src/msg/ecs_packet.rs | 7 ------- server/Cargo.toml | 2 +- server/src/sys/mod.rs | 1 - server/src/sys/sentinel.rs | 15 --------------- voxygen/src/ui/mod.rs | 15 ++++++++++++--- world/src/sim/mod.rs | 2 +- 8 files changed, 19 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0b821910f2..030eb943a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3062,9 +3062,8 @@ dependencies = [ [[package]] name = "specs-idvs" version = "0.1.0" -source = "git+https://gitlab.com/veloren/specs-idvs.git?branch=imbris/specs-15#f049bf725f2a690d01ea8a83da49c7ebf8d8ea2a" +source = "git+https://gitlab.com/veloren/specs-idvs.git#111548cf44e9bb4c43feb12aa3fc253953ac6e4a" dependencies = [ - "hibitset 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3460,7 +3459,7 @@ dependencies = [ "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", - "specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git?branch=imbris/specs-15)", + "specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git)", "sum_type 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3484,7 +3483,7 @@ dependencies = [ "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", - "specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git?branch=imbris/specs-15)", + "specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git)", "uvth 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "veloren-common 0.4.0", @@ -4166,7 +4165,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum smithay-client-toolkit 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "93960e8975909fcb14cc755de93af2149d8b8f4eb368315537d40cfd0f324054" "checksum smithay-clipboard 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9667a262ef7a9ff1c55a7e665cd3d36f9bc2809f94167b1fb3fc31423a83f8c0" "checksum specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4943fde8c5d3d14c3d19d2a4c7abbd7b626c270a19e6cd35252294a48feb698c" -"checksum specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git?branch=imbris/specs-15)" = "" +"checksum specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git)" = "" "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" diff --git a/common/Cargo.toml b/common/Cargo.toml index 8362c5ce84..adcdd3f834 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Joshua Barretto ", "Maciej ĆwiÄ™ka sync::handle_res_update(time, world), EcsResPacket::MustHaveMoreThanOneVariant(_) => unimplemented!(), EcsResPacket::TimeOfDay(time_of_day) => sync::handle_res_update(time_of_day, world), } @@ -41,7 +39,6 @@ sum_type! { MountState(comp::MountState), Mounting(comp::Mounting), Mass(comp::Mass), - //Projectile(comp::Projectile), Gravity(comp::Gravity), Sticky(comp::Sticky), } @@ -61,7 +58,6 @@ sum_type! { MountState(PhantomData), Mounting(PhantomData), Mass(PhantomData), - //Projectile(PhantomData), Gravity(PhantomData), Sticky(PhantomData), } @@ -80,7 +76,6 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPacket::MountState(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Mounting(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Mass(comp) => sync::handle_insert(comp, entity, world), - //EcsCompPacket::Projectile(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Gravity(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Sticky(comp) => sync::handle_insert(comp, entity, world), } @@ -97,7 +92,6 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPacket::MountState(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Mounting(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Mass(comp) => sync::handle_modify(comp, entity, world), - //EcsCompPacket::Projectile(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Gravity(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Sticky(comp) => sync::handle_modify(comp, entity, world), } @@ -116,7 +110,6 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPhantom::MountState(_) => sync::handle_remove::(entity, world), EcsCompPhantom::Mounting(_) => sync::handle_remove::(entity, world), EcsCompPhantom::Mass(_) => sync::handle_remove::(entity, world), - //EcsCompPhantom::Projectile(_) => sync::handle_remove::(entity, world), EcsCompPhantom::Gravity(_) => sync::handle_remove::(entity, world), EcsCompPhantom::Sticky(_) => sync::handle_remove::(entity, world), } diff --git a/server/Cargo.toml b/server/Cargo.toml index d5234f894c..009ff93252 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" common = { package = "veloren-common", path = "../common" } world = { package = "veloren-world", path = "../world" } -specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", branch = "imbris/specs-15"} +specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git" } log = "0.4.8" specs = { version = "0.15.1", features = ["shred-derive"] } diff --git a/server/src/sys/mod.rs b/server/src/sys/mod.rs index cfb30c7479..72860c92c8 100644 --- a/server/src/sys/mod.rs +++ b/server/src/sys/mod.rs @@ -21,7 +21,6 @@ const SENTINEL_SYS: &str = "sentinel_sys"; const SUBSCRIPTION_SYS: &str = "server_subscription_sys"; const TERRAIN_SYNC_SYS: &str = "server_terrain_sync_sys"; const TERRAIN_SYS: &str = "server_terrain_sys"; -//const MESSAGE_SYS: &str = "server_message_sys"; pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { // TODO: makes some of these dependent on systems in common like the phys system diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs index 31acac56b3..081e5a7c55 100644 --- a/server/src/sys/sentinel.rs +++ b/server/src/sys/sentinel.rs @@ -53,7 +53,6 @@ pub struct TrackedComps<'a> { pub mass: ReadStorage<'a, Mass>, pub sticky: ReadStorage<'a, Sticky>, pub gravity: ReadStorage<'a, Gravity>, - //pub projectile: ReadStorage<'a, Projectile>, } impl<'a> TrackedComps<'a> { pub fn create_entity_package(&self, entity: EcsEntity) -> EntityPackage { @@ -112,10 +111,6 @@ impl<'a> TrackedComps<'a> { .get(entity) .copied() .map(|c| packets.push(c.into())); - //self.projectile - // .get(entity) - // .cloned() - // .map(|c| packets.push(c.into())); EntityPackage(uid, packets) } @@ -135,7 +130,6 @@ pub struct ReadTrackers<'a> { pub mass: ReadExpect<'a, UpdateTracker>, pub sticky: ReadExpect<'a, UpdateTracker>, pub gravity: ReadExpect<'a, UpdateTracker>, - //pub projectile: ReadExpect<'a, UpdateTracker>, } impl<'a> ReadTrackers<'a> { pub fn create_sync_package( @@ -162,12 +156,6 @@ impl<'a> ReadTrackers<'a> { .with_component(&comps.uid, &*self.mass, &comps.mass, filter) .with_component(&comps.uid, &*self.sticky, &comps.sticky, filter) .with_component(&comps.uid, &*self.gravity, &comps.gravity, filter) - //.with_component( - // &comps.uid, - // self.projectile.deref(), - // &comps.projectile, - // filter, - //) } } @@ -186,7 +174,6 @@ pub struct WriteTrackers<'a> { mass: WriteExpect<'a, UpdateTracker>, sticky: WriteExpect<'a, UpdateTracker>, gravity: WriteExpect<'a, UpdateTracker>, - //projectile: WriteExpect<'a, UpdateTracker>, } fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) { @@ -204,7 +191,6 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) { trackers.mass.record_changes(&comps.mass); trackers.sticky.record_changes(&comps.sticky); trackers.gravity.record_changes(&comps.gravity); - //trackers.projectile.record_changes(&comps.projectile); } pub fn register_trackers(world: &mut World) { @@ -221,7 +207,6 @@ pub fn register_trackers(world: &mut World) { world.register_tracker::(); world.register_tracker::(); world.register_tracker::(); - //world.register_tracker::(); } #[derive(SystemData)] diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index e5e581adf8..b9514a903b 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -342,7 +342,7 @@ impl Ui { // moving origin to top-left corner (from middle). let min_x = self.ui.win_w / 2.0 + l; let min_y = self.ui.win_h / 2.0 - b - h; - Aabr { + let intersection = Aabr { min: Vec2 { x: (min_x * scale_factor) as u16, y: (min_y * scale_factor) as u16, @@ -352,7 +352,13 @@ impl Ui { y: ((min_y + h) * scale_factor) as u16, }, } - .intersection(window_scissor) + .intersection(window_scissor); + + if intersection.is_valid() { + intersection + } else { + Aabr::new_empty(Vec2::zero()) + } }; if new_scissor != current_scissor { // Finish the current command. @@ -750,7 +756,10 @@ impl Ui { } fn default_scissor(renderer: &Renderer) -> Aabr { - let (screen_w, screen_h) = renderer.get_resolution().map(|e| e as u16).into_tuple(); + let (screen_w, screen_h) = renderer + .get_resolution() + .map(|e| (e as u16).max(1)) + .into_tuple(); Aabr { min: Vec2 { x: 0, y: 0 }, max: Vec2 { diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index 2ade596ad0..ce7a484676 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -324,7 +324,7 @@ impl WorldSim { let logistic_cdf = |x: f64| (x / logistic_2_base).tanh() * 0.5 + 0.5; let erosion_pow = 2.0; - let n_steps = 7; + let n_steps = 100; let erosion_factor = |x: f64| logistic_cdf(erosion_pow * logit(x)); let alt = do_erosion( 0.0, From b2752d2419199535fc3525dd8bc6ac5ab22c4a35 Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 18 Dec 2019 00:22:52 -0500 Subject: [PATCH 14/51] Cutout unnecessary Resource syncing machinery and Tracker trait --- client/src/lib.rs | 27 +++++++-------- common/src/msg/ecs_packet.rs | 23 +------------ common/src/msg/mod.rs | 2 +- common/src/msg/server.rs | 10 +++--- common/src/state.rs | 2 +- common/src/sync/mod.rs | 6 ++-- common/src/sync/packet.rs | 62 ++++++++--------------------------- common/src/sync/sync_ext.rs | 49 ++++++++++----------------- common/src/sync/track.rs | 54 +++++++++++------------------- server/src/lib.rs | 17 ++++------ server/src/sys/entity_sync.rs | 13 ++++---- server/src/sys/sentinel.rs | 59 +++++++++------------------------ 12 files changed, 102 insertions(+), 222 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index c6eab89d3b..6cb7658c64 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -79,9 +79,9 @@ impl Client { // Wait for initial sync let (state, entity, server_info, world_map) = match postbox.next_message() { Some(ServerMsg::InitialSync { - ecs_state, - entity_uid, + entity_package, server_info, + time_of_day, // world_map: /*(map_size, world_map)*/map_size, }) => { // TODO: Voxygen should display this. @@ -95,12 +95,10 @@ impl Client { ); } + // Initialize `State` let mut state = State::default(); - state.ecs_mut().apply_state_package(ecs_state); - let entity = state - .ecs() - .entity_from_uid(entity_uid) - .ok_or(Error::ServerWentMad)?; + let entity = state.ecs_mut().apply_entity_package(entity_package); + *state.ecs_mut().write_resource() = time_of_day; // assert_eq!(world_map.len(), map_size.x * map_size.y); let map_size = Vec2::new(1024, 1024); @@ -539,7 +537,7 @@ impl Client { self.last_ping_delta = Instant::now() .duration_since(self.last_server_ping) - .as_secs_f64() + .as_secs_f64(); } ServerMsg::ChatMsg { chat_type, message } => { frontend_events.push(Event::Chat { chat_type, message }) @@ -551,15 +549,14 @@ impl Client { return Err(Error::Other("Failed to find entity from uid.".to_owned())); } } - ServerMsg::EcsSync(sync_package) => { - self.state.ecs_mut().apply_sync_package(sync_package) + ServerMsg::TimeOfDay(time_of_day) => { + *self.state.ecs_mut().write_resource() = time_of_day; + } + ServerMsg::EcsSync(sync_package) => { + self.state.ecs_mut().apply_sync_package(sync_package); } - ServerMsg::EcsResSync(res_sync_package) => self - .state - .ecs_mut() - .apply_res_sync_package(res_sync_package), ServerMsg::CreateEntity(entity_package) => { - self.state.ecs_mut().apply_entity_package(entity_package) + self.state.ecs_mut().apply_entity_package(entity_package); } ServerMsg::DeleteEntity(entity) => { if self diff --git a/common/src/msg/ecs_packet.rs b/common/src/msg/ecs_packet.rs index 8f0ee66ad3..e714416ff9 100644 --- a/common/src/msg/ecs_packet.rs +++ b/common/src/msg/ecs_packet.rs @@ -1,29 +1,8 @@ -use crate::{comp, state, sync}; +use crate::{comp, sync}; use serde_derive::{Deserialize, Serialize}; use std::marker::PhantomData; use sum_type::sum_type; -// TODO: remove me -#[derive(Clone, Debug, Serialize, Deserialize)] -pub enum MustHaveMoreThanOneVariant {} - -// Automatically derive From for EcsResPacket -// for each variant EcsResPacket::T(T). -sum_type! { - #[derive(Clone, Debug, Serialize, Deserialize)] - pub enum EcsResPacket { - MustHaveMoreThanOneVariant(MustHaveMoreThanOneVariant), - TimeOfDay(state::TimeOfDay), - } -} -impl sync::ResPacket for EcsResPacket { - fn apply(self, world: &specs::World) { - match self { - EcsResPacket::MustHaveMoreThanOneVariant(_) => unimplemented!(), - EcsResPacket::TimeOfDay(time_of_day) => sync::handle_res_update(time_of_day, world), - } - } -} // Automatically derive From for EcsCompPacket // for each variant EcsCompPacket::T(T.) sum_type! { diff --git a/common/src/msg/mod.rs b/common/src/msg/mod.rs index 09bdae25bb..12f72addf5 100644 --- a/common/src/msg/mod.rs +++ b/common/src/msg/mod.rs @@ -4,7 +4,7 @@ pub mod server; // Reexports pub use self::client::ClientMsg; -pub use self::ecs_packet::{EcsCompPacket, EcsResPacket}; +pub use self::ecs_packet::EcsCompPacket; pub use self::server::{RequestStateError, ServerError, ServerInfo, ServerMsg}; #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index 90bc785ddb..7b922527d4 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -1,6 +1,6 @@ -use super::{ClientState, EcsCompPacket, EcsResPacket}; +use super::{ClientState, EcsCompPacket}; use crate::{ - comp, sync, + comp, state, sync, terrain::{Block, TerrainChunk}, ChatType, }; @@ -26,9 +26,9 @@ pub struct ServerInfo { #[derive(Debug, Clone, Serialize, Deserialize)] pub enum ServerMsg { InitialSync { - ecs_state: sync::StatePackage, - entity_uid: u64, + entity_package: sync::EntityPackage, server_info: ServerInfo, + time_of_day: state::TimeOfDay, // world_map: Vec2, /*, Vec)*/ }, StateAnswer(Result), @@ -40,8 +40,8 @@ pub enum ServerMsg { message: String, }, SetPlayerEntity(u64), + TimeOfDay(state::TimeOfDay), EcsSync(sync::SyncPackage), - EcsResSync(sync::ResSyncPackage), CreateEntity(sync::EntityPackage), DeleteEntity(u64), EntityPos { diff --git a/common/src/state.rs b/common/src/state.rs index b3378eea75..5e19b25c43 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -23,7 +23,7 @@ use vek::*; const DAY_CYCLE_FACTOR: f64 = 24.0 * 2.0; /// A resource that stores the time of day. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct TimeOfDay(pub f64); /// A resource that stores the tick (i.e: physics) time. diff --git a/common/src/sync/mod.rs b/common/src/sync/mod.rs index d26ad789fd..7a5cae6d18 100644 --- a/common/src/sync/mod.rs +++ b/common/src/sync/mod.rs @@ -6,9 +6,9 @@ mod uid; // Reexports pub use packet::{ - handle_insert, handle_modify, handle_remove, handle_res_update, CompPacket, EntityPackage, - ResPacket, ResSyncPackage, StatePackage, SyncPackage, + handle_insert, handle_modify, handle_remove, CompPacket, EntityPackage, StatePackage, + SyncPackage, }; pub use sync_ext::WorldSyncExt; -pub use track::{Tracker, UpdateTracker}; +pub use track::UpdateTracker; pub use uid::{Uid, UidAllocator}; diff --git a/common/src/sync/packet.rs b/common/src/sync/packet.rs index dbad6ea228..b3ea29985c 100644 --- a/common/src/sync/packet.rs +++ b/common/src/sync/packet.rs @@ -1,10 +1,7 @@ -use super::{ - track::{Tracker, UpdateTracker}, - uid::Uid, -}; +use super::{track::UpdateTracker, uid::Uid}; use log::error; use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use specs::{shred::Resource, Component, Entity, Join, ReadStorage, World, WorldExt}; +use specs::{Component, Entity, Join, ReadStorage, World, WorldExt}; use std::{ convert::{TryFrom, TryInto}, fmt::Debug, @@ -19,10 +16,6 @@ pub trait CompPacket: Clone + Debug + Send + 'static { fn apply_remove(phantom: Self::Phantom, entity: Entity, world: &World); } -pub trait ResPacket: Clone + Debug + Send + 'static { - fn apply(self, world: &World); -} - /// Useful for implementing CompPacket trait pub fn handle_insert(comp: C, entity: Entity, world: &World) { if let Err(err) = world.write_storage::().insert(entity, comp) { @@ -40,10 +33,6 @@ pub fn handle_modify(comp: C, entity: Entity, world: &World) { pub fn handle_remove(entity: Entity, world: &World) { let _ = world.write_storage::().remove(entity); } -/// Useful for implementing ResPacket trait -pub fn handle_res_update(res: R, world: &World) { - *world.write_resource::() = res; -} #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub enum CompUpdateKind { @@ -53,24 +42,25 @@ pub enum CompUpdateKind { } #[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EntityPackage(pub u64, pub Vec

); - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct StatePackage { - pub entities: Vec>, - pub resources: Vec, +pub struct EntityPackage { + pub uid: u64, + pub comps: Vec

, } -impl Default for StatePackage { +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct StatePackage { + pub entities: Vec>, +} + +impl Default for StatePackage

{ fn default() -> Self { Self { entities: Vec::new(), - resources: Vec::new(), } } } -impl StatePackage { +impl StatePackage

{ pub fn new() -> Self { Self::default() } @@ -85,13 +75,6 @@ impl StatePackage { self.entities.push(entry); self } - pub fn with_res(mut self, res: &C) -> Self - where - R: From, - { - self.resources.push(R::from(res.clone())); - self - } } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -122,7 +105,7 @@ impl SyncPackage

{ pub fn with_component<'a, C: Component + Clone + Send + Sync>( mut self, uids: &ReadStorage<'a, Uid>, - tracker: &impl Tracker, + tracker: &UpdateTracker, storage: &ReadStorage<'a, C>, filter: impl Join + Copy, ) -> Self @@ -137,22 +120,3 @@ impl SyncPackage

{ self } } - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ResSyncPackage { - pub resources: Vec, -} -impl ResSyncPackage { - pub fn new() -> Self { - Self { - resources: Vec::new(), - } - } - pub fn with_res(mut self, res: &C) -> Self - where - R: From, - { - self.resources.push(R::from(res.clone())); - self - } -} diff --git a/common/src/sync/sync_ext.rs b/common/src/sync/sync_ext.rs index ac2da7675f..b567b6f8d2 100644 --- a/common/src/sync/sync_ext.rs +++ b/common/src/sync/sync_ext.rs @@ -1,8 +1,5 @@ use super::{ - packet::{ - CompPacket, CompUpdateKind, EntityPackage, ResPacket, ResSyncPackage, StatePackage, - SyncPackage, - }, + packet::{CompPacket, CompUpdateKind, EntityPackage, StatePackage, SyncPackage}, track::UpdateTracker, uid::{Uid, UidAllocator}, }; @@ -25,13 +22,12 @@ pub trait WorldSyncExt { fn delete_entity_and_clear_from_uid_allocator(&mut self, uid: u64); fn uid_from_entity(&self, entity: specs::Entity) -> Option; fn entity_from_uid(&self, uid: u64) -> Option; - fn apply_entity_package(&mut self, entity_package: EntityPackage

); - fn apply_state_package( + fn apply_entity_package( &mut self, - state_package: StatePackage, - ); + entity_package: EntityPackage

, + ) -> specs::Entity; + fn apply_state_package(&mut self, state_package: StatePackage

); fn apply_sync_package(&mut self, package: SyncPackage

); - fn apply_res_sync_package(&mut self, package: ResSyncPackage); } impl WorldSyncExt for specs::World { @@ -71,13 +67,18 @@ impl WorldSyncExt for specs::World { .retrieve_entity_internal(uid) } - fn apply_entity_package(&mut self, entity_package: EntityPackage

) { - let EntityPackage(entity_uid, packets) = entity_package; + fn apply_entity_package( + &mut self, + entity_package: EntityPackage

, + ) -> specs::Entity { + let EntityPackage { uid, comps } = entity_package; - let entity = create_entity_with_uid(self, entity_uid); - for packet in packets { + let entity = create_entity_with_uid(self, uid); + for packet in comps { packet.apply_insert(entity, self) } + + entity } fn delete_entity_and_clear_from_uid_allocator(&mut self, uid: u64) { @@ -90,25 +91,15 @@ impl WorldSyncExt for specs::World { } } - fn apply_state_package( - &mut self, - state_package: StatePackage, - ) { - let StatePackage { - entities, - resources, - } = state_package; - - // Apply state package resources - for res_packet in resources { - res_packet.apply(self); - } + fn apply_state_package(&mut self, state_package: StatePackage

) { + let StatePackage { entities } = state_package; // Apply state package entities for entity_package in entities { self.apply_entity_package(entity_package); } + // TODO: determine if this is needed // Initialize entities //self.maintain(); } @@ -151,12 +142,6 @@ impl WorldSyncExt for specs::World { self.delete_entity_and_clear_from_uid_allocator(entity_uid); } } - fn apply_res_sync_package(&mut self, package: ResSyncPackage) { - // Update resources - for res_packet in package.resources { - res_packet.apply(self); - } - } } // Private utilities diff --git a/common/src/sync/track.rs b/common/src/sync/track.rs index e5aaa65357..8c57360e60 100644 --- a/common/src/sync/track.rs +++ b/common/src/sync/track.rs @@ -8,29 +8,6 @@ use std::{ marker::PhantomData, }; -pub trait Tracker: Send + 'static -where - P: From, - C: TryFrom

, - P::Phantom: From>, - P::Phantom: TryInto>, - C::Storage: specs::storage::Tracked, -{ - fn add_packet_for<'a>( - &self, - storage: &specs::ReadStorage<'a, C>, - entity: specs::Entity, - packets: &mut Vec

, - ); - fn get_updates_for<'a>( - &self, - uids: &specs::ReadStorage<'a, Uid>, - storage: &specs::ReadStorage<'a, C>, - filter: impl Join + Copy, - buf: &mut Vec<(u64, CompUpdateKind

)>, - ); -} - pub struct UpdateTracker { reader_id: specs::ReaderId, inserted: BitSet, @@ -92,32 +69,39 @@ where } } -impl Tracker for UpdateTracker -where - P: From, - C: TryFrom

, - P::Phantom: From>, - P::Phantom: TryInto>, - C::Storage: specs::storage::Tracked, -{ - fn add_packet_for<'a>( +impl UpdateTracker { + pub fn add_packet_for<'a, P>( &self, storage: &ReadStorage<'a, C>, entity: Entity, packets: &mut Vec

, - ) { + ) where + P: CompPacket, + P: From, + C: TryFrom

, + P::Phantom: From>, + P::Phantom: TryInto>, + C::Storage: specs::storage::Tracked, + { if let Some(comp) = storage.get(entity) { packets.push(P::from(comp.clone())); } } - fn get_updates_for<'a>( + pub fn get_updates_for<'a, P>( &self, uids: &specs::ReadStorage<'a, Uid>, storage: &specs::ReadStorage<'a, C>, entity_filter: impl Join + Copy, buf: &mut Vec<(u64, CompUpdateKind

)>, - ) { + ) where + P: CompPacket, + P: From, + C: TryFrom

, + P::Phantom: From>, + P::Phantom: TryInto>, + C::Storage: specs::storage::Tracked, + { // Generate inserted updates for (uid, comp, _, _) in (uids, storage, &self.inserted, entity_filter).join() { buf.push(( diff --git a/server/src/lib.rs b/server/src/lib.rs index 571866eb98..f8815ad6cf 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -19,7 +19,7 @@ use crate::{ chunk_generator::ChunkGenerator, client::{Client, RegionSubscription}, cmd::CHAT_COMMANDS, - sys::sentinel::{DeletedEntities, TrackedComps, TrackedResources}, + sys::sentinel::{DeletedEntities, TrackedComps}, }; use common::{ assets, comp, @@ -992,7 +992,8 @@ impl Server { .create_entity_synced() .with(client) .build(); - // Return the state of the current world (all of the components that Sphynx tracks). + // Send client all the tracked components currently attached to its entity as well + // as synced resources (currently only `TimeOfDay`) log::debug!("Starting initial sync with client."); self.state .ecs() @@ -1000,15 +1001,11 @@ impl Server { .get_mut(entity) .unwrap() .notify(ServerMsg::InitialSync { - ecs_state: TrackedResources::fetch(&self.state.ecs()) - .state_package() - // Send client their entity - .with_entity( - TrackedComps::fetch(&self.state.ecs()) - .create_entity_package(entity), - ), - entity_uid: self.state.ecs().uid_from_entity(entity).unwrap().into(), // Can't fail. + // Send client their entity + entity_package: TrackedComps::fetch(&self.state.ecs()) + .create_entity_package(entity), server_info: self.server_info.clone(), + time_of_day: *self.state.ecs().read_resource(), // world_map: (WORLD_SIZE/*, self.world.sim().get_map()*/), }); log::debug!("Done initial sync with client."); diff --git a/server/src/sys/entity_sync.rs b/server/src/sys/entity_sync.rs index 7bb94fb3a5..cb571b7c7c 100644 --- a/server/src/sys/entity_sync.rs +++ b/server/src/sys/entity_sync.rs @@ -1,5 +1,5 @@ use super::{ - sentinel::{DeletedEntities, ReadTrackers, TrackedComps, TrackedResources}, + sentinel::{DeletedEntities, ReadTrackers, TrackedComps}, SysTimer, }; use crate::{ @@ -10,6 +10,7 @@ use common::{ comp::{CharacterState, ForceUpdate, Inventory, InventoryUpdate, Last, Ori, Pos, Vel}, msg::ServerMsg, region::{Event as RegionEvent, RegionMap}, + state::TimeOfDay, sync::Uid, }; use specs::{ @@ -22,6 +23,7 @@ impl<'a> System<'a> for Sys { type SystemData = ( Entities<'a>, Read<'a, Tick>, + ReadExpect<'a, TimeOfDay>, ReadExpect<'a, RegionMap>, Write<'a, SysTimer>, ReadStorage<'a, Uid>, @@ -41,7 +43,6 @@ impl<'a> System<'a> for Sys { Write<'a, DeletedEntities>, TrackedComps<'a>, ReadTrackers<'a>, - TrackedResources<'a>, ); fn run( @@ -49,6 +50,7 @@ impl<'a> System<'a> for Sys { ( entities, tick, + time_of_day, region_map, mut timer, uids, @@ -68,7 +70,6 @@ impl<'a> System<'a> for Sys { mut deleted_entities, tracked_comps, trackers, - tracked_resources, ): Self::SystemData, ) { timer.start(); @@ -329,10 +330,10 @@ impl<'a> System<'a> for Sys { inventory_updates.clear(); // Sync resources - // TODO: doesn't really belong in this system - let res_msg = ServerMsg::EcsResSync(tracked_resources.create_res_sync_package()); + // TODO: doesn't really belong in this system (rename system or create another system?) + let tof_msg = ServerMsg::TimeOfDay(*time_of_day); for client in (&mut clients).join() { - client.notify(res_msg.clone()); + client.notify(tof_msg.clone()); } timer.end(); diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs index 081e5a7c55..8fc04ea445 100644 --- a/server/src/sys/sentinel.rs +++ b/server/src/sys/sentinel.rs @@ -4,12 +4,8 @@ use common::{ Body, CanBuild, Gravity, Item, LightEmitter, Mass, MountState, Mounting, Player, Scale, Stats, Sticky, }, - msg::{EcsCompPacket, EcsResPacket}, - state::TimeOfDay, - sync::{ - CompPacket, EntityPackage, ResSyncPackage, StatePackage, SyncPackage, Uid, UpdateTracker, - WorldSyncExt, - }, + msg::EcsCompPacket, + sync::{EntityPackage, SyncPackage, Uid, UpdateTracker, WorldSyncExt}, }; use hashbrown::HashMap; use specs::{ @@ -62,57 +58,48 @@ impl<'a> TrackedComps<'a> { .copied() .expect("No uid to create an entity package") .0; - let mut packets = Vec::new(); - self.body - .get(entity) - .copied() - .map(|c| packets.push(c.into())); + let mut comps = Vec::new(); + self.body.get(entity).copied().map(|c| comps.push(c.into())); self.player .get(entity) .cloned() - .map(|c| packets.push(c.into())); + .map(|c| comps.push(c.into())); self.stats .get(entity) .cloned() - .map(|c| packets.push(c.into())); + .map(|c| comps.push(c.into())); self.can_build .get(entity) .cloned() - .map(|c| packets.push(c.into())); + .map(|c| comps.push(c.into())); self.light_emitter .get(entity) .copied() - .map(|c| packets.push(c.into())); - self.item - .get(entity) - .cloned() - .map(|c| packets.push(c.into())); + .map(|c| comps.push(c.into())); + self.item.get(entity).cloned().map(|c| comps.push(c.into())); self.scale .get(entity) .copied() - .map(|c| packets.push(c.into())); + .map(|c| comps.push(c.into())); self.mounting .get(entity) .cloned() - .map(|c| packets.push(c.into())); + .map(|c| comps.push(c.into())); self.mount_state .get(entity) .cloned() - .map(|c| packets.push(c.into())); - self.mass - .get(entity) - .copied() - .map(|c| packets.push(c.into())); + .map(|c| comps.push(c.into())); + self.mass.get(entity).copied().map(|c| comps.push(c.into())); self.sticky .get(entity) .copied() - .map(|c| packets.push(c.into())); + .map(|c| comps.push(c.into())); self.gravity .get(entity) .copied() - .map(|c| packets.push(c.into())); + .map(|c| comps.push(c.into())); - EntityPackage(uid, packets) + EntityPackage { uid, comps } } } #[derive(SystemData)] @@ -209,20 +196,6 @@ pub fn register_trackers(world: &mut World) { world.register_tracker::(); } -#[derive(SystemData)] -pub struct TrackedResources<'a> { - time_of_day: ReadExpect<'a, TimeOfDay>, -} -impl<'a> TrackedResources<'a> { - pub fn create_res_sync_package(&self) -> ResSyncPackage { - ResSyncPackage::new().with_res(&*self.time_of_day) - } - /// Create state package with resources included - pub fn state_package(&self) -> StatePackage { - StatePackage::new().with_res(&*self.time_of_day) - } -} - /// Deleted entities grouped by region pub struct DeletedEntities { map: HashMap, Vec>, From 934c5d684676610e87bcbfdf3122ffb3d2c75318 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 19 Dec 2019 22:31:41 -0500 Subject: [PATCH 15/51] Various tweaks: moved radius determination to function on , comments, simplified server Destroy event code, debug assert modified components aren't removed in change tracking, etc --- common/src/comp/body.rs | 17 +++++++++++++++++ common/src/sync/packet.rs | 3 +++ common/src/sync/track.rs | 7 +++---- common/src/sys/agent.rs | 7 +++++-- common/src/sys/combat.rs | 24 +++++++++++++----------- server/src/lib.rs | 20 ++++++++++++-------- voxygen/src/ui/mod.rs | 5 +---- 7 files changed, 54 insertions(+), 29 deletions(-) diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index b2ba589b24..6b63bb8f51 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -33,6 +33,23 @@ impl Body { _ => false, } } + // Note: this might need to be refined to something more complex for realistic + // behavior with less cylindrical bodies (e.g. wolfs) + pub fn radius(&self) -> f32 { + // TODO: Improve these values (some might be reliant on more info in inner type) + match self { + Body::Humanoid(_) => 0.5, + Body::QuadrupedSmall(_) => 0.6, + Body::QuadrupedMedium(_) => 0.9, + Body::BirdMedium(_) => 0.5, + Body::FishMedium(_) => 0.5, + Body::Dragon(_) => 2.5, + Body::BirdSmall(_) => 0.2, + Body::FishSmall(_) => 0.2, + Body::BipedLarge(_) => 1.0, + Body::Object(_) => 0.3, + } + } } impl Component for Body { diff --git a/common/src/sync/packet.rs b/common/src/sync/packet.rs index b3ea29985c..a9d3363eeb 100644 --- a/common/src/sync/packet.rs +++ b/common/src/sync/packet.rs @@ -8,6 +8,9 @@ use std::{ marker::PhantomData, }; +/// Implemented by type that carries component data for insertion and modification +/// The assocatied `Phantom` type only carries information about which component type is of +/// interest and is used to transmit deletion events pub trait CompPacket: Clone + Debug + Send + 'static { type Phantom: Clone + Debug + Serialize + DeserializeOwned; diff --git a/common/src/sync/track.rs b/common/src/sync/track.rs index 8c57360e60..3cccda6794 100644 --- a/common/src/sync/track.rs +++ b/common/src/sync/track.rs @@ -51,10 +51,9 @@ where self.inserted.add(*id); } specs::storage::ComponentEvent::Modified(id) => { - // We don't care about modification if the component was just added or was - // removed - // Could potentially remove since this should theoretically never occur... - if !self.removed.contains(*id) && !self.inserted.contains(*id) { + // We don't care about modification if the component was just added + if !self.inserted.contains(*id) { + debug_assert!(!self.removed.contains(*id)); // Theoretically impossible self.modified.add(*id); } } diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index ef768e2a9d..5ce18dacab 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -147,8 +147,11 @@ impl<'a> System<'a> for Sys { if target_stats.is_dead { choose_new = true; } else if dist < 0.001 { - // TODO: move back? (probably can only happen when entities are at a - // different z-level due to repulsion) + // Probably can only happen when entities are at a different z-level + // since at the same level repulsion would keep them apart. + // Distinct from the first if block since we may want to change the + // behavior for this case. + choose_new = true; } else if dist < MIN_ATTACK_DIST { // Fight (and slowly move closer) inputs.move_dir = diff --git a/common/src/sys/combat.rs b/common/src/sys/combat.rs index 807ca96945..78cba752c0 100644 --- a/common/src/sys/combat.rs +++ b/common/src/sys/combat.rs @@ -1,7 +1,7 @@ use crate::{ comp::{ - ActionState::*, CharacterState, Controller, HealthChange, HealthSource, Item, ItemKind, - Ori, Pos, Scale, Stats, + ActionState::*, Body, CharacterState, Controller, HealthChange, HealthSource, Item, + ItemKind, Ori, Pos, Scale, Stats, }, event::{EventBus, LocalEvent, ServerEvent}, state::DeltaTime, @@ -30,8 +30,9 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Ori>, ReadStorage<'a, Scale>, ReadStorage<'a, Controller>, + ReadStorage<'a, Body>, + ReadStorage<'a, Stats>, WriteStorage<'a, CharacterState>, - WriteStorage<'a, Stats>, ); fn run( @@ -46,15 +47,16 @@ impl<'a> System<'a> for Sys { orientations, scales, controllers, - mut character_states, + bodies, stats, + mut character_states, ): Self::SystemData, ) { let mut server_emitter = server_bus.emitter(); let mut _local_emitter = local_bus.emitter(); // Attacks - for (entity, uid, pos, ori, scale_maybe, _, stat) in ( + for (entity, uid, pos, ori, scale_maybe, _, attacker_stats) in ( &entities, &uids, &positions, @@ -68,7 +70,7 @@ impl<'a> System<'a> for Sys { let recover_duration = if let Some(Item { kind: ItemKind::Tool { kind, .. }, .. - }) = stat.equipment.main + }) = attacker_stats.equipment.main { kind.attack_recover_duration() } else { @@ -96,7 +98,7 @@ impl<'a> System<'a> for Sys { if deal_damage { if let Some(Attack { .. }) = &character_states.get(entity).map(|c| c.action) { // Go through all other entities - for (b, uid_b, pos_b, ori_b, scale_b_maybe, character_b, stat_b) in ( + for (b, uid_b, pos_b, ori_b, scale_b_maybe, character_b, stats_b, body_b) in ( &entities, &uids, &positions, @@ -104,6 +106,7 @@ impl<'a> System<'a> for Sys { scales.maybe(), &character_states, &stats, + &bodies, ) .join() { @@ -115,19 +118,18 @@ impl<'a> System<'a> for Sys { // Scales let scale = scale_maybe.map_or(1.0, |s| s.0); let scale_b = scale_b_maybe.map_or(1.0, |s| s.0); - // TODO: don't do this here - let rad_b = 0.5 * scale_b; + let rad_b = body_b.radius() * scale_b; // Check if it is a hit if entity != b - && !stat_b.is_dead + && !stats_b.is_dead // Spherical wedge shaped attack field && pos.0.distance_squared(pos_b.0) < (rad_b + scale * ATTACK_RANGE).powi(2) && ori2.angle_between(pos_b2 - pos2) < ATTACK_ANGLE.to_radians() / 2.0 + (rad_b / pos2.distance(pos_b2)).atan() { // Weapon gives base damage let mut dmg = if let Some(ItemKind::Tool { power, .. }) = - stat.equipment.main.as_ref().map(|i| &i.kind) + attacker_stats.equipment.main.as_ref().map(|i| &i.kind) { *power as i32 } else { diff --git a/server/src/lib.rs b/server/src/lib.rs index f8815ad6cf..8804efe33f 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -413,21 +413,25 @@ impl Server { } } - // This sucks - let mut remove = false; + let mut remove = true; if let Some(client) = state.ecs().write_storage::().get_mut(entity) { - let _ = state + remove = false; + state .ecs() .write_storage() - .insert(entity, comp::Vel(Vec3::zero())); - let _ = state + .insert(entity, comp::Vel(Vec3::zero())) + .err() + .map(|err| error!("Failed to set zero vel on dead client: {:?}", err)); + state .ecs() .write_storage() - .insert(entity, comp::ForceUpdate); + .insert(entity, comp::ForceUpdate) + .err() + .map(|err| { + error!("Failed to insert ForceUpdate on dead client: {:?}", err) + }); client.force_state(ClientState::Dead); - } else { - remove = true; } if remove { diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index b9514a903b..6a20dbfbf0 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -756,10 +756,7 @@ impl Ui { } fn default_scissor(renderer: &Renderer) -> Aabr { - let (screen_w, screen_h) = renderer - .get_resolution() - .map(|e| (e as u16).max(1)) - .into_tuple(); + let (screen_w, screen_h) = renderer.get_resolution().into_tuple(); Aabr { min: Vec2 { x: 0, y: 0 }, max: Vec2 { From 6524ea31d11ef5f99b562e0b9ab463cfd8b68ac1 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 19 Dec 2019 23:28:37 -0500 Subject: [PATCH 16/51] Fix flight turning --- common/src/sys/movement.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/src/sys/movement.rs b/common/src/sys/movement.rs index f0f157b9ce..4c85dfc8cc 100644 --- a/common/src/sys/movement.rs +++ b/common/src/sys/movement.rs @@ -175,6 +175,10 @@ impl<'a> System<'a> for Sys { } else { Vec2::from(inputs.move_dir) } + } else if let Glide = character.movement { + // Note: non-gliding forces will also affect velocity and thus orientation + // producing potentially unexpected changes in direction + Vec2::from(vel.0) } else { Vec2::from(inputs.move_dir) }; From c60367e1beeb549174359df01931d85af3a6c127 Mon Sep 17 00:00:00 2001 From: Forest Anderson Date: Sun, 29 Dec 2019 12:28:00 +0000 Subject: [PATCH 17/51] Added changelog --- CHANGELOG.md | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..8f3e32f16c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,128 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +- Added new debug item +- Bows give experience by projectiles having an owner +- Allow cancelling chunk generation +- Include licence in assets +- Added dropping items +- Added initial region system implementation +- Added /giveitem command +- Strip Linux executables +- Added moon +- Added clouds +- Added tarpaulin coverage +- Added ability to jump while underwater +- Added proper SFX system +- Added changelog + +### Changed + +- Fixed near and far view planes +- Improvements to armor names +- Animation fixes to line up with true positions +- Proper message for command permission check failure +- Improved meshing +- Improved dusk +- Improved movement and climbing +- Improved water rendering and chunk render order +- Moved computations to terrain fragment shaders +- Fixed title music +- Made rolling less violent when changing directions +- Fixed singleplayer crash +- Improved error information in client and server +- Store items as RON files +- Updated download info in readme +- Fixed cloud performance +- Fixed region display name +- Fixed the bow fire rate + +### Removed + +- Remove heaptrack as it is now deprecated + +## [0.4.0] - 2019-10-10 + +### Added + +- Added adjustable FOV slider +- Added /explosion command +- Added first person switch +- Added singleplayer server settings +- Added admin check for commands +- Started asset reloading system +- Added SRGB conversion in shaders +- Added adminify to give temp admin privilages + +### Changed + +- Collision and fall damage fixes +- Switched to eventbus system +- Improved seed generation, diffusion function +- Switch to hashbrown in server/client +- Improved colors and lighting +- Replaced view distance culling with frustum culling + +## [0.3.0] - 2019-08-04 + +### Added + +- Added enemies +- Added player info to debug window +- Added server info +- Game settings persist after closing +- Added caves +- Added random NPC names +- Added tree roots, houses, basic lights +- Added XP and leveling +- Added build mode +- Character customization, multiple races +- Inventories (WIP) +- Day/night, better shaders, voxel shadows + +### Changed + +- Fixed attack delay +- Fixed disclaimer to show only once +- Only send physics updates for entities within view distance +- Fix for headphones and invalid device parameters +- Fixed asset names for consistancy +- Fixes animals jumping after their target no matter how far\ +- Improved SFX in caves +- Better combat, movement, and animations +- Many performance optimizations +- Better world generation, more biomes + +## [0.2.0] - 2019-05-28 + +### Added + +- Hang Gliding +- Pets: Pig and Wolf. They can be spawned with /pig and /wolf commands. +- Name tags: You can finally know who is this guy with the blue shirt! +- Singleplayer: No need to start a server just to play alone +- Character customization: It isn't fully complete but still allows you to look different than others +- Music! +- Major performance improvements related to the fact that we rewrote the entire game +- 0% chance to get a deadlock +- Animations: You finally can move your limbs! +- Combat: You can finally swing your sword that has been on your back. Enemies are coming soon, but you can always fight with other players +- When a server dies the game no longer crashes - you will be just kicked to the main menu + +## [0.1.0] - 2018-XX-XX + +_0.1.0 was part of the legacy engine_ + +[unreleased]: https://gitlab.com/veloren/veloren/compare?from=v0.4.0&to=master +[0.0.4]: https://gitlab.com/veloren/veloren/compare?from=v0.3.0&to=v0.4.0 +[0.0.3]: https://gitlab.com/veloren/veloren/compare?from=v0.2.0&to=v0.3.0 +[0.0.2]: https://gitlab.com/veloren/veloren/compare?from=7d17f8b67a2a6d5aa00730f028cedc430fd5075a&to=v0.2.0 +[0.0.1]: https://gitlab.com/veloren/game From badd3113d53e257049ef45d4c606552f770c29cd Mon Sep 17 00:00:00 2001 From: Dylan Kile Date: Sun, 29 Dec 2019 20:58:21 +0000 Subject: [PATCH 18/51] hierarchical pathfinding --- common/src/hierarchical.rs | 130 +++++++++++++++++++++++++++++++++++++ common/src/lib.rs | 1 + common/src/pathfinding.rs | 24 +++++-- common/src/sys/agent.rs | 6 +- server/src/cmd.rs | 4 +- 5 files changed, 157 insertions(+), 8 deletions(-) create mode 100644 common/src/hierarchical.rs diff --git a/common/src/hierarchical.rs b/common/src/hierarchical.rs new file mode 100644 index 0000000000..0bfe94aec7 --- /dev/null +++ b/common/src/hierarchical.rs @@ -0,0 +1,130 @@ +use crate::{ + astar::astar, + pathfinding::WorldPath, + vol::{ReadVol, RectRasterableVol}, + volumes::vol_grid_2d::VolGrid2d, +}; + +use std::fmt::Debug; +use vek::*; + +#[derive(Clone, Debug, Default)] +pub struct ChunkPath { + pub from: Vec3, + pub dest: Vec3, + pub chunk_path: Option>>, +} + +impl ChunkPath { + pub fn new( + vol: &VolGrid2d, + from: Vec3, + dest: Vec3, + ) -> Self { + let ifrom: Vec3 = Vec3::from(from.map(|e| e.floor() as i32)); + let idest: Vec3 = Vec3::from(dest.map(|e| e.floor() as i32)); + + let start_chunk = vol.pos_key(ifrom); + let end_chunk = vol.pos_key(idest); + + let chunk_path = astar( + start_chunk, + end_chunk, + chunk_euclidean_distance, + |pos| ChunkPath::chunk_get_neighbors(vol, pos), + chunk_transition_cost, + ); + + Self { + from, + dest, + chunk_path, + } + } + + pub fn chunk_get_neighbors( + _vol: &VolGrid2d, + pos: &Vec2, + ) -> impl IntoIterator> { + let directions = vec![ + Vec2::new(1, 0), // Right chunk + Vec2::new(-1, 0), // Left chunk + Vec2::new(0, 1), // Top chunk + Vec2::new(0, -1), // Bottom chunk + ]; + + let neighbors: Vec> = directions.into_iter().map(|dir| dir + pos).collect(); + + neighbors.into_iter() + } + pub fn worldpath_get_neighbors( + &mut self, + vol: &VolGrid2d, + pos: Vec3, + ) -> impl IntoIterator> { + let directions = vec![ + Vec3::new(0, 1, 0), // Forward + Vec3::new(0, 1, 1), // Forward upward + Vec3::new(0, 1, 2), // Forward Upwardx2 + Vec3::new(0, 1, -1), // Forward downward + Vec3::new(1, 0, 0), // Right + Vec3::new(1, 0, 1), // Right upward + Vec3::new(1, 0, 2), // Right Upwardx2 + Vec3::new(1, 0, -1), // Right downward + Vec3::new(0, -1, 0), // Backwards + Vec3::new(0, -1, 1), // Backward Upward + Vec3::new(0, -1, 2), // Backward Upwardx2 + Vec3::new(0, -1, -1), // Backward downward + Vec3::new(-1, 0, 0), // Left + Vec3::new(-1, 0, 1), // Left upward + Vec3::new(-1, 0, 2), // Left Upwardx2 + Vec3::new(-1, 0, -1), // Left downward + ]; + + let neighbors: Vec> = directions + .into_iter() + .map(|dir| dir + pos) + .filter(|new_pos| self.is_valid_space(vol, *new_pos)) + .collect(); + neighbors.into_iter() + } + pub fn is_valid_space( + &mut self, + vol: &VolGrid2d, + pos: Vec3, + ) -> bool { + let is_walkable_position = WorldPath::is_walkable_space(vol, pos); + let mut is_within_chunk = false; + match self.chunk_path.clone() { + Some(chunk_path) => { + is_within_chunk = chunk_path + .iter() + .any(|new_pos| new_pos.cmpeq(&vol.pos_key(pos)).iter().all(|e| *e)); + } + _ => { + println!("No chunk path"); + } + } + return is_walkable_position && is_within_chunk; + } + pub fn get_worldpath( + &mut self, + vol: &VolGrid2d, + ) -> WorldPath { + let wp = WorldPath::new(vol, self.from, self.dest, |vol, pos| { + self.worldpath_get_neighbors(vol, *pos) + }); + println!("Fetching world path from hierarchical path: {:?}", wp); + wp + } +} + +pub fn chunk_euclidean_distance(start: &Vec2, end: &Vec2) -> f32 { + let istart = start.map(|e| e as f32); + let iend = end.map(|e| e as f32); + istart.distance(iend) +} + +pub fn chunk_transition_cost(_start: &Vec2, _end: &Vec2) -> f32 { + 1.0f32 +} diff --git a/common/src/lib.rs b/common/src/lib.rs index 2550d7db7e..8540e359fb 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -14,6 +14,7 @@ pub mod comp; pub mod effect; pub mod event; pub mod figure; +pub mod hierarchical; pub mod msg; pub mod npc; pub mod pathfinding; diff --git a/common/src/pathfinding.rs b/common/src/pathfinding.rs index 26bc6e5ef5..f970498141 100644 --- a/common/src/pathfinding.rs +++ b/common/src/pathfinding.rs @@ -13,19 +13,31 @@ pub struct WorldPath { } impl WorldPath { - pub fn new(vol: &V, from: Vec3, dest: Vec3) -> Self { + pub fn new( + vol: &V, + from: Vec3, + dest: Vec3, + get_neighbors: impl FnMut(&V, &Vec3) -> I, + ) -> Self + where + I: IntoIterator>, + { let ifrom: Vec3 = Vec3::from(from.map(|e| e.floor() as i32)); let idest: Vec3 = Vec3::from(dest.map(|e| e.floor() as i32)); - let path = WorldPath::get_path(vol, ifrom, idest); + let path = WorldPath::get_path(vol, ifrom, idest, get_neighbors); Self { from, dest, path } } - pub fn get_path( + pub fn get_path( vol: &V, from: Vec3, dest: Vec3, - ) -> Option>> { + mut get_neighbors: impl FnMut(&V, &Vec3) -> I, + ) -> Option>> + where + I: IntoIterator>, + { let new_start = WorldPath::get_z_walkable_space(vol, from); let new_dest = WorldPath::get_z_walkable_space(vol, dest); @@ -34,7 +46,7 @@ impl WorldPath { new_start, new_dest, euclidean_distance, - |pos| WorldPath::get_neighbors(vol, pos), + |pos| get_neighbors(vol, pos), transition_cost, ) } else { @@ -136,7 +148,7 @@ impl WorldPath { if let Some(mut block_path) = self.path.clone() { if let Some(next_pos) = block_path.clone().last() { if self.path_is_blocked(vol) { - self.path = WorldPath::get_path(vol, ipos, idest) + self.path = WorldPath::get_path(vol, ipos, idest, WorldPath::get_neighbors); } if Vec2::::from(ipos) == Vec2::::from(*next_pos) { diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index 5ce18dacab..ed337de06c 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -1,6 +1,7 @@ use crate::comp::{ Agent, CharacterState, Controller, MountState, MovementState::Glide, Pos, Stats, }; +use crate::hierarchical::ChunkPath; use crate::pathfinding::WorldPath; use crate::terrain::TerrainGrid; use rand::{seq::SliceRandom, thread_rng}; @@ -72,7 +73,10 @@ impl<'a> System<'a> for Sys { const MAX_TRAVEL_DIST: f32 = 200.0; let new_dest = Vec3::new(rand::random::(), rand::random::(), 0.0) * MAX_TRAVEL_DIST; - new_path = Some(WorldPath::new(&*terrain, pos.0, pos.0 + new_dest)); + new_path = Some( + ChunkPath::new(&*terrain, pos.0, pos.0 + new_dest) + .get_worldpath(&*terrain), + ); }; path.move_along_path( diff --git a/server/src/cmd.rs b/server/src/cmd.rs index cca446f1a9..36793f6e66 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -7,6 +7,7 @@ use chrono::{NaiveTime, Timelike}; use common::{ assets, comp, event::{EventBus, ServerEvent}, + hierarchical::ChunkPath, msg::ServerMsg, npc::{get_npc_name, NpcKind}, pathfinding::WorldPath, @@ -517,7 +518,8 @@ fn handle_pathfind(server: &mut Server, player: EcsEntity, args: String, action: .read_component_cloned::(target_entity) { let target = start_pos.0 + Vec3::new(x, y, z); - let new_path = WorldPath::new(&*server.state.terrain(), start_pos.0, target); + let new_path = ChunkPath::new(&*server.state.terrain(), start_pos.0, target) + .get_worldpath(&*server.state.terrain()); server.state.write_component( target_entity, From ec3e0750203d9dc97ddfbce76418bc47a12172d0 Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 23 Dec 2019 01:02:00 -0500 Subject: [PATCH 19/51] fix(player list): Show players not in range on the player list fix(overflow): Stops including block updates that fail (since chunks don't exist on the client) in `TerrainUpdates` (which would trigger meshing of those nonexistent chunks). Furthermore, removes remeshing of chunks with block updates if those chunks don't have all their neighbours (since those wouldn't be meshed in the first place). --- client/src/lib.rs | 52 +++++++++++++++++++---------- common/src/msg/client.rs | 2 +- common/src/msg/mod.rs | 2 +- common/src/msg/server.rs | 9 +++++ common/src/state.rs | 13 +++----- common/src/volumes/vol_grid_2d.rs | 7 +++- server/src/cmd.rs | 17 ++++++++-- server/src/lib.rs | 13 +++++++- server/src/sys/message.rs | 40 ++++++++++++++++++++-- server/src/sys/terrain.rs | 3 ++ voxygen/src/hud/social.rs | 35 ++++++++------------ voxygen/src/scene/terrain.rs | 55 ++++++++++++++++++++----------- 12 files changed, 174 insertions(+), 74 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index 6cb7658c64..932add96d5 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -10,8 +10,8 @@ pub use specs::{join::Join, saveload::Marker, Entity as EcsEntity, ReadStorage, use common::{ comp::{self, ControlEvent, Controller, ControllerInputs, InventoryManip}, msg::{ - validate_chat_msg, ChatMsgValidationError, ClientMsg, ClientState, RequestStateError, - ServerError, ServerInfo, ServerMsg, MAX_BYTES_CHAT_MSG, + validate_chat_msg, ChatMsgValidationError, ClientMsg, ClientState, PlayerListUpdate, + RequestStateError, ServerError, ServerInfo, ServerMsg, MAX_BYTES_CHAT_MSG, }, net::PostBox, state::State, @@ -52,6 +52,7 @@ pub struct Client { thread_pool: ThreadPool, pub server_info: ServerInfo, pub world_map: Arc, + pub player_list: HashMap, postbox: PostBox, @@ -71,7 +72,6 @@ pub struct Client { impl Client { /// Create a new `Client`. - #[allow(dead_code)] pub fn new>(addr: A, view_distance: Option) -> Result { let client_state = ClientState::Connected; let mut postbox = PostBox::to(addr)?; @@ -137,6 +137,7 @@ impl Client { thread_pool, server_info, world_map, + player_list: HashMap::new(), postbox, @@ -154,7 +155,6 @@ impl Client { }) } - #[allow(dead_code)] pub fn with_thread_pool(mut self, thread_pool: ThreadPool) -> Self { self.thread_pool = thread_pool; self @@ -282,7 +282,6 @@ impl Client { } /// Send a chat message to the server. - #[allow(dead_code)] pub fn send_chat(&mut self, msg: String) { match validate_chat_msg(&msg) { Ok(()) => self.postbox.send_message(ClientMsg::chat(msg)), @@ -294,7 +293,6 @@ impl Client { } /// Remove all cached terrain - #[allow(dead_code)] pub fn clear_terrain(&mut self) { self.state.clear_terrain(); self.pending_chunks.clear(); @@ -316,7 +314,6 @@ impl Client { } /// Execute a single client tick, handle input and update the game state by the given duration. - #[allow(dead_code)] pub fn tick(&mut self, inputs: ControllerInputs, dt: Duration) -> Result, Error> { // This tick function is the centre of the Veloren universe. Most client-side things are // managed from here, and as such it's important that it stays organised. Please consult @@ -389,6 +386,10 @@ impl Client { // Remove chunks that are too far from the player. let mut chunks_to_remove = Vec::new(); self.state.terrain().iter().for_each(|(key, _)| { + // Subtract 2 from the offset before computing squared magnitude + // 1 for the chunks needed bordering other chunks for meshing + // 1 as a buffer so that if the player moves back in that direction the chunks + // don't need to be reloaded if (chunk_pos - key) .map(|e: i32| (e.abs() as u32).checked_sub(2).unwrap_or(0)) .magnitude_squared() @@ -492,7 +493,6 @@ impl Client { } /// Clean up the client after a tick. - #[allow(dead_code)] pub fn cleanup(&mut self) { // Cleanup the local state self.state.cleanup(); @@ -531,6 +531,27 @@ impl Client { }, ServerMsg::Shutdown => return Err(Error::ServerShutdown), ServerMsg::InitialSync { .. } => return Err(Error::ServerWentMad), + ServerMsg::PlayerListUpdate(PlayerListUpdate::Init(list)) => { + self.player_list = list + } + ServerMsg::PlayerListUpdate(PlayerListUpdate::Add(uid, name)) => { + if let Some(old_name) = self.player_list.insert(uid, name.clone()) { + warn!("Received msg to insert {} with uid {} into the player list but there was already an entry for {} with the same uid that was overwritten!", name, uid, old_name); + } + } + ServerMsg::PlayerListUpdate(PlayerListUpdate::Remove(uid)) => { + if self.player_list.remove(&uid).is_none() { + warn!("Received msg to remove uid {} from the player list by they weren't in the list!", uid); + } + } + ServerMsg::PlayerListUpdate(PlayerListUpdate::Alias(uid, new_name)) => { + if let Some(name) = self.player_list.get_mut(&uid) { + *name = new_name; + } else { + warn!("Received msg to alias player with uid {} to {} but this uid is not in the player list", uid, new_name); + } + } + ServerMsg::Ping => self.postbox.send_message(ClientMsg::Pong), ServerMsg::Pong => { self.last_server_pong = Instant::now(); @@ -602,9 +623,11 @@ impl Client { } self.pending_chunks.remove(&key); } - ServerMsg::TerrainBlockUpdates(mut blocks) => blocks - .drain() - .for_each(|(pos, block)| self.state.set_block(pos, block)), + ServerMsg::TerrainBlockUpdates(mut blocks) => { + blocks.drain().for_each(|(pos, block)| { + self.state.set_block(pos, block); + }); + } ServerMsg::StateAnswer(Ok(state)) => { self.client_state = state; } @@ -636,24 +659,20 @@ impl Client { } /// Get the player's entity. - #[allow(dead_code)] pub fn entity(&self) -> EcsEntity { self.entity } /// Get the client state - #[allow(dead_code)] pub fn get_client_state(&self) -> ClientState { self.client_state } /// Get the current tick number. - #[allow(dead_code)] pub fn get_tick(&self) -> u64 { self.tick } - #[allow(dead_code)] pub fn get_ping_ms(&self) -> f64 { self.last_ping_delta * 1000.0 } @@ -661,19 +680,16 @@ impl Client { /// Get a reference to the client's worker thread pool. This pool should be used for any /// computationally expensive operations that run outside of the main thread (i.e., threads that /// block on I/O operations are exempt). - #[allow(dead_code)] pub fn thread_pool(&self) -> &ThreadPool { &self.thread_pool } /// Get a reference to the client's game state. - #[allow(dead_code)] pub fn state(&self) -> &State { &self.state } /// Get a mutable reference to the client's game state. - #[allow(dead_code)] pub fn state_mut(&mut self) -> &mut State { &mut self.state } diff --git a/common/src/msg/client.rs b/common/src/msg/client.rs index b8e26f95cc..2b031db3f1 100644 --- a/common/src/msg/client.rs +++ b/common/src/msg/client.rs @@ -23,7 +23,7 @@ pub enum ClientMsg { Ping, Pong, ChatMsg { - chat_type: ChatType, + chat_type: ChatType, // This is unused afaik, TODO: remove message: String, }, PlayerPhysics { diff --git a/common/src/msg/mod.rs b/common/src/msg/mod.rs index 12f72addf5..13fc0eeb64 100644 --- a/common/src/msg/mod.rs +++ b/common/src/msg/mod.rs @@ -5,7 +5,7 @@ pub mod server; // Reexports pub use self::client::ClientMsg; pub use self::ecs_packet::EcsCompPacket; -pub use self::server::{RequestStateError, ServerError, ServerInfo, ServerMsg}; +pub use self::server::{PlayerListUpdate, RequestStateError, ServerError, ServerInfo, ServerMsg}; #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] pub enum ClientState { diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index 7b922527d4..710d8a4dfa 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -23,6 +23,14 @@ pub struct ServerInfo { pub git_date: String, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum PlayerListUpdate { + Init(HashMap), + Add(u64, String), + Remove(u64), + Alias(u64, String), +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub enum ServerMsg { InitialSync { @@ -31,6 +39,7 @@ pub enum ServerMsg { time_of_day: state::TimeOfDay, // world_map: Vec2, /*, Vec)*/ }, + PlayerListUpdate(PlayerListUpdate), StateAnswer(Result), ForceState(ClientState), Ping, diff --git a/common/src/state.rs b/common/src/state.rs index 5e19b25c43..6966d3b1cc 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -326,17 +326,14 @@ impl State { // Apply terrain changes let mut terrain = self.ecs.write_resource::(); - self.ecs - .read_resource::() - .blocks - .iter() - .for_each(|(pos, block)| { - let _ = terrain.set(*pos, *block); - }); - self.ecs.write_resource::().modified_blocks = std::mem::replace( + let mut modified_blocks = std::mem::replace( &mut self.ecs.write_resource::().blocks, Default::default(), ); + // Apply block modifications + // Only include in `TerrainChanges` if successful + modified_blocks.retain(|pos, block| terrain.set(*pos, *block).is_ok()); + self.ecs.write_resource::().modified_blocks = modified_blocks; // Process local events let events = self.ecs.read_resource::>().recv_all(); diff --git a/common/src/volumes/vol_grid_2d.rs b/common/src/volumes/vol_grid_2d.rs index 0086bd4ee4..00e21a19aa 100644 --- a/common/src/volumes/vol_grid_2d.rs +++ b/common/src/volumes/vol_grid_2d.rs @@ -167,6 +167,8 @@ impl VolGrid2d { pub struct CachedVolGrid2d<'a, V: RectRasterableVol> { vol_grid_2d: &'a VolGrid2d, + // This can't be invalidated by mutations of the chunks hashmap since we hold an immutable + // reference to the `VolGrid2d` cache: Option<(Vec2, Arc)>, } impl<'a, V: RectRasterableVol> CachedVolGrid2d<'a, V> { @@ -178,9 +180,9 @@ impl<'a, V: RectRasterableVol> CachedVolGrid2d<'a, V> { } } impl<'a, V: RectRasterableVol + ReadVol> CachedVolGrid2d<'a, V> { - // Note: this may be invalidated by mutations of the chunks hashmap #[inline(always)] pub fn get(&mut self, pos: Vec3) -> Result<&V::Vox, VolGrid2dError> { + // Calculate chunk key from block pos let ck = VolGrid2d::::chunk_key(pos); let chunk = if self .cache @@ -188,13 +190,16 @@ impl<'a, V: RectRasterableVol + ReadVol> CachedVolGrid2d<'a, V> { .map(|(key, _)| *key == ck) .unwrap_or(false) { + // If the chunk with that key is in the cache use that &self.cache.as_ref().unwrap().1 } else { + // Otherwise retrieve from the hashmap let chunk = self .vol_grid_2d .chunks .get(&ck) .ok_or(VolGrid2dError::NoSuchChunk)?; + // Store most recently looked up chunk in the cache self.cache = Some((ck, chunk.clone())); chunk }; diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 36793f6e66..9f0cc61b46 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -8,11 +8,11 @@ use common::{ assets, comp, event::{EventBus, ServerEvent}, hierarchical::ChunkPath, - msg::ServerMsg, + msg::{PlayerListUpdate, ServerMsg}, npc::{get_npc_name, NpcKind}, pathfinding::WorldPath, state::TimeOfDay, - sync::WorldSyncExt, + sync::{Uid, WorldSyncExt}, terrain::{Block, BlockKind, TerrainChunkSize}, vol::RectVolSize, }; @@ -407,6 +407,19 @@ fn handle_alias(server: &mut Server, entity: EcsEntity, args: String, action: &C .write_storage::() .get_mut(entity) .map(|player| player.alias = alias); + + // Update name on client player lists + let ecs = server.state.ecs(); + if let (Some(uid), Some(player)) = ( + ecs.read_storage::().get(entity), + ecs.read_storage::().get(entity), + ) { + let msg = ServerMsg::PlayerListUpdate(PlayerListUpdate::Alias( + (*uid).into(), + player.alias.clone(), + )); + server.state.notify_registered_clients(msg); + } } else { server.notify_client(entity, ServerMsg::private(String::from(action.help_string))); } diff --git a/server/src/lib.rs b/server/src/lib.rs index 8804efe33f..24429bd6c7 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -25,7 +25,7 @@ use common::{ assets, comp, effect::Effect, event::{EventBus, ServerEvent}, - msg::{ClientMsg, ClientState, ServerError, ServerInfo, ServerMsg}, + msg::{ClientMsg, ClientState, PlayerListUpdate, ServerError, ServerInfo, ServerMsg}, net::PostOffice, state::{BlockChange, State, TimeOfDay}, sync::{Uid, WorldSyncExt}, @@ -762,6 +762,17 @@ impl Server { } ServerEvent::ClientDisconnect(entity) => { + // Tell other clients to remove from player list + if let (Some(uid), Some(_)) = ( + state.read_storage::().get(entity), + state.read_storage::().get(entity), + ) { + state.notify_registered_clients(ServerMsg::PlayerListUpdate( + PlayerListUpdate::Remove((*uid).into()), + )) + } + + // Delete client entity if let Err(err) = state.delete_entity_recorded(entity) { error!("Failed to delete disconnected client: {:?}", err); } diff --git a/server/src/sys/message.rs b/server/src/sys/message.rs index 6537e4e01a..b7b47c0215 100644 --- a/server/src/sys/message.rs +++ b/server/src/sys/message.rs @@ -3,12 +3,16 @@ use crate::{auth_provider::AuthProvider, client::Client, CLIENT_TIMEOUT}; use common::{ comp::{Admin, Body, CanBuild, Controller, ForceUpdate, Ori, Player, Pos, Vel}, event::{EventBus, ServerEvent}, - msg::{validate_chat_msg, ChatMsgValidationError, MAX_BYTES_CHAT_MSG}, - msg::{ClientMsg, ClientState, RequestStateError, ServerMsg}, + msg::{ + validate_chat_msg, ChatMsgValidationError, ClientMsg, ClientState, PlayerListUpdate, + RequestStateError, ServerMsg, MAX_BYTES_CHAT_MSG, + }, state::{BlockChange, Time}, + sync::Uid, terrain::{Block, TerrainGrid}, vol::Vox, }; +use hashbrown::HashMap; use specs::{ Entities, Join, Read, ReadExpect, ReadStorage, System, Write, WriteExpect, WriteStorage, }; @@ -22,6 +26,7 @@ impl<'a> System<'a> for Sys { Read<'a, Time>, ReadExpect<'a, TerrainGrid>, Write<'a, SysTimer>, + ReadStorage<'a, Uid>, ReadStorage<'a, Body>, ReadStorage<'a, CanBuild>, ReadStorage<'a, Admin>, @@ -44,6 +49,7 @@ impl<'a> System<'a> for Sys { time, terrain, mut timer, + uids, bodies, can_build, admins, @@ -64,6 +70,14 @@ impl<'a> System<'a> for Sys { let mut new_chat_msgs = Vec::new(); + // Player list to send new players. + let player_list = (&uids, &players) + .join() + .map(|(uid, player)| ((*uid).into(), player.alias.clone())) + .collect::>(); + // List of new players to update player lists of all clients. + let mut new_players = Vec::new(); + for (entity, client) in (&entities, &mut clients).join() { let mut disconnect = false; let new_msgs = client.postbox.new_messages(); @@ -127,10 +141,18 @@ impl<'a> System<'a> for Sys { } match client.client_state { ClientState::Connected => { + // Add Player component to this client let _ = players.insert(entity, player); // Tell the client its request was successful. client.allow_state(ClientState::Registered); + + // Send initial player list + client.notify(ServerMsg::PlayerListUpdate(PlayerListUpdate::Init( + player_list.clone(), + ))); + // Add to list to notify all clients of the new player + new_players.push(entity); } // Use RequestState instead (No need to send `player` again). _ => client.error_state(RequestStateError::Impossible), @@ -281,6 +303,20 @@ impl<'a> System<'a> for Sys { } } + // Handle new players. + // Tell all clients to add them to the player list. + for entity in new_players { + if let (Some(uid), Some(player)) = (uids.get(entity), players.get(entity)) { + let msg = ServerMsg::PlayerListUpdate(PlayerListUpdate::Add( + (*uid).into(), + player.alias.clone(), + )); + for client in (&mut clients).join().filter(|c| c.is_registered()) { + client.notify(msg.clone()) + } + } + } + // Handle new chat messages. for (entity, msg) in new_chat_msgs { match msg { diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index af9dee1c74..c9560c4b81 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -71,6 +71,9 @@ impl<'a> System<'a> for Sys { }) { let chunk_pos = terrain.pos_key(pos.0.map(|e| e as i32)); + // Subtract 2 from the offset before computing squared magnitude + // 1 since chunks need neighbors to be meshed + // 1 to act as a buffer if the player moves in that direction let adjusted_dist_sqr = (Vec2::from(chunk_pos) - Vec2::from(key)) .map(|e: i32| (e.abs() as u32).checked_sub(2).unwrap_or(0)) .magnitude_squared(); diff --git a/voxygen/src/hud/social.rs b/voxygen/src/hud/social.rs index b57ab9226c..9cdea0e1c3 100644 --- a/voxygen/src/hud/social.rs +++ b/voxygen/src/hud/social.rs @@ -1,13 +1,11 @@ use super::{img_ids::Imgs, Fonts, Show, TEXT_COLOR, TEXT_COLOR_3}; -use common::comp; use conrod_core::{ color, widget::{self, Button, Image, Rectangle, Scrollbar, Text}, widget_ids, /*, Color*/ Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; -use specs::{Join, WorldExt}; use client::{self, Client}; @@ -178,25 +176,12 @@ impl<'a> Widget for Social<'a> { // Players list // TODO: this list changes infrequently enough that it should not have to be recreated every frame - let ecs = self.client.state().ecs(); - let players = ecs.read_storage::(); - let mut count = 0; - for player in players.join() { - if ids.player_names.len() <= count { - ids.update(|ids| { - ids.player_names - .resize(count + 1, &mut ui.widget_id_generator()) - }) - } - - Text::new(&player.alias) - .down_from(ids.online_title, count as f64 * (15.0 + 3.0)) - .font_size(15) - .font_id(self.fonts.cyri) - .color(TEXT_COLOR) - .set(ids.player_names[count], ui); - - count += 1; + let count = self.client.player_list.len(); + if ids.player_names.len() < count { + ids.update(|ids| { + ids.player_names + .resize(count, &mut ui.widget_id_generator()) + }) } Text::new(&format!("{} player(s) online\n", count)) .top_left_with_margins_on(ids.content_align, -2.0, 7.0) @@ -204,6 +189,14 @@ impl<'a> Widget for Social<'a> { .font_id(self.fonts.cyri) .color(TEXT_COLOR) .set(ids.online_title, ui); + for (i, (_, player_alias)) in self.client.player_list.iter().enumerate() { + Text::new(player_alias) + .down(3.0) + .font_size(15) + .font_id(self.fonts.cyri) + .color(TEXT_COLOR) + .set(ids.player_names[i], ui); + } } // Friends Tab diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 02ffd92ec1..93202101e2 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -17,7 +17,7 @@ use common::{ use crossbeam::channel; use dot_vox::DotVoxData; use frustum_query::frustum::Frustum; -use hashbrown::HashMap; +use hashbrown::{hash_map::Entry, HashMap}; use std::{f32, fmt::Debug, i32, marker::PhantomData, ops::Mul, time::Duration}; use vek::*; @@ -836,31 +836,48 @@ impl Terrain { .map(|(p, _)| *p) { let chunk_pos = client.state().terrain().pos_key(pos); + let new_mesh_state = ChunkMeshState { + pos: chunk_pos, + started_tick: current_tick, + active_worker: None, + }; + // Only mesh if this chunk has all its neighbors + // If it does have all its neighbors either it should have already been meshed or is in + // mesh_todo + match self.mesh_todo.entry(chunk_pos) { + Entry::Occupied(mut entry) => { + entry.insert(new_mesh_state); + } + Entry::Vacant(entry) => { + if self.chunks.contains_key(&chunk_pos) { + entry.insert(new_mesh_state); + } + } + } - self.mesh_todo.insert( - chunk_pos, - ChunkMeshState { - pos: chunk_pos, - started_tick: current_tick, - active_worker: None, - }, - ); - - // Handle chunks on chunk borders + // Handle block changes on chunk borders for x in -1..2 { for y in -1..2 { let neighbour_pos = pos + Vec3::new(x, y, 0); let neighbour_chunk_pos = client.state().terrain().pos_key(neighbour_pos); if neighbour_chunk_pos != chunk_pos { - self.mesh_todo.insert( - neighbour_chunk_pos, - ChunkMeshState { - pos: neighbour_chunk_pos, - started_tick: current_tick, - active_worker: None, - }, - ); + let new_mesh_state = ChunkMeshState { + pos: neighbour_chunk_pos, + started_tick: current_tick, + active_worker: None, + }; + // Only mesh if this chunk has all its neighbors + match self.mesh_todo.entry(neighbour_chunk_pos) { + Entry::Occupied(mut entry) => { + entry.insert(new_mesh_state); + } + Entry::Vacant(entry) => { + if self.chunks.contains_key(&neighbour_chunk_pos) { + entry.insert(new_mesh_state); + } + } + } } // TODO: Remesh all neighbours because we have complex lighting now From 8aff5faa83d344ab00c6b72d286ff9bea717dc9d Mon Sep 17 00:00:00 2001 From: Monty Marz Date: Mon, 30 Dec 2019 12:16:35 +0000 Subject: [PATCH 20/51] assets update acacia trees updated help.png bigger map zone name npc levels from 0-10 boss levels from 20-50 --- CHANGELOG.md | 3 + Cargo.toml | 2 +- assets/common/items/weapons/hammer_1.ron | 8 + assets/common/items/weapons/staff_1.ron | 8 + assets/common/items/weapons/starter_axe.ron | 2 +- assets/common/items/weapons/starter_bow.ron | 2 +- .../common/items/weapons/starter_dagger.ron | 2 +- .../common/items/weapons/starter_hammer.ron | 2 +- assets/common/items/weapons/starter_staff.ron | 2 +- assets/common/items/weapons/starter_sword.ron | 2 +- .../element/buttons/indicator_mmap.vox | 4 +- .../element/buttons/indicator_mmap_2.vox | 3 + .../element/buttons/indicator_mmap_3.vox | 3 + .../buttons/min_plus/mmap_button-min.vox | 3 + .../min_plus/mmap_button-min_hover.vox | 3 + .../min_plus/mmap_button-min_press.vox | 3 + .../buttons/min_plus/mmap_button-plus.vox | 3 + .../min_plus/mmap_button-plus_hover.vox | 3 + .../min_plus/mmap_button-plus_press.vox | 3 + assets/voxygen/element/frames/enemybar.vox | 3 + assets/voxygen/element/help.png | 4 +- assets/voxygen/element/icons/skull.vox | 3 + assets/voxygen/element/icons/skull_2.vox | 3 + assets/voxygen/voxel/armor/back/short-0.vox | 3 + assets/voxygen/voxel/npc/oger/belt.vox | 3 + assets/voxygen/voxel/npc/oger/chest.vox | 3 + assets/voxygen/voxel/npc/oger/foot.vox | 3 + assets/voxygen/voxel/npc/oger/hand-l.vox | 3 + assets/voxygen/voxel/npc/oger/hand-r.vox | 3 + assets/voxygen/voxel/npc/oger/head.vox | 3 + assets/voxygen/voxel/npc/oger/legs.vox | 3 + assets/voxygen/voxel/npc/oger/shoulder.vox | 3 + .../voxel/weapon/hammer/hammer_1_2h.vox | 3 + .../voxel/weapon/staff/wood-simple.vox | 3 + assets/world/tree/acacia/1.vox | 4 +- assets/world/tree/acacia/2.vox | 4 +- assets/world/tree/acacia/3.vox | 4 +- assets/world/tree/acacia/4.vox | 4 +- assets/world/tree/acacia/5.vox | 4 +- assets/world/tree/acacia_savannah/1.vox | 3 + assets/world/tree/acacia_savannah/2.vox | 3 + assets/world/tree/acacia_savannah/3.vox | 3 + assets/world/tree/acacia_savannah/4.vox | 3 + assets/world/tree/acacia_savannah/5.vox | 3 + common/src/comp/body/giant.rs | 69 +++++ server/src/sys/message.rs | 1 + server/src/sys/terrain.rs | 18 +- voxygen/src/hud/img_ids.rs | 14 + voxygen/src/hud/map.rs | 43 +++- voxygen/src/hud/minimap.rs | 74 +++++- voxygen/src/hud/mod.rs | 242 +++++++++++++----- voxygen/src/hud/settings_window.rs | 4 +- voxygen/src/hud/skillbar.rs | 8 +- voxygen/src/session.rs | 1 + 54 files changed, 498 insertions(+), 118 deletions(-) create mode 100644 assets/common/items/weapons/hammer_1.ron create mode 100644 assets/common/items/weapons/staff_1.ron create mode 100644 assets/voxygen/element/buttons/indicator_mmap_2.vox create mode 100644 assets/voxygen/element/buttons/indicator_mmap_3.vox create mode 100644 assets/voxygen/element/buttons/min_plus/mmap_button-min.vox create mode 100644 assets/voxygen/element/buttons/min_plus/mmap_button-min_hover.vox create mode 100644 assets/voxygen/element/buttons/min_plus/mmap_button-min_press.vox create mode 100644 assets/voxygen/element/buttons/min_plus/mmap_button-plus.vox create mode 100644 assets/voxygen/element/buttons/min_plus/mmap_button-plus_hover.vox create mode 100644 assets/voxygen/element/buttons/min_plus/mmap_button-plus_press.vox create mode 100644 assets/voxygen/element/frames/enemybar.vox create mode 100644 assets/voxygen/element/icons/skull.vox create mode 100644 assets/voxygen/element/icons/skull_2.vox create mode 100644 assets/voxygen/voxel/armor/back/short-0.vox create mode 100644 assets/voxygen/voxel/npc/oger/belt.vox create mode 100644 assets/voxygen/voxel/npc/oger/chest.vox create mode 100644 assets/voxygen/voxel/npc/oger/foot.vox create mode 100644 assets/voxygen/voxel/npc/oger/hand-l.vox create mode 100644 assets/voxygen/voxel/npc/oger/hand-r.vox create mode 100644 assets/voxygen/voxel/npc/oger/head.vox create mode 100644 assets/voxygen/voxel/npc/oger/legs.vox create mode 100644 assets/voxygen/voxel/npc/oger/shoulder.vox create mode 100644 assets/voxygen/voxel/weapon/hammer/hammer_1_2h.vox create mode 100644 assets/voxygen/voxel/weapon/staff/wood-simple.vox create mode 100644 assets/world/tree/acacia_savannah/1.vox create mode 100644 assets/world/tree/acacia_savannah/2.vox create mode 100644 assets/world/tree/acacia_savannah/3.vox create mode 100644 assets/world/tree/acacia_savannah/4.vox create mode 100644 assets/world/tree/acacia_savannah/5.vox create mode 100644 common/src/comp/body/giant.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f3e32f16c..bec6a47843 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added ability to jump while underwater - Added proper SFX system - Added changelog +- Added animated Map and Minimap position indicator +- Added visuals to indicate strength compared to the player ### Changed @@ -44,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed cloud performance - Fixed region display name - Fixed the bow fire rate +- Healthbars now flash on critical health ### Removed diff --git a/Cargo.toml b/Cargo.toml index 4c463c2db7..9c674add42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ members = [ # default profile for devs, fast to compile, okay enough to run, no debug information [profile.dev] opt-level = 2 -overflow-checks = true +overflow-checks = false debug-assertions = true panic = "abort" debug = false diff --git a/assets/common/items/weapons/hammer_1.ron b/assets/common/items/weapons/hammer_1.ron new file mode 100644 index 0000000000..badb1732cc --- /dev/null +++ b/assets/common/items/weapons/hammer_1.ron @@ -0,0 +1,8 @@ +Item( + name: "Crude Mallet", + description: "Breaks bones like sticks and stones.", + kind: Tool( + kind: Hammer, + power: 20, + ), +) diff --git a/assets/common/items/weapons/staff_1.ron b/assets/common/items/weapons/staff_1.ron new file mode 100644 index 0000000000..59e41d09ed --- /dev/null +++ b/assets/common/items/weapons/staff_1.ron @@ -0,0 +1,8 @@ +Item( + name: "Humble Stick", + description: "Walking stick with a sharpened end.", + kind: Tool( + kind: Hammer, + power: 6, + ), +) diff --git a/assets/common/items/weapons/starter_axe.ron b/assets/common/items/weapons/starter_axe.ron index 74d97b8864..7a27c1e6db 100644 --- a/assets/common/items/weapons/starter_axe.ron +++ b/assets/common/items/weapons/starter_axe.ron @@ -3,6 +3,6 @@ Item( description: "Every dent tells the story of a chopped tree.", kind: Tool( kind: Axe, - power: 10, + power: 15, ), ) diff --git a/assets/common/items/weapons/starter_bow.ron b/assets/common/items/weapons/starter_bow.ron index d59933630c..0be646d0e3 100644 --- a/assets/common/items/weapons/starter_bow.ron +++ b/assets/common/items/weapons/starter_bow.ron @@ -3,6 +3,6 @@ Item( description: "Someone carved his initials into it...", kind: Tool( kind: Bow, - power: 10, + power: 15, ), ) diff --git a/assets/common/items/weapons/starter_dagger.ron b/assets/common/items/weapons/starter_dagger.ron index e374c14160..88b4990620 100644 --- a/assets/common/items/weapons/starter_dagger.ron +++ b/assets/common/items/weapons/starter_dagger.ron @@ -3,6 +3,6 @@ Item( description: "Great for cutting meat.", kind: Tool( kind: Dagger, - power: 10, + power: 15, ), ) diff --git a/assets/common/items/weapons/starter_hammer.ron b/assets/common/items/weapons/starter_hammer.ron index 02e0840e17..c27875a5c2 100644 --- a/assets/common/items/weapons/starter_hammer.ron +++ b/assets/common/items/weapons/starter_hammer.ron @@ -3,6 +3,6 @@ Item( description: "'Property of...' The rest is missing. ", kind: Tool( kind: Hammer, - power: 10, + power: 15, ), ) diff --git a/assets/common/items/weapons/starter_staff.ron b/assets/common/items/weapons/starter_staff.ron index f2ada50d49..791b518bea 100644 --- a/assets/common/items/weapons/starter_staff.ron +++ b/assets/common/items/weapons/starter_staff.ron @@ -3,6 +3,6 @@ Item( description: "Smells like resin and magic.", kind: Tool( kind: Staff, - power: 10, + power: 20, ), ) diff --git a/assets/common/items/weapons/starter_sword.ron b/assets/common/items/weapons/starter_sword.ron index dadbc9d2d5..eb4ce67111 100644 --- a/assets/common/items/weapons/starter_sword.ron +++ b/assets/common/items/weapons/starter_sword.ron @@ -3,6 +3,6 @@ Item( description: "Held together by Rust and hope.", kind: Tool( kind: Sword, - power: 10, + power: 15, ), ) diff --git a/assets/voxygen/element/buttons/indicator_mmap.vox b/assets/voxygen/element/buttons/indicator_mmap.vox index 942f8892cc..b1a6233f9b 100644 --- a/assets/voxygen/element/buttons/indicator_mmap.vox +++ b/assets/voxygen/element/buttons/indicator_mmap.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0773c7dd90d30b77affb6452cd3499f0bd5b069c71b4b1cc1734d7815a14d239 -size 56900 +oid sha256:5e647033fe3c7370a0dbf5b923c8efbe5839e4d485a12c5c3c21084936d34355 +size 56692 diff --git a/assets/voxygen/element/buttons/indicator_mmap_2.vox b/assets/voxygen/element/buttons/indicator_mmap_2.vox new file mode 100644 index 0000000000..63da2b0477 --- /dev/null +++ b/assets/voxygen/element/buttons/indicator_mmap_2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c503390eed517f975dbc4e55b40cad10e4337a1b35b26e344d8fa5fe38a7813e +size 56772 diff --git a/assets/voxygen/element/buttons/indicator_mmap_3.vox b/assets/voxygen/element/buttons/indicator_mmap_3.vox new file mode 100644 index 0000000000..b0dd4025d8 --- /dev/null +++ b/assets/voxygen/element/buttons/indicator_mmap_3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:571d8fa25a8ad7e9cf02fcab951dd94cfae360b8ae480b0307aded8bcbc57949 +size 56772 diff --git a/assets/voxygen/element/buttons/min_plus/mmap_button-min.vox b/assets/voxygen/element/buttons/min_plus/mmap_button-min.vox new file mode 100644 index 0000000000..2d357a2041 --- /dev/null +++ b/assets/voxygen/element/buttons/min_plus/mmap_button-min.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1c333365527174d741c93b2b76718f36b93d9c095a4069d86fb6709f977ab0a0 +size 1640 diff --git a/assets/voxygen/element/buttons/min_plus/mmap_button-min_hover.vox b/assets/voxygen/element/buttons/min_plus/mmap_button-min_hover.vox new file mode 100644 index 0000000000..7aa3bfb619 --- /dev/null +++ b/assets/voxygen/element/buttons/min_plus/mmap_button-min_hover.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b7dba6b97ae900053f4b65c82964bf9097af87ef1860ae773e12b6008f6808a +size 1640 diff --git a/assets/voxygen/element/buttons/min_plus/mmap_button-min_press.vox b/assets/voxygen/element/buttons/min_plus/mmap_button-min_press.vox new file mode 100644 index 0000000000..2da392109a --- /dev/null +++ b/assets/voxygen/element/buttons/min_plus/mmap_button-min_press.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c4e5b2f0c0a612025fdfc85c968a090ab635e7c51b56ec464c3c2855ccd25d3 +size 1624 diff --git a/assets/voxygen/element/buttons/min_plus/mmap_button-plus.vox b/assets/voxygen/element/buttons/min_plus/mmap_button-plus.vox new file mode 100644 index 0000000000..85ba1d2f1a --- /dev/null +++ b/assets/voxygen/element/buttons/min_plus/mmap_button-plus.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f1c9f4927664cc47d6b28d6962c15c5414ff87dcc4734cb04a4f824d69253d41 +size 1656 diff --git a/assets/voxygen/element/buttons/min_plus/mmap_button-plus_hover.vox b/assets/voxygen/element/buttons/min_plus/mmap_button-plus_hover.vox new file mode 100644 index 0000000000..05db19fa1a --- /dev/null +++ b/assets/voxygen/element/buttons/min_plus/mmap_button-plus_hover.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea0a6a621d1c9d1b44aaddb16a21a1711ba4f5e9283f3bb8f66055d414e6b641 +size 1656 diff --git a/assets/voxygen/element/buttons/min_plus/mmap_button-plus_press.vox b/assets/voxygen/element/buttons/min_plus/mmap_button-plus_press.vox new file mode 100644 index 0000000000..c61033c8a7 --- /dev/null +++ b/assets/voxygen/element/buttons/min_plus/mmap_button-plus_press.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:15f28c6f1b7ae17aaf6766ec036f9cc837c74715ea4beeb242b7d69efb92edae +size 1608 diff --git a/assets/voxygen/element/frames/enemybar.vox b/assets/voxygen/element/frames/enemybar.vox new file mode 100644 index 0000000000..86d8e7b3d9 --- /dev/null +++ b/assets/voxygen/element/frames/enemybar.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6bb91912f72a88fb39e4a06dd6a847b0e4512a934ce193cb1325abb91549e455 +size 60720 diff --git a/assets/voxygen/element/help.png b/assets/voxygen/element/help.png index de5404dc26..c399bd2d1a 100644 --- a/assets/voxygen/element/help.png +++ b/assets/voxygen/element/help.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58e48fef0c655f3d4de7dc94b4aa4d5583183d4d6b9c796764b1518de00ffb04 -size 14170 +oid sha256:4c71ba3a6458d00f3c6fb2820f1a83c6138a4776fdfd7167c2766b40b7bbb377 +size 14939 diff --git a/assets/voxygen/element/icons/skull.vox b/assets/voxygen/element/icons/skull.vox new file mode 100644 index 0000000000..6f12b02c2b --- /dev/null +++ b/assets/voxygen/element/icons/skull.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6eeb17f7682aa533fc805de9272f55f01d10c06d2c6afefed54ce23d46fe93ab +size 56456 diff --git a/assets/voxygen/element/icons/skull_2.vox b/assets/voxygen/element/icons/skull_2.vox new file mode 100644 index 0000000000..a32adc29ff --- /dev/null +++ b/assets/voxygen/element/icons/skull_2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6717aca430c81b346951f22fbb03e2dca4765a3fd56b7e515f267138af9f6e18 +size 56512 diff --git a/assets/voxygen/voxel/armor/back/short-0.vox b/assets/voxygen/voxel/armor/back/short-0.vox new file mode 100644 index 0000000000..b9c5362a58 --- /dev/null +++ b/assets/voxygen/voxel/armor/back/short-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c9e63b1debc909844e95ad7eb8b16c3dc94d1362b541fca7028f24dc2398fbd +size 44573 diff --git a/assets/voxygen/voxel/npc/oger/belt.vox b/assets/voxygen/voxel/npc/oger/belt.vox new file mode 100644 index 0000000000..3be13b8607 --- /dev/null +++ b/assets/voxygen/voxel/npc/oger/belt.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:640138a4516812405d5b7b8fe5e92652127e939cf09882ec2d40066995944aed +size 1736 diff --git a/assets/voxygen/voxel/npc/oger/chest.vox b/assets/voxygen/voxel/npc/oger/chest.vox new file mode 100644 index 0000000000..a7851d6b4f --- /dev/null +++ b/assets/voxygen/voxel/npc/oger/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f1a313f34a4ac2da2e4622f0b3c641d6f3c22da12c08433eba641be35b20b4c7 +size 3124 diff --git a/assets/voxygen/voxel/npc/oger/foot.vox b/assets/voxygen/voxel/npc/oger/foot.vox new file mode 100644 index 0000000000..5f93e9b833 --- /dev/null +++ b/assets/voxygen/voxel/npc/oger/foot.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:922d8355b060ba8344793dafb3bf998198753d8b6bc528e125e11423ac15d149 +size 1508 diff --git a/assets/voxygen/voxel/npc/oger/hand-l.vox b/assets/voxygen/voxel/npc/oger/hand-l.vox new file mode 100644 index 0000000000..605d6363f9 --- /dev/null +++ b/assets/voxygen/voxel/npc/oger/hand-l.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:64beb9f9cabf9cd887b8fe7d6323bdf0908063359809e2c18da58733fb9b82bc +size 44439 diff --git a/assets/voxygen/voxel/npc/oger/hand-r.vox b/assets/voxygen/voxel/npc/oger/hand-r.vox new file mode 100644 index 0000000000..09d273756c --- /dev/null +++ b/assets/voxygen/voxel/npc/oger/hand-r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5367735a13345ea6d2cc64bdc99bb1153851553658ff6c1425874de6cf06b5b8 +size 1332 diff --git a/assets/voxygen/voxel/npc/oger/head.vox b/assets/voxygen/voxel/npc/oger/head.vox new file mode 100644 index 0000000000..ff1ff1f084 --- /dev/null +++ b/assets/voxygen/voxel/npc/oger/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1bdee396a4bddcd426bde3bdf8fd06b2fb544a992398dd1f0a804a7149a35a4b +size 3784 diff --git a/assets/voxygen/voxel/npc/oger/legs.vox b/assets/voxygen/voxel/npc/oger/legs.vox new file mode 100644 index 0000000000..68243de5b6 --- /dev/null +++ b/assets/voxygen/voxel/npc/oger/legs.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cb8b4fdac51bc1a662ebb1cec3e5ef2c52167e0a021b603c9226e9afe2259ab8 +size 2428 diff --git a/assets/voxygen/voxel/npc/oger/shoulder.vox b/assets/voxygen/voxel/npc/oger/shoulder.vox new file mode 100644 index 0000000000..93585a80e0 --- /dev/null +++ b/assets/voxygen/voxel/npc/oger/shoulder.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52a3f3b21c4994f1e610c1377587d0131b32b14b2ed07bcaaec2ddb88cbb2505 +size 1748 diff --git a/assets/voxygen/voxel/weapon/hammer/hammer_1_2h.vox b/assets/voxygen/voxel/weapon/hammer/hammer_1_2h.vox new file mode 100644 index 0000000000..cb72e2bf45 --- /dev/null +++ b/assets/voxygen/voxel/weapon/hammer/hammer_1_2h.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:192c79add7e4fb06f635176fd1324fd8b95df85f5a58428cf71d0235cf378ef4 +size 58028 diff --git a/assets/voxygen/voxel/weapon/staff/wood-simple.vox b/assets/voxygen/voxel/weapon/staff/wood-simple.vox new file mode 100644 index 0000000000..7e69534fda --- /dev/null +++ b/assets/voxygen/voxel/weapon/staff/wood-simple.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b3fe2dfa4d4e9505762e70bd86c1719cfa0b579b0050211a30f769492c77898 +size 55932 diff --git a/assets/world/tree/acacia/1.vox b/assets/world/tree/acacia/1.vox index cda1574acc..c430606bfc 100644 --- a/assets/world/tree/acacia/1.vox +++ b/assets/world/tree/acacia/1.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c8f5224352c662e4400b16f0ebff2ee7accdf188b20748d5049f16f7011902bd -size 51468 +oid sha256:2a5035086a7d26f04608f40d22aca9d47adf98998d1b7e15e2372888a3b43ae8 +size 76828 diff --git a/assets/world/tree/acacia/2.vox b/assets/world/tree/acacia/2.vox index 32ecce590e..5ebcb50566 100644 --- a/assets/world/tree/acacia/2.vox +++ b/assets/world/tree/acacia/2.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fcbe884c673e8e16911318fe228bfba6bc36e65bc1f8c26c9706d92719eac97c -size 44527 +oid sha256:688a03d477499e69541b7feec4ce6bebd7dede1e743540e2c3cbcd9b0a53c016 +size 56619 diff --git a/assets/world/tree/acacia/3.vox b/assets/world/tree/acacia/3.vox index 8bc06e54cc..7c8243bb9a 100644 --- a/assets/world/tree/acacia/3.vox +++ b/assets/world/tree/acacia/3.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9734b6769fa66c77ddee14490b1c6a1241048fbdf7f7cfacfefb77c045e484b2 -size 44795 +oid sha256:455b635d1bc20402a3290cbfdc7c030d3de428287b820cf0dde1aa0be4a74ee2 +size 57487 diff --git a/assets/world/tree/acacia/4.vox b/assets/world/tree/acacia/4.vox index 6bc02dac6e..d089cfa34e 100644 --- a/assets/world/tree/acacia/4.vox +++ b/assets/world/tree/acacia/4.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c2a53a49c63b45712ee7ddcf9c6ec991193bc17041d12f63264e6372e112c056 -size 51196 +oid sha256:a37debf05102414ef85d2a1799ba28749de7e5d5290c152d374494a984bfe22a +size 72004 diff --git a/assets/world/tree/acacia/5.vox b/assets/world/tree/acacia/5.vox index 0c22065caa..56f0e5f01a 100644 --- a/assets/world/tree/acacia/5.vox +++ b/assets/world/tree/acacia/5.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cdea24bb04530868486a9b50a84c756a5a90981a70af1bb3c50c1ca72e3b666e -size 51672 +oid sha256:c1cc51107d88924dbf1637ae8f424b5292299eb35c50eeb07cae0be5fe3766f6 +size 88092 diff --git a/assets/world/tree/acacia_savannah/1.vox b/assets/world/tree/acacia_savannah/1.vox new file mode 100644 index 0000000000..cda1574acc --- /dev/null +++ b/assets/world/tree/acacia_savannah/1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c8f5224352c662e4400b16f0ebff2ee7accdf188b20748d5049f16f7011902bd +size 51468 diff --git a/assets/world/tree/acacia_savannah/2.vox b/assets/world/tree/acacia_savannah/2.vox new file mode 100644 index 0000000000..32ecce590e --- /dev/null +++ b/assets/world/tree/acacia_savannah/2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fcbe884c673e8e16911318fe228bfba6bc36e65bc1f8c26c9706d92719eac97c +size 44527 diff --git a/assets/world/tree/acacia_savannah/3.vox b/assets/world/tree/acacia_savannah/3.vox new file mode 100644 index 0000000000..8bc06e54cc --- /dev/null +++ b/assets/world/tree/acacia_savannah/3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9734b6769fa66c77ddee14490b1c6a1241048fbdf7f7cfacfefb77c045e484b2 +size 44795 diff --git a/assets/world/tree/acacia_savannah/4.vox b/assets/world/tree/acacia_savannah/4.vox new file mode 100644 index 0000000000..6bc02dac6e --- /dev/null +++ b/assets/world/tree/acacia_savannah/4.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2a53a49c63b45712ee7ddcf9c6ec991193bc17041d12f63264e6372e112c056 +size 51196 diff --git a/assets/world/tree/acacia_savannah/5.vox b/assets/world/tree/acacia_savannah/5.vox new file mode 100644 index 0000000000..0c22065caa --- /dev/null +++ b/assets/world/tree/acacia_savannah/5.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cdea24bb04530868486a9b50a84c756a5a90981a70af1bb3c50c1ca72e3b666e +size 51672 diff --git a/common/src/comp/body/giant.rs b/common/src/comp/body/giant.rs new file mode 100644 index 0000000000..9ded72c2b5 --- /dev/null +++ b/common/src/comp/body/giant.rs @@ -0,0 +1,69 @@ +use rand::{seq::SliceRandom, thread_rng}; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct Body { + pub head: Head, + pub shoulder: Shoulder, + pub chest: Chest, + pub hand: Hand + pub belt: Belt, + pub pants: Pants, + pub foot: Foot, +} + +impl Body { + pub fn random() -> Self { + let mut rng = thread_rng(); + Self { + head: *(&ALL_HEADS).choose(&mut rng).unwrap(), + shoulder: *(&ALL_SHOULDERS).choose(&mut rng).unwrap(), + chest: *(&ALL_CHESTS).choose(&mut rng).unwrap(), + hand: *(&ALL_HANDS).choose(&mut rng).unwrap(), + belt: *(&ALL_BELTS).choose(&mut rng).unwrap(), + pants: *(&ALL_PANTS).choose(&mut rng).unwrap(), + foot: *(&ALL_FEET).choose(&mut rng).unwrap(), + } + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Head { + Default, +} +const ALL_HEADS: [Head; 1] = [Head::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Shoulder { + Default, +} +const ALL_SHOULDERS: [Shoulder; 1] = [Shoulder::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Chest { + Default, +} +const ALL_CHESTS: [Chest; 1] = [Chest::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Hand { + Default, +} +const ALL_HANDS: [Hand; 1] = [Hand::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Belt { + Default, +} +const ALL_BELTS: [Belt; 1] = [Belt::Default]; +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Pants { + Default, +} +const ALL_FEET: [Foot; 1] = [Foot::Default]; +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Foot { + Default, +} + + + diff --git a/server/src/sys/message.rs b/server/src/sys/message.rs index b7b47c0215..f2466c281f 100644 --- a/server/src/sys/message.rs +++ b/server/src/sys/message.rs @@ -109,6 +109,7 @@ impl<'a> System<'a> for Sys { client.error_state(RequestStateError::Already) } ClientState::Spectator | ClientState::Character | ClientState::Dead => { + // TODO: remove position etc here client.allow_state(ClientState::Registered) } ClientState::Pending => {} diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index c9560c4b81..c72866d385 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -98,10 +98,8 @@ impl<'a> System<'a> for Sys { for npc in supplement.npcs { let (mut stats, mut body) = if rand::random() { let stats = comp::Stats::new( - "Humanoid".to_string(), - Some(assets::load_expect_cloned( - "common.items.weapons.starter_sword", - )), + "Traveler".to_string(), + Some(assets::load_expect_cloned("common.items.weapons.staff_1")), ); let body = comp::Body::Humanoid(comp::humanoid::Body::random()); (stats, body) @@ -113,20 +111,18 @@ impl<'a> System<'a> for Sys { let mut scale = 1.0; // TODO: Remove this and implement scaling or level depending on stuff like species instead - stats.level.set_level(rand::thread_rng().gen_range(1, 3)); + stats.level.set_level(rand::thread_rng().gen_range(1, 10)); if npc.boss { if rand::random::() < 0.8 { stats = comp::Stats::new( - "Humanoid".to_string(), - Some(assets::load_expect_cloned( - "common.items.weapons.starter_sword", - )), + "Fearless Wanderer".to_string(), + Some(assets::load_expect_cloned("common.items.weapons.hammer_1")), ); body = comp::Body::Humanoid(comp::humanoid::Body::random()); } - stats.level.set_level(rand::thread_rng().gen_range(10, 50)); - scale = 2.5 + rand::random::(); + stats.level.set_level(rand::thread_rng().gen_range(20, 50)); + scale = 2.0 + rand::random::(); } stats.update_max_hp(); diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index b4b37616e9..ac1593693f 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -118,10 +118,14 @@ image_ids! { grass: "voxygen.element.icons.item_grass", apple: "voxygen.element.icons.item_apple", mushroom: "voxygen.element.icons.item_mushroom", + skull: "voxygen.element.icons.skull", + skull_2: "voxygen.element.icons.skull_2", // Map map_indicator: "voxygen.element.buttons.map_indicator", indicator_mmap: "voxygen.element.buttons.indicator_mmap", + indicator_mmap_2: "voxygen.element.buttons.indicator_mmap_2", + indicator_mmap_3: "voxygen.element.buttons.indicator_mmap_3", // Crosshair @@ -154,6 +158,12 @@ image_ids! { mmap_open: "voxygen.element.buttons.button_mmap_open", mmap_open_hover: "voxygen.element.buttons.button_mmap_open_hover", mmap_open_press: "voxygen.element.buttons.button_mmap_open_press", + mmap_plus: "voxygen.element.buttons.min_plus.mmap_button-plus", + mmap_plus_hover: "voxygen.element.buttons.min_plus.mmap_button-plus_hover", + mmap_plus_press: "voxygen.element.buttons.min_plus.mmap_button-plus_hover", + mmap_minus: "voxygen.element.buttons.min_plus.mmap_button-min", + mmap_minus_hover: "voxygen.element.buttons.min_plus.mmap_button-min_hover", + mmap_minus_press: "voxygen.element.buttons.min_plus.mmap_button-min_press", // Grid grid: "voxygen.element.buttons.grid", @@ -221,6 +231,10 @@ image_ids! { key: "voxygen.voxel.object.key", key_gold: "voxygen.voxel.object.key_gold", + // Enemy Healthbar + enemy_health: "voxygen.element.frames.enemybar", + + ////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/voxygen/src/hud/map.rs b/voxygen/src/hud/map.rs index 885a69f319..8d7eccc10c 100644 --- a/voxygen/src/hud/map.rs +++ b/voxygen/src/hud/map.rs @@ -5,7 +5,7 @@ use conrod_core::{ color, image::Id, widget::{self, Button, Image, Rectangle, Text}, - widget_ids, Colorable, Positionable, Sizeable, Widget, WidgetCommon, + widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon, }; use specs::WorldExt; use vek::*; @@ -31,12 +31,12 @@ widget_ids! { pub struct Map<'a> { _show: &'a Show, client: &'a Client, - _world_map: Id, imgs: &'a Imgs, fonts: &'a Fonts, #[conrod(common_builder)] common: widget::CommonBuilder, + pulse: f32, } impl<'a> Map<'a> { pub fn new( @@ -45,6 +45,7 @@ impl<'a> Map<'a> { imgs: &'a Imgs, world_map: Id, fonts: &'a Fonts, + pulse: f32, ) -> Self { Self { _show: show, @@ -53,6 +54,7 @@ impl<'a> Map<'a> { client, fonts: fonts, common: widget::CommonBuilder::default(), + pulse, } } } @@ -129,9 +131,10 @@ impl<'a> Widget for Map<'a> { // Location Name match self.client.current_chunk() { Some(chunk) => Text::new(chunk.meta().name()) - .mid_top_with_margin_on(state.ids.map_bg, 70.0) - .font_size(20) + .mid_top_with_margin_on(state.ids.map_bg, 55.0) + .font_size(60) .color(TEXT_COLOR) + .font_id(self.fonts.alkhemi) .parent(state.ids.map_frame_r) .set(state.ids.location_name, ui), None => Text::new(" ") @@ -157,15 +160,33 @@ impl<'a> Widget for Map<'a> { .map_or(Vec3::zero(), |pos| pos.0); let worldsize = 32768.0; // TODO This has to get the actual world size and not be hardcoded - let x = player_pos.x as f64 / worldsize * 700.0; + let x = player_pos.x as f64 / worldsize * 700.0/*= x-Size of the map image*/; let y = (/*1.0 -*/player_pos.y as f64 / worldsize) * 700.0; + let indic_ani = (self.pulse * 6.0/*animation speed*/).cos()/*starts at 1.0*/ * 0.5 + 0.50; // changes the animation frame + let indic_scale = 1.2; // Indicator - Image::new(self.imgs.map_indicator) - .bottom_left_with_margins_on(state.ids.grid, y, x - (12.0 * 1.4) / 2.0) - .w_h(12.0 * 1.4, 21.0 * 1.4) - .floating(true) - .parent(ui.window) - .set(state.ids.indicator, ui); + Image::new(if indic_ani <= 0.3 { + self.imgs.indicator_mmap + } else if indic_ani <= 0.6 { + self.imgs.indicator_mmap_2 + } else { + self.imgs.indicator_mmap_3 + }) + .bottom_left_with_margins_on(state.ids.grid, y, x - (20.0 * 1.2) / 2.0) + .w_h( + 22.0 * 1.2, + if indic_ani <= 0.3 { + 16.0 * indic_scale + } else if indic_ani <= 0.6 { + 23.0 * indic_scale + } else { + 34.0 * indic_scale + }, + ) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))) + .floating(true) + .parent(ui.window) + .set(state.ids.indicator, ui); None } diff --git a/voxygen/src/hud/minimap.rs b/voxygen/src/hud/minimap.rs index be1e34ad2c..e5b7f8278c 100644 --- a/voxygen/src/hud/minimap.rs +++ b/voxygen/src/hud/minimap.rs @@ -17,6 +17,8 @@ widget_ids! { mmap_frame_bg, mmap_location, mmap_button, + mmap_plus, + mmap_minus, zone_display_bg, zone_display, grid, @@ -35,6 +37,8 @@ pub struct MiniMap<'a> { fonts: &'a Fonts, #[conrod(common_builder)] common: widget::CommonBuilder, + pulse: f32, + zoom: f32, } impl<'a> MiniMap<'a> { @@ -44,6 +48,8 @@ impl<'a> MiniMap<'a> { imgs: &'a Imgs, world_map: Id, fonts: &'a Fonts, + pulse: f32, + zoom: f32, ) -> Self { Self { show, @@ -52,6 +58,8 @@ impl<'a> MiniMap<'a> { _world_map: world_map, fonts: fonts, common: widget::CommonBuilder::default(), + pulse, + zoom, } } } @@ -87,20 +95,49 @@ impl<'a> Widget for MiniMap<'a> { fn update(self, args: widget::UpdateArgs) -> Self::Event { let widget::UpdateArgs { state, ui, .. } = args; - + let zoom = self.zoom as f64; if self.show.mini_map { Image::new(self.imgs.mmap_frame) - .w_h(100.0 * 4.0, 100.0 * 4.0) + .w_h(100.0 * 4.0 * zoom, 100.0 * 4.0 * zoom) .top_right_with_margins_on(ui.window, 5.0, 5.0) .set(state.ids.mmap_frame, ui); Rectangle::fill_with([92.0 * 4.0, 82.0 * 4.0], color::TRANSPARENT) - .mid_top_with_margin_on(state.ids.mmap_frame, 13.0 * 4.0 + 4.0) + .mid_top_with_margin_on(state.ids.mmap_frame, 13.0 * 4.0 + 4.0 * zoom) .set(state.ids.mmap_frame_bg, ui); + // Zoom Buttons + // TODO: Add zoomable minimap + + /*if Button::image(self.imgs.mmap_plus) + .w_h(100.0 * 0.2 * zoom, 100.0 * 0.2 * zoom) + .hover_image(self.imgs.mmap_plus_hover) + .press_image(self.imgs.mmap_plus_press) + .top_left_with_margins_on(state.ids.mmap_frame, 0.0, 0.0) + .set(state.ids.mmap_plus, ui) + .was_clicked() + { + if zoom > 0.0 { + zoom = zoom + 1.0 + } else if zoom == 5.0 { + } + } + if Button::image(self.imgs.mmap_minus) + .w_h(100.0 * 0.2 * zoom, 100.0 * 0.2 * zoom) + .hover_image(self.imgs.mmap_minus_hover) + .press_image(self.imgs.mmap_minus_press) + .down_from(state.ids.mmap_plus, 0.0) + .set(state.ids.mmap_minus, ui) + .was_clicked() + { + if zoom < 6.0 { + zoom = zoom - 1.0 + } else if zoom == 0.0 { + } + }*/ // Map Image Image::new(/*self.world_map*/ self.imgs.map_placeholder) .middle_of(state.ids.mmap_frame_bg) - .w_h(92.0 * 4.0, 82.0 * 4.0) + .w_h(92.0 * 4.0 * zoom, 82.0 * 4.0 * zoom) .parent(state.ids.mmap_frame_bg) .set(state.ids.grid, ui); // Coordinates @@ -115,13 +152,28 @@ impl<'a> Widget for MiniMap<'a> { let worldsize = 32768.0; // TODO This has to get the actual world size and not be hardcoded let x = player_pos.x as f64 / worldsize * 92.0 * 4.0; let y = (/*1.0X-*/player_pos.y as f64 / worldsize) * 82.0 * 4.0; + let indic_ani = (self.pulse * 6.0).cos() * 0.5 + 0.5; //Animation timer + let indic_scale = 0.8; // Indicator - Image::new(self.imgs.indicator_mmap) - .bottom_left_with_margins_on(state.ids.grid, y, x - 5.0) - .w_h(10.0, 10.0) - .floating(true) - .parent(ui.window) - .set(state.ids.indicator, ui); + Image::new(if indic_ani <= 0.5 { + self.imgs.indicator_mmap + } else { + self.imgs.indicator_mmap_2 + }) + .bottom_left_with_margins_on(state.ids.grid, y, x - 5.0) + .w_h( + // Animation frames depening on timer value from 0.0 to 1.0 + 22.0 * 0.8, + if indic_ani <= 0.5 { + 18.0 * indic_scale + } else { + 23.0 * indic_scale + }, + ) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))) + .floating(true) + .parent(ui.window) + .set(state.ids.indicator, ui); } else { Image::new(self.imgs.mmap_frame_closed) .w_h(100.0 * 2.0, 11.0 * 2.0) @@ -137,7 +189,7 @@ impl<'a> Widget for MiniMap<'a> { .wh(if self.show.mini_map { [100.0 * 0.4; 2] } else { - [100.0 * 0.2; 2] + [100.0 * 0.2 * zoom; 2] }) .hover_image(if self.show.mini_map { self.imgs.mmap_open_hover diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 7da5038331..b718dc912d 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -14,7 +14,9 @@ mod social; mod spell; use crate::hud::img_ids::ImgsRot; +//use rand::Rng; pub use settings_window::ScaleChange; +use std::time::Duration; use bag::Bag; use buttons::Buttons; @@ -64,7 +66,7 @@ const TEXT_COLOR_3: Color = Color::Rgba(1.0, 1.0, 1.0, 0.1); //const BG_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 0.8); const HP_COLOR: Color = Color::Rgba(0.33, 0.63, 0.0, 1.0); const LOW_HP_COLOR: Color = Color::Rgba(0.93, 0.59, 0.03, 1.0); -const CRITICAL_HP_COLOR: Color = Color::Rgba(1.0, 0.0, 0.0, 1.0); +const CRITICAL_HP_COLOR: Color = Color::Rgba(0.79, 0.19, 0.17, 1.0); const MANA_COLOR: Color = Color::Rgba(0.47, 0.55, 1.0, 0.9); //const FOCUS_COLOR: Color = Color::Rgba(1.0, 0.56, 0.04, 1.0); //const RAGE_COLOR: Color = Color::Rgba(0.5, 0.04, 0.13, 1.0); @@ -86,8 +88,12 @@ widget_ids! { // Character Names name_tags[], + levels[], + levels_skull[], // Health Bars health_bars[], + mana_bars[], + health_bar_fronts[], health_bar_backs[], // Intro Text @@ -410,6 +416,8 @@ pub struct Hud { force_ungrab: bool, force_chat_input: Option, force_chat_cursor: Option, + pulse: f32, + zoom: f32, } impl Hud { @@ -469,6 +477,8 @@ impl Hud { force_ungrab: false, force_chat_input: None, force_chat_cursor: None, + pulse: 0.0, + zoom: 1.0, } } @@ -477,9 +487,12 @@ impl Hud { client: &Client, global_state: &GlobalState, debug_info: DebugInfo, + dt: Duration, ) -> Vec { let mut events = Vec::new(); let (ref mut ui_widgets, ref mut tooltip_manager) = self.ui.set_widgets(); + // pulse time for pulsating elements + self.pulse = self.pulse + dt.as_secs_f32(); let version = format!( "{}-{}", @@ -522,6 +535,10 @@ impl Hud { let entities = ecs.entities(); let me = client.entity(); let view_distance = client.view_distance().unwrap_or(1); + let own_level = stats + .get(client.entity()) + .map_or(0, |stats| stats.level.level()); + // Get player position. let player_pos = client .state() @@ -530,8 +547,95 @@ impl Hud { .get(client.entity()) .map_or(Vec3::zero(), |pos| pos.0); let mut name_id_walker = self.ids.name_tags.walk(); + let mut level_id_walker = self.ids.levels.walk(); + let mut level_skull_id_walker = self.ids.levels_skull.walk(); let mut health_id_walker = self.ids.health_bars.walk(); + let mut mana_id_walker = self.ids.mana_bars.walk(); let mut health_back_id_walker = self.ids.health_bar_backs.walk(); + let mut health_front_id_walker = self.ids.health_bar_fronts.walk(); + // Render Health Bars + for (_entity, pos, stats, scale) in (&entities, &pos, &stats, scales.maybe()) + .join() + .filter(|(entity, _, stats, _)| { + *entity != me && !stats.is_dead + //&& stats.health.current() != stats.health.maximum() + }) + // Don't process health bars outside the vd (visibility further limited by ui backend) + .filter(|(_, pos, _, _)| { + Vec2::from(pos.0 - player_pos) + .map2(TerrainChunk::RECT_SIZE, |d: f32, sz| { + d.abs() as f32 / sz as f32 + }) + .magnitude() + < view_distance as f32 + }) + { + let scale = scale.map(|s| s.0).unwrap_or(1.0); + + let back_id = health_back_id_walker.next( + &mut self.ids.health_bar_backs, + &mut ui_widgets.widget_id_generator(), + ); + let health_bar_id = health_id_walker.next( + &mut self.ids.health_bars, + &mut ui_widgets.widget_id_generator(), + ); + let mana_bar_id = mana_id_walker.next( + &mut self.ids.mana_bars, + &mut ui_widgets.widget_id_generator(), + ); + let front_id = health_front_id_walker.next( + &mut self.ids.health_bar_fronts, + &mut ui_widgets.widget_id_generator(), + ); + let hp_percentage = + stats.health.current() as f64 / stats.health.maximum() as f64 * 100.0; + let hp_ani = (self.pulse * 4.0/*speed factor*/).cos() * 0.5 + 1.0; //Animation timer + let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani); + + // Background + Rectangle::fill_with([82.0, 8.0], Color::Rgba(0.3, 0.3, 0.3, 0.5)) + .x_y(0.0, -25.0) + .position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) + .resolution(100.0) + .set(back_id, ui_widgets); + + // % HP Filling + Image::new(self.imgs.bar_content) + .w_h(72.9 * (hp_percentage / 100.0), 5.9) + .x_y(4.5, -24.0) + .color(Some(if hp_percentage <= 25.0 { + crit_hp_color + } else if hp_percentage <= 50.0 { + LOW_HP_COLOR + } else { + HP_COLOR + })) + .position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) + .resolution(100.0) + .set(health_bar_id, ui_widgets); + // % Mana Filling + Rectangle::fill_with( + [ + 73.0 * (stats.energy.current() as f64 / stats.energy.maximum() as f64), + 1.5, + ], + MANA_COLOR, + ) + .x_y(4.5, -28.0) + .position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) + .resolution(100.0) + .set(mana_bar_id, ui_widgets); + + // Foreground + Image::new(self.imgs.enemy_health) + .w_h(84.0, 10.0) + .x_y(0.0, -25.0) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.99))) + .position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) + .resolution(100.0) + .set(front_id, ui_widgets); + } // Render Name Tags for (pos, name, level, scale) in @@ -558,69 +662,71 @@ impl Hud { (pos.0, name, stats.level, scale) }) { - let info = format!("{} Level {}", name, level.level()); + let name = format!("{}", name); let scale = scale.map(|s| s.0).unwrap_or(1.0); - - let id = name_id_walker.next( + let name_id = name_id_walker.next( &mut self.ids.name_tags, &mut ui_widgets.widget_id_generator(), ); - Text::new(&info) + let level_id = level_id_walker + .next(&mut self.ids.levels, &mut ui_widgets.widget_id_generator()); + let level_skull_id = level_skull_id_walker.next( + &mut self.ids.levels_skull, + &mut ui_widgets.widget_id_generator(), + ); + + // Name + Text::new(&name) .font_size(20) .color(Color::Rgba(0.61, 0.61, 0.89, 1.0)) .x_y(0.0, 0.0) .position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) .resolution(100.0) - .set(id, ui_widgets); - } + .set(name_id, ui_widgets); - // Render Health Bars - for (_entity, pos, stats, scale) in (&entities, &pos, &stats, scales.maybe()) - .join() - .filter(|(entity, _, stats, _)| { - *entity != me - && !stats.is_dead - && stats.health.current() != stats.health.maximum() - }) - // Don't process health bars outside the vd (visibility further limited by ui backend) - .filter(|(_, pos, _, _)| { - Vec2::from(pos.0 - player_pos) - .map2(TerrainChunk::RECT_SIZE, |d: f32, sz| { - d.abs() as f32 / sz as f32 - }) - .magnitude() - < view_distance as f32 - }) - { - let scale = scale.map(|s| s.0).unwrap_or(1.0); - - let back_id = health_back_id_walker.next( - &mut self.ids.health_bar_backs, - &mut ui_widgets.widget_id_generator(), - ); - let bar_id = health_id_walker.next( - &mut self.ids.health_bars, - &mut ui_widgets.widget_id_generator(), - ); - // Background - Rectangle::fill_with([120.0, 8.0], Color::Rgba(0.3, 0.3, 0.3, 0.5)) - .x_y(0.0, -25.0) - .position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) + // Level + const LOW: Color = Color::Rgba(0.54, 0.81, 0.94, 0.4); + const HIGH: Color = Color::Rgba(1.0, 0.0, 0.0, 1.0); + const EQUAL: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); + let op_level = level.level(); + let level_str = format!("{}", op_level); + // Change visuals of the level display depending on the player level/opponent level + let level_comp = op_level as i64 - own_level as i64; + // + 10 level above player -> skull + // + 5-10 levels above player -> high + // -5 - +5 levels around player level -> equal + // - 5 levels below player -> low + Text::new(if level_comp < 10 { &level_str } else { "?" }) + .font_size(if op_level > 9 && level_comp < 10 { + 7 + } else { + 8 + }) + .color(if level_comp > 4 { + HIGH + } else if level_comp < -5 { + LOW + } else { + EQUAL + }) + .x_y(-37.0, -24.0) + .position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) .resolution(100.0) - .set(back_id, ui_widgets); - - // % HP Filling - Rectangle::fill_with( - [ - 120.0 * (stats.health.current() as f64 / stats.health.maximum() as f64), - 8.0, - ], - HP_COLOR, - ) - .x_y(0.0, -25.0) - .position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) - .resolution(100.0) - .set(bar_id, ui_widgets); + .set(level_id, ui_widgets); + if level_comp > 9 { + let skull_ani = ((self.pulse * 0.7/*speed factor*/).cos() * 0.5 + 0.5) * 10.0; //Animation timer + Image::new(if skull_ani as i32 == 1 && rand::random::() < 0.9 { + self.imgs.skull_2 + } else { + self.imgs.skull + }) + .w_h(30.0, 30.0) + .x_y(0.0, 24.0) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.8))) + .position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) + .resolution(100.0) + .set(level_skull_id, ui_widgets); + } } } // Introduction Text @@ -915,7 +1021,7 @@ impl Hud { if self.show.help && !self.show.map && !self.show.esc_menu { Image::new(self.imgs.help) .middle_of(ui_widgets.window) - .w_h(1260.0, 519.0) + .w_h(1260.0 * 1.2, 519.0 * 1.2) .set(self.ids.help, ui_widgets); // Show tips if Button::image(self.imgs.button) @@ -969,8 +1075,16 @@ impl Hud { } // MiniMap - match MiniMap::new(&self.show, client, &self.imgs, self.world_map, &self.fonts) - .set(self.ids.minimap, ui_widgets) + match MiniMap::new( + &self.show, + client, + &self.imgs, + self.world_map, + &self.fonts, + self.pulse, + self.zoom, + ) + .set(self.ids.minimap, ui_widgets) { Some(minimap::Event::Toggle) => self.show.toggle_mini_map(), None => {} @@ -1005,7 +1119,7 @@ impl Hud { .read_storage::() .get(client.entity()) { - Skillbar::new(global_state, &self.imgs, &self.fonts, stats) + Skillbar::new(global_state, &self.imgs, &self.fonts, &stats, self.pulse) .set(self.ids.skillbar, ui_widgets); } @@ -1169,8 +1283,15 @@ impl Hud { } // Map if self.show.map { - match Map::new(&self.show, client, &self.imgs, self.world_map, &self.fonts) - .set(self.ids.map, ui_widgets) + match Map::new( + &self.show, + client, + &self.imgs, + self.world_map, + &self.fonts, + self.pulse, + ) + .set(self.ids.map, ui_widgets) { Some(map::Event::Close) => { self.show.map(false); @@ -1354,11 +1475,12 @@ impl Hud { global_state: &mut GlobalState, debug_info: DebugInfo, camera: &Camera, + dt: Duration, ) -> Vec { if let Some(maybe_id) = self.to_focus.take() { self.ui.focus_widget(maybe_id); } - let events = self.update_layout(client, global_state, debug_info); + let events = self.update_layout(client, global_state, debug_info, dt); let (view_mat, _, _) = camera.compute_dependents(client); let fov = camera.get_fov(); self.ui.maintain( diff --git a/voxygen/src/hud/settings_window.rs b/voxygen/src/hud/settings_window.rs index bb7572a61e..97f635463f 100644 --- a/voxygen/src/hud/settings_window.rs +++ b/voxygen/src/hud/settings_window.rs @@ -451,7 +451,7 @@ impl<'a> Widget for SettingsWindow<'a> { if let Some(new_val) = ImageSlider::continuous( scale.log(2.0), 0.5f64.log(2.0), - 1.2f64.log(2.0), + 1.0f64.log(2.0), self.imgs.slider_indicator, self.imgs.slider, ) @@ -857,7 +857,7 @@ impl<'a> Widget for SettingsWindow<'a> { { events.push(Event::ChatTransp(new_val)); } - Rectangle::fill_with([40.0 * 4.0, 1.0 * 4.0], color::TRANSPARENT) + Rectangle::fill_with([60.0 * 4.0, 1.0 * 4.0], color::TRANSPARENT) .down_from(state.ids.chat_transp_title, 30.0) .set(state.ids.placeholder, ui); } diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index 860ef4f57b..ff536fc45e 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -92,6 +92,7 @@ pub struct Skillbar<'a> { imgs: &'a Imgs, fonts: &'a Fonts, stats: &'a Stats, + pulse: f32, #[conrod(common_builder)] common: widget::CommonBuilder, current_resource: ResourceType, @@ -103,6 +104,7 @@ impl<'a> Skillbar<'a> { imgs: &'a Imgs, fonts: &'a Fonts, stats: &'a Stats, + pulse: f32, ) -> Self { Self { imgs, @@ -111,6 +113,7 @@ impl<'a> Skillbar<'a> { global_state, current_resource: ResourceType::Mana, common: widget::CommonBuilder::default(), + pulse, } } } @@ -164,6 +167,8 @@ impl<'a> Widget for Skillbar<'a> { const BG_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 0.8); const BG_COLOR_2: Color = Color::Rgba(0.0, 0.0, 0.0, 0.99); + let hp_ani = (self.pulse * 4.0/*speed factor*/).cos() * 0.5 + 0.8; //Animation timer + let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani); // Stamina Wheel /* @@ -300,7 +305,6 @@ impl<'a> Widget for Skillbar<'a> { .top_left_with_margins_on(state.ids.xp_bar_left, 2.0 * scale, 10.0 * scale) .set(state.ids.xp_bar_filling, ui); // Level Display - if self.stats.level.level() < 10 { Text::new(&level) .bottom_left_with_margins_on( @@ -777,7 +781,7 @@ impl<'a> Widget for Skillbar<'a> { Image::new(self.imgs.bar_content) .w_h(97.0 * scale * hp_percentage / 100.0, 16.0 * scale) .color(Some(if hp_percentage <= 20.0 { - CRITICAL_HP_COLOR + crit_hp_color } else if hp_percentage <= 40.0 { LOW_HP_COLOR } else { diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 2ff3286fd0..8e7e0275c0 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -389,6 +389,7 @@ impl PlayState for SessionState { .cloned(), }, &self.scene.camera(), + clock.get_last_delta(), ); // Maintain the UI. From cfbf69ae893323e2833453b9107c59d817840e13 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 30 Dec 2019 15:16:21 +0000 Subject: [PATCH 21/51] Made rolling less slippy, added tilt --- common/src/sys/movement.rs | 10 ++++++++-- voxygen/src/anim/character/roll.rs | 20 +++++++++++++++++--- voxygen/src/anim/character/run.rs | 1 - voxygen/src/scene/figure/mod.rs | 2 +- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/common/src/sys/movement.rs b/common/src/sys/movement.rs index 4c85dfc8cc..31553d3d07 100644 --- a/common/src/sys/movement.rs +++ b/common/src/sys/movement.rs @@ -1,7 +1,8 @@ use super::phys::GRAVITY; use crate::{ comp::{ - CharacterState, Controller, Mounting, MovementState::*, Ori, PhysicsState, Pos, Stats, Vel, + ActionState, CharacterState, Controller, Mounting, MovementState::*, Ori, PhysicsState, + Pos, Stats, Vel, }, event::{EventBus, ServerEvent}, state::DeltaTime, @@ -180,7 +181,12 @@ impl<'a> System<'a> for Sys { // producing potentially unexpected changes in direction Vec2::from(vel.0) } else { - Vec2::from(inputs.move_dir) + if let ActionState::Roll { .. } = character.action { + // So can can't spin/slip around while rolling + Vec2::from(vel.0) + } else { + Vec2::from(inputs.move_dir) + } }; if ori_dir.magnitude_squared() > 0.0001 diff --git a/voxygen/src/anim/character/roll.rs b/voxygen/src/anim/character/roll.rs index 92e6149e2e..2e76022b01 100644 --- a/voxygen/src/anim/character/roll.rs +++ b/voxygen/src/anim/character/roll.rs @@ -10,11 +10,11 @@ pub struct RollAnimation; impl Animation for RollAnimation { type Skeleton = CharacterSkeleton; - type Dependency = (Option, f64); + type Dependency = (Option, Vec3, Vec3, f64); fn update_skeleton( skeleton: &Self::Skeleton, - (_active_tool_kind, _global_time): Self::Dependency, + (_active_tool_kind, orientation, last_ori, _global_time): Self::Dependency, anim_time: f64, _rate: &mut f32, skeleton_attr: &SkeletonAttr, @@ -27,6 +27,20 @@ impl Animation for RollAnimation { let wave_slow = (anim_time as f32 * 2.8 + PI).sin(); let wave_dub = (anim_time as f32 * 5.5).sin(); + let ori = Vec2::from(orientation); + let last_ori = Vec2::from(last_ori); + let tilt = if Vec2::new(ori, last_ori) + .map(|o| Vec2::::from(o).magnitude_squared()) + .map(|m| m > 0.001 && m.is_finite()) + .reduce_and() + && ori.angle_between(last_ori).is_finite() + { + ori.angle_between(last_ori).min(0.5) + * last_ori.determine_side(Vec2::zero(), ori).signum() + } else { + 0.0 + } * 1.3; + next.head.offset = Vec3::new( 0.0 + skeleton_attr.neck_right, -2.0 + skeleton_attr.neck_forward, @@ -102,7 +116,7 @@ impl Animation for RollAnimation { next.torso.offset = Vec3::new(0.0, 11.0, 0.1 + wave_dub * 16.0) / 11.0 * skeleton_attr.scaler; - next.torso.ori = Quaternion::rotation_x(wave_slow * 6.5); + next.torso.ori = Quaternion::rotation_x(wave_slow * 6.5) * Quaternion::rotation_y(tilt); next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler; next } diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index 38fdc58728..4e5ae350d6 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -56,7 +56,6 @@ impl Animation for RunAnimation { let ori = Vec2::from(orientation); let last_ori = Vec2::from(last_ori); - let tilt = if Vec2::new(ori, last_ori) .map(|o| Vec2::::from(o).magnitude_squared()) .map(|m| m > 0.001 && m.is_finite()) diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index b5e33ee35d..a5f88385d7 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -280,7 +280,7 @@ impl FigureMgr { ), (_, Roll { .. }) => anim::character::RollAnimation::update_skeleton( &target_base, - (active_tool_kind, time), + (active_tool_kind, ori.0, state.last_ori, time), state.action_time, &mut action_animation_rate, skeleton_attr, From d55ea709f64fdf56cec6a08829e13097729ade15 Mon Sep 17 00:00:00 2001 From: Mckol Date: Tue, 31 Dec 2019 17:09:29 +0000 Subject: [PATCH 22/51] Added the link to airshipper-git AUR package to the README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 33953974c4..0881a8f748 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,8 @@ If you want to compile Veloren yourself, take a look at the [How to Compile Guid #### Arch +[AUR Airshipper](https://aur.archlinux.org/packages/airshipper-git): `yay -Sy airshipper-git` + [AUR latest binary release](https://aur.archlinux.org/packages/veloren-bin/): `yay -Sy veloren-bin` [AUR latest release](https://aur.archlinux.org/packages/veloren/): `yay -Sy veloren` From ede05c47b04438c1ee236f2459eb1584574664f4 Mon Sep 17 00:00:00 2001 From: Imbris Date: Tue, 31 Dec 2019 03:10:51 -0500 Subject: [PATCH 23/51] fix(char screen induced ghosts): Adds removing extra components and deleting entities clientside when going back to the character screen. Also, simplifies ClientState by removing the Dead variant and removing ClientMsg::StateRequest in favor of more specific ClientMsg variants. --- client/src/lib.rs | 55 +++++++++++++++++--------- common/src/event.rs | 5 ++- common/src/msg/client.rs | 49 +++-------------------- common/src/msg/mod.rs | 1 - common/src/msg/server.rs | 4 +- server/src/client.rs | 12 ++---- server/src/lib.rs | 61 ++++++++++++++++++++++------- server/src/sys/message.rs | 81 +++++++++++++++++---------------------- voxygen/src/session.rs | 4 +- 9 files changed, 135 insertions(+), 137 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index 932add96d5..0ceed6b47b 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -5,7 +5,11 @@ pub mod error; // Reexports pub use crate::error::Error; -pub use specs::{join::Join, saveload::Marker, Entity as EcsEntity, ReadStorage, WorldExt}; +pub use specs::{ + join::Join, + saveload::{Marker, MarkerAllocator}, + Builder, Entity as EcsEntity, ReadStorage, WorldExt, +}; use common::{ comp::{self, ControlEvent, Controller, ControllerInputs, InventoryManip}, @@ -15,7 +19,7 @@ use common::{ }, net::PostBox, state::State, - sync::{Uid, WorldSyncExt}, + sync::{Uid, UidAllocator, WorldSyncExt}, terrain::{block::Block, TerrainChunk, TerrainChunkSize}, vol::RectVolSize, ChatType, @@ -84,7 +88,7 @@ impl Client { time_of_day, // world_map: /*(map_size, world_map)*/map_size, }) => { - // TODO: Voxygen should display this. + // TODO: Display that versions don't match in Voxygen if server_info.git_hash != common::util::GIT_HASH.to_string() { log::warn!( "Server is running {}[{}], you are running {}[{}], versions might be incompatible!", @@ -183,17 +187,15 @@ impl Client { self.client_state = ClientState::Pending; } - /// Request a state transition to `ClientState::Character`. + /// Send disconnect message to the server pub fn request_logout(&mut self) { - self.postbox - .send_message(ClientMsg::RequestState(ClientState::Connected)); + self.postbox.send_message(ClientMsg::Disconnect); self.client_state = ClientState::Pending; } - /// Request a state transition to `ClientState::Character`. + /// Request a state transition to `ClientState::Registered` from an ingame state. pub fn request_remove_character(&mut self) { - self.postbox - .send_message(ClientMsg::RequestState(ClientState::Registered)); + self.postbox.send_message(ClientMsg::ExitIngame); self.client_state = ClientState::Pending; } @@ -282,9 +284,9 @@ impl Client { } /// Send a chat message to the server. - pub fn send_chat(&mut self, msg: String) { - match validate_chat_msg(&msg) { - Ok(()) => self.postbox.send_message(ClientMsg::chat(msg)), + pub fn send_chat(&mut self, message: String) { + match validate_chat_msg(&message) { + Ok(()) => self.postbox.send_message(ClientMsg::ChatMsg { message }), Err(ChatMsgValidationError::TooLong) => log::warn!( "Attempted to send a message that's too long (Over {} bytes)", MAX_BYTES_CHAT_MSG @@ -331,7 +333,7 @@ impl Client { // 1) Handle input from frontend. // Pass character actions from frontend input to the player's entity. - if let ClientState::Character | ClientState::Dead = self.client_state { + if let ClientState::Character = self.client_state { self.state.write_component( self.entity, Controller { @@ -560,8 +562,8 @@ impl Client { .duration_since(self.last_server_ping) .as_secs_f64(); } - ServerMsg::ChatMsg { chat_type, message } => { - frontend_events.push(Event::Chat { chat_type, message }) + ServerMsg::ChatMsg { message, chat_type } => { + frontend_events.push(Event::Chat { message, chat_type }) } ServerMsg::SetPlayerEntity(uid) => { if let Some(entity) = self.state.ecs().entity_from_uid(uid) { @@ -591,6 +593,26 @@ impl Client { .delete_entity_and_clear_from_uid_allocator(entity); } } + // Cleanup for when the client goes back to the `Registered` state + ServerMsg::ExitIngameCleanup => { + // Get client entity Uid + let client_uid = self + .state + .read_component_cloned::(self.entity) + .map(|u| u.into()) + .expect("Client doesn't have a Uid!!!"); + // Clear ecs of all entities + self.state.ecs_mut().delete_all(); + self.state.ecs_mut().maintain(); + self.state.ecs_mut().insert(UidAllocator::default()); + // Recreate client entity with Uid + let entity_builder = self.state.ecs_mut().create_entity(); + let uid = entity_builder + .world + .write_resource::() + .allocate(entity_builder.entity, Some(client_uid)); + self.entity = entity_builder.with(uid).build(); + } ServerMsg::EntityPos { entity, pos } => { if let Some(entity) = self.state.ecs().entity_from_uid(entity) { self.state.write_component(entity, pos); @@ -641,9 +663,6 @@ impl Client { error, state ); } - ServerMsg::ForceState(state) => { - self.client_state = state; - } ServerMsg::Disconnect => { frontend_events.push(Event::Disconnect); } diff --git a/common/src/event.rs b/common/src/event.rs index ecdc180fe0..6dd8856f75 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -89,12 +89,15 @@ pub enum ServerEvent { Mount(EcsEntity, EcsEntity), Unmount(EcsEntity), Possess(Uid, Uid), - CreatePlayer { + CreateCharacter { entity: EcsEntity, name: String, body: comp::Body, main: Option, }, + ExitIngame { + entity: EcsEntity, + }, CreateNpc { pos: comp::Pos, stats: comp::Stats, diff --git a/common/src/msg/client.rs b/common/src/msg/client.rs index 2b031db3f1..ff2856bc81 100644 --- a/common/src/msg/client.rs +++ b/common/src/msg/client.rs @@ -1,6 +1,4 @@ -use super::ClientState; -use crate::terrain::block::Block; -use crate::{comp, ChatType}; +use crate::{comp, terrain::block::Block}; use vek::*; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -14,16 +12,18 @@ pub enum ClientMsg { body: comp::Body, main: Option, // Specifier for the weapon }, + /// Request `ClientState::Registered` from an ingame state + ExitIngame, + /// Request `ClientState::Specator` from a registered or ingame state + Spectate, ControllerInputs(comp::ControllerInputs), ControlEvent(comp::ControlEvent), - RequestState(ClientState), SetViewDistance(u32), BreakBlock(Vec3), PlaceBlock(Vec3, Block), Ping, Pong, ChatMsg { - chat_type: ChatType, // This is unused afaik, TODO: remove message: String, }, PlayerPhysics { @@ -36,42 +36,3 @@ pub enum ClientMsg { }, Disconnect, } - -impl ClientMsg { - pub fn chat(message: String) -> ClientMsg { - ClientMsg::ChatMsg { - chat_type: ChatType::Chat, - message, - } - } - pub fn tell(message: String) -> ClientMsg { - ClientMsg::ChatMsg { - chat_type: ChatType::Tell, - message, - } - } - pub fn game(message: String) -> ClientMsg { - ClientMsg::ChatMsg { - chat_type: ChatType::GameUpdate, - message, - } - } - pub fn broadcast(message: String) -> ClientMsg { - ClientMsg::ChatMsg { - chat_type: ChatType::Broadcast, - message, - } - } - pub fn private(message: String) -> ClientMsg { - ClientMsg::ChatMsg { - chat_type: ChatType::Private, - message, - } - } - pub fn kill(message: String) -> ClientMsg { - ClientMsg::ChatMsg { - chat_type: ChatType::Private, - message, - } - } -} diff --git a/common/src/msg/mod.rs b/common/src/msg/mod.rs index 13fc0eeb64..f0c19f719d 100644 --- a/common/src/msg/mod.rs +++ b/common/src/msg/mod.rs @@ -13,7 +13,6 @@ pub enum ClientState { Connected, Registered, Spectator, - Dead, Character, } diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index 710d8a4dfa..f517b7790e 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -41,7 +41,9 @@ pub enum ServerMsg { }, PlayerListUpdate(PlayerListUpdate), StateAnswer(Result), - ForceState(ClientState), + /// Trigger cleanup for when the client goes back to the `Registered` state from an ingame + /// state + ExitIngameCleanup, Ping, Pong, ChatMsg { diff --git a/server/src/client.rs b/server/src/client.rs index 6d15deae2a..333599d82c 100644 --- a/server/src/client.rs +++ b/server/src/client.rs @@ -11,6 +11,7 @@ pub struct Client { pub client_state: ClientState, pub postbox: PostBox, pub last_ping: f64, + pub login_msg_sent: bool, } impl Component for Client { @@ -23,16 +24,13 @@ impl Client { } pub fn is_registered(&self) -> bool { match self.client_state { - ClientState::Registered - | ClientState::Spectator - | ClientState::Dead - | ClientState::Character => true, + ClientState::Registered | ClientState::Spectator | ClientState::Character => true, _ => false, } } pub fn is_ingame(&self) -> bool { match self.client_state { - ClientState::Spectator | ClientState::Character | ClientState::Dead => true, + ClientState::Spectator | ClientState::Character => true, _ => false, } } @@ -45,10 +43,6 @@ impl Client { self.postbox .send_message(ServerMsg::StateAnswer(Err((error, self.client_state)))); } - pub fn force_state(&mut self, new_state: ClientState) { - self.client_state = new_state; - self.postbox.send_message(ServerMsg::ForceState(new_state)); - } } // Distance from fuzzy_chunk before snapping to current chunk diff --git a/server/src/lib.rs b/server/src/lib.rs index 24429bd6c7..a67ced3508 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -28,7 +28,7 @@ use common::{ msg::{ClientMsg, ClientState, PlayerListUpdate, ServerError, ServerInfo, ServerMsg}, net::PostOffice, state::{BlockChange, State, TimeOfDay}, - sync::{Uid, WorldSyncExt}, + sync::{Uid,UidAllocator, WorldSyncExt}, terrain::{block::Block, TerrainChunkSize, TerrainGrid}, vol::{ReadVol, RectVolSize, Vox}, }; @@ -37,7 +37,7 @@ use metrics::ServerMetrics; use rand::Rng; use specs::{ join::Join, world::EntityBuilder as EcsEntityBuilder, Builder, Entity as EcsEntity, RunNow, - SystemData, WorldExt, + SystemData, WorldExt, saveload::MarkerAllocator, }; use std::{ i32, @@ -413,10 +413,8 @@ impl Server { } } - let mut remove = true; - if let Some(client) = state.ecs().write_storage::().get_mut(entity) { - remove = false; + if state.ecs().write_storage::().get_mut(entity).is_some() { state .ecs() .write_storage() @@ -431,10 +429,8 @@ impl Server { .map(|err| { error!("Failed to insert ForceUpdate on dead client: {:?}", err) }); - client.force_state(ClientState::Dead); - } - - if remove { + } else { + // If not a player delete the entity if let Err(err) = state.delete_entity_recorded(entity) { error!("Failed to delete destroyed entity: {:?}", err); } @@ -580,13 +576,12 @@ impl Server { ServerEvent::Respawn(entity) => { // Only clients can respawn - if let Some(client) = state.ecs().write_storage::().get_mut(entity) { + if state.ecs().write_storage::().get_mut(entity).is_some() { let respawn_point = state .read_component_cloned::(entity) .map(|wp| wp.get_pos()) .unwrap_or(state.ecs().read_resource::().0); - client.allow_state(ClientState::Character); state .ecs() .write_storage::() @@ -597,10 +592,13 @@ impl Server { .write_storage::() .get_mut(entity) .map(|pos| pos.0 = respawn_point); - let _ = state + state .ecs() .write_storage() - .insert(entity, comp::ForceUpdate); + .insert(entity, comp::ForceUpdate) + .err().map(|err| + error!("Error inserting ForceUpdate component when respawning client: {:?}", err) + ); } } @@ -730,7 +728,7 @@ impl Server { } } - ServerEvent::CreatePlayer { + ServerEvent::CreateCharacter { entity, name, body, @@ -747,6 +745,40 @@ impl Server { sys::subscription::initialize_region_subscription(state.ecs(), entity); } + ServerEvent::ExitIngame { entity } => { + // Create new entity with just `Clienti`, `Uid`, and `Player` components + // Easier than checking and removing all other known components + // Note: If other `ServerEvent`s are referring to this entity they will be + // disrupted + let maybe_client = + state.ecs().write_storage::().remove(entity); + let maybe_uid = + state.read_component_cloned::(entity); + let maybe_player = + state.ecs().write_storage::().remove(entity); + if let (Some(mut client), Some(uid), Some(player)) = ( + maybe_client, maybe_uid, maybe_player, + ) { + // Tell client its request was successful + client.allow_state(ClientState::Registered); + // Tell client to clear out other entities and its own components + client.notify(ServerMsg::ExitIngameCleanup); + + let entity_builder = + state.ecs_mut().create_entity().with(client).with(player); + // Ensure UidAllocator maps this uid to the new entity + let uid = entity_builder + .world + .write_resource::() + .allocate(entity_builder.entity, Some(uid.into())); + entity_builder.with(uid).build(); + } + // Delete old entity + if let Err(err) = state.delete_entity_recorded(entity) { + error!("Failed to delete entity when removing character: {:?}", err); + } + } + ServerEvent::CreateNpc { pos, stats, @@ -993,6 +1025,7 @@ impl Server { client_state: ClientState::Connected, postbox, last_ping: self.state.get_time(), + login_msg_sent: false, }; if self.server_settings.max_players diff --git a/server/src/sys/message.rs b/server/src/sys/message.rs index f2466c281f..30f063436f 100644 --- a/server/src/sys/message.rs +++ b/server/src/sys/message.rs @@ -1,7 +1,7 @@ use super::SysTimer; use crate::{auth_provider::AuthProvider, client::Client, CLIENT_TIMEOUT}; use common::{ - comp::{Admin, Body, CanBuild, Controller, ForceUpdate, Ori, Player, Pos, Vel}, + comp::{Admin, Body, CanBuild, Controller, ForceUpdate, Ori, Player, Pos, Stats, Vel}, event::{EventBus, ServerEvent}, msg::{ validate_chat_msg, ChatMsgValidationError, ClientMsg, ClientState, PlayerListUpdate, @@ -31,6 +31,7 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, CanBuild>, ReadStorage<'a, Admin>, ReadStorage<'a, ForceUpdate>, + ReadStorage<'a, Stats>, WriteExpect<'a, AuthProvider>, Write<'a, BlockChange>, WriteStorage<'a, Pos>, @@ -54,6 +55,7 @@ impl<'a> System<'a> for Sys { can_build, admins, force_updates, + stats, mut accounts, mut block_changes, mut positions, @@ -98,40 +100,26 @@ impl<'a> System<'a> for Sys { // Process incoming messages. for msg in new_msgs { match msg { - ClientMsg::RequestState(requested_state) => match requested_state { - ClientState::Connected => disconnect = true, // Default state - ClientState::Registered => match client.client_state { - // Use ClientMsg::Register instead. - ClientState::Connected => { - client.error_state(RequestStateError::WrongMessage) - } - ClientState::Registered => { - client.error_state(RequestStateError::Already) - } - ClientState::Spectator | ClientState::Character | ClientState::Dead => { - // TODO: remove position etc here - client.allow_state(ClientState::Registered) - } - ClientState::Pending => {} - }, - ClientState::Spectator => match requested_state { - // Become Registered first. - ClientState::Connected => { - client.error_state(RequestStateError::Impossible) - } - ClientState::Spectator => { - client.error_state(RequestStateError::Already) - } - ClientState::Registered - | ClientState::Character - | ClientState::Dead => client.allow_state(ClientState::Spectator), - ClientState::Pending => {} - }, - // Use ClientMsg::Character instead. - ClientState::Character => { + // Go back to registered state (char selection screen) + ClientMsg::ExitIngame => match client.client_state { + // Use ClientMsg::Register instead. + ClientState::Connected => { client.error_state(RequestStateError::WrongMessage) } - ClientState::Dead => client.error_state(RequestStateError::Impossible), + ClientState::Registered => client.error_state(RequestStateError::Already), + ClientState::Spectator | ClientState::Character => { + server_emitter.emit(ServerEvent::ExitIngame { entity }); + } + ClientState::Pending => {} + }, + // Request spectator state + ClientMsg::Spectate => match client.client_state { + // Become Registered first. + ClientState::Connected => client.error_state(RequestStateError::Impossible), + ClientState::Spectator => client.error_state(RequestStateError::Already), + ClientState::Registered | ClientState::Character => { + client.allow_state(ClientState::Spectator) + } ClientState::Pending => {} }, // Valid player @@ -173,12 +161,12 @@ impl<'a> System<'a> for Sys { ClientMsg::Character { name, body, main } => match client.client_state { // Become Registered first. ClientState::Connected => client.error_state(RequestStateError::Impossible), - ClientState::Registered | ClientState::Spectator | ClientState::Dead => { - if let (Some(player), None) = ( + ClientState::Registered | ClientState::Spectator => { + if let (Some(player), false) = ( players.get(entity), - // Only send login message if the player didn't have a body + // Only send login message if it wasn't already sent // previously - bodies.get(entity), + client.login_msg_sent, ) { new_chat_msgs.push(( None, @@ -187,9 +175,10 @@ impl<'a> System<'a> for Sys { &player.alias )), )); + client.login_msg_sent = true; } - server_emitter.emit(ServerEvent::CreatePlayer { + server_emitter.emit(ServerEvent::CreateCharacter { entity, name, body, @@ -205,7 +194,7 @@ impl<'a> System<'a> for Sys { | ClientState::Spectator => { client.error_state(RequestStateError::Impossible) } - ClientState::Dead | ClientState::Character => { + ClientState::Character => { if let Some(controller) = controllers.get_mut(entity) { controller.inputs = inputs; } @@ -218,21 +207,19 @@ impl<'a> System<'a> for Sys { | ClientState::Spectator => { client.error_state(RequestStateError::Impossible) } - ClientState::Dead | ClientState::Character => { + ClientState::Character => { if let Some(controller) = controllers.get_mut(entity) { controller.events.push(event); } } ClientState::Pending => {} }, - ClientMsg::ChatMsg { chat_type, message } => match client.client_state { + ClientMsg::ChatMsg { message } => match client.client_state { ClientState::Connected => client.error_state(RequestStateError::Impossible), ClientState::Registered | ClientState::Spectator - | ClientState::Dead | ClientState::Character => match validate_chat_msg(&message) { - Ok(()) => new_chat_msgs - .push((Some(entity), ServerMsg::ChatMsg { chat_type, message })), + Ok(()) => new_chat_msgs.push((Some(entity), ServerMsg::chat(message))), Err(ChatMsgValidationError::TooLong) => log::warn!( "Recieved a chat message that's too long (max:{} len:{})", MAX_BYTES_CHAT_MSG, @@ -243,7 +230,9 @@ impl<'a> System<'a> for Sys { }, ClientMsg::PlayerPhysics { pos, vel, ori } => match client.client_state { ClientState::Character => { - if force_updates.get(entity).is_none() { + if force_updates.get(entity).is_none() + && stats.get(entity).map_or(true, |s| !s.is_dead) + { let _ = positions.insert(entity, pos); let _ = velocities.insert(entity, vel); let _ = orientations.insert(entity, ori); @@ -263,7 +252,7 @@ impl<'a> System<'a> for Sys { } } ClientMsg::TerrainChunkRequest { key } => match client.client_state { - ClientState::Connected | ClientState::Registered | ClientState::Dead => { + ClientState::Connected | ClientState::Registered => { client.error_state(RequestStateError::Impossible); } ClientState::Spectator | ClientState::Character => { diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 8e7e0275c0..3deff8abd4 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -121,9 +121,7 @@ impl PlayState for SessionState { // Game loop let mut current_client_state = self.client.borrow().get_client_state(); - while let ClientState::Pending | ClientState::Character | ClientState::Dead = - current_client_state - { + while let ClientState::Pending | ClientState::Character = current_client_state { // Compute camera data let (view_mat, _, cam_pos) = self .scene From 06ea29bd4cce8ee04e08a19740640626f7054042 Mon Sep 17 00:00:00 2001 From: Imbris Date: Tue, 31 Dec 2019 03:32:37 -0500 Subject: [PATCH 24/51] Small connection error handling improvement --- voxygen/src/menu/main/client_init.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/voxygen/src/menu/main/client_init.rs b/voxygen/src/menu/main/client_init.rs index ff53f27006..6649d6ceff 100644 --- a/voxygen/src/menu/main/client_init.rs +++ b/voxygen/src/menu/main/client_init.rs @@ -1,5 +1,5 @@ use client::{error::Error as ClientError, Client}; -use common::comp; +use common::{comp, net::PostError}; use crossbeam::channel::{unbounded, Receiver, TryRecvError}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; @@ -87,6 +87,10 @@ impl ClientInit { } Err(err) => { match err { + ClientError::Network(PostError::Bincode(_)) => { + last_err = Some(Error::ConnectionFailed(err)); + break 'tries; + } // Assume the connection failed and try again soon ClientError::Network(_) => {} ClientError::TooManyPlayers => { From c9caf148779eb5045cf64c7c99868c2e7e9ec6b4 Mon Sep 17 00:00:00 2001 From: Imbris Date: Tue, 31 Dec 2019 03:47:00 -0500 Subject: [PATCH 25/51] Fix formatting, Update CHANGELOG, turn overflow checks on for dev profile --- CHANGELOG.md | 1 + Cargo.toml | 4 ++-- server/src/lib.rs | 44 +++++++++++++++++++++++++------------------- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bec6a47843..50b2594f95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed region display name - Fixed the bow fire rate - Healthbars now flash on critical health +- Fixed ghosts when going back to character screen ### Removed diff --git a/Cargo.toml b/Cargo.toml index 9c674add42..1c26a0fa62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,10 +14,10 @@ members = [ # default profile for devs, fast to compile, okay enough to run, no debug information [profile.dev] opt-level = 2 -overflow-checks = false +overflow-checks = true debug-assertions = true panic = "abort" -debug = false +debug = false codegen-units = 8 lto = false incremental = true diff --git a/server/src/lib.rs b/server/src/lib.rs index a67ced3508..d6d1ba9948 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -28,7 +28,7 @@ use common::{ msg::{ClientMsg, ClientState, PlayerListUpdate, ServerError, ServerInfo, ServerMsg}, net::PostOffice, state::{BlockChange, State, TimeOfDay}, - sync::{Uid,UidAllocator, WorldSyncExt}, + sync::{Uid, UidAllocator, WorldSyncExt}, terrain::{block::Block, TerrainChunkSize, TerrainGrid}, vol::{ReadVol, RectVolSize, Vox}, }; @@ -36,8 +36,8 @@ use log::{debug, error}; use metrics::ServerMetrics; use rand::Rng; use specs::{ - join::Join, world::EntityBuilder as EcsEntityBuilder, Builder, Entity as EcsEntity, RunNow, - SystemData, WorldExt, saveload::MarkerAllocator, + join::Join, saveload::MarkerAllocator, world::EntityBuilder as EcsEntityBuilder, Builder, + Entity as EcsEntity, RunNow, SystemData, WorldExt, }; use std::{ i32, @@ -413,8 +413,12 @@ impl Server { } } - - if state.ecs().write_storage::().get_mut(entity).is_some() { + if state + .ecs() + .write_storage::() + .get_mut(entity) + .is_some() + { state .ecs() .write_storage() @@ -576,7 +580,12 @@ impl Server { ServerEvent::Respawn(entity) => { // Only clients can respawn - if state.ecs().write_storage::().get_mut(entity).is_some() { + if state + .ecs() + .write_storage::() + .get_mut(entity) + .is_some() + { let respawn_point = state .read_component_cloned::(entity) .map(|wp| wp.get_pos()) @@ -596,7 +605,7 @@ impl Server { .ecs() .write_storage() .insert(entity, comp::ForceUpdate) - .err().map(|err| + .err().map(|err| error!("Error inserting ForceUpdate component when respawning client: {:?}", err) ); } @@ -750,19 +759,16 @@ impl Server { // Easier than checking and removing all other known components // Note: If other `ServerEvent`s are referring to this entity they will be // disrupted - let maybe_client = - state.ecs().write_storage::().remove(entity); - let maybe_uid = - state.read_component_cloned::(entity); - let maybe_player = - state.ecs().write_storage::().remove(entity); - if let (Some(mut client), Some(uid), Some(player)) = ( - maybe_client, maybe_uid, maybe_player, - ) { - // Tell client its request was successful - client.allow_state(ClientState::Registered); + let maybe_client = state.ecs().write_storage::().remove(entity); + let maybe_uid = state.read_component_cloned::(entity); + let maybe_player = state.ecs().write_storage::().remove(entity); + if let (Some(mut client), Some(uid), Some(player)) = + (maybe_client, maybe_uid, maybe_player) + { + // Tell client its request was successful + client.allow_state(ClientState::Registered); // Tell client to clear out other entities and its own components - client.notify(ServerMsg::ExitIngameCleanup); + client.notify(ServerMsg::ExitIngameCleanup); let entity_builder = state.ecs_mut().create_entity().with(client).with(player); From 1acf08390a4e69d97b29482b2475767f702668c7 Mon Sep 17 00:00:00 2001 From: Imbris Date: Tue, 31 Dec 2019 16:37:55 -0500 Subject: [PATCH 26/51] Fix issue where controller events aren't processed while mounted. Fix non humanoids being able to climb and glide. --- CHANGELOG.md | 2 ++ Cargo.toml | 2 +- common/src/sys/controller.rs | 62 +++++++++++++++++++++--------------- common/src/sys/mod.rs | 4 +-- common/src/sys/mount.rs | 18 +++++++++-- common/src/sys/movement.rs | 3 +- 6 files changed, 57 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50b2594f95..9874892a9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed the bow fire rate - Healthbars now flash on critical health - Fixed ghosts when going back to character screen +- Fixed not being able to unmount +- Fixed non-humanoids being able to climb and glide ### Removed diff --git a/Cargo.toml b/Cargo.toml index 1c26a0fa62..122302dbfc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,7 @@ opt-level = 2 inherits= 'dev' debug = true -# this profil is used for veloren releases, compile time doesn't matter +# this profile is used for veloren releases, compile time doesn't matter # we need stacktraces, light debug information, as much checks as possible # I would like to put it in a seperate `official_release` target, but that doesnt share caches with `cargo test` and `cargo bench` [profile.release] diff --git a/common/src/sys/controller.rs b/common/src/sys/controller.rs index 999ebbba4a..ddc8ad08f8 100644 --- a/common/src/sys/controller.rs +++ b/common/src/sys/controller.rs @@ -327,6 +327,24 @@ impl<'a> System<'a> for Sys { // Or do nothing continue; } + + // Process controller events + for event in controller.events.drain(..) { + match event { + ControlEvent::Mount(mountee_uid) => { + if let Some(mountee_entity) = + uid_allocator.retrieve_entity_internal(mountee_uid.id()) + { + server_emitter.emit(ServerEvent::Mount(entity, mountee_entity)); + } + } + ControlEvent::Unmount => server_emitter.emit(ServerEvent::Unmount(entity)), + ControlEvent::InventoryManip(manip) => { + server_emitter.emit(ServerEvent::InventoryManip(entity, manip)) + } //ControlEvent::Respawn => server_emitter.emit(ServerEvent::Unmount(entity)), + } + } + // If mounted, character state is controlled by mount if mount.is_some() { character.movement = Sit; @@ -394,16 +412,17 @@ impl<'a> System<'a> for Sys { // Any Action + Falling (action_state, Fall) => { character.movement = get_state_from_move_dir(&inputs.move_dir); - if inputs.glide.is_pressed() { + if inputs.glide.is_pressed() && can_glide(body) { character.movement = Glide; continue; } // Try to climb if let (true, Some(_wall_dir)) = ( - inputs.climb.is_pressed() | inputs.climb_down.is_pressed() - && body.is_humanoid(), + (inputs.climb.is_pressed() | inputs.climb_down.is_pressed()) + && can_climb(body), physics.on_wall, ) { + println!("here 1"); character.movement = Climb; continue; } @@ -530,10 +549,11 @@ impl<'a> System<'a> for Sys { // Try to climb if let (true, Some(_wall_dir)) = ( - inputs.climb.is_pressed() | inputs.climb_down.is_pressed() - && body.is_humanoid(), + (inputs.climb.is_pressed() | inputs.climb_down.is_pressed()) + && can_climb(body), physics.on_wall, ) { + println!("here 2"); character.movement = Climb; continue; } @@ -578,9 +598,7 @@ impl<'a> System<'a> for Sys { // While not on ground ... else { // Try to glide - if physics.on_wall == None - && inputs.glide.is_pressed() - && body.is_humanoid() + if physics.on_wall == None && inputs.glide.is_pressed() && can_glide(&body) { character.movement = Glide; continue; @@ -652,7 +670,8 @@ impl<'a> System<'a> for Sys { if !inputs.glide.is_pressed() { character.movement = Fall; - } else if let Some(_wall_dir) = physics.on_wall { + } else if let (Some(_wall_dir), true) = (physics.on_wall, can_climb(body)) { + println!("here 3"); character.movement = Climb; } @@ -681,23 +700,14 @@ impl<'a> System<'a> for Sys { // character.movement = Fall; // } }; - - // Process other controller events - for event in controller.events.drain(..) { - match event { - ControlEvent::Mount(mountee_uid) => { - if let Some(mountee_entity) = - uid_allocator.retrieve_entity_internal(mountee_uid.id()) - { - server_emitter.emit(ServerEvent::Mount(entity, mountee_entity)); - } - } - ControlEvent::Unmount => server_emitter.emit(ServerEvent::Unmount(entity)), - ControlEvent::InventoryManip(manip) => { - server_emitter.emit(ServerEvent::InventoryManip(entity, manip)) - } //ControlEvent::Respawn => server_emitter.emit(ServerEvent::Unmount(entity)), - } - } } } } + +fn can_glide(body: &Body) -> bool { + body.is_humanoid() +} + +fn can_climb(body: &Body) -> bool { + body.is_humanoid() +} diff --git a/common/src/sys/mod.rs b/common/src/sys/mod.rs index 8006c20abc..6f2c402318 100644 --- a/common/src/sys/mod.rs +++ b/common/src/sys/mod.rs @@ -24,8 +24,8 @@ const CLEANUP_SYS: &str = "cleanup_sys"; pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) { dispatch_builder.add(agent::Sys, AGENT_SYS, &[]); - dispatch_builder.add(controller::Sys, CONTROLLER_SYS, &[AGENT_SYS]); - dispatch_builder.add(mount::Sys, MOUNT_SYS, &[CONTROLLER_SYS]); + dispatch_builder.add(mount::Sys, MOUNT_SYS, &[AGENT_SYS]); + dispatch_builder.add(controller::Sys, CONTROLLER_SYS, &[AGENT_SYS, MOUNT_SYS]); dispatch_builder.add(movement::Sys, MOVEMENT_SYS, &[]); dispatch_builder.add(combat::Sys, COMBAT_SYS, &[CONTROLLER_SYS]); dispatch_builder.add(stats::Sys, STATS_SYS, &[COMBAT_SYS]); diff --git a/common/src/sys/mount.rs b/common/src/sys/mount.rs index 741ee9212d..acb0e65b5e 100644 --- a/common/src/sys/mount.rs +++ b/common/src/sys/mount.rs @@ -40,9 +40,15 @@ impl<'a> System<'a> for Sys { match mount_states.get_unchecked() { MountState::Unmounted => {} MountState::MountedBy(mounter_uid) => { - if let Some((controller, mounter)) = uid_allocator + // Note: currently controller events are not passed through since none of them + // are currently relevant to controlling the mounted entity + if let Some((inputs, mounter)) = uid_allocator .retrieve_entity_internal(mounter_uid.id()) - .and_then(|mounter| controllers.get(mounter).cloned().map(|x| (x, mounter))) + .and_then(|mounter| { + controllers + .get(mounter) + .map(|c| (c.inputs.clone(), mounter)) + }) { // TODO: consider joining on these? (remember we can use .maybe()) let pos = positions.get(entity).copied(); @@ -53,7 +59,13 @@ impl<'a> System<'a> for Sys { let _ = orientations.insert(mounter, ori); let _ = velocities.insert(mounter, vel); } - let _ = controllers.insert(entity, controller); + let _ = controllers.insert( + entity, + Controller { + inputs, + ..Default::default() + }, + ); } else { *(mount_states.get_mut_unchecked()) = MountState::Unmounted; } diff --git a/common/src/sys/movement.rs b/common/src/sys/movement.rs index 4c85dfc8cc..805de636a4 100644 --- a/common/src/sys/movement.rs +++ b/common/src/sys/movement.rs @@ -209,8 +209,7 @@ impl<'a> System<'a> for Sys { // Climb if let (true, Some(_wall_dir)) = ( - (inputs.climb.is_pressed() | inputs.climb_down.is_pressed()) - && vel.0.z <= CLIMB_SPEED, + character.movement == Climb && vel.0.z <= CLIMB_SPEED, physics.on_wall, ) { if inputs.climb_down.is_pressed() && !inputs.climb.is_pressed() { From 2644e2948466a4724c2ef80927a4979b9e5f64d5 Mon Sep 17 00:00:00 2001 From: S Handley Date: Wed, 1 Jan 2020 02:55:48 +0000 Subject: [PATCH 27/51] Refactor and Rename for clarity Implements a potential structure for splitting the SFX event mapping into smaller individual files for maintainability. - Remove inventory events for now: For a later commit. - No longer panic when there is a failure parsing the sfx file: log the error and not play sfx. --- assets/voxygen/audio/sfx.ron | 34 +---- common/src/event.rs | 7 +- voxygen/src/audio/sfx/event_mapper/mod.rs | 27 ++++ .../movement.rs} | 77 +++++++---- .../src/audio/sfx/event_mapper/progression.rs | 120 ++++++++++++++++++ voxygen/src/audio/sfx/mod.rs | 52 +++++--- 6 files changed, 239 insertions(+), 78 deletions(-) create mode 100644 voxygen/src/audio/sfx/event_mapper/mod.rs rename voxygen/src/audio/sfx/{event_mapper.rs => event_mapper/movement.rs} (81%) create mode 100644 voxygen/src/audio/sfx/event_mapper/progression.rs diff --git a/assets/voxygen/audio/sfx.ron b/assets/voxygen/audio/sfx.ron index 3a3ca23a26..8310f26c09 100644 --- a/assets/voxygen/audio/sfx.ron +++ b/assets/voxygen/audio/sfx.ron @@ -1,7 +1,6 @@ ( - items: [ - ( - trigger: Run, + { + Run: ( files: [ "voxygen.audio.sfx.footsteps.stepgrass_1", "voxygen.audio.sfx.footsteps.stepgrass_2", @@ -12,40 +11,17 @@ ], threshold: 0.25, ), - ( - trigger: GliderOpen, + GliderOpen: ( files: [ "voxygen.audio.sfx.glider_open", ], threshold: 0.5, ), - ( - trigger: GliderClose, + GliderClose: ( files: [ "voxygen.audio.sfx.glider_close", ], threshold: 0.5, ), - ( - trigger: Attack(Sword), - files: [ - "voxygen.audio.sfx.weapon.sword", - ], - threshold: 0.5, - ), - ( - trigger: Attack(Hammer), - files: [ - "voxygen.audio.sfx.weapon.sword", - ], - threshold: 0.5, - ), - ( - trigger: Attack(Bow), - files: [ - "voxygen.audio.sfx.weapon.bow", - ], - threshold: 0.5, - ), - ], + } ) \ No newline at end of file diff --git a/common/src/event.rs b/common/src/event.rs index ecdc180fe0..1eebf3f08e 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -29,18 +29,17 @@ pub enum SfxEvent { OpenChest, ChatTellReceived, OpenBag, - LevelUp, + Run, Roll, Climb, Swim, - Run, GliderOpen, Glide, GliderClose, Jump, Fall, - InventoryAdd, - InventoryDrop, + ExperienceGained, + LevelUp, LightLantern, ExtinguishLantern, Attack(Tool), diff --git a/voxygen/src/audio/sfx/event_mapper/mod.rs b/voxygen/src/audio/sfx/event_mapper/mod.rs new file mode 100644 index 0000000000..e195d1cba2 --- /dev/null +++ b/voxygen/src/audio/sfx/event_mapper/mod.rs @@ -0,0 +1,27 @@ +pub mod movement; +pub mod progression; + +use movement::MovementEventMapper; +use progression::ProgressionEventMapper; + +use super::SfxTriggers; +use client::Client; + +pub struct SfxEventMapper { + progression_event_mapper: ProgressionEventMapper, + movement_event_mapper: MovementEventMapper, +} + +impl SfxEventMapper { + pub fn new() -> Self { + Self { + progression_event_mapper: ProgressionEventMapper::new(), + movement_event_mapper: MovementEventMapper::new(), + } + } + + pub fn maintain(&mut self, client: &Client, triggers: &SfxTriggers) { + self.progression_event_mapper.maintain(client, triggers); + self.movement_event_mapper.maintain(client, triggers); + } +} diff --git a/voxygen/src/audio/sfx/event_mapper.rs b/voxygen/src/audio/sfx/event_mapper/movement.rs similarity index 81% rename from voxygen/src/audio/sfx/event_mapper.rs rename to voxygen/src/audio/sfx/event_mapper/movement.rs index 9a6f7c3d92..114a785390 100644 --- a/voxygen/src/audio/sfx/event_mapper.rs +++ b/voxygen/src/audio/sfx/event_mapper/movement.rs @@ -1,5 +1,5 @@ -/// sfx::event_mapper watches the local entities and determines which sfx to emit, -/// and the position at which the sound should be emitted from +/// event_mapper::movement watches all local entities movements and determines which +/// sfx to emit, and the position at which the sound should be emitted from use crate::audio::sfx::{SfxTriggerItem, SfxTriggers}; use client::Client; @@ -18,11 +18,11 @@ struct LastSfxEvent { time: Instant, } -pub struct SfxEventMapper { +pub struct MovementEventMapper { event_history: HashMap, } -impl SfxEventMapper { +impl MovementEventMapper { pub fn new() -> Self { Self { event_history: HashMap::new(), @@ -68,12 +68,7 @@ impl SfxEventMapper { }; // Check for SFX config entry for this movement - let sfx_trigger_item: Option<&SfxTriggerItem> = triggers - .items - .iter() - .find(|item| item.trigger == mapped_event); - - if Self::should_emit(state, sfx_trigger_item) { + if Self::should_emit(state, triggers.get_key_value(&mapped_event)) { ecs.read_resource::>() .emitter() .emit(SfxEventItem::new(mapped_event, Some(pos.0))); @@ -110,10 +105,10 @@ impl SfxEventMapper { /// 2. The sfx has not been played since it's timeout threshold has elapsed, which prevents firing every tick fn should_emit( last_play_entry: &LastSfxEvent, - sfx_trigger_item: Option<&SfxTriggerItem>, + sfx_trigger_item: Option<(&SfxEvent, &SfxTriggerItem)>, ) -> bool { - if let Some(item) = sfx_trigger_item { - if last_play_entry.event == item.trigger { + if let Some((event, item)) = sfx_trigger_item { + if &last_play_entry.event == event { last_play_entry.time.elapsed().as_secs_f64() >= item.threshold } else { true @@ -147,6 +142,13 @@ impl SfxEventMapper { SfxEvent::Glide } } + (MovementState::Stand, _, previous_event) => { + if previous_event == SfxEvent::Glide { + SfxEvent::GliderClose + } else { + SfxEvent::Idle + } + } _ => SfxEvent::Idle, } } @@ -168,15 +170,16 @@ mod tests { time: Instant::now(), }; - let result = SfxEventMapper::should_emit(&last_sfx_event, None); + let result = MovementEventMapper::should_emit(&last_sfx_event, None); assert_eq!(result, false); } #[test] fn config_but_played_since_threshold_no_emit() { + let event = SfxEvent::Run; + let trigger_item = SfxTriggerItem { - trigger: SfxEvent::Run, files: vec![String::from("some.path.to.sfx.file")], threshold: 1.0, }; @@ -187,15 +190,17 @@ mod tests { time: Instant::now(), }; - let result = SfxEventMapper::should_emit(&last_sfx_event, Some(&trigger_item)); + let result = + MovementEventMapper::should_emit(&last_sfx_event, Some((&event, &trigger_item))); assert_eq!(result, false); } #[test] fn config_and_not_played_since_threshold_emits() { + let event = SfxEvent::Run; + let trigger_item = SfxTriggerItem { - trigger: SfxEvent::Run, files: vec![String::from("some.path.to.sfx.file")], threshold: 0.5, }; @@ -205,15 +210,17 @@ mod tests { time: Instant::now().checked_add(Duration::from_secs(1)).unwrap(), }; - let result = SfxEventMapper::should_emit(&last_sfx_event, Some(&trigger_item)); + let result = + MovementEventMapper::should_emit(&last_sfx_event, Some((&event, &trigger_item))); assert_eq!(result, true); } #[test] fn same_previous_event_elapsed_emits() { + let event = SfxEvent::Run; + let trigger_item = SfxTriggerItem { - trigger: SfxEvent::Run, files: vec![String::from("some.path.to.sfx.file")], threshold: 0.5, }; @@ -225,14 +232,15 @@ mod tests { .unwrap(), }; - let result = SfxEventMapper::should_emit(&last_sfx_event, Some(&trigger_item)); + let result = + MovementEventMapper::should_emit(&last_sfx_event, Some((&event, &trigger_item))); assert_eq!(result, true); } #[test] fn maps_idle() { - let result = SfxEventMapper::map_movement_event( + let result = MovementEventMapper::map_movement_event( &CharacterState { movement: MovementState::Stand, action: ActionState::Idle, @@ -245,7 +253,7 @@ mod tests { #[test] fn maps_run() { - let result = SfxEventMapper::map_movement_event( + let result = MovementEventMapper::map_movement_event( &CharacterState { movement: MovementState::Run, action: ActionState::Idle, @@ -258,7 +266,7 @@ mod tests { #[test] fn maps_roll() { - let result = SfxEventMapper::map_movement_event( + let result = MovementEventMapper::map_movement_event( &CharacterState { action: ActionState::Roll { time_left: Duration::new(1, 0), @@ -274,7 +282,7 @@ mod tests { #[test] fn maps_fall() { - let result = SfxEventMapper::map_movement_event( + let result = MovementEventMapper::map_movement_event( &CharacterState { movement: MovementState::Fall, action: ActionState::Idle, @@ -287,7 +295,7 @@ mod tests { #[test] fn maps_glider_open() { - let result = SfxEventMapper::map_movement_event( + let result = MovementEventMapper::map_movement_event( &CharacterState { movement: MovementState::Glide, action: ActionState::Idle, @@ -300,7 +308,7 @@ mod tests { #[test] fn maps_glide() { - let result = SfxEventMapper::map_movement_event( + let result = MovementEventMapper::map_movement_event( &CharacterState { movement: MovementState::Glide, action: ActionState::Idle, @@ -312,8 +320,8 @@ mod tests { } #[test] - fn maps_glider_close() { - let result = SfxEventMapper::map_movement_event( + fn maps_glider_close_when_closing_mid_flight() { + let result = MovementEventMapper::map_movement_event( &CharacterState { movement: MovementState::Fall, action: ActionState::Idle, @@ -323,4 +331,17 @@ mod tests { assert_eq!(result, SfxEvent::GliderClose); } + + #[test] + fn maps_glider_close_when_landing() { + let result = MovementEventMapper::map_movement_event( + &CharacterState { + movement: MovementState::Stand, + action: ActionState::Idle, + }, + SfxEvent::Glide, + ); + + assert_eq!(result, SfxEvent::GliderClose); + } } diff --git a/voxygen/src/audio/sfx/event_mapper/progression.rs b/voxygen/src/audio/sfx/event_mapper/progression.rs new file mode 100644 index 0000000000..a264c8bb23 --- /dev/null +++ b/voxygen/src/audio/sfx/event_mapper/progression.rs @@ -0,0 +1,120 @@ +/// event_mapper::progression watches the the current player's level +/// and experience and emits associated SFX +use crate::audio::sfx::SfxTriggers; + +use client::Client; +use common::{ + comp::Stats, + event::{EventBus, SfxEvent, SfxEventItem}, +}; +use specs::WorldExt; + +#[derive(Clone, PartialEq)] +struct ProgressionState { + level: u32, + exp: u32, +} + +impl Default for ProgressionState { + fn default() -> Self { + Self { level: 1, exp: 0 } + } +} + +pub struct ProgressionEventMapper { + state: ProgressionState, +} + +impl ProgressionEventMapper { + pub fn new() -> Self { + Self { + state: ProgressionState::default(), + } + } + + pub fn maintain(&mut self, client: &Client, triggers: &SfxTriggers) { + let ecs = client.state().ecs(); + + // level and exp changes + let next_state = + ecs.read_storage::() + .get(client.entity()) + .map_or(self.state.clone(), |stats| ProgressionState { + level: stats.level.level(), + exp: stats.exp.current(), + }); + + if &self.state != &next_state { + if let Some(mapped_event) = self.map_event(&next_state) { + let sfx_trigger_item = triggers.get_trigger(&mapped_event); + + if sfx_trigger_item.is_some() { + ecs.read_resource::>() + .emitter() + .emit(SfxEventItem::at_player_position(mapped_event)); + } + } + + self.state = next_state; + } + } + + fn map_event(&mut self, next_state: &ProgressionState) -> Option { + let sfx_event = if next_state.level > self.state.level { + Some(SfxEvent::LevelUp) + } else if next_state.exp > self.state.exp { + Some(SfxEvent::ExperienceGained) + } else { + None + }; + + sfx_event + } +} + +#[cfg(test)] +mod tests { + use super::*; + use common::event::SfxEvent; + + #[test] + fn no_change_returns_none() { + let mut mapper = ProgressionEventMapper::new(); + let next_client_state = ProgressionState::default(); + + assert_eq!(mapper.map_event(&next_client_state), None); + } + + #[test] + fn change_level_returns_levelup() { + let mut mapper = ProgressionEventMapper::new(); + let next_client_state = ProgressionState { level: 2, exp: 0 }; + + assert_eq!( + mapper.map_event(&next_client_state), + Some(SfxEvent::LevelUp) + ); + } + + #[test] + fn change_exp_returns_expup() { + let mut mapper = ProgressionEventMapper::new(); + let next_client_state = ProgressionState { level: 1, exp: 100 }; + + assert_eq!( + mapper.map_event(&next_client_state), + Some(SfxEvent::ExperienceGained) + ); + } + + #[test] + fn level_up_and_gained_exp_prioritises_levelup() { + let mut mapper = ProgressionEventMapper::new(); + let next_client_state = ProgressionState { level: 2, exp: 100 }; + + assert_eq!( + mapper.map_event(&next_client_state), + Some(SfxEvent::LevelUp) + ); + } +} diff --git a/voxygen/src/audio/sfx/mod.rs b/voxygen/src/audio/sfx/mod.rs index 52ab02614c..ad37a5fb46 100644 --- a/voxygen/src/audio/sfx/mod.rs +++ b/voxygen/src/audio/sfx/mod.rs @@ -1,4 +1,5 @@ -/// The SfxManager listens for SFX events and plays the sound at the provided position +/// The Sfx Manager manages individual sfx event system, listens for +/// SFX events and plays the sound at the requested position, or the current player position mod event_mapper; use crate::audio::AudioFrontend; @@ -8,37 +9,53 @@ use common::{ comp::{Ori, Pos}, event::{EventBus, SfxEvent, SfxEventItem}, }; +use event_mapper::SfxEventMapper; +use hashbrown::HashMap; use serde::Deserialize; use specs::WorldExt; use vek::*; #[derive(Deserialize)] pub struct SfxTriggerItem { - pub trigger: SfxEvent, pub files: Vec, pub threshold: f64, } #[derive(Deserialize)] -pub struct SfxTriggers { - pub items: Vec, +pub struct SfxTriggers(HashMap); + +impl Default for SfxTriggers { + fn default() -> Self { + Self(HashMap::new()) + } +} + +impl SfxTriggers { + pub fn get_trigger(&self, trigger: &SfxEvent) -> Option<&SfxTriggerItem> { + self.0.get(trigger) + } + + pub fn get_key_value(&self, trigger: &SfxEvent) -> Option<(&SfxEvent, &SfxTriggerItem)> { + self.0.get_key_value(trigger) + } } pub struct SfxMgr { triggers: SfxTriggers, - event_mapper: event_mapper::SfxEventMapper, + event_mapper: SfxEventMapper, } impl SfxMgr { pub fn new() -> Self { Self { triggers: Self::load_sfx_items(), - event_mapper: event_mapper::SfxEventMapper::new(), + event_mapper: SfxEventMapper::new(), } } pub fn maintain(&mut self, audio: &mut AudioFrontend, client: &Client) { self.event_mapper.maintain(client, &self.triggers); + let ecs = client.state().ecs(); let player_position = ecs @@ -61,16 +78,7 @@ impl SfxMgr { _ => player_position, }; - // Get the SFX config entry for this movement - let sfx_trigger_item: Option<&SfxTriggerItem> = self - .triggers - .items - .iter() - .find(|item| item.trigger == event.sfx); - - if sfx_trigger_item.is_some() { - let item = sfx_trigger_item.expect("Invalid sfx item"); - + if let Some(item) = self.triggers.get_trigger(&event.sfx) { let sfx_file = match item.files.len() { 1 => item .files @@ -91,6 +99,16 @@ impl SfxMgr { let file = assets::load_file("voxygen.audio.sfx", &["ron"]) .expect("Failed to load the sfx config file"); - ron::de::from_reader(file).expect("Error parsing sfx manifest") + match ron::de::from_reader(file) { + Ok(config) => config, + Err(e) => { + log::warn!( + "Error parsing sfx config file, sfx will not be available: {}", + format!("{:#?}", e) + ); + + SfxTriggers::default() + } + } } } From f52aef224efcbba56107a7f04cef41ba8cceba32 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 2 Jan 2020 04:46:15 -0500 Subject: [PATCH 28/51] Fix typos, don't insert Controller if it doesn't already exist in the mount system so that Controller components are not added to entities client side --- common/src/msg/client.rs | 2 +- common/src/sys/controller.rs | 9 +++++---- common/src/sys/mount.rs | 9 ++++----- server/src/lib.rs | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/common/src/msg/client.rs b/common/src/msg/client.rs index ff2856bc81..b4022483ad 100644 --- a/common/src/msg/client.rs +++ b/common/src/msg/client.rs @@ -14,7 +14,7 @@ pub enum ClientMsg { }, /// Request `ClientState::Registered` from an ingame state ExitIngame, - /// Request `ClientState::Specator` from a registered or ingame state + /// Request `ClientState::Spectator` from a registered or ingame state Spectate, ControllerInputs(comp::ControllerInputs), ControlEvent(comp::ControlEvent), diff --git a/common/src/sys/controller.rs b/common/src/sys/controller.rs index ddc8ad08f8..f68839f571 100644 --- a/common/src/sys/controller.rs +++ b/common/src/sys/controller.rs @@ -341,7 +341,11 @@ impl<'a> System<'a> for Sys { ControlEvent::Unmount => server_emitter.emit(ServerEvent::Unmount(entity)), ControlEvent::InventoryManip(manip) => { server_emitter.emit(ServerEvent::InventoryManip(entity, manip)) - } //ControlEvent::Respawn => server_emitter.emit(ServerEvent::Unmount(entity)), + } /*ControlEvent::Respawn => { + if state.is_dead { + server_emitter.emit(ServerEvent::Respawn(entity)), + } + }*/ } } @@ -422,7 +426,6 @@ impl<'a> System<'a> for Sys { && can_climb(body), physics.on_wall, ) { - println!("here 1"); character.movement = Climb; continue; } @@ -553,7 +556,6 @@ impl<'a> System<'a> for Sys { && can_climb(body), physics.on_wall, ) { - println!("here 2"); character.movement = Climb; continue; } @@ -671,7 +673,6 @@ impl<'a> System<'a> for Sys { if !inputs.glide.is_pressed() { character.movement = Fall; } else if let (Some(_wall_dir), true) = (physics.on_wall, can_climb(body)) { - println!("here 3"); character.movement = Climb; } diff --git a/common/src/sys/mount.rs b/common/src/sys/mount.rs index acb0e65b5e..4a8b2ca7bf 100644 --- a/common/src/sys/mount.rs +++ b/common/src/sys/mount.rs @@ -59,13 +59,12 @@ impl<'a> System<'a> for Sys { let _ = orientations.insert(mounter, ori); let _ = velocities.insert(mounter, vel); } - let _ = controllers.insert( - entity, - Controller { + controllers.get_mut(entity).map(|controller| { + *controller = Controller { inputs, ..Default::default() - }, - ); + } + }); } else { *(mount_states.get_mut_unchecked()) = MountState::Unmounted; } diff --git a/server/src/lib.rs b/server/src/lib.rs index d6d1ba9948..2a5147ad1f 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -755,7 +755,7 @@ impl Server { } ServerEvent::ExitIngame { entity } => { - // Create new entity with just `Clienti`, `Uid`, and `Player` components + // Create new entity with just `Client`, `Uid`, and `Player` components // Easier than checking and removing all other known components // Note: If other `ServerEvent`s are referring to this entity they will be // disrupted From 38d44cc87f2fe23743a8ea5ff9ee03a873f0ecda Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Mon, 6 Jan 2020 15:07:08 +0100 Subject: [PATCH 29/51] fixed the trees being cut off --- assets/world/manifests/acacias.ron | 10 +++++----- assets/world/manifests/mangrove_trees.ron | 12 ++++++------ assets/world/manifests/oaks.ron | 16 ++++++++-------- assets/world/tree/acacia/1.vox | 4 ++-- assets/world/tree/acacia/2.vox | 4 ++-- assets/world/tree/acacia/3.vox | 4 ++-- assets/world/tree/acacia/4.vox | 4 ++-- assets/world/tree/acacia/5.vox | 4 ++-- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/assets/world/manifests/acacias.ron b/assets/world/manifests/acacias.ron index 20a86a4d06..7a7484c2d0 100644 --- a/assets/world/manifests/acacias.ron +++ b/assets/world/manifests/acacias.ron @@ -2,23 +2,23 @@ [ ( specifier: "world.tree.acacia.1", - center: (16, 17, 1) + center: (17, 18, 4) ), ( specifier: "world.tree.acacia.2", - center: (5, 6, 1) + center: (5, 5, 4) ), ( specifier: "world.tree.acacia.3", - center: (5, 6, 1) + center: (6, 6, 3) ), ( specifier: "world.tree.acacia.4", - center: (15, 16, 1) + center: (12, 14, 4) ), ( specifier: "world.tree.acacia.5", - center: (19, 18, 1) + center: (19, 19, 4) ), ] ) diff --git a/assets/world/manifests/mangrove_trees.ron b/assets/world/manifests/mangrove_trees.ron index 525cdb9b41..0dc5983246 100644 --- a/assets/world/manifests/mangrove_trees.ron +++ b/assets/world/manifests/mangrove_trees.ron @@ -2,7 +2,7 @@ [ ( specifier: "world.tree.mangroves.1", - center: (18, 18, 8) + center: (19, 18, 8) ), ( specifier: "world.tree.mangroves.2", @@ -10,11 +10,11 @@ ), ( specifier: "world.tree.mangroves.3", - center: (18, 18, 8) + center: (18, 19, 8) ), ( specifier: "world.tree.mangroves.4", - center: (18, 16, 8) + center: (19, 18, 8) ), ( specifier: "world.tree.mangroves.5", @@ -22,15 +22,15 @@ ), ( specifier: "world.tree.mangroves.6", - center: (18, 18, 9) + center: (18, 21, 9) ), ( specifier: "world.tree.mangroves.7", - center: (18, 17, 9) + center: (20, 17, 9) ), ( specifier: "world.tree.mangroves.8", - center: (18, 18, 9) + center: (18, 19, 9) ), ] ) diff --git a/assets/world/manifests/oaks.ron b/assets/world/manifests/oaks.ron index 81301c48c1..53b5faef50 100644 --- a/assets/world/manifests/oaks.ron +++ b/assets/world/manifests/oaks.ron @@ -2,19 +2,19 @@ [ ( specifier: "world.tree.oak_green.1", - center: (15, 18, 14) + center: (15, 17, 14) ), ( specifier: "world.tree.oak_green.2", - center: (15, 18, 14) + center: (18, 17, 14) ), ( specifier: "world.tree.oak_green.3", - center: (16, 20, 14) + center: (19, 20, 14) ), ( specifier: "world.tree.oak_green.4", - center: (18, 21, 14) + center: (19, 20, 14) ), ( specifier: "world.tree.oak_green.5", @@ -22,19 +22,19 @@ ), ( specifier: "world.tree.oak_green.6", - center: (16, 21, 14) + center: (18, 21, 14) ), ( specifier: "world.tree.oak_green.7", - center: (20, 19, 14) + center: (20, 21, 14) ), ( specifier: "world.tree.oak_green.8", - center: (22, 20, 14) + center: (22, 21, 14) ), ( specifier: "world.tree.oak_green.9", - center:(26, 26, 14) + center:(21, 21, 14) ), ] ) diff --git a/assets/world/tree/acacia/1.vox b/assets/world/tree/acacia/1.vox index c430606bfc..7f3bb1b173 100644 --- a/assets/world/tree/acacia/1.vox +++ b/assets/world/tree/acacia/1.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2a5035086a7d26f04608f40d22aca9d47adf98998d1b7e15e2372888a3b43ae8 -size 76828 +oid sha256:96fbf34cd1b8bf56bf6bd369ddfbbba6ba181b0ffbd7367c15a1a32a0dd25379 +size 77084 diff --git a/assets/world/tree/acacia/2.vox b/assets/world/tree/acacia/2.vox index 5ebcb50566..c80037b118 100644 --- a/assets/world/tree/acacia/2.vox +++ b/assets/world/tree/acacia/2.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:688a03d477499e69541b7feec4ce6bebd7dede1e743540e2c3cbcd9b0a53c016 -size 56619 +oid sha256:5b89cd2aa4c79d86637e82f325bdb5f3ebb89e0c216c97e891b1f05f7f14bf91 +size 56643 diff --git a/assets/world/tree/acacia/3.vox b/assets/world/tree/acacia/3.vox index 7c8243bb9a..30d4e6bf6a 100644 --- a/assets/world/tree/acacia/3.vox +++ b/assets/world/tree/acacia/3.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:455b635d1bc20402a3290cbfdc7c030d3de428287b820cf0dde1aa0be4a74ee2 -size 57487 +oid sha256:b086b9949e2025fc674b0df09ce8d490b646537ee89cfbd70717db0c253afbc2 +size 57551 diff --git a/assets/world/tree/acacia/4.vox b/assets/world/tree/acacia/4.vox index d089cfa34e..cdee6ba1c6 100644 --- a/assets/world/tree/acacia/4.vox +++ b/assets/world/tree/acacia/4.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a37debf05102414ef85d2a1799ba28749de7e5d5290c152d374494a984bfe22a -size 72004 +oid sha256:0ed2d8fe61bae4f075f95e5f1a14936cadab3bc69eac0784672557942314d878 +size 72196 diff --git a/assets/world/tree/acacia/5.vox b/assets/world/tree/acacia/5.vox index 56f0e5f01a..f744a7aaec 100644 --- a/assets/world/tree/acacia/5.vox +++ b/assets/world/tree/acacia/5.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1cc51107d88924dbf1637ae8f424b5292299eb35c50eeb07cae0be5fe3766f6 -size 88092 +oid sha256:9dc5d76617a8aa6ae70e692b30e7f71ba6e32b558a1934446eca77ebdabb59f1 +size 88204 From 43febb5bf307c80531f08dcdfa62bd13fee81299 Mon Sep 17 00:00:00 2001 From: Pierce Brooks Date: Tue, 7 Jan 2020 05:45:43 +0000 Subject: [PATCH 30/51] fix #426: Use new dispatch dependency to ensure proper thread routing of msgbox NSAlert calls ( correct MR workflow ) --- Cargo.lock | 7 +++++++ voxygen/Cargo.toml | 3 +++ voxygen/src/main.rs | 8 +++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 030eb943a1..47f8ff68bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -893,6 +893,11 @@ dependencies = [ "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dispatch" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "dlib" version = "0.4.1" @@ -3512,6 +3517,7 @@ dependencies = [ "crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "discord-rpc-sdk 0.1.1 (git+https://github.com/Songtronix/rust-discord-rpc.git)", + "dispatch 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "euc 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3926,6 +3932,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" "checksum discord-rpc-sdk 0.1.1 (git+https://github.com/Songtronix/rust-discord-rpc.git)" = "" "checksum discord-rpc-sys 0.1.0 (git+https://github.com/Songtronix/rust-discord-rpc.git)" = "" +"checksum dispatch 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e93ca78226c51902d7aa8c12c988338aadd9e85ed9c6be8aaac39192ff3605" "checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a" "checksum dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11afd3251e588f2770226659b2a1d55ec2f8aaf2ca42bdcdbd01ff53b4a81e70" "checksum downcast-rs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6" diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index daa6fbfd66..e432239808 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -64,5 +64,8 @@ hashbrown = { version = "0.6.2", features = ["serde", "nightly"] } chrono = "0.4.9" rust-argon2 = "0.5" +[target.'cfg(target_os = "macos")'.dependencies] +dispatch = "0.1.4" + [target.'cfg(windows)'.build-dependencies] winres = "0.1" diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index 6ebdfc38a6..70ade6247a 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -201,7 +201,13 @@ fn main() { ); #[cfg(feature = "msgbox")] - msgbox::create("Voxygen has panicked", &msg, msgbox::IconType::Error); + { + #[cfg(target_os = "macos")] + dispatch::Queue::main() + .sync(|| msgbox::create("Voxygen has panicked", &msg, msgbox::IconType::Error)); + #[cfg(not(target_os = "macos"))] + msgbox::create("Voxygen has panicked", &msg, msgbox::IconType::Error); + } default_hook(panic_info); })); From fd9cc7678621eb6f34266bf0ec0e023da8e24cd1 Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Tue, 19 Nov 2019 16:20:20 +0300 Subject: [PATCH 31/51] Reimplement #210 --- assets/voxygen/shaders/terrain-frag.glsl | 2 +- voxygen/src/mesh/terrain.rs | 10 +++++++++- voxygen/src/render/pipelines/terrain.rs | 14 +++----------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index 0fb2811441..b148b6da4f 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -27,7 +27,7 @@ void main() { // Increase array access by 3 to access positive values uint norm_dir = ((f_pos_norm >> 29) & 0x1u) * 3u; // Use an array to avoid conditional branching - vec3 f_norm = normals[norm_axis + norm_dir]; + vec3 f_norm = normals[(f_pos_norm >> 29) & 0x7u]; vec3 light, diffuse_light, ambient_light; get_sun_diffuse(f_norm, time_of_day.x, light, diffuse_light, ambient_light, 1.0); diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index fc557a5ffd..5154c20617 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -236,7 +236,15 @@ impl + ReadVol + Debug> Meshable, norm: Vec3, col: Rgb, light: f32) -> Self { - let (norm_axis, norm_dir) = norm - .as_slice() - .into_iter() - .enumerate() - .find(|(_i, e)| **e != 0.0) - .unwrap_or((0, &1.0)); - let norm_bits = (norm_axis << 1) | if *norm_dir > 0.0 { 1 } else { 0 }; - + pub fn new(norm_bits: u32, light: u32, pos: Vec3, col: Rgb) -> Self { Self { pos_norm: 0 | ((pos.x as u32) & 0x00FF) << 0 | ((pos.y as u32) & 0x00FF) << 8 | ((pos.z.max(0.0).min((1 << 13) as f32) as u32) & 0x1FFF) << 16 - | ((norm_bits as u32) & 0x7) << 29, + | (norm_bits & 0x7) << 29, col_light: 0 | ((col.r.mul(255.0) as u32) & 0xFF) << 8 | ((col.g.mul(255.0) as u32) & 0xFF) << 16 | ((col.b.mul(255.0) as u32) & 0xFF) << 24 - | ((light.mul(255.0) as u32) & 0xFF) << 0, + | (light & 0xFF) << 0, } } } From e32153e98096a6ee834c182d9606da054850bc5b Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Tue, 19 Nov 2019 18:13:33 +0300 Subject: [PATCH 32/51] Improve frustum culling by using AABBs, add related debug information --- Cargo.lock | 34 ++++++++++++++++++++++-- voxygen/Cargo.toml | 2 +- voxygen/src/hud/mod.rs | 31 +++++++++++++++++++++- voxygen/src/scene/camera.rs | 5 +--- voxygen/src/scene/figure/mod.rs | 24 ++++++++++++++--- voxygen/src/scene/mod.rs | 12 ++++++++- voxygen/src/scene/terrain.rs | 46 +++++++++++++++++---------------- voxygen/src/session.rs | 4 +++ 8 files changed, 123 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 47f8ff68bd..e89e538426 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -864,6 +864,15 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dirs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "dirs-sys" version = "0.3.4" @@ -1055,7 +1064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "frustum_query" version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/yusdacra/frustum_query#866b36607a3a80356f0fc7a1cb29c2c59a70fdab" [[package]] name = "fsevent" @@ -2974,6 +2983,16 @@ name = "shrev" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "simplelog" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "siphasher" version = "0.2.3" @@ -3226,6 +3245,15 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "term" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termcolor" version = "1.0.5" @@ -3929,6 +3957,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum derivative 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "942ca430eef7a3806595a6737bc388bf51adb888d3fc0dd1b50f1c170167ee3a" "checksum directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c" "checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" +"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" "checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" "checksum discord-rpc-sdk 0.1.1 (git+https://github.com/Songtronix/rust-discord-rpc.git)" = "" "checksum discord-rpc-sys 0.1.0 (git+https://github.com/Songtronix/rust-discord-rpc.git)" = "" @@ -3952,7 +3981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum frustum_query 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e1771c26abed26b2527d888742fffd27dab86d205bf4846748abf29c06ef5a05" +"checksum frustum_query 0.1.2 (git+https://github.com/yusdacra/frustum_query)" = "" "checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" "checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" @@ -4192,6 +4221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" +"checksum term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index e432239808..acc9183562 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -55,7 +55,7 @@ directories = "2.0.2" num = "0.2.0" backtrace = "0.3.40" rand = "0.7.2" -frustum_query = "0.1.2" +frustum_query = { git = "https://github.com/yusdacra/frustum_query" } # context for pinning to commit: https://gitlab.com/veloren/veloren/issues/280 rodio = { git = "https://github.com/RustAudio/rodio", rev = "e5474a2"} cpal = "0.10" diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index b718dc912d..48d60c6bd5 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -119,6 +119,8 @@ widget_ids! { loaded_distance, time, entity_count, + num_chunks, + num_figures, // Game Version version, @@ -172,6 +174,10 @@ pub struct DebugInfo { pub ping_ms: f64, pub coordinates: Option, pub velocity: Option, + pub num_chunks: u32, + pub num_visible_chunks: u32, + pub num_figures: u32, + pub num_figures_visible: u32, } pub enum Event { @@ -979,6 +985,7 @@ impl Hud { .font_id(self.fonts.cyri) .font_size(14) .set(self.ids.time, ui_widgets); + // Number of entities let entity_count = client.state().ecs().entities().join().count(); Text::new(&format!("Entity count: {}", entity_count)) @@ -987,11 +994,33 @@ impl Hud { .font_id(self.fonts.cyri) .font_size(14) .set(self.ids.entity_count, ui_widgets); + + // Number of chunks + Text::new(&format!( + "Chunks: {} ({} visible)", + debug_info.num_chunks, debug_info.num_visible_chunks, + )) + .color(TEXT_COLOR) + .down_from(self.ids.entity_count, 5.0) + .font_id(self.fonts.cyri) + .font_size(14) + .set(self.ids.num_chunks, ui_widgets); + + // Number of figures + Text::new(&format!( + "Figures: {} ({} visible)", + debug_info.num_figures, debug_info.num_figures_visible, + )) + .color(TEXT_COLOR) + .down_from(self.ids.num_chunks, 5.0) + .font_id(self.fonts.cyri) + .font_size(14) + .set(self.ids.num_figures, ui_widgets); // Help Window Text::new("Press 'F1' to show Keybindings") .color(TEXT_COLOR) - .down_from(self.ids.entity_count, 5.0) + .down_from(self.ids.num_figures, 5.0) .font_id(self.fonts.cyri) .font_size(14) .set(self.ids.help_info, ui_widgets); diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index 4176c53769..f7a990b279 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -103,10 +103,7 @@ impl Camera { pub fn frustum(&self, client: &Client) -> Frustum { let (view_mat, proj_mat, _) = self.compute_dependents(client); - Frustum::from_modelview_and_projection( - &view_mat.into_col_array(), - &proj_mat.into_col_array(), - ) + Frustum::from_modelview_projection((proj_mat * view_mat).into_col_arrays()) } /// Rotate the camera about its focus by the given delta, limiting the input accordingly. diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index a5f88385d7..3623914008 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -43,6 +43,8 @@ pub struct FigureMgr { fish_small_states: HashMap>, biped_large_states: HashMap>, object_states: HashMap>, + figure_count: usize, + visible_figure_count: usize, } impl FigureMgr { @@ -59,6 +61,8 @@ impl FigureMgr { fish_small_states: HashMap::new(), biped_large_states: HashMap::new(), object_states: HashMap::new(), + figure_count: 0, + visible_figure_count: 0, } } @@ -78,6 +82,8 @@ impl FigureMgr { .get(client.entity()) .map_or(Vec3::zero(), |pos| pos.0); + self.figure_count = 0; + for (entity, pos, ori, scale, body, character, last_character, stats) in ( &ecs.entities(), &ecs.read_storage::(), @@ -90,6 +96,7 @@ impl FigureMgr { ) .join() { + self.figure_count += 1; // Don't process figures outside the vd let vd_frac = Vec2::from(pos.0 - player_pos) .map2(TerrainChunk::RECT_SIZE, |d: f32, sz| { @@ -823,6 +830,8 @@ impl FigureMgr { .read_storage::(); let character_state = character_state_storage.get(client.entity()); + self.visible_figure_count = 0; + for (entity, _, _, body, stats, _) in ( &ecs.entities(), &ecs.read_storage::(), @@ -835,15 +844,14 @@ impl FigureMgr { // Don't render figures outside of frustum (camera viewport, max draw distance is farplane) .filter(|(_, pos, _, _, _, scale)| { frustum.sphere_intersecting( - &pos.0.x, - &pos.0.y, - &pos.0.z, - &(scale.unwrap_or(&Scale(1.0)).0 * 2.0), + pos.0.into_array(), + scale.unwrap_or(&Scale(1.0)).0 * 2.0, ) }) // Don't render dead entities .filter(|(_, _, _, _, stats, _)| stats.map_or(true, |s| !s.is_dead)) { + self.visible_figure_count += 1; if let Some((locals, bone_consts)) = match body { Body::Humanoid(_) => self .character_states @@ -912,6 +920,14 @@ impl FigureMgr { } } } + + pub fn figure_count(&self) -> usize { + self.figure_count + } + + pub fn figure_count_visible(&self) -> usize { + self.visible_figure_count + } } pub struct FigureState { diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index d43450806d..28c9f97abc 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -94,7 +94,7 @@ impl Scene { } } - /// Get a reference to the scene's globals + /// Get a reference to the scene's globals. pub fn globals(&self) -> &Consts { &self.globals } @@ -104,6 +104,16 @@ impl Scene { &self.camera } + /// Get a reference to the scene's terrain. + pub fn terrain(&self) -> &Terrain { + &self.terrain + } + + /// Get a reference to the scene's figure manager. + pub fn figure_mgr(&self) -> &FigureMgr { + &self.figure_mgr + } + /// Get a mutable reference to the scene's camera. pub fn camera_mut(&mut self) -> &mut Camera { &mut self.camera diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 93202101e2..6b39543a34 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -1035,10 +1035,7 @@ impl Terrain { } // Construct view frustum - let frustum = Frustum::from_modelview_and_projection( - &view_mat.into_col_array(), - &proj_mat.into_col_array(), - ); + let frustum = Frustum::from_modelview_projection((proj_mat * view_mat).into_col_arrays()); // Update chunk visibility let chunk_sz = V::RECT_SIZE.x as f32; @@ -1050,28 +1047,33 @@ impl Terrain { let in_range = Vec2::::from(focus_pos).distance_squared(nearest_in_chunk) < loaded_distance.powf(2.0); - // Ensure the chunk is within the view frustrum - let chunk_mid = Vec3::new( - chunk_pos.x + chunk_sz / 2.0, - chunk_pos.y + chunk_sz / 2.0, - (chunk.z_bounds.0 + chunk.z_bounds.1) * 0.5, - ); - let chunk_radius = ((chunk.z_bounds.1 - chunk.z_bounds.0) / 2.0) - .max(chunk_sz / 2.0) - .powf(2.0) - .mul(2.0) - .sqrt(); - let in_frustum = frustum.sphere_intersecting( - &chunk_mid.x, - &chunk_mid.y, - &chunk_mid.z, - &chunk_radius, - ); + if !in_range { + chunk.visible = in_range; + continue; + } - chunk.visible = in_range && in_frustum; + // Ensure the chunk is within the view frustum + let chunk_min = [chunk_pos.x, chunk_pos.y, chunk.z_bounds.0]; + let chunk_max = [ + chunk_pos.x + chunk_sz, + chunk_pos.y + chunk_sz, + chunk.z_bounds.1, + ]; + + let in_frustum = frustum.aabb_intersecting(chunk_min, chunk_max); + + chunk.visible = in_frustum; } } + pub fn chunk_count(&self) -> usize { + self.chunks.len() + } + + pub fn visible_chunk_count(&self) -> usize { + self.chunks.iter().filter(|(_, c)| c.visible).count() + } + pub fn render( &self, renderer: &mut Renderer, diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 3deff8abd4..e3eb0bac70 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -385,6 +385,10 @@ impl PlayState for SessionState { .read_storage::() .get(self.client.borrow().entity()) .cloned(), + num_chunks: self.scene.terrain().chunk_count() as u32, + num_visible_chunks: self.scene.terrain().visible_chunk_count() as u32, + num_figures: self.scene.figure_mgr().figure_count() as u32, + num_figures_visible: self.scene.figure_mgr().figure_count_visible() as u32, }, &self.scene.camera(), clock.get_last_delta(), From c19c222a90b2d6650a7b594362615318d5481146 Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Tue, 19 Nov 2019 22:43:30 +0300 Subject: [PATCH 33/51] Use temporal coherence for chunk frustum culling --- Cargo.lock | 12 ++++++------ voxygen/Cargo.toml | 2 +- voxygen/src/scene/camera.rs | 2 +- voxygen/src/scene/figure/mod.rs | 2 +- voxygen/src/scene/terrain.rs | 7 +++++-- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e89e538426..06b2135261 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1062,9 +1062,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "frustum_query" -version = "0.1.2" -source = "git+https://github.com/yusdacra/frustum_query#866b36607a3a80356f0fc7a1cb29c2c59a70fdab" +name = "frustum_culling" +version = "0.1.0" +source = "git+https://gitlab.com/yusdacra/frustum_culling#735aef658c7e5eb0c4d543cacbea2f3e06216438" [[package]] name = "fsevent" @@ -3549,8 +3549,8 @@ dependencies = [ "dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "euc 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fern 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", - "frustum_query 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fern 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", + "frustum_culling 0.1.0 (git+https://gitlab.com/yusdacra/frustum_culling)", "gfx 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_device_gl 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_window_glutin 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3981,7 +3981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum frustum_query 0.1.2 (git+https://github.com/yusdacra/frustum_query)" = "" +"checksum frustum_culling 0.1.0 (git+https://gitlab.com/yusdacra/frustum_culling)" = "" "checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" "checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index acc9183562..e493a44a92 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -55,7 +55,7 @@ directories = "2.0.2" num = "0.2.0" backtrace = "0.3.40" rand = "0.7.2" -frustum_query = { git = "https://github.com/yusdacra/frustum_query" } +frustum_culling = { git = "https://gitlab.com/yusdacra/frustum_culling" } # context for pinning to commit: https://gitlab.com/veloren/veloren/issues/280 rodio = { git = "https://github.com/RustAudio/rodio", rev = "e5474a2"} cpal = "0.10" diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index f7a990b279..b1595b0eaa 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -1,6 +1,6 @@ use client::Client; use common::vol::{ReadVol, Vox}; -use frustum_query::frustum::Frustum; +use frustum_culling::Frustum; use std::f32::consts::PI; use vek::*; diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 3623914008..7d94eb92cd 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -843,7 +843,7 @@ impl FigureMgr { .join() // Don't render figures outside of frustum (camera viewport, max draw distance is farplane) .filter(|(_, pos, _, _, _, scale)| { - frustum.sphere_intersecting( + frustum.test_sphere( pos.0.into_array(), scale.unwrap_or(&Scale(1.0)).0 * 2.0, ) diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 6b39543a34..4ef832be70 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -16,7 +16,7 @@ use common::{ }; use crossbeam::channel; use dot_vox::DotVoxData; -use frustum_query::frustum::Frustum; +use frustum_query::Frustum; use hashbrown::{hash_map::Entry, HashMap}; use std::{f32, fmt::Debug, i32, marker::PhantomData, ops::Mul, time::Duration}; use vek::*; @@ -31,6 +31,7 @@ struct TerrainChunkData { visible: bool, z_bounds: (f32, f32), + frustum_last_plane_index: u8, } struct ChunkMeshState { @@ -1021,6 +1022,7 @@ impl Terrain { .expect("Failed to upload chunk locals to the GPU!"), visible: false, z_bounds: response.z_bounds, + frustum_last_plane_index: 0, }, ); @@ -1060,8 +1062,9 @@ impl Terrain { chunk.z_bounds.1, ]; - let in_frustum = frustum.aabb_intersecting(chunk_min, chunk_max); + let (in_frustum, last_plane_index) = frustum.test_aabb_coherence(chunk_min, chunk_max, chunk.frustum_last_plane_index); + chunk.frustum_last_plane_index = last_plane_index; chunk.visible = in_frustum; } } From 31d18b3381941e4d92ce1f5fb99517c33f3da308 Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Wed, 20 Nov 2019 02:29:34 +0300 Subject: [PATCH 34/51] Use temporal coherence for figure frustum culling, don't process figures if they are not in view frustum --- Cargo.lock | 2 +- voxygen/src/menu/char_selection/scene.rs | 2 + voxygen/src/scene/figure/mod.rs | 173 ++++++++++++++++++----- voxygen/src/scene/mod.rs | 2 +- 4 files changed, 143 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 06b2135261..73f02110b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1064,7 +1064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "frustum_culling" version = "0.1.0" -source = "git+https://gitlab.com/yusdacra/frustum_culling#735aef658c7e5eb0c4d543cacbea2f3e06216438" +source = "git+https://gitlab.com/yusdacra/frustum_culling#7145dbee5eadf4df0cbe5aeda856a0967f47ace4" [[package]] name = "fsevent" diff --git a/voxygen/src/menu/char_selection/scene.rs b/voxygen/src/menu/char_selection/scene.rs index 906e60c0a4..e5712f956e 100644 --- a/voxygen/src/menu/char_selection/scene.rs +++ b/voxygen/src/menu/char_selection/scene.rs @@ -169,6 +169,8 @@ impl Scene { 1.0 / 60.0, // TODO: Use actual deltatime here? 1.0, 1.0, + 0, + true, ); } diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 7d94eb92cd..cdf1be2e24 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -43,8 +43,6 @@ pub struct FigureMgr { fish_small_states: HashMap>, biped_large_states: HashMap>, object_states: HashMap>, - figure_count: usize, - visible_figure_count: usize, } impl FigureMgr { @@ -61,8 +59,6 @@ impl FigureMgr { fish_small_states: HashMap::new(), biped_large_states: HashMap::new(), object_states: HashMap::new(), - figure_count: 0, - visible_figure_count: 0, } } @@ -70,7 +66,7 @@ impl FigureMgr { self.model_cache.clean(tick); } - pub fn maintain(&mut self, renderer: &mut Renderer, client: &Client) { + pub fn maintain(&mut self, renderer: &mut Renderer, client: &Client, camera: &Camera) { let time = client.state().get_time(); let tick = client.get_tick(); let ecs = client.state().ecs(); @@ -82,8 +78,6 @@ impl FigureMgr { .get(client.entity()) .map_or(Vec3::zero(), |pos| pos.0); - self.figure_count = 0; - for (entity, pos, ori, scale, body, character, last_character, stats) in ( &ecs.entities(), &ecs.read_storage::(), @@ -96,7 +90,79 @@ impl FigureMgr { ) .join() { - self.figure_count += 1; + // Don't process figures outside the frustum spectrum + let frustum = camera.frustum(client); + + let (in_frustum, lpindex) = frustum.test_sphere_coherence( + pos.0.into_array(), + scale.unwrap_or(&Scale(1.0)).0 * 2.0, + match body { + Body::Humanoid(_) => { + self.character_states.get(&entity).map(|state| state.lpindex) + } + Body::QuadrupedSmall(_) => { + self.quadruped_small_states.get(&entity).map(|state| state.lpindex) + } + Body::QuadrupedMedium(_) => { + self.quadruped_medium_states.get(&entity).map(|state| state.lpindex) + } + Body::BirdMedium(_) => { + self.bird_medium_states.get(&entity).map(|state| state.lpindex) + } + Body::FishMedium(_) => { + self.fish_medium_states.get(&entity).map(|state| state.lpindex) + } + Body::Dragon(_) => { + self.dragon_states.get(&entity).map(|state| state.lpindex) + } + Body::BirdSmall(_) => { + self.bird_small_states.get(&entity).map(|state| state.lpindex) + } + Body::FishSmall(_) => { + self.fish_small_states.get(&entity).map(|state| state.lpindex) + } + Body::BipedLarge(_) => { + self.biped_large_states.get(&entity).map(|state| state.lpindex) + } + Body::Object(_) => { + self.object_states.get(&entity).map(|state| state.lpindex) + } + }.unwrap_or(0), + ); + + match body { + Body::Humanoid(_) => { + self.character_states.get_mut(&entity).map(|state| state.visible = in_frustum); + } + Body::QuadrupedSmall(_) => { + self.quadruped_small_states.get_mut(&entity).map(|state| state.visible = in_frustum); + } + Body::QuadrupedMedium(_) => { + self.quadruped_medium_states.get_mut(&entity).map(|state| state.visible = in_frustum); + } + Body::BirdMedium(_) => { + self.bird_medium_states.get_mut(&entity).map(|state| state.visible = in_frustum); + } + Body::FishMedium(_) => { + self.fish_medium_states.get_mut(&entity).map(|state| state.visible = in_frustum); + } + Body::Dragon(_) => { + self.dragon_states.get_mut(&entity).map(|state| state.visible = in_frustum); + } + Body::BirdSmall(_) => { + self.bird_small_states.get_mut(&entity).map(|state| state.visible = in_frustum); + } + Body::FishSmall(_) => { + self.fish_small_states.get_mut(&entity).map(|state| state.visible = in_frustum); + } + Body::BipedLarge(_) => { + self.biped_large_states.get_mut(&entity).map(|state| state.visible = in_frustum); + } + Body::Object(_) => { + self.object_states.get_mut(&entity).map(|state| state.visible = in_frustum); + } + } + // Don't process figures outside the vd let vd_frac = Vec2::from(pos.0 - player_pos) .map2(TerrainChunk::RECT_SIZE, |d: f32, sz| { @@ -139,7 +205,7 @@ impl FigureMgr { } } continue; - } else if vd_frac > 1.0 { + } else if vd_frac > 1.0 || !in_frustum { continue; } @@ -320,6 +386,8 @@ impl FigureMgr { dt, movement_animation_rate, action_animation_rate, + lpindex, + true, ); } Body::QuadrupedSmall(_) => { @@ -377,6 +445,8 @@ impl FigureMgr { dt, movement_animation_rate, action_animation_rate, + lpindex, + true, ); } Body::QuadrupedMedium(_) => { @@ -434,6 +504,8 @@ impl FigureMgr { dt, movement_animation_rate, action_animation_rate, + lpindex, + true, ); } Body::BirdMedium(_) => { @@ -489,6 +561,8 @@ impl FigureMgr { dt, movement_animation_rate, action_animation_rate, + lpindex, + true, ); } Body::FishMedium(_) => { @@ -544,6 +618,8 @@ impl FigureMgr { dt, movement_animation_rate, action_animation_rate, + lpindex, + true, ); } Body::Dragon(_) => { @@ -599,6 +675,8 @@ impl FigureMgr { dt, movement_animation_rate, action_animation_rate, + lpindex, + true, ); } Body::BirdSmall(_) => { @@ -654,6 +732,8 @@ impl FigureMgr { dt, movement_animation_rate, action_animation_rate, + lpindex, + true, ); } Body::FishSmall(_) => { @@ -709,6 +789,8 @@ impl FigureMgr { dt, movement_animation_rate, action_animation_rate, + lpindex, + true, ); } Body::BipedLarge(_) => { @@ -764,6 +846,8 @@ impl FigureMgr { dt, movement_animation_rate, action_animation_rate, + lpindex, + true, ); } Body::Object(_) => { @@ -783,6 +867,8 @@ impl FigureMgr { dt, movement_animation_rate, action_animation_rate, + lpindex, + true, ); } } @@ -823,15 +909,11 @@ impl FigureMgr { let tick = client.get_tick(); let ecs = client.state().ecs(); - let frustum = camera.frustum(client); - let character_state_storage = client .state() .read_storage::(); let character_state = character_state_storage.get(client.entity()); - self.visible_figure_count = 0; - for (entity, _, _, body, stats, _) in ( &ecs.entities(), &ecs.read_storage::(), @@ -841,59 +923,55 @@ impl FigureMgr { ecs.read_storage::().maybe(), ) .join() - // Don't render figures outside of frustum (camera viewport, max draw distance is farplane) - .filter(|(_, pos, _, _, _, scale)| { - frustum.test_sphere( - pos.0.into_array(), - scale.unwrap_or(&Scale(1.0)).0 * 2.0, - ) - }) // Don't render dead entities .filter(|(_, _, _, _, stats, _)| stats.map_or(true, |s| !s.is_dead)) { - self.visible_figure_count += 1; - if let Some((locals, bone_consts)) = match body { + if let Some((locals, bone_consts, visible)) = match body { Body::Humanoid(_) => self .character_states .get(&entity) - .map(|state| (state.locals(), state.bone_consts())), + .map(|state| (state.locals(), state.bone_consts(), state.visible)), Body::QuadrupedSmall(_) => self .quadruped_small_states .get(&entity) - .map(|state| (state.locals(), state.bone_consts())), + .map(|state| (state.locals(), state.bone_consts(), state.visible)), Body::QuadrupedMedium(_) => self .quadruped_medium_states .get(&entity) - .map(|state| (state.locals(), state.bone_consts())), + .map(|state| (state.locals(), state.bone_consts(), state.visible)), Body::BirdMedium(_) => self .bird_medium_states .get(&entity) - .map(|state| (state.locals(), state.bone_consts())), + .map(|state| (state.locals(), state.bone_consts(), state.visible)), Body::FishMedium(_) => self .fish_medium_states .get(&entity) - .map(|state| (state.locals(), state.bone_consts())), + .map(|state| (state.locals(), state.bone_consts(), state.visible)), Body::Dragon(_) => self .dragon_states .get(&entity) - .map(|state| (state.locals(), state.bone_consts())), + .map(|state| (state.locals(), state.bone_consts(), state.visible)), Body::BirdSmall(_) => self .bird_small_states .get(&entity) - .map(|state| (state.locals(), state.bone_consts())), + .map(|state| (state.locals(), state.bone_consts(), state.visible)), Body::FishSmall(_) => self .fish_small_states .get(&entity) - .map(|state| (state.locals(), state.bone_consts())), + .map(|state| (state.locals(), state.bone_consts(), state.visible)), Body::BipedLarge(_) => self .biped_large_states .get(&entity) - .map(|state| (state.locals(), state.bone_consts())), + .map(|state| (state.locals(), state.bone_consts(), state.visible)), Body::Object(_) => self .object_states .get(&entity) - .map(|state| (state.locals(), state.bone_consts())), + .map(|state| (state.locals(), state.bone_consts(), state.visible)), } { + if !visible { + continue; + } + let is_player = entity == client.entity(); let player_camera_mode = if is_player { @@ -922,11 +1000,30 @@ impl FigureMgr { } pub fn figure_count(&self) -> usize { - self.figure_count + self.character_states.len() + + self.quadruped_small_states.len() + + self.character_states.len() + + self.quadruped_medium_states.len() + + self.bird_medium_states.len() + + self.fish_medium_states.len() + + self.dragon_states.len() + + self.bird_small_states.len() + + self.fish_small_states.len() + + self.biped_large_states.len() + + self.object_states.len() } pub fn figure_count_visible(&self) -> usize { - self.visible_figure_count + self.character_states.iter().filter(|(_, c)| c.visible).count() + + self.quadruped_small_states.iter().filter(|(_, c)| c.visible).count() + + self.quadruped_medium_states.iter().filter(|(_, c)| c.visible).count() + + self.bird_medium_states.iter().filter(|(_, c)| c.visible).count() + + self.fish_medium_states.iter().filter(|(_, c)| c.visible).count() + + self.dragon_states.iter().filter(|(_, c)| c.visible).count() + + self.bird_small_states.iter().filter(|(_, c)| c.visible).count() + + self.fish_small_states.iter().filter(|(_, c)| c.visible).count() + + self.biped_large_states.iter().filter(|(_, c)| c.visible).count() + + self.object_states.iter().filter(|(_, c)| c.visible).count() } } @@ -939,6 +1036,8 @@ pub struct FigureState { pos: Vec3, ori: Vec3, last_ori: Vec3, + lpindex: u8, + visible: bool, } impl FigureState { @@ -954,6 +1053,8 @@ impl FigureState { pos: Vec3::zero(), ori: Vec3::zero(), last_ori: Vec3::zero(), + lpindex: 0, + visible: false, } } @@ -968,7 +1069,11 @@ impl FigureState { dt: f32, movement_rate: f32, action_rate: f32, + lpindex: u8, + visible: bool, ) { + self.visible = visible; + self.lpindex = lpindex; self.last_ori = Lerp::lerp(self.last_ori, ori, 15.0 * dt); // Update interpolation values diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 28c9f97abc..66aaacf40c 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -301,7 +301,7 @@ impl Scene { ); // Maintain the figures. - self.figure_mgr.maintain(renderer, client); + self.figure_mgr.maintain(renderer, client, &self.camera); // Remove unused figures. self.figure_mgr.clean(client.get_tick()); From 0b67dad4a5f8ca651d42be616e1dcd59548b6c6d Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Sun, 24 Nov 2019 23:53:47 +0300 Subject: [PATCH 35/51] Fix figure visible value not updating --- Cargo.lock | 32 +-------- voxygen/src/scene/figure/mod.rs | 122 +++++++++++++++++++++----------- 2 files changed, 80 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 73f02110b1..691c3eb30d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -864,15 +864,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "dirs" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "dirs-sys" version = "0.3.4" @@ -2983,16 +2974,6 @@ name = "shrev" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "simplelog" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "siphasher" version = "0.2.3" @@ -3245,15 +3226,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "term" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "termcolor" version = "1.0.5" @@ -3549,7 +3521,7 @@ dependencies = [ "dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "euc 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fern 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", + "fern 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "frustum_culling 0.1.0 (git+https://gitlab.com/yusdacra/frustum_culling)", "gfx 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_device_gl 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3957,7 +3929,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum derivative 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "942ca430eef7a3806595a6737bc388bf51adb888d3fc0dd1b50f1c170167ee3a" "checksum directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c" "checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" -"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" "checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" "checksum discord-rpc-sdk 0.1.1 (git+https://github.com/Songtronix/rust-discord-rpc.git)" = "" "checksum discord-rpc-sys 0.1.0 (git+https://github.com/Songtronix/rust-discord-rpc.git)" = "" @@ -4221,7 +4192,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" -"checksum term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index cdf1be2e24..69cd4c3a51 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -90,6 +90,84 @@ impl FigureMgr { ) .join() { + // Don't process figures outside the vd + let vd_frac = Vec2::from(pos.0 - player_pos) + .map2(TerrainChunk::RECT_SIZE, |d: f32, sz| { + d.abs() as f32 / sz as f32 + }) + .magnitude() + / view_distance as f32; + // Keep from re-adding/removing entities on the border of the vd + if vd_frac > 1.2 { + match body { + Body::Humanoid(_) => { + self.character_states.remove(&entity); + } + Body::QuadrupedSmall(_) => { + self.quadruped_small_states.remove(&entity); + } + Body::QuadrupedMedium(_) => { + self.quadruped_medium_states.remove(&entity); + } + Body::BirdMedium(_) => { + self.bird_medium_states.remove(&entity); + } + Body::FishMedium(_) => { + self.fish_medium_states.remove(&entity); + } + Body::Dragon(_) => { + self.dragon_states.remove(&entity); + } + Body::BirdSmall(_) => { + self.bird_small_states.remove(&entity); + } + Body::FishSmall(_) => { + self.fish_small_states.remove(&entity); + } + Body::BipedLarge(_) => { + self.biped_large_states.remove(&entity); + } + Body::Object(_) => { + self.object_states.remove(&entity); + } + } + continue; + } else if vd_frac > 1.0 { + match body { + Body::Humanoid(_) => { + self.character_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::QuadrupedSmall(_) => { + self.quadruped_small_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::QuadrupedMedium(_) => { + self.quadruped_medium_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::BirdMedium(_) => { + self.bird_medium_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::FishMedium(_) => { + self.fish_medium_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::Dragon(_) => { + self.dragon_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::BirdSmall(_) => { + self.bird_small_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::FishSmall(_) => { + self.fish_small_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::BipedLarge(_) => { + self.biped_large_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::Object(_) => { + self.object_states.get_mut(&entity).map(|state| state.visible = false); + } + } + continue; + } + // Don't process figures outside the frustum spectrum let frustum = camera.frustum(client); @@ -163,49 +241,7 @@ impl FigureMgr { } } - // Don't process figures outside the vd - let vd_frac = Vec2::from(pos.0 - player_pos) - .map2(TerrainChunk::RECT_SIZE, |d: f32, sz| { - d.abs() as f32 / sz as f32 - }) - .magnitude() - / view_distance as f32; - // Keep from re-adding/removing entities on the border of the vd - if vd_frac > 1.2 { - match body { - Body::Humanoid(_) => { - self.character_states.remove(&entity); - } - Body::QuadrupedSmall(_) => { - self.quadruped_small_states.remove(&entity); - } - Body::QuadrupedMedium(_) => { - self.quadruped_medium_states.remove(&entity); - } - Body::BirdMedium(_) => { - self.bird_medium_states.remove(&entity); - } - Body::FishMedium(_) => { - self.fish_medium_states.remove(&entity); - } - Body::Dragon(_) => { - self.dragon_states.remove(&entity); - } - Body::BirdSmall(_) => { - self.bird_small_states.remove(&entity); - } - Body::FishSmall(_) => { - self.fish_small_states.remove(&entity); - } - Body::BipedLarge(_) => { - self.biped_large_states.remove(&entity); - } - Body::Object(_) => { - self.object_states.remove(&entity); - } - } - continue; - } else if vd_frac > 1.0 || !in_frustum { + if !in_frustum { continue; } From 24013f1a3225a1dc0059b4c19412a750058e39e8 Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Tue, 7 Jan 2020 19:40:06 +0300 Subject: [PATCH 36/51] Use `treeculler` crate --- Cargo.lock | 17 ++++---- voxygen/Cargo.toml | 2 +- voxygen/src/scene/camera.rs | 4 +- voxygen/src/scene/figure/mod.rs | 71 ++++++++++++++++----------------- voxygen/src/scene/terrain.rs | 6 +-- 5 files changed, 51 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 691c3eb30d..038127bc5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1052,11 +1052,6 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "frustum_culling" -version = "0.1.0" -source = "git+https://gitlab.com/yusdacra/frustum_culling#7145dbee5eadf4df0cbe5aeda856a0967f47ace4" - [[package]] name = "fsevent" version = "0.4.0" @@ -3308,6 +3303,14 @@ dependencies = [ "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "treeculler" +version = "0.1.0" +source = "git+https://gitlab.com/yusdacra/treeculler.git#6c0fdf1c1cbf00be22e37410985d6a3973cd9bed" +dependencies = [ + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tuple_utils" version = "0.3.0" @@ -3522,7 +3525,6 @@ dependencies = [ "euc 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "fern 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", - "frustum_culling 0.1.0 (git+https://gitlab.com/yusdacra/frustum_culling)", "gfx 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_device_gl 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_window_glutin 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3542,6 +3544,7 @@ dependencies = [ "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "treeculler 0.1.0 (git+https://gitlab.com/yusdacra/treeculler.git)", "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "veloren-client 0.4.0", "veloren-common 0.4.0", @@ -3952,7 +3955,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum frustum_culling 0.1.0 (git+https://gitlab.com/yusdacra/frustum_culling)" = "" "checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" "checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" @@ -4201,6 +4203,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tiny_http 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1661fa0a44c95d01604bd05c66732a446c657efb62b5164a7a083a3b552b4951" "checksum tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4574b75faccaacddb9b284faecdf0b544b80b6b294f3d062d325c5726a209c20" "checksum toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01d1404644c8b12b16bfcffa4322403a91a451584daaaa7c28d3152e6cbc98cf" +"checksum treeculler 0.1.0 (git+https://gitlab.com/yusdacra/treeculler.git)" = "" "checksum tuple_utils 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44834418e2c5b16f47bedf35c28e148db099187dd5feee6367fb2525863af4f1" "checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" "checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index e493a44a92..322575db69 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -55,7 +55,7 @@ directories = "2.0.2" num = "0.2.0" backtrace = "0.3.40" rand = "0.7.2" -frustum_culling = { git = "https://gitlab.com/yusdacra/frustum_culling" } +treeculler = { git = "https://gitlab.com/yusdacra/treeculler.git" } # context for pinning to commit: https://gitlab.com/veloren/veloren/issues/280 rodio = { git = "https://github.com/RustAudio/rodio", rev = "e5474a2"} cpal = "0.10" diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index b1595b0eaa..77886cb981 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -1,6 +1,6 @@ use client::Client; use common::vol::{ReadVol, Vox}; -use frustum_culling::Frustum; +use treeculler::Frustum; use std::f32::consts::PI; use vek::*; @@ -100,7 +100,7 @@ impl Camera { (view_mat, proj_mat, cam_pos) } - pub fn frustum(&self, client: &Client) -> Frustum { + pub fn frustum(&self, client: &Client) -> Frustum { let (view_mat, proj_mat, _) = self.compute_dependents(client); Frustum::from_modelview_projection((proj_mat * view_mat).into_col_arrays()) diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 69cd4c3a51..2c7d9e5d9f 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -27,6 +27,7 @@ use common::{ use hashbrown::HashMap; use log::trace; use specs::{Entity as EcsEntity, Join, WorldExt}; +use treeculler::{BoundingSphere, BVol}; use vek::*; const DAMAGE_FADE_COEFFICIENT: f64 = 5.0; @@ -171,9 +172,8 @@ impl FigureMgr { // Don't process figures outside the frustum spectrum let frustum = camera.frustum(client); - let (in_frustum, lpindex) = frustum.test_sphere_coherence( - pos.0.into_array(), - scale.unwrap_or(&Scale(1.0)).0 * 2.0, + let (in_frustum, lpindex) = BoundingSphere::new(pos.0.into_array(), scale.unwrap_or(&Scale(1.0)).0 * 2.0).coherent_test_against_frustum( + &frustum, match body { Body::Humanoid(_) => { self.character_states.get(&entity).map(|state| state.lpindex) @@ -208,40 +208,39 @@ impl FigureMgr { }.unwrap_or(0), ); - match body { - Body::Humanoid(_) => { - self.character_states.get_mut(&entity).map(|state| state.visible = in_frustum); - } - Body::QuadrupedSmall(_) => { - self.quadruped_small_states.get_mut(&entity).map(|state| state.visible = in_frustum); - } - Body::QuadrupedMedium(_) => { - self.quadruped_medium_states.get_mut(&entity).map(|state| state.visible = in_frustum); - } - Body::BirdMedium(_) => { - self.bird_medium_states.get_mut(&entity).map(|state| state.visible = in_frustum); - } - Body::FishMedium(_) => { - self.fish_medium_states.get_mut(&entity).map(|state| state.visible = in_frustum); - } - Body::Dragon(_) => { - self.dragon_states.get_mut(&entity).map(|state| state.visible = in_frustum); - } - Body::BirdSmall(_) => { - self.bird_small_states.get_mut(&entity).map(|state| state.visible = in_frustum); - } - Body::FishSmall(_) => { - self.fish_small_states.get_mut(&entity).map(|state| state.visible = in_frustum); - } - Body::BipedLarge(_) => { - self.biped_large_states.get_mut(&entity).map(|state| state.visible = in_frustum); - } - Body::Object(_) => { - self.object_states.get_mut(&entity).map(|state| state.visible = in_frustum); - } - } - if !in_frustum { + match body { + Body::Humanoid(_) => { + self.character_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::QuadrupedSmall(_) => { + self.quadruped_small_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::QuadrupedMedium(_) => { + self.quadruped_medium_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::BirdMedium(_) => { + self.bird_medium_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::FishMedium(_) => { + self.fish_medium_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::Dragon(_) => { + self.dragon_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::BirdSmall(_) => { + self.bird_small_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::FishSmall(_) => { + self.fish_small_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::BipedLarge(_) => { + self.biped_large_states.get_mut(&entity).map(|state| state.visible = false); + } + Body::Object(_) => { + self.object_states.get_mut(&entity).map(|state| state.visible = false); + } + } continue; } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 4ef832be70..3f84b40318 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -16,9 +16,9 @@ use common::{ }; use crossbeam::channel; use dot_vox::DotVoxData; -use frustum_query::Frustum; +use treeculler::{Frustum, AABB, BVol}; use hashbrown::{hash_map::Entry, HashMap}; -use std::{f32, fmt::Debug, i32, marker::PhantomData, ops::Mul, time::Duration}; +use std::{f32, fmt::Debug, i32, marker::PhantomData, time::Duration}; use vek::*; struct TerrainChunkData { @@ -1062,7 +1062,7 @@ impl Terrain { chunk.z_bounds.1, ]; - let (in_frustum, last_plane_index) = frustum.test_aabb_coherence(chunk_min, chunk_max, chunk.frustum_last_plane_index); + let (in_frustum, last_plane_index) = AABB::new(chunk_min, chunk_max).coherent_test_against_frustum(&frustum, chunk.frustum_last_plane_index); chunk.frustum_last_plane_index = last_plane_index; chunk.visible = in_frustum; From 71db9d63502c1e259b6ab5e814cc85dbd1684d6e Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Tue, 7 Jan 2020 20:37:55 +0300 Subject: [PATCH 37/51] Replace radio list with drop down selector for AA mode setting --- voxygen/src/hud/settings_window.rs | 54 +++++++++++++++++------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/voxygen/src/hud/settings_window.rs b/voxygen/src/hud/settings_window.rs index 97f635463f..6d08ac6969 100644 --- a/voxygen/src/hud/settings_window.rs +++ b/voxygen/src/hud/settings_window.rs @@ -4,7 +4,7 @@ use super::{ }; use crate::{ render::AaMode, - ui::{ImageSlider, RadioList, ScaleMode, ToggleButton}, + ui::{ImageSlider, ScaleMode, ToggleButton}, GlobalState, }; use conrod_core::{ @@ -84,8 +84,8 @@ widget_ids! { fov_slider, fov_text, fov_value, - aa_radio_buttons, aa_mode_text, + aa_mode_list, audio_volume_slider, audio_volume_text, sfx_volume_slider, @@ -1332,30 +1332,36 @@ impl<'a> Widget for SettingsWindow<'a> { .font_id(self.fonts.cyri) .color(TEXT_COLOR) .set(state.ids.aa_mode_text, ui); - let mode_label_list = [ - (&AaMode::None, "No AA"), - (&AaMode::Fxaa, "FXAA"), - (&AaMode::MsaaX4, "MSAA x4"), - (&AaMode::MsaaX8, "MSAA x8"), - (&AaMode::MsaaX16, "MSAA x16 (experimental)"), - (&AaMode::SsaaX4, "SSAA x4"), + + let mode_list = [ + AaMode::None, + AaMode::Fxaa, + AaMode::MsaaX4, + AaMode::MsaaX8, + AaMode::MsaaX16, + AaMode::SsaaX4, ]; - if let Some((_, mode)) = RadioList::new( - (0..mode_label_list.len()) - .find(|i| *mode_label_list[*i].0 == self.global_state.settings.graphics.aa_mode) - .unwrap_or(0), - self.imgs.check, - self.imgs.check_checked, - &mode_label_list, - ) - .hover_images(self.imgs.check_mo, self.imgs.check_checked_mo) - .press_images(self.imgs.check_press, self.imgs.check_press) - .down_from(state.ids.aa_mode_text, 8.0) - .text_color(TEXT_COLOR) - .font_size(12) - .set(state.ids.aa_radio_buttons, ui) + let mode_label_list = [ + "No AA", + "FXAA", + "MSAA x4", + "MSAA x8", + "MSAA x16 (experimental)", + "SSAA x4", + ]; + + // Get which AA mode is currently active + let selected = mode_list.iter().position(|x| *x == self.global_state.settings.graphics.aa_mode); + + if let Some(clicked) = DropDownList::new(&mode_label_list, selected) + .w_h(400.0, 22.0) + .color(MENU_BG) + .label_color(TEXT_COLOR) + .label_font_id(self.fonts.cyri) + .down_from(state.ids.aa_mode_text, 8.0) + .set(state.ids.aa_mode_list, ui) { - events.push(Event::ChangeAaMode(*mode)) + events.push(Event::ChangeAaMode(mode_list[clicked])); } } From 5b65b1659460c7020c5c383eb942896770bc4ffd Mon Sep 17 00:00:00 2001 From: S Handley Date: Wed, 8 Jan 2020 12:48:00 +0000 Subject: [PATCH 38/51] Prevent NPCs from spawnign underwater This should be set until there are underwater NPC types. --- world/src/lib.rs | 5 ++++- world/src/sim/mod.rs | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/world/src/lib.rs b/world/src/lib.rs index 75c6a2e69c..745515cd54 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -148,7 +148,10 @@ impl World { const SPAWN_RATE: f32 = 0.1; const BOSS_RATE: f32 = 0.03; let supplement = ChunkSupplement { - npcs: if rand::thread_rng().gen::() < SPAWN_RATE && sim_chunk.chaos < 0.5 { + npcs: if rand::thread_rng().gen::() < SPAWN_RATE + && sim_chunk.chaos < 0.5 + && !sim_chunk.is_underwater + { vec![NpcInfo { pos: gen_entity_pos(), boss: rand::thread_rng().gen::() < BOSS_RATE, diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index ce7a484676..8735ad135b 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -970,6 +970,7 @@ pub struct SimChunk { pub spawn_rate: f32, pub location: Option, pub river: RiverData, + pub is_underwater: bool, pub structures: Structures, } @@ -1146,6 +1147,7 @@ impl SimChunk { } else { 0.0 }, + is_underwater, is_cliffs: cliff > 0.5 && !is_underwater, near_cliffs: cliff > 0.2, tree_density, From 4a0a2d5229f7f0d802160065e10f95e89a47764c Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Wed, 8 Jan 2020 20:09:54 +0300 Subject: [PATCH 39/51] Cargo fmt --- voxygen/src/hud/mod.rs | 2 +- voxygen/src/hud/settings_window.rs | 4 +- voxygen/src/mesh/terrain.rs | 18 ++- voxygen/src/scene/camera.rs | 2 +- voxygen/src/scene/figure/mod.rs | 234 +++++++++++++++++++---------- voxygen/src/scene/terrain.rs | 9 +- 6 files changed, 183 insertions(+), 86 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 48d60c6bd5..7af4cad854 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -994,7 +994,7 @@ impl Hud { .font_id(self.fonts.cyri) .font_size(14) .set(self.ids.entity_count, ui_widgets); - + // Number of chunks Text::new(&format!( "Chunks: {} ({} visible)", diff --git a/voxygen/src/hud/settings_window.rs b/voxygen/src/hud/settings_window.rs index 6d08ac6969..b63678dc58 100644 --- a/voxygen/src/hud/settings_window.rs +++ b/voxygen/src/hud/settings_window.rs @@ -1351,7 +1351,9 @@ impl<'a> Widget for SettingsWindow<'a> { ]; // Get which AA mode is currently active - let selected = mode_list.iter().position(|x| *x == self.global_state.settings.graphics.aa_mode); + let selected = mode_list + .iter() + .position(|x| *x == self.global_state.settings.graphics.aa_mode); if let Some(clicked) = DropDownList::new(&mode_label_list, selected) .w_h(400.0, 22.0) diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index 5154c20617..75439e1f0a 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -238,11 +238,23 @@ impl + ReadVol + Debug> Meshable 1.0 { match body { Body::Humanoid(_) => { - self.character_states.get_mut(&entity).map(|state| state.visible = false); + self.character_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::QuadrupedSmall(_) => { - self.quadruped_small_states.get_mut(&entity).map(|state| state.visible = false); + self.quadruped_small_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::QuadrupedMedium(_) => { - self.quadruped_medium_states.get_mut(&entity).map(|state| state.visible = false); + self.quadruped_medium_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::BirdMedium(_) => { - self.bird_medium_states.get_mut(&entity).map(|state| state.visible = false); + self.bird_medium_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::FishMedium(_) => { - self.fish_medium_states.get_mut(&entity).map(|state| state.visible = false); + self.fish_medium_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::Dragon(_) => { - self.dragon_states.get_mut(&entity).map(|state| state.visible = false); + self.dragon_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::BirdSmall(_) => { - self.bird_small_states.get_mut(&entity).map(|state| state.visible = false); + self.bird_small_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::FishSmall(_) => { - self.fish_small_states.get_mut(&entity).map(|state| state.visible = false); + self.fish_small_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::BipedLarge(_) => { - self.biped_large_states.get_mut(&entity).map(|state| state.visible = false); + self.biped_large_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::Object(_) => { - self.object_states.get_mut(&entity).map(|state| state.visible = false); + self.object_states + .get_mut(&entity) + .map(|state| state.visible = false); } } continue; @@ -172,73 +192,104 @@ impl FigureMgr { // Don't process figures outside the frustum spectrum let frustum = camera.frustum(client); - let (in_frustum, lpindex) = BoundingSphere::new(pos.0.into_array(), scale.unwrap_or(&Scale(1.0)).0 * 2.0).coherent_test_against_frustum( - &frustum, - match body { - Body::Humanoid(_) => { - self.character_states.get(&entity).map(|state| state.lpindex) - } - Body::QuadrupedSmall(_) => { - self.quadruped_small_states.get(&entity).map(|state| state.lpindex) - } - Body::QuadrupedMedium(_) => { - self.quadruped_medium_states.get(&entity).map(|state| state.lpindex) - } - Body::BirdMedium(_) => { - self.bird_medium_states.get(&entity).map(|state| state.lpindex) - } - Body::FishMedium(_) => { - self.fish_medium_states.get(&entity).map(|state| state.lpindex) - } - Body::Dragon(_) => { - self.dragon_states.get(&entity).map(|state| state.lpindex) - } - Body::BirdSmall(_) => { - self.bird_small_states.get(&entity).map(|state| state.lpindex) - } - Body::FishSmall(_) => { - self.fish_small_states.get(&entity).map(|state| state.lpindex) - } - Body::BipedLarge(_) => { - self.biped_large_states.get(&entity).map(|state| state.lpindex) - } - Body::Object(_) => { - self.object_states.get(&entity).map(|state| state.lpindex) - } - }.unwrap_or(0), - ); + let (in_frustum, lpindex) = + BoundingSphere::new(pos.0.into_array(), scale.unwrap_or(&Scale(1.0)).0 * 2.0) + .coherent_test_against_frustum( + &frustum, + match body { + Body::Humanoid(_) => self + .character_states + .get(&entity) + .map(|state| state.lpindex), + Body::QuadrupedSmall(_) => self + .quadruped_small_states + .get(&entity) + .map(|state| state.lpindex), + Body::QuadrupedMedium(_) => self + .quadruped_medium_states + .get(&entity) + .map(|state| state.lpindex), + Body::BirdMedium(_) => self + .bird_medium_states + .get(&entity) + .map(|state| state.lpindex), + Body::FishMedium(_) => self + .fish_medium_states + .get(&entity) + .map(|state| state.lpindex), + Body::Dragon(_) => { + self.dragon_states.get(&entity).map(|state| state.lpindex) + } + Body::BirdSmall(_) => self + .bird_small_states + .get(&entity) + .map(|state| state.lpindex), + Body::FishSmall(_) => self + .fish_small_states + .get(&entity) + .map(|state| state.lpindex), + Body::BipedLarge(_) => self + .biped_large_states + .get(&entity) + .map(|state| state.lpindex), + Body::Object(_) => { + self.object_states.get(&entity).map(|state| state.lpindex) + } + } + .unwrap_or(0), + ); if !in_frustum { match body { Body::Humanoid(_) => { - self.character_states.get_mut(&entity).map(|state| state.visible = false); + self.character_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::QuadrupedSmall(_) => { - self.quadruped_small_states.get_mut(&entity).map(|state| state.visible = false); + self.quadruped_small_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::QuadrupedMedium(_) => { - self.quadruped_medium_states.get_mut(&entity).map(|state| state.visible = false); + self.quadruped_medium_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::BirdMedium(_) => { - self.bird_medium_states.get_mut(&entity).map(|state| state.visible = false); + self.bird_medium_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::FishMedium(_) => { - self.fish_medium_states.get_mut(&entity).map(|state| state.visible = false); + self.fish_medium_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::Dragon(_) => { - self.dragon_states.get_mut(&entity).map(|state| state.visible = false); + self.dragon_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::BirdSmall(_) => { - self.bird_small_states.get_mut(&entity).map(|state| state.visible = false); + self.bird_small_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::FishSmall(_) => { - self.fish_small_states.get_mut(&entity).map(|state| state.visible = false); + self.fish_small_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::BipedLarge(_) => { - self.biped_large_states.get_mut(&entity).map(|state| state.visible = false); + self.biped_large_states + .get_mut(&entity) + .map(|state| state.visible = false); } Body::Object(_) => { - self.object_states.get_mut(&entity).map(|state| state.visible = false); + self.object_states + .get_mut(&entity) + .map(|state| state.visible = false); } } continue; @@ -1036,29 +1087,60 @@ impl FigureMgr { pub fn figure_count(&self) -> usize { self.character_states.len() - + self.quadruped_small_states.len() - + self.character_states.len() - + self.quadruped_medium_states.len() - + self.bird_medium_states.len() - + self.fish_medium_states.len() - + self.dragon_states.len() - + self.bird_small_states.len() - + self.fish_small_states.len() - + self.biped_large_states.len() - + self.object_states.len() + + self.quadruped_small_states.len() + + self.character_states.len() + + self.quadruped_medium_states.len() + + self.bird_medium_states.len() + + self.fish_medium_states.len() + + self.dragon_states.len() + + self.bird_small_states.len() + + self.fish_small_states.len() + + self.biped_large_states.len() + + self.object_states.len() } pub fn figure_count_visible(&self) -> usize { - self.character_states.iter().filter(|(_, c)| c.visible).count() - + self.quadruped_small_states.iter().filter(|(_, c)| c.visible).count() - + self.quadruped_medium_states.iter().filter(|(_, c)| c.visible).count() - + self.bird_medium_states.iter().filter(|(_, c)| c.visible).count() - + self.fish_medium_states.iter().filter(|(_, c)| c.visible).count() - + self.dragon_states.iter().filter(|(_, c)| c.visible).count() - + self.bird_small_states.iter().filter(|(_, c)| c.visible).count() - + self.fish_small_states.iter().filter(|(_, c)| c.visible).count() - + self.biped_large_states.iter().filter(|(_, c)| c.visible).count() - + self.object_states.iter().filter(|(_, c)| c.visible).count() + self.character_states + .iter() + .filter(|(_, c)| c.visible) + .count() + + self + .quadruped_small_states + .iter() + .filter(|(_, c)| c.visible) + .count() + + self + .quadruped_medium_states + .iter() + .filter(|(_, c)| c.visible) + .count() + + self + .bird_medium_states + .iter() + .filter(|(_, c)| c.visible) + .count() + + self + .fish_medium_states + .iter() + .filter(|(_, c)| c.visible) + .count() + + self.dragon_states.iter().filter(|(_, c)| c.visible).count() + + self + .bird_small_states + .iter() + .filter(|(_, c)| c.visible) + .count() + + self + .fish_small_states + .iter() + .filter(|(_, c)| c.visible) + .count() + + self + .biped_large_states + .iter() + .filter(|(_, c)| c.visible) + .count() + + self.object_states.iter().filter(|(_, c)| c.visible).count() } } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 3f84b40318..17ec303719 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -16,9 +16,9 @@ use common::{ }; use crossbeam::channel; use dot_vox::DotVoxData; -use treeculler::{Frustum, AABB, BVol}; use hashbrown::{hash_map::Entry, HashMap}; use std::{f32, fmt::Debug, i32, marker::PhantomData, time::Duration}; +use treeculler::{BVol, Frustum, AABB}; use vek::*; struct TerrainChunkData { @@ -1062,7 +1062,8 @@ impl Terrain { chunk.z_bounds.1, ]; - let (in_frustum, last_plane_index) = AABB::new(chunk_min, chunk_max).coherent_test_against_frustum(&frustum, chunk.frustum_last_plane_index); + let (in_frustum, last_plane_index) = AABB::new(chunk_min, chunk_max) + .coherent_test_against_frustum(&frustum, chunk.frustum_last_plane_index); chunk.frustum_last_plane_index = last_plane_index; chunk.visible = in_frustum; @@ -1071,8 +1072,8 @@ impl Terrain { pub fn chunk_count(&self) -> usize { self.chunks.len() - } - + } + pub fn visible_chunk_count(&self) -> usize { self.chunks.iter().filter(|(_, c)| c.visible).count() } From 127f8fb72bcc371b313d218af55f8c55cc238881 Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Thu, 9 Jan 2020 22:07:55 +0300 Subject: [PATCH 40/51] Fix `lpindex` not being updated for culled objects, and don't recalculate frustum for every entity --- voxygen/src/scene/figure/mod.rs | 73 ++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 6887710b40..c05211da6a 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -73,6 +73,7 @@ impl FigureMgr { let ecs = client.state().ecs(); let view_distance = client.view_distance().unwrap_or(1); let dt = client.state().get_delta_time(); + let frustum = camera.frustum(client); // Get player position. let player_pos = ecs .read_storage::() @@ -190,8 +191,6 @@ impl FigureMgr { } // Don't process figures outside the frustum spectrum - let frustum = camera.frustum(client); - let (in_frustum, lpindex) = BoundingSphere::new(pos.0.into_array(), scale.unwrap_or(&Scale(1.0)).0 * 2.0) .coherent_test_against_frustum( @@ -242,54 +241,64 @@ impl FigureMgr { if !in_frustum { match body { Body::Humanoid(_) => { - self.character_states - .get_mut(&entity) - .map(|state| state.visible = false); + self.character_states.get_mut(&entity).map(|state| { + state.lpindex = lpindex; + state.visible = false + }); } Body::QuadrupedSmall(_) => { - self.quadruped_small_states - .get_mut(&entity) - .map(|state| state.visible = false); + self.quadruped_small_states.get_mut(&entity).map(|state| { + state.lpindex = lpindex; + state.visible = false + }); } Body::QuadrupedMedium(_) => { - self.quadruped_medium_states - .get_mut(&entity) - .map(|state| state.visible = false); + self.quadruped_medium_states.get_mut(&entity).map(|state| { + state.lpindex = lpindex; + state.visible = false + }); } Body::BirdMedium(_) => { - self.bird_medium_states - .get_mut(&entity) - .map(|state| state.visible = false); + self.bird_medium_states.get_mut(&entity).map(|state| { + state.lpindex = lpindex; + state.visible = false + }); } Body::FishMedium(_) => { - self.fish_medium_states - .get_mut(&entity) - .map(|state| state.visible = false); + self.fish_medium_states.get_mut(&entity).map(|state| { + state.lpindex = lpindex; + state.visible = false + }); } Body::Dragon(_) => { - self.dragon_states - .get_mut(&entity) - .map(|state| state.visible = false); + self.dragon_states.get_mut(&entity).map(|state| { + state.lpindex = lpindex; + state.visible = false + }); } Body::BirdSmall(_) => { - self.bird_small_states - .get_mut(&entity) - .map(|state| state.visible = false); + self.bird_small_states.get_mut(&entity).map(|state| { + state.lpindex = lpindex; + state.visible = false + }); } Body::FishSmall(_) => { - self.fish_small_states - .get_mut(&entity) - .map(|state| state.visible = false); + self.fish_small_states.get_mut(&entity).map(|state| { + state.lpindex = lpindex; + state.visible = false + }); } Body::BipedLarge(_) => { - self.biped_large_states - .get_mut(&entity) - .map(|state| state.visible = false); + self.biped_large_states.get_mut(&entity).map(|state| { + state.lpindex = lpindex; + state.visible = false + }); } Body::Object(_) => { - self.object_states - .get_mut(&entity) - .map(|state| state.visible = false); + self.object_states.get_mut(&entity).map(|state| { + state.lpindex = lpindex; + state.visible = false + }); } } continue; From 851d7858e6627fc83b6afde27fc9adb9235dc811 Mon Sep 17 00:00:00 2001 From: Monty Marz Date: Fri, 10 Jan 2020 00:33:38 +0000 Subject: [PATCH 41/51] Scrolling Combat Text (SCT) --- .gitignore | 1 + CHANGELOG.md | 5 + Cargo.lock | 1 + assets/voxygen/background/bg_1.png | 3 + .../background/{bg_load.png => bg_2.png} | 0 assets/voxygen/background/bg_3.png | 3 + assets/voxygen/background/bg_4.png | 3 + assets/voxygen/background/bg_5.png | 3 + assets/voxygen/background/bg_6.png | 3 + assets/voxygen/background/bg_7.png | 3 + assets/voxygen/background/bg_8.png | 3 + assets/voxygen/background/death.png | 3 + assets/voxygen/background/hurt.png | 3 + assets/voxygen/background/map.png | 4 +- .../frames/{enemybar.vox => enemybar-0.vox} | 0 assets/voxygen/element/frames/enemybar.png | 3 + assets/voxygen/element/icons/skull.vox | 4 +- assets/voxygen/element/icons/skull_2.vox | 4 +- .../element/skillbar/enemy_bar_content.png | 3 + assets/voxygen/shaders/ui-vert.glsl | 4 + chat-cli/src/main.rs | 6 +- client/src/lib.rs | 11 +- common/src/sys/mod.rs | 18 +- server-cli/.gitignore | 2 +- server/src/cmd.rs | 4 +- server/src/settings.rs | 2 +- server/src/sys/mod.rs | 8 +- voxygen/Cargo.toml | 1 + voxygen/src/ecs/comp.rs | 34 + voxygen/src/ecs/mod.rs | 28 + voxygen/src/ecs/sys.rs | 17 + voxygen/src/ecs/sys/floater.rs | 181 +++++ voxygen/src/ecs/sys/interpolation.rs | 80 +++ voxygen/src/hud/img_ids.rs | 10 +- voxygen/src/hud/map.rs | 23 +- voxygen/src/hud/mod.rs | 669 +++++++++++++++--- voxygen/src/hud/settings_window.rs | 185 ++++- voxygen/src/hud/skillbar.rs | 72 +- voxygen/src/main.rs | 1 + voxygen/src/menu/char_selection/mod.rs | 10 +- voxygen/src/menu/main/mod.rs | 4 +- voxygen/src/menu/main/ui.rs | 26 +- voxygen/src/render/pipelines/ui.rs | 6 +- voxygen/src/scene/figure/mod.rs | 2 + voxygen/src/scene/mod.rs | 33 +- voxygen/src/session.rs | 31 +- voxygen/src/settings.rs | 16 +- voxygen/src/ui/mod.rs | 39 +- voxygen/src/ui/widgets/ingame.rs | 9 + 49 files changed, 1411 insertions(+), 173 deletions(-) create mode 100644 assets/voxygen/background/bg_1.png rename assets/voxygen/background/{bg_load.png => bg_2.png} (100%) create mode 100644 assets/voxygen/background/bg_3.png create mode 100644 assets/voxygen/background/bg_4.png create mode 100644 assets/voxygen/background/bg_5.png create mode 100644 assets/voxygen/background/bg_6.png create mode 100644 assets/voxygen/background/bg_7.png create mode 100644 assets/voxygen/background/bg_8.png create mode 100644 assets/voxygen/background/death.png create mode 100644 assets/voxygen/background/hurt.png rename assets/voxygen/element/frames/{enemybar.vox => enemybar-0.vox} (100%) create mode 100644 assets/voxygen/element/frames/enemybar.png create mode 100644 assets/voxygen/element/skillbar/enemy_bar_content.png create mode 100644 voxygen/src/ecs/comp.rs create mode 100644 voxygen/src/ecs/mod.rs create mode 100644 voxygen/src/ecs/sys.rs create mode 100644 voxygen/src/ecs/sys/floater.rs create mode 100644 voxygen/src/ecs/sys/interpolation.rs diff --git a/.gitignore b/.gitignore index 6948eaa0bc..4422efb240 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ todo.txt # direnv /.envrc +*.bat diff --git a/CHANGELOG.md b/CHANGELOG.md index 9874892a9e..e77e82627b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added changelog - Added animated Map and Minimap position indicator - Added visuals to indicate strength compared to the player +- Added Scrolling Combat Text (SCT) & Settings for it +- Added a Death Screen and Hurt Screen +- Added randomly selected Loading Screen background images + ### Changed @@ -50,6 +54,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed ghosts when going back to character screen - Fixed not being able to unmount - Fixed non-humanoids being able to climb and glide +- Made shadows and lights use interpolated positions ### Removed diff --git a/Cargo.lock b/Cargo.lock index 038127bc5e..0344df16fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3544,6 +3544,7 @@ dependencies = [ "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "specs-idvs 0.1.0 (git+https://gitlab.com/veloren/specs-idvs.git)", "treeculler 0.1.0 (git+https://gitlab.com/yusdacra/treeculler.git)", "vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "veloren-client 0.4.0", diff --git a/assets/voxygen/background/bg_1.png b/assets/voxygen/background/bg_1.png new file mode 100644 index 0000000000..932d14be00 --- /dev/null +++ b/assets/voxygen/background/bg_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:abdedad035b9e4cd495af42e343068b783f2b09a8d7635cff895be2243cf1cc2 +size 538326 diff --git a/assets/voxygen/background/bg_load.png b/assets/voxygen/background/bg_2.png similarity index 100% rename from assets/voxygen/background/bg_load.png rename to assets/voxygen/background/bg_2.png diff --git a/assets/voxygen/background/bg_3.png b/assets/voxygen/background/bg_3.png new file mode 100644 index 0000000000..c3584377b3 --- /dev/null +++ b/assets/voxygen/background/bg_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:258da639ea3e41ff10b42c27936229a18de7a73afb8358b67c1ffec88082ec82 +size 2406949 diff --git a/assets/voxygen/background/bg_4.png b/assets/voxygen/background/bg_4.png new file mode 100644 index 0000000000..ec2995123f --- /dev/null +++ b/assets/voxygen/background/bg_4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94a252fcec90d115b26f64eaf92a539ecd5db52e9974a42758280dc6e25296dc +size 2179461 diff --git a/assets/voxygen/background/bg_5.png b/assets/voxygen/background/bg_5.png new file mode 100644 index 0000000000..40818d7056 --- /dev/null +++ b/assets/voxygen/background/bg_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ccd718e84b59b156d97788f1bea39d38ff34e7cfc3aacf5380b28586e1403ef +size 1205008 diff --git a/assets/voxygen/background/bg_6.png b/assets/voxygen/background/bg_6.png new file mode 100644 index 0000000000..41250ee39d --- /dev/null +++ b/assets/voxygen/background/bg_6.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d4785086ec9941d7a159c47c5475d01d0a13b3b73ef1952f869a9c31fa1739d2 +size 793666 diff --git a/assets/voxygen/background/bg_7.png b/assets/voxygen/background/bg_7.png new file mode 100644 index 0000000000..40e86c134e --- /dev/null +++ b/assets/voxygen/background/bg_7.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe436e2811629b57c47af449949dedbd0ff9a3a63136e196636e072a3b8bc320 +size 1244674 diff --git a/assets/voxygen/background/bg_8.png b/assets/voxygen/background/bg_8.png new file mode 100644 index 0000000000..47c19d7db9 --- /dev/null +++ b/assets/voxygen/background/bg_8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8096f8a7b94e49cfe2cfba3ad6f9bd152078bca834ea7ea7af9e9889bcf99ceb +size 710326 diff --git a/assets/voxygen/background/death.png b/assets/voxygen/background/death.png new file mode 100644 index 0000000000..3852c5424b --- /dev/null +++ b/assets/voxygen/background/death.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a24fc708b5c3fee34fdad50cc4be002f6df12f358522af413098ddb150b24ced +size 143395 diff --git a/assets/voxygen/background/hurt.png b/assets/voxygen/background/hurt.png new file mode 100644 index 0000000000..91e6fef724 --- /dev/null +++ b/assets/voxygen/background/hurt.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fdab32e2b5443e930f7fe4d3e188b51c6dc26f0729ae8763696386024dc6bed1 +size 260584 diff --git a/assets/voxygen/background/map.png b/assets/voxygen/background/map.png index 7e284d0568..a9733ceb45 100644 --- a/assets/voxygen/background/map.png +++ b/assets/voxygen/background/map.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:664f74c2b92f6319aa30cd0775af6976c629a8d9f521febac0748bacb432c3f3 -size 747328 +oid sha256:398b577a57ad9670b3400a3772a0798ccc409d8dfcb073ae050fae8cb314fbd2 +size 906590 diff --git a/assets/voxygen/element/frames/enemybar.vox b/assets/voxygen/element/frames/enemybar-0.vox similarity index 100% rename from assets/voxygen/element/frames/enemybar.vox rename to assets/voxygen/element/frames/enemybar-0.vox diff --git a/assets/voxygen/element/frames/enemybar.png b/assets/voxygen/element/frames/enemybar.png new file mode 100644 index 0000000000..82515fb6c0 --- /dev/null +++ b/assets/voxygen/element/frames/enemybar.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bfa1034410f86cc56f8ca737054ff8a8bf71dd4d696fa3bd8195d866cb4405d3 +size 1607 diff --git a/assets/voxygen/element/icons/skull.vox b/assets/voxygen/element/icons/skull.vox index 6f12b02c2b..024f888038 100644 --- a/assets/voxygen/element/icons/skull.vox +++ b/assets/voxygen/element/icons/skull.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6eeb17f7682aa533fc805de9272f55f01d10c06d2c6afefed54ce23d46fe93ab -size 56456 +oid sha256:1708cf57ec4d132e3478f86aef7083d37cf85b890a2ddcf4278d8b5d4394f53d +size 57720 diff --git a/assets/voxygen/element/icons/skull_2.vox b/assets/voxygen/element/icons/skull_2.vox index a32adc29ff..140ab7bf2c 100644 --- a/assets/voxygen/element/icons/skull_2.vox +++ b/assets/voxygen/element/icons/skull_2.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6717aca430c81b346951f22fbb03e2dca4765a3fd56b7e515f267138af9f6e18 -size 56512 +oid sha256:d9ddbabd913b6b5afaf2d9344b457cdd9068ee5a1f019141c3f13e364b463dda +size 57784 diff --git a/assets/voxygen/element/skillbar/enemy_bar_content.png b/assets/voxygen/element/skillbar/enemy_bar_content.png new file mode 100644 index 0000000000..d1ac7bf94c --- /dev/null +++ b/assets/voxygen/element/skillbar/enemy_bar_content.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7611fe460a24c1340bf5b72ed7e6f4dbdfc0b7617cc4f0e56449c3f6c3f03f13 +size 141 diff --git a/assets/voxygen/shaders/ui-vert.glsl b/assets/voxygen/shaders/ui-vert.glsl index 2411525756..bcdeca839f 100644 --- a/assets/voxygen/shaders/ui-vert.glsl +++ b/assets/voxygen/shaders/ui-vert.glsl @@ -25,6 +25,10 @@ void main() { if (w_pos.w == 1.0) { // In-game element gl_Position = proj_mat * (view_mat * w_pos + vec4(v_pos, 0.0, 0.0)); + } else if (w_pos.w == -1.0 ) { + // Fixed scale In-game element + vec4 projected_pos = proj_mat * view_mat * vec4(w_pos.xyz, 1.0); + gl_Position = vec4(projected_pos.xy / projected_pos.w + v_pos, 0.0, 1.0); } else { // Interface element gl_Position = vec4(v_pos, 0.0, 1.0); diff --git a/chat-cli/src/main.rs b/chat-cli/src/main.rs index 2f288c6500..f21da11295 100644 --- a/chat-cli/src/main.rs +++ b/chat-cli/src/main.rs @@ -65,7 +65,11 @@ fn main() { client.send_chat(msg) } - let events = match client.tick(comp::ControllerInputs::default(), clock.get_last_delta()) { + let events = match client.tick( + comp::ControllerInputs::default(), + clock.get_last_delta(), + |_| {}, + ) { Ok(events) => events, Err(err) => { error!("Error: {:?}", err); diff --git a/client/src/lib.rs b/client/src/lib.rs index 0ceed6b47b..d9691c9ed1 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -8,7 +8,7 @@ pub use crate::error::Error; pub use specs::{ join::Join, saveload::{Marker, MarkerAllocator}, - Builder, Entity as EcsEntity, ReadStorage, WorldExt, + Builder, DispatcherBuilder, Entity as EcsEntity, ReadStorage, WorldExt, }; use common::{ @@ -316,7 +316,12 @@ impl Client { } /// Execute a single client tick, handle input and update the game state by the given duration. - pub fn tick(&mut self, inputs: ControllerInputs, dt: Duration) -> Result, Error> { + pub fn tick( + &mut self, + inputs: ControllerInputs, + dt: Duration, + add_foreign_systems: impl Fn(&mut DispatcherBuilder), + ) -> Result, Error> { // This tick function is the centre of the Veloren universe. Most client-side things are // managed from here, and as such it's important that it stays organised. Please consult // the core developers before making significant changes to this code. Here is the @@ -374,7 +379,7 @@ impl Client { // 3) Update client local data // 4) Tick the client's LocalState - self.state.tick(dt, |_| {}); + self.state.tick(dt, add_foreign_systems); // 5) Terrain let pos = self diff --git a/common/src/sys/mod.rs b/common/src/sys/mod.rs index 6f2c402318..2bf9d2ac8c 100644 --- a/common/src/sys/mod.rs +++ b/common/src/sys/mod.rs @@ -12,15 +12,15 @@ mod stats; use specs::DispatcherBuilder; // System names -const AGENT_SYS: &str = "agent_sys"; -const CONTROLLER_SYS: &str = "controller_sys"; -const MOUNT_SYS: &str = "mount_sys"; -const PHYS_SYS: &str = "phys_sys"; -const MOVEMENT_SYS: &str = "movement_sys"; -const PROJECTILE_SYS: &str = "projectile_sys"; -const COMBAT_SYS: &str = "combat_sys"; -const STATS_SYS: &str = "stats_sys"; -const CLEANUP_SYS: &str = "cleanup_sys"; +pub const AGENT_SYS: &str = "agent_sys"; +pub const CONTROLLER_SYS: &str = "controller_sys"; +pub const MOUNT_SYS: &str = "mount_sys"; +pub const PHYS_SYS: &str = "phys_sys"; +pub const MOVEMENT_SYS: &str = "movement_sys"; +pub const PROJECTILE_SYS: &str = "projectile_sys"; +pub const COMBAT_SYS: &str = "combat_sys"; +pub const STATS_SYS: &str = "stats_sys"; +pub const CLEANUP_SYS: &str = "cleanup_sys"; pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) { dispatch_builder.add(agent::Sys, AGENT_SYS, &[]); diff --git a/server-cli/.gitignore b/server-cli/.gitignore index dc83325b30..8b13789179 100644 --- a/server-cli/.gitignore +++ b/server-cli/.gitignore @@ -1 +1 @@ -settings.ron + diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 9f0cc61b46..ae79ae6215 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -87,9 +87,9 @@ lazy_static! { /// Static list of chat commands available to the server. pub static ref CHAT_COMMANDS: Vec = vec![ ChatCommand::new( - "giveitem", + "give_item", "{d}", - "/giveitem \n\ + "/give_item \n\ Example: common/items/debug/boost", true, handle_give,), diff --git a/server/src/settings.rs b/server/src/settings.rs index 533c3891c4..444ba9580a 100644 --- a/server/src/settings.rs +++ b/server/src/settings.rs @@ -22,7 +22,7 @@ impl Default for ServerSettings { Self { gameserver_address: SocketAddr::from(([0; 4], 14004)), metrics_address: SocketAddr::from(([0; 4], 14005)), - world_seed: 1337, + world_seed: 5284, server_name: "Veloren Alpha".to_owned(), server_description: "This is the best Veloren server.".to_owned(), max_players: 100, diff --git a/server/src/sys/mod.rs b/server/src/sys/mod.rs index 72860c92c8..fff86de2be 100644 --- a/server/src/sys/mod.rs +++ b/server/src/sys/mod.rs @@ -24,8 +24,12 @@ const TERRAIN_SYS: &str = "server_terrain_sys"; pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { // TODO: makes some of these dependent on systems in common like the phys system - dispatch_builder.add(sentinel::Sys, SENTINEL_SYS, &[]); - dispatch_builder.add(subscription::Sys, SUBSCRIPTION_SYS, &[]); + dispatch_builder.add(sentinel::Sys, SENTINEL_SYS, &[common::sys::PHYS_SYS]); + dispatch_builder.add( + subscription::Sys, + SUBSCRIPTION_SYS, + &[common::sys::PHYS_SYS], + ); dispatch_builder.add( entity_sync::Sys, ENTITY_SYNC_SYS, diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 322575db69..b736ad5f33 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -28,6 +28,7 @@ euc = "0.3.0" # ECS specs = "0.15.1" +specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git" } # Mathematics vek = { version = "0.9.9", features = ["serde"] } diff --git a/voxygen/src/ecs/comp.rs b/voxygen/src/ecs/comp.rs new file mode 100644 index 0000000000..96efe460d0 --- /dev/null +++ b/voxygen/src/ecs/comp.rs @@ -0,0 +1,34 @@ +use specs::Component; +use specs_idvs::IDVStorage; +use vek::*; + +// Floats over entity that has had a health change, rising up over time until it vanishes +#[derive(Copy, Clone, Debug)] +pub struct HpFloater { + pub timer: f32, + // Numbers of times significant damage has been dealt + pub hp_change: i32, + // Used for randomly offseting + pub rand: f32, +} +#[derive(Clone, Debug, Default)] +pub struct HpFloaterList { + // Order oldest to newest + pub floaters: Vec, + // Keep from spawning more floaters from same hp change + // Note: this can't detect a change if equivalent healing and damage take place simultaneously + pub last_hp: u32, +} +impl Component for HpFloaterList { + type Storage = IDVStorage; +} + +// Used for smooth interpolation of visual elements that are tied to entity position +#[derive(Copy, Clone, Debug)] +pub struct Interpolated { + pub pos: Vec3, + pub ori: Vec3, +} +impl Component for Interpolated { + type Storage = IDVStorage; +} diff --git a/voxygen/src/ecs/mod.rs b/voxygen/src/ecs/mod.rs new file mode 100644 index 0000000000..779bcbc2b6 --- /dev/null +++ b/voxygen/src/ecs/mod.rs @@ -0,0 +1,28 @@ +pub mod comp; +pub mod sys; + +use specs::{Entity, World, WorldExt}; + +#[derive(Copy, Clone, Debug)] +pub struct MyEntity(pub Entity); + +#[derive(Copy, Clone, Debug)] +pub struct ExpFloater { + pub exp_change: i32, // Maybe you can loose exp :p + pub timer: f32, + // Used to randomly offset position + pub rand: (f32, f32), +} +#[derive(Clone, Debug, Default)] +pub struct MyExpFloaterList { + pub floaters: Vec, + pub last_exp: u32, + pub last_level: u32, + pub last_exp_max: u32, +} + +pub fn init(world: &mut World) { + world.register::(); + world.register::(); + world.insert(MyExpFloaterList::default()); +} diff --git a/voxygen/src/ecs/sys.rs b/voxygen/src/ecs/sys.rs new file mode 100644 index 0000000000..d26f70977d --- /dev/null +++ b/voxygen/src/ecs/sys.rs @@ -0,0 +1,17 @@ +pub mod floater; +mod interpolation; + +use specs::DispatcherBuilder; + +// System names +const FLOATER_SYS: &str = "floater_voxygen_sys"; +const INTERPOLATION_SYS: &str = "interpolation_voxygen_sys"; + +pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) { + dispatch_builder.add( + interpolation::Sys, + INTERPOLATION_SYS, + &[common::sys::PHYS_SYS], + ); + dispatch_builder.add(floater::Sys, FLOATER_SYS, &[INTERPOLATION_SYS]); +} diff --git a/voxygen/src/ecs/sys/floater.rs b/voxygen/src/ecs/sys/floater.rs new file mode 100644 index 0000000000..d8ab4a03b6 --- /dev/null +++ b/voxygen/src/ecs/sys/floater.rs @@ -0,0 +1,181 @@ +use crate::ecs::{ + comp::{HpFloater, HpFloaterList}, + ExpFloater, MyEntity, MyExpFloaterList, +}; +use common::{ + comp::{HealthSource, Pos, Stats}, + state::DeltaTime, + sync::Uid, +}; +use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, Write, WriteStorage}; + +// How long floaters last (in seconds) +pub const HP_SHOWTIME: f32 = 3.0; +pub const MY_HP_SHOWTIME: f32 = 2.5; +pub const MY_EXP_SHOWTIME: f32 = 4.0; + +pub struct Sys; +impl<'a> System<'a> for Sys { + type SystemData = ( + Entities<'a>, + ReadExpect<'a, MyEntity>, + Read<'a, DeltaTime>, + Write<'a, MyExpFloaterList>, + ReadStorage<'a, Uid>, + ReadStorage<'a, Pos>, + ReadStorage<'a, Stats>, + WriteStorage<'a, HpFloaterList>, + ); + + fn run( + &mut self, + (entities, my_entity, dt, mut my_exp_floater_list, uids, pos, stats, mut hp_floater_lists): Self::SystemData, + ) { + // Add hp floater lists to all entities with stats and a postion + // Note: neccessary in order to know last_hp + for (entity, last_hp) in (&entities, &stats, &pos, !&hp_floater_lists) + .join() + .map(|(e, s, _, _)| (e, s.health.current())) + .collect::>() + { + let _ = hp_floater_lists.insert( + entity, + HpFloaterList { + floaters: Vec::new(), + last_hp, + }, + ); + } + + // Add hp floaters to all entities that have been damaged + let my_uid = uids.get(my_entity.0); + for (entity, health, hp_floater_list) in (&entities, &stats, &mut hp_floater_lists) + .join() + .map(|(e, s, fl)| (e, s.health, fl)) + { + // Check if health has changed (won't work if damaged and then healed with + // equivalently in the same frame) + if hp_floater_list.last_hp != health.current() { + hp_floater_list.last_hp = health.current(); + // TODO: What if multiple health changes occured since last check here + // Also, If we make stats store a vec of the last_changes (from say the last frame), + // what if the client recieves the stats component from two different server ticks at + // once, then one will be lost (tbf this is probably a rare occurance and the results + // would just be a transient glitch in the display of these damage numbers) (maybe + // health changes could be sent to the client as a list of events) + if match health.last_change.1.cause { + HealthSource::Attack { by } => { + my_entity.0 == entity || my_uid.map_or(false, |&uid| by == uid) + } + HealthSource::Suicide => my_entity.0 == entity, + HealthSource::World => my_entity.0 == entity, + HealthSource::Revive => false, + HealthSource::Command => true, + HealthSource::LevelUp => my_entity.0 == entity, + HealthSource::Item => true, + HealthSource::Unknown => false, + } { + hp_floater_list.floaters.push(HpFloater { + timer: 0.0, + hp_change: health.last_change.1.amount, + rand: rand::random(), + }); + } + } + } + + // Remove floater lists on entities without stats or without posistion + for entity in (&entities, !&stats, &hp_floater_lists) + .join() + .map(|(e, _, _)| e) + .collect::>() + { + hp_floater_lists.remove(entity); + } + for entity in (&entities, !&pos, &hp_floater_lists) + .join() + .map(|(e, _, _)| e) + .collect::>() + { + hp_floater_lists.remove(entity); + } + + // Maintain existing floaters + for ( + entity, + HpFloaterList { + ref mut floaters, + ref last_hp, + }, + ) in (&entities, &mut hp_floater_lists).join() + { + for mut floater in floaters.iter_mut() { + // Increment timer + floater.timer += dt.0; + } + // Clear floaters if newest floater is past show time or health runs out + if floaters.last().map_or(false, |f| { + f.timer + > if entity != my_entity.0 { + HP_SHOWTIME + } else { + MY_HP_SHOWTIME + } + || *last_hp == 0 + }) { + floaters.clear(); + } + } + + // Update MyExpFloaterList + if let Some(stats) = stats.get(my_entity.0) { + let mut fl = my_exp_floater_list; + // Add a floater if exp changed + // TODO: can't handle if you level up more than once (maybe store total exp in stats) + let exp_change = if stats.level.level() != fl.last_level { + if stats.level.level() > fl.last_level { + stats.exp.current() as i32 + fl.last_exp_max as i32 - fl.last_exp as i32 + } else { + // Level down + stats.exp.current() as i32 - stats.exp.maximum() as i32 - fl.last_exp as i32 + } + } else { + stats.exp.current() as i32 - fl.last_exp as i32 + }; + + if exp_change != 0 { + fl.floaters.push(ExpFloater { + timer: 0.0, + exp_change, + rand: (rand::random(), rand::random()), + }); + } + + // Increment timers + for mut floater in &mut fl.floaters { + floater.timer += dt.0; + } + + // Clear if the newest is past show time + if fl + .floaters + .last() + .map_or(false, |f| f.timer > MY_EXP_SHOWTIME) + { + fl.floaters.clear(); + } + + // Update stored values + fl.last_exp = stats.exp.current(); + fl.last_exp_max = stats.exp.maximum(); + fl.last_level = stats.level.level(); + } else { + // Clear if stats component doesn't exist + my_exp_floater_list.floaters.clear(); + // Clear stored values + my_exp_floater_list.last_exp = 0; + my_exp_floater_list.last_exp_max = 0; + my_exp_floater_list.last_level = 0; + } + } +} diff --git a/voxygen/src/ecs/sys/interpolation.rs b/voxygen/src/ecs/sys/interpolation.rs new file mode 100644 index 0000000000..80ddfc6261 --- /dev/null +++ b/voxygen/src/ecs/sys/interpolation.rs @@ -0,0 +1,80 @@ +use crate::ecs::comp::Interpolated; +use common::{ + comp::{Ori, Pos, Vel}, + state::DeltaTime, +}; +use log::warn; +use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage}; +use vek::*; + +/// This system will allow NPCs to modify their controller +pub struct Sys; +impl<'a> System<'a> for Sys { + type SystemData = ( + Entities<'a>, + Read<'a, DeltaTime>, + ReadStorage<'a, Pos>, + ReadStorage<'a, Ori>, + ReadStorage<'a, Vel>, + WriteStorage<'a, Interpolated>, + ); + + fn run( + &mut self, + (entities, dt, positions, orientations, velocities, mut interpolated): Self::SystemData, + ) { + // Update interpolated positions and orientations + for (pos, ori, i, vel) in (&positions, &orientations, &mut interpolated, &velocities).join() + { + // Update interpolation values + if i.pos.distance_squared(pos.0) < 64.0 * 64.0 { + i.pos = Lerp::lerp(i.pos, pos.0 + vel.0 * 0.03, 10.0 * dt.0); + let ori_interp = Slerp::slerp(i.ori, ori.0, 5.0 * dt.0); + // Check for NaNs + // TODO: why are we getting NaNs here! Zero-length ori vectors? + i.ori = if !ori_interp.map(|e| e.is_nan()).reduce_or() { + ori_interp + } else { + ori.0 + }; + } else { + i.pos = pos.0; + i.ori = ori.0; + } + } + // Insert interpolation components for entities which don't have them + for (entity, pos, ori) in (&entities, &positions, &orientations, !&interpolated) + .join() + .map(|(e, p, o, _)| (e, p.0, o.0)) + .collect::>() + { + interpolated + .insert(entity, Interpolated { pos, ori }) + .err() + .map(|err| warn!("Error inserting Interpolated component: {}", err)); + } + // Remove Interpolated component from entities which don't have a position or an + // orientation or a velocity + for entity in (&entities, !&positions, &interpolated) + .join() + .map(|(e, _, _)| e) + .collect::>() + { + interpolated.remove(entity); + } + for entity in (&entities, !&orientations, &interpolated) + .join() + .map(|(e, _, _)| e) + .collect::>() + { + interpolated.remove(entity); + } + for entity in (&entities, !&velocities, &interpolated) + .join() + .map(|(e, _, _)| e) + .collect::>() + { + interpolated.remove(entity); + } + } +} diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index ac1593693f..ff0f81d731 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -231,8 +231,7 @@ image_ids! { key: "voxygen.voxel.object.key", key_gold: "voxygen.voxel.object.key_gold", - // Enemy Healthbar - enemy_health: "voxygen.element.frames.enemybar", + @@ -247,6 +246,13 @@ image_ids! { charwindow_gradient:"voxygen.element.misc_bg.charwindow", map_placeholder: "voxygen.background.map", + death_bg: "voxygen.background.death", + hurt_bg: "voxygen.background.hurt", + + // Enemy Healthbar + enemy_health: "voxygen.element.frames.enemybar", + // Enemy Bar Content: + enemy_bar: "voxygen.element.skillbar.enemy_bar_content", // Spell Book Window spellbook_icon: "voxygen.element.icons.spellbook", // Bag diff --git a/voxygen/src/hud/map.rs b/voxygen/src/hud/map.rs index 8d7eccc10c..2890b5ae22 100644 --- a/voxygen/src/hud/map.rs +++ b/voxygen/src/hud/map.rs @@ -9,7 +9,6 @@ use conrod_core::{ }; use specs::WorldExt; use vek::*; - widget_ids! { struct Ids { map_frame, @@ -37,6 +36,7 @@ pub struct Map<'a> { #[conrod(common_builder)] common: widget::CommonBuilder, pulse: f32, + velocity: f32, } impl<'a> Map<'a> { pub fn new( @@ -46,6 +46,7 @@ impl<'a> Map<'a> { world_map: Id, fonts: &'a Fonts, pulse: f32, + velocity: f32, ) -> Self { Self { _show: show, @@ -55,6 +56,7 @@ impl<'a> Map<'a> { fonts: fonts, common: widget::CommonBuilder::default(), pulse, + velocity, } } } @@ -84,6 +86,15 @@ impl<'a> Widget for Map<'a> { fn update(self, args: widget::UpdateArgs) -> Self::Event { let widget::UpdateArgs { state, ui, .. } = args; + // Set map transparency to 0.5 when player is moving + /*let vel = match self.velocity { + Some(velocity) => velocity.0.magnitude(), + None => 0.0, + };*/ + let mut fade = 1.0; + if self.velocity > 7.0 { + fade = 0.7 + }; // BG Rectangle::fill_with([824.0, 976.0], color::TRANSPARENT) @@ -96,24 +107,29 @@ impl<'a> Widget for Map<'a> { Image::new(self.imgs.map_frame_l) .top_left_with_margins_on(state.ids.map_bg, 0.0, 0.0) .w_h(412.0, 488.0) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade))) .set(state.ids.map_frame_l, ui); Image::new(self.imgs.map_frame_r) .right_from(state.ids.map_frame_l, 0.0) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade))) .w_h(412.0, 488.0) .set(state.ids.map_frame_r, ui); Image::new(self.imgs.map_frame_br) .down_from(state.ids.map_frame_r, 0.0) .w_h(412.0, 488.0) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade))) .set(state.ids.map_frame_br, ui); Image::new(self.imgs.map_frame_bl) .down_from(state.ids.map_frame_l, 0.0) .w_h(412.0, 488.0) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade))) .set(state.ids.map_frame_bl, ui); // Icon Image::new(self.imgs.map_icon) .w_h(224.0 / 3.0, 224.0 / 3.0) .top_left_with_margins_on(state.ids.map_frame, -10.0, -10.0) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade))) .set(state.ids.map_icon, ui); // X-Button @@ -121,6 +137,7 @@ impl<'a> Widget for Map<'a> { .w_h(28.0, 28.0) .hover_image(self.imgs.close_button_hover) .press_image(self.imgs.close_button_press) + .color(Color::Rgba(1.0, 1.0, 1.0, fade - 0.5)) .top_right_with_margins_on(state.ids.map_frame_r, 0.0, 0.0) .set(state.ids.map_close, ui) .was_clicked() @@ -144,9 +161,11 @@ impl<'a> Widget for Map<'a> { .color(TEXT_COLOR) .set(state.ids.location_name, ui), } + // Map Image Image::new(/*self.world_map*/ self.imgs.map_placeholder) .middle_of(state.ids.map_bg) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade))) .w_h(700.0, 700.0) .parent(state.ids.map_bg) .set(state.ids.grid, ui); @@ -183,7 +202,7 @@ impl<'a> Widget for Map<'a> { 34.0 * indic_scale }, ) - .color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade + 0.2))) .floating(true) .parent(ui.window) .set(state.ids.indicator, ui); diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 7af4cad854..88124a4439 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -13,8 +13,7 @@ mod skillbar; mod social; mod spell; -use crate::hud::img_ids::ImgsRot; -//use rand::Rng; +use crate::{ecs::comp::HpFloaterList, hud::img_ids::ImgsRot}; pub use settings_window::ScaleChange; use std::time::Duration; @@ -36,6 +35,7 @@ use social::{Social, SocialTab}; use spell::Spell; use crate::{ + ecs::comp as vcomp, render::{AaMode, Consts, Globals, Renderer}, scene::camera::Camera, //settings::ControlSettings, @@ -60,6 +60,7 @@ use crate::{discord, discord::DiscordUpdate}; const XP_COLOR: Color = Color::Rgba(0.59, 0.41, 0.67, 1.0); const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); +//const TEXT_COLOR_GREY: Color = Color::Rgba(1.0, 1.0, 1.0, 0.5); const MENU_BG: Color = Color::Rgba(0.0, 0.0, 0.0, 0.4); //const TEXT_COLOR_2: Color = Color::Rgba(0.0, 0.0, 0.0, 1.0); const TEXT_COLOR_3: Color = Color::Rgba(1.0, 1.0, 1.0, 0.1); @@ -88,6 +89,7 @@ widget_ids! { // Character Names name_tags[], + name_tags_bgs[], levels[], levels_skull[], // Health Bars @@ -96,6 +98,18 @@ widget_ids! { health_bar_fronts[], health_bar_backs[], + // SCT + player_scts[], + player_sct_bgs[], + sct_exp_bgs[], + sct_exps[], + sct_lvl_bg, + sct_lvl, + hurt_bg, + death_bg, + sct_bgs[], + scts[], + // Intro Text intro_bg, intro_text, @@ -128,6 +142,7 @@ widget_ids! { // Help help, help_info, + debug_info, // Window Frames window_frame_0, @@ -200,6 +215,10 @@ pub enum Event { Intro(Intro), ToggleBarNumbers(BarNumbers), ToggleShortcutNumbers(ShortcutNumbers), + Sct(bool), + SctPlayerBatch(bool), + SctDamageBatch(bool), + ToggleDebug(bool), UiScale(ScaleChange), CharacterSelection, UseInventorySlot(usize), @@ -265,7 +284,6 @@ pub struct Show { ingame: bool, settings_tab: SettingsTab, social_tab: SocialTab, - want_grab: bool, } impl Show { @@ -424,6 +442,7 @@ pub struct Hud { force_chat_cursor: Option, pulse: f32, zoom: f32, + velocity: f32, } impl Hud { @@ -461,7 +480,7 @@ impl Hud { show: Show { help: false, intro: true, - debug: true, + debug: false, bag: false, esc_menu: false, open_windows: Windows::None, @@ -485,6 +504,7 @@ impl Hud { force_chat_cursor: None, pulse: 0.0, zoom: 1.0, + velocity: 0.0, } } @@ -499,43 +519,23 @@ impl Hud { let (ref mut ui_widgets, ref mut tooltip_manager) = self.ui.set_widgets(); // pulse time for pulsating elements self.pulse = self.pulse + dt.as_secs_f32(); + self.velocity = match debug_info.velocity { + Some(velocity) => velocity.0.magnitude(), + None => 0.0, + }; let version = format!( "{}-{}", env!("CARGO_PKG_VERSION"), common::util::GIT_VERSION.to_string() ); - if self.show.ingame { - // Crosshair - if !self.show.help { - Image::new( - // TODO: Do we want to match on this every frame? - match global_state.settings.gameplay.crosshair_type { - CrosshairType::Round => self.imgs.crosshair_outer_round, - CrosshairType::RoundEdges => self.imgs.crosshair_outer_round_edges, - CrosshairType::Edges => self.imgs.crosshair_outer_edges, - }, - ) - .w_h(21.0 * 1.5, 21.0 * 1.5) - .middle_of(ui_widgets.window) - .color(Some(Color::Rgba( - 1.0, - 1.0, - 1.0, - global_state.settings.gameplay.crosshair_transp, - ))) - .set(self.ids.crosshair_outer, ui_widgets); - Image::new(self.imgs.crosshair_inner) - .w_h(21.0 * 2.0, 21.0 * 2.0) - .middle_of(self.ids.crosshair_outer) - .color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.6))) - .set(self.ids.crosshair_inner, ui_widgets); - } - // Nametags and healthbars + if self.show.ingame { let ecs = client.state().ecs(); let pos = ecs.read_storage::(); let stats = ecs.read_storage::(); + let hp_floater_lists = ecs.read_storage::(); + let interpolated = ecs.read_storage::(); let players = ecs.read_storage::(); let scales = ecs.read_storage::(); let entities = ecs.entities(); @@ -545,6 +545,62 @@ impl Hud { .get(client.entity()) .map_or(0, |stats| stats.level.level()); + if let Some(stats) = stats.get(me) { + // Hurt Frame + let hp_percentage = + stats.health.current() as f32 / stats.health.maximum() as f32 * 100.0; + if hp_percentage < 10.0 && !stats.is_dead { + let hurt_fade = + (self.pulse * (10.0 - hp_percentage as f32) * 0.1/*speed factor*/).sin() + * 0.5 + + 0.6; //Animation timer + Image::new(self.imgs.hurt_bg) + .wh_of(ui_widgets.window) + .middle_of(ui_widgets.window) + .graphics_for(ui_widgets.window) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, hurt_fade))) + .set(self.ids.hurt_bg, ui_widgets); + } + // Death Frame + if stats.is_dead { + Image::new(self.imgs.death_bg) + .wh_of(ui_widgets.window) + .middle_of(ui_widgets.window) + .graphics_for(ui_widgets.window) + .color(Some(Color::Rgba(0.0, 0.0, 0.0, 1.0))) + .set(self.ids.death_bg, ui_widgets); + } + // Crosshair + if !self.show.help && !stats.is_dead { + Image::new( + // TODO: Do we want to match on this every frame? + match global_state.settings.gameplay.crosshair_type { + CrosshairType::Round => self.imgs.crosshair_outer_round, + CrosshairType::RoundEdges => self.imgs.crosshair_outer_round_edges, + CrosshairType::Edges => self.imgs.crosshair_outer_edges, + }, + ) + .w_h(21.0 * 1.5, 21.0 * 1.5) + .middle_of(ui_widgets.window) + .color(Some(Color::Rgba( + 1.0, + 1.0, + 1.0, + global_state.settings.gameplay.crosshair_transp, + ))) + .set(self.ids.crosshair_outer, ui_widgets); + Image::new(self.imgs.crosshair_inner) + .w_h(21.0 * 2.0, 21.0 * 2.0) + .middle_of(self.ids.crosshair_outer) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.6))) + .set(self.ids.crosshair_inner, ui_widgets); + } + } + + // Nametags and healthbars + + // Max amount the sct font size increases when "flashing" + const FLASH_MAX: f32 = 25.0; // Get player position. let player_pos = client .state() @@ -553,21 +609,31 @@ impl Hud { .get(client.entity()) .map_or(Vec3::zero(), |pos| pos.0); let mut name_id_walker = self.ids.name_tags.walk(); + let mut name_id_bg_walker = self.ids.name_tags_bgs.walk(); let mut level_id_walker = self.ids.levels.walk(); let mut level_skull_id_walker = self.ids.levels_skull.walk(); let mut health_id_walker = self.ids.health_bars.walk(); let mut mana_id_walker = self.ids.mana_bars.walk(); let mut health_back_id_walker = self.ids.health_bar_backs.walk(); let mut health_front_id_walker = self.ids.health_bar_fronts.walk(); + let mut sct_bg_id_walker = self.ids.sct_bgs.walk(); + let mut sct_id_walker = self.ids.scts.walk(); // Render Health Bars - for (_entity, pos, stats, scale) in (&entities, &pos, &stats, scales.maybe()) + for (pos, stats, scale, hp_floater_list) in ( + &entities, + &pos, + interpolated.maybe(), + &stats, + scales.maybe(), + hp_floater_lists.maybe(), // Potentially move this to its own loop + ) .join() - .filter(|(entity, _, stats, _)| { + .filter(|(entity, _, _, stats, _, _)| { *entity != me && !stats.is_dead //&& stats.health.current() != stats.health.maximum() }) // Don't process health bars outside the vd (visibility further limited by ui backend) - .filter(|(_, pos, _, _)| { + .filter(|(_, pos, _, _, _, _)| { Vec2::from(pos.0 - player_pos) .map2(TerrainChunk::RECT_SIZE, |d: f32, sz| { d.abs() as f32 / sz as f32 @@ -575,9 +641,15 @@ impl Hud { .magnitude() < view_distance as f32 }) + .map(|(_, pos, interpolated, stats, scale, f)| { + ( + interpolated.map_or(pos.0, |i| i.pos), + stats, + scale.map_or(1.0, |s| s.0), + f, + ) + }) { - let scale = scale.map(|s| s.0).unwrap_or(1.0); - let back_id = health_back_id_walker.next( &mut self.ids.health_bar_backs, &mut ui_widgets.widget_id_generator(), @@ -596,20 +668,22 @@ impl Hud { ); let hp_percentage = stats.health.current() as f64 / stats.health.maximum() as f64 * 100.0; + let energy_percentage = + stats.energy.current() as f64 / stats.energy.maximum() as f64 * 100.0; let hp_ani = (self.pulse * 4.0/*speed factor*/).cos() * 0.5 + 1.0; //Animation timer let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani); // Background Rectangle::fill_with([82.0, 8.0], Color::Rgba(0.3, 0.3, 0.3, 0.5)) .x_y(0.0, -25.0) - .position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) + .position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) .resolution(100.0) .set(back_id, ui_widgets); // % HP Filling - Image::new(self.imgs.bar_content) + Image::new(self.imgs.enemy_bar) .w_h(72.9 * (hp_percentage / 100.0), 5.9) - .x_y(4.5, -24.0) + .x_y(4.5 + (hp_percentage / 100.0 * 36.45) - 36.45, -24.0) .color(Some(if hp_percentage <= 25.0 { crit_hp_color } else if hp_percentage <= 50.0 { @@ -617,7 +691,7 @@ impl Hud { } else { HP_COLOR })) - .position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) + .position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) .resolution(100.0) .set(health_bar_id, ui_widgets); // % Mana Filling @@ -628,8 +702,8 @@ impl Hud { ], MANA_COLOR, ) - .x_y(4.5, -28.0) - .position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) + .x_y(4.5 + (energy_percentage / 100.0 * 36.5) - 36.45, -28.0) + .position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) .resolution(100.0) .set(mana_bar_id, ui_widgets); @@ -638,42 +712,426 @@ impl Hud { .w_h(84.0, 10.0) .x_y(0.0, -25.0) .color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.99))) - .position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) + .position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) .resolution(100.0) .set(front_id, ui_widgets); + + // Enemy SCT + if let Some(HpFloaterList { floaters, .. }) = hp_floater_list + .filter(|fl| !fl.floaters.is_empty() && global_state.settings.gameplay.sct) + { + // Colors + const WHITE: Rgb = Rgb::new(1.0, 0.9, 0.8); + const LIGHT_OR: Rgb = Rgb::new(1.0, 0.925, 0.749); + const LIGHT_MED_OR: Rgb = Rgb::new(1.0, 0.85, 0.498); + const MED_OR: Rgb = Rgb::new(1.0, 0.776, 0.247); + const DARK_ORANGE: Rgb = Rgb::new(1.0, 0.7, 0.0); + const RED_ORANGE: Rgb = Rgb::new(1.0, 0.349, 0.0); + const DAMAGE_COLORS: [Rgb; 6] = [ + WHITE, + LIGHT_OR, + LIGHT_MED_OR, + MED_OR, + DARK_ORANGE, + RED_ORANGE, + ]; + // Largest value that select the first color is 40, then it shifts colors + // every 5 + let font_col = |font_size: u32| { + DAMAGE_COLORS[(font_size.saturating_sub(36) / 5).min(5) as usize] + }; + + if global_state.settings.gameplay.sct_damage_batch { + let number_speed = 50.0; // Damage number speed + let sct_bg_id = sct_bg_id_walker + .next(&mut self.ids.sct_bgs, &mut ui_widgets.widget_id_generator()); + let sct_id = sct_id_walker + .next(&mut self.ids.scts, &mut ui_widgets.widget_id_generator()); + // Calculate total change + // Ignores healing + let hp_damage = floaters.iter().fold(0, |acc, f| { + if f.hp_change < 0 { + acc + f.hp_change + } else { + acc + } + }); + let max_hp_frac = hp_damage.abs() as f32 / stats.health.maximum() as f32; + let timer = floaters + .last() + .expect("There must be at least one floater") + .timer; + // Increase font size based on fraction of maximum health + // "flashes" by having a larger size in the first 100ms + let font_size = 30 + + (max_hp_frac * 30.0) as u32 + + if timer < 0.1 { + (FLASH_MAX * (1.0 - timer / 0.1)) as u32 + } else { + 0 + }; + let font_col = font_col(font_size); + // Timer sets the widget offset + let y = (timer as f64 / crate::ecs::sys::floater::HP_SHOWTIME as f64 + * number_speed) + + 30.0; + // Timer sets text transparency + let fade = ((crate::ecs::sys::floater::HP_SHOWTIME - timer) * 0.25) + 0.2; + + Text::new(&format!("{}", (hp_damage).abs())) + .font_size(font_size) + .color(Color::Rgba(0.0, 0.0, 0.0, fade)) + .x_y(0.0, y - 3.0) + .position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale as f32 + 1.8)) + .fixed_scale() + .resolution(100.0) + .set(sct_bg_id, ui_widgets); + Text::new(&format!("{}", hp_damage.abs())) + .font_size(font_size) + .x_y(0.0, y) + .color(if hp_damage < 0 { + Color::Rgba(font_col.r, font_col.g, font_col.b, fade) + } else { + Color::Rgba(0.1, 1.0, 0.1, fade) + }) + .position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale as f32 + 1.8)) + .fixed_scale() + .resolution(100.0) + .set(sct_id, ui_widgets); + } else { + for floater in floaters { + let number_speed = 250.0; // Single Numbers Speed + let sct_bg_id = sct_bg_id_walker + .next(&mut self.ids.sct_bgs, &mut ui_widgets.widget_id_generator()); + let sct_id = sct_id_walker + .next(&mut self.ids.scts, &mut ui_widgets.widget_id_generator()); + // Calculate total change + let max_hp_frac = + floater.hp_change.abs() as f32 / stats.health.maximum() as f32; + // Increase font size based on fraction of maximum health + // "flashes" by having a larger size in the first 100ms + let font_size = 30 + + (max_hp_frac * 30.0) as u32 + + if floater.timer < 0.1 { + (FLASH_MAX * (1.0 - floater.timer / 0.1)) as u32 + } else { + 0 + }; + let font_col = font_col(font_size); + // Timer sets the widget offset + let y = (floater.timer as f64 + / crate::ecs::sys::floater::HP_SHOWTIME as f64 + * number_speed) + + 30.0; + // Timer sets text transparency + let fade = ((crate::ecs::sys::floater::HP_SHOWTIME - floater.timer) + * 0.25) + + 0.2; + + Text::new(&format!("{}", (floater.hp_change).abs())) + .font_size(font_size) + .color(if floater.hp_change < 0 { + Color::Rgba(0.0, 0.0, 0.0, fade) + } else { + Color::Rgba(0.1, 1.0, 0.1, 0.0) + }) + .x_y(0.0, y - 3.0) + .position_ingame( + pos + Vec3::new(0.0, 0.0, 1.5 * scale as f32 + 1.8), + ) + .fixed_scale() + .resolution(100.0) + .set(sct_bg_id, ui_widgets); + Text::new(&format!("{}", (floater.hp_change).abs())) + .font_size(font_size) + .x_y(0.0, y) + .color(if floater.hp_change < 0 { + Color::Rgba(font_col.r, font_col.g, font_col.b, fade) + } else { + Color::Rgba(0.1, 1.0, 0.1, 0.0) + }) + .position_ingame( + pos + Vec3::new(0.0, 0.0, 1.5 * scale as f32 + 1.8), + ) + .fixed_scale() + .resolution(100.0) + .set(sct_id, ui_widgets); + } + } + } + } + + if global_state.settings.gameplay.sct { + // Render Player SCT numbers + let mut player_sct_bg_id_walker = self.ids.player_sct_bgs.walk(); + let mut player_sct_id_walker = self.ids.player_scts.walk(); + if let (Some(HpFloaterList { floaters, .. }), Some(stats)) = ( + hp_floater_lists + .get(me) + .filter(|fl| !fl.floaters.is_empty()), + stats.get(me), + ) { + if global_state.settings.gameplay.sct_player_batch { + let number_speed = 100.0; // Player Batched Numbers Speed + let player_sct_bg_id = player_sct_bg_id_walker.next( + &mut self.ids.player_sct_bgs, + &mut ui_widgets.widget_id_generator(), + ); + let player_sct_id = player_sct_id_walker.next( + &mut self.ids.player_scts, + &mut ui_widgets.widget_id_generator(), + ); + // Calculate total change + // Ignores healing + let hp_damage = floaters.iter().fold(0, |acc, f| f.hp_change.min(0) + acc); + let max_hp_frac = hp_damage.abs() as f32 / stats.health.maximum() as f32; + let timer = floaters + .last() + .expect("There must be at least one floater") + .timer; + // Increase font size based on fraction of maximum health + // "flashes" by having a larger size in the first 100ms + let font_size = 30 + + (max_hp_frac * 30.0) as u32 + + if timer < 0.1 { + (FLASH_MAX * (1.0 - timer / 0.1)) as u32 + } else { + 0 + }; + // Timer sets the widget offset + let y = timer as f64 * number_speed * -1.0; + // Timer sets text transparency + let hp_fade = + ((crate::ecs::sys::floater::MY_HP_SHOWTIME - timer) * 0.25) + 0.2; + Text::new(&format!("{}", (hp_damage).abs())) + .font_size(font_size) + .color(Color::Rgba(0.0, 0.0, 0.0, hp_fade)) + .mid_bottom_with_margin_on(ui_widgets.window, 297.0 + y) + .set(player_sct_bg_id, ui_widgets); + Text::new(&format!("{}", (hp_damage).abs())) + .font_size(font_size) + .color(if hp_damage < 0 { + Color::Rgba(1.0, 0.1, 0.0, hp_fade) + } else { + Color::Rgba(0.1, 1.0, 0.1, 0.0) + }) + .mid_bottom_with_margin_on(ui_widgets.window, 300.0 + y) + .set(player_sct_id, ui_widgets); + }; + for floater in floaters { + // Healing always single numbers so just skip damage when in batch mode + + if global_state.settings.gameplay.sct_player_batch && floater.hp_change < 0 + { + continue; + } + let number_speed = 50.0; // Player Heal Speed + let player_sct_bg_id = player_sct_bg_id_walker.next( + &mut self.ids.player_sct_bgs, + &mut ui_widgets.widget_id_generator(), + ); + let player_sct_id = player_sct_id_walker.next( + &mut self.ids.player_scts, + &mut ui_widgets.widget_id_generator(), + ); + let max_hp_frac = + floater.hp_change.abs() as f32 / stats.health.maximum() as f32; + // Increase font size based on fraction of maximum health + // "flashes" by having a larger size in the first 100ms + let font_size = 30 + + (max_hp_frac * 30.0) as u32 + + if floater.timer < 0.1 { + (FLASH_MAX * (1.0 - floater.timer / 0.1)) as u32 + } else { + 0 + }; + // Timer sets the widget offset + let y = if floater.hp_change < 0 { + floater.timer as f64 + * number_speed + * floater.hp_change.signum() as f64 + //* -1.0 + + 300.0 + - ui_widgets.win_h * 0.5 + } else { + floater.timer as f64 + * number_speed + * floater.hp_change.signum() as f64 + * -1.0 + + 300.0 + - ui_widgets.win_h * 0.5 + }; + // Healing is offset randomly + let x = if floater.hp_change < 0 { + 0.0 + } else { + (floater.rand as f64 - 0.5) * 0.2 * ui_widgets.win_w + }; + // Timer sets text transparency + let hp_fade = ((crate::ecs::sys::floater::MY_HP_SHOWTIME - floater.timer) + * 0.25) + + 0.2; + Text::new(&format!("{}", (floater.hp_change).abs())) + .font_size(font_size) + .color(Color::Rgba(0.0, 0.0, 0.0, hp_fade)) + .x_y(x, y - 3.0) + .set(player_sct_bg_id, ui_widgets); + Text::new(&format!("{}", (floater.hp_change).abs())) + .font_size(font_size) + .color(if floater.hp_change < 0 { + Color::Rgba(1.0, 0.1, 0.0, hp_fade) + } else { + Color::Rgba(0.1, 1.0, 0.1, hp_fade) + }) + .x_y(x, y) + .set(player_sct_id, ui_widgets); + } + } + // EXP Numbers + if let (Some(floaters), Some(stats)) = ( + Some(&*ecs.read_resource::()) + .map(|l| &l.floaters) + .filter(|f| !f.is_empty()), + stats.get(me), + ) { + // TODO replace with setting + let batched_sct = false; + if batched_sct { + let number_speed = 50.0; // Number Speed for Cumulated EXP + let player_sct_bg_id = player_sct_bg_id_walker.next( + &mut self.ids.player_sct_bgs, + &mut ui_widgets.widget_id_generator(), + ); + let player_sct_id = player_sct_id_walker.next( + &mut self.ids.player_scts, + &mut ui_widgets.widget_id_generator(), + ); + // Sum xp change + let exp_change = floaters.iter().fold(0, |acc, f| f.exp_change + acc); + // Can't fail since we filtered out empty lists above + let (timer, rand) = floaters + .last() + .map(|f| (f.timer, f.rand)) + .expect("Impossible"); + // Increase font size based on fraction of maximum health + // "flashes" by having a larger size in the first 100ms + let font_size_xp = 30 + + (exp_change.abs() as f32 / stats.exp.maximum() as f32 * 50.0) as u32 + + if timer < 0.1 { + (FLASH_MAX * (1.0 - timer / 0.1)) as u32 + } else { + 0 + }; + + let y = timer as f64 * number_speed; // Timer sets the widget offset + let fade = ((4.0 - timer as f32) * 0.25) + 0.2; // Timer sets text transparency + + Text::new(&format!("{} Exp", exp_change)) + .font_size(font_size_xp) + .color(Color::Rgba(0.0, 0.0, 0.0, fade)) + .x_y( + ui_widgets.win_w * (0.5 * rand.0 as f64 - 0.25), + ui_widgets.win_h * (0.15 * rand.1 as f64) + y - 3.0, + ) + .set(player_sct_bg_id, ui_widgets); + Text::new(&format!("{} Exp", exp_change)) + .font_size(font_size_xp) + .color(Color::Rgba(0.59, 0.41, 0.67, fade)) + .x_y( + ui_widgets.win_w * (0.5 * rand.0 as f64 - 0.25), + ui_widgets.win_h * (0.15 * rand.1 as f64) + y, + ) + .set(player_sct_id, ui_widgets); + } else { + for floater in floaters { + let number_speed = 50.0; // Number Speed for Single EXP + let player_sct_bg_id = player_sct_bg_id_walker.next( + &mut self.ids.player_sct_bgs, + &mut ui_widgets.widget_id_generator(), + ); + let player_sct_id = player_sct_id_walker.next( + &mut self.ids.player_scts, + &mut ui_widgets.widget_id_generator(), + ); + // Increase font size based on fraction of maximum health + // "flashes" by having a larger size in the first 100ms + let font_size_xp = 30 + + (floater.exp_change.abs() as f32 / stats.exp.maximum() as f32 + * 50.0) as u32 + + if floater.timer < 0.1 { + (FLASH_MAX * (1.0 - floater.timer / 0.1)) as u32 + } else { + 0 + }; + + let y = floater.timer as f64 * number_speed; // Timer sets the widget offset + let fade = ((4.0 - floater.timer as f32) * 0.25) + 0.2; // Timer sets text transparency + + Text::new(&format!("{} Exp", floater.exp_change)) + .font_size(font_size_xp) + .color(Color::Rgba(0.0, 0.0, 0.0, fade)) + .x_y( + ui_widgets.win_w * (0.5 * floater.rand.0 as f64 - 0.25), + ui_widgets.win_h * (0.15 * floater.rand.1 as f64) + y - 3.0, + ) + .set(player_sct_bg_id, ui_widgets); + Text::new(&format!("{} Exp", floater.exp_change)) + .font_size(font_size_xp) + .color(Color::Rgba(0.59, 0.41, 0.67, fade)) + .x_y( + ui_widgets.win_w * (0.5 * floater.rand.0 as f64 - 0.25), + ui_widgets.win_h * (0.15 * floater.rand.1 as f64) + y, + ) + .set(player_sct_id, ui_widgets); + } + } + } } // Render Name Tags - for (pos, name, level, scale) in - (&entities, &pos, &stats, players.maybe(), scales.maybe()) - .join() - .filter(|(entity, _, stats, _, _)| *entity != me && !stats.is_dead) - // Don't process nametags outside the vd (visibility further limited by ui backend) - .filter(|(_, pos, _, _, _)| { - Vec2::from(pos.0 - player_pos) - .map2(TerrainChunk::RECT_SIZE, |d: f32, sz| { - d.abs() as f32 / sz as f32 - }) - .magnitude() - < view_distance as f32 - }) - .map(|(_, pos, stats, player, scale)| { - // TODO: This is temporary - // If the player used the default character name display their name instead - let name = if stats.name == "Character Name" { - player.map_or(&stats.name, |p| &p.alias) - } else { - &stats.name - }; - (pos.0, name, stats.level, scale) - }) + for (pos, name, level, scale) in ( + &entities, + &pos, + interpolated.maybe(), + &stats, + players.maybe(), + scales.maybe(), + ) + .join() + .filter(|(entity, _, _, stats, _, _)| *entity != me && !stats.is_dead) + // Don't process nametags outside the vd (visibility further limited by ui backend) + .filter(|(_, pos, _, _, _, _)| { + Vec2::from(pos.0 - player_pos) + .map2(TerrainChunk::RECT_SIZE, |d: f32, sz| { + d.abs() as f32 / sz as f32 + }) + .magnitude() + < view_distance as f32 + }) + .map(|(_, pos, interpolated, stats, player, scale)| { + // TODO: This is temporary + // If the player used the default character name display their name instead + let name = if stats.name == "Character Name" { + player.map_or(&stats.name, |p| &p.alias) + } else { + &stats.name + }; + ( + interpolated.map_or(pos.0, |i| i.pos), + format!("{}", name), + stats.level, + scale.map_or(1.0, |s| s.0), + ) + }) { - let name = format!("{}", name); - let scale = scale.map(|s| s.0).unwrap_or(1.0); let name_id = name_id_walker.next( &mut self.ids.name_tags, &mut ui_widgets.widget_id_generator(), ); + let name_bg_id = name_id_bg_walker.next( + &mut self.ids.name_tags_bgs, + &mut ui_widgets.widget_id_generator(), + ); let level_id = level_id_walker .next(&mut self.ids.levels, &mut ui_widgets.widget_id_generator()); let level_skull_id = level_skull_id_walker.next( @@ -682,6 +1140,13 @@ impl Hud { ); // Name + Text::new(&name) + .font_size(20) + .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) + .x_y(-1.0, -1.0) + .position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) + .resolution(100.0) + .set(name_bg_id, ui_widgets); Text::new(&name) .font_size(20) .color(Color::Rgba(0.61, 0.61, 0.89, 1.0)) @@ -726,15 +1191,16 @@ impl Hud { } else { self.imgs.skull }) - .w_h(30.0, 30.0) - .x_y(0.0, 24.0) - .color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.8))) + .w_h(18.0, 18.0) + .x_y(-39.0, -25.0) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))) .position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) .resolution(100.0) .set(level_skull_id, ui_widgets); } } } + // Introduction Text let intro_text: &'static str = "Welcome to the Veloren Alpha!\n\ @@ -906,7 +1372,7 @@ impl Hud { } // Display debug window. - if self.show.debug { + if global_state.settings.gameplay.toggle_debug { // Alpha Version Text::new(&version) .top_left_with_margins_on(ui_widgets.window, 5.0, 5.0) @@ -1018,12 +1484,46 @@ impl Hud { .set(self.ids.num_figures, ui_widgets); // Help Window - Text::new("Press 'F1' to show Keybindings") - .color(TEXT_COLOR) - .down_from(self.ids.num_figures, 5.0) - .font_id(self.fonts.cyri) - .font_size(14) - .set(self.ids.help_info, ui_widgets); + Text::new(&format!( + "Press {:?} to show keybindings", + global_state.settings.controls.help + )) + .color(TEXT_COLOR) + .down_from(self.ids.num_figures, 5.0) + .font_id(self.fonts.cyri) + .font_size(14) + .set(self.ids.help_info, ui_widgets); + // Info about Debug Shortcut + Text::new(&format!( + "Press {:?} to toggle debug info", + global_state.settings.controls.toggle_debug + )) + .color(TEXT_COLOR) + .down_from(self.ids.help_info, 5.0) + .font_id(self.fonts.cyri) + .font_size(14) + .set(self.ids.debug_info, ui_widgets); + } else { + // Help Window + Text::new(&format!( + "Press {:?} to show keybindings", + global_state.settings.controls.help + )) + .color(TEXT_COLOR) + .top_left_with_margins_on(ui_widgets.window, 5.0, 5.0) + .font_id(self.fonts.cyri) + .font_size(16) + .set(self.ids.help_info, ui_widgets); + // Info about Debug Shortcut + Text::new(&format!( + "Press {:?} to toggle debug info", + global_state.settings.controls.toggle_debug + )) + .color(TEXT_COLOR) + .down_from(self.ids.help_info, 5.0) + .font_id(self.fonts.cyri) + .font_size(12) + .set(self.ids.debug_info, ui_widgets); } // Add Bag-Space Button. @@ -1185,6 +1685,15 @@ impl Hud { .set(self.ids.settings_window, ui_widgets) { match event { + settings_window::Event::Sct(sct) => { + events.push(Event::Sct(sct)); + } + settings_window::Event::SctPlayerBatch(sct_player_batch) => { + events.push(Event::SctPlayerBatch(sct_player_batch)); + } + settings_window::Event::SctDamageBatch(sct_damage_batch) => { + events.push(Event::SctDamageBatch(sct_damage_batch)); + } settings_window::Event::ToggleHelp => self.show.help = !self.show.help, settings_window::Event::ToggleDebug => self.show.debug = !self.show.debug, settings_window::Event::ChangeTab(tab) => self.show.open_setting_tab(tab), @@ -1319,6 +1828,7 @@ impl Hud { self.world_map, &self.fonts, self.pulse, + self.velocity, ) .set(self.ids.map, ui_widgets) { @@ -1471,7 +1981,8 @@ impl Hud { true } GameInput::ToggleDebug => { - self.show.debug = !self.show.debug; + global_state.settings.gameplay.toggle_debug = + !global_state.settings.gameplay.toggle_debug; true } GameInput::ToggleIngameUi => { diff --git a/voxygen/src/hud/settings_window.rs b/voxygen/src/hud/settings_window.rs index b63678dc58..011d8bc0ca 100644 --- a/voxygen/src/hud/settings_window.rs +++ b/voxygen/src/hud/settings_window.rs @@ -18,6 +18,7 @@ const FPS_CHOICES: [u32; 11] = [15, 30, 40, 50, 60, 90, 120, 144, 240, 300, 500] widget_ids! { struct Ids { settings_content, + settings_content_r, settings_icon, settings_button_mo, settings_close, @@ -109,7 +110,24 @@ widget_ids! { placeholder, chat_transp_title, chat_transp_text, - chat_transp_slider + chat_transp_slider, + sct_title, + sct_show_text, + sct_show_radio, + sct_single_dmg_text, + sct_single_dmg_radio, + sct_show_batch_text, + sct_show_batch_radio, + sct_batched_dmg_text, + sct_batched_dmg_radio, + sct_inc_dmg_text, + sct_inc_dmg_radio, + sct_batch_inc_text, + sct_batch_inc_radio, + sct_num_dur_text, + sct_num_dur_slider, + sct_num_dur_value, + } } @@ -178,6 +196,9 @@ pub enum Event { CrosshairType(CrosshairType), UiScale(ScaleChange), ChatTransp(f32), + Sct(bool), + SctPlayerBatch(bool), + SctDamageBatch(bool), } pub enum ScaleChange { @@ -229,6 +250,10 @@ impl<'a> Widget for SettingsWindow<'a> { .scroll_kids() .scroll_kids_vertically() .set(state.ids.settings_content, ui); + Rectangle::fill_with([198.0 * 4.0 * 0.5, 97.0 * 4.0], color::TRANSPARENT) + .top_right_with_margins_on(state.ids.settings_content, 0.0, 0.0) + .parent(state.ids.settings_content) + .set(state.ids.settings_content_r, ui); Scrollbar::y_axis(state.ids.settings_content) .thickness(5.0) .rgba(0.33, 0.33, 0.33, 1.0) @@ -279,7 +304,7 @@ impl<'a> Widget for SettingsWindow<'a> { events.push(Event::ChangeTab(SettingsTab::Interface)); } - // Contents + // Contents Left Side if let SettingsTab::Interface = self.show.settings_tab { let crosshair_transp = self.global_state.settings.gameplay.crosshair_transp; let crosshair_type = self.global_state.settings.gameplay.crosshair_type; @@ -309,7 +334,7 @@ impl<'a> Widget for SettingsWindow<'a> { events.push(Event::ToggleHelp); } - Text::new("Show Help Window") + Text::new("Help Window") .right_from(state.ids.button_help, 10.0) .font_size(14) .font_id(self.fonts.cyri) @@ -333,7 +358,7 @@ impl<'a> Widget for SettingsWindow<'a> { events.push(Event::ToggleDebug); } - Text::new("Show Debug Info") + Text::new("Debug Info") .right_from(state.ids.debug_button, 10.0) .font_size(14) .font_id(self.fonts.cyri) @@ -360,7 +385,7 @@ impl<'a> Widget for SettingsWindow<'a> { Intro::Never => events.push(Event::Intro(Intro::Show)), } }; - Text::new("Show Tips on Startup") + Text::new("Tips on Startup") .right_from(state.ids.tips_button, 10.0) .font_size(14) .font_id(self.fonts.cyri) @@ -683,7 +708,7 @@ impl<'a> Widget for SettingsWindow<'a> { XpBar::OnGain => events.push(Event::ToggleXpBar(XpBar::Always)), } } - Text::new("Always show Experience Bar") + Text::new("Toggle Experience Bar") .right_from(state.ids.show_xpbar_button, 10.0) .font_size(14) .font_id(self.fonts.cyri) @@ -717,7 +742,7 @@ impl<'a> Widget for SettingsWindow<'a> { } } } - Text::new("Always show Shortcuts") + Text::new("Toggle Shortcuts") .right_from(state.ids.show_shortcuts_button, 10.0) .font_size(14) .font_id(self.fonts.cyri) @@ -725,10 +750,151 @@ impl<'a> Widget for SettingsWindow<'a> { .color(TEXT_COLOR) .set(state.ids.show_shortcuts_text, ui); + Rectangle::fill_with([60.0 * 4.0, 1.0 * 4.0], color::TRANSPARENT) + .down_from(state.ids.show_shortcuts_text, 30.0) + .set(state.ids.placeholder, ui); + + // Content Right Side + + /*Scrolling Combat text + + O Show Damage Numbers + O Show single Damage Numbers + O Show batched dealt Damage + O Show incoming Damage + O Batch incoming Numbers + + Number Display Duration: 1s ----I----5s + */ + // SCT/ Scrolling Combat Text + Text::new("Scrolling Combat Text") + .top_left_with_margins_on(state.ids.settings_content_r, 5.0, 5.0) + .font_size(18) + .font_id(self.fonts.cyri) + .color(TEXT_COLOR) + .set(state.ids.sct_title, ui); + // Generally toggle the SCT + let show_sct = ToggleButton::new( + self.global_state.settings.gameplay.sct, + self.imgs.checkbox, + self.imgs.checkbox_checked, + ) + .w_h(18.0, 18.0) + .down_from(state.ids.sct_title, 20.0) + .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo) + .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked) + .set(state.ids.sct_show_radio, ui); + + if self.global_state.settings.gameplay.sct != show_sct { + events.push(Event::Sct(!self.global_state.settings.gameplay.sct)) + } + Text::new("Scrolling Combat Text") + .right_from(state.ids.sct_show_radio, 10.0) + .font_size(14) + .font_id(self.fonts.cyri) + .graphics_for(state.ids.sct_show_radio) + .color(TEXT_COLOR) + .set(state.ids.sct_show_text, ui); + if self.global_state.settings.gameplay.sct { + // Toggle single damage numbers + let show_sct_damage_batch = !ToggleButton::new( + !self.global_state.settings.gameplay.sct_damage_batch, + self.imgs.checkbox, + self.imgs.checkbox_checked, + ) + .w_h(18.0, 18.0) + .down_from(state.ids.sct_show_text, 8.0) + .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo) + .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked) + .set(state.ids.sct_single_dmg_radio, ui); + + Text::new("Single Damage Numbers") + .right_from(state.ids.sct_single_dmg_radio, 10.0) + .font_size(14) + .font_id(self.fonts.cyri) + .graphics_for(state.ids.sct_single_dmg_radio) + .color(TEXT_COLOR) + .set(state.ids.sct_single_dmg_text, ui); + // Toggle Batched Damage + let show_sct_damage_batch = ToggleButton::new( + show_sct_damage_batch, + self.imgs.checkbox, + self.imgs.checkbox_checked, + ) + .w_h(18.0, 18.0) + .down_from(state.ids.sct_single_dmg_radio, 8.0) + .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo) + .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked) + .set(state.ids.sct_show_batch_radio, ui); + + if self.global_state.settings.gameplay.sct_damage_batch != show_sct_damage_batch { + events.push(Event::SctDamageBatch( + !self.global_state.settings.gameplay.sct_damage_batch, + )) + } + Text::new("Cumulated Damage") + .right_from(state.ids.sct_show_batch_radio, 10.0) + .font_size(14) + .font_id(self.fonts.cyri) + .graphics_for(state.ids.sct_batched_dmg_radio) + .color(TEXT_COLOR) + .set(state.ids.sct_show_batch_text, ui); + // Toggle Incoming Damage + let show_sct_player_batch = !ToggleButton::new( + !self.global_state.settings.gameplay.sct_player_batch, + self.imgs.checkbox, + self.imgs.checkbox_checked, + ) + .w_h(18.0, 18.0) + .down_from(state.ids.sct_show_batch_radio, 8.0) + .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo) + .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked) + .set(state.ids.sct_inc_dmg_radio, ui); + + Text::new("Incoming Damage") + .right_from(state.ids.sct_inc_dmg_radio, 10.0) + .font_size(14) + .font_id(self.fonts.cyri) + .graphics_for(state.ids.sct_inc_dmg_radio) + .color(TEXT_COLOR) + .set(state.ids.sct_inc_dmg_text, ui); + // Toggle Batched Incoming Damage + let show_sct_player_batch = ToggleButton::new( + show_sct_player_batch, + self.imgs.checkbox, + self.imgs.checkbox_checked, + ) + .w_h(18.0, 18.0) + .down_from(state.ids.sct_inc_dmg_radio, 8.0) + .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo) + .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked) + .set(state.ids.sct_batch_inc_radio, ui); + + if self.global_state.settings.gameplay.sct_player_batch != show_sct_player_batch { + events.push(Event::SctPlayerBatch( + !self.global_state.settings.gameplay.sct_player_batch, + )) + } + Text::new("Cumulated Incoming Damage") + .right_from(state.ids.sct_batch_inc_radio, 10.0) + .font_size(14) + .font_id(self.fonts.cyri) + .graphics_for(state.ids.sct_batch_inc_radio) + .color(TEXT_COLOR) + .set(state.ids.sct_batch_inc_text, ui); + } + // Energybars Numbers // Hotbar text Text::new("Energybar Numbers") - .down_from(state.ids.show_shortcuts_button, 20.0) + .down_from( + if self.global_state.settings.gameplay.sct { + state.ids.sct_batch_inc_radio + } else { + state.ids.sct_show_radio + }, + 20.0, + ) .font_size(18) .font_id(self.fonts.cyri) .color(TEXT_COLOR) @@ -857,9 +1023,6 @@ impl<'a> Widget for SettingsWindow<'a> { { events.push(Event::ChatTransp(new_val)); } - Rectangle::fill_with([60.0 * 4.0, 1.0 * 4.0], color::TRANSPARENT) - .down_from(state.ids.chat_transp_title, 30.0) - .set(state.ids.placeholder, ui); } // 2) Gameplay Tab -------------------------------- diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index ff536fc45e..6b72c9ccee 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -70,14 +70,19 @@ widget_ids! { healthbar_bg, healthbar_filling, health_text, + health_text_bg, energybar_bg, energybar_filling, energy_text, + energy_text_bg, level_up, level_down, level_align, level_message, + level_message_bg, stamina_wheel, + death_bg, + hurt_bg, } } @@ -215,7 +220,7 @@ impl<'a> Widget for Skillbar<'a> { // Update last_value state.update(|s| s.last_level = current_level); state.update(|s| s.last_update_level = Instant::now()); - } + }; let seconds_level = state.last_update_level.elapsed().as_secs_f32(); let fade_level = if current_level == 1 { @@ -236,6 +241,12 @@ impl<'a> Widget for Skillbar<'a> { .middle_of(state.ids.level_align) .font_size(30) .font_id(self.fonts.cyri) + .color(Color::Rgba(0.0, 0.0, 0.0, fade_level)) + .set(state.ids.level_message_bg, ui); + Text::new(&level_up_text) + .bottom_left_with_margins_on(state.ids.level_message_bg, 2.0, 2.0) + .font_size(30) + .font_id(self.fonts.cyri) .color(Color::Rgba(1.0, 1.0, 1.0, fade_level)) .set(state.ids.level_message, ui); Image::new(self.imgs.level_up) @@ -251,35 +262,38 @@ impl<'a> Widget for Skillbar<'a> { .graphics_for(state.ids.level_align) .set(state.ids.level_down, ui); // Death message - if hp_percentage == 0.0 { + if self.stats.is_dead { Text::new("You Died") - .mid_top_with_margin_on(ui.window, 60.0) - .font_size(40) + .middle_of(ui.window) + .font_size(50) .font_id(self.fonts.cyri) .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) .set(state.ids.death_message_1_bg, ui); Text::new(&format!( - "Press {:?} to respawn.", + "Press {:?} to respawn at your Waypoint.\n\ + \n\ + Press Enter, type in /waypoint and confirm to set it here.", self.global_state.settings.controls.respawn )) - .mid_bottom_with_margin_on(state.ids.death_message_1, -30.0) - .font_size(15) + .mid_bottom_with_margin_on(state.ids.death_message_1_bg, -120.0) + .font_size(30) .font_id(self.fonts.cyri) .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) .set(state.ids.death_message_2_bg, ui); - Text::new("You Died") - .top_left_with_margins_on(state.ids.death_message_1_bg, -2.0, -2.0) - .font_size(40) + .bottom_left_with_margins_on(state.ids.death_message_1_bg, 2.0, 2.0) + .font_size(50) .font_id(self.fonts.cyri) .color(CRITICAL_HP_COLOR) .set(state.ids.death_message_1, ui); Text::new(&format!( - "Press {:?} to respawn.", + "Press {:?} to respawn at your Waypoint.\n\ + \n\ + Press Enter, type in /waypoint and confirm to set it here.", self.global_state.settings.controls.respawn )) - .top_left_with_margins_on(state.ids.death_message_2_bg, -1.5, -1.5) - .font_size(15) + .bottom_left_with_margins_on(state.ids.death_message_2_bg, 2.0, 2.0) + .font_size(30) .color(CRITICAL_HP_COLOR) .set(state.ids.death_message_2, ui); } @@ -812,7 +826,13 @@ impl<'a> Widget for Skillbar<'a> { self.stats.health.maximum() as u32 ); Text::new(&hp_text) - .mid_top_with_margin_on(state.ids.healthbar_bg, 5.0 * scale) + .mid_top_with_margin_on(state.ids.healthbar_bg, 6.0 * scale) + .font_size(14) + .font_id(self.fonts.cyri) + .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) + .set(state.ids.health_text_bg, ui); + Text::new(&hp_text) + .bottom_left_with_margins_on(state.ids.health_text_bg, 2.0, 2.0) .font_size(14) .font_id(self.fonts.cyri) .color(TEXT_COLOR) @@ -823,7 +843,13 @@ impl<'a> Widget for Skillbar<'a> { self.stats.energy.maximum() as u32 ); Text::new(&energy_text) - .mid_top_with_margin_on(state.ids.energybar_bg, 5.0 * scale) + .mid_top_with_margin_on(state.ids.energybar_bg, 6.0 * scale) + .font_size(14) + .font_id(self.fonts.cyri) + .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) + .set(state.ids.energy_text_bg, ui); + Text::new(&energy_text) + .bottom_left_with_margins_on(state.ids.energy_text_bg, 2.0, 2.0) .font_size(14) .font_id(self.fonts.cyri) .color(TEXT_COLOR) @@ -833,14 +859,26 @@ impl<'a> Widget for Skillbar<'a> { if let BarNumbers::Percent = bar_values { let hp_text = format!("{}%", hp_percentage as u32); Text::new(&hp_text) - .mid_top_with_margin_on(state.ids.healthbar_bg, 5.0 * scale) + .mid_top_with_margin_on(state.ids.healthbar_bg, 6.0 * scale) + .font_size(14) + .font_id(self.fonts.cyri) + .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) + .set(state.ids.health_text_bg, ui); + Text::new(&hp_text) + .bottom_left_with_margins_on(state.ids.health_text_bg, 2.0, 2.0) .font_size(14) .font_id(self.fonts.cyri) .color(TEXT_COLOR) .set(state.ids.health_text, ui); let energy_text = format!("{}%", energy_percentage as u32); Text::new(&energy_text) - .mid_top_with_margin_on(state.ids.energybar_bg, 5.0 * scale) + .mid_top_with_margin_on(state.ids.energybar_bg, 6.0 * scale) + .font_size(14) + .font_id(self.fonts.cyri) + .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) + .set(state.ids.energy_text_bg, ui); + Text::new(&energy_text) + .bottom_left_with_margins_on(state.ids.energy_text_bg, 2.0, 2.0) .font_size(14) .font_id(self.fonts.cyri) .color(TEXT_COLOR) diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index 70ade6247a..b6fac4e48b 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -16,6 +16,7 @@ use std::sync::Mutex; pub mod ui; pub mod anim; pub mod audio; +mod ecs; pub mod error; pub mod hud; pub mod key_state; diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index a80b8acbde..62af6386e9 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -108,11 +108,11 @@ impl PlayState for CharSelectionState { .render(global_state.window.renderer_mut(), self.scene.globals()); // Tick the client (currently only to keep the connection alive). - if let Err(err) = self - .client - .borrow_mut() - .tick(comp::ControllerInputs::default(), clock.get_last_delta()) - { + if let Err(err) = self.client.borrow_mut().tick( + comp::ControllerInputs::default(), + clock.get_last_delta(), + |_| {}, + ) { global_state.info_message = Some( "Connection lost!\nDid the server restart?\nIs the client up to date?" .to_owned(), diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index f972819a3b..511341e14e 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -69,8 +69,10 @@ impl PlayState for MainMenuState { // Poll client creation. match client_init.as_ref().and_then(|init| init.poll()) { - Some(Ok(client)) => { + Some(Ok(mut client)) => { self.main_menu_ui.connected(); + // Register voxygen components / resources + crate::ecs::init(client.state_mut().ecs_mut()); return PlayStateResult::Push(Box::new(CharSelectionState::new( global_state, std::rc::Rc::new(std::cell::RefCell::new(client)), diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 5c62db41c1..5340c37184 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -1,3 +1,4 @@ +use crate::ui::Graphic; use crate::{ render::Renderer, ui::{ @@ -7,6 +8,7 @@ use crate::{ }, GlobalState, }; +use common::assets::load_expect; use conrod_core::{ color, color::TRANSPARENT, @@ -14,6 +16,7 @@ use conrod_core::{ widget::{text_box::Event as TextBoxEvent, Button, Image, List, Rectangle, Text, TextBox}, widget_ids, Borderable, Color, Colorable, Labelable, Positionable, Sizeable, Widget, }; +use rand::{seq::SliceRandom, thread_rng}; use std::time::Duration; widget_ids! { @@ -84,7 +87,6 @@ image_ids! { bg: "voxygen.background.bg_main", - load: "voxygen.background.bg_load", nothing: (), @@ -129,6 +131,7 @@ pub enum PopupType { Error, ConnectionInfo, } + pub struct PopupData { msg: String, button_text: String, @@ -150,6 +153,7 @@ pub struct MainMenuUi { show_servers: bool, show_disclaimer: bool, time: f32, + bg_img_id: conrod_core::image::Id, } impl MainMenuUi { @@ -157,6 +161,18 @@ impl MainMenuUi { let window = &mut global_state.window; let networking = &global_state.settings.networking; let gameplay = &global_state.settings.gameplay; + // Randomly loaded background images + let bg_imgs = [ + "voxygen.background.bg_1", + "voxygen.background.bg_2", + "voxygen.background.bg_3", + "voxygen.background.bg_4", + "voxygen.background.bg_5", + "voxygen.background.bg_6", + "voxygen.background.bg_7", + "voxygen.background.bg_8", + ]; + let mut rng = thread_rng(); let mut ui = Ui::new(window).unwrap(); ui.set_scaling_mode(gameplay.ui_scale); @@ -165,6 +181,9 @@ impl MainMenuUi { // Load images let imgs = Imgs::load(&mut ui).expect("Failed to load images"); let rot_imgs = ImgsRot::load(&mut ui).expect("Failed to load images!"); + let bg_img_id = ui.add_graphic(Graphic::Image(load_expect( + bg_imgs.choose(&mut rng).unwrap(), + ))); // Load fonts let fonts = Fonts::load(&mut ui).expect("Failed to load fonts"); @@ -183,6 +202,7 @@ impl MainMenuUi { connect: false, time: 0.0, show_disclaimer: global_state.settings.show_disclaimer, + bg_img_id, } } @@ -225,14 +245,14 @@ impl MainMenuUi { .desc_text_color(TEXT_COLOR_2); // Background image, Veloren logo, Alpha-Version Label - Image::new(if self.connect { - self.imgs.load + self.bg_img_id } else { self.imgs.bg }) .middle_of(ui_widgets.window) .set(self.ids.bg, ui_widgets); + // Version displayed top right corner Text::new(&version) .color(TEXT_COLOR) diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 8787def27a..1d89ed3e5f 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -43,10 +43,10 @@ impl Pipeline for UiPipeline { type Vertex = Vertex; } -impl From> for Locals { - fn from(pos: Vec3) -> Self { +impl From> for Locals { + fn from(pos: Vec4) -> Self { Self { - pos: [pos.x, pos.y, pos.z, 1.0], + pos: pos.into_array(), } } } diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 6887710b40..2ce0f36da9 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -1194,6 +1194,7 @@ impl FigureState { self.last_ori = Lerp::lerp(self.last_ori, ori, 15.0 * dt); // Update interpolation values + // TODO: use values from Interpolated component instead of recalculating if self.pos.distance_squared(pos) < 64.0 * 64.0 { self.pos = Lerp::lerp(self.pos, pos + vel * 0.03, 10.0 * dt); self.ori = Slerp::slerp(self.ori, ori, 5.0 * dt); @@ -1205,6 +1206,7 @@ impl FigureState { self.movement_time += (dt * movement_rate) as f64; self.action_time += (dt * action_rate) as f64; + // TODO: what are the interpolated ori values used for if not here??? let mat = Mat4::::identity() * Mat4::translation_3d(self.pos) * Mat4::rotation_z(-ori.x.atan2(ori.y)) diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 66aaacf40c..9be5180727 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -215,23 +215,31 @@ impl Scene { let mut lights = ( &client.state().ecs().read_storage::(), client.state().ecs().read_storage::().maybe(), + client + .state() + .ecs() + .read_storage::() + .maybe(), &client.state().ecs().read_storage::(), ) .join() - .filter(|(pos, _, _)| { + .filter(|(pos, _, _, _)| { (pos.0.distance_squared(player_pos) as f32) < self.loaded_distance.powf(2.0) + LIGHT_DIST_RADIUS }) - .map(|(pos, ori, light_emitter)| { + .map(|(pos, ori, interpolated, light_emitter)| { + // Use interpolated values if they are available + let (pos, ori) = + interpolated.map_or((pos.0, ori.map(|o| o.0)), |i| (i.pos, Some(i.ori))); let rot = { if let Some(o) = ori { - Mat3::rotation_z(-o.0.x.atan2(o.0.y)) + Mat3::rotation_z(-o.x.atan2(o.y)) } else { Mat3::identity() } }; Light::new( - pos.0 + (rot * light_emitter.offset), + pos + (rot * light_emitter.offset), light_emitter.col, light_emitter.strength, ) @@ -246,17 +254,28 @@ impl Scene { // Update shadow constants let mut shadows = ( &client.state().ecs().read_storage::(), + client + .state() + .ecs() + .read_storage::() + .maybe(), client.state().ecs().read_storage::().maybe(), &client.state().ecs().read_storage::(), &client.state().ecs().read_storage::(), ) .join() - .filter(|(_, _, _, stats)| !stats.is_dead) - .filter(|(pos, _, _, _)| { + .filter(|(_, _, _, _, stats)| !stats.is_dead) + .filter(|(pos, _, _, _, _)| { (pos.0.distance_squared(player_pos) as f32) < (self.loaded_distance.min(SHADOW_MAX_DIST) + SHADOW_DIST_RADIUS).powf(2.0) }) - .map(|(pos, scale, _, _)| Shadow::new(pos.0, scale.map(|s| s.0).unwrap_or(1.0))) + .map(|(pos, interpolated, scale, _, _)| { + Shadow::new( + // Use interpolated values pos if it is available + interpolated.map_or(pos.0, |i| i.pos), + scale.map_or(1.0, |s| s.0), + ) + }) .collect::>(); shadows.sort_by_key(|shadow| shadow.get_pos().distance_squared(player_pos) as i32); shadows.truncate(MAX_SHADOW_COUNT); diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index e3eb0bac70..ab37b411b9 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -1,4 +1,5 @@ use crate::{ + ecs::MyEntity, hud::{DebugInfo, Event as HudEvent, Hud}, key_state::KeyState, render::Renderer, @@ -40,6 +41,14 @@ impl SessionState { .camera_mut() .set_fov_deg(global_state.settings.graphics.fov); let hud = Hud::new(global_state, &client.borrow()); + { + let my_entity = client.borrow().entity(); + client + .borrow_mut() + .state_mut() + .ecs_mut() + .insert(MyEntity(my_entity)); + } Self { scene, client, @@ -55,7 +64,11 @@ impl SessionState { /// Tick the session (and the client attached to it). fn tick(&mut self, dt: Duration) -> Result<(), Error> { self.inputs.tick(dt); - for event in self.client.borrow_mut().tick(self.inputs.clone(), dt)? { + for event in self.client.borrow_mut().tick( + self.inputs.clone(), + dt, + crate::ecs::sys::add_local_systems, + )? { match event { Chat { chat_type: _, @@ -423,6 +436,22 @@ impl PlayState for SessionState { global_state.settings.gameplay.zoom_inversion = zoom_inverted; global_state.settings.save_to_file_warn(); } + HudEvent::Sct(sct) => { + global_state.settings.gameplay.sct = sct; + global_state.settings.save_to_file_warn(); + } + HudEvent::SctPlayerBatch(sct_player_batch) => { + global_state.settings.gameplay.sct_player_batch = sct_player_batch; + global_state.settings.save_to_file_warn(); + } + HudEvent::SctDamageBatch(sct_damage_batch) => { + global_state.settings.gameplay.sct_damage_batch = sct_damage_batch; + global_state.settings.save_to_file_warn(); + } + HudEvent::ToggleDebug(toggle_debug) => { + global_state.settings.gameplay.toggle_debug = toggle_debug; + global_state.settings.save_to_file_warn(); + } HudEvent::ToggleMouseYInvert(mouse_y_inverted) => { global_state.window.mouse_y_inversion = mouse_y_inverted; global_state.settings.gameplay.mouse_y_inversion = mouse_y_inverted; diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index e2a567f174..940823465f 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -85,8 +85,8 @@ impl Default for ControlSettings { screenshot: KeyMouse::Key(VirtualKeyCode::F4), toggle_ingame_ui: KeyMouse::Key(VirtualKeyCode::F6), roll: KeyMouse::Mouse(MouseButton::Middle), - respawn: KeyMouse::Mouse(MouseButton::Left), - interact: KeyMouse::Key(VirtualKeyCode::E), + respawn: KeyMouse::Key(VirtualKeyCode::Space), + interact: KeyMouse::Mouse(MouseButton::Right), toggle_wield: KeyMouse::Key(VirtualKeyCode::T), charge: KeyMouse::Key(VirtualKeyCode::V), } @@ -100,6 +100,10 @@ pub struct GameplaySettings { pub pan_sensitivity: u32, pub zoom_sensitivity: u32, pub zoom_inversion: bool, + pub toggle_debug: bool, + pub sct: bool, + pub sct_player_batch: bool, + pub sct_damage_batch: bool, pub mouse_y_inversion: bool, pub crosshair_transp: f32, pub chat_transp: f32, @@ -118,6 +122,10 @@ impl Default for GameplaySettings { zoom_sensitivity: 100, zoom_inversion: false, mouse_y_inversion: false, + toggle_debug: false, + sct: true, + sct_player_batch: true, + sct_damage_batch: false, crosshair_transp: 0.6, chat_transp: 0.4, crosshair_type: CrosshairType::Round, @@ -179,9 +187,9 @@ pub struct GraphicsSettings { impl Default for GraphicsSettings { fn default() -> Self { Self { - view_distance: 5, + view_distance: 10, max_fps: 60, - fov: 75, + fov: 50, aa_mode: AaMode::Fxaa, } } diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 6a20dbfbf0..87b0b27697 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -305,7 +305,7 @@ impl Ui { enum Placement { Interface, // Number of primitives left to render ingame and relative scaling/resolution - InWorld(usize, Option), + InWorld(usize, Option<(f64, f64)>), }; let mut placement = Placement::Interface; @@ -399,7 +399,7 @@ impl Ui { // Functions for converting for conrod scalar coords to GL vertex coords (-1.0 to 1.0). let (ui_win_w, ui_win_h) = match placement { - Placement::InWorld(_, Some(res)) => (res as f64, res as f64), + Placement::InWorld(_, Some(res)) => res, // Behind the camera or far away Placement::InWorld(_, None) => continue, Placement::Interface => (self.ui.win_w, self.ui.win_h), @@ -624,10 +624,12 @@ impl Ui { .parameters; let pos_in_view = view_mat * Vec4::from_point(parameters.pos); + let scale_factor = self.ui.win_w as f64 / (-2.0 * pos_in_view.z as f64 * (0.5 * fov as f64).tan() + // TODO: make this have no effect for fixed scale * parameters.res as f64); // Don't process ingame elements behind the camera or very far away placement = if scale_factor > 0.2 { @@ -642,32 +644,43 @@ impl Ui { }); start = mesh.vertices().len(); // Push new position command + let mut world_pos = Vec4::from_point(parameters.pos); + if parameters.fixed_scale { + world_pos.w = -1.0 + }; + if self.ingame_locals.len() > ingame_local_index { renderer .update_consts( &mut self.ingame_locals[ingame_local_index], - &[parameters.pos.into()], + &[world_pos.into()], ) .unwrap(); } else { - self.ingame_locals.push( - renderer.create_consts(&[parameters.pos.into()]).unwrap(), - ); + self.ingame_locals + .push(renderer.create_consts(&[world_pos.into()]).unwrap()); } self.draw_commands .push(DrawCommand::WorldPos(Some(ingame_local_index))); ingame_local_index += 1; - p_scale_factor = ((scale_factor * 10.0).log2().round().powi(2) - / 10.0) - .min(1.6) - .max(0.2); + p_scale_factor = if parameters.fixed_scale { + self.scale.scale_factor_physical() + } else { + ((scale_factor * 10.0).log2().round().powi(2) / 10.0) + .min(1.6) + .max(0.2) + }; // Scale down ingame elements that are close to the camera - let res = if scale_factor > 3.2 { - parameters.res * scale_factor as f32 / 3.2 + let res = if parameters.fixed_scale { + (self.ui.win_w, self.ui.win_h) + } else if scale_factor > 3.2 { + let res = parameters.res * scale_factor as f32 / 3.2; + (res as f64, res as f64) } else { - parameters.res + let res = parameters.res; + (res as f64, res as f64) }; Placement::InWorld(parameters.num, Some(res)) diff --git a/voxygen/src/ui/widgets/ingame.rs b/voxygen/src/ui/widgets/ingame.rs index a8a41c31c1..c9e96193eb 100644 --- a/voxygen/src/ui/widgets/ingame.rs +++ b/voxygen/src/ui/widgets/ingame.rs @@ -57,6 +57,9 @@ pub struct IngameParameters { // Used for widgets that are rasterized before being sent to the gpu (text & images) // Potentially make this automatic based on distance to camera? pub res: f32, + // Whether the widgets should be scaled based on distance to the camera or if they should be a + // fixed size (res is ignored in that case) + pub fixed_scale: bool, } pub struct State { @@ -74,10 +77,15 @@ impl Ingame { num: widget.prim_count(), pos, res: 1.0, + fixed_scale: false, }, widget, } } + pub fn fixed_scale(mut self) -> Self { + self.parameters.fixed_scale = true; + self + } builder_methods! { pub resolution { parameters.res = f32 } } @@ -147,6 +155,7 @@ impl IngameAnchor { num: 0, pos, res: 1.0, + fixed_scale: false, }, } } From 70eb2eed33fd65a47935280fa5c9e942c8fdb5d8 Mon Sep 17 00:00:00 2001 From: Songtronix Date: Fri, 10 Jan 2020 17:01:50 +0100 Subject: [PATCH 42/51] remove: discord rich presence --- Cargo.lock | 303 --------------------------- voxygen/Cargo.toml | 5 - voxygen/src/discord.rs | 143 ------------- voxygen/src/hud/esc_menu.rs | 12 -- voxygen/src/hud/mod.rs | 12 -- voxygen/src/logging.rs | 1 - voxygen/src/main.rs | 48 ----- voxygen/src/menu/main/client_init.rs | 14 -- voxygen/src/singleplayer.rs | 11 - 9 files changed, 549 deletions(-) delete mode 100644 voxygen/src/discord.rs diff --git a/Cargo.lock b/Cargo.lock index 0344df16fb..aaa82d2295 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,14 +13,6 @@ dependencies = [ "const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "aho-corasick" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "aho-corasick" version = "0.7.6" @@ -56,14 +48,6 @@ name = "android_glue" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "anymap" version = "0.12.1" @@ -124,14 +108,6 @@ name = "ascii" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "aster" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "atk-sys" version = "0.6.0" @@ -210,26 +186,6 @@ dependencies = [ "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bindgen" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "clang-sys 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "bindgen" version = "0.51.1" @@ -248,16 +204,6 @@ dependencies = [ "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bitflags" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitflags" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "1.2.1" @@ -379,14 +325,6 @@ name = "cc" version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "cexpr" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "cexpr" version = "0.3.6" @@ -433,17 +371,6 @@ name = "chunked_transfer" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "clang-sys" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "clang-sys" version = "0.28.1" @@ -459,13 +386,9 @@ name = "clap" version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -489,14 +412,6 @@ dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "cmake" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "cocoa" version = "0.18.5" @@ -875,24 +790,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "discord-rpc-sdk" -version = "0.1.1" -source = "git+https://github.com/Songtronix/rust-discord-rpc.git#5823404967954992c0ee48c731f12ab2ca3aaa1d" -dependencies = [ - "discord-rpc-sys 0.1.0 (git+https://github.com/Songtronix/rust-discord-rpc.git)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "discord-rpc-sys" -version = "0.1.0" -source = "git+https://github.com/Songtronix/rust-discord-rpc.git#5823404967954992c0ee48c731f12ab2ca3aaa1d" -dependencies = [ - "bindgen 0.26.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "dispatch" version = "0.1.4" @@ -935,15 +832,6 @@ name = "either" version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "env_logger" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "env_logger" version = "0.6.2" @@ -1292,11 +1180,6 @@ dependencies = [ "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "glob" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "glob" version = "0.3.0" @@ -1601,11 +1484,6 @@ name = "khronos_api" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "lazy_static" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "lazy_static" version = "1.4.0" @@ -1631,16 +1509,6 @@ name = "libc" version = "0.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "libloading" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "libloading" version = "0.5.2" @@ -1727,14 +1595,6 @@ name = "maybe-uninit" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "memchr" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "memchr" version = "2.2.1" @@ -1917,14 +1777,6 @@ dependencies = [ "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "nom" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "nom" version = "4.2.3" @@ -2382,26 +2234,6 @@ name = "protobuf" version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "quasi" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quasi_codegen" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "quick-error" version = "1.2.2" @@ -2659,18 +2491,6 @@ dependencies = [ "rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex" version = "1.3.1" @@ -2690,14 +2510,6 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex-syntax" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex-syntax" version = "0.6.12" @@ -2786,11 +2598,6 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "rustc_version" version = "0.2.3" @@ -3095,11 +2902,6 @@ name = "stdweb" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "sum_type" version = "0.2.0" @@ -3151,48 +2953,6 @@ dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "syntex" -version = "0.58.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syntex_errors" -version = "0.58.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syntex_pos" -version = "0.58.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syntex_syntax" -version = "0.58.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "tempdir" version = "0.3.7" @@ -3202,15 +2962,6 @@ dependencies = [ "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "term" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "term" version = "0.5.2" @@ -3324,11 +3075,6 @@ dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ucd-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unicase" version = "1.4.2" @@ -3358,11 +3104,6 @@ name = "unicode-width" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unicode-xid" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unicode-xid" version = "0.1.0" @@ -3383,11 +3124,6 @@ dependencies = [ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "utf8-ranges" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "uvth" version = "3.1.1" @@ -3398,11 +3134,6 @@ dependencies = [ "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "vec_map" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "vek" version = "0.9.11" @@ -3519,7 +3250,6 @@ dependencies = [ "cpal 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "discord-rpc-sdk 0.1.1 (git+https://github.com/Songtronix/rust-discord-rpc.git)", "dispatch 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "euc 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3533,7 +3263,6 @@ dependencies = [ "guillotiere 0.4.2 (git+https://github.com/Imberflur/guillotiere)", "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "msgbox 0.4.0 (git+https://github.com/bekker/msgbox-rs.git?rev=68fe39a)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3838,12 +3567,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" "checksum ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6f33b5018f120946c1dcf279194f238a9f146725593ead1c08fa47ff22b0b5d3" -"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum alsa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0edcbbf9ef68f15ae1b620f722180b82a98b6f0628d30baa6b8d2a5abc87d58" "checksum andrew 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9b7f09f89872c2b6b29e319377b1fbe91c6f5947df19a25596e121cf19a7b35e" "checksum android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" "checksum approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94" "checksum approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3" @@ -3853,7 +3580,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" "checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14" -"checksum aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfdf7355d9db158df68f976ed030ab0f6578af811f5a7bb6dcf221ec24e0e0" "checksum atk-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8dc233521f7bffd3042c31082ea71bd08820abf44bac938fb36591e20f76f39" "checksum atom 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3c86699c3f02778ec07158376991c8f783dd1f2f95c579ffaf0738dc984b2fe2" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" @@ -3863,10 +3589,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ab639324e3ee8774d296864fbc0dbbb256cf1a41c490b94cba90c082915f92" -"checksum bindgen 0.26.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c57d6c0f6e31f8dcf4d12720a3c2a9ffb70638772a5784976cf4fce52145f22a" "checksum bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebd71393f1ec0509b553aa012b9b58e81dadbdff7130bd3b8cba576e69b32f75" -"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" -"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum bitvec 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a993f74b4c99c1908d156b8d2e0fb6277736b0ecbd833982fd1241d39b2766a6" "checksum blake2b_simd 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b83b7baab1e671718d78204225800d6b170e648188ac7dc992e9d6bddf87d0c0" @@ -3883,20 +3606,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cairo-sys-rs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0395175ecba60accac076a02c31d143b9dcd9d5eb5316d7163a3273803b765c7" "checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" "checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8" -"checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c" "checksum cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "55e7ec0b74fe5897894cbc207092c577e87c52f8a59e8ca8d97ef37551f60a49" "checksum chashmap 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff41a3c2c1e39921b9003de14bf0439c7b63a9039637c291e1a64925d8ddfa45" "checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" "checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" -"checksum clang-sys 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "611ec2e3a7623afd8a8c0d027887b6b55759d894abbf5fe11b9dc11b50d5b49a" "checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum claxon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f86c952727a495bda7abaf09bafdee1a939194dd793d9a8e26281df55ac43b00" "checksum clipboard-win 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3a093d6fed558e5fe24c3dfc85a68bb68f1c824f440d3ba5aca189e2998786b" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" "checksum cocoa 0.18.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1706996401131526e36b3b49f0c4d912639ce110996f3ca144d78946727bce54" "checksum cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f29f7768b2d1be17b96158e3285951d366b40211320fb30826a76cb7a0da6400" "checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" @@ -3934,15 +3654,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c" "checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" "checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" -"checksum discord-rpc-sdk 0.1.1 (git+https://github.com/Songtronix/rust-discord-rpc.git)" = "" -"checksum discord-rpc-sys 0.1.0 (git+https://github.com/Songtronix/rust-discord-rpc.git)" = "" "checksum dispatch 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e93ca78226c51902d7aa8c12c988338aadd9e85ed9c6be8aaac39192ff3605" "checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a" "checksum dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11afd3251e588f2770226659b2a1d55ec2f8aaf2ca42bdcdbd01ff53b4a81e70" "checksum downcast-rs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6" "checksum draw_state 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "33cf9537e2d06891448799b96d5a8c8083e0e90522a7fdabe6ebf4f41d79d651" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum euc 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c20f6684a8420df7c300a36bed7cb0b2387b2bc385d4940282399b5df0c08ebd" "checksum euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)" = "596b99621b9477e7a5f94d2d8dd13a9c5c302ac358b822c67a42b6f1054450e1" @@ -3979,7 +3696,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum gleam 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "cae10d7c99d0e77b4766e850a60898a17c1abaf01075531f1066f03dc7dc5fc5" "checksum glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e0be1b1432e227bcd1a9b28db9dc1474a7e7fd4227e08e16f35304f32d09b61" "checksum glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615bef979b5838526aee99241afc80cfb2e34a8735d4bcb8ec6072598c18a408" -"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" "checksum glsl-include 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "daa2afb1631e7ab4543e0dde0e3fc68bb49c58fee89c07f30a26553b1f684ab6" "checksum glutin 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "938ce7a2b1bbfe1535166133bea3f9c1b46350d2794b49561303575e9e1b9949" @@ -4012,12 +3728,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum jpeg-decoder 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "c1aae18ffeeae409c6622c3b6a7ee49792a7e5a062eea1b135fbb74e301792ba" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum khronos_api 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" -"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum lewton 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8d542c1a317036c45c2aa1cf10cc9d403ca91eb2d333ef1a4917e5cb10628bd0" "checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" -"checksum libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd38073de8f7965d0c17d30546d4bb6da311ab428d1c7a3fc71dff7f9d4979b9" "checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" "checksum line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" @@ -4030,7 +3744,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" -"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" @@ -4049,7 +3762,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum noise 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "337525774dd8a197b613a01ea88058ef0ed023e5ed1e4b7e93de478e1f2bf770" -"checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" "checksum notify 5.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d742ae493f34bd2e20ec2f3c1276fc1981343a8efd7ef12bca4368d0303bed50" "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" @@ -4100,8 +3812,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum prometheus 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5567486d5778e2c6455b1b90ff1c558f29e751fc018130fa182e15828e728af1" "checksum prometheus-static-metric 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1baa57413523cff73783204f73299a3f602ebcf51a5e64752b32bc1b3c376013" "checksum protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40361836defdd5871ff7e84096c6f6444af7fc157f8ef1789f54f147687caa20" -"checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3" -"checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" @@ -4130,10 +3840,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" -"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" -"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum rodio 0.9.0 (git+https://github.com/RustAudio/rodio?rev=e5474a2)" = "" @@ -4143,7 +3851,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum rusttype 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "310942406a39981bed7e12b09182a221a29e0990f3e7e0c971f131922ed135d5" "checksum rusttype 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "14a911032fb5791ccbeec9f28fdcb9bf0983b81f227bafdfd227c658d0731c8a" @@ -4181,19 +3888,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" "checksum stb_truetype 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f77b6b07e862c66a9f3e62a07588fee67cd90a9135a2b942409f195507b4fb51" "checksum stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum sum_type 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da5b4a0c9f3c7c8e891e445a7c776627e208e8bba23ab680798066dd283e6a15" "checksum svg_fmt 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20e5f95e89d737f30cd1f98a9af9a85c2a1cc162cfedfba5a0c54cf92d7206fc" "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" "checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92" "checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" -"checksum syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a8f5e3aaa79319573d19938ea38d068056b826db9883a5d47f86c1cecc688f0e" -"checksum syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "867cc5c2d7140ae7eaad2ae9e8bf39cb18a67ca651b7834f88d46ca98faadb9c" -"checksum syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13ad4762fe52abc9f4008e85c4fb1b1fe3aa91ccb99ff4826a439c7c598e1047" -"checksum syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e0e4dbae163dd98989464c23dd503161b338790640e11537686f2ef0f25c791" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" @@ -4207,18 +3908,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum treeculler 0.1.0 (git+https://gitlab.com/yusdacra/treeculler.git)" = "" "checksum tuple_utils 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44834418e2c5b16f47bedf35c28e148db099187dd5feee6367fb2525863af4f1" "checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" -"checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf" "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" -"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" "checksum uvth 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e59a167890d173eb0fcd7a1b99b84dc05c521ae8d76599130b8e19bef287abbf" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum vek 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "1eb3ca8ea588deba055424cc1a79a830428b2f6c270b8d8f91946f660fa4d8ee" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index b736ad5f33..3e497aef74 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -7,7 +7,6 @@ default-run = "veloren-voxygen" [features] gl = ["gfx_device_gl"] -discord = ["discord-rpc-sdk", "lazy_static"] singleplayer = ["server"] default = ["gl", "singleplayer", "msgbox"] @@ -33,10 +32,6 @@ specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git" } # Mathematics vek = { version = "0.9.9", features = ["serde"] } -# Discord -discord-rpc-sdk = { git = "https://github.com/Songtronix/rust-discord-rpc.git", optional = true } -lazy_static = { version = "1.4.0", optional = true } - # Singleplayer server = { package = "veloren-server", path = "../server", optional = true } diff --git a/voxygen/src/discord.rs b/voxygen/src/discord.rs deleted file mode 100644 index 4021646d01..0000000000 --- a/voxygen/src/discord.rs +++ /dev/null @@ -1,143 +0,0 @@ -use crate::DISCORD_INSTANCE; -use crossbeam::channel::{unbounded, Sender}; -use discord_rpc_sdk::{DiscordUser, EventHandlers, RichPresence, RPC}; -//use parking_lot::Mutex; -use std::sync::Mutex; -use std::thread; -use std::thread::JoinHandle; -use std::time::SystemTime; - -/// Connects to the discord application where Images and more resides -/// can be viewed at https://discordapp.com/developers/applications/583662036194689035/rich-presence/assets -/// but requires an invitation. -const DISCORD_APPLICATION_ID: &str = "583662036194689035"; - -/// Represents an update of the game which should be reflected in Discord -pub enum DiscordUpdate { - Details(String), - State(String), - SmallImg(String), - SmallImgDesc(String), - LargeImg(String), - LargeImgDesc(String), - Shutdown, -} - -pub struct DiscordState { - pub tx: Sender, - pub thread: Option>, -} - -pub fn run() -> Mutex { - let (tx, rx) = unbounded(); - - Mutex::new(DiscordState { - tx, - thread: Some(thread::spawn(move || { - let rpc: RPC = match RPC::init::(DISCORD_APPLICATION_ID, true, None) { - Ok(rpc) => rpc, - Err(e) => { - log::error!("failed to initiate discord_game_sdk: {}", e); - return; - } - }; - - //Set initial Status - let mut current_presence = RichPresence { - details: Some("In Menu".to_string()), - state: Some("Idling".to_string()), - start_time: Some(SystemTime::now()), - //end_time: Some(SystemTime::now().checked_add(Duration::from_secs(360)).unwrap()), - large_image_key: Some("snow_background".to_string()), - large_image_text: Some("Veloren.net".to_string()), - small_image_key: Some("veloren_logo_1024".to_string()), - small_image_text: Some("*insert joke here*".to_string()), - //party_id: Some("randompartyid".to_owned()), - //party_size: Some(4), - //party_max: Some(13), - //spectate_secret: Some("randomhash".to_string()), - //join_secret: Some("anotherrandomhash".to_string()), - ..Default::default() - }; - - match rpc.update_presence(current_presence.clone()) { - Ok(_) => {} - Err(e) => log::error!("Failed to update discord presence: {}", e), - } - - 'outer: loop { - rpc.run_callbacks(); - - let msg = rx.try_recv(); - match msg { - Ok(update) => { - match update { - DiscordUpdate::Details(x) => current_presence.details = Some(x), - DiscordUpdate::State(x) => current_presence.state = Some(x), - DiscordUpdate::SmallImg(x) => { - current_presence.small_image_key = Some(x) - } - DiscordUpdate::SmallImgDesc(x) => { - current_presence.small_image_text = Some(x) - } - DiscordUpdate::LargeImg(x) => { - current_presence.large_image_key = Some(x) - } - DiscordUpdate::LargeImgDesc(x) => { - current_presence.large_image_text = Some(x) - } - DiscordUpdate::Shutdown => break 'outer, - }; - - match rpc.update_presence(current_presence.clone()) { - Ok(_) => {} - Err(e) => log::error!("Failed to update discord presence: {}", e), - } - } - Err(_) => {} - } - } - - rpc.clear_presence(); - })), - }) -} - -struct Handlers; - -impl EventHandlers for Handlers { - fn ready(user: DiscordUser) { - log::debug!("We're ready! {:?}", user); - } - - fn errored(errcode: i32, message: &str) { - log::warn!("Error {}: {}", errcode, message); - } - - fn disconnected(errcode: i32, message: &str) { - log::debug!("Disconnected {}: {}", errcode, message); - } - - fn join_game(secret: &str) { - log::debug!("Joining {}", secret); - } - - fn spectate_game(secret: &str) { - log::debug!("Spectating {}", secret); - } - - fn join_request(from: DiscordUser) { - log::debug!("Join request from {:?}", from); - } -} - -pub fn send_all(updates: Vec) { - match DISCORD_INSTANCE.lock() { - Ok(disc) => { - for update in updates { - let _ = disc.tx.send(update); - } - } - Err(e) => log::error!("couldn't send Update to discord: {}", e), - } -} diff --git a/voxygen/src/hud/esc_menu.rs b/voxygen/src/hud/esc_menu.rs index cc45b395c6..88ec9bc052 100644 --- a/voxygen/src/hud/esc_menu.rs +++ b/voxygen/src/hud/esc_menu.rs @@ -5,9 +5,6 @@ use conrod_core::{ use super::{img_ids::Imgs, settings_window::SettingsTab, Fonts, TEXT_COLOR}; -#[cfg(feature = "discord")] -use crate::{discord, discord::DiscordUpdate}; - widget_ids! { struct Ids { esc_bg, @@ -153,15 +150,6 @@ impl<'a> Widget for EscMenu<'a> { .set(state.ids.menu_button_5, ui) .was_clicked() { - #[cfg(feature = "discord")] - { - discord::send_all(vec![ - DiscordUpdate::Details("Menu".into()), - DiscordUpdate::State("Idling".into()), - DiscordUpdate::LargeImg("bg_main".into()), - ]); - } - return Some(Event::Logout); }; // Quit diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 88124a4439..d498385923 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -55,9 +55,6 @@ use specs::{Join, WorldExt}; use std::collections::VecDeque; use vek::*; -#[cfg(feature = "discord")] -use crate::{discord, discord::DiscordUpdate}; - const XP_COLOR: Color = Color::Rgba(0.59, 0.41, 0.67, 1.0); const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); //const TEXT_COLOR_GREY: Color = Color::Rgba(1.0, 1.0, 1.0, 0.5); @@ -1852,15 +1849,6 @@ impl Hud { } Some(esc_menu::Event::Logout) => { events.push(Event::Logout); - - #[cfg(feature = "discord")] - { - discord::send_all(vec![ - DiscordUpdate::Details("Menu".into()), - DiscordUpdate::State("Idling".into()), - DiscordUpdate::LargeImg("bg_main".into()), - ]); - } } Some(esc_menu::Event::Quit) => events.push(Event::Quit), Some(esc_menu::Event::CharacterSelection) => events.push(Event::CharacterSelection), diff --git a/voxygen/src/logging.rs b/voxygen/src/logging.rs index 48fb256e95..4085b3c30f 100644 --- a/voxygen/src/logging.rs +++ b/voxygen/src/logging.rs @@ -17,7 +17,6 @@ pub fn init( let mut base = fern::Dispatch::new() .level_for("dot_vox::parser", log::LevelFilter::Warn) .level_for("gfx_device_gl::factory", log::LevelFilter::Warn) - .level_for("veloren_voxygen::discord", log::LevelFilter::Warn) .level_for("uvth", log::LevelFilter::Warn) .level_for("tiny_http", log::LevelFilter::Warn); diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index b6fac4e48b..28d5ae0fe9 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -2,16 +2,6 @@ #![feature(drain_filter)] #![recursion_limit = "2048"] -#[cfg(feature = "discord")] -#[macro_use] -extern crate lazy_static; - -#[cfg(feature = "discord")] -pub mod discord; - -#[cfg(feature = "discord")] -use std::sync::Mutex; - #[macro_use] pub mod ui; pub mod anim; @@ -88,14 +78,6 @@ pub trait PlayState { fn name(&self) -> &'static str; } -#[cfg(feature = "discord")] -lazy_static! { - //Set up discord rich presence - static ref DISCORD_INSTANCE: Mutex = { - discord::run() - }; -} - fn main() { // Initialize logging. let term_log_level = std::env::var_os("VOXYGEN_LOG") @@ -213,17 +195,6 @@ fn main() { default_hook(panic_info); })); - // Initialise Discord - #[cfg(feature = "discord")] - { - use discord::DiscordUpdate; - discord::send_all(vec![ - DiscordUpdate::Details("Menu".into()), - DiscordUpdate::State("Idling".into()), - DiscordUpdate::LargeImg("bg_main".into()), - ]); - } - // Set up the initial play state. let mut states: Vec> = vec![Box::new(MainMenuState::new(&mut global_state))]; states @@ -282,25 +253,6 @@ fn main() { } } - //Properly shutdown discord thread - #[cfg(feature = "discord")] - { - match DISCORD_INSTANCE.lock() { - Ok(mut disc) => { - let _ = disc.tx.send(discord::DiscordUpdate::Shutdown); - match disc.thread.take() { - Some(th) => { - let _ = th.join(); - } - None => { - error!("couldn't gracefully shutdown discord thread"); - } - } - } - Err(e) => error!("couldn't gracefully shutdown discord thread: {}", e), - } - } - // Save any unsaved changes to settings global_state.settings.save_to_file_warn(); } diff --git a/voxygen/src/menu/main/client_init.rs b/voxygen/src/menu/main/client_init.rs index 6649d6ceff..557dc715d3 100644 --- a/voxygen/src/menu/main/client_init.rs +++ b/voxygen/src/menu/main/client_init.rs @@ -5,9 +5,6 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::{net::ToSocketAddrs, thread, time::Duration}; -#[cfg(feature = "discord")] -use crate::{discord, discord::DiscordUpdate}; - #[derive(Debug)] pub enum Error { // Error parsing input string or error resolving host name. @@ -72,17 +69,6 @@ impl ClientInit { } //client.register(player, password); let _ = tx.send(Ok(client)); - - #[cfg(feature = "discord")] - { - if !server_address.eq("127.0.0.1") { - discord::send_all(vec![ - DiscordUpdate::Details(server_address), - DiscordUpdate::State("Playing...".into()), - ]); - } - } - return; } Err(err) => { diff --git a/voxygen/src/singleplayer.rs b/voxygen/src/singleplayer.rs index b9978bee64..a1b3cec031 100644 --- a/voxygen/src/singleplayer.rs +++ b/voxygen/src/singleplayer.rs @@ -8,9 +8,6 @@ use std::{ time::Duration, }; -#[cfg(feature = "discord")] -use crate::{discord, discord::DiscordUpdate}; - const TPS: u64 = 30; enum Msg { @@ -68,14 +65,6 @@ fn run_server(mut server: Server, rec: Receiver) { // Set up an fps clock let mut clock = Clock::start(); - #[cfg(feature = "discord")] - { - discord::send_all(vec![ - DiscordUpdate::Details("Singleplayer".into()), - DiscordUpdate::State("Playing...".into()), - ]); - } - loop { let events = server .tick(Input::default(), clock.get_last_delta()) From c6f64564a8e221f88b28b5cfd9fab0caea9c5cfe Mon Sep 17 00:00:00 2001 From: Shane Handley Date: Sat, 11 Jan 2020 13:08:33 +0900 Subject: [PATCH 43/51] Remove emission of an audio event from stats sys This was accidentally left in by me during some testing of server emission of SFX events to all clients. There was no effect on gameplay since we dont emit a sound for this event yet, but it should not be here. The audio event is correctly handled elsewhere by each client. --- common/src/sys/stats.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/common/src/sys/stats.rs b/common/src/sys/stats.rs index f8aa9e281b..f4ac03e576 100644 --- a/common/src/sys/stats.rs +++ b/common/src/sys/stats.rs @@ -1,6 +1,6 @@ use crate::{ comp::{HealthSource, Stats}, - event::{EventBus, ServerEvent, SfxEvent, SfxEventItem}, + event::{EventBus, ServerEvent}, state::DeltaTime, }; use specs::{Entities, Join, Read, System, WriteStorage}; @@ -13,14 +13,10 @@ impl<'a> System<'a> for Sys { Entities<'a>, Read<'a, DeltaTime>, Read<'a, EventBus>, - Read<'a, EventBus>, WriteStorage<'a, Stats>, ); - fn run( - &mut self, - (entities, dt, server_event_bus, audio_event_bus, mut stats): Self::SystemData, - ) { + fn run(&mut self, (entities, dt, server_event_bus, mut stats): Self::SystemData) { let mut server_event_emitter = server_event_bus.emitter(); // Increment last change timer @@ -58,10 +54,6 @@ impl<'a> System<'a> for Sys { stat.level.change_by(1); } - audio_event_bus - .emitter() - .emit(SfxEventItem::at_player_position(SfxEvent::LevelUp)); - stat.update_max_hp(); stat.health .set_to(stat.health.maximum(), HealthSource::LevelUp) From e0fc3ce425eaa5d87dfe750aa61bdc05f673b4f1 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Sat, 11 Jan 2020 21:31:57 +0100 Subject: [PATCH 44/51] fixed number shadow for "0" damage appearing on level up --- voxygen/src/hud/mod.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index d498385923..e316298721 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -902,7 +902,11 @@ impl Hud { ((crate::ecs::sys::floater::MY_HP_SHOWTIME - timer) * 0.25) + 0.2; Text::new(&format!("{}", (hp_damage).abs())) .font_size(font_size) - .color(Color::Rgba(0.0, 0.0, 0.0, hp_fade)) + .color(if hp_damage < 0 { + Color::Rgba(0.0, 0.0, 0.0, hp_fade) + } else { + Color::Rgba(0.0, 0.0, 0.0, 0.0) + }) .mid_bottom_with_margin_on(ui_widgets.window, 297.0 + y) .set(player_sct_bg_id, ui_widgets); Text::new(&format!("{}", (hp_damage).abs())) @@ -910,7 +914,7 @@ impl Hud { .color(if hp_damage < 0 { Color::Rgba(1.0, 0.1, 0.0, hp_fade) } else { - Color::Rgba(0.1, 1.0, 0.1, 0.0) + Color::Rgba(0.0, 0.0, 0.0, 0.0) }) .mid_bottom_with_margin_on(ui_widgets.window, 300.0 + y) .set(player_sct_id, ui_widgets); From e1adf408564b84595a9ca315be47c97d293b7fe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Korg=C3=B3l?= Date: Sun, 12 Jan 2020 15:45:20 +0100 Subject: [PATCH 45/51] Improvement: Replace all '..=b' with '..b + 1' --- client/src/lib.rs | 4 ++-- common/src/region.rs | 4 ++-- common/src/sys/phys.rs | 6 ++++-- common/src/volumes/vol_grid_2d.rs | 4 ++-- common/src/volumes/vol_grid_3d.rs | 6 +++--- server/src/lib.rs | 2 +- voxygen/src/menu/main/client_init.rs | 2 +- world/src/sim/mod.rs | 4 ++-- world/src/sim/util.rs | 2 +- 9 files changed, 18 insertions(+), 16 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index d9691c9ed1..1f20cc1227 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -411,7 +411,7 @@ impl Client { // Request chunks from the server. let mut all_loaded = true; - 'outer: for dist in 0..=view_distance as i32 { + 'outer: for dist in 0..(view_distance as i32) + 1 { // Only iterate through chunks that need to be loaded for circular vd // The (dist - 2) explained: // -0.5 because a chunk is visible if its corner is within the view distance @@ -428,7 +428,7 @@ impl Client { dist }; - for i in -top..=top { + for i in -top..top + 1 { let keys = [ chunk_pos + Vec2::new(dist, i), chunk_pos + Vec2::new(i, dist), diff --git a/common/src/region.rs b/common/src/region.rs index 2725f6fb47..295c86dc44 100644 --- a/common/src/region.rs +++ b/common/src/region.rs @@ -372,8 +372,8 @@ pub fn regions_in_vd(pos: Vec3, vd: f32) -> HashSet> { let max = RegionMap::pos_key(pos_xy.map(|e| (e + vd_extended) as i32)); let min = RegionMap::pos_key(pos_xy.map(|e| (e - vd_extended) as i32)); - for x in min.x..=max.x { - for y in min.y..=max.y { + for x in min.x..max.x + 1 { + for y in min.y..max.y + 1 { let key = Vec2::new(x, y); if region_in_vd(key, pos, vd) { diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index 67689495b4..955d229c22 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -110,8 +110,10 @@ impl<'a> System<'a> for Sys { let hdist = player_rad.ceil() as i32; let vdist = player_height.ceil() as i32; // Neighbouring blocks iterator - let near_iter = (-hdist..=hdist) - .map(move |i| (-hdist..=hdist).map(move |j| (0..=vdist).map(move |k| (i, j, k)))) + let near_iter = (-hdist..hdist + 1) + .map(move |i| { + (-hdist..hdist + 1).map(move |j| (0..vdist + 1).map(move |k| (i, j, k))) + }) .flatten() .flatten(); diff --git a/common/src/volumes/vol_grid_2d.rs b/common/src/volumes/vol_grid_2d.rs index 00e21a19aa..ac97fb5738 100644 --- a/common/src/volumes/vol_grid_2d.rs +++ b/common/src/volumes/vol_grid_2d.rs @@ -69,8 +69,8 @@ impl>, V: RectRasterableVol + ReadVol + Debug> SampleVol fo let mut sample = VolGrid2d::new()?; let chunk_min = Self::chunk_key(range.min); let chunk_max = Self::chunk_key(range.max); - for x in chunk_min.x..=chunk_max.x { - for y in chunk_min.y..=chunk_max.y { + for x in chunk_min.x..chunk_max.x + 1 { + for y in chunk_min.y..chunk_max.y + 1 { let chunk_key = Vec2::new(x, y); let chunk = self.get_key_arc(chunk_key).cloned(); diff --git a/common/src/volumes/vol_grid_3d.rs b/common/src/volumes/vol_grid_3d.rs index 627d1aeb42..8d8dfc84c4 100644 --- a/common/src/volumes/vol_grid_3d.rs +++ b/common/src/volumes/vol_grid_3d.rs @@ -73,9 +73,9 @@ impl>, V: RasterableVol + ReadVol + Debug> SampleVol for Vo let mut sample = VolGrid3d::new()?; let chunk_min = Self::chunk_key(range.min); let chunk_max = Self::chunk_key(range.max); - for x in chunk_min.x..=chunk_max.x { - for y in chunk_min.y..=chunk_max.y { - for z in chunk_min.z..=chunk_max.z { + for x in chunk_min.x..chunk_max.x + 1 { + for y in chunk_min.y..chunk_max.y + 1 { + for z in chunk_min.z..chunk_max.z + 1 { let chunk_key = Vec3::new(x, y, z); let chunk = self.get_key_arc(chunk_key).cloned(); diff --git a/server/src/lib.rs b/server/src/lib.rs index 2a5147ad1f..6a1575c772 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -132,7 +132,7 @@ impl Server { // until the first air block is found // (up to max_z + 1, because max_z could still be a soild block) // if no air block is found default to max_z + 1 - let z = (min_z..=max_z + 1) + let z = (min_z..(max_z + 1) + 1) .find(|z| { block_sampler .get_with_z_cache( diff --git a/voxygen/src/menu/main/client_init.rs b/voxygen/src/menu/main/client_init.rs index 557dc715d3..5ebcf4526e 100644 --- a/voxygen/src/menu/main/client_init.rs +++ b/voxygen/src/menu/main/client_init.rs @@ -51,7 +51,7 @@ impl ClientInit { let mut last_err = None; - 'tries: for _ in 0..=60 { + 'tries: for _ in 0..60 + 1 { // 300 Seconds if cancel2.load(Ordering::Relaxed) { break; diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index 8735ad135b..bc58f926a7 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -454,8 +454,8 @@ impl WorldSim { _ => {} } */ let pos = uniform_idx_as_vec2(posi); - for x in pos.x - 1..=pos.x + 1 { - for y in pos.y - 1..=pos.y + 1 { + for x in pos.x - 1..(pos.x + 1) + 1 { + for y in pos.y - 1..(pos.y + 1) + 1 { if x >= 0 && y >= 0 && x < WORLD_SIZE.x as i32 && y < WORLD_SIZE.y as i32 { let posi = vec2_as_uniform_idx(Vec2::new(x, y)); if !is_underwater(posi) { diff --git a/world/src/sim/util.rs b/world/src/sim/util.rs index 252dc68050..c88cdcdc1e 100644 --- a/world/src/sim/util.rs +++ b/world/src/sim/util.rs @@ -101,7 +101,7 @@ pub fn cdf_irwin_hall(weights: &[f32; N], samples: [f32; N]) -> y /= weights.iter().product::(); // Remember to multiply by 1 / N! at the end. - y / (1..=N as i32).product::() as f32 + y / (1..(N as i32) + 1).product::() as f32 } /// First component of each element of the vector is the computed CDF of the noise function at this From 00c1493548cc348a0c474241d88fb07d75c22005 Mon Sep 17 00:00:00 2001 From: S Handley Date: Sun, 12 Jan 2020 16:35:20 +0000 Subject: [PATCH 46/51] Play the Run SFX when a character lands after jumping or falling This is a small detail but makes a noticable difference. --- .../src/audio/sfx/event_mapper/movement.rs | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/voxygen/src/audio/sfx/event_mapper/movement.rs b/voxygen/src/audio/sfx/event_mapper/movement.rs index 114a785390..b78396b859 100644 --- a/voxygen/src/audio/sfx/event_mapper/movement.rs +++ b/voxygen/src/audio/sfx/event_mapper/movement.rs @@ -128,13 +128,11 @@ impl MovementEventMapper { (MovementState::Climb, ..) => SfxEvent::Climb, (MovementState::Swim, ..) => SfxEvent::Swim, (MovementState::Run, ..) => SfxEvent::Run, - (MovementState::Fall, _, previous_event) => { - if previous_event != SfxEvent::Glide { - SfxEvent::Fall - } else { - SfxEvent::GliderClose - } - } + (MovementState::Jump, ..) => SfxEvent::Jump, + (MovementState::Fall, _, SfxEvent::Glide) => SfxEvent::GliderClose, + (MovementState::Stand, _, SfxEvent::Fall) => SfxEvent::Run, + (MovementState::Fall, _, SfxEvent::Jump) => SfxEvent::Idle, + (MovementState::Fall, _, _) => SfxEvent::Fall, (MovementState::Glide, _, previous_event) => { if previous_event != SfxEvent::GliderOpen && previous_event != SfxEvent::Glide { SfxEvent::GliderOpen @@ -142,13 +140,7 @@ impl MovementEventMapper { SfxEvent::Glide } } - (MovementState::Stand, _, previous_event) => { - if previous_event == SfxEvent::Glide { - SfxEvent::GliderClose - } else { - SfxEvent::Idle - } - } + (MovementState::Stand, _, SfxEvent::Glide) => SfxEvent::GliderClose, _ => SfxEvent::Idle, } } @@ -287,12 +279,25 @@ mod tests { movement: MovementState::Fall, action: ActionState::Idle, }, - SfxEvent::Idle, + SfxEvent::Fall, ); assert_eq!(result, SfxEvent::Fall); } + #[test] + fn maps_land_on_ground_to_run() { + let result = MovementEventMapper::map_movement_event( + &CharacterState { + movement: MovementState::Stand, + action: ActionState::Idle, + }, + SfxEvent::Fall, + ); + + assert_eq!(result, SfxEvent::Run); + } + #[test] fn maps_glider_open() { let result = MovementEventMapper::map_movement_event( From f6dfb74b3e7bf034578f692d8b2f02458df30ab8 Mon Sep 17 00:00:00 2001 From: Monty Marz Date: Sun, 12 Jan 2020 19:01:02 +0000 Subject: [PATCH 47/51] fix slightly lower trigger velocity slighty more transp map image --- assets/voxygen/voxel/fixture/selection_bg - Kopie.vox | 3 --- voxygen/src/hud/map.rs | 8 ++------ 2 files changed, 2 insertions(+), 9 deletions(-) delete mode 100644 assets/voxygen/voxel/fixture/selection_bg - Kopie.vox diff --git a/assets/voxygen/voxel/fixture/selection_bg - Kopie.vox b/assets/voxygen/voxel/fixture/selection_bg - Kopie.vox deleted file mode 100644 index 77eeb2bfc8..0000000000 --- a/assets/voxygen/voxel/fixture/selection_bg - Kopie.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:32253fa8615d7c9df356cfc19c8763be931e18b3e1042fa0dd1e4ca36f70de2a -size 605856 diff --git a/voxygen/src/hud/map.rs b/voxygen/src/hud/map.rs index 2890b5ae22..37199f594f 100644 --- a/voxygen/src/hud/map.rs +++ b/voxygen/src/hud/map.rs @@ -87,12 +87,8 @@ impl<'a> Widget for Map<'a> { fn update(self, args: widget::UpdateArgs) -> Self::Event { let widget::UpdateArgs { state, ui, .. } = args; // Set map transparency to 0.5 when player is moving - /*let vel = match self.velocity { - Some(velocity) => velocity.0.magnitude(), - None => 0.0, - };*/ let mut fade = 1.0; - if self.velocity > 7.0 { + if self.velocity > 2.5 { fade = 0.7 }; @@ -165,7 +161,7 @@ impl<'a> Widget for Map<'a> { // Map Image Image::new(/*self.world_map*/ self.imgs.map_placeholder) .middle_of(state.ids.map_bg) - .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade))) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade - 0.1))) .w_h(700.0, 700.0) .parent(state.ids.map_bg) .set(state.ids.grid, ui); From 28060e7b6ed764539b097f797cc3c035471f63c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gilbert=20R=C3=B6hrbein?= Date: Sun, 12 Jan 2020 17:43:25 +0100 Subject: [PATCH 48/51] fixing #405 - Energy as its own component --- common/src/comp/energy.rs | 54 ++++++++++++++++++++++++++++++++++++ common/src/comp/mod.rs | 2 ++ common/src/comp/stats.rs | 51 ---------------------------------- common/src/msg/ecs_packet.rs | 5 ++++ common/src/state.rs | 1 + server/src/lib.rs | 2 ++ server/src/sys/sentinel.rs | 14 ++++++++-- voxygen/src/hud/mod.rs | 39 ++++++++++++++++---------- voxygen/src/hud/skillbar.rs | 12 ++++---- 9 files changed, 107 insertions(+), 73 deletions(-) create mode 100644 common/src/comp/energy.rs diff --git a/common/src/comp/energy.rs b/common/src/comp/energy.rs new file mode 100644 index 0000000000..88164813e0 --- /dev/null +++ b/common/src/comp/energy.rs @@ -0,0 +1,54 @@ +use specs::{Component, FlaggedStorage}; +use specs_idvs::IDVStorage; + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub struct Energy { + current: u32, + maximum: u32, + pub last_change: Option<(i32, f64, EnergySource)>, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub enum EnergySource { + CastSpell, + LevelUp, + Unknown, +} + +impl Energy { + pub fn new(amount: u32) -> Energy { + Energy { + current: amount, + maximum: amount, + last_change: None, + } + } + + pub fn current(&self) -> u32 { + self.current + } + + pub fn maximum(&self) -> u32 { + self.maximum + } + + pub fn set_to(&mut self, amount: u32, cause: EnergySource) { + let amount = amount.min(self.maximum); + self.last_change = Some((amount as i32 - self.current as i32, 0.0, cause)); + self.current = amount; + } + + pub fn change_by(&mut self, amount: i32, cause: EnergySource) { + self.current = ((self.current as i32 + amount).max(0) as u32).min(self.maximum); + self.last_change = Some((amount, 0.0, cause)); + } + + pub fn set_maximum(&mut self, amount: u32) { + self.maximum = amount; + self.current = self.current.min(self.maximum); + } +} + +impl Component for Energy { + type Storage = FlaggedStorage>; +} diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index 42f8e6e161..5f2a631c89 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -3,6 +3,7 @@ mod agent; mod body; mod character_state; mod controller; +mod energy; mod inputs; mod inventory; mod last; @@ -25,6 +26,7 @@ pub use controller::{ ControlEvent, Controller, ControllerInputs, Input, InputState, InventoryManip, MountState, Mounting, }; +pub use energy::Energy; pub use inputs::CanBuild; pub use inventory::{item, Inventory, InventoryUpdate, Item, ItemKind}; pub use last::Last; diff --git a/common/src/comp/stats.rs b/common/src/comp/stats.rs index e4eceeaaa1..532f6cb8be 100644 --- a/common/src/comp/stats.rs +++ b/common/src/comp/stats.rs @@ -19,12 +19,6 @@ pub enum HealthSource { Item, Unknown, } -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -pub enum EnergySource { - CastSpell, - LevelUp, - Unknown, -} #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub struct Health { @@ -33,13 +27,6 @@ pub struct Health { pub last_change: (f64, HealthChange), } -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -pub struct Energy { - current: u32, - maximum: u32, - pub last_change: Option<(i32, f64, EnergySource)>, -} - #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub struct Exp { current: u32, @@ -90,32 +77,6 @@ impl Health { } } -impl Energy { - pub fn current(&self) -> u32 { - self.current - } - - pub fn maximum(&self) -> u32 { - self.maximum - } - - pub fn set_to(&mut self, amount: u32, cause: EnergySource) { - let amount = amount.min(self.maximum); - self.last_change = Some((amount as i32 - self.current as i32, 0.0, cause)); - self.current = amount; - } - - pub fn change_by(&mut self, amount: i32, cause: EnergySource) { - self.current = ((self.current as i32 + amount).max(0) as u32).min(self.maximum); - self.last_change = Some((amount, 0.0, cause)); - } - - pub fn set_maximum(&mut self, amount: u32) { - self.maximum = amount; - self.current = self.current.min(self.maximum); - } -} - impl Exp { pub fn current(&self) -> u32 { self.current @@ -161,7 +122,6 @@ impl Level { pub struct Stats { pub name: String, pub health: Health, - pub energy: Energy, pub level: Level, pub exp: Exp, pub equipment: Equipment, @@ -204,11 +164,6 @@ impl Stats { current: 0, maximum: 50, }, - energy: Energy { - current: 200, - maximum: 200, - last_change: None, - }, equipment: Equipment { main: main, alt: None, @@ -229,12 +184,6 @@ impl Stats { self.health.current = amount; self } - - pub fn with_max_energy(mut self, amount: u32) -> Self { - self.energy.maximum = amount; - self.energy.current = amount; - self - } } impl Component for Stats { diff --git a/common/src/msg/ecs_packet.rs b/common/src/msg/ecs_packet.rs index e714416ff9..6e1a2a65a7 100644 --- a/common/src/msg/ecs_packet.rs +++ b/common/src/msg/ecs_packet.rs @@ -12,6 +12,7 @@ sum_type! { Player(comp::Player), CanBuild(comp::CanBuild), Stats(comp::Stats), + Energy(comp::Energy), LightEmitter(comp::LightEmitter), Item(comp::Item), Scale(comp::Scale), @@ -31,6 +32,7 @@ sum_type! { Player(PhantomData), CanBuild(PhantomData), Stats(PhantomData), + Energy(PhantomData), LightEmitter(PhantomData), Item(PhantomData), Scale(PhantomData), @@ -49,6 +51,7 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPacket::Player(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::CanBuild(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Stats(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::Energy(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Item(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Scale(comp) => sync::handle_insert(comp, entity, world), @@ -65,6 +68,7 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPacket::Player(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::CanBuild(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Stats(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::Energy(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Item(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Scale(comp) => sync::handle_modify(comp, entity, world), @@ -81,6 +85,7 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPhantom::Player(_) => sync::handle_remove::(entity, world), EcsCompPhantom::CanBuild(_) => sync::handle_remove::(entity, world), EcsCompPhantom::Stats(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::Energy(_) => sync::handle_remove::(entity, world), EcsCompPhantom::LightEmitter(_) => { sync::handle_remove::(entity, world) } diff --git a/common/src/state.rs b/common/src/state.rs index 6966d3b1cc..a111a5f1fa 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -110,6 +110,7 @@ impl State { ecs.register::(); ecs.register::(); ecs.register::(); + ecs.register::(); ecs.register::(); ecs.register::(); ecs.register::(); diff --git a/server/src/lib.rs b/server/src/lib.rs index 6a1575c772..6bf0557244 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -258,6 +258,7 @@ impl Server { state.write_component(entity, body); state.write_component(entity, comp::Stats::new(name, main)); + state.write_component(entity, comp::Energy::new(200)); state.write_component(entity, comp::Controller::default()); state.write_component(entity, comp::Pos(spawn_point)); state.write_component(entity, comp::Vel(Vec3::zero())); @@ -1184,6 +1185,7 @@ impl StateExt for State { .with(comp::Controller::default()) .with(body) .with(stats) + .with(comp::Energy::new(100)) .with(comp::Gravity(1.0)) .with(comp::CharacterState::default()) } diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs index 8fc04ea445..320a07a4dd 100644 --- a/server/src/sys/sentinel.rs +++ b/server/src/sys/sentinel.rs @@ -1,8 +1,8 @@ use super::SysTimer; use common::{ comp::{ - Body, CanBuild, Gravity, Item, LightEmitter, Mass, MountState, Mounting, Player, Scale, - Stats, Sticky, + Body, CanBuild, Energy, Gravity, Item, LightEmitter, Mass, MountState, Mounting, Player, + Scale, Stats, Sticky, }, msg::EcsCompPacket, sync::{EntityPackage, SyncPackage, Uid, UpdateTracker, WorldSyncExt}, @@ -40,6 +40,7 @@ pub struct TrackedComps<'a> { pub body: ReadStorage<'a, Body>, pub player: ReadStorage<'a, Player>, pub stats: ReadStorage<'a, Stats>, + pub energy: ReadStorage<'a, Energy>, pub can_build: ReadStorage<'a, CanBuild>, pub light_emitter: ReadStorage<'a, LightEmitter>, pub item: ReadStorage<'a, Item>, @@ -68,6 +69,10 @@ impl<'a> TrackedComps<'a> { .get(entity) .cloned() .map(|c| comps.push(c.into())); + self.energy + .get(entity) + .cloned() + .map(|c| comps.push(c.into())); self.can_build .get(entity) .cloned() @@ -108,6 +113,7 @@ pub struct ReadTrackers<'a> { pub body: ReadExpect<'a, UpdateTracker>, pub player: ReadExpect<'a, UpdateTracker>, pub stats: ReadExpect<'a, UpdateTracker>, + pub energy: ReadExpect<'a, UpdateTracker>, pub can_build: ReadExpect<'a, UpdateTracker>, pub light_emitter: ReadExpect<'a, UpdateTracker>, pub item: ReadExpect<'a, UpdateTracker>, @@ -129,6 +135,7 @@ impl<'a> ReadTrackers<'a> { .with_component(&comps.uid, &*self.body, &comps.body, filter) .with_component(&comps.uid, &*self.player, &comps.player, filter) .with_component(&comps.uid, &*self.stats, &comps.stats, filter) + .with_component(&comps.uid, &*self.energy, &comps.energy, filter) .with_component(&comps.uid, &*self.can_build, &comps.can_build, filter) .with_component( &comps.uid, @@ -152,6 +159,7 @@ pub struct WriteTrackers<'a> { body: WriteExpect<'a, UpdateTracker>, player: WriteExpect<'a, UpdateTracker>, stats: WriteExpect<'a, UpdateTracker>, + energy: WriteExpect<'a, UpdateTracker>, can_build: WriteExpect<'a, UpdateTracker>, light_emitter: WriteExpect<'a, UpdateTracker>, item: WriteExpect<'a, UpdateTracker>, @@ -169,6 +177,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) { trackers.body.record_changes(&comps.body); trackers.player.record_changes(&comps.player); trackers.stats.record_changes(&comps.stats); + trackers.energy.record_changes(&comps.energy); trackers.can_build.record_changes(&comps.can_build); trackers.light_emitter.record_changes(&comps.light_emitter); trackers.item.record_changes(&comps.item); @@ -185,6 +194,7 @@ pub fn register_trackers(world: &mut World) { world.register_tracker::(); world.register_tracker::(); world.register_tracker::(); + world.register_tracker::(); world.register_tracker::(); world.register_tracker::(); world.register_tracker::(); diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index e316298721..a318424935 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -531,6 +531,7 @@ impl Hud { let ecs = client.state().ecs(); let pos = ecs.read_storage::(); let stats = ecs.read_storage::(); + let energy = ecs.read_storage::(); let hp_floater_lists = ecs.read_storage::(); let interpolated = ecs.read_storage::(); let players = ecs.read_storage::(); @@ -615,22 +616,24 @@ impl Hud { let mut health_front_id_walker = self.ids.health_bar_fronts.walk(); let mut sct_bg_id_walker = self.ids.sct_bgs.walk(); let mut sct_id_walker = self.ids.scts.walk(); + // Render Health Bars - for (pos, stats, scale, hp_floater_list) in ( + for (pos, stats, energy, scale, hp_floater_list) in ( &entities, &pos, interpolated.maybe(), &stats, + &energy, scales.maybe(), hp_floater_lists.maybe(), // Potentially move this to its own loop ) .join() - .filter(|(entity, _, _, stats, _, _)| { + .filter(|(entity, _, _, stats, _, _, _)| { *entity != me && !stats.is_dead //&& stats.health.current() != stats.health.maximum() }) // Don't process health bars outside the vd (visibility further limited by ui backend) - .filter(|(_, pos, _, _, _, _)| { + .filter(|(_, pos, _, _, _, _, _)| { Vec2::from(pos.0 - player_pos) .map2(TerrainChunk::RECT_SIZE, |d: f32, sz| { d.abs() as f32 / sz as f32 @@ -638,10 +641,11 @@ impl Hud { .magnitude() < view_distance as f32 }) - .map(|(_, pos, interpolated, stats, scale, f)| { + .map(|(_, pos, interpolated, stats, energy, scale, f)| { ( interpolated.map_or(pos.0, |i| i.pos), stats, + energy, scale.map_or(1.0, |s| s.0), f, ) @@ -665,8 +669,7 @@ impl Hud { ); let hp_percentage = stats.health.current() as f64 / stats.health.maximum() as f64 * 100.0; - let energy_percentage = - stats.energy.current() as f64 / stats.energy.maximum() as f64 * 100.0; + let energy_percentage = energy.current() as f64 / energy.maximum() as f64 * 100.0; let hp_ani = (self.pulse * 4.0/*speed factor*/).cos() * 0.5 + 1.0; //Animation timer let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani); @@ -694,7 +697,7 @@ impl Hud { // % Mana Filling Rectangle::fill_with( [ - 73.0 * (stats.energy.current() as f64 / stats.energy.maximum() as f64), + 73.0 * (energy.current() as f64 / energy.maximum() as f64), 1.5, ], MANA_COLOR, @@ -1643,14 +1646,20 @@ impl Hud { // Skillbar // Get player stats - if let Some(stats) = client - .state() - .ecs() - .read_storage::() - .get(client.entity()) - { - Skillbar::new(global_state, &self.imgs, &self.fonts, &stats, self.pulse) - .set(self.ids.skillbar, ui_widgets); + let ecs = client.state().ecs(); + let stats = ecs.read_storage::(); + let energy = ecs.read_storage::(); + let entity = client.entity(); + if let (Some(stats), Some(energy)) = (stats.get(entity), energy.get(entity)) { + Skillbar::new( + global_state, + &self.imgs, + &self.fonts, + &stats, + &energy, + self.pulse, + ) + .set(self.ids.skillbar, ui_widgets); } // Chat box diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index 6b72c9ccee..cd935021c1 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -3,7 +3,7 @@ use super::{ /*FOCUS_COLOR, RAGE_COLOR,*/ HP_COLOR, LOW_HP_COLOR, MANA_COLOR, TEXT_COLOR, XP_COLOR, }; use crate::GlobalState; -use common::comp::{item::Debug, item::Tool, ItemKind, Stats}; +use common::comp::{item::Debug, item::Tool, Energy, ItemKind, Stats}; use conrod_core::{ color, widget::{self, Button, Image, Rectangle, Text}, @@ -97,6 +97,7 @@ pub struct Skillbar<'a> { imgs: &'a Imgs, fonts: &'a Fonts, stats: &'a Stats, + energy: &'a Energy, pulse: f32, #[conrod(common_builder)] common: widget::CommonBuilder, @@ -109,12 +110,14 @@ impl<'a> Skillbar<'a> { imgs: &'a Imgs, fonts: &'a Fonts, stats: &'a Stats, + energy: &'a Energy, pulse: f32, ) -> Self { Self { imgs, fonts: fonts, stats, + energy, global_state, current_resource: ResourceType::Mana, common: widget::CommonBuilder::default(), @@ -162,8 +165,7 @@ impl<'a> Widget for Skillbar<'a> { let hp_percentage = self.stats.health.current() as f64 / self.stats.health.maximum() as f64 * 100.0; - let energy_percentage = - self.stats.energy.current() as f64 / self.stats.energy.maximum() as f64 * 100.0; + let energy_percentage = self.energy.current() as f64 / self.energy.maximum() as f64 * 100.0; let scale = 2.0; @@ -839,8 +841,8 @@ impl<'a> Widget for Skillbar<'a> { .set(state.ids.health_text, ui); let energy_text = format!( "{}/{}", - self.stats.energy.current() as u32, - self.stats.energy.maximum() as u32 + self.energy.current() as u32, + self.energy.maximum() as u32 ); Text::new(&energy_text) .mid_top_with_margin_on(state.ids.energybar_bg, 6.0 * scale) From af8468315dc7c2cc22df46ecaaa79f65a82f150c Mon Sep 17 00:00:00 2001 From: Acrimon Date: Mon, 13 Jan 2020 16:38:10 +0100 Subject: [PATCH 49/51] Made color conversion way more accurate. --- common/src/util/mod.rs | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/common/src/util/mod.rs b/common/src/util/mod.rs index 7ccb111fd9..ba1457fc72 100644 --- a/common/src/util/mod.rs +++ b/common/src/util/mod.rs @@ -7,28 +7,40 @@ lazy_static::lazy_static! { use vek::{Mat3, Rgb, Rgba, Vec3}; -/// This is a fast approximation of powf. This should only be used when minor accuracy loss is acceptable. + #[inline(always)] #[allow(unsafe_code)] -fn approx_powf(b: f32, e: f32) -> f32 { - unsafe { - let b = b as f64; - let e = e as f64; - union Swagger { - f: f64, - a: [i32; 2], - } - let mut b = Swagger { f: b }; - b.a[1] = (e * (b.a[1] as f64 - 1072632447.0) + 1072632447.0) as i32; - b.a[0] = 0; - b.f as f32 +unsafe fn approx_powf_internal(mut a: f64, b: f64) -> f64 { + let mut e = b as i32; + union Swagger { + d: f64, + x: [i32; 2], } + let mut u = Swagger { d: a }; + u.x[1] = ((b - e as f64) * (u.x[1] as f64 - 1072632447.0) + 1072632447.0) as i32; + u.x[0] = 0; + let mut r = 1.0_f64; + while e > 0 { + if e & 1 > 0 { + r *= a; + } + a *= a; + e >>= 1; + } + return r * u.d; +} + +#[inline(always)] +#[allow(unsafe_code)] +fn approx_powf(a: f32, b: f32) -> f32 { + unsafe { approx_powf_internal(a as f64, b as f64) as f32 } } #[cfg(test)] mod approx_powf_tests { fn close_ei(a: f32, b: f32) -> bool { - (a - b < 1.0 && a - b > 0.0) || (b - a < 1.0 && b - a > 0.0) + const ACCEPTABLE_DIFF: f32 = 0.05; + (a - b < ACCEPTABLE_DIFF && a - b > 0.0) || (b - a < ACCEPTABLE_DIFF && b - a > 0.0) } #[test] From 71bd7f15ee25e1bf62c224c4e39ff8866504bece Mon Sep 17 00:00:00 2001 From: Acrimon Date: Mon, 13 Jan 2020 20:54:56 +0100 Subject: [PATCH 50/51] Even better conversion impl. --- Cargo.lock | 52 ++++++++++++++++---------------- common/src/util/mod.rs | 68 ++++-------------------------------------- 2 files changed, 31 insertions(+), 89 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aaa82d2295..c8f438c727 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,7 +145,7 @@ version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -193,7 +193,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -335,7 +335,7 @@ dependencies = [ [[package]] name = "cfg-if" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -585,7 +585,7 @@ name = "crc32fast" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -626,7 +626,7 @@ name = "crossbeam" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -657,7 +657,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -670,7 +670,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -698,7 +698,7 @@ name = "crossbeam-utils" version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -708,7 +708,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -765,7 +765,7 @@ name = "directories" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -784,7 +784,7 @@ name = "dirs-sys" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -906,7 +906,7 @@ name = "filetime" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1042,7 +1042,7 @@ name = "getrandom" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1552,7 +1552,7 @@ name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1671,10 +1671,10 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.20" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1694,7 +1694,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.20 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1747,7 +1747,7 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1759,7 +1759,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1801,7 +1801,7 @@ dependencies = [ "inotify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.20 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2041,7 +2041,7 @@ name = "parking_lot_core" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2210,7 +2210,7 @@ name = "prometheus" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2684,7 +2684,7 @@ name = "sdl2-sys" version = "0.32.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3187,7 +3187,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-compress 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.20 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "notify 5.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3607,7 +3607,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" "checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8" "checksum cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d" -"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "55e7ec0b74fe5897894cbc207092c577e87c52f8a59e8ca8d97ef37551f60a49" "checksum chashmap 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff41a3c2c1e39921b9003de14bf0439c7b63a9039637c291e1a64925d8ddfa45" "checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" @@ -3752,7 +3752,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum minifb 0.13.0 (git+https://github.com/emoon/rust_minifb.git)" = "" "checksum minimp3 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "542e9bed56860c5070a09939eee0e2df6f8f73f60304ddf56d620947e7017239" "checksum minimp3-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c109ae05c00ad6e3a53fab101e2f234545bdd010f0fffd399355efaf70817817" -"checksum mio 0.6.20 (registry+https://github.com/rust-lang/crates.io-index)" = "72f4261ee7ab03cd36dc99eea4db8be6e83e4164da470e0c84f6726d6c605855" +"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a785740271256c230f57462d3b83e52f998433a7062fc18f96d5999474a9f915" diff --git a/common/src/util/mod.rs b/common/src/util/mod.rs index ba1457fc72..37f726b938 100644 --- a/common/src/util/mod.rs +++ b/common/src/util/mod.rs @@ -7,74 +7,16 @@ lazy_static::lazy_static! { use vek::{Mat3, Rgb, Rgba, Vec3}; - -#[inline(always)] -#[allow(unsafe_code)] -unsafe fn approx_powf_internal(mut a: f64, b: f64) -> f64 { - let mut e = b as i32; - union Swagger { - d: f64, - x: [i32; 2], - } - let mut u = Swagger { d: a }; - u.x[1] = ((b - e as f64) * (u.x[1] as f64 - 1072632447.0) + 1072632447.0) as i32; - u.x[0] = 0; - let mut r = 1.0_f64; - while e > 0 { - if e & 1 > 0 { - r *= a; - } - a *= a; - e >>= 1; - } - return r * u.d; -} - -#[inline(always)] -#[allow(unsafe_code)] -fn approx_powf(a: f32, b: f32) -> f32 { - unsafe { approx_powf_internal(a as f64, b as f64) as f32 } -} - -#[cfg(test)] -mod approx_powf_tests { - fn close_ei(a: f32, b: f32) -> bool { - const ACCEPTABLE_DIFF: f32 = 0.05; - (a - b < ACCEPTABLE_DIFF && a - b > 0.0) || (b - a < ACCEPTABLE_DIFF && b - a > 0.0) - } - - #[test] - fn accuracy_1() { - let test_values: Vec = vec![3.0, 2.5, 1.5, 2.2]; - test_values.windows(2).for_each(|a| { - assert!(close_ei(a[0].powf(a[1]), super::approx_powf(a[0], a[1]))); - }); - } -} - #[inline(always)] pub fn srgb_to_linear(col: Rgb) -> Rgb { - #[inline(always)] - fn to_linear(x: f32) -> f32 { - if x <= 0.04045 { - x / 12.92 - } else { - approx_powf((x + 0.055) / 1.055, 2.4) - } - } - col.map(to_linear) + 0.012522878 * col + 0.682171111 * col * col + 0.305306011 * col * col * col } #[inline(always)] pub fn linear_to_srgb(col: Rgb) -> Rgb { - #[inline(always)] - fn to_srgb(x: f32) -> f32 { - if x <= 0.0031308 { - x * 12.92 - } else { - approx_powf(x, 1.0 / 2.4) * 1.055 - 0.055 - } - } - col.map(to_srgb) + let s1 = col.sqrt(); + let s2 = s1.sqrt(); + let s3 = s2.sqrt(); + 0.585122381 * s1 + 0.783140355 * s2 - 0.368262736 * s3 } #[inline(always)] pub fn srgba_to_linear(col: Rgba) -> Rgba { From d36b2636278f7e7502e71c4cc207b58e0ce73157 Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 13 Jan 2020 23:19:38 -0500 Subject: [PATCH 51/51] Branch on lower color values for more accurate speedy color conversion, add simple color conversion benchmarks --- common/Cargo.toml | 4 ++++ common/benches/chonk_benchmark.rs | 5 ++--- common/benches/color_benchmark.rs | 22 ++++++++++++++++++++++ common/src/util/mod.rs | 22 +++++++++++++++++----- 4 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 common/benches/color_benchmark.rs diff --git a/common/Cargo.toml b/common/Cargo.toml index adcdd3f834..6559126368 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -37,3 +37,7 @@ criterion = "0.3" [[bench]] name = "chonk_benchmark" harness = false + +[[bench]] +name = "color_benchmark" +harness = false diff --git a/common/benches/chonk_benchmark.rs b/common/benches/chonk_benchmark.rs index ee803378cb..d325f02888 100644 --- a/common/benches/chonk_benchmark.rs +++ b/common/benches/chonk_benchmark.rs @@ -1,7 +1,6 @@ -#[macro_use] -extern crate criterion; - use criterion::black_box; +use criterion::criterion_group; +use criterion::criterion_main; use criterion::Criterion; use vek::*; diff --git a/common/benches/color_benchmark.rs b/common/benches/color_benchmark.rs new file mode 100644 index 0000000000..5031cb4c06 --- /dev/null +++ b/common/benches/color_benchmark.rs @@ -0,0 +1,22 @@ +use criterion::black_box; +use criterion::criterion_group; +use criterion::criterion_main; +use criterion::Criterion; + +use vek::*; +use veloren_common::util::{linear_to_srgb, srgb_to_linear}; + +fn criterion_benchmark(c: &mut Criterion) { + c.bench_function("color: srgb to linear (0.5, 0.1, 0.5)", |b| { + b.iter(|| { + black_box(srgb_to_linear(black_box(Rgb::new(0.5, 0.1, 0.5)))); + }) + }); + c.bench_function("color: linear to srgb (0.5, 0.1, 0.5)", |b| { + b.iter(|| { + black_box(linear_to_srgb(black_box(Rgb::new(0.5, 0.1, 0.5)))); + }) + }); +} +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/common/src/util/mod.rs b/common/src/util/mod.rs index 37f726b938..5f49bf49ef 100644 --- a/common/src/util/mod.rs +++ b/common/src/util/mod.rs @@ -9,14 +9,26 @@ use vek::{Mat3, Rgb, Rgba, Vec3}; #[inline(always)] pub fn srgb_to_linear(col: Rgb) -> Rgb { - 0.012522878 * col + 0.682171111 * col * col + 0.305306011 * col * col * col + col.map(|c| { + if c <= 0.104 { + c * 0.08677088 + } else { + 0.012522878 * c + 0.682171111 * c * c + 0.305306011 * c * c * c + } + }) } #[inline(always)] pub fn linear_to_srgb(col: Rgb) -> Rgb { - let s1 = col.sqrt(); - let s2 = s1.sqrt(); - let s3 = s2.sqrt(); - 0.585122381 * s1 + 0.783140355 * s2 - 0.368262736 * s3 + col.map(|c| { + if c <= 0.0060 { + c * 11.500726 + } else { + let s1 = c.sqrt(); + let s2 = s1.sqrt(); + let s3 = s2.sqrt(); + 0.585122381 * s1 + 0.783140355 * s2 - 0.368262736 * s3 + } + }) } #[inline(always)] pub fn srgba_to_linear(col: Rgba) -> Rgba {