-
Notifications
You must be signed in to change notification settings - Fork 1
/
Packet.cs
455 lines (419 loc) · 15.8 KB
/
Packet.cs
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Text;
namespace Leder_Efter_Server
{
/// <summary>Sent from server to client.</summary>
public enum ServerPackets
{
welcome = 1,
signIn,
signUp,
hostRoom,
joinRoom,
leaveRoom,
destroyRoom,
playerJoined,
startMatch,
playerPosition,
chatbox,
randomize,
color,
spawnPlayer,
playerPos,
playerRot,
readyGaQi,
winlose,
triviaQuestion,
triviaDatabase,
scorePlaySent
}
/// <summary>Sent from client to server.</summary>
public enum ClientPackets
{
welcomeRequest = 1,
signInRequest,
signUpRequest,
hostRoomRequest,
joinRoomRequest,
leaveRoomRequest,
destroyRoomRequest,
startMatchRequest,
playerPositionRequest,
chatboxRequest,
randomizeRequest,
colorRequest,
playerMovement,
mintakSpawnDong,
readyGan,
triviaQuestionRequest,
triviaDatabaseRequest,
storeScorePlay,
scorePlayRequest
}
public class Packet : IDisposable
{
private List<byte> buffer;
private byte[] readableBuffer;
private int readPos;
/// <summary>Creates a new empty packet (without an ID).</summary>
public Packet()
{
buffer = new List<byte>(); // Intitialize buffer
readPos = 0; // Set readPos to 0
}
/// <summary>Creates a new packet with a given ID. Used for sending.</summary>
/// <param name="_id">The packet ID.</param>
public Packet(int _id)
{
buffer = new List<byte>(); // Intitialize buffer
readPos = 0; // Set readPos to 0
Write(_id); // Write packet id to the buffer
}
/// <summary>Creates a packet from which data can be read. Used for receiving.</summary>
/// <param name="_data">The bytes to add to the packet.</param>
public Packet(byte[] _data)
{
buffer = new List<byte>(); // Intitialize buffer
readPos = 0; // Set readPos to 0
SetBytes(_data);
}
#region Functions
/// <summary>Sets the packet's content and prepares it to be read.</summary>
/// <param name="_data">The bytes to add to the packet.</param>
public void SetBytes(byte[] _data)
{
Write(_data);
readableBuffer = buffer.ToArray();
}
/// <summary>Inserts the length of the packet's content at the start of the buffer.</summary>
public void WriteLength()
{
buffer.InsertRange(0, BitConverter.GetBytes(buffer.Count)); // Insert the byte length of the packet at the very beginning
}
/// <summary>Inserts the given int at the start of the buffer.</summary>
/// <param name="_value">The int to insert.</param>
public void InsertInt(int _value)
{
buffer.InsertRange(0, BitConverter.GetBytes(_value)); // Insert the int at the start of the buffer
}
/// <summary>Gets the packet's content in array form.</summary>
public byte[] ToArray()
{
readableBuffer = buffer.ToArray();
return readableBuffer;
}
/// <summary>Gets the length of the packet's content.</summary>
public int Length()
{
return buffer.Count; // Return the length of buffer
}
/// <summary>Gets the length of the unread data contained in the packet.</summary>
public int UnreadLength()
{
return Length() - readPos; // Return the remaining length (unread)
}
/// <summary>Resets the packet instance to allow it to be reused.</summary>
/// <param name="_shouldReset">Whether or not to reset the packet.</param>
public void Reset(bool _shouldReset = true)
{
if (_shouldReset)
{
buffer.Clear(); // Clear buffer
readableBuffer = null;
readPos = 0; // Reset readPos
}
else
{
readPos -= 4; // "Unread" the last read int
}
}
#endregion
#region Write Data
/// <summary>Adds a byte to the packet.</summary>
/// <param name="_value">The byte to add.</param>
public void Write(byte _value)
{
buffer.Add(_value);
}
/// <summary>Adds an array of bytes to the packet.</summary>
/// <param name="_value">The byte array to add.</param>
public void Write(byte[] _value)
{
buffer.AddRange(_value);
}
/// <summary>Adds a short to the packet.</summary>
/// <param name="_value">The short to add.</param>
public void Write(short _value)
{
buffer.AddRange(BitConverter.GetBytes(_value));
}
/// <summary>Adds an int to the packet.</summary>
/// <param name="_value">The int to add.</param>
public void Write(int _value)
{
buffer.AddRange(BitConverter.GetBytes(_value));
}
/// <summary>Adds a long to the packet.</summary>
/// <param name="_value">The long to add.</param>
public void Write(long _value)
{
buffer.AddRange(BitConverter.GetBytes(_value));
}
/// <summary>Adds a float to the packet.</summary>
/// <param name="_value">The float to add.</param>
public void Write(float _value)
{
buffer.AddRange(BitConverter.GetBytes(_value));
}
/// <summary>Adds a bool to the packet.</summary>
/// <param name="_value">The bool to add.</param>
public void Write(bool _value)
{
buffer.AddRange(BitConverter.GetBytes(_value));
}
/// <summary>Adds a string to the packet.</summary>
/// <param name="_value">The string to add.</param>
public void Write(string _value)
{
Write(_value.Length); // Add the length of the string to the packet
buffer.AddRange(Encoding.ASCII.GetBytes(_value)); // Add the string itself
}
/// <summary>Adds an object to the packet.</summary>
/// <param name="_value">The object to add.</param>
public void Write<T>(T _value)
{
byte[] _objectByteArray = ClassSerializer.ObjectToByteArray(_value); //serialize object and convert it to byte array
Write(_objectByteArray.Length); // Add the length of the object byte array to the packet
Write(_objectByteArray); // Add the object byte array itself
}
/// <summary>Adds a Vector3 to the packet.</summary>
/// <param name="_value">The Vector3 to add.</param>
public void Write(Vector3 _value)
{
Write(_value.X);
Write(_value.Y);
Write(_value.Z);
}
/// <summary>Adds a Quaternion to the packet.</summary>
/// <param name="_value">The Quaternion to add.</param>
public void Write(Quaternion _value)
{
Write(_value.X);
Write(_value.Y);
Write(_value.Z);
Write(_value.W);
}
#endregion
#region Read Data
/// <summary>Reads a byte from the packet.</summary>
/// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
public byte ReadByte(bool _moveReadPos = true)
{
if (buffer.Count > readPos)
{
// If there are unread bytes
byte _value = readableBuffer[readPos]; // Get the byte at readPos' position
if (_moveReadPos)
{
// If _moveReadPos is true
readPos += 1; // Increase readPos by 1
}
return _value; // Return the byte
}
else
{
throw new Exception("Could not read value of type 'byte'!");
}
}
/// <summary>Reads an array of bytes from the packet.</summary>
/// <param name="_length">The length of the byte array.</param>
/// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
public byte[] ReadBytes(int _length, bool _moveReadPos = true)
{
if (buffer.Count > readPos)
{
// If there are unread bytes
byte[] _value = buffer.GetRange(readPos, _length).ToArray(); // Get the bytes at readPos' position with a range of _length
if (_moveReadPos)
{
// If _moveReadPos is true
readPos += _length; // Increase readPos by _length
}
return _value; // Return the bytes
}
else
{
throw new Exception("Could not read value of type 'byte[]'!");
}
}
/// <summary>Reads a short from the packet.</summary>
/// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
public short ReadShort(bool _moveReadPos = true)
{
if (buffer.Count > readPos)
{
// If there are unread bytes
short _value = BitConverter.ToInt16(readableBuffer, readPos); // Convert the bytes to a short
if (_moveReadPos)
{
// If _moveReadPos is true and there are unread bytes
readPos += 2; // Increase readPos by 2
}
return _value; // Return the short
}
else
{
throw new Exception("Could not read value of type 'short'!");
}
}
/// <summary>Reads an int from the packet.</summary>
/// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
public int ReadInt(bool _moveReadPos = true)
{
if (buffer.Count > readPos)
{
// If there are unread bytes
int _value = BitConverter.ToInt32(readableBuffer, readPos); // Convert the bytes to an int
if (_moveReadPos)
{
// If _moveReadPos is true
readPos += 4; // Increase readPos by 4
}
return _value; // Return the int
}
else
{
throw new Exception("Could not read value of type 'int'!");
}
}
/// <summary>Reads a long from the packet.</summary>
/// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
public long ReadLong(bool _moveReadPos = true)
{
if (buffer.Count > readPos)
{
// If there are unread bytes
long _value = BitConverter.ToInt64(readableBuffer, readPos); // Convert the bytes to a long
if (_moveReadPos)
{
// If _moveReadPos is true
readPos += 8; // Increase readPos by 8
}
return _value; // Return the long
}
else
{
throw new Exception("Could not read value of type 'long'!");
}
}
/// <summary>Reads a float from the packet.</summary>
/// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
public float ReadFloat(bool _moveReadPos = true)
{
if (buffer.Count > readPos)
{
// If there are unread bytes
float _value = BitConverter.ToSingle(readableBuffer, readPos); // Convert the bytes to a float
if (_moveReadPos)
{
// If _moveReadPos is true
readPos += 4; // Increase readPos by 4
}
return _value; // Return the float
}
else
{
throw new Exception("Could not read value of type 'float'!");
}
}
/// <summary>Reads a bool from the packet.</summary>
/// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
public bool ReadBool(bool _moveReadPos = true)
{
if (buffer.Count > readPos)
{
// If there are unread bytes
bool _value = BitConverter.ToBoolean(readableBuffer, readPos); // Convert the bytes to a bool
if (_moveReadPos)
{
// If _moveReadPos is true
readPos += 1; // Increase readPos by 1
}
return _value; // Return the bool
}
else
{
throw new Exception("Could not read value of type 'bool'!");
}
}
/// <summary>Reads a string from the packet.</summary>
/// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
public string ReadString(bool _moveReadPos = true)
{
try
{
int _length = ReadInt(); // Get the length of the string
string _value = Encoding.ASCII.GetString(readableBuffer, readPos, _length); // Convert the bytes to a string
if (_moveReadPos && _value.Length > 0)
{
// If _moveReadPos is true string is not empty
readPos += _length; // Increase readPos by the length of the string
}
return _value; // Return the string
}
catch
{
throw new Exception("Could not read value of type 'string'!");
}
}
/// <summary>Reads an object from the packet.</summary>
/// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
public T ReadObject<T>(bool _moveReadPos = true)
{
try
{
int _length = ReadInt(_moveReadPos); // Get the length of the object bytes array
byte[] _objectByteArray = ReadBytes(_length, _moveReadPos); // Get the object byte array
return (T)ClassSerializer.ByteArrayToObject(_objectByteArray); // Convert the byte array and return the object
}
catch
{
throw new Exception("Could not read value of type 'object'!");
}
}
/// <summary>Reads a Vector3 from the packet.</summary>
/// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
public Vector3 ReadVector3(bool _moveReadPos = true)
{
return new Vector3(ReadFloat(_moveReadPos), ReadFloat(_moveReadPos), ReadFloat(_moveReadPos));
}
/// <summary>Reads a Quaternion from the packet.</summary>
/// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
public Quaternion ReadQuaternion(bool _moveReadPos = true)
{
return new Quaternion(ReadFloat(_moveReadPos), ReadFloat(_moveReadPos), ReadFloat(_moveReadPos), ReadFloat(_moveReadPos));
}
#endregion
private bool disposed = false;
protected virtual void Dispose(bool _disposing)
{
if (!disposed)
{
if (_disposing)
{
buffer = null;
readableBuffer = null;
readPos = 0;
}
disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}