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
This commit is contained in:
juliancoffee 2021-09-04 01:40:02 +03:00
parent 844e93e67b
commit 43d40c4efc
6 changed files with 55 additions and 36 deletions

View File

@ -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<uuid::Uuid, PlayerPhysicsSetting>,
}
/// Store of BattleMode cooldowns for players while they go offline
#[derive(Clone, Default, Debug)]
pub struct BattleModeBuffer {
map: HashMap<CharacterId, (BattleMode, Time)>,
}
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,

View File

@ -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::<Presence>().get(entity),
state.read_storage::<comp::SkillSet>().get(entity),
@ -211,6 +211,7 @@ fn persist_entity(state: &mut State, entity: EcsEntity) -> EcsEntity {
state.read_storage::<Uid>().get(entity),
state.read_storage::<comp::Player>().get(entity),
state.ecs().fetch_mut::<CharacterUpdater>(),
state.ecs().fetch_mut::<BattleModeBuffer>(),
) {
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::<BattleModeBuffer>();
if let Some(change) = player_info.last_battlemode_change {
let mode = player_info.battle_mode;
let save = (mode, change);

View File

@ -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<CharacterId, (BattleMode, Time)>,
}
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<World>,

View File

@ -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)]

View File

@ -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::<BattleModeBuffer>();
if let Some((mode, change)) = battlemode_buffer.pop(char_id) {
let mut players = self.ecs().write_storage::<comp::Player>();
let battlemode_buffer = self.ecs().fetch::<BattleModeBuffer>();
let mut players = self.ecs().write_storage::<comp::Player>();
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::<Settings>();
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;
}
}
}

View File

@ -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);