Add in-memory persistence for battlemode changes

This commit is contained in:
juliancoffee 2021-09-03 23:49:13 +03:00
parent fbe745fe1e
commit 1baa9e9879
5 changed files with 55 additions and 7 deletions

View File

@ -1,5 +1,7 @@
use crate::character::CharacterId;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use crate::comp::Pos; use crate::comp::Pos;
use hashbrown::HashMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use specs::Entity; use specs::Entity;
@ -75,6 +77,22 @@ pub struct PlayerPhysicsSettings {
pub settings: hashbrown::HashMap<uuid::Uuid, PlayerPhysicsSetting>, 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. /// Describe how players interact with other players.
/// ///
/// May be removed when we will discover better way /// May be removed when we will discover better way

View File

@ -6,6 +6,7 @@ use crate::{
use common::{ use common::{
comp, comp,
comp::{group, pet::is_tameable}, comp::{group, pet::is_tameable},
resources::BattleModeBuffer,
uid::{Uid, UidAllocator}, uid::{Uid, UidAllocator},
}; };
use common_base::span; use common_base::span;
@ -201,12 +202,14 @@ fn persist_entity(state: &mut State, entity: EcsEntity) -> EcsEntity {
Some(skill_set), Some(skill_set),
Some(inventory), Some(inventory),
Some(player_uid), Some(player_uid),
Some(player_info),
mut character_updater, mut character_updater,
) = ( ) = (
state.read_storage::<Presence>().get(entity), state.read_storage::<Presence>().get(entity),
state.read_storage::<comp::SkillSet>().get(entity), state.read_storage::<comp::SkillSet>().get(entity),
state.read_storage::<comp::Inventory>().get(entity), state.read_storage::<comp::Inventory>().get(entity),
state.read_storage::<Uid>().get(entity), state.read_storage::<Uid>().get(entity),
state.read_storage::<comp::Player>().get(entity),
state.ecs().fetch_mut::<CharacterUpdater>(), state.ecs().fetch_mut::<CharacterUpdater>(),
) { ) {
match presence.kind { match presence.kind {
@ -216,6 +219,13 @@ fn persist_entity(state: &mut State, entity: EcsEntity) -> EcsEntity {
.read_storage::<common::comp::Waypoint>() .read_storage::<common::comp::Waypoint>()
.get(entity) .get(entity)
.cloned(); .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);
battlemode_buffer.push(char_id, save);
}
// Get player's pets // Get player's pets
let alignments = state.ecs().read_storage::<comp::Alignment>(); let alignments = state.ecs().read_storage::<comp::Alignment>();

View File

@ -69,7 +69,7 @@ use common::{
comp::{item::MaterialStatManifest, CharacterAbility}, comp::{item::MaterialStatManifest, CharacterAbility},
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
recipe::default_recipe_book, recipe::default_recipe_book,
resources::TimeOfDay, resources::{BattleModeBuffer, TimeOfDay},
rtsim::RtSimEntity, rtsim::RtSimEntity,
slowjob::SlowJobPool, slowjob::SlowJobPool,
terrain::{TerrainChunk, TerrainChunkSize}, terrain::{TerrainChunk, TerrainChunkSize},
@ -196,8 +196,10 @@ impl Server {
let ecs_system_metrics = EcsSystemMetrics::new(&registry).unwrap(); let ecs_system_metrics = EcsSystemMetrics::new(&registry).unwrap();
let tick_metrics = TickMetrics::new(&registry).unwrap(); let tick_metrics = TickMetrics::new(&registry).unwrap();
let physics_metrics = PhysicsMetrics::new(&registry).unwrap(); let physics_metrics = PhysicsMetrics::new(&registry).unwrap();
let battlemode_buffer = BattleModeBuffer::default();
let mut state = State::server(); let mut state = State::server();
state.ecs_mut().insert(battlemode_buffer);
state.ecs_mut().insert(settings.clone()); state.ecs_mut().insert(settings.clone());
state.ecs_mut().insert(editable_settings); state.ecs_mut().insert(editable_settings);
state.ecs_mut().insert(DataDir { state.ecs_mut().insert(DataDir {

View File

@ -16,7 +16,7 @@ use common::{
Group, Inventory, Poise, Group, Inventory, Poise,
}, },
effect::Effect, effect::Effect,
resources::TimeOfDay, resources::{BattleModeBuffer, TimeOfDay},
slowjob::SlowJobPool, slowjob::SlowJobPool,
uid::{Uid, UidAllocator}, uid::{Uid, UidAllocator},
}; };
@ -496,8 +496,8 @@ impl StateExt for State {
}), }),
)); ));
// NOTE: By fetching the player_uid, we validated that the entity exists, and we // NOTE: By fetching the player_uid, we validated that the entity exists,
// call nothing that can delete it in any of the subsequent // and we call nothing that can delete it in any of the subsequent
// commands, so we can assume that all of these calls succeed, // commands, so we can assume that all of these calls succeed,
// justifying ignoring the result of insertion. // justifying ignoring the result of insertion.
self.write_component_ignore_entity_dead(entity, comp::Collider::Box { self.write_component_ignore_entity_dead(entity, comp::Collider::Box {
@ -567,6 +567,23 @@ impl StateExt for State {
} else { } else {
warn!("Player has no pos, cannot load {} pets", pets.len()); warn!("Player has no pos, cannot load {} pets", pets.len());
} }
let presences = self.ecs().read_storage::<Presence>();
let presence = presences.get(entity);
if let Some(Presence {
kind: PresenceKind::Character(char_id),
..
}) = 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>();
if let Some(mut player_info) = players.get_mut(entity) {
player_info.battle_mode = mode;
player_info.last_battlemode_change = Some(change);
}
}
}
} }
} }

View File

@ -174,9 +174,10 @@ impl<'a> System<'a> for Sys {
return Ok(()); return Ok(());
} }
// FIXME: // NOTE: this is just default value.
// Take last battle_mode and last battle_mode change //
// from in-memory persistence // 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 { let battle_mode = match read_data.settings.battle_mode {
ServerBattleMode::Global(mode) => mode, ServerBattleMode::Global(mode) => mode,
ServerBattleMode::PerPlayer { default: mode } => mode, ServerBattleMode::PerPlayer { default: mode } => mode,