Cooldowns

- Add last_battlemode_change to Player component
- check on last_battlemode_change in handle_battlemode
- set last_battlemode_change after setting battlemode
- still are not persisted in any way
This commit is contained in:
juliancoffee 2021-08-31 18:55:28 +03:00
parent 85e8c50d35
commit fbe745fe1e
3 changed files with 57 additions and 38 deletions

View File

@ -3,7 +3,7 @@ use specs::{Component, DerefFlaggedStorage, NullStorage};
use specs_idvs::IdvStorage;
use uuid::Uuid;
use crate::resources::BattleMode;
use crate::resources::{BattleMode, Time};
const MAX_ALIAS_LEN: usize = 32;
@ -20,6 +20,7 @@ pub enum DisconnectReason {
pub struct Player {
pub alias: String,
pub battle_mode: BattleMode,
pub last_battlemode_change: Option<Time>,
uuid: Uuid,
}
@ -30,10 +31,16 @@ impl BattleMode {
}
impl Player {
pub fn new(alias: String, battle_mode: BattleMode, uuid: Uuid) -> Self {
pub fn new(
alias: String,
battle_mode: BattleMode,
uuid: Uuid,
last_battlemode_change: Option<Time>,
) -> Self {
Self {
alias,
battle_mode,
last_battlemode_change,
uuid,
}
}

View File

@ -34,7 +34,7 @@ use common::{
event::{EventBus, ServerEvent},
generation::EntityInfo,
npc::{self, get_npc_name},
resources::{BattleMode, PlayerPhysicsSettings, TimeOfDay},
resources::{BattleMode, PlayerPhysicsSettings, Time, TimeOfDay},
terrain::{Block, BlockKind, SpriteKind, TerrainChunkSize},
uid::Uid,
vol::RectVolSize,
@ -55,7 +55,6 @@ use vek::*;
use wiring::{Circuit, Wire, WiringAction, WiringActionEffect, WiringElement};
use world::{site::SiteKind, util::Sampler};
use std::ops::DerefMut;
use tracing::{error, info, warn};
pub trait ChatCommandExt {
@ -3128,12 +3127,11 @@ fn handle_battlemode(
.get(chunk_pos)
.ok_or("Cannot get current chunk for target")?;
// search for towns in chunk
//
// NOTE: this code finds town even if it is far from it.
// Does it count plant fields?
let site_ids = &chunk.sites;
let mut in_town = false;
for site_id in site_ids.iter() {
// NOTE: this code finds town even if it is far from actual
// houses in settlement. Is it because of plant fields?
let site = index.sites.get(*site_id);
if matches!(site.kind, SiteKind::Settlement(_)) {
in_town = true;
@ -3151,12 +3149,40 @@ fn handle_battlemode(
}
let mut players = ecs.write_storage::<comp::Player>();
let mut player = players
let mut player_info = players
.get_mut(target)
.ok_or("Cannot get player component for target")?;
// FIXME: handle cooldown before merge here!
//
set_battlemode(&mode, player.deref_mut(), server, client)
let time = ecs.read_resource::<Time>();
if let Some(Time(last_change)) = player_info.last_battlemode_change {
const COOLDOWN: f64 = 60.0 * 5.0;
let Time(time) = *time;
let elapsed = time - last_change;
if elapsed < COOLDOWN {
#[rustfmt::skip]
let msg = format!(
"You can switch battlemode only once in {:.0} seconds. \
Last change was {:.0} seconds before",
COOLDOWN, elapsed,
);
return Err(msg);
}
}
let mode = match mode.as_str() {
"pvp" => BattleMode::PvP,
"pve" => BattleMode::PvE,
_ => return Err("Available modes: pvp, pve".to_owned()),
};
player_info.battle_mode = mode;
player_info.last_battlemode_change = Some(*time);
server.notify_client(
client,
ServerGeneral::server_msg(
ChatType::CommandInfo,
format!("New battle mode: {:?}", mode),
),
);
Ok(())
} else {
let players = ecs.read_storage::<comp::Player>();
let player = players
@ -3180,42 +3206,27 @@ fn handle_battlemode_force(
args: Vec<String>,
action: &ChatCommand,
) -> CmdResult<()> {
let mode = parse_args!(args, String).ok_or_else(|| action.help_string())?;
let ecs = server.state.ecs();
let settings = ecs.read_resource::<Settings>();
if !settings.battle_mode.allow_choosing() {
server.notify_client(
client,
ServerGeneral::server_msg(
ChatType::CommandInfo,
"Warning! Forcing battle mode while not enabled in settings!".to_owned(),
),
);
return Err("Command disabled in server settings".to_owned());
}
let mut players = ecs.write_storage::<comp::Player>();
let mut player = players
.get_mut(target)
.ok_or("Cannot get player component for target")?;
set_battlemode(&mode, player.deref_mut(), server, client)
}
fn set_battlemode(
mode: &str,
player_info: &mut comp::Player,
server: &Server,
client: EcsEntity,
) -> CmdResult<()> {
let mode = match mode {
let mode = parse_args!(args, String).ok_or_else(|| action.help_string())?;
let mode = match mode.as_str() {
"pvp" => BattleMode::PvP,
"pve" => BattleMode::PvE,
_ => return Err("Available modes: pvp, pve".to_owned()),
};
let mut players = ecs.write_storage::<comp::Player>();
let mut player_info = players
.get_mut(target)
.ok_or("Cannot get player component for target")?;
player_info.battle_mode = mode;
server.notify_client(
client,
ServerGeneral::server_msg(
ChatType::CommandInfo,
format!("New battle mode: {:?}", player_info.battle_mode),
format!("Set battle mode to: {:?}", mode),
),
);
Ok(())

View File

@ -174,14 +174,15 @@ impl<'a> System<'a> for Sys {
return Ok(());
}
// FIXME:
// Take last battle_mode and last battle_mode change
// from in-memory persistence
let battle_mode = match read_data.settings.battle_mode {
ServerBattleMode::Global(mode) => mode,
// FIXME:
// Should this use just default battle_mode
// or should we take it from last change?
ServerBattleMode::PerPlayer { default: mode } => mode,
};
let player = Player::new(username, battle_mode, uuid);
let player = Player::new(username, battle_mode, uuid, None);
let admin = read_data.editable_settings.admins.get(&uuid);
if !player.is_valid() {