eolib/packet/
sequencer.rs

1use std::cmp;
2
3use rand::Rng;
4
5use crate::data::CHAR_MAX;
6
7#[derive(Debug)]
8/// Used for packet sequencing
9///
10/// The sequence value is sent at the start of every client packet
11/// and verified on the server.
12///
13/// The starting value can be reset at different stages in game play.
14///
15/// In the original game protocol these places are:
16/// - Handshake (Init_Init packet)
17/// - Account creation
18/// - Server pings
19pub struct Sequencer {
20    start: i32,
21    counter: i32,
22}
23
24impl Sequencer {
25    /// creates a new [Sequencer] with the specified starting value
26    pub fn new(start: i32) -> Self {
27        Self { start, counter: 0 }
28    }
29
30    /// returns the next sequence value
31    pub fn next_sequence(&mut self) -> i32 {
32        self.counter = (self.counter + 1) % 10;
33        self.start + self.counter
34    }
35
36    /// sets a new starting value for the sequencer
37    pub fn set_start(&mut self, start: i32) {
38        self.start = start;
39    }
40
41    /// gets the current starting value for the sequencer
42    pub fn get_start(&self) -> i32 {
43        self.start
44    }
45}
46
47/// returns a random sequence start value
48pub fn generate_sequence_start() -> i32 {
49    let mut rng = rand::thread_rng();
50    rng.gen_range(0..=CHAR_MAX - 10)
51}
52
53/// returns sequence bytes from a starting value
54///
55/// used by the server for Init_Init packet
56pub fn get_init_sequence_bytes(start: i32) -> [i32; 2] {
57    let mut rng = rand::thread_rng();
58    let seq1_min = cmp::max(0, (start - (CHAR_MAX - 1) + 13 + 6) / 7);
59    let seq1_max = (start + 13) / 7;
60    let seq1 = rng.gen_range(0..=seq1_max - seq1_min) + seq1_min;
61    let seq2 = start - seq1 * 7 + 13;
62    [seq1, seq2]
63}
64
65/// returns the initial sequence start value from sequence bytes
66///
67/// used by the client after receiving Init_Init packet
68pub fn get_init_sequence_start(s1: i32, s2: i32) -> i32 {
69    s1 * 7 + s2 - 13
70}
71
72/// returns sequence bytes from a starting value
73///
74/// used by the server for Ping packet
75pub fn get_ping_sequence_bytes(start: i32) -> [i32; 2] {
76    let mut rng = rand::thread_rng();
77    let seq1_max = start + 252;
78    let seq1_min = start;
79    let seq1 = rng.gen_range(seq1_min..=seq1_max);
80    let seq2 = seq1 - start;
81    [seq1, seq2]
82}
83
84/// returns the ping sequence start value from sequence bytes
85///
86/// used by the client after receiving Ping packet
87pub fn get_ping_sequence_start(s1: i32, s2: i32) -> i32 {
88    s1 - s2
89}