1use crate::{
2 comp::{
3 BuffKind, ability,
4 inventory::{
5 InventorySortOrder,
6 item::tool::ToolKind,
7 slot::{EquipSlot, InvSlotId, Slot},
8 },
9 invite::{InviteKind, InviteResponse},
10 },
11 mounting::VolumePos,
12 rtsim,
13 trade::{TradeAction, TradeId},
14 uid::Uid,
15 util::Dir,
16};
17use serde::{Deserialize, Serialize};
18use specs::Component;
19use std::collections::BTreeMap;
20use vek::*;
21
22#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
23pub enum InventoryEvent {
24 Pickup(Uid),
25 Swap(InvSlotId, InvSlotId),
26 SplitSwap(InvSlotId, InvSlotId),
27 Drop(InvSlotId),
28 SplitDrop(InvSlotId),
29 Sort(InventorySortOrder),
30 CraftRecipe {
31 craft_event: CraftEvent,
32 craft_sprite: Option<VolumePos>,
33 },
34 OverflowMove(usize, InvSlotId),
35 OverflowDrop(usize),
36 OverflowSplitDrop(usize),
37}
38
39#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
40pub enum InventoryAction {
41 Swap(EquipSlot, Slot),
42 Drop(EquipSlot),
43 Use(Slot),
44 Sort(InventorySortOrder),
45 Collect(Vec3<i32>),
46 ToggleSpriteLight(VolumePos, bool),
49}
50
51#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
52pub enum InventoryManip {
53 Pickup(Uid),
54 Collect {
55 sprite_pos: Vec3<i32>,
56 required_item: Option<(InvSlotId, bool)>,
58 },
59 Use(Slot),
60 Swap(Slot, Slot),
61 SplitSwap(Slot, Slot),
62 Drop(Slot),
63 SplitDrop(Slot),
64 Sort(InventorySortOrder),
65 CraftRecipe {
66 craft_event: CraftEvent,
67 craft_sprite: Option<VolumePos>,
68 },
69 SwapEquippedWeapons,
70}
71
72impl From<InventoryEvent> for InventoryManip {
73 fn from(inv_event: InventoryEvent) -> Self {
74 match inv_event {
75 InventoryEvent::Pickup(pickup) => Self::Pickup(pickup),
76 InventoryEvent::Swap(inv1, inv2) => {
77 Self::Swap(Slot::Inventory(inv1), Slot::Inventory(inv2))
78 },
79 InventoryEvent::SplitSwap(inv1, inv2) => {
80 Self::SplitSwap(Slot::Inventory(inv1), Slot::Inventory(inv2))
81 },
82 InventoryEvent::Drop(inv) => Self::Drop(Slot::Inventory(inv)),
83 InventoryEvent::SplitDrop(inv) => Self::SplitDrop(Slot::Inventory(inv)),
84 InventoryEvent::Sort(sort_order) => Self::Sort(sort_order),
85 InventoryEvent::CraftRecipe {
86 craft_event,
87 craft_sprite,
88 } => Self::CraftRecipe {
89 craft_event,
90 craft_sprite,
91 },
92 InventoryEvent::OverflowMove(o, inv) => {
93 Self::Swap(Slot::Overflow(o), Slot::Inventory(inv))
94 },
95 InventoryEvent::OverflowDrop(o) => Self::Drop(Slot::Overflow(o)),
96 InventoryEvent::OverflowSplitDrop(o) => Self::SplitDrop(Slot::Overflow(o)),
97 }
98 }
99}
100
101#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
102pub enum CraftEvent {
103 Simple {
104 recipe: String,
105 slots: Vec<(u32, InvSlotId)>,
106 amount: u32,
107 },
108 Salvage(InvSlotId),
109 ModularWeapon {
111 primary_component: InvSlotId,
112 secondary_component: InvSlotId,
113 },
114 ModularWeaponPrimaryComponent {
116 toolkind: ToolKind,
117 material: InvSlotId,
118 modifier: Option<InvSlotId>,
119 slots: Vec<(u32, InvSlotId)>,
120 },
121 Repair {
122 item: Slot,
123 slots: Vec<(u32, InvSlotId)>,
124 },
125}
126
127#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
128pub enum GroupManip {
129 Leave,
130 Kick(Uid),
131 AssignLeader(Uid),
132}
133
134#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, strum::EnumString)]
135pub enum UtteranceKind {
136 Calm,
137 Angry,
138 Surprised,
139 Hurt,
140 Greeting,
141 Scream,
142 Ambush,
143 }
147
148#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
149pub enum ControlEvent {
150 EnableLantern,
152 DisableLantern,
153 Interact(Uid),
154 InitiateInvite(Uid, InviteKind),
155 InviteResponse(InviteResponse),
156 PerformTradeAction(TradeId, TradeAction),
157 Mount(Uid),
158 MountVolume(VolumePos),
159 Unmount,
160 SetPetStay(Uid, bool),
161 InventoryEvent(InventoryEvent),
162 GroupManip(GroupManip),
163 RemoveBuff(BuffKind),
164 LeaveStance,
165 GiveUp,
166 Respawn,
167 Utterance(UtteranceKind),
168 ChangeAbility {
169 slot: usize,
170 auxiliary_key: ability::AuxiliaryKey,
171 new_ability: ability::AuxiliaryAbility,
172 },
173 ActivatePortal(Uid),
174 InteractWith {
175 target: Uid,
176 kind: crate::interaction::InteractionKind,
177 },
178 Dialogue(Uid, rtsim::Dialogue),
179}
180
181#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
182pub enum ControlAction {
183 SwapEquippedWeapons,
184 InventoryAction(InventoryAction),
185 Wield,
186 GlideWield,
187 Unwield,
188 Sit,
189 Crawl,
190 Dance,
191 Sneak,
192 Stand,
193 Talk,
194 StartInput {
195 input: InputKind,
196 target_entity: Option<Uid>,
197 select_pos: Option<Vec3<f32>>,
199 },
200 CancelInput {
201 input: InputKind,
202 },
203}
204
205impl ControlAction {
206 pub fn basic_input(input: InputKind) -> Self {
207 ControlAction::StartInput {
208 input,
209 target_entity: None,
210 select_pos: None,
211 }
212 }
213}
214
215#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Ord, PartialOrd)]
216#[repr(u32)]
217pub enum InputKind {
218 Primary = 0,
219 Secondary = 1,
220 Block = 2,
221 Ability(usize) = 3,
222 Roll = 4,
223 Jump = 5,
224 Fly = 6,
225}
226
227impl InputKind {
228 pub fn is_ability(self) -> bool {
229 matches!(
230 self,
231 Self::Primary | Self::Secondary | Self::Ability(_) | Self::Block
232 )
233 }
234}
235
236impl From<InputKind> for Option<ability::AbilityInput> {
237 fn from(input: InputKind) -> Option<ability::AbilityInput> {
238 use ability::AbilityInput;
239 match input {
240 InputKind::Block => Some(AbilityInput::Guard),
241 InputKind::Primary => Some(AbilityInput::Primary),
242 InputKind::Secondary => Some(AbilityInput::Secondary),
243 InputKind::Roll => Some(AbilityInput::Movement),
244 InputKind::Ability(index) => Some(AbilityInput::Auxiliary(index)),
245 InputKind::Jump | InputKind::Fly => None,
246 }
247 }
248}
249
250#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
251pub struct InputAttr {
252 pub select_pos: Option<Vec3<f32>>,
253 pub target_entity: Option<Uid>,
254}
255
256#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
257pub struct ControllerInputs {
258 pub move_dir: Vec2<f32>,
259 pub move_z: f32, pub look_dir: Dir,
262 pub break_block_pos: Option<Vec3<f32>>,
263 pub strafing: bool,
267}
268
269#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
270pub struct Controller {
271 pub inputs: ControllerInputs,
272 pub queued_inputs: BTreeMap<InputKind, InputAttr>,
273 pub events: Vec<ControlEvent>,
275 pub actions: Vec<ControlAction>,
276}
277
278impl ControllerInputs {
279 pub fn sanitize(&mut self) {
281 self.move_dir = if self.move_dir.map(|e| e.is_finite()).reduce_and() {
282 self.move_dir / self.move_dir.magnitude().max(1.0)
283 } else {
284 Vec2::zero()
285 };
286 self.move_z = if self.move_z.is_finite() {
287 self.move_z.clamped(-1.0, 1.0)
288 } else {
289 0.0
290 };
291 }
292
293 pub fn update_with_new(&mut self, new: Self) {
295 self.move_dir = new.move_dir;
296 self.move_z = new.move_z;
297 self.look_dir = new.look_dir;
298 self.break_block_pos = new.break_block_pos;
299 }
300}
301
302impl Controller {
303 pub fn reset(&mut self) {
305 self.inputs = Default::default();
306 self.queued_inputs = Default::default();
307 }
308
309 pub fn clear_events(&mut self) { self.events.clear(); }
310
311 pub fn push_event(&mut self, event: ControlEvent) { self.events.push(event); }
312
313 pub fn push_utterance(&mut self, utterance: UtteranceKind) {
314 self.push_event(ControlEvent::Utterance(utterance));
315 }
316
317 pub fn push_invite_response(&mut self, invite_response: InviteResponse) {
318 self.push_event(ControlEvent::InviteResponse(invite_response));
319 }
320
321 pub fn push_initiate_invite(&mut self, uid: Uid, invite: InviteKind) {
322 self.push_event(ControlEvent::InitiateInvite(uid, invite));
323 }
324
325 pub fn push_action(&mut self, action: ControlAction) { self.actions.push(action); }
326
327 pub fn push_basic_input(&mut self, input: InputKind) {
328 self.push_action(ControlAction::basic_input(input));
329 }
330
331 pub fn push_cancel_input(&mut self, input: InputKind) {
332 self.push_action(ControlAction::CancelInput { input });
333 }
334}
335
336impl Component for Controller {
337 type Storage = specs::VecStorage<Self>;
338}