Test de communication de paquets entre un client et un serveur
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

Packet.cs 12KB

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. }