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(InputKind),
201}
202
203impl ControlAction {
204 pub fn basic_input(input: InputKind) -> Self {
205 ControlAction::StartInput {
206 input,
207 target_entity: None,
208 select_pos: None,
209 }
210 }
211}
212
213#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Ord, PartialOrd)]
214#[repr(u32)]
215pub enum InputKind {
216 Primary = 0,
217 Secondary = 1,
218 Block = 2,
219 Ability(usize) = 3,
220 Roll = 4,
221 Jump = 5,
222 Fly = 6,
223}
224
225impl InputKind {
226 pub fn is_ability(self) -> bool {
227 matches!(
228 self,
229 Self::Primary | Self::Secondary | Self::Ability(_) | Self::Block
230 )
231 }
232}
233
234impl From<InputKind> for Option<ability::AbilityInput> {
235 fn from(input: InputKind) -> Option<ability::AbilityInput> {
236 use ability::AbilityInput;
237 match input {
238 InputKind::Block => Some(AbilityInput::Guard),
239 InputKind::Primary => Some(AbilityInput::Primary),
240 InputKind::Secondary => Some(AbilityInput::Secondary),
241 InputKind::Roll => Some(AbilityInput::Movement),
242 InputKind::Ability(index) => Some(AbilityInput::Auxiliary(index)),
243 InputKind::Jump | InputKind::Fly => None,
244 }
245 }
246}
247
248#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
249pub struct InputAttr {
250 pub select_pos: Option<Vec3<f32>>,
251 pub target_entity: Option<Uid>,
252}
253
254#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
255pub struct ControllerInputs {
256 pub move_dir: Vec2<f32>,
257 pub move_z: f32, pub look_dir: Dir,
260 pub break_block_pos: Option<Vec3<f32>>,
261 pub strafing: bool,
265}
266
267#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
268pub struct Controller {
269 pub inputs: ControllerInputs,
270 pub queued_inputs: BTreeMap<InputKind, InputAttr>,
271 pub events: Vec<ControlEvent>,
273 pub actions: Vec<ControlAction>,
274}
275
276impl ControllerInputs {
277 pub fn sanitize(&mut self) {
279 self.move_dir = if self.move_dir.map(|e| e.is_finite()).reduce_and() {
280 self.move_dir / self.move_dir.magnitude().max(1.0)
281 } else {
282 Vec2::zero()
283 };
284 self.move_z = if self.move_z.is_finite() {
285 self.move_z.clamped(-1.0, 1.0)
286 } else {
287 0.0
288 };
289 }
290
291 pub fn update_with_new(&mut self, new: Self) {
293 self.move_dir = new.move_dir;
294 self.move_z = new.move_z;
295 self.look_dir = new.look_dir;
296 self.break_block_pos = new.break_block_pos;
297 }
298}
299
300impl Controller {
301 pub fn reset(&mut self) {
303 self.inputs = Default::default();
304 self.queued_inputs = Default::default();
305 }
306
307 pub fn clear_events(&mut self) { self.events.clear(); }
308
309 pub fn push_event(&mut self, event: ControlEvent) { self.events.push(event); }
310
311 pub fn push_utterance(&mut self, utterance: UtteranceKind) {
312 self.push_event(ControlEvent::Utterance(utterance));
313 }
314
315 pub fn push_invite_response(&mut self, invite_response: InviteResponse) {
316 self.push_event(ControlEvent::InviteResponse(invite_response));
317 }
318
319 pub fn push_initiate_invite(&mut self, uid: Uid, invite: InviteKind) {
320 self.push_event(ControlEvent::InitiateInvite(uid, invite));
321 }
322
323 pub fn push_action(&mut self, action: ControlAction) { self.actions.push(action); }
324
325 pub fn push_basic_input(&mut self, input: InputKind) {
326 self.push_action(ControlAction::basic_input(input));
327 }
328
329 pub fn push_cancel_input(&mut self, input: InputKind) {
330 self.push_action(ControlAction::CancelInput(input));
331 }
332}
333
334impl Component for Controller {
335 type Storage = specs::VecStorage<Self>;
336}