2020-10-16 06:08:45 +00:00
|
|
|
use crate::{
|
2021-02-08 17:31:17 +00:00
|
|
|
comp::{
|
2021-11-11 22:55:14 +00:00
|
|
|
ability,
|
2022-01-10 00:10:25 +00:00
|
|
|
inventory::{
|
|
|
|
item::tool::ToolKind,
|
|
|
|
slot::{EquipSlot, InvSlotId, Slot},
|
|
|
|
},
|
2021-02-13 23:32:55 +00:00
|
|
|
invite::{InviteKind, InviteResponse},
|
2021-03-21 17:45:01 +00:00
|
|
|
BuffKind,
|
2021-02-08 17:31:17 +00:00
|
|
|
},
|
2021-02-13 23:32:55 +00:00
|
|
|
trade::{TradeAction, TradeId},
|
2020-12-13 17:11:55 +00:00
|
|
|
uid::Uid,
|
2020-10-16 06:08:45 +00:00
|
|
|
util::Dir,
|
|
|
|
};
|
2020-07-06 14:23:08 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2022-01-16 13:57:38 +00:00
|
|
|
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)]
|
2021-03-01 22:40:42 +00:00
|
|
|
pub enum InventoryEvent {
|
2020-04-04 17:51:41 +00:00
|
|
|
Pickup(Uid),
|
2021-02-08 18:55:50 +00:00
|
|
|
Swap(InvSlotId, InvSlotId),
|
2021-03-02 00:08:46 +00:00
|
|
|
SplitSwap(InvSlotId, InvSlotId),
|
2021-02-08 18:55:50 +00:00
|
|
|
Drop(InvSlotId),
|
2021-04-19 15:56:16 +00:00
|
|
|
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,
|
2021-04-17 14:58:43 +00:00
|
|
|
craft_sprite: Option<Vec3<i32>>,
|
|
|
|
},
|
2020-04-04 17:51:41 +00:00
|
|
|
}
|
|
|
|
|
2022-09-08 19:51:02 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
2021-03-01 22:40:42 +00:00
|
|
|
pub enum InventoryAction {
|
2021-02-08 17:31:17 +00:00
|
|
|
Swap(EquipSlot, Slot),
|
|
|
|
Drop(EquipSlot),
|
2021-03-01 22:40:42 +00:00
|
|
|
Use(Slot),
|
2021-04-17 16:24:33 +00:00
|
|
|
Sort,
|
2021-08-20 04:23:39 +00:00
|
|
|
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)]
|
2021-03-01 22:40:42 +00:00
|
|
|
pub enum InventoryManip {
|
2021-02-08 18:55:50 +00:00
|
|
|
Pickup(Uid),
|
2023-03-03 23:21:37 +00:00
|
|
|
Collect {
|
|
|
|
sprite_pos: Vec3<i32>,
|
|
|
|
required_item: Option<(InvSlotId, bool)>,
|
|
|
|
},
|
2021-02-08 18:55:50 +00:00
|
|
|
Use(Slot),
|
|
|
|
Swap(Slot, Slot),
|
2021-03-02 00:08:46 +00:00
|
|
|
SplitSwap(Slot, Slot),
|
2021-02-08 18:55:50 +00:00
|
|
|
Drop(Slot),
|
2021-04-19 15:56:16 +00:00
|
|
|
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,
|
2021-04-17 14:58:43 +00:00
|
|
|
craft_sprite: Option<Vec3<i32>>,
|
|
|
|
},
|
2021-07-25 23:30:17 +00:00
|
|
|
SwapEquippedWeapons,
|
2021-02-08 18:55:50 +00:00
|
|
|
}
|
|
|
|
|
2021-03-01 22:40:42 +00:00
|
|
|
impl From<InventoryEvent> for InventoryManip {
|
|
|
|
fn from(inv_event: InventoryEvent) -> Self {
|
|
|
|
match inv_event {
|
|
|
|
InventoryEvent::Pickup(pickup) => Self::Pickup(pickup),
|
|
|
|
InventoryEvent::Swap(inv1, inv2) => {
|
2021-02-08 18:55:50 +00:00
|
|
|
Self::Swap(Slot::Inventory(inv1), Slot::Inventory(inv2))
|
|
|
|
},
|
2021-03-01 22:40:42 +00:00
|
|
|
InventoryEvent::SplitSwap(inv1, inv2) => {
|
2021-03-02 00:08:46 +00:00
|
|
|
Self::SplitSwap(Slot::Inventory(inv1), Slot::Inventory(inv2))
|
|
|
|
},
|
2021-03-01 22:40:42 +00:00
|
|
|
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,
|
|
|
|
},
|
2021-02-08 18:55:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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 {
|
2021-10-06 22:18:12 +00:00
|
|
|
Simple {
|
|
|
|
recipe: String,
|
2021-10-25 19:34:39 +00:00
|
|
|
slots: Vec<(u32, InvSlotId)>,
|
2022-08-12 00:47:48 +00:00
|
|
|
amount: u32,
|
2021-10-06 22:18:12 +00:00
|
|
|
},
|
2021-10-05 21:27:11 +00:00
|
|
|
Salvage(InvSlotId),
|
2021-11-05 02:28:01 +00:00
|
|
|
// TODO: Maybe look at making this more general when there are more modular recipes?
|
|
|
|
ModularWeapon {
|
2021-11-20 16:52:20 +00:00
|
|
|
primary_component: InvSlotId,
|
|
|
|
secondary_component: InvSlotId,
|
2021-11-05 02:28:01 +00:00
|
|
|
},
|
2022-01-10 00:10:25 +00:00
|
|
|
// TODO: Maybe try to consolidate into another? Otherwise eventually make more general.
|
|
|
|
ModularWeaponPrimaryComponent {
|
|
|
|
toolkind: ToolKind,
|
|
|
|
material: InvSlotId,
|
|
|
|
modifier: Option<InvSlotId>,
|
|
|
|
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)]
|
2020-04-26 17:03:19 +00:00
|
|
|
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,
|
2021-06-16 12:49:43 +00:00
|
|
|
Greeting,
|
2021-10-15 19:49:25 +00:00
|
|
|
Scream,
|
2022-07-12 20:16:12 +00:00
|
|
|
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)]
|
2019-09-09 19:11:40 +00:00
|
|
|
pub enum ControlEvent {
|
2020-10-07 02:23:20 +00:00
|
|
|
//ToggleLantern,
|
|
|
|
EnableLantern,
|
|
|
|
DisableLantern,
|
2021-01-31 20:29:50 +00:00
|
|
|
Interact(Uid),
|
2021-02-13 23:32:55 +00:00
|
|
|
InitiateInvite(Uid, InviteKind),
|
|
|
|
InviteResponse(InviteResponse),
|
|
|
|
PerformTradeAction(TradeId, TradeAction),
|
2019-09-09 19:11:40 +00:00
|
|
|
Mount(Uid),
|
|
|
|
Unmount,
|
2021-03-01 22:40:42 +00:00
|
|
|
InventoryEvent(InventoryEvent),
|
2020-04-26 17:03:19 +00:00
|
|
|
GroupManip(GroupManip),
|
2020-10-19 03:00:35 +00:00
|
|
|
RemoveBuff(BuffKind),
|
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,
|
2021-11-26 04:30:28 +00:00
|
|
|
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 {
|
2021-02-08 17:31:17 +00:00
|
|
|
SwapEquippedWeapons,
|
2021-03-01 22:40:42 +00:00
|
|
|
InventoryAction(InventoryAction),
|
2020-03-26 15:05:17 +00:00
|
|
|
Wield,
|
2020-06-16 21:32:39 +00:00
|
|
|
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,
|
2021-01-31 20:29:50 +00:00
|
|
|
Talk,
|
2021-03-05 06:09:56 +00:00
|
|
|
StartInput {
|
2021-03-12 21:01:30 +00:00
|
|
|
input: InputKind,
|
2021-03-21 03:28:13 +00:00
|
|
|
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>>,
|
2021-03-05 06:09:56 +00:00
|
|
|
},
|
2021-03-12 04:53:25 +00:00
|
|
|
CancelInput(InputKind),
|
2021-03-05 06:09:56 +00:00
|
|
|
}
|
|
|
|
|
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,
|
2021-03-21 03:28:13 +00:00
|
|
|
target_entity: None,
|
2021-03-21 16:09:16 +00:00
|
|
|
select_pos: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-05 06:09:56 +00:00
|
|
|
#[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,
|
2021-03-14 20:35:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl InputKind {
|
|
|
|
pub fn is_ability(self) -> bool {
|
2021-04-19 05:35:46 +00:00
|
|
|
matches!(
|
|
|
|
self,
|
|
|
|
Self::Primary | Self::Secondary | Self::Ability(_) | Self::Block
|
|
|
|
)
|
2021-03-14 20:35:28 +00:00
|
|
|
}
|
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 {
|
|
|
|
InputKind::Primary => Some(AbilityInput::Primary),
|
|
|
|
InputKind::Secondary => Some(AbilityInput::Secondary),
|
|
|
|
InputKind::Roll => Some(AbilityInput::Movement),
|
|
|
|
InputKind::Ability(index) => Some(AbilityInput::Auxiliary(index)),
|
|
|
|
InputKind::Jump | InputKind::Fly | InputKind::Block => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-21 03:28:13 +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>>,
|
2021-03-21 03:28:13 +00:00
|
|
|
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)]
|
2019-10-15 04:06:14 +00:00
|
|
|
pub struct ControllerInputs {
|
2020-03-24 07:38:16 +00:00
|
|
|
pub climb: Option<Climb>,
|
2019-10-15 04:06:14 +00:00
|
|
|
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) */
|
2020-03-28 01:31:22 +00:00
|
|
|
pub look_dir: Dir,
|
2021-09-14 01:51:54 +00:00
|
|
|
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,
|
2019-10-15 04:06:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
|
|
|
pub struct Controller {
|
|
|
|
pub inputs: ControllerInputs,
|
2021-03-21 16:09:16 +00:00
|
|
|
pub queued_inputs: BTreeMap<InputKind, InputAttr>,
|
2019-10-21 00:59:53 +00:00
|
|
|
// TODO: consider SmallVec
|
2019-09-09 19:11:40 +00:00
|
|
|
pub events: Vec<ControlEvent>,
|
2020-03-24 07:38:16 +00:00
|
|
|
pub actions: Vec<ControlAction>,
|
2019-09-09 19:11:40 +00:00
|
|
|
}
|
|
|
|
|
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;
|
2021-09-14 01:51:54 +00:00
|
|
|
self.break_block_pos = new.break_block_pos;
|
2019-12-03 06:30:08 +00:00
|
|
|
}
|
2019-11-29 15:20:35 +00:00
|
|
|
}
|
|
|
|
|
2019-09-09 19:11:40 +00:00
|
|
|
impl Controller {
|
2019-11-29 15:20:35 +00:00
|
|
|
/// Sets all inputs to default
|
2021-07-31 19:33:28 +00:00
|
|
|
pub fn reset(&mut self) {
|
|
|
|
self.inputs = Default::default();
|
|
|
|
self.queued_inputs = Default::default();
|
|
|
|
}
|
2019-09-09 19:11:40 +00:00
|
|
|
|
2020-02-01 20:39:39 +00:00
|
|
|
pub fn clear_events(&mut self) { self.events.clear(); }
|
2019-09-09 19:11:40 +00:00
|
|
|
|
2020-02-01 20:39:39 +00:00
|
|
|
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 {
|
2022-08-08 04:38:20 +00:00
|
|
|
type Storage = specs::VecStorage<Self>;
|
2019-06-09 14:20:20 +00:00
|
|
|
}
|