airmash_protocol/packets/
server.rs

1//! Packets that the server sends to the client.
2
3use std::ops::{Deref, DerefMut};
4
5use bstr::BString;
6
7use crate::enums::*;
8#[cfg(feature = "serde")]
9use crate::packets::serde::{opt_vec, VecRemote};
10use crate::types::*;
11
12/// A player has said something in global chat.
13#[derive(Clone, Debug)]
14#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15pub struct ChatPublic {
16  pub id: Player,
17  pub text: BString,
18}
19
20/// A player has said something locally.
21#[derive(Clone, Debug)]
22#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
23pub struct ChatSay {
24  pub id: Player,
25  pub text: BString,
26}
27
28/// A player has said something in team chat for the current team.
29#[derive(Clone, Debug)]
30#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
31pub struct ChatTeam {
32  pub id: Player,
33  pub text: BString,
34}
35
36/// A player has been votemuted
37#[derive(Copy, Clone, Debug)]
38#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
39pub struct ChatVoteMutePassed {
40  pub id: Player,
41}
42
43/// A player has whispered.
44///
45/// This only occurs if the current player is either the whisperer or the one
46/// who originally sent the whisper message.
47#[derive(Clone, Debug)]
48#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
49pub struct ChatWhisper {
50  pub from: Player,
51  pub to: Player,
52  pub text: BString,
53}
54
55/// Reply to a [`Command`](../client/struct.command.html).
56#[derive(Clone, Debug)]
57#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
58pub struct CommandReply {
59  // #[cfg_attr(feature = "serde", serde(rename = "type"))]
60  pub ty: CommandReplyType,
61  pub text: BString,
62}
63
64/// Acknowledge successful receipt of a [`Backup`][0] packet.
65///
66/// [0]: ../client/struct.backup.html
67#[derive(Copy, Clone, Debug, Default)]
68#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
69pub struct Backup;
70
71/// TODO: Unknown why this is needed.
72#[derive(Copy, Clone, Debug, Default)]
73#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
74pub struct Ack;
75
76/// The current player has been votemuted.
77///
78/// This happens after enough players have sent a [`VoteMute`][0] packet to the
79/// server.
80///
81/// [0]: ../client/struct.VoteMute.html
82#[derive(Copy, Clone, Debug, Default)]
83#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
84pub struct ChatVoteMuted;
85
86/// The client has carried out an invalid action, been ratelimited, or is
87/// banned.
88#[derive(Copy, Clone, Debug)]
89#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
90pub struct Error {
91  pub error: ErrorType,
92}
93
94/// A predator has begun/stopped boosting
95#[derive(Copy, Clone, Debug)]
96#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
97pub struct EventBoost {
98  pub clock: u32,
99  pub id: Player,
100  pub boost: bool,
101  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
102  pub pos: Position,
103  pub rot: Rotation,
104  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
105  pub speed: Velocity,
106  pub energy: Energy,
107  pub energy_regen: EnergyRegen,
108}
109
110/// A player has run into a wall
111#[derive(Copy, Clone, Debug)]
112#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
113pub struct EventBounce {
114  pub clock: u32,
115  pub id: Player,
116  pub keystate: ServerKeyState,
117  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
118  pub pos: Position,
119  pub rot: Rotation,
120  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
121  pub speed: Velocity,
122}
123
124/// Event for when a player goes beyond the event horizon.
125///
126/// This indicates that the server will stop sending updates about this plane
127/// until it comes back within the event horizon.
128#[derive(Copy, Clone, Debug)]
129#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
130pub struct EventLeaveHorizon {
131  #[cfg_attr(feature = "serde", serde(rename = "type"))]
132  pub ty: LeaveHorizonType,
133  /// This could be either a player or a mob
134  pub id: u16,
135}
136
137/// A player has been repelled by a goliath.
138#[derive(Copy, Clone, Debug)]
139#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
140pub struct EventRepelPlayer {
141  pub id: Player,
142  pub keystate: ServerKeyState,
143  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
144  pub pos: Position,
145  pub rot: Rotation,
146  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
147  pub speed: Velocity,
148  pub energy: Energy,
149  pub energy_regen: EnergyRegen,
150  pub health: Health,
151  pub health_regen: HealthRegen,
152}
153
154/// A projectile has been repelled by a goliath
155#[derive(Copy, Clone, Debug)]
156#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
157pub struct EventRepelMob {
158  pub id: Mob,
159  #[cfg_attr(feature = "serde", serde(rename = "type"))]
160  pub ty: MobType,
161  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
162  pub pos: Position,
163  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
164  pub speed: Velocity,
165  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
166  pub accel: Accel,
167  pub max_speed: Speed,
168}
169
170/// Event triggered when something (player or missile) is deflected by a goliath
171/// repel.
172#[derive(Clone, Debug)]
173#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
174pub struct EventRepel {
175  pub clock: u32,
176  pub id: Player,
177  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
178  pub pos: Position,
179  pub rot: Rotation,
180  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
181  pub speed: Velocity,
182  pub energy: Energy,
183  pub energy_regen: EnergyRegen,
184  pub players: Vec<EventRepelPlayer>,
185  pub mobs: Vec<EventRepelMob>,
186}
187
188/// A prowler has entered/exited stealth mode
189#[derive(Copy, Clone, Debug)]
190#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
191pub struct EventStealth {
192  pub id: Player,
193  pub state: bool,
194  pub energy: Energy,
195  pub energy_regen: EnergyRegen,
196}
197
198/// Update the "Wall of Fire" in BTR
199#[derive(Copy, Clone, Debug)]
200#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
201pub struct GameFirewall {
202  /// This field is not used for anything by the client.
203  #[cfg_attr(feature = "serde", serde(rename = "type"))]
204  pub ty: u8,
205  pub status: FirewallStatus,
206  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
207  pub pos: Position,
208  pub radius: f32,
209  pub speed: f32,
210}
211
212/// Update position of flag in CTF
213#[derive(Copy, Clone, Debug)]
214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
215pub struct GameFlag {
216  #[cfg_attr(feature = "serde", serde(rename = "type"))]
217  pub ty: FlagUpdateType,
218  pub flag: u8,
219  pub id: Option<Player>,
220  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
221  pub pos: Position,
222  /// Blue team score
223  pub blueteam: u8,
224  /// Red team score
225  pub redteam: u8,
226}
227
228/// Info on the number of players currently alive
229#[derive(Copy, Clone, Debug)]
230#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
231pub struct GamePlayersAlive {
232  pub players: u16,
233}
234
235/// Update which player the client is spectating.
236#[derive(Copy, Clone, Debug)]
237#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
238pub struct GameSpectate {
239  pub id: Player,
240}
241
242/// Initial data passed in for a player when the server starts.
243///
244/// This is an element of the `players` array within the [`Login`] packet.
245#[derive(Clone, Debug)]
246#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
247pub struct LoginPlayer {
248  pub id: Player,
249  pub status: PlayerStatus,
250  pub level: Level,
251  pub name: BString,
252  #[cfg_attr(feature = "serde", serde(rename = "type"))]
253  pub ty: PlaneType,
254  pub team: Team,
255  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
256  pub pos: Position,
257  pub rot: Rotation,
258  pub flag: FlagCode,
259  pub upgrades: Upgrades,
260}
261
262/// Initial Login packet sent to the server
263#[derive(Clone, Debug)]
264#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
265pub struct Login {
266  pub success: bool,
267  pub id: Player,
268  pub team: Team,
269  pub clock: u32,
270  pub token: BString,
271  #[cfg_attr(feature = "serde", serde(rename = "type"))]
272  pub ty: GameType,
273  pub room: BString,
274  pub players: Vec<LoginPlayer>,
275}
276
277#[derive(Clone, Debug)]
278#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
279pub struct LoginBot {
280  pub id: Player,
281}
282
283/// Upgraded Login packet introduced in <https://github.com/wight-airmash/ab-protocol>
284#[derive(Clone, Debug)]
285#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
286
287pub struct Login2 {
288  #[cfg_attr(feature = "serde", serde(flatten))]
289  pub login: Login,
290  #[cfg_attr(feature = "serde", serde(rename = "serverConfiguration"))]
291  pub config: BString,
292  pub bots: Vec<LoginBot>,
293}
294
295/// A missile despawned with an explosion. This is used when a missile collides
296/// with a mountain to generate an explosion client-side.
297#[derive(Copy, Clone, Debug)]
298#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
299pub struct MobDespawnCoords {
300  pub id: Mob,
301  #[cfg_attr(feature = "serde", serde(rename = "type"))]
302  pub ty: MobType,
303  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
304  pub pos: Position,
305}
306
307/// A mob despawned.
308///
309/// This is used when a powerup despawns and when a missile despawns without
310/// hitting anything. It does not cause an explosion to be shown at the
311/// location.
312#[derive(Copy, Clone, Debug)]
313#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
314pub struct MobDespawn {
315  pub id: Mob,
316  #[cfg_attr(feature = "serde", serde(rename = "type"))]
317  pub ty: DespawnType,
318}
319
320/// Update for an immobile mob.
321///
322/// This is sent when a powerup is enters a player's view radius.
323#[derive(Copy, Clone, Debug)]
324#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
325pub struct MobUpdateStationary {
326  pub id: Mob,
327  #[cfg_attr(feature = "serde", serde(rename = "type"))]
328  pub ty: MobType,
329  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
330  pub pos: Position,
331}
332
333/// Update for a mobile missile-type mob.
334///
335/// This is sent when a mob enters a player's view radius or something changes
336/// about its state that needs to be communicated to the client.
337#[derive(Copy, Clone, Debug)]
338#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
339pub struct MobUpdate {
340  pub clock: u32,
341  pub id: Mob,
342  #[cfg_attr(feature = "serde", serde(rename = "type"))]
343  pub ty: MobType,
344  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
345  pub pos: Position,
346  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
347  pub speed: Velocity,
348  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
349  pub accel: Accel,
350  pub max_speed: Speed,
351}
352
353/// MobUpdate but extended with an extra ownerId field as present in
354/// ab-protocol.
355#[derive(Copy, Clone, Debug)]
356#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
357pub struct MobUpdate2 {
358  #[cfg_attr(feature = "serde", serde(flatten))]
359  pub update: MobUpdate,
360  #[cfg_attr(feature = "serde", serde(flatten))]
361  #[cfg_attr(feature = "serde", serde(rename = "ownerId"))]
362  pub owner: Player,
363}
364
365/// Resulting ping data sent back from the server.
366#[derive(Copy, Clone, Debug)]
367#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
368pub struct PingResult {
369  pub ping: u16,
370  #[cfg_attr(feature = "serde", serde(rename = "playersTotal"))]
371  pub players_total: u32,
372  #[cfg_attr(feature = "serde", serde(rename = "playersGame"))]
373  pub players_game: u32,
374}
375
376/// A ping request by the server.
377///
378/// All clients must respond with a [`Pong`] with `num` set to the same value as
379/// this packet. If a client does not do this, the client will be disconnected
380/// by the server.
381///
382/// [`Pong`]: crate::client::Pong
383#[derive(Copy, Clone, Debug)]
384#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
385pub struct Ping {
386  pub clock: u32,
387  pub num: u32,
388}
389
390/// Data on a projectile fired by a plane.
391///
392/// This is used in the `projectiles` array of the [`PlayerFire`] packet.
393#[derive(Copy, Clone, Debug)]
394#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
395pub struct PlayerFireProjectile {
396  pub id: Mob,
397  #[cfg_attr(feature = "serde", serde(rename = "type"))]
398  pub ty: MobType,
399  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
400  pub pos: Position,
401  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
402  pub speed: Velocity,
403  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
404  pub accel: Accel,
405  pub max_speed: Speed,
406}
407
408/// Packet for whan a player fires missiles.
409#[derive(Clone, Debug)]
410#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
411pub struct PlayerFire {
412  pub clock: u32,
413  pub id: Player,
414  pub energy: Energy,
415  pub energy_regen: EnergyRegen,
416  pub projectiles: Vec<PlayerFireProjectile>,
417}
418
419/// Packet for when a player changes their flag.
420#[derive(Copy, Clone, Debug)]
421#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
422pub struct PlayerFlag {
423  pub id: Player,
424  pub flag: FlagCode,
425}
426
427/// Data on a player that has been hit by a shot fired by another player.
428#[derive(Copy, Clone, Debug)]
429#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
430pub struct PlayerHitPlayer {
431  pub id: Player,
432  pub health: Health,
433  pub health_regen: HealthRegen,
434}
435
436/// Event for when players have been hit by a missile.
437#[derive(Clone, Debug)]
438#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
439pub struct PlayerHit {
440  pub id: Mob,
441  // #[cfg_attr(feature = "serde", serde(rename = "type"))]
442  pub ty: MobType,
443  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
444  pub pos: Position,
445  pub owner: Player,
446  pub players: Vec<PlayerHitPlayer>,
447}
448
449#[derive(Copy, Clone, Debug)]
450#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
451pub struct PlayerKill {
452  pub id: Player,
453  pub killer: Option<Player>,
454  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
455  pub pos: Position,
456}
457
458/// Packet for when a player leaves.
459#[derive(Copy, Clone, Debug)]
460#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
461pub struct PlayerLeave {
462  pub id: Player,
463}
464
465/// Assign a level to a player.
466///
467/// Either the player levelled up, or the server is updating their level for all
468/// clients.
469#[derive(Copy, Clone, Debug)]
470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
471pub struct PlayerLevel {
472  pub id: Player,
473  #[cfg_attr(feature = "serde", serde(rename = "type"))]
474  pub ty: PlayerLevelType,
475  pub level: Level,
476}
477
478/// Data for a newly-joined player.
479#[derive(Clone, Debug)]
480#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
481pub struct PlayerNew {
482  pub id: Player,
483  pub status: PlayerStatus,
484  pub name: BString,
485  #[cfg_attr(feature = "serde", serde(rename = "type"))]
486  pub ty: PlaneType,
487  pub team: Team,
488  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
489  pub pos: Position,
490  pub rot: Rotation,
491  pub flag: FlagCode,
492  pub upgrades: Upgrades,
493}
494
495/// The current player picked up a powerup.
496#[derive(Copy, Clone, Debug)]
497#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
498pub struct PlayerPowerup {
499  #[cfg_attr(feature = "serde", serde(rename = "type"))]
500  pub ty: PowerupType,
501  /// Lifetime of the powerup, in milliseconds.
502  pub duration: u32,
503}
504
505/// Packet for when a player respawns.
506#[derive(Copy, Clone, Debug)]
507#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
508pub struct PlayerRespawn {
509  pub id: Player,
510  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
511  pub pos: Position,
512  pub rot: Rotation,
513  pub upgrades: Upgrades,
514}
515
516/// Details about a player that has switched teams.
517#[derive(Copy, Clone, Debug)]
518#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
519pub struct PlayerReteamPlayer {
520  pub id: Player,
521  pub team: Team,
522}
523
524/// Packet for when players change teams
525#[derive(Clone, Debug)]
526#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
527pub struct PlayerReteam {
528  /// List of players that have changed teams.
529  pub players: Vec<PlayerReteamPlayer>,
530}
531
532/// A player has switched planes.
533#[derive(Copy, Clone, Debug)]
534#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
535pub struct PlayerType {
536  pub id: Player,
537  #[cfg_attr(feature = "serde", serde(rename = "type"))]
538  pub ty: PlaneType,
539}
540
541/// Movement update for a player.
542#[derive(Copy, Clone, Debug)]
543#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
544pub struct PlayerUpdate {
545  pub clock: u32,
546  pub id: Player,
547  pub keystate: ServerKeyState,
548  pub upgrades: Upgrades,
549  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
550  pub pos: Position,
551  pub rot: Rotation,
552  #[cfg_attr(feature = "serde", serde(with = "VecRemote"))]
553  pub speed: Velocity,
554}
555
556/// A player has upgraded themselves.
557#[derive(Copy, Clone, Debug)]
558#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
559pub struct PlayerUpgrade {
560  pub upgrades: u16,
561  #[cfg_attr(feature = "serde", serde(rename = "type"))]
562  pub ty: UpgradeType,
563  pub speed: u8,
564  pub defense: u8,
565  pub energy: u8,
566  pub missile: u8,
567}
568
569/// Leaderboard data, part of the [`ScoreBoard`] packet.
570#[derive(Copy, Clone, Debug)]
571#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
572pub struct ScoreBoardData {
573  pub id: Player,
574  pub score: Score,
575  pub level: Level,
576}
577
578/// Low-res player positions, part of the [`ScoreBoard`] packet.
579#[derive(Copy, Clone, Debug)]
580#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
581pub struct ScoreBoardRanking {
582  pub id: Player,
583  #[cfg_attr(feature = "serde", serde(with = "opt_vec"))]
584  pub pos: Option<Position>,
585}
586
587/// Leaderboard + Global player positions.
588///
589/// This is sent every 5 seconds by the server and is used by the client to
590/// update the leaderboard and minimap.
591#[derive(Clone, Debug)]
592#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
593pub struct ScoreBoard {
594  pub data: Vec<ScoreBoardData>,
595  pub rankings: Vec<ScoreBoardRanking>,
596}
597
598#[derive(Copy, Clone, Debug)]
599#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
600pub struct ScoreUpdate {
601  pub id: Player,
602  pub score: Score,
603  pub earnings: Score,
604  /// The number of unused upgrades that the player has.
605  pub upgrades: u16,
606  pub total_kills: u32,
607  pub total_deaths: u32,
608}
609
610/// End of game packet for CTF and BTR.
611///
612/// # CTF
613/// In CTF, the data of this packet contains a JSON string with 3 fields.
614///
615/// - `w`: The id of the winning team.
616/// - `b`: The bounty given to each player
617/// of the winning team.
618/// - `t`: The time (in seconds) that the banner should remain on screen before
619///   closing (unless closed by the player.)
620///
621/// # BTR
622/// In BTR, the data of this packet contains a JSON string with 5 fields.
623///
624/// - `p`: The name of the winning player.
625/// - `f`: The flag id of the winning player.
626/// - `b`: The bounty given to the winning player.
627/// - `k`: The number of kills that the winning player has.
628/// - `t`: The time (in seconds) that the banner should remain on the screen
629///   before closing (unless closed by the player.)
630#[derive(Clone, Debug)]
631#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
632pub struct ServerCustom {
633  #[cfg_attr(feature = "serde", serde(rename = "type"))]
634  pub ty: ServerCustomType,
635  pub data: BString,
636}
637
638/// Server banned message
639#[derive(Clone, Debug)]
640#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
641pub struct ServerMessage {
642  #[cfg_attr(feature = "serde", serde(rename = "type"))]
643  pub ty: ServerMessageType,
644  pub duration: u32,
645  pub text: BString,
646}
647
648/// Per-player data for detailed (tab) menu in BTR.
649#[derive(Copy, Clone, Debug)]
650#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
651pub struct ScoreDetailedBTREntry {
652  pub id: Player,
653  pub level: Level,
654  pub alive: bool,
655  pub wins: u16,
656  pub score: Score,
657  pub kills: u16,
658  pub deaths: u16,
659  pub damage: f32,
660  pub ping: u16,
661}
662
663#[derive(Clone, Debug)]
664#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
665pub struct ScoreDetailedBTR {
666  pub scores: Vec<ScoreDetailedBTREntry>,
667}
668
669/// Per-player data for detailed (tab) menu in CTF.
670#[derive(Copy, Clone, Debug)]
671#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
672pub struct ScoreDetailedCTFEntry {
673  pub id: Player,
674  pub level: Level,
675  pub captures: u16,
676  pub score: Score,
677  pub kills: u16,
678  pub deaths: u16,
679  pub damage: f32,
680  pub ping: u16,
681}
682
683/// Detailed score menu (tab) data for CTF.
684#[derive(Clone, Debug)]
685#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
686pub struct ScoreDetailedCTF {
687  pub scores: Vec<ScoreDetailedCTFEntry>,
688}
689
690/// Per-player data for detailed (tab) menu in FFA.
691#[derive(Copy, Clone, Debug)]
692#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
693pub struct ScoreDetailedFFAEntry {
694  pub id: Player,
695  pub level: Level,
696  pub score: Score,
697  pub kills: u16,
698  pub deaths: u16,
699  pub damage: f32,
700  pub ping: u16,
701}
702
703/// Detailed score menu (tab) data for FFA.
704#[derive(Clone, Debug)]
705#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
706pub struct ScoreDetailedFFA {
707  pub scores: Vec<ScoreDetailedFFAEntry>,
708}
709
710//===================================================================
711// Extra trait implementations
712
713impl Deref for Login2 {
714  type Target = Login;
715
716  fn deref(&self) -> &Self::Target {
717    &self.login
718  }
719}
720
721impl DerefMut for Login2 {
722  fn deref_mut(&mut self) -> &mut Self::Target {
723    &mut self.login
724  }
725}
726
727impl Deref for MobUpdate2 {
728  type Target = MobUpdate;
729
730  fn deref(&self) -> &Self::Target {
731    &self.update
732  }
733}
734
735impl DerefMut for MobUpdate2 {
736  fn deref_mut(&mut self) -> &mut Self::Target {
737    &mut self.update
738  }
739}