veloren/common/src/comp/controller.rs

262 lines
7.2 KiB
Rust
Raw Normal View History

use crate::{comp::inventory::slot::Slot, sync::Uid, util::Dir};
use serde::{Deserialize, Serialize};
use specs::{Component, FlaggedStorage};
use specs_idvs::IdvStorage;
2019-11-29 15:20:35 +00:00
use std::time::Duration;
2019-07-29 19:54:58 +00:00
use vek::*;
2019-06-09 14:20:20 +00:00
/// Default duration before an input is considered 'held'.
pub const DEFAULT_HOLD_DURATION: Duration = Duration::from_millis(200);
2019-11-29 15:20:35 +00:00
2020-04-04 17:51:41 +00:00
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum InventoryManip {
Pickup(Uid),
Collect(Vec3<i32>),
Use(Slot),
Swap(Slot, Slot),
Drop(Slot),
2020-07-14 20:11:39 +00:00
CraftRecipe(String),
2020-04-04 17:51:41 +00:00
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum GroupManip {
Invite(Uid),
Accept,
2020-07-19 21:49:18 +00:00
Decline,
Leave,
Kick(Uid),
AssignLeader(Uid),
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ControlEvent {
ToggleLantern,
Mount(Uid),
Unmount,
InventoryManip(InventoryManip),
GroupManip(GroupManip),
2020-03-24 07:38:16 +00:00
Respawn,
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub enum ControlAction {
SwapLoadout,
2020-03-26 15:05:17 +00:00
Wield,
GlideWield,
2020-03-26 15:05:17 +00:00
Unwield,
Sit,
2020-05-27 06:41:55 +00:00
Dance,
2020-03-26 15:05:17 +00:00
Stand,
2020-03-24 07:38:16 +00:00
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
enum Freshness {
New,
TickedOnce,
Old,
}
2019-11-29 15:20:35 +00:00
/// Whether a key is pressed or unpressed
/// and how long it has been in that state
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Input {
/// Should not be pub because duration should
/// always be reset when state is updated
2020-03-24 07:38:16 +00:00
pressed: bool,
/// Should only be updated by npc agents
/// through appropriate fn
2019-11-29 15:20:35 +00:00
duration: Duration,
2020-03-24 07:38:16 +00:00
/// How fresh is the last change to the input state
freshness: Freshness,
2019-11-29 15:20:35 +00:00
}
impl Input {
2020-03-24 07:38:16 +00:00
fn tick(&mut self, dt: Duration) {
// Increase how long input has been in current state
self.duration = self.duration.checked_add(dt).unwrap_or_default();
2020-03-24 07:38:16 +00:00
self.tick_freshness();
}
2020-03-23 17:13:44 +00:00
2020-03-24 07:38:16 +00:00
fn tick_freshness(&mut self) {
self.freshness = match self.freshness {
Freshness::New => Freshness::TickedOnce,
Freshness::TickedOnce => Freshness::Old,
Freshness::Old => Freshness::Old,
2020-03-23 17:13:44 +00:00
};
}
2020-03-24 07:38:16 +00:00
/// Update input with newer version
/// Used to update inputs with input recieved from clients
pub fn update_with_new(&mut self, new: Self) {
if self.pressed != new.pressed {
self.freshness = Freshness::New;
}
self.pressed = new.pressed;
self.duration = new.duration;
}
2020-03-23 17:13:44 +00:00
/// Whether input is being pressed down
2020-03-24 07:38:16 +00:00
pub fn is_pressed(&self) -> bool { self.pressed }
2020-03-23 17:13:44 +00:00
/// Whether it's the first frame this input has been pressed
2020-03-24 07:38:16 +00:00
pub fn is_just_pressed(&self) -> bool { self.is_pressed() && self.freshness != Freshness::Old }
2020-03-23 17:13:44 +00:00
/// Whether it's the first frame this input has been unpressed
2020-03-24 07:38:16 +00:00
pub fn is_just_unpressed(&self) -> bool {
!self.is_pressed() && self.freshness != Freshness::Old
}
2020-03-23 17:13:44 +00:00
/// Whether input has been pressed longer than
2019-11-29 15:20:35 +00:00
/// `DEFAULT_HOLD_DURATION`
pub fn is_held_down(&self) -> bool {
2020-02-09 21:15:10 +00:00
self.is_pressed() && self.duration >= DEFAULT_HOLD_DURATION
2019-11-29 15:20:35 +00:00
}
2020-03-23 17:13:44 +00:00
/// Whether input has been unpressed longer than
/// `DEFAULT_HOLD_DURATION`
pub fn is_held_up(&self) -> bool {
!self.is_pressed() && self.duration >= DEFAULT_HOLD_DURATION
}
/// Whether input has been pressed for longer than `threshold` duration
pub fn held_for_dur(&self, threshold: Duration) -> bool {
2020-03-07 21:03:10 +00:00
self.is_pressed() && self.duration >= threshold
2020-01-08 13:17:36 +00:00
}
2020-03-23 17:13:44 +00:00
/// Handles logic of updating state of Input
2020-03-24 07:38:16 +00:00
pub fn set_state(&mut self, pressed: bool) {
if self.pressed != pressed {
self.pressed = pressed;
self.duration = Duration::default();
self.freshness = Freshness::New;
}
}
2020-03-23 17:13:44 +00:00
2020-03-24 07:38:16 +00:00
/// Increases `input.duration` by `dur`
2019-11-29 15:20:35 +00:00
pub fn inc_dur(&mut self, dur: Duration) {
self.duration = self.duration.checked_add(dur).unwrap_or_default();
2019-11-29 15:20:35 +00:00
}
2020-03-24 07:38:16 +00:00
/// Returns `input.duration`
pub fn get_dur(&self) -> Duration { self.duration }
2019-11-29 15:20:35 +00:00
}
impl Default for Input {
fn default() -> Self {
Self {
2020-03-24 07:38:16 +00:00
pressed: false,
2019-11-29 15:20:35 +00:00
duration: Duration::default(),
2020-03-24 07:38:16 +00:00
freshness: Freshness::New,
2019-11-29 15:20:35 +00:00
}
}
}
2020-03-24 07:38:16 +00:00
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub enum Climb {
Up,
Down,
Hold,
}
2019-06-09 14:20:20 +00:00
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct ControllerInputs {
2019-11-29 15:20:35 +00:00
pub primary: Input,
pub secondary: Input,
2020-03-24 12:59:53 +00:00
pub ability3: Input,
2019-11-29 15:20:35 +00:00
pub jump: Input,
pub roll: Input,
pub glide: Input,
pub wall_leap: Input,
pub charge: Input,
2020-03-24 07:38:16 +00:00
pub climb: Option<Climb>,
pub swim: Input,
pub move_dir: Vec2<f32>,
pub look_dir: Dir,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct Controller {
pub inputs: ControllerInputs,
// TODO: consider SmallVec
pub events: Vec<ControlEvent>,
2020-03-24 07:38:16 +00:00
pub actions: Vec<ControlAction>,
}
2019-11-29 15:20:35 +00:00
impl ControllerInputs {
/// Updates all inputs, accounting for delta time
2020-03-24 07:38:16 +00:00
pub fn tick(&mut self, dt: Duration) {
self.primary.tick(dt);
self.secondary.tick(dt);
self.ability3.tick(dt);
self.jump.tick(dt);
self.roll.tick(dt);
self.glide.tick(dt);
self.wall_leap.tick(dt);
self.charge.tick(dt);
self.swim.tick(dt);
2020-03-24 07:38:16 +00:00
}
pub fn tick_freshness(&mut self) {
self.primary.tick_freshness();
self.secondary.tick_freshness();
self.ability3.tick_freshness();
self.jump.tick_freshness();
self.roll.tick_freshness();
self.glide.tick_freshness();
self.wall_leap.tick_freshness();
self.charge.tick_freshness();
self.swim.tick_freshness();
2020-03-24 07:38:16 +00:00
}
/// Updates Controller inputs with new version received from the client
pub fn update_with_new(&mut self, new: Self) {
self.primary.update_with_new(new.primary);
self.secondary.update_with_new(new.secondary);
self.ability3.update_with_new(new.ability3);
self.jump.update_with_new(new.jump);
self.roll.update_with_new(new.roll);
self.glide.update_with_new(new.glide);
self.wall_leap.update_with_new(new.wall_leap);
self.charge.update_with_new(new.charge);
self.climb = new.climb;
self.swim.update_with_new(new.swim);
2020-03-24 07:38:16 +00:00
self.move_dir = new.move_dir;
self.look_dir = new.look_dir;
}
2020-03-24 12:59:53 +00:00
pub fn holding_ability_key(&self) -> bool {
self.primary.is_pressed() || self.secondary.is_pressed() || self.ability3.is_pressed()
}
2019-11-29 15:20:35 +00:00
}
impl Controller {
2019-11-29 15:20:35 +00:00
/// Sets all inputs to default
pub fn reset(&mut self) { *self = Self::default(); }
pub fn clear_events(&mut self) { self.events.clear(); }
pub fn push_event(&mut self, event: ControlEvent) { self.events.push(event); }
2019-06-09 14:20:20 +00:00
}
impl Component for Controller {
type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
2019-06-09 14:20:20 +00:00
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum MountState {
Unmounted,
MountedBy(Uid),
}
impl Component for MountState {
type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Mounting(pub Uid);
impl Component for Mounting {
type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
}