Test de communication de paquets entre un client et un serveur
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using UnityEngine;
  5. /// <summary>Sent from server to client.</summary>
  6. public enum ServerPackets
  7. {
  8. welcome = 1,
  9. spawnPlayer,
  10. playerPosition,
  11. playerRotation,
  12. playerDisconnected,
  13. playerHealth,
  14. playerRespawned
  15. }
  16. /// <summary>Sent from client to server.</summary>
  17. public enum ClientPackets
  18. {
  19. welcomeReceived = 1,
  20. playerMovement,
  21. playerShoot
  22. }
  23. public class Packet : IDisposable
  24. {
  25. private List<byte> buffer;
  26. private byte[] readableBuffer;
  27. private int readPos;
  28. /// <summary>Creates a new empty packet (without an ID).</summary>
  29. public Packet()
  30. {
  31. buffer = new List<byte>(); // Intitialize buffer
  32. readPos = 0; // Set readPos to 0
  33. }
  34. /// <summary>Creates a new packet with a given ID. Used for sending.</summary>
  35. /// <param name="_id">The packet ID.</param>
  36. public Packet(int _id)
  37. {
  38. buffer = new List<byte>(); // Intitialize buffer
  39. readPos = 0; // Set readPos to 0
  40. Write(_id); // Write packet id to the buffer
  41. }
  42. /// <summary>Creates a packet from which data can be read. Used for receiving.</summary>
  43. /// <param name="_data">The bytes to add to the packet.</param>
  44. public Packet(byte[] _data)
  45. {
  46. buffer = new List<byte>(); // Intitialize buffer
  47. readPos = 0; // Set readPos to 0
  48. SetBytes(_data);
  49. }
  50. #region Functions
  51. /// <summary>Sets the packet's content and prepares it to be read.</summary>
  52. /// <param name="_data">The bytes to add to the packet.</param>
  53. public void SetBytes(byte[] _data)
  54. {
  55. Write(_data);
  56. readableBuffer = buffer.ToArray();
  57. }
  58. /// <summary>Inserts the length of the packet's content at the start of the buffer.</summary>
  59. public void WriteLength()
  60. {
  61. buffer.InsertRange(0, BitConverter.GetBytes(buffer.Count)); // Insert the byte length of the packet at the very beginning
  62. }
  63. /// <summary>Inserts the given int at the start of the buffer.</summary>
  64. /// <param name="_value">The int to insert.</param>
  65. public void InsertInt(int _value)
  66. {
  67. buffer.InsertRange(0, BitConverter.GetBytes(_value)); // Insert the int at the start of the buffer
  68. }
  69. /// <summary>Gets the packet's content in array form.</summary>
  70. public byte[] ToArray()
  71. {
  72. readableBuffer = buffer.ToArray();
  73. return readableBuffer;
  74. }
  75. /// <summary>Gets the length of the packet's content.</summary>
  76. public int Length()
  77. {
  78. return buffer.Count; // Return the length of buffer
  79. }
  80. /// <summary>Gets the length of the unread data contained in the packet.</summary>
  81. public int UnreadLength()
  82. {
  83. return Length() - readPos; // Return the remaining length (unread)
  84. }
  85. /// <summary>Resets the packet instance to allow it to be reused.</summary>
  86. /// <param name="_shouldReset">Whether or not to reset the packet.</param>
  87. public void Reset(bool _shouldReset = true)
  88. {
  89. if (_shouldReset)
  90. {
  91. buffer.Clear(); // Clear buffer
  92. readableBuffer = null;
  93. readPos = 0; // Reset readPos
  94. }
  95. else
  96. {
  97. readPos -= 4; // "Unread" the last read int
  98. }
  99. }
  100. #endregion
  101. #region Write Data
  102. /// <summary>Adds a byte to the packet.</summary>
  103. /// <param name="_value">The byte to add.</param>
  104. public void Write(byte _value)
  105. {
  106. buffer.Add(_value);
  107. }
  108. /// <summary>Adds an array of bytes to the packet.</summary>
  109. /// <param name="_value">The byte array to add.</param>
  110. public void Write(byte[] _value)
  111. {
  112. buffer.AddRange(_value);
  113. }
  114. /// <summary>Adds a short to the packet.</summary>
  115. /// <param name="_value">The short to add.</param>
  116. public void Write(short _value)
  117. {
  118. buffer.AddRange(BitConverter.GetBytes(_value));
  119. }
  120. /// <summary>Adds an int to the packet.</summary>
  121. /// <param name="_value">The int to add.</param>
  122. public void Write(int _value)
  123. {
  124. buffer.AddRange(BitConverter.GetBytes(_value));
  125. }
  126. /// <summary>Adds a long to the packet.</summary>
  127. /// <param name="_value">The long to add.</param>
  128. public void Write(long _value)
  129. {
  130. buffer.AddRange(BitConverter.GetBytes(_value));
  131. }
  132. /// <summary>Adds a float to the packet.</summary>
  133. /// <param name="_value">The float to add.</param>
  134. public void Write(float _value)
  135. {
  136. buffer.AddRange(BitConverter.GetBytes(_value));
  137. }
  138. /// <summary>Adds a bool to the packet.</summary>
  139. /// <param name="_value">The bool to add.</param>
  140. public void Write(bool _value)
  141. {
  142. buffer.AddRange(BitConverter.GetBytes(_value));
  143. }
  144. /// <summary>Adds a string to the packet.</summary>
  145. /// <param name="_value">The string to add.</param>
  146. public void Write(string _value)
  147. {
  148. Write(_value.Length); // Add the length of the string to the packet
  149. buffer.AddRange(Encoding.ASCII.GetBytes(_value)); // Add the string itself
  150. }
  151. public void Write(Vector3 _value)
  152. {
  153. Write(_value.x);
  154. Write(_value.y);
  155. Write(_value.z);
  156. }
  157. public void Write(Quaternion _value)
  158. {
  159. Write(_value.x);
  160. Write(_value.y);
  161. Write(_value.z);
  162. Write(_value.w);
  163. }
  164. #endregion
  165. #region Read Data
  166. /// <summary>Reads a byte from the packet.</summary>
  167. /// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
  168. public byte ReadByte(bool _moveReadPos = true)
  169. {
  170. if (buffer.Count > readPos)
  171. {
  172. // If there are unread bytes
  173. byte _value = readableBuffer[readPos]; // Get the byte at readPos' position
  174. if (_moveReadPos)
  175. {
  176. // If _moveReadPos is true
  177. readPos += 1; // Increase readPos by 1
  178. }
  179. return _value; // Return the byte
  180. }
  181. else
  182. {
  183. throw new Exception("Could not read value of type 'byte'!");
  184. }
  185. }
  186. /// <summary>Reads an array of bytes from the packet.</summary>
  187. /// <param name="_length">The length of the byte array.</param>
  188. /// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
  189. public byte[] ReadBytes(int _length, bool _moveReadPos = true)
  190. {
  191. if (buffer.Count > readPos)
  192. {
  193. // If there are unread bytes
  194. byte[] _value = buffer.GetRange(readPos, _length).ToArray(); // Get the bytes at readPos' position with a range of _length
  195. if (_moveReadPos)
  196. {
  197. // If _moveReadPos is true
  198. readPos += _length; // Increase readPos by _length
  199. }
  200. return _value; // Return the bytes
  201. }
  202. else
  203. {
  204. throw new Exception("Could not read value of type 'byte[]'!");
  205. }
  206. }
  207. /// <summary>Reads a short from the packet.</summary>
  208. /// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
  209. public short ReadShort(bool _moveReadPos = true)
  210. {
  211. if (buffer.Count > readPos)
  212. {
  213. // If there are unread bytes
  214. short _value = BitConverter.ToInt16(readableBuffer, readPos); // Convert the bytes to a short
  215. if (_moveReadPos)
  216. {
  217. // If _moveReadPos is true and there are unread bytes
  218. readPos += 2; // Increase readPos by 2
  219. }
  220. return _value; // Return the short
  221. }
  222. else
  223. {
  224. throw new Exception("Could not read value of type 'short'!");
  225. }
  226. }
  227. /// <summary>Reads an int from the packet.</summary>
  228. /// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
  229. public int ReadInt(bool _moveReadPos = true)
  230. {
  231. if (buffer.Count > readPos)
  232. {
  233. // If there are unread bytes
  234. int _value = BitConverter.ToInt32(readableBuffer, readPos); // Convert the bytes to an int
  235. if (_moveReadPos)
  236. {
  237. // If _moveReadPos is true
  238. readPos += 4; // Increase readPos by 4
  239. }
  240. return _value; // Return the int
  241. }
  242. else
  243. {
  244. throw new Exception("Could not read value of type 'int'!");
  245. }
  246. }
  247. /// <summary>Reads a long from the packet.</summary>
  248. /// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
  249. public long ReadLong(bool _moveReadPos = true)
  250. {
  251. if (buffer.Count > readPos)
  252. {
  253. // If there are unread bytes
  254. long _value = BitConverter.ToInt64(readableBuffer, readPos); // Convert the bytes to a long
  255. if (_moveReadPos)
  256. {
  257. // If _moveReadPos is true
  258. readPos += 8; // Increase readPos by 8
  259. }
  260. return _value; // Return the long
  261. }
  262. else
  263. {
  264. throw new Exception("Could not read value of type 'long'!");
  265. }
  266. }
  267. /// <summary>Reads a float from the packet.</summary>
  268. /// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
  269. public float ReadFloat(bool _moveReadPos = true)
  270. {
  271. if (buffer.Count > readPos)
  272. {
  273. // If there are unread bytes
  274. float _value = BitConverter.ToSingle(readableBuffer, readPos); // Convert the bytes to a float
  275. if (_moveReadPos)
  276. {
  277. // If _moveReadPos is true
  278. readPos += 4; // Increase readPos by 4
  279. }
  280. return _value; // Return the float
  281. }
  282. else
  283. {
  284. throw new Exception("Could not read value of type 'float'!");
  285. }
  286. }
  287. /// <summary>Reads a bool from the packet.</summary>
  288. /// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
  289. public bool ReadBool(bool _moveReadPos = true)
  290. {
  291. if (buffer.Count > readPos)
  292. {
  293. // If there are unread bytes
  294. bool _value = BitConverter.ToBoolean(readableBuffer, readPos); // Convert the bytes to a bool
  295. if (_moveReadPos)
  296. {
  297. // If _moveReadPos is true
  298. readPos += 1; // Increase readPos by 1
  299. }
  300. return _value; // Return the bool
  301. }
  302. else
  303. {
  304. throw new Exception("Could not read value of type 'bool'!");
  305. }
  306. }
  307. /// <summary>Reads a string from the packet.</summary>
  308. /// <param name="_moveReadPos">Whether or not to move the buffer's read position.</param>
  309. public string ReadString(bool _moveReadPos = true)
  310. {
  311. try
  312. {
  313. int _length = ReadInt(); // Get the length of the string
  314. string _value = Encoding.ASCII.GetString(readableBuffer, readPos, _length); // Convert the bytes to a string
  315. if (_moveReadPos && _value.Length > 0)
  316. {
  317. // If _moveReadPos is true string is not empty
  318. readPos += _length; // Increase readPos by the length of the string
  319. }
  320. return _value; // Return the string
  321. }
  322. catch
  323. {
  324. throw new Exception("Could not read value of type 'string'!");
  325. }
  326. }
  327. public Vector3 ReadVector3(bool _moveReadPos = true)
  328. {
  329. return new Vector3(ReadFloat(_moveReadPos), ReadFloat(_moveReadPos), ReadFloat(_moveReadPos));
  330. }
  331. public Quaternion ReadQuaternion(bool _moveReadPos = true)
  332. {
  333. return new Quaternion(ReadFloat(_moveReadPos), ReadFloat(_moveReadPos), ReadFloat(_moveReadPos), ReadFloat(_moveReadPos));
  334. }
  335. #endregion
  336. private bool disposed = false;
  337. protected virtual void Dispose(bool _disposing)
  338. {
  339. if (!disposed)
  340. {
  341. if (_disposing)
  342. {
  343. buffer = null;
  344. readableBuffer = null;
  345. readPos = 0;
  346. }
  347. disposed = true;
  348. }
  349. }
  350. public void Dispose()
  351. {
  352. Dispose(true);
  353. GC.SuppressFinalize(this);
  354. }
  355. }