diff --git a/client/src/lib.rs b/client/src/lib.rs index b3319391ba..f61d59e9c2 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -5,6 +5,7 @@ pub mod input; // Reexports pub use specs::Entity as EcsEntity; +pub use specs::join::Join; pub use crate::{ error::Error, input::Input, @@ -23,7 +24,7 @@ use common::{ state::State, terrain::TerrainChunk, net::PostBox, - msg::{ClientMsg, ServerMsg}, + msg::{ClientState, ClientMsg, ServerMsg}, }; const SERVER_TIMEOUT: f64 = 20.0; // Seconds @@ -33,14 +34,15 @@ pub enum Event { } pub struct Client { + client_state: ClientState, thread_pool: ThreadPool, last_ping: f64, - postbox: PostBox, + pub postbox: PostBox, tick: u64, state: State, - player: EcsEntity, + entity: EcsEntity, view_distance: u64, pending_chunks: HashSet>, @@ -55,24 +57,24 @@ impl Client { view_distance: u64, ) -> Result { + let mut client_state = ClientState::Disconnected; let mut postbox = PostBox::to(addr)?; // Send connection request - postbox.send_message(ClientMsg::Connect { - player, - }); + postbox.send_message(ClientMsg::Connect { player }); - // Wait for handshake from server - let (state, player) = match postbox.next_message() { - Some(ServerMsg::Handshake { ecs_state, player_entity }) => { + // Wait for initial sync + let (state, player_entity) = match postbox.next_message() { + Some(ServerMsg::InitialSync { ecs_state, player_entity_uid }) => { let mut state = State::from_state_package(ecs_state); - let player_entity = state.ecs().entity_from_uid(player_entity).ok_or(Error::ServerWentMad)?; + let player_entity = state.ecs().entity_from_uid(player_entity_uid).ok_or(Error::ServerWentMad)?; (state, player_entity) }, _ => return Err(Error::ServerWentMad), }; Ok(Self { + client_state, thread_pool: threadpool::Builder::new() .thread_name("veloren-worker".into()) .build(), @@ -82,7 +84,7 @@ impl Client { tick: 0, state, - player, + entity: player_entity, view_distance, pending_chunks: HashSet::new(), @@ -103,10 +105,10 @@ impl Client { #[allow(dead_code)] pub fn state_mut(&mut self) -> &mut State { &mut self.state } - /// Get the player entity + /// Get the player's entity #[allow(dead_code)] - pub fn player(&self) -> EcsEntity { - self.player + pub fn entity(&self) -> EcsEntity { + self.entity } /// Get the current tick number. @@ -146,7 +148,7 @@ impl Client { println!("Chunk at {:?}", k); }); - self.state.write_component(self.player, comp::Control { + self.state.write_component(self.entity, comp::Control { move_dir: input.move_dir, }); @@ -155,9 +157,9 @@ impl Client { // Update the server about the player's physics attributes match ( - self.state.read_storage().get(self.player).cloned(), - self.state.read_storage().get(self.player).cloned(), - self.state.read_storage().get(self.player).cloned(), + self.state.read_storage().get(self.entity).cloned(), + self.state.read_storage().get(self.entity).cloned(), + self.state.read_storage().get(self.entity).cloned(), ) { (Some(pos), Some(vel), Some(dir)) => { self.postbox.send_message(ClientMsg::PlayerPhysics { pos, vel, dir }); @@ -166,14 +168,14 @@ impl Client { } // Update the server about the player's currently playing animation and the previous one - if let Some(animation_history) = self.state.read_storage::().get(self.player).cloned() { + if let Some(animation_history) = self.state.read_storage::().get(self.entity).cloned() { if Some(animation_history.current) != animation_history.last { self.postbox.send_message(ClientMsg::PlayerAnimation(animation_history)); } } // Request chunks from the server - if let Some(pos) = self.state.read_storage::().get(self.player) { + if let Some(pos) = self.state.read_storage::().get(self.entity) { let chunk_pos = self.state.terrain().pos_key(pos.0.map(|e| e as i32)); for i in chunk_pos.x - 1..chunk_pos.x + 1 { @@ -213,12 +215,12 @@ impl Client { for msg in new_msgs { match msg { - ServerMsg::Handshake { .. } => return Err(Error::ServerWentMad), + ServerMsg::InitialSync { .. } => return Err(Error::ServerWentMad), ServerMsg::Shutdown => return Err(Error::ServerShutdown), ServerMsg::Ping => self.postbox.send_message(ClientMsg::Pong), ServerMsg::Pong => {}, ServerMsg::Chat(msg) => frontend_events.push(Event::Chat(msg)), - ServerMsg::SetPlayerEntity(uid) => self.player = self.state.ecs().entity_from_uid(uid).unwrap(), // TODO: Don't unwrap here! + ServerMsg::SetPlayerEntity(uid) => self.entity = self.state.ecs().entity_from_uid(uid).unwrap(), // TODO: Don't unwrap here! ServerMsg::EcsSync(sync_package) => self.state.ecs_mut().sync_with_package(sync_package), ServerMsg::EntityPhysics { entity, pos, vel, dir } => match self.state.ecs().entity_from_uid(entity) { Some(entity) => { @@ -238,6 +240,18 @@ impl Client { self.state.insert_chunk(key, *chunk); self.pending_chunks.remove(&key); }, + ServerMsg::StateAnswer(Ok(state)) => { + println!("ok state: {:?}", state); + self.client_state = state; + }, + ServerMsg::StateAnswer(Err((error, state))) => { + println!("err state: {:?}", state); + self.client_state = state; + }, + ServerMsg::ForceState { state } => { + println!("forced state: {:?}", state); + self.client_state = state; + }, } } } else if let Some(err) = self.postbox.error() { diff --git a/common/src/msg/client.rs b/common/src/msg/client.rs index 1f07ad25bb..3f1afe1370 100644 --- a/common/src/msg/client.rs +++ b/common/src/msg/client.rs @@ -1,15 +1,12 @@ use vek::*; +use super::ClientState; use crate::comp; -#[derive(Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum ClientMsg { - Connect { - player: comp::Player, - - }, - Character { - character: comp::Character, - }, + Connect { player: comp::Player }, + Character(comp::Character), + RequestState(ClientState), Ping, Pong, Chat(String), diff --git a/common/src/msg/mod.rs b/common/src/msg/mod.rs index b38939eeb2..9c3fafa00b 100644 --- a/common/src/msg/mod.rs +++ b/common/src/msg/mod.rs @@ -3,6 +3,13 @@ pub mod server; pub mod client; // Reexports -pub use self::server::ServerMsg; +pub use self::server::{ServerMsg, RequestStateError}; pub use self::client::ClientMsg; pub use self::ecs_packet::EcsPacket; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum ClientState { + Disconnected, + Spectator, + Character, +} diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index 3372b524fb..5ad7a023b2 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -3,15 +3,25 @@ use crate::{ comp, terrain::TerrainChunk, }; -use super::EcsPacket; +use super::{EcsPacket, ClientState}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum RequestStateError { + Denied, + Already, + Impossible, +} #[derive(Clone, Serialize, Deserialize)] pub enum ServerMsg { - Handshake { - ecs_state: sphynx::StatePackage, - player_entity: u64, + StateAnswer(Result), + ForceState { + state: ClientState, + }, + InitialSync { + ecs_state: sphynx::StatePackage, + player_entity_uid: u64, }, - Shutdown, Ping, Pong, Chat(String), @@ -31,4 +41,5 @@ pub enum ServerMsg { key: Vec3, chunk: Box, }, + Shutdown, } diff --git a/server/src/client.rs b/server/src/client.rs index c0e2eafe90..8dcb1edfce 100644 --- a/server/src/client.rs +++ b/server/src/client.rs @@ -2,19 +2,13 @@ use std::collections::HashMap; use specs::Entity as EcsEntity; use common::{ comp, - msg::{ServerMsg, ClientMsg}, + msg::{ServerMsg, ClientMsg, ClientState}, net::PostBox, }; use crate::Error; -#[derive(PartialEq)] -pub enum ClientState { - Connecting, - Connected, -} - pub struct Client { - pub state: ClientState, + pub client_state: ClientState, pub postbox: PostBox, pub last_ping: f64, } @@ -52,7 +46,7 @@ impl Clients { pub fn notify_connected(&mut self, msg: ServerMsg) { for client in self.clients.values_mut() { - if client.state == ClientState::Connected { + if client.client_state != ClientState::Disconnected { client.notify(msg.clone()); } } @@ -60,7 +54,7 @@ impl Clients { pub fn notify_connected_except(&mut self, except_entity: EcsEntity, msg: ServerMsg) { for (entity, client) in self.clients.iter_mut() { - if client.state == ClientState::Connected && *entity != except_entity { + if client.client_state != ClientState::Disconnected && *entity != except_entity { client.notify(msg.clone()); } } diff --git a/server/src/lib.rs b/server/src/lib.rs index a90bc04c3a..c2504c4912 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -8,10 +8,10 @@ pub mod cmd; // Reexports pub use crate::{error::Error, input::Input}; -use crate::{client::{Client, ClientState, Clients}, cmd::CHAT_COMMANDS}; +use crate::{client::{Client, Clients}, cmd::CHAT_COMMANDS}; use common::{ comp, - msg::{ClientMsg, ServerMsg}, + msg::{ClientState, ClientMsg, ServerMsg, RequestStateError}, net::PostOffice, state::{State, Uid}, terrain::TerrainChunk, @@ -115,7 +115,7 @@ impl Server { .with(character) } - pub fn create_player_character(state: &mut State, entity: EcsEntity, character: comp::Character) { + pub fn create_player_character(state: &mut State, entity: EcsEntity, client: &mut Client, character: comp::Character) { state.write_component(entity, character); state.write_component(entity, comp::phys::Pos(Vec3::zero())); state.write_component(entity, comp::phys::Vel(Vec3::zero())); @@ -128,6 +128,10 @@ impl Server { last: None, current: Animation::Idle }); + + // Tell the client his request was successful + client.notify(ServerMsg::StateAnswer(Ok(ClientState::Character))); + client.client_state = ClientState::Character; } /// Execute a single server tick, handle input and update the game state by the given duration @@ -171,10 +175,7 @@ impl Server { for (entity, player, pos) in ( &self.state.ecs().entities(), &self.state.ecs().read_storage::(), - &self - .state - .ecs() - .read_storage::(), + &self.state.ecs().read_storage::(), ) .join() { @@ -216,7 +217,7 @@ impl Server { self.clients.add( entity, Client { - state: ClientState::Connecting, + client_state: ClientState::Disconnected, postbox, last_ping: self.state.get_time(), }, @@ -247,27 +248,62 @@ impl Server { // Process incoming messages for msg in new_msgs { - match client.state { - ClientState::Connecting => match msg { - ClientMsg::Connect { player } => { - Self::initialize_client(state, entity, client, player); + match msg { + ClientMsg::RequestState(requested_state) => match requested_state { + ClientState::Spectator => match client.client_state { + // Use ClientMsg::Connect instead + ClientState::Disconnected => {}, + ClientState::Spectator => { + // Already + client.postbox.send_message(ServerMsg::StateAnswer( + Err((RequestStateError::Already, ClientState::Spectator)))); + }, + ClientState::Character => { + // Always allow + client.postbox.send_message(ServerMsg::StateAnswer( + Ok(ClientState::Spectator))); + }, + }, + // Use ClientMsg::Character instead + ClientState::Character => { unimplemented!("TODO: Check for previously used character"); }, + ClientState::Disconnected => disconnect = true, + }, + ClientMsg::Connect { player } => match client.client_state { + ClientState::Disconnected => Self::initialize_client(state, entity, client, player), + _ => {}, + }, + ClientMsg::Character(character) => match client.client_state { + ClientState::Spectator => Self::create_player_character(state, entity, client, character), + // Currently only possible from spectator + _ => disconnect = true, + }, + + // Always possible + ClientMsg::Ping => client.postbox.send_message(ServerMsg::Pong), + ClientMsg::Pong => {} + ClientMsg::Disconnect => disconnect = true, + + ClientMsg::Chat(msg) => match client.client_state { + ClientState::Disconnected => {} + _ => new_chat_msgs.push((entity, msg)), + }, + + ClientMsg::PlayerAnimation(animation_history) => match client.client_state { + ClientState::Character => { + state.write_component(entity, animation_history); } _ => disconnect = true, }, - ClientState::Connected => match msg { - ClientMsg::Connect { .. } => disconnect = true, // Not allowed when already connected - ClientMsg::Disconnect => disconnect = true, - ClientMsg::Character { character } => Self::create_player_character(state, entity, character), - ClientMsg::Ping => client.postbox.send_message(ServerMsg::Pong), - ClientMsg::Pong => {} - ClientMsg::Chat(msg) => new_chat_msgs.push((entity, msg)), - ClientMsg::PlayerAnimation(animation_history) => state.write_component(entity, animation_history), - ClientMsg::PlayerPhysics { pos, vel, dir } => { + ClientMsg::PlayerPhysics { pos, vel, dir } => match client.client_state { + ClientState::Character => { state.write_component(entity, pos); state.write_component(entity, vel); state.write_component(entity, dir); - } - ClientMsg::TerrainChunkRequest { key } => { + }, + _ => disconnect = true, + }, + ClientMsg::TerrainChunkRequest { key } => match client.client_state { + ClientState::Spectator | ClientState::Character => { match state.terrain().get_key(key) { Some(chunk) => {} /*client.postbox.send_message(ServerMsg::TerrainChunkUpdate { key, @@ -275,8 +311,9 @@ impl Server { }),*/ None => requested_chunks.push(key), } - } - }, + }, + ClientState::Disconnected => {}, + } } } } else if state.get_time() - client.last_ping > CLIENT_TIMEOUT || // Timeout @@ -290,7 +327,10 @@ impl Server { } if disconnect { + println!("Someone disconnected!"); disconnected_clients.push(entity); + client.postbox.send_message(ServerMsg::StateAnswer( + Err((RequestStateError::Impossible, ClientState::Disconnected)))); true } else { false @@ -345,13 +385,11 @@ impl Server { // Save player metadata (for example the username) state.write_component(entity, player); - client.state = ClientState::Connected; - - // Return a handshake with the state of the current world + // Return the state of the current world // (All components Sphynx tracks) - client.notify(ServerMsg::Handshake { + client.notify(ServerMsg::InitialSync { ecs_state: state.ecs().gen_state_package(), - player_entity: state + player_entity_uid: state .ecs() .uid_from_entity(entity) .unwrap() @@ -370,6 +408,10 @@ impl Server { animation_history: animation_history, }); } + + // Tell the client his request was successful + client.notify(ServerMsg::StateAnswer(Ok(ClientState::Spectator))); + client.client_state = ClientState::Spectator; } /// Sync client states with the most up to date information diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 051e2e155e..6d32bf1212 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -6,7 +6,10 @@ use crate::{ GlobalState, PlayState, PlayStateResult, }; use client::{self, Client}; -use common::clock::Clock; +use common::{ + clock::Clock, + msg::ClientMsg, +}; use std::{cell::RefCell, rc::Rc, time::Duration}; use ui::CharSelectionUi; use vek::*; @@ -67,9 +70,10 @@ impl PlayState for CharSelectionState { global_state.singleplayer = None; return PlayStateResult::Pop; }, - ui::Event::Play => return PlayStateResult::Switch( + ui::Event::Play => { + self.client.borrow_mut().postbox.send_message(ClientMsg::Character(self.char_selection_ui.character)); Box::new(SessionState::new(&mut global_state.window, self.client.clone())) - ), + }, } } diff --git a/voxygen/src/menu/char_selection/ui.rs b/voxygen/src/menu/char_selection/ui.rs index 48e337d56a..f3e73e65c9 100644 --- a/voxygen/src/menu/char_selection/ui.rs +++ b/voxygen/src/menu/char_selection/ui.rs @@ -6,7 +6,7 @@ use crate::{ use common::{ assets, comp::character::{ - self, + Character, Race, Gender, Head, @@ -353,17 +353,9 @@ pub struct CharSelectionUi { font_opensans: FontId, character_creation: bool, selected_char_no: Option, - race: Race, - gender: Gender, - head: Head, - chest: Chest, - belt: Belt, - pants: Pants, - hand: Hand, - foot: Foot, - weapon: Weapon, - creation_state: CreationState, character_name: String, + pub character: Character, + creation_state: CreationState, } impl CharSelectionUi { @@ -396,15 +388,7 @@ impl CharSelectionUi { character_creation: false, selected_char_no: None, character_name: "Character Name".to_string(), - race: Race::Human, - gender: Gender::Male, - head: Head::DefaultHead, - chest: Chest::DefaultChest, - belt: Belt::DefaultBelt, - pants: Pants::DefaultPants, - hand: Hand::DefaultHand, - foot: Foot::DefaultFoot, - weapon: Weapon::Sword, + character: Character::random(), creation_state: CreationState::Race, } } @@ -711,7 +695,7 @@ impl CharSelectionUi { .w_h(68.0, 68.0) .mid_left_of(self.ids.gender_bg) .set(self.ids.male, ui_widgets); - if Button::image(if let Gender::Male = self.gender { + if Button::image(if let Gender::Male = self.character.gender { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -722,14 +706,14 @@ impl CharSelectionUi { .set(self.ids.gender_1, ui_widgets) .was_clicked() { - self.gender = Gender::Male; + self.character.gender = Gender::Male; } // Female Image::new(self.imgs.female) .w_h(68.0, 68.0) .right_from(self.ids.male, 16.0) .set(self.ids.female, ui_widgets); - if Button::image(if let Gender::Female = self.gender { + if Button::image(if let Gender::Female = self.character.gender { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -740,7 +724,7 @@ impl CharSelectionUi { .set(self.ids.gender_2, ui_widgets) .was_clicked() { - self.gender = Gender::Female; + self.character.gender = Gender::Female; } // for alignment Rectangle::fill_with([458.0, 68.0], color::TRANSPARENT) @@ -748,7 +732,7 @@ impl CharSelectionUi { .set(self.ids.races_bg, ui_widgets); // TODO: If races where in some sort of array format we could do this in a loop // Human - Image::new(if let Gender::Male = self.gender { + Image::new(if let Gender::Male = self.character.gender { self.imgs.human_m } else { self.imgs.human_f @@ -756,7 +740,7 @@ impl CharSelectionUi { .w_h(68.0, 68.0) .mid_left_of(self.ids.races_bg) .set(self.ids.human, ui_widgets); - if Button::image(if let Race::Human = self.race { + if Button::image(if let Race::Human = self.character.race { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -767,11 +751,11 @@ impl CharSelectionUi { .set(self.ids.race_1, ui_widgets) .was_clicked() { - self.race = Race::Human; + self.character.race = Race::Human; } // Orc - Image::new(if let Gender::Male = self.gender { + Image::new(if let Gender::Male = self.character.gender { self.imgs.orc_m } else { self.imgs.orc_f @@ -779,7 +763,7 @@ impl CharSelectionUi { .w_h(68.0, 68.0) .right_from(self.ids.human, 10.0) .set(self.ids.orc, ui_widgets); - if Button::image(if let Race::Orc = self.race { + if Button::image(if let Race::Orc = self.character.race { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -790,10 +774,10 @@ impl CharSelectionUi { .set(self.ids.race_2, ui_widgets) .was_clicked() { - self.race = Race::Orc; + self.character.race = Race::Orc; } // Dwarf - Image::new(if let Gender::Male = self.gender { + Image::new(if let Gender::Male = self.character.gender { self.imgs.dwarf_m } else { self.imgs.dwarf_f @@ -801,7 +785,7 @@ impl CharSelectionUi { .w_h(68.0, 68.0) .right_from(self.ids.human, 10.0 * 2.0 + 68.0) .set(self.ids.dwarf, ui_widgets); - if Button::image(if let Race::Dwarf = self.race { + if Button::image(if let Race::Dwarf = self.character.race { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -812,10 +796,10 @@ impl CharSelectionUi { .set(self.ids.race_3, ui_widgets) .was_clicked() { - self.race = Race::Dwarf; + self.character.race = Race::Dwarf; } // Elf - Image::new(if let Gender::Male = self.gender { + Image::new(if let Gender::Male = self.character.gender { self.imgs.elf_m } else { self.imgs.elf_f @@ -823,7 +807,7 @@ impl CharSelectionUi { .w_h(68.0, 68.0) .right_from(self.ids.human, 10.0 * 3.0 + 68.0 * 2.0) .set(self.ids.elf, ui_widgets); - if Button::image(if let Race::Elf = self.race { + if Button::image(if let Race::Elf = self.character.race { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -834,10 +818,10 @@ impl CharSelectionUi { .set(self.ids.race_4, ui_widgets) .was_clicked() { - self.race = Race::Elf; + self.character.race = Race::Elf; } // Undead - Image::new(if let Gender::Male = self.gender { + Image::new(if let Gender::Male = self.character.gender { self.imgs.undead_m } else { self.imgs.undead_f @@ -845,7 +829,7 @@ impl CharSelectionUi { .w_h(68.0, 68.0) .right_from(self.ids.human, 10.0 * 4.0 + 68.0 * 3.0) .set(self.ids.undead, ui_widgets); - if Button::image(if let Race::Undead = self.race { + if Button::image(if let Race::Undead = self.character.race { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -856,17 +840,17 @@ impl CharSelectionUi { .set(self.ids.race_5, ui_widgets) .was_clicked() { - self.race = Race::Undead; + self.character.race = Race::Undead; } // Danari - Image::new(if let Gender::Male = self.gender { + Image::new(if let Gender::Male = self.character.gender { self.imgs.danari_m } else { self.imgs.danari_f }) .right_from(self.ids.human, 10.0 * 5.0 + 68.0 * 4.0) .set(self.ids.danari, ui_widgets); - if Button::image(if let Race::Danari = self.race { + if Button::image(if let Race::Danari = self.character.race { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -878,7 +862,7 @@ impl CharSelectionUi { .set(self.ids.race_6, ui_widgets) .was_clicked() { - self.race = Race::Danari; + self.character.race = Race::Danari; } // Description Headline and Text @@ -939,7 +923,7 @@ impl CharSelectionUi { \n\ Outcast communities consisting of these Blessed Danari have formed all over the land."; - let (race_str, race_desc) = match self.race { + let (race_str, race_desc) = match self.character.race { Race::Human => ("Humans", HUMAN_DESC), Race::Orc => ("Orcs", ORC_DESC), Race::Dwarf => ("Dwarves", DWARF_DESC), @@ -979,7 +963,7 @@ impl CharSelectionUi { .w_h(60.0, 60.0) .mid_left_of(self.ids.weapon_bg) .set(self.ids.sword_shield, ui_widgets); - if Button::image(if let Weapon::SwordShield = self.weapon { + if Button::image(if let Weapon::SwordShield = self.character.weapon { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -990,7 +974,7 @@ impl CharSelectionUi { .set(self.ids.weapon_1, ui_widgets) .was_clicked() { - self.weapon = Weapon::SwordShield; + self.character.weapon = Weapon::SwordShield; } // Daggers @@ -998,7 +982,7 @@ impl CharSelectionUi { .w_h(60.0, 60.0) .right_from(self.ids.sword_shield, 8.0) .set(self.ids.daggers, ui_widgets); - if Button::image(if let Weapon::Daggers = self.weapon { + if Button::image(if let Weapon::Daggers = self.character.weapon { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -1009,7 +993,7 @@ impl CharSelectionUi { .set(self.ids.weapon_2, ui_widgets) .was_clicked() { - self.weapon = Weapon::Daggers; + self.character.weapon = Weapon::Daggers; } // Sword @@ -1017,7 +1001,7 @@ impl CharSelectionUi { .w_h(60.0, 60.0) .right_from(self.ids.sword_shield, 8.0 * 2.0 + 60.0 * 1.0) .set(self.ids.sword, ui_widgets); - if Button::image(if let Weapon::Sword = self.weapon { + if Button::image(if let Weapon::Sword = self.character.weapon { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -1028,14 +1012,14 @@ impl CharSelectionUi { .set(self.ids.weapon_3, ui_widgets) .was_clicked() { - self.weapon = Weapon::Sword; + self.character.weapon = Weapon::Sword; } // Axe Image::new(self.imgs.axe) .w_h(60.0, 60.0) .right_from(self.ids.sword_shield, 8.0 * 3.0 + 60.0 * 2.0) .set(self.ids.axe, ui_widgets); - if Button::image(if let Weapon::Axe = self.weapon { + if Button::image(if let Weapon::Axe = self.character.weapon { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -1046,14 +1030,14 @@ impl CharSelectionUi { .set(self.ids.weapon_4, ui_widgets) .was_clicked() { - self.weapon = Weapon::Axe; + self.character.weapon = Weapon::Axe; } // Hammer Image::new(self.imgs.hammer) .w_h(60.0, 60.0) .right_from(self.ids.sword_shield, 8.0 * 4.0 + 60.0 * 3.0) .set(self.ids.hammer, ui_widgets); - if Button::image(if let Weapon::Hammer = self.weapon { + if Button::image(if let Weapon::Hammer = self.character.weapon { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -1064,14 +1048,14 @@ impl CharSelectionUi { .set(self.ids.weapon_5, ui_widgets) .was_clicked() { - self.weapon = Weapon::Hammer; + self.character.weapon = Weapon::Hammer; } // Bow Image::new(self.imgs.bow) .w_h(60.0, 60.0) .right_from(self.ids.sword_shield, 8.0 * 5.0 + 60.0 * 4.0) .set(self.ids.bow, ui_widgets); - if Button::image(if let Weapon::Bow = self.weapon { + if Button::image(if let Weapon::Bow = self.character.weapon { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -1082,14 +1066,14 @@ impl CharSelectionUi { .set(self.ids.weapon_6, ui_widgets) .was_clicked() { - self.weapon = Weapon::Bow; + self.character.weapon = Weapon::Bow; } // Staff Image::new(self.imgs.staff) .w_h(60.0, 60.0) .right_from(self.ids.sword_shield, 8.0 * 6.0 + 60.0 * 5.0) .set(self.ids.staff, ui_widgets); - if Button::image(if let Weapon::Staff = self.weapon { + if Button::image(if let Weapon::Staff = self.character.weapon { self.imgs.icon_border_pressed } else { self.imgs.icon_border @@ -1100,7 +1084,7 @@ impl CharSelectionUi { .set(self.ids.weapon_7, ui_widgets) .was_clicked() { - self.weapon = Weapon::Staff; + self.character.weapon = Weapon::Staff; } // TODO: Load these from files (or from the server???) @@ -1112,7 +1096,7 @@ impl CharSelectionUi { const BOW_DESC: &str = " MISSING "; const STAFF_DESC: &str = " MISSING "; - let (weapon_str, weapon_desc) = match self.weapon { + let (weapon_str, weapon_desc) = match self.character.weapon { Weapon::SwordShield => ("Sword and Shield", SWORDSHIELD_DESC), Weapon::Daggers => ("Daggers", DAGGERS_DESC), Weapon::Sword => ("Sword", SWORD_DESC), @@ -1459,7 +1443,7 @@ impl CharSelectionUi { .was_clicked() {}; // Beard -> Only active when "male" was chosen - if let Gender::Male = self.gender { + if let Gender::Male = self.character.gender { Text::new("Beard Style") .mid_top_with_margin_on(self.ids.hair_window, 340.0) .color(TEXT_COLOR) @@ -1490,7 +1474,7 @@ impl CharSelectionUi { // Color -> Picker // Brightness -> Slider BodyPart::Accessories => { - match self.race { + match self.character.race { Race::Human => { Text::new("Head Band") .mid_top_with_margin_on(self.ids.accessories_window, 60.0) diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index e89243fa67..0fd74edb59 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -112,7 +112,7 @@ impl Scene { .state() .ecs() .read_storage::() - .get(client.player()) + .get(client.entity()) .map(|pos| pos.0) .unwrap_or(Vec3::zero());