1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use std::{mem::align_of, num::NonZeroU64};
use alkahest::{Pack, Schema, SchemaUnpack, Seq};
mod client;
mod server;
pub use self::{client::*, server::*};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct PlayerId(pub NonZeroU64);
#[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)]
#[error("Zero PlayerId unpacked")]
pub struct ZeroPlayerIdError;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct ClientId(pub NonZeroU64);
impl SchemaUnpack<'_> for PlayerId {
type Unpacked = Result<Self, ZeroPlayerIdError>;
}
impl Schema for PlayerId {
type Packed = u64;
fn align() -> usize {
align_of::<u64>()
}
fn unpack<'a>(packed: u64, _input: &'a [u8]) -> Result<Self, ZeroPlayerIdError> {
NonZeroU64::new(packed)
.map(PlayerId)
.ok_or(ZeroPlayerIdError)
}
}
impl Pack<PlayerId> for PlayerId {
fn pack(self, _offset: usize, _output: &mut [u8]) -> (u64, usize) {
(self.0.get(), 0)
}
}
pub struct MaybePlayerId;
impl SchemaUnpack<'_> for MaybePlayerId {
type Unpacked = Option<PlayerId>;
}
impl Schema for MaybePlayerId {
type Packed = u64;
fn align() -> usize {
align_of::<u64>()
}
fn unpack<'a>(packed: u64, _input: &'a [u8]) -> Option<PlayerId> {
NonZeroU64::new(packed).map(PlayerId)
}
}
impl Pack<MaybePlayerId> for PlayerId {
fn pack(self, _offset: usize, _output: &mut [u8]) -> (u64, usize) {
(self.0.get(), 0)
}
}
impl Pack<MaybePlayerId> for Option<PlayerId> {
fn pack(self, _offset: usize, _output: &mut [u8]) -> (u64, usize) {
(self.map_or(0, |pid| pid.0.get()), 0)
}
}
#[allow(unused)]
#[derive(Schema)]
enum ClientMessage<P: Schema = (), I: Schema = ()> {
Connect {
token: alkahest::Str,
},
AddPlayer {
player: P,
},
Inputs {
step: u64,
next_update_step: u64,
inputs: Seq<(PlayerId, I)>,
},
}
#[allow(unused)]
#[derive(Schema)]
enum ServerMessage<J: Schema = (), U: Schema = ()> {
Connected { step: u64 },
PlayerJoined { info: J },
Updates { server_step: u64, updates: U },
}