veloren/common/src/comp/controller.rs

326 lines
8.8 KiB
Rust
Raw Normal View History

use crate::{
comp::{
2021-11-11 22:55:14 +00:00
ability,
2023-05-04 10:23:46 +00:00
dialogue::Subject,
inventory::{
item::tool::ToolKind,
slot::{EquipSlot, InvSlotId, Slot},
},
invite::{InviteKind, InviteResponse},
2021-03-21 17:45:01 +00:00
BuffKind,
},
2023-04-17 13:38:41 +00:00
mounting::VolumePos,
trade::{TradeAction, TradeId},
uid::Uid,
util::Dir,
};
use serde::{Deserialize, Serialize};
use specs::Component;
2021-03-21 16:09:16 +00:00
use std::collections::BTreeMap;
2019-07-29 19:54:58 +00:00
use vek::*;
2019-06-09 14:20:20 +00:00
2022-09-08 19:51:02 +00:00
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum InventoryEvent {
2020-04-04 17:51:41 +00:00
Pickup(Uid),
Swap(InvSlotId, InvSlotId),
2021-03-02 00:08:46 +00:00
SplitSwap(InvSlotId, InvSlotId),
Drop(InvSlotId),
SplitDrop(InvSlotId),
2021-04-17 16:24:33 +00:00
Sort,
2021-04-17 14:58:43 +00:00
CraftRecipe {
2021-10-05 21:27:11 +00:00
craft_event: CraftEvent,
2023-04-17 13:38:41 +00:00
craft_sprite: Option<VolumePos>,
2021-04-17 14:58:43 +00:00
},
2020-04-04 17:51:41 +00:00
}
2022-09-08 19:51:02 +00:00
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum InventoryAction {
Swap(EquipSlot, Slot),
Drop(EquipSlot),
Use(Slot),
2021-04-17 16:24:33 +00:00
Sort,
Collect(Vec3<i32>),
2021-02-07 16:57:41 +00:00
}
2022-09-08 19:51:02 +00:00
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum InventoryManip {
Pickup(Uid),
2023-03-03 23:21:37 +00:00
Collect {
sprite_pos: Vec3<i32>,
2023-03-10 04:01:37 +00:00
/// If second field is `true`, item will be consumed on collection.
2023-03-03 23:21:37 +00:00
required_item: Option<(InvSlotId, bool)>,
},
Use(Slot),
Swap(Slot, Slot),
2021-03-02 00:08:46 +00:00
SplitSwap(Slot, Slot),
Drop(Slot),
SplitDrop(Slot),
2021-04-17 16:24:33 +00:00
Sort,
2021-04-17 14:58:43 +00:00
CraftRecipe {
2021-10-05 21:27:11 +00:00
craft_event: CraftEvent,
2023-04-17 13:38:41 +00:00
craft_sprite: Option<VolumePos>,
2021-04-17 14:58:43 +00:00
},
SwapEquippedWeapons,
}
impl From<InventoryEvent> for InventoryManip {
fn from(inv_event: InventoryEvent) -> Self {
match inv_event {
InventoryEvent::Pickup(pickup) => Self::Pickup(pickup),
InventoryEvent::Swap(inv1, inv2) => {
Self::Swap(Slot::Inventory(inv1), Slot::Inventory(inv2))
},
InventoryEvent::SplitSwap(inv1, inv2) => {
2021-03-02 00:08:46 +00:00
Self::SplitSwap(Slot::Inventory(inv1), Slot::Inventory(inv2))
},
InventoryEvent::Drop(inv) => Self::Drop(Slot::Inventory(inv)),
2021-04-17 18:35:48 +00:00
InventoryEvent::SplitDrop(inv) => Self::SplitDrop(Slot::Inventory(inv)),
2021-04-17 16:24:33 +00:00
InventoryEvent::Sort => Self::Sort,
2021-04-17 18:35:48 +00:00
InventoryEvent::CraftRecipe {
2021-10-05 21:27:11 +00:00
craft_event,
2021-04-17 18:35:48 +00:00
craft_sprite,
} => Self::CraftRecipe {
2021-10-05 21:27:11 +00:00
craft_event,
2021-04-17 18:35:48 +00:00
craft_sprite,
},
}
}
}
2022-09-08 19:51:02 +00:00
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
2021-10-05 21:27:11 +00:00
pub enum CraftEvent {
Simple {
recipe: String,
slots: Vec<(u32, InvSlotId)>,
2022-08-12 00:47:48 +00:00
amount: u32,
},
2021-10-05 21:27:11 +00:00
Salvage(InvSlotId),
// TODO: Maybe look at making this more general when there are more modular recipes?
ModularWeapon {
primary_component: InvSlotId,
secondary_component: InvSlotId,
},
// TODO: Maybe try to consolidate into another? Otherwise eventually make more general.
ModularWeaponPrimaryComponent {
toolkind: ToolKind,
material: InvSlotId,
modifier: Option<InvSlotId>,
slots: Vec<(u32, InvSlotId)>,
},
2022-07-17 19:33:14 +00:00
Repair {
item: Slot,
slots: Vec<(u32, InvSlotId)>,
},
2021-10-05 21:27:11 +00:00
}
2022-09-08 19:51:02 +00:00
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum GroupManip {
Leave,
Kick(Uid),
AssignLeader(Uid),
}
2021-06-15 16:15:58 +00:00
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum UtteranceKind {
Calm,
Angry,
Surprised,
2021-06-15 22:01:16 +00:00
Hurt,
Greeting,
2021-10-15 19:49:25 +00:00
Scream,
Ambush,
2021-06-18 06:24:57 +00:00
/* Death,
2022-07-15 16:59:37 +00:00
* TODO: Wait for more post-death features (i.e. animations) before implementing death
2021-06-18 06:24:57 +00:00
* sounds */
2021-06-15 16:15:58 +00:00
}
2022-09-08 19:51:02 +00:00
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum ControlEvent {
2020-10-07 02:23:20 +00:00
//ToggleLantern,
EnableLantern,
DisableLantern,
2023-05-04 10:23:46 +00:00
Interact(Uid, Subject),
InitiateInvite(Uid, InviteKind),
InviteResponse(InviteResponse),
PerformTradeAction(TradeId, TradeAction),
Mount(Uid),
2023-04-17 13:38:41 +00:00
MountVolume(VolumePos),
Unmount,
InventoryEvent(InventoryEvent),
GroupManip(GroupManip),
RemoveBuff(BuffKind),
LeaveStance,
2020-03-24 07:38:16 +00:00
Respawn,
2021-06-15 16:15:58 +00:00
Utterance(UtteranceKind),
2021-11-11 22:55:14 +00:00
ChangeAbility {
slot: usize,
auxiliary_key: ability::AuxiliaryKey,
2021-11-11 22:55:14 +00:00
new_ability: ability::AuxiliaryAbility,
},
2020-03-24 07:38:16 +00:00
}
2021-02-07 16:57:41 +00:00
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
2020-03-24 07:38:16 +00:00
pub enum ControlAction {
SwapEquippedWeapons,
InventoryAction(InventoryAction),
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-08-02 05:09:11 +00:00
Sneak,
2020-03-26 15:05:17 +00:00
Stand,
Talk,
StartInput {
2021-03-12 21:01:30 +00:00
input: InputKind,
target_entity: Option<Uid>,
2021-03-21 16:09:16 +00:00
// Some inputs need a selected position, such as mining
select_pos: Option<Vec3<f32>>,
},
CancelInput(InputKind),
}
2021-03-21 16:09:16 +00:00
impl ControlAction {
2021-03-21 17:45:01 +00:00
pub fn basic_input(input: InputKind) -> Self {
2021-03-21 16:09:16 +00:00
ControlAction::StartInput {
input,
target_entity: None,
2021-03-21 16:09:16 +00:00
select_pos: None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Ord, PartialOrd)]
#[repr(u32)]
pub enum InputKind {
Primary = 0,
2021-03-13 00:38:20 +00:00
Secondary = 1,
2021-04-10 03:40:20 +00:00
Block = 2,
Ability(usize) = 3,
Roll = 4,
Jump = 5,
Fly = 6,
}
impl InputKind {
pub fn is_ability(self) -> bool {
matches!(
self,
Self::Primary | Self::Secondary | Self::Ability(_) | Self::Block
)
}
2019-11-29 15:20:35 +00:00
}
2021-11-11 22:55:14 +00:00
impl From<InputKind> for Option<ability::AbilityInput> {
fn from(input: InputKind) -> Option<ability::AbilityInput> {
use ability::AbilityInput;
match input {
2023-07-28 21:29:32 +00:00
InputKind::Block => Some(AbilityInput::Guard),
2021-11-11 22:55:14 +00:00
InputKind::Primary => Some(AbilityInput::Primary),
InputKind::Secondary => Some(AbilityInput::Secondary),
InputKind::Roll => Some(AbilityInput::Movement),
InputKind::Ability(index) => Some(AbilityInput::Auxiliary(index)),
2023-07-28 21:29:32 +00:00
InputKind::Jump | InputKind::Fly => None,
2021-11-11 22:55:14 +00:00
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
2021-03-21 17:45:01 +00:00
pub struct InputAttr {
pub select_pos: Option<Vec3<f32>>,
pub target_entity: Option<Uid>,
2021-03-21 17:45:01 +00:00
}
2022-09-08 19:51:02 +00:00
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
2020-03-24 07:38:16 +00:00
pub enum Climb {
Up,
Down,
Hold,
}
2019-06-09 14:20:20 +00:00
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct ControllerInputs {
2020-03-24 07:38:16 +00:00
pub climb: Option<Climb>,
pub move_dir: Vec2<f32>,
2020-11-03 22:46:07 +00:00
pub move_z: f32, /* z axis (not combined with move_dir because they may have independent
* limits) */
pub look_dir: Dir,
pub break_block_pos: Option<Vec3<f32>>,
2021-06-21 12:27:19 +00:00
/// Attempt to enable strafing.
/// Currently, setting this to false will *not* disable strafing during a
/// wielding character state.
pub strafing: bool,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct Controller {
pub inputs: ControllerInputs,
2023-02-12 20:23:16 +00:00
pub queued_inputs: BTreeMap<InputKind, InputAttr>,
// 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 {
2021-06-21 20:13:49 +00:00
/// Sanitize inputs to avoid clients sending bad data.
pub fn sanitize(&mut self) {
self.move_dir = if self.move_dir.map(|e| e.is_finite()).reduce_and() {
self.move_dir / self.move_dir.magnitude().max(1.0)
} else {
Vec2::zero()
};
self.move_z = if self.move_z.is_finite() {
self.move_z.clamped(-1.0, 1.0)
} else {
0.0
};
}
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.climb = new.climb;
self.move_dir = new.move_dir;
2020-11-03 22:46:07 +00:00
self.move_z = new.move_z;
2020-03-24 07:38:16 +00:00
self.look_dir = new.look_dir;
self.break_block_pos = new.break_block_pos;
}
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.inputs = Default::default();
self.queued_inputs = Default::default();
}
pub fn clear_events(&mut self) { self.events.clear(); }
pub fn push_event(&mut self, event: ControlEvent) { self.events.push(event); }
2022-01-26 18:52:19 +00:00
2022-01-26 20:12:19 +00:00
pub fn push_utterance(&mut self, utterance: UtteranceKind) {
self.push_event(ControlEvent::Utterance(utterance));
}
2022-01-26 20:16:29 +00:00
pub fn push_invite_response(&mut self, invite_response: InviteResponse) {
self.push_event(ControlEvent::InviteResponse(invite_response));
}
2022-01-26 20:23:37 +00:00
pub fn push_initiate_invite(&mut self, uid: Uid, invite: InviteKind) {
self.push_event(ControlEvent::InitiateInvite(uid, invite));
}
2022-01-26 18:52:19 +00:00
pub fn push_action(&mut self, action: ControlAction) { self.actions.push(action); }
2022-01-26 19:09:59 +00:00
pub fn push_basic_input(&mut self, input: InputKind) {
self.push_action(ControlAction::basic_input(input));
}
2022-01-26 19:15:40 +00:00
pub fn push_cancel_input(&mut self, input: InputKind) {
self.push_action(ControlAction::CancelInput(input));
}
2019-06-09 14:20:20 +00:00
}
impl Component for Controller {
type Storage = specs::VecStorage<Self>;
2019-06-09 14:20:20 +00:00
}