1pub mod config;
2pub mod console;
3pub mod database;
4mod display;
5pub mod net_msg;
6pub mod replay;
7
8pub use teehistorian;
10pub use twsnap;
12
13pub use display::DisplayChunk;
14
15use crate::console::Command;
16use serde::{Deserialize, Serialize};
17use twsnap::time::Instant;
18use twsnap::Snap;
19use vek::Vec2;
20
21#[derive(Clone, Debug, PartialEq, Eq, Default, Serialize, Deserialize)]
22pub struct Input {
23 pub direction: i32,
24 pub target_x: i32,
25 pub target_y: i32,
26 pub jump: i32,
27 pub fire: i32,
28 pub hook: i32,
29 pub player_flags: i32,
31 pub wanted_weapon: i32,
32 pub next_weapon: i32,
33 pub prev_weapon: i32,
34}
35
36impl Input {
37 pub fn new() -> Input {
39 Input {
40 direction: 0,
41 target_x: 0,
42 target_y: -1,
43 jump: 0,
44 fire: 0,
45 hook: 0,
46 player_flags: 0,
47 wanted_weapon: 0,
48 next_weapon: 0,
49 prev_weapon: 0,
50 }
51 }
52
53 fn disallow_target_center(mut self) -> Self {
54 if self.target_x == 0 && self.target_y == 0 {
55 self.target_y = -1;
56 }
57 self
58 }
59
60 fn count_presses(mut cur: i32, mut prev: i32) -> i32 {
62 let mut count = 0;
64 prev &= 63; cur &= 63;
66 while prev != cur {
67 prev = (prev + 1) & 63;
68 if prev & 1 != 0 {
69 count += 1;
70 }
71 }
72 count
73 }
74
75 pub fn count_weapon_next(&self, prev: &Input) -> i32 {
77 Input::count_presses(self.next_weapon, prev.next_weapon)
78 }
79
80 pub fn count_weapon_prev(&self, prev: &Input) -> i32 {
82 Input::count_presses(self.prev_weapon, prev.prev_weapon)
83 }
84
85 pub fn count_weapon_fire(&self, prev: &Input) -> i32 {
87 Input::count_presses(self.fire, prev.fire)
88 }
89
90 pub fn cursor(&self) -> Vec2<f32> {
92 Vec2::new(self.target_x as f32, self.target_y as f32)
93 }
94
95 pub fn firing(&self) -> bool {
97 (self.fire & 1) != 0
98 }
99
100 pub fn spec_cam_active(&self) -> bool {
102 (self.player_flags & (1 << 5)) != 0
103 }
104}
105
106impl From<[i32; 10]> for Input {
107 fn from(input: [i32; 10]) -> Self {
108 Input {
109 direction: input[0],
110 target_x: input[1],
111 target_y: input[2],
112 jump: input[3],
113 fire: input[4],
114 hook: input[5],
115 player_flags: input[6],
117 wanted_weapon: input[7],
118 next_weapon: input[8],
119 prev_weapon: input[9],
120 }
121 .disallow_target_center()
122 }
123}
124
125impl Input {
126 pub fn add_input_diff(&mut self, input_diff: [i32; 10]) {
127 self.direction += input_diff[0];
128 self.target_x += input_diff[1];
129 self.target_y += input_diff[2];
130 self.jump += input_diff[3];
131 self.fire += input_diff[4];
132 self.hook += input_diff[5];
133 self.player_flags += input_diff[6];
134 self.wanted_weapon += input_diff[7];
135 self.next_weapon += input_diff[8];
136 self.prev_weapon += input_diff[9];
137 }
138}
139
140pub trait Game {
141 fn player_join(&mut self, id: u32);
143 fn player_ready(&mut self, id: u32);
144 fn player_input(&mut self, id: u32, input: &Input);
145 fn player_leave(&mut self, id: u32);
146
147 fn on_net_msg(&mut self, id: u32, msg: &net_msg::ClNetMessage);
148 fn on_command(&mut self, id: u32, command: &Command);
149
150 fn swap_tees(&mut self, id1: u32, id2: u32);
151
152 fn tick(&mut self, cur_time: Instant);
154
155 fn is_empty(&self) -> bool;
158}
159
160pub trait Snapper {
161 fn snap(&self, snapshot: &mut Snap);
162}
163
164pub fn normalize(v: Vec2<f32>) -> Vec2<f32> {
168 let divisor = v.magnitude();
170 if divisor == 0.0 {
172 return Vec2::zero();
174 }
175 let l = 1.0 / divisor;
177 v * l
179}