wgtk/net/element/
client.rs

1//! Definition of the elements that can be sent from server to client
2//! once connected to the base application..
3
4
5use std::io::{self, Write, Read};
6
7use glam::Vec3A;
8
9use crate::util::io::*;
10
11use super::{Element, SimpleElement, TopElement, NoopElement, ElementLength, ElementIdRange};
12use super::entity::{MethodCall};
13
14
15/// This modules defines in constants the numerical identifiers for
16/// client app elements.
17pub mod id {
18
19    use super::ElementIdRange;
20
21    pub const UPDATE_FREQUENCY_NOTIFICATION: u8 = 0x02;
22    pub const SET_GAME_TIME: u8                 = 0x03;
23    pub const RESET_ENTITIES: u8                = 0x04;
24    pub const CREATE_BASE_PLAYER: u8            = 0x05;
25    pub const CREATE_CELL_PLAYER: u8            = 0x06;
26    // TODO: 0x07: DummyPacket
27    // TODO: 0x08: SpaceProperty
28    // TODO: 0x09: AddSpaceGeometryMapping
29    // TODO: 0x0A: RemoveSpaceGeometryMapping
30    // TODO: 0x0B: CreateEntity
31    // TODO: 0x0C: CreateEntityDetailed
32    pub const TICK_SYNC: u8                     = 0x13;
33    pub const SELECT_PLAYER_ENTITY: u8          = 0x1A;
34    pub const FORCED_POSITION: u8               = 0x1B;
35
36    pub const ENTITY_METHOD: ElementIdRange     = ElementIdRange::new(0xA7, 0xFE);
37
38}
39
40
41/// The server informs us how frequently it is going to send update
42/// the the client, and also give the server game time (exactly the
43/// same as [`SetGameTime`] element, but inlined here).
44#[derive(Debug, Clone)]
45pub struct UpdateFrequencyNotification {
46    /// The frequency in hertz.
47    pub frequency: u8,
48    /// The server game time.
49    pub game_time: u32,
50}
51
52impl SimpleElement for UpdateFrequencyNotification {
53
54    fn encode(&self, write: &mut impl Write) -> io::Result<()> {
55        write.write_u8(self.frequency)?;
56        write.write_u16(1)?;
57        write.write_u32(self.game_time)
58    }
59
60    fn decode(read: &mut impl Read, _len: usize) -> io::Result<Self> {
61        Ok(Self { 
62            frequency: read.read_u8()?,
63            // Skip 2 bytes that we don't use.
64            game_time: { read.read_u16()?; read.read_u32()? },
65        })
66    }
67
68}
69
70impl TopElement for UpdateFrequencyNotification {
71    const LEN: ElementLength = ElementLength::Fixed(7);
72}
73
74
75/// The server informs us of the current (server) game time.
76#[derive(Debug, Clone)]
77pub struct SetGameTime {
78    /// The server game time.
79    pub game_time: u32,
80}
81
82impl SimpleElement for SetGameTime {
83
84    fn encode(&self, write: &mut impl Write) -> io::Result<()> {
85        write.write_u32(self.game_time)
86    }
87
88    fn decode(read: &mut impl Read, _len: usize) -> io::Result<Self> {
89        Ok(Self { game_time: read.read_u32()? })
90    }
91
92}
93
94impl TopElement for SetGameTime {
95    const LEN: ElementLength = ElementLength::Fixed(4);
96}
97
98
99/// The server wants to resets the entities in the Area of Interest (AoI).
100#[derive(Debug, Clone)]
101pub struct ResetEntities {
102    pub keep_player_on_base: bool,
103}
104
105impl SimpleElement for ResetEntities {
106
107    fn encode(&self, write: &mut impl Write) -> io::Result<()> {
108        write.write_bool(self.keep_player_on_base)
109    }
110
111    fn decode(read: &mut impl Read, _len: usize) -> io::Result<Self> {
112        Ok(Self { keep_player_on_base: read.read_bool()? })
113    }
114
115}
116
117impl TopElement for ResetEntities {
118    const LEN: ElementLength = ElementLength::Fixed(1);
119}
120
121
122/// Sent from the base when a player should be created, the entity id
123/// is given with its type.
124/// 
125/// The remaining data will later be decoded properly depending on the
126/// entity type, it's used for initializing its properties (TODO).
127/// For example the `Login` entity receive the account UID.
128#[derive(Debug, Clone)]
129pub struct CreateBasePlayer<E> {
130    /// The unique identifier of the entity being created.
131    pub entity_id: u32,
132    /// The entity type identifier being created.
133    pub entity_type: u16,
134    /// This string's usage is currently unknown.
135    pub unk: String,
136    /// The actual data to be sent for creating the player's entity.
137    pub entity_data: E,
138    /// This integer describe the number of entity components composing
139    /// the entity, this value must be strictly equal to the same value
140    /// as the client.
141    /// 
142    /// TODO: This number is used to know how much entity components
143    /// must be parsed after this number. Components can be seen as
144    /// regular components. **It's not currently implemented.**
145    pub entity_components_count: u8,
146}
147
148impl<E: Element<Config = ()>> SimpleElement for CreateBasePlayer<E> {
149
150    fn encode(&self, write: &mut impl Write) -> io::Result<()> {
151        write.write_u32(self.entity_id)?;
152        write.write_u16(self.entity_type)?;
153        write.write_string_variable(&self.unk)?;
154        self.entity_data.encode(&mut *write, &())?;
155        write.write_u8(self.entity_components_count)
156    }
157
158    fn decode(read: &mut impl Read, len: usize) -> io::Result<Self> {
159        Ok(Self {
160            entity_id: read.read_u32()?,
161            entity_type: read.read_u16()?,
162            unk: read.read_string_variable()?,
163            entity_data: E::decode(&mut *read, len - 7, &())?,
164            entity_components_count: read.read_u8()?,
165        })
166    }
167}
168
169impl<E: Element<Config = ()>> TopElement for CreateBasePlayer<E> {
170    const LEN: ElementLength = ElementLength::Variable16;
171}
172
173
174/// It is used as a timestamp for the elements in a bundle.
175#[derive(Debug, Clone)]
176pub struct TickSync {
177    pub tick: u8,
178}
179
180impl SimpleElement for TickSync {
181
182    fn encode(&self, write: &mut impl Write) -> io::Result<()> {
183        write.write_u8(self.tick)
184    }
185
186    fn decode(read: &mut impl Read, _len: usize) -> io::Result<Self> {
187        Ok(Self { tick: read.read_u8()? })
188    }
189
190}
191
192impl TopElement for TickSync {
193    const LEN: ElementLength = ElementLength::Fixed(1);
194}
195
196
197/// Sent by the server to inform that subsequent elements will target
198/// the player entity.
199#[derive(Debug, Default, Clone, Copy)]
200pub struct SelectPlayerEntity;
201
202impl NoopElement for SelectPlayerEntity { }
203impl TopElement for SelectPlayerEntity {
204    const LEN: ElementLength = ElementLength::Fixed(0);
205}
206
207
208/// This is when an update is being forced back for an (ordinarily)
209/// client controlled entity, including for the player. Usually this is
210/// due to a physics correction from the server, but it could be for any
211/// reason decided by the server (e.g. server-initiated teleport).
212#[derive(Debug, Clone)]
213pub struct ForcedPosition {
214    pub entity_id: u32,
215    pub space_id: u32,
216    pub vehicle_entity_id: u32,
217    pub position: Vec3A,
218    pub direction: Vec3A,
219}
220
221impl SimpleElement for ForcedPosition {
222
223    fn encode(&self, write: &mut impl Write) -> io::Result<()> {
224        write.write_u32(self.entity_id)?;
225        write.write_u32(self.space_id)?;
226        write.write_u32(self.vehicle_entity_id)?;
227        write.write_vec3(self.position)?;
228        write.write_vec3(self.direction)
229    }
230
231    fn decode(read: &mut impl Read, _len: usize) -> io::Result<Self> {
232        Ok(Self {
233            entity_id: read.read_u32()?,
234            space_id: read.read_u32()?,
235            vehicle_entity_id: read.read_u32()?,
236            position: read.read_vec3()?,
237            direction: read.read_vec3()?,
238        })
239    }
240
241}
242
243
244pub const ENTITY_METHOD_ID_RANGE: ElementIdRange = ElementIdRange::new(0x4E, 0xA6);
245
246
247/// Call a method on the currently selected client's entity.
248pub struct EntityMethod<M: MethodCall> {
249    pub method: M,
250}
251
252impl<M: MethodCall> EntityMethod<M> {
253
254
255
256}
257
258
259
260// /// Setting a selected entity's property value.
261// #[derive(Debug)]
262// pub struct EntityProperty {
263
264// }
265
266// impl EntityProperty {
267
268//     pub const FIRST_ID: u8 = 0xA7;
269//     pub const LAST_ID: u8 = 0xFE;
270
271//     /// Convert a property index to a message id.
272//     pub const fn index_to_id(index: u8) -> u8 {
273//         Self::FIRST_ID + index
274//     }
275
276//     /// Convert a message id to method index.
277//     pub const fn id_to_index(id: u8) -> u16 {
278//         (id - Self::FIRST_ID) as _
279//     }
280
281// }