From 182d3c4815f9b69a5d56cdc09b82603834c01919 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Sat, 4 Sep 2021 01:40:02 +0300 Subject: [PATCH] Workaround of bug with global Player component * Set default value of battle_mode and last_battlemode_change explicitly if isn't found in battlemode_buffer --- common/src/resources.rs | 20 +------------------- server/src/events/player.rs | 6 +++--- server/src/lib.rs | 24 +++++++++++++++++++++++- server/src/settings.rs | 7 +++++++ server/src/state_ext.rs | 25 +++++++++++++++++++------ server/src/sys/msg/register.rs | 9 ++------- 6 files changed, 55 insertions(+), 36 deletions(-) diff --git a/common/src/resources.rs b/common/src/resources.rs index 688562c081..fee169e388 100644 --- a/common/src/resources.rs +++ b/common/src/resources.rs @@ -1,7 +1,5 @@ -use crate::character::CharacterId; #[cfg(not(target_arch = "wasm32"))] use crate::comp::Pos; -use hashbrown::HashMap; use serde::{Deserialize, Serialize}; #[cfg(not(target_arch = "wasm32"))] use specs::Entity; @@ -77,27 +75,11 @@ pub struct PlayerPhysicsSettings { pub settings: hashbrown::HashMap, } -/// Store of BattleMode cooldowns for players while they go offline -#[derive(Clone, Default, Debug)] -pub struct BattleModeBuffer { - map: HashMap, -} - -impl BattleModeBuffer { - pub fn push(&mut self, char_id: CharacterId, save: (BattleMode, Time)) { - self.map.insert(char_id, save); - } - - pub fn pop(&mut self, char_id: &CharacterId) -> Option<(BattleMode, Time)> { - self.map.remove(char_id) - } -} - /// Describe how players interact with other players. /// /// May be removed when we will discover better way /// to handle duels and murders -#[derive(Copy, Clone, Debug, Deserialize, Serialize)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, Deserialize, Serialize)] pub enum BattleMode { PvP, PvE, diff --git a/server/src/events/player.rs b/server/src/events/player.rs index 517ec11819..0bd57edab1 100644 --- a/server/src/events/player.rs +++ b/server/src/events/player.rs @@ -1,12 +1,11 @@ use super::Event; use crate::{ client::Client, metrics::PlayerMetrics, persistence::character_updater::CharacterUpdater, - presence::Presence, state_ext::StateExt, Server, + presence::Presence, state_ext::StateExt, BattleModeBuffer, Server, }; use common::{ comp, comp::{group, pet::is_tameable}, - resources::BattleModeBuffer, uid::{Uid, UidAllocator}, }; use common_base::span; @@ -204,6 +203,7 @@ fn persist_entity(state: &mut State, entity: EcsEntity) -> EcsEntity { Some(player_uid), Some(player_info), mut character_updater, + mut battlemode_buffer, ) = ( state.read_storage::().get(entity), state.read_storage::().get(entity), @@ -211,6 +211,7 @@ fn persist_entity(state: &mut State, entity: EcsEntity) -> EcsEntity { state.read_storage::().get(entity), state.read_storage::().get(entity), state.ecs().fetch_mut::(), + state.ecs().fetch_mut::(), ) { match presence.kind { PresenceKind::Character(char_id) => { @@ -220,7 +221,6 @@ fn persist_entity(state: &mut State, entity: EcsEntity) -> EcsEntity { .get(entity) .cloned(); // Store last battle mode change - let mut battlemode_buffer = state.ecs().fetch_mut::(); if let Some(change) = player_info.last_battlemode_change { let mode = player_info.battle_mode; let save = (mode, change); diff --git a/server/src/lib.rs b/server/src/lib.rs index 227a9b4379..736f2e7392 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -64,12 +64,13 @@ use crate::{ use common::grid::Grid; use common::{ assets::AssetExt, + character::CharacterId, cmd::ChatCommand, comp, comp::{item::MaterialStatManifest, CharacterAbility}, event::{EventBus, ServerEvent}, recipe::default_recipe_book, - resources::{BattleModeBuffer, TimeOfDay}, + resources::{BattleMode, Time, TimeOfDay}, rtsim::RtSimEntity, slowjob::SlowJobPool, terrain::{TerrainChunk, TerrainChunkSize}, @@ -109,6 +110,7 @@ use crate::{ persistence::{DatabaseSettings, SqlLogMode}, sys::terrain, }; +use hashbrown::HashMap; use std::sync::RwLock; #[cfg(feature = "plugins")] @@ -152,6 +154,26 @@ enum DisconnectType { #[derive(Copy, Clone)] pub struct TickStart(Instant); +/// Store of BattleMode cooldowns for players while they go offline +#[derive(Clone, Default, Debug)] +pub struct BattleModeBuffer { + map: HashMap, +} + +impl BattleModeBuffer { + pub fn push(&mut self, char_id: CharacterId, save: (BattleMode, Time)) { + self.map.insert(char_id, save); + } + + pub fn get(&self, char_id: &CharacterId) -> Option<&(BattleMode, Time)> { + self.map.get(char_id) + } + + pub fn pop(&mut self, char_id: &CharacterId) -> Option<(BattleMode, Time)> { + self.map.remove(char_id) + } +} + pub struct Server { state: State, world: Arc, diff --git a/server/src/settings.rs b/server/src/settings.rs index f2c7004d29..d3cd0ace6c 100644 --- a/server/src/settings.rs +++ b/server/src/settings.rs @@ -53,6 +53,13 @@ impl ServerBattleMode { ServerBattleMode::PerPlayer { .. } => true, } } + + pub fn default_mode(&self) -> BattleMode { + match self { + ServerBattleMode::Global(mode) => *mode, + ServerBattleMode::PerPlayer { default: mode } => *mode, + } + } } #[derive(Clone, Debug, Serialize, Deserialize)] diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs index 08ff295c36..d51463ae7e 100644 --- a/server/src/state_ext.rs +++ b/server/src/state_ext.rs @@ -5,7 +5,7 @@ use crate::{ presence::{Presence, RepositionOnChunkLoad}, settings::Settings, sys::sentinel::DeletedEntities, - wiring, SpawnPoint, + wiring, BattleModeBuffer, SpawnPoint, }; use common::{ character::CharacterId, @@ -16,7 +16,7 @@ use common::{ Group, Inventory, Poise, }, effect::Effect, - resources::{BattleModeBuffer, TimeOfDay}, + resources::TimeOfDay, slowjob::SlowJobPool, uid::{Uid, UidAllocator}, }; @@ -575,12 +575,25 @@ impl StateExt for State { .. }) = presence { - let mut battlemode_buffer = self.ecs().fetch_mut::(); - if let Some((mode, change)) = battlemode_buffer.pop(char_id) { - let mut players = self.ecs().write_storage::(); + let battlemode_buffer = self.ecs().fetch::(); + let mut players = self.ecs().write_storage::(); + if let Some((mode, change)) = battlemode_buffer.get(char_id) { + if let Some(mut player_info) = players.get_mut(entity) { + player_info.battle_mode = *mode; + player_info.last_battlemode_change = Some(*change); + } + } else { + // FIXME: + // ??? + // + // This probably shouldn't exist, + // but without this code, character gets battle_mode from + // another character on this account. + let settings = self.ecs().read_resource::(); + let mode = settings.battle_mode.default_mode(); if let Some(mut player_info) = players.get_mut(entity) { player_info.battle_mode = mode; - player_info.last_battlemode_change = Some(change); + player_info.last_battlemode_change = None; } } } diff --git a/server/src/sys/msg/register.rs b/server/src/sys/msg/register.rs index 682b8405a0..e5e0f5ea57 100644 --- a/server/src/sys/msg/register.rs +++ b/server/src/sys/msg/register.rs @@ -2,7 +2,6 @@ use crate::{ client::Client, login_provider::{LoginProvider, PendingLogin}, metrics::PlayerMetrics, - settings::ServerBattleMode, EditableSettings, Settings, }; use common::{ @@ -176,12 +175,8 @@ impl<'a> System<'a> for Sys { // NOTE: this is just default value. // - // It will be overwritten in ServerExt::update_character_data - // from stored last battlemode change if such exists. - let battle_mode = match read_data.settings.battle_mode { - ServerBattleMode::Global(mode) => mode, - ServerBattleMode::PerPlayer { default: mode } => mode, - }; + // It will be overwritten in ServerExt::update_character_data. + let battle_mode = read_data.settings.battle_mode.default_mode(); let player = Player::new(username, battle_mode, uuid, None); let admin = read_data.editable_settings.admins.get(&uuid);