Client LuaCsForBarotrauma
Message.cs
1 using Lidgren.Network;
2 using System;
3 using System.IO;
4 using System.IO.Compression;
5 using System.Runtime.InteropServices;
6 using System.Text;
7 using Microsoft.Xna.Framework;
8 
9 namespace Barotrauma.Networking
10 {
11  public static class MsgConstants
12  {
13  // MTU currently set to the upper limit of what EOS P2P can do
14  // TODO: determine dynamically so other protocols can use a larger MTU,
15  // as well as handle a client with a lower MTU set outside of our control
16  public const int MTU = 1170;
17 
18  public const int CompressionThreshold = 1000;
19  public const int InitialBufferSize = 256;
20  public const int BufferOverAllocateAmount = 4;
21  }
22 
26  [StructLayout(LayoutKind.Explicit)]
27  public struct SingleUIntUnion
28  {
32  [FieldOffset(0)]
33  public float SingleValue;
34 
38  [FieldOffset(0)]
39  public uint UIntValue;
40  }
41 
42  internal static class MsgWriter
43  {
44  internal static void UpdateBitLength(ref int bitLength, int bitPos)
45  {
46  bitLength = Math.Max(bitLength, bitPos);
47  }
48 
49  internal static void WriteBoolean(ref byte[] buf, ref int bitPos, ref int bitLength, bool val)
50  {
51 #if DEBUG
52  int resetPos = bitPos;
53 #endif
54 
55  EnsureBufferSize(ref buf, bitPos + 1);
56 
57  int bytePos = bitPos / 8;
58  int bitOffset = bitPos % 8;
59  byte bitFlag = (byte)(1 << bitOffset);
60  byte bitMask = (byte)((~bitFlag) & 0xff);
61  buf[bytePos] &= bitMask;
62  if (val) buf[bytePos] |= bitFlag;
63  bitPos++;
64  UpdateBitLength(ref bitLength, bitPos);
65 #if DEBUG
66  bool testVal = MsgReader.ReadBoolean(buf, ref resetPos);
67  if (testVal != val || resetPos != bitPos)
68  {
69  DebugConsole.ThrowError($"Boolean written incorrectly! {testVal}, {val}; {resetPos}, {bitPos}");
70  }
71 #endif
72  }
73 
74  internal static void WritePadBits(ref byte[] buf, ref int bitPos, ref int bitLength)
75  {
76  int bitOffset = bitPos % 8;
77  bitPos += ((8 - bitOffset) % 8);
78  UpdateBitLength(ref bitLength, bitPos);
79  EnsureBufferSize(ref buf, bitPos);
80  }
81 
82  internal static void WriteByte(ref byte[] buf, ref int bitPos, ref int bitLength, byte val)
83  {
84  EnsureBufferSize(ref buf, bitPos + 8);
85  NetBitWriter.WriteByte(val, 8, buf, bitPos);
86  bitPos += 8;
87  UpdateBitLength(ref bitLength, bitPos);
88  }
89 
90  internal static void WriteUInt16(ref byte[] buf, ref int bitPos, ref int bitLength, UInt16 val)
91  {
92  EnsureBufferSize(ref buf, bitPos + 16);
93  NetBitWriter.WriteUInt16(val, 16, buf, bitPos);
94  bitPos += 16;
95  UpdateBitLength(ref bitLength, bitPos);
96  }
97 
98  internal static void WriteInt16(ref byte[] buf, ref int bitPos, ref int bitLength, Int16 val)
99  {
100  EnsureBufferSize(ref buf, bitPos + 16);
101  NetBitWriter.WriteUInt16((UInt16)val, 16, buf, bitPos);
102  bitPos += 16;
103  UpdateBitLength(ref bitLength, bitPos);
104  }
105 
106  internal static void WriteUInt32(ref byte[] buf, ref int bitPos, ref int bitLength, UInt32 val)
107  {
108  EnsureBufferSize(ref buf, bitPos + 32);
109  NetBitWriter.WriteUInt32(val, 32, buf, bitPos);
110  bitPos += 32;
111  UpdateBitLength(ref bitLength, bitPos);
112  }
113 
114  internal static void WriteInt32(ref byte[] buf, ref int bitPos, ref int bitLength, Int32 val)
115  {
116  EnsureBufferSize(ref buf, bitPos + 32);
117  NetBitWriter.WriteUInt32((UInt32)val, 32, buf, bitPos);
118  bitPos += 32;
119  UpdateBitLength(ref bitLength, bitPos);
120  }
121 
122  internal static void WriteUInt64(ref byte[] buf, ref int bitPos, ref int bitLength, UInt64 val)
123  {
124  EnsureBufferSize(ref buf, bitPos + 64);
125  NetBitWriter.WriteUInt64(val, 64, buf, bitPos);
126  bitPos += 64;
127  UpdateBitLength(ref bitLength, bitPos);
128  }
129 
130  internal static void WriteInt64(ref byte[] buf, ref int bitPos, ref int bitLength, Int64 val)
131  {
132  EnsureBufferSize(ref buf, bitPos + 64);
133  NetBitWriter.WriteUInt64((UInt64)val, 64, buf, bitPos);
134  bitPos += 64;
135  UpdateBitLength(ref bitLength, bitPos);
136  }
137 
138  internal static void WriteSingle(ref byte[] buf, ref int bitPos, ref int bitLength, Single val)
139  {
140  // Use union to avoid BitConverter.GetBytes() which allocates memory on the heap
141  SingleUIntUnion su;
142  su.UIntValue = 0; // must initialize every member of the union to avoid warning
143  su.SingleValue = val;
144 
145  EnsureBufferSize(ref buf, bitPos + 32);
146 
147  NetBitWriter.WriteUInt32(su.UIntValue, 32, buf, bitPos);
148  bitPos += 32;
149  UpdateBitLength(ref bitLength, bitPos);
150  }
151 
152  internal static void WriteDouble(ref byte[] buf, ref int bitPos, ref int bitLength, Double val)
153  {
154  EnsureBufferSize(ref buf, bitPos + 64);
155 
156  byte[] bytes = BitConverter.GetBytes(val);
157  WriteBytes(ref buf, ref bitPos, ref bitLength, bytes, 0, 8);
158  }
159 
160  internal static void WriteColorR8G8B8(ref byte[] buf, ref int bitPos, ref int bitLength, Color val)
161  {
162  EnsureBufferSize(ref buf, bitPos + 24);
163 
164  WriteByte(ref buf, ref bitPos, ref bitLength, val.R);
165  WriteByte(ref buf, ref bitPos, ref bitLength, val.G);
166  WriteByte(ref buf, ref bitPos, ref bitLength, val.B);
167  }
168 
169  internal static void WriteColorR8G8B8A8(ref byte[] buf, ref int bitPos, ref int bitLength, Color val)
170  {
171  EnsureBufferSize(ref buf, bitPos + 32);
172 
173  WriteByte(ref buf, ref bitPos, ref bitLength, val.R);
174  WriteByte(ref buf, ref bitPos, ref bitLength, val.G);
175  WriteByte(ref buf, ref bitPos, ref bitLength, val.B);
176  WriteByte(ref buf, ref bitPos, ref bitLength, val.A);
177  }
178 
179  internal static void WriteString(ref byte[] buf, ref int bitPos, ref int bitLength, string val)
180  {
181  if (string.IsNullOrEmpty(val))
182  {
183  WriteVariableUInt32(ref buf, ref bitPos, ref bitLength, 0u);
184  return;
185  }
186 
187  byte[] bytes = Encoding.UTF8.GetBytes(val);
188  WriteVariableUInt32(ref buf, ref bitPos, ref bitLength, (uint)bytes.Length);
189  WriteBytes(ref buf, ref bitPos, ref bitLength, bytes, 0, bytes.Length);
190  }
191 
192  internal static void WriteVariableUInt32(ref byte[] buf, ref int bitPos, ref int bitLength, uint value)
193  {
194  uint remainingValue = value;
195  while (remainingValue >= 0x80)
196  {
197  WriteByte(ref buf, ref bitPos, ref bitLength, (byte)(remainingValue | 0x80));
198  remainingValue >>= 7;
199  }
200 
201  WriteByte(ref buf, ref bitPos, ref bitLength, (byte)remainingValue);
202  }
203 
204  internal static void WriteRangedInteger(ref byte[] buf, ref int bitPos, ref int bitLength, int val, int min, int max)
205  {
206  uint range = (uint)(max - min);
207  int numberOfBits = NetUtility.BitsToHoldUInt(range);
208 
209  EnsureBufferSize(ref buf, bitPos + numberOfBits);
210 
211  uint rvalue = (uint)(val - min);
212  NetBitWriter.WriteUInt32(rvalue, numberOfBits, buf, bitPos);
213  bitPos += numberOfBits;
214  UpdateBitLength(ref bitLength, bitPos);
215  }
216 
217  internal static void WriteRangedSingle(ref byte[] buf, ref int bitPos, ref int bitLength, Single val, Single min, Single max, int numberOfBits)
218  {
219  float range = max - min;
220  float unit = ((val - min) / range);
221  int maxVal = (1 << numberOfBits) - 1;
222 
223  EnsureBufferSize(ref buf, bitPos + numberOfBits);
224 
225  NetBitWriter.WriteUInt32((UInt32)(maxVal * unit), numberOfBits, buf, bitPos);
226  bitPos += numberOfBits;
227  UpdateBitLength(ref bitLength, bitPos);
228  }
229 
230  internal static void WriteBytes(ref byte[] buf, ref int bitPos, ref int bitLength, byte[] val, int pos, int length)
231  {
232  EnsureBufferSize(ref buf, bitPos + length * 8);
233  NetBitWriter.WriteBytes(val, pos, length, buf, bitPos);
234  bitPos += length * 8;
235  UpdateBitLength(ref bitLength, bitPos);
236  }
237 
238  internal static void EnsureBufferSize(ref byte[] buf, int numberOfBits)
239  {
240  int byteLen = (numberOfBits + 7) / 8;
241  if (buf == null)
242  {
243  buf = new byte[byteLen + MsgConstants.BufferOverAllocateAmount];
244  return;
245  }
246 
247  if (buf.Length < byteLen)
248  {
249  Array.Resize(ref buf, byteLen + MsgConstants.BufferOverAllocateAmount);
250  }
251  }
252  }
253 
254  internal static class MsgReader
255  {
256  internal static bool ReadBoolean(byte[] buf, ref int bitPos)
257  {
258  byte retval = NetBitWriter.ReadByte(buf, 1, bitPos);
259  bitPos++;
260  return retval > 0;
261  }
262 
263  internal static void ReadPadBits(ref int bitPos)
264  {
265  int bitOffset = bitPos % 8;
266  bitPos += (8 - bitOffset) % 8;
267  }
268 
269  internal static byte ReadByte(byte[] buf, ref int bitPos)
270  {
271  byte retval = NetBitWriter.ReadByte(buf, 8, bitPos);
272  bitPos += 8;
273  return retval;
274  }
275 
276  internal static byte PeekByte(byte[] buf, ref int bitPos)
277  {
278  byte retval = NetBitWriter.ReadByte(buf, 8, bitPos);
279  return retval;
280  }
281 
282  internal static UInt16 ReadUInt16(byte[] buf, ref int bitPos)
283  {
284  uint retval = NetBitWriter.ReadUInt16(buf, 16, bitPos);
285  bitPos += 16;
286  return (ushort)retval;
287  }
288 
289  internal static Int16 ReadInt16(byte[] buf, ref int bitPos)
290  {
291  return (Int16)ReadUInt16(buf, ref bitPos);
292  }
293 
294  internal static UInt32 ReadUInt32(byte[] buf, ref int bitPos)
295  {
296  uint retval = NetBitWriter.ReadUInt32(buf, 32, bitPos);
297  bitPos += 32;
298  return retval;
299  }
300 
301  internal static Int32 ReadInt32(byte[] buf, ref int bitPos)
302  {
303  return (Int32)ReadUInt32(buf, ref bitPos);
304  }
305 
306  internal static UInt64 ReadUInt64(byte[] buf, ref int bitPos)
307  {
308  ulong low = NetBitWriter.ReadUInt32(buf, 32, bitPos);
309  bitPos += 32;
310  ulong high = NetBitWriter.ReadUInt32(buf, 32, bitPos);
311  ulong retval = low + (high << 32);
312  bitPos += 32;
313  return retval;
314  }
315 
316  internal static Int64 ReadInt64(byte[] buf, ref int bitPos)
317  {
318  return (Int64)ReadUInt64(buf, ref bitPos);
319  }
320 
321  internal static Single ReadSingle(byte[] buf, ref int bitPos)
322  {
323  if ((bitPos & 7) == 0) // read directly
324  {
325  float retval = BitConverter.ToSingle(buf, bitPos >> 3);
326  bitPos += 32;
327  return retval;
328  }
329 
330  byte[] bytes = ReadBytes(buf, ref bitPos, 4);
331  return BitConverter.ToSingle(bytes, 0);
332  }
333 
334  internal static Double ReadDouble(byte[] buf, ref int bitPos)
335  {
336  if ((bitPos & 7) == 0) // read directly
337  {
338  // read directly
339  double retval = BitConverter.ToDouble(buf, bitPos >> 3);
340  bitPos += 64;
341  return retval;
342  }
343 
344  byte[] bytes = ReadBytes(buf, ref bitPos, 8);
345  return BitConverter.ToDouble(bytes, 0);
346  }
347 
348  internal static Color ReadColorR8G8B8(byte[] buf, ref int bitPos)
349  {
350  byte r = ReadByte(buf, ref bitPos);
351  byte g = ReadByte(buf, ref bitPos);
352  byte b = ReadByte(buf, ref bitPos);
353  return new Color(r, g, b, (byte)255);
354  }
355 
356  internal static Color ReadColorR8G8B8A8(byte[] buf, ref int bitPos)
357  {
358  byte r = ReadByte(buf, ref bitPos);
359  byte g = ReadByte(buf, ref bitPos);
360  byte b = ReadByte(buf, ref bitPos);
361  byte a = ReadByte(buf, ref bitPos);
362  return new Color(r, g, b, a);
363  }
364 
365  internal static UInt32 ReadVariableUInt32(byte[] buf, ref int bitPos)
366  {
367  int bitLength = buf.Length * 8;
368 
369  int result = 0;
370  int shift = 0;
371  while (bitLength - bitPos >= 8)
372  {
373  byte chunk = ReadByte(buf, ref bitPos);
374  result |= (chunk & 0x7f) << shift;
375  shift += 7;
376  if ((chunk & 0x80) == 0) { return (uint)result; }
377  }
378 
379  // ouch; failed to find enough bytes; malformed variable length number?
380  return (uint)result;
381  }
382 
383  internal static String ReadString(byte[] buf, ref int bitPos)
384  {
385  int bitLength = buf.Length * 8;
386  int byteLen = (int)ReadVariableUInt32(buf, ref bitPos);
387 
388  if (byteLen <= 0) { return String.Empty; }
389 
390  if ((ulong)(bitLength - bitPos) < ((ulong)byteLen * 8))
391  {
392  // not enough data
393  return null;
394  }
395 
396  if ((bitPos & 7) == 0)
397  {
398  // read directly
399  string retval = Encoding.UTF8.GetString(buf, bitPos >> 3, byteLen);
400  bitPos += (8 * byteLen);
401  return retval;
402  }
403 
404  byte[] bytes = ReadBytes(buf, ref bitPos, byteLen);
405  return Encoding.UTF8.GetString(bytes, 0, bytes.Length);
406  }
407 
408  internal static int ReadRangedInteger(byte[] buf, ref int bitPos, int min, int max)
409  {
410  uint range = (uint)(max - min);
411  int numBits = NetUtility.BitsToHoldUInt(range);
412 
413  uint rvalue = NetBitWriter.ReadUInt32(buf, numBits, bitPos);
414  bitPos += numBits;
415 
416  return (int)(min + rvalue);
417  }
418 
419  internal static Single ReadRangedSingle(byte[] buf, ref int bitPos, Single min, Single max, int bitCount)
420  {
421  int maxInt = (1 << bitCount) - 1;
422  int intVal = ReadRangedInteger(buf, ref bitPos, 0, maxInt);
423  Single range = max - min;
424  return min + range * intVal / maxInt;
425  }
426 
427  internal static byte[] ReadBytes(byte[] buf, ref int bitPos, int numberOfBytes)
428  {
429  byte[] retval = new byte[numberOfBytes];
430  NetBitWriter.ReadBytes(buf, numberOfBytes, bitPos, retval, 0);
431  bitPos += 8 * numberOfBytes;
432  return retval;
433  }
434  }
435 
436  internal sealed class WriteOnlyMessage : IWriteMessage
437  {
438  private byte[] buf = new byte[MsgConstants.InitialBufferSize];
439  private int seekPos;
440  private int lengthBits;
441 
442  public int BitPosition
443  {
444  get => seekPos;
445  set => seekPos = value;
446  }
447 
448  public int BytePosition => seekPos / 8;
449 
450  public byte[] Buffer => buf;
451 
452  public int LengthBits
453  {
454  get
455  {
456  lengthBits = seekPos > lengthBits ? seekPos : lengthBits;
457  return lengthBits;
458  }
459  set
460  {
461  lengthBits = value;
462  seekPos = seekPos > lengthBits ? lengthBits : seekPos;
463  MsgWriter.EnsureBufferSize(ref buf, lengthBits);
464  }
465  }
466 
467  public int LengthBytes => (LengthBits + 7) / 8;
468 
469  public void WriteBoolean(bool val)
470  {
471  MsgWriter.WriteBoolean(ref buf, ref seekPos, ref lengthBits, val);
472  }
473 
474  public void WritePadBits()
475  {
476  MsgWriter.WritePadBits(ref buf, ref seekPos, ref lengthBits);
477  }
478 
479  public void WriteByte(byte val)
480  {
481  MsgWriter.WriteByte(ref buf, ref seekPos, ref lengthBits, val);
482  }
483 
484  public void WriteUInt16(UInt16 val)
485  {
486  MsgWriter.WriteUInt16(ref buf, ref seekPos, ref lengthBits, val);
487  }
488 
489  public void WriteInt16(Int16 val)
490  {
491  MsgWriter.WriteInt16(ref buf, ref seekPos, ref lengthBits, val);
492  }
493 
494  public void WriteUInt32(UInt32 val)
495  {
496  MsgWriter.WriteUInt32(ref buf, ref seekPos, ref lengthBits, val);
497  }
498 
499  public void WriteInt32(Int32 val)
500  {
501  MsgWriter.WriteInt32(ref buf, ref seekPos, ref lengthBits, val);
502  }
503 
504  public void WriteUInt64(UInt64 val)
505  {
506  MsgWriter.WriteUInt64(ref buf, ref seekPos, ref lengthBits, val);
507  }
508 
509  public void WriteInt64(Int64 val)
510  {
511  MsgWriter.WriteInt64(ref buf, ref seekPos, ref lengthBits, val);
512  }
513 
514  public void WriteSingle(Single val)
515  {
516  MsgWriter.WriteSingle(ref buf, ref seekPos, ref lengthBits, val);
517  }
518 
519  public void WriteDouble(Double val)
520  {
521  MsgWriter.WriteDouble(ref buf, ref seekPos, ref lengthBits, val);
522  }
523 
524  public void WriteColorR8G8B8(Color val)
525  {
526  MsgWriter.WriteColorR8G8B8(ref buf, ref seekPos, ref lengthBits, val);
527  }
528 
529  public void WriteColorR8G8B8A8(Color val)
530  {
531  MsgWriter.WriteColorR8G8B8A8(ref buf, ref seekPos, ref lengthBits, val);
532  }
533 
534  public void WriteVariableUInt32(UInt32 val)
535  {
536  MsgWriter.WriteVariableUInt32(ref buf, ref seekPos, ref lengthBits, val);
537  }
538 
539  public void WriteString(String val)
540  {
541  MsgWriter.WriteString(ref buf, ref seekPos, ref lengthBits, val);
542  }
543 
544  public void WriteIdentifier(Identifier val)
545  {
546  WriteString(val.Value);
547  }
548 
549  public void WriteRangedInteger(int val, int min, int max)
550  {
551  MsgWriter.WriteRangedInteger(ref buf, ref seekPos, ref lengthBits, val, min, max);
552  }
553 
554  public void WriteRangedSingle(Single val, Single min, Single max, int bitCount)
555  {
556  MsgWriter.WriteRangedSingle(ref buf, ref seekPos, ref lengthBits, val, min, max, bitCount);
557  }
558 
559  public void WriteBytes(byte[] val, int startPos, int length)
560  {
561  MsgWriter.WriteBytes(ref buf, ref seekPos, ref lengthBits, val, startPos, length);
562  }
563 
564  public byte[] PrepareForSending(bool compressPastThreshold, out bool isCompressed, out int length)
565  {
566  byte[] outBuf;
567  if (LengthBytes <= MsgConstants.CompressionThreshold || !compressPastThreshold)
568  {
569  isCompressed = false;
570  outBuf = new byte[LengthBytes];
571  Array.Copy(buf, outBuf, LengthBytes);
572  length = LengthBytes;
573  }
574  else
575  {
576  using MemoryStream output = new MemoryStream();
577 
578  using (DeflateStream dstream = new DeflateStream(output, CompressionLevel.Fastest))
579  {
580  dstream.Write(buf, 0, LengthBytes);
581  }
582 
583  byte[] compressedBuf = output.ToArray();
584  //don't send the data as compressed if the data takes up more space after compression
585  //(which may happen when sending a sub/save file that's already been compressed with a better compression ratio)
586  if (compressedBuf.Length >= LengthBytes)
587  {
588  isCompressed = false;
589  outBuf = new byte[LengthBytes];
590  Array.Copy(buf, outBuf, LengthBytes);
591  length = LengthBytes;
592  }
593  else
594  {
595  isCompressed = true;
596  outBuf = compressedBuf;
597  length = outBuf.Length;
598  DebugConsole.Log($"Compressed message: {LengthBytes} to {length}");
599  }
600  }
601 
602  return outBuf;
603  }
604  }
605 
606  internal sealed class ReadOnlyMessage : IReadMessage
607  {
608  private int seekPos;
609  private int lengthBits;
610 
611  public int BitPosition
612  {
613  get => seekPos;
614  set => seekPos = value;
615  }
616 
617  public int BytePosition => seekPos / 8;
618 
619  public byte[] Buffer { get; }
620 
621  public int LengthBits
622  {
623  get
624  {
625  lengthBits = seekPos > lengthBits ? seekPos : lengthBits;
626  return lengthBits;
627  }
628  set
629  {
630  lengthBits = value;
631  seekPos = seekPos > lengthBits ? lengthBits : seekPos;
632  }
633  }
634 
635  public int LengthBytes => (LengthBits + 7) / 8;
636 
637  public NetworkConnection Sender { get; }
638 
639  public ReadOnlyMessage(byte[] inBuf, bool isCompressed, int startPos, int byteLength, NetworkConnection sender)
640  {
641  Sender = sender;
642  if (isCompressed)
643  {
644  byte[] decompressedData;
645  using (MemoryStream input = new MemoryStream(inBuf, startPos, byteLength))
646  {
647  using (MemoryStream output = new MemoryStream())
648  {
649  using (DeflateStream dstream = new DeflateStream(input, CompressionMode.Decompress))
650  {
651  dstream.CopyTo(output);
652  }
653 
654  decompressedData = output.ToArray();
655  }
656  }
657 
658  Buffer = new byte[decompressedData.Length];
659  try
660  {
661  Array.Copy(decompressedData, 0, Buffer, 0, decompressedData.Length);
662  }
663  catch (ArgumentException e)
664  {
665  throw new ArgumentException(
666  $"Failed to copy the incoming compressed buffer. Source buffer length: {decompressedData.Length}, start position: {0}, length: {decompressedData.Length}, destination buffer length: {Buffer.Length}.", e);
667  }
668 
669  lengthBits = decompressedData.Length * 8;
670  DebugConsole.Log("Decompressing message: " + byteLength + " to " + LengthBytes);
671  }
672  else
673  {
674  Buffer = new byte[inBuf.Length];
675  try
676  {
677  Array.Copy(inBuf, startPos, Buffer, 0, byteLength);
678  }
679  catch (ArgumentException e)
680  {
681  throw new ArgumentException($"Failed to copy the incoming uncompressed buffer. Source buffer length: {inBuf.Length}, start position: {startPos}, length: {byteLength}, destination buffer length: {Buffer.Length}.", e);
682  }
683 
684  lengthBits = byteLength * 8;
685  }
686 
687  seekPos = 0;
688  }
689 
690  public bool ReadBoolean()
691  {
692  return MsgReader.ReadBoolean(Buffer, ref seekPos);
693  }
694 
695  public void ReadPadBits() { MsgReader.ReadPadBits(ref seekPos); }
696 
697  public byte ReadByte()
698  {
699  return MsgReader.ReadByte(Buffer, ref seekPos);
700  }
701 
702  public byte PeekByte()
703  {
704  return MsgReader.PeekByte(Buffer, ref seekPos);
705  }
706 
707  public UInt16 ReadUInt16()
708  {
709  return MsgReader.ReadUInt16(Buffer, ref seekPos);
710  }
711 
712  public Int16 ReadInt16()
713  {
714  return MsgReader.ReadInt16(Buffer, ref seekPos);
715  }
716 
717  public UInt32 ReadUInt32()
718  {
719  return MsgReader.ReadUInt32(Buffer, ref seekPos);
720  }
721 
722  public Int32 ReadInt32()
723  {
724  return MsgReader.ReadInt32(Buffer, ref seekPos);
725  }
726 
727  public UInt64 ReadUInt64()
728  {
729  return MsgReader.ReadUInt64(Buffer, ref seekPos);
730  }
731 
732  public Int64 ReadInt64()
733  {
734  return MsgReader.ReadInt64(Buffer, ref seekPos);
735  }
736 
737  public Single ReadSingle()
738  {
739  return MsgReader.ReadSingle(Buffer, ref seekPos);
740  }
741 
742  public Double ReadDouble()
743  {
744  return MsgReader.ReadDouble(Buffer, ref seekPos);
745  }
746 
747  public UInt32 ReadVariableUInt32()
748  {
749  return MsgReader.ReadVariableUInt32(Buffer, ref seekPos);
750  }
751 
752  public String ReadString()
753  {
754  return MsgReader.ReadString(Buffer, ref seekPos);
755  }
756 
757  public Identifier ReadIdentifier()
758  {
759  return ReadString().ToIdentifier();
760  }
761 
762  public Color ReadColorR8G8B8()
763  {
764  return MsgReader.ReadColorR8G8B8(Buffer, ref seekPos);
765  }
766 
767  public Color ReadColorR8G8B8A8()
768  {
769  return MsgReader.ReadColorR8G8B8A8(Buffer, ref seekPos);
770  }
771 
772  public int ReadRangedInteger(int min, int max)
773  {
774  return MsgReader.ReadRangedInteger(Buffer, ref seekPos, min, max);
775  }
776 
777  public Single ReadRangedSingle(Single min, Single max, int bitCount)
778  {
779  return MsgReader.ReadRangedSingle(Buffer, ref seekPos, min, max, bitCount);
780  }
781 
782  public byte[] ReadBytes(int numberOfBytes)
783  {
784  return MsgReader.ReadBytes(Buffer, ref seekPos, numberOfBytes);
785  }
786  }
787 
788  internal sealed class ReadWriteMessage : IWriteMessage, IReadMessage
789  {
790  private byte[] buf;
791  private int seekPos;
792  private int lengthBits;
793 
794  public ReadWriteMessage()
795  {
796  buf = new byte[MsgConstants.InitialBufferSize];
797  seekPos = 0;
798  lengthBits = 0;
799  }
800 
801  public ReadWriteMessage(byte[] b, int bitPos, int lBits, bool copyBuf)
802  {
803  buf = copyBuf ? (byte[])b.Clone() : b;
804  seekPos = bitPos;
805  lengthBits = lBits;
806  }
807 
808  public int BitPosition
809  {
810  get => seekPos;
811  set => seekPos = value;
812  }
813 
814  public int BytePosition => seekPos / 8;
815 
816  public byte[] Buffer => buf;
817 
818  public int LengthBits
819  {
820  get
821  {
822  lengthBits = seekPos > lengthBits ? seekPos : lengthBits;
823  return lengthBits;
824  }
825  set
826  {
827  lengthBits = value;
828  seekPos = seekPos > lengthBits ? lengthBits : seekPos;
829  }
830  }
831 
832  public int LengthBytes => (LengthBits + 7) / 8;
833 
834  public NetworkConnection Sender => null;
835 
836  public void WriteBoolean(bool val)
837  {
838  MsgWriter.WriteBoolean(ref buf, ref seekPos, ref lengthBits, val);
839  }
840 
841  public void WritePadBits()
842  {
843  MsgWriter.WritePadBits(ref buf, ref seekPos, ref lengthBits);
844  }
845 
846  public void WriteByte(byte val)
847  {
848  MsgWriter.WriteByte(ref buf, ref seekPos, ref lengthBits, val);
849  }
850 
851  public void WriteUInt16(UInt16 val)
852  {
853  MsgWriter.WriteUInt16(ref buf, ref seekPos, ref lengthBits, val);
854  }
855 
856  public void WriteInt16(Int16 val)
857  {
858  MsgWriter.WriteInt16(ref buf, ref seekPos, ref lengthBits, val);
859  }
860 
861  public void WriteUInt32(UInt32 val)
862  {
863  MsgWriter.WriteUInt32(ref buf, ref seekPos, ref lengthBits, val);
864  }
865 
866  public void WriteInt32(Int32 val)
867  {
868  MsgWriter.WriteInt32(ref buf, ref seekPos, ref lengthBits, val);
869  }
870 
871  public void WriteUInt64(UInt64 val)
872  {
873  MsgWriter.WriteUInt64(ref buf, ref seekPos, ref lengthBits, val);
874  }
875 
876  public void WriteInt64(Int64 val)
877  {
878  MsgWriter.WriteInt64(ref buf, ref seekPos, ref lengthBits, val);
879  }
880 
881  public void WriteSingle(Single val)
882  {
883  MsgWriter.WriteSingle(ref buf, ref seekPos, ref lengthBits, val);
884  }
885 
886  public void WriteDouble(Double val)
887  {
888  MsgWriter.WriteDouble(ref buf, ref seekPos, ref lengthBits, val);
889  }
890 
891  public void WriteColorR8G8B8(Color val)
892  {
893  MsgWriter.WriteColorR8G8B8(ref buf, ref seekPos, ref lengthBits, val);
894  }
895 
896  public void WriteColorR8G8B8A8(Color val)
897  {
898  MsgWriter.WriteColorR8G8B8A8(ref buf, ref seekPos, ref lengthBits, val);
899  }
900 
901  public void WriteVariableUInt32(UInt32 val)
902  {
903  MsgWriter.WriteVariableUInt32(ref buf, ref seekPos, ref lengthBits, val);
904  }
905 
906  public void WriteString(String val)
907  {
908  MsgWriter.WriteString(ref buf, ref seekPos, ref lengthBits, val);
909  }
910 
911  public void WriteIdentifier(Identifier val)
912  {
913  WriteString(val.Value);
914  }
915 
916  public void WriteRangedInteger(int val, int min, int max)
917  {
918  MsgWriter.WriteRangedInteger(ref buf, ref seekPos, ref lengthBits, val, min, max);
919  }
920 
921  public void WriteRangedSingle(Single val, Single min, Single max, int bitCount)
922  {
923  MsgWriter.WriteRangedSingle(ref buf, ref seekPos, ref lengthBits, val, min, max, bitCount);
924  }
925 
926  public void WriteBytes(byte[] val, int startPos, int length)
927  {
928  MsgWriter.WriteBytes(ref buf, ref seekPos, ref lengthBits, val, startPos, length);
929  }
930 
931  public bool ReadBoolean()
932  {
933  return MsgReader.ReadBoolean(buf, ref seekPos);
934  }
935 
936  public void ReadPadBits() { MsgReader.ReadPadBits(ref seekPos); }
937 
938  public byte ReadByte()
939  {
940  return MsgReader.ReadByte(buf, ref seekPos);
941  }
942 
943  public byte PeekByte()
944  {
945  return MsgReader.PeekByte(buf, ref seekPos);
946  }
947 
948  public UInt16 ReadUInt16()
949  {
950  return MsgReader.ReadUInt16(buf, ref seekPos);
951  }
952 
953  public Int16 ReadInt16()
954  {
955  return MsgReader.ReadInt16(buf, ref seekPos);
956  }
957 
958  public UInt32 ReadUInt32()
959  {
960  return MsgReader.ReadUInt32(buf, ref seekPos);
961  }
962 
963  public Int32 ReadInt32()
964  {
965  return MsgReader.ReadInt32(buf, ref seekPos);
966  }
967 
968  public UInt64 ReadUInt64()
969  {
970  return MsgReader.ReadUInt64(buf, ref seekPos);
971  }
972 
973  public Int64 ReadInt64()
974  {
975  return MsgReader.ReadInt64(buf, ref seekPos);
976  }
977 
978  public Single ReadSingle()
979  {
980  return MsgReader.ReadSingle(buf, ref seekPos);
981  }
982 
983  public Double ReadDouble()
984  {
985  return MsgReader.ReadDouble(buf, ref seekPos);
986  }
987 
988  public UInt32 ReadVariableUInt32()
989  {
990  return MsgReader.ReadVariableUInt32(buf, ref seekPos);
991  }
992 
993  public String ReadString()
994  {
995  return MsgReader.ReadString(buf, ref seekPos);
996  }
997 
998  public Identifier ReadIdentifier()
999  {
1000  return ReadString().ToIdentifier();
1001  }
1002 
1003  public Color ReadColorR8G8B8()
1004  {
1005  return MsgReader.ReadColorR8G8B8(buf, ref seekPos);
1006  }
1007 
1008  public Color ReadColorR8G8B8A8()
1009  {
1010  return MsgReader.ReadColorR8G8B8A8(buf, ref seekPos);
1011  }
1012 
1013  public int ReadRangedInteger(int min, int max)
1014  {
1015  return MsgReader.ReadRangedInteger(buf, ref seekPos, min, max);
1016  }
1017 
1018  public Single ReadRangedSingle(Single min, Single max, int bitCount)
1019  {
1020  return MsgReader.ReadRangedSingle(buf, ref seekPos, min, max, bitCount);
1021  }
1022 
1023  public byte[] ReadBytes(int numberOfBytes)
1024  {
1025  return MsgReader.ReadBytes(buf, ref seekPos, numberOfBytes);
1026  }
1027 
1028  public byte[] PrepareForSending(bool compressPastThreshold, out bool isCompressed, out int outLength)
1029  {
1030  throw new InvalidOperationException("ReadWriteMessages are not to be sent");
1031  }
1032 
1033  }
1034 }
void WriteColorR8G8B8A8(Microsoft.Xna.Framework.Color val)
void WriteColorR8G8B8(Microsoft.Xna.Framework.Color val)
Utility struct for writing Singles
Definition: Message.cs:28
uint UIntValue
Value as an unsigned 32 bit integer
Definition: Message.cs:39
float SingleValue
Value as a 32 bit float
Definition: Message.cs:33