use crate::{ comp::{ inventory::slot::{EquipSlot, InvSlotId, Slot}, invite::{InviteKind, InviteResponse}, BuffKind, }, trade::{TradeAction, TradeId}, uid::Uid, util::Dir, }; use serde::{Deserialize, Serialize}; use specs::{Component, DerefFlaggedStorage}; use specs_idvs::IdvStorage; use std::collections::BTreeMap; use vek::*; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub enum InventoryEvent { Pickup(Uid), Collect(Vec3), Swap(InvSlotId, InvSlotId), SplitSwap(InvSlotId, InvSlotId), Drop(InvSlotId), SplitDrop(InvSlotId), CraftRecipe(String), } #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] pub enum InventoryAction { Swap(EquipSlot, Slot), Drop(EquipSlot), Use(Slot), } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub enum InventoryManip { Pickup(Uid), Collect(Vec3), Use(Slot), Swap(Slot, Slot), SplitSwap(Slot, Slot), Drop(Slot), SplitDrop(Slot), CraftRecipe(String), } impl From for InventoryManip { fn from(inv_action: InventoryAction) -> Self { match inv_action { InventoryAction::Use(slot) => Self::Use(slot), InventoryAction::Swap(equip, slot) => Self::Swap(Slot::Equip(equip), slot), InventoryAction::Drop(equip) => Self::Drop(Slot::Equip(equip)), } } } impl From for InventoryManip { fn from(inv_event: InventoryEvent) -> Self { match inv_event { InventoryEvent::Pickup(pickup) => Self::Pickup(pickup), InventoryEvent::Collect(collect) => Self::Collect(collect), InventoryEvent::Swap(inv1, inv2) => { Self::Swap(Slot::Inventory(inv1), Slot::Inventory(inv2)) }, InventoryEvent::SplitSwap(inv1, inv2) => { Self::SplitSwap(Slot::Inventory(inv1), Slot::Inventory(inv2)) }, InventoryEvent::Drop(inv) => Self::Drop(Slot::Inventory(inv)), InventoryEvent::SplitDrop(inv) => Self::SplitDrop(Slot::Inventory(inv)), InventoryEvent::CraftRecipe(recipe) => Self::CraftRecipe(recipe), } } } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub enum GroupManip { Leave, Kick(Uid), AssignLeader(Uid), } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub enum ControlEvent { //ToggleLantern, EnableLantern, DisableLantern, Interact(Uid), InitiateInvite(Uid, InviteKind), InviteResponse(InviteResponse), PerformTradeAction(TradeId, TradeAction), Mount(Uid), Unmount, InventoryEvent(InventoryEvent), GroupManip(GroupManip), RemoveBuff(BuffKind), Respawn, } #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] pub enum ControlAction { SwapEquippedWeapons, InventoryAction(InventoryAction), Wield, GlideWield, Unwield, Sit, Dance, Sneak, Stand, Talk, StartInput { input: InputKind, target: Option, // Some inputs need a selected position, such as mining select_pos: Option>, }, CancelInput(InputKind), } impl ControlAction { pub fn basic_input(input: InputKind) -> Self { ControlAction::StartInput { input, target: None, select_pos: None, } } } #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Ord, PartialOrd)] #[repr(u32)] pub enum InputKind { Primary = 0, Secondary = 1, Ability(usize) = 2, Roll = 3, Jump = 4, Fly = 5, } impl InputKind { pub fn is_ability(self) -> bool { matches!(self, Self::Primary | Self::Secondary | Self::Ability(_)) } } #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct InputAttr { pub select_pos: Option>, } #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] pub enum Climb { Up, Down, Hold, } #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] pub struct ControllerInputs { pub climb: Option, pub move_dir: Vec2, pub move_z: f32, /* z axis (not combined with move_dir because they may have independent * limits) */ pub look_dir: Dir, pub select_pos: Option>, } #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] pub struct Controller { pub inputs: ControllerInputs, pub queued_inputs: BTreeMap, // TODO: consider SmallVec pub events: Vec, pub actions: Vec, } impl ControllerInputs { /// Updates Controller inputs with new version received from the client pub fn update_with_new(&mut self, new: Self) { self.climb = new.climb; self.move_dir = new.move_dir; self.move_z = new.move_z; self.look_dir = new.look_dir; self.select_pos = new.select_pos; } } impl Controller { /// 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); } } impl Component for Controller { type Storage = IdvStorage; } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub enum MountState { Unmounted, MountedBy(Uid), } impl Component for MountState { type Storage = DerefFlaggedStorage>; } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Mounting(pub Uid); impl Component for Mounting { type Storage = DerefFlaggedStorage>; }