aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchai <215380520@qq.com>2023-10-12 22:10:06 +0800
committerchai <215380520@qq.com>2023-10-12 22:10:06 +0800
commitb33272a12c3204931ad3426c600786a4cac3fb58 (patch)
treee57e3dac9803f8464190c872ec4b8e6939f1adf2
parent8d2a2cd5de40e2b94ef5007c32832ed9a063dc40 (diff)
* messagereader
-rw-r--r--Documents/~$资料.xlsxbin0 -> 165 bytes
-rw-r--r--Documents/资料.xlsxbin1187005 -> 1436203 bytes
-rw-r--r--MultiplayerToolkit/Assets/MultiplayerToolkit/IRecyclable.cs29
-rw-r--r--MultiplayerToolkit/Assets/MultiplayerToolkit/IRecyclable.cs.meta11
-rw-r--r--MultiplayerToolkit/Assets/MultiplayerToolkit/MessageReader.cs456
-rw-r--r--MultiplayerToolkit/Assets/MultiplayerToolkit/MessageReader.cs.meta11
-rw-r--r--MultiplayerToolkit/Assets/MultiplayerToolkit/MessageWriter.cs307
-rw-r--r--MultiplayerToolkit/Assets/MultiplayerToolkit/MessageWriter.cs.meta11
-rw-r--r--MultiplayerToolkit/Assets/MultiplayerToolkit/ObjectPool.cs108
-rw-r--r--MultiplayerToolkit/Assets/MultiplayerToolkit/ObjectPool.cs.meta11
-rw-r--r--MultiplayerToolkit/Assets/MultiplayerToolkit/Packet.cs6
-rw-r--r--MultiplayerToolkit/Assets/MultiplayerToolkit/Test/TestTcp/Test_TcpClient.cs14
-rw-r--r--MultiplayerToolkit/Assets/MultiplayerToolkit/Test/TestTcp/Test_TcpServer.cs26
-rw-r--r--MultiplayerToolkit/ProjectSettings/ProjectSettings.asset32
14 files changed, 987 insertions, 35 deletions
diff --git a/Documents/~$资料.xlsx b/Documents/~$资料.xlsx
new file mode 100644
index 0000000..1e0c8b3
--- /dev/null
+++ b/Documents/~$资料.xlsx
Binary files differ
diff --git a/Documents/资料.xlsx b/Documents/资料.xlsx
index 0cec306..224fc20 100644
--- a/Documents/资料.xlsx
+++ b/Documents/资料.xlsx
Binary files differ
diff --git a/MultiplayerToolkit/Assets/MultiplayerToolkit/IRecyclable.cs b/MultiplayerToolkit/Assets/MultiplayerToolkit/IRecyclable.cs
new file mode 100644
index 0000000..17d3104
--- /dev/null
+++ b/MultiplayerToolkit/Assets/MultiplayerToolkit/IRecyclable.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MultiplayerToolkit
+{
+ /// <summary>
+ /// Interface for all items that can be returned to an object pool.
+ /// </summary>
+ /// <threadsafety static="true" instance="true"/>
+ public interface IRecyclable
+ {
+ /// <summary>
+ /// Returns this object back to the object pool.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Calling this when you are done with the object returns the object back to a pool in order to be reused.
+ /// This can reduce the amount of work the GC has to do dramatically but it is optional to call this.
+ /// </para>
+ /// <para>
+ /// Calling this indicates to Hazel that this can be reused and thus you should only call this when you are
+ /// completely finished with the object as the contents can be overwritten at any point after.
+ /// </para>
+ /// </remarks>
+ void Recycle();
+ }
+}
diff --git a/MultiplayerToolkit/Assets/MultiplayerToolkit/IRecyclable.cs.meta b/MultiplayerToolkit/Assets/MultiplayerToolkit/IRecyclable.cs.meta
new file mode 100644
index 0000000..396ffcd
--- /dev/null
+++ b/MultiplayerToolkit/Assets/MultiplayerToolkit/IRecyclable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b07026b6854d9e749ad6375ae957f557
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/MultiplayerToolkit/Assets/MultiplayerToolkit/MessageReader.cs b/MultiplayerToolkit/Assets/MultiplayerToolkit/MessageReader.cs
new file mode 100644
index 0000000..3bd5db8
--- /dev/null
+++ b/MultiplayerToolkit/Assets/MultiplayerToolkit/MessageReader.cs
@@ -0,0 +1,456 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace MultiplayerToolkit
+{
+ public class MessageReader : IRecyclable
+ {
+ public static readonly ObjectPool<MessageReader> ReaderPool = new ObjectPool<MessageReader>(() => new MessageReader());
+
+ public byte[] Buffer;
+ public byte Tag;
+
+ public int Length;
+
+ public int BytesRemaining => this.Length - this.Position;
+
+ private MessageReader Parent;
+
+ public int Position
+ {
+ get { return this._position; }
+ set
+ {
+ this._position = value;
+ this.readHead = value ;
+ }
+ }
+
+ private int _position;
+ private int readHead;
+
+ public static MessageReader GetSized(int minSize)
+ {
+ var output = ReaderPool.GetObject();
+
+ if (output.Buffer == null || output.Buffer.Length < minSize)
+ {
+ output.Buffer = new byte[minSize];
+ }
+ else
+ {
+ Array.Clear(output.Buffer, 0, output.Buffer.Length);
+ }
+
+ output.Offset = 0;
+ output.Position = 0;
+ output.Tag = byte.MaxValue;
+ return output;
+ }
+
+ public static MessageReader Get(byte[] buffer)
+ {
+ var output = ReaderPool.GetObject();
+
+ output.Buffer = buffer;
+ output.Offset = 0;
+ output.Position = 0;
+ output.Length = buffer.Length;
+ output.Tag = byte.MaxValue;
+
+ return output;
+ }
+
+ public static MessageReader CopyMessageIntoParent(MessageReader source)
+ {
+ var output = MessageReader.GetSized(source.Length + 3);
+ System.Buffer.BlockCopy(source.Buffer, source.Offset - 3, output.Buffer, 0, source.Length + 3);
+
+ output.Offset = 0;
+ output.Position = 0;
+ output.Length = source.Length + 3;
+
+ return output;
+ }
+
+ /// <summary>
+ /// 复制一份
+ /// </summary>
+ /// <param name="source"></param>
+ /// <returns></returns>
+ public static MessageReader Get(MessageReader source)
+ {
+ var output = MessageReader.GetSized(source.Buffer.Length);
+ System.Buffer.BlockCopy(source.Buffer, 0, output.Buffer, 0, source.Buffer.Length);
+
+ output.Offset = source.Offset;
+
+ output._position = source._position;
+ output.readHead = source.readHead;
+
+ output.Length = source.Length;
+ output.Tag = source.Tag;
+
+ return output;
+ }
+
+ public static MessageReader Get(byte[] buffer, int offset)
+ {
+ // Ensure there is at least a header
+ if (offset + 3 > buffer.Length) return null;
+
+ var output = ReaderPool.GetObject();
+
+ output.Buffer = buffer;
+ output.Offset = offset;
+ output.Position = 0;
+
+ output.Length = output.ReadUInt16();
+ output.Tag = output.ReadByte();
+
+ output.Offset += 3;
+ output.Position = 0;
+
+ return output;
+ }
+
+ /// <summary>
+ /// Produces a MessageReader using the parent's buffer. This MessageReader should **NOT** be recycled.
+ /// </summary>
+ public MessageReader ReadMessage()
+ {
+ // Ensure there is at least a header
+ if (this.BytesRemaining < 3) throw new InvalidDataException($"ReadMessage header is longer than message length: 3 of {this.BytesRemaining}");
+
+ var output = new MessageReader();
+
+ output.Parent = this;
+ output.Buffer = this.Buffer;
+ output.Offset = this.readHead;
+ output.Position = 0;
+
+ output.Length = output.ReadUInt16();
+ output.Tag = output.ReadByte();
+
+ output.Offset += 3;
+ output.Position = 0;
+
+ if (this.BytesRemaining < output.Length + 3) throw new InvalidDataException($"Message Length at Position {this.readHead} is longer than message length: {output.Length + 3} of {this.BytesRemaining}");
+
+ this.Position += output.Length + 3;
+ return output;
+ }
+
+ /// <summary>
+ /// Produces a MessageReader with a new buffer. This MessageReader should be recycled.
+ /// </summary>
+ public MessageReader ReadMessageAsNewBuffer()
+ {
+ if (this.BytesRemaining < 3) throw new InvalidDataException($"ReadMessage header is longer than message length: 3 of {this.BytesRemaining}");
+
+ var len = this.ReadUInt16();
+ var tag = this.ReadByte();
+
+ if (this.BytesRemaining < len) throw new InvalidDataException($"Message Length at Position {this.readHead} is longer than message length: {len} of {this.BytesRemaining}");
+
+ var output = MessageReader.GetSized(len);
+
+ Array.Copy(this.Buffer, this.readHead, output.Buffer, 0, len);
+
+ output.Length = len;
+ output.Tag = tag;
+
+ this.Position += output.Length;
+ return output;
+ }
+
+ public MessageWriter StartWriter()
+ {
+ var output = new MessageWriter(this.Buffer);
+ output.Position = this.readHead;
+ return output;
+ }
+
+ public MessageReader Duplicate()
+ {
+ var output = GetSized(this.Length);
+ Array.Copy(this.Buffer, this.Offset, output.Buffer, 0, this.Length);
+ output.Length = this.Length;
+ output.Offset = 0;
+ output.Position = 0;
+
+ return output;
+ }
+
+ public void RemoveMessage(MessageReader reader)
+ {
+ var temp = MessageReader.GetSized(reader.Buffer.Length);
+ try
+ {
+ var headerOffset = reader.Offset - 3;
+ var endOfMessage = reader.Offset + reader.Length;
+ var len = reader.Buffer.Length - endOfMessage;
+
+ Array.Copy(reader.Buffer, endOfMessage, temp.Buffer, 0, len);
+ Array.Copy(temp.Buffer, 0, this.Buffer, headerOffset, len);
+
+ this.AdjustLength(reader.Offset, reader.Length + 3);
+ }
+ finally
+ {
+ temp.Recycle();
+ }
+ }
+
+ public void InsertMessage(MessageReader reader, MessageWriter writer)
+ {
+ var temp = MessageReader.GetSized(reader.Buffer.Length);
+ try
+ {
+ var headerOffset = reader.Offset - 3;
+ var startOfMessage = reader.Offset;
+ var len = reader.Buffer.Length - startOfMessage;
+ int writerOffset = 0;
+ //switch (writer.SendOption)
+ //{
+ // case SendOption.Reliable:
+ // writerOffset = 3;
+ // break;
+ // case SendOption.None:
+ // writerOffset = 1;
+ // break;
+ //}
+
+ //store the original buffer in temp
+ Array.Copy(reader.Buffer, headerOffset, temp.Buffer, 0, len);
+
+ //put the contents of writer in at headerOffset
+ Array.Copy(writer.Buffer, writerOffset, this.Buffer, headerOffset, writer.Length-writerOffset);
+
+ //put the original buffer in after that
+ Array.Copy(temp.Buffer, 0, this.Buffer, headerOffset + (writer.Length-writerOffset), len - writer.Length);
+
+ this.AdjustLength(-1 * reader.Offset , -1 * (writer.Length - writerOffset));
+ }
+ finally
+ {
+ temp.Recycle();
+ }
+ }
+
+ private void AdjustLength(int offset, int amount)
+ {
+ if (this.readHead > offset)
+ {
+ this.Position -= amount;
+ }
+
+ if (Parent != null)
+ {
+ var lengthOffset = this.Offset - 3;
+ var curLen = this.Buffer[lengthOffset]
+ | (this.Buffer[lengthOffset + 1] << 8);
+
+ curLen -= amount;
+ this.Length -= amount;
+
+ this.Buffer[lengthOffset] = (byte)curLen;
+ this.Buffer[lengthOffset + 1] = (byte)(this.Buffer[lengthOffset + 1] >> 8);
+
+ Parent.AdjustLength(offset, amount);
+ }
+ }
+
+ public void Recycle()
+ {
+ this.Parent = null;
+ ReaderPool.PutObject(this);
+ }
+
+ #region Read Methods
+ public bool ReadBoolean()
+ {
+ byte val = this.FastByte();
+ return val != 0;
+ }
+
+ public sbyte ReadSByte()
+ {
+ return (sbyte)this.FastByte();
+ }
+
+ public byte ReadByte()
+ {
+ return this.FastByte();
+ }
+
+ public ushort ReadUInt16()
+ {
+ ushort output =
+ (ushort)(this.FastByte()
+ | this.FastByte() << 8);
+ return output;
+ }
+
+ public short ReadInt16()
+ {
+ short output =
+ (short)(this.FastByte()
+ | this.FastByte() << 8);
+ return output;
+ }
+
+ public uint ReadUInt32()
+ {
+ uint output = this.FastByte()
+ | (uint)this.FastByte() << 8
+ | (uint)this.FastByte() << 16
+ | (uint)this.FastByte() << 24;
+
+ return output;
+ }
+
+ public int ReadInt32()
+ {
+ int output = this.FastByte()
+ | this.FastByte() << 8
+ | this.FastByte() << 16
+ | this.FastByte() << 24;
+
+ return output;
+ }
+
+ public ulong ReadUInt64()
+ {
+ ulong output = (ulong)this.FastByte()
+ | (ulong)this.FastByte() << 8
+ | (ulong)this.FastByte() << 16
+ | (ulong)this.FastByte() << 24
+ | (ulong)this.FastByte() << 32
+ | (ulong)this.FastByte() << 40
+ | (ulong)this.FastByte() << 48
+ | (ulong)this.FastByte() << 56;
+
+ return output;
+ }
+
+ public long ReadInt64()
+ {
+ long output = (long)this.FastByte()
+ | (long)this.FastByte() << 8
+ | (long)this.FastByte() << 16
+ | (long)this.FastByte() << 24
+ | (long)this.FastByte() << 32
+ | (long)this.FastByte() << 40
+ | (long)this.FastByte() << 48
+ | (long)this.FastByte() << 56;
+
+ return output;
+ }
+
+ public unsafe float ReadSingle()
+ {
+ float output = 0;
+ fixed (byte* bufPtr = &this.Buffer[this.readHead])
+ {
+ byte* outPtr = (byte*)&output;
+
+ *outPtr = *bufPtr;
+ *(outPtr + 1) = *(bufPtr + 1);
+ *(outPtr + 2) = *(bufPtr + 2);
+ *(outPtr + 3) = *(bufPtr + 3);
+ }
+
+ this.Position += 4;
+ return output;
+ }
+
+ public string ReadString()
+ {
+ int len = this.ReadPackedInt32();
+ if (this.BytesRemaining < len) throw new InvalidDataException($"Read length is longer than message length: {len} of {this.BytesRemaining}");
+
+ string output = UTF8Encoding.UTF8.GetString(this.Buffer, this.readHead, len);
+
+ this.Position += len;
+ return output;
+ }
+
+ public byte[] ReadBytesAndSize()
+ {
+ int len = this.ReadPackedInt32();
+ if (this.BytesRemaining < len) throw new InvalidDataException($"Read length is longer than message length: {len} of {this.BytesRemaining}");
+
+ return this.ReadBytes(len);
+ }
+
+ public byte[] ReadBytes(int length)
+ {
+ if (this.BytesRemaining < length) throw new InvalidDataException($"Read length is longer than message length: {length} of {this.BytesRemaining}");
+
+ byte[] output = new byte[length];
+ Array.Copy(this.Buffer, this.readHead, output, 0, output.Length);
+ this.Position += output.Length;
+ return output;
+ }
+
+ ///
+ public int ReadPackedInt32()
+ {
+ return (int)this.ReadPackedUInt32();
+ }
+
+ ///
+ public uint ReadPackedUInt32()
+ {
+ bool readMore = true;
+ int shift = 0;
+ uint output = 0;
+
+ while (readMore)
+ {
+ if (this.BytesRemaining < 1) throw new InvalidDataException($"Read length is longer than message length.");
+
+ byte b = this.ReadByte();
+ if (b >= 0x80)
+ {
+ readMore = true;
+ b ^= 0x80;
+ }
+ else
+ {
+ readMore = false;
+ }
+
+ output |= (uint)(b << shift);
+ shift += 7;
+ }
+
+ return output;
+ }
+ #endregion
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private byte FastByte()
+ {
+ this._position++;
+ return this.Buffer[this.readHead++];
+ }
+
+ public unsafe static bool IsLittleEndian()
+ {
+ byte b;
+ unsafe
+ {
+ int i = 1;
+ byte* bp = (byte*)&i;
+ b = *bp;
+ }
+
+ return b == 1;
+ }
+ }
+}
diff --git a/MultiplayerToolkit/Assets/MultiplayerToolkit/MessageReader.cs.meta b/MultiplayerToolkit/Assets/MultiplayerToolkit/MessageReader.cs.meta
new file mode 100644
index 0000000..2f470c6
--- /dev/null
+++ b/MultiplayerToolkit/Assets/MultiplayerToolkit/MessageReader.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 35714cf36eee0fc458f427f0a6cea532
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/MultiplayerToolkit/Assets/MultiplayerToolkit/MessageWriter.cs b/MultiplayerToolkit/Assets/MultiplayerToolkit/MessageWriter.cs
new file mode 100644
index 0000000..226a2d4
--- /dev/null
+++ b/MultiplayerToolkit/Assets/MultiplayerToolkit/MessageWriter.cs
@@ -0,0 +1,307 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace MultiplayerToolkit
+{
+
+ /// <summary>
+ /// AmongUsùȥ˰ͷش
+ /// ṹ
+ /// -------------------------------------
+ /// 2bytes(ushort) Эij
+ /// Э
+ /// -------------------------------------
+ /// </summary>
+ public class MessageWriter : IRecyclable
+ {
+ public static int BufferSize = 64000;
+ public static readonly ObjectPool<MessageWriter> WriterPool = new ObjectPool<MessageWriter>(() => new MessageWriter(BufferSize));
+
+ public byte[] Buffer;
+ public int Length; // Эܳ
+ public int Position; // дλ
+
+ private Stack<int> messageStarts = new Stack<int>(); // ¼ЭbufferеʼλãǶ׽ṹ
+
+ public MessageWriter(byte[] buffer)
+ {
+ this.Buffer = buffer;
+ this.Length = this.Buffer.Length;
+ }
+
+ ///
+ public MessageWriter(int bufferSize)
+ {
+ this.Buffer = new byte[bufferSize];
+ }
+
+ public byte[] ToByteArray()
+ {
+ byte[] output = new byte[this.Length];
+ System.Buffer.BlockCopy(this.Buffer, 0, output, 0, this.Length);
+ return output;
+ }
+
+ /// <param name="sendOption">The option specifying how the message should be sent.</param>
+ public static MessageWriter Get()
+ {
+ MessageWriter output = WriterPool.GetObject();
+ output.Clear();
+
+ return output;
+ }
+
+ public bool HasBytes(int expected)
+ {
+ return this.Length >= 3 + expected;
+ }
+
+ ///
+ public void StartMessage(/*byte typeFlag*/)
+ {
+ var messageStart = this.Position;
+ messageStarts.Push(messageStart);
+ this.Buffer[messageStart] = 0; // length
+ this.Buffer[messageStart + 1] = 0; // length
+ this.Position += 2; // ushort length
+ //this.Write(typeFlag);
+ }
+
+ ///
+ public void EndMessage()
+ {
+ var lastMessageStart = messageStarts.Pop();
+ ushort length = (ushort)(this.Position - lastMessageStart - /*3*/2); // Minus length and type byte
+ this.Buffer[lastMessageStart] = (byte)length;
+ this.Buffer[lastMessageStart + 1] = (byte)(length >> 8);
+ }
+
+ /// <summary>
+ /// ȡǰ༭messageصһ
+ /// </summary>
+ public void CancelMessage()
+ {
+ this.Position = this.messageStarts.Pop();
+ this.Length = this.Position;
+ }
+
+ public void Clear()
+ {
+ Array.Clear(this.Buffer, 0, this.Buffer.Length);
+ this.messageStarts.Clear();
+ this.Length = 0;
+ this.Position = 0;
+ }
+
+ /// <summary>
+ /// message
+ /// </summary>
+ public void Recycle()
+ {
+ this.Position = this.Length = 0;
+ WriterPool.PutObject(this);
+ }
+
+#region WriteMethods
+
+ public void CopyFrom(MessageReader target)
+ {
+ int offset, length;
+ if (target.Tag == byte.MaxValue)
+ {
+ offset = target.Offset;
+ length = target.Length;
+ }
+ else
+ {
+ offset = target.Offset - 3;
+ length = target.Length + 3;
+ }
+
+ System.Buffer.BlockCopy(target.Buffer, offset, this.Buffer, this.Position, length);
+ this.Position += length;
+ if (this.Position > this.Length) this.Length = this.Position;
+ }
+
+ public void Write(bool value)
+ {
+ this.Buffer[this.Position++] = (byte)(value ? 1 : 0);
+ if (this.Position > this.Length) this.Length = this.Position;
+ }
+
+ public void Write(sbyte value)
+ {
+ this.Buffer[this.Position++] = (byte)value;
+ if (this.Position > this.Length) this.Length = this.Position;
+ }
+
+ public void Write(byte value)
+ {
+ this.Buffer[this.Position++] = value;
+ if (this.Position > this.Length) this.Length = this.Position;
+ }
+
+ public void Write(short value)
+ {
+ this.Buffer[this.Position++] = (byte)value;
+ this.Buffer[this.Position++] = (byte)(value >> 8);
+ if (this.Position > this.Length) this.Length = this.Position;
+ }
+
+ public void Write(ushort value)
+ {
+ this.Buffer[this.Position++] = (byte)value;
+ this.Buffer[this.Position++] = (byte)(value >> 8);
+ if (this.Position > this.Length) this.Length = this.Position;
+ }
+
+ public void Write(uint value)
+ {
+ this.Buffer[this.Position++] = (byte)value;
+ this.Buffer[this.Position++] = (byte)(value >> 8);
+ this.Buffer[this.Position++] = (byte)(value >> 16);
+ this.Buffer[this.Position++] = (byte)(value >> 24);
+ if (this.Position > this.Length) this.Length = this.Position;
+ }
+
+ public void Write(int value)
+ {
+ this.Buffer[this.Position++] = (byte)value;
+ this.Buffer[this.Position++] = (byte)(value >> 8);
+ this.Buffer[this.Position++] = (byte)(value >> 16);
+ this.Buffer[this.Position++] = (byte)(value >> 24);
+ if (this.Position > this.Length) this.Length = this.Position;
+ }
+
+ public void Write(ulong value)
+ {
+ this.Buffer[this.Position++] = (byte)value;
+ this.Buffer[this.Position++] = (byte)(value >> 8);
+ this.Buffer[this.Position++] = (byte)(value >> 16);
+ this.Buffer[this.Position++] = (byte)(value >> 24);
+ this.Buffer[this.Position++] = (byte)(value >> 32);
+ this.Buffer[this.Position++] = (byte)(value >> 40);
+ this.Buffer[this.Position++] = (byte)(value >> 48);
+ this.Buffer[this.Position++] = (byte)(value >> 56);
+ if (this.Position > this.Length) this.Length = this.Position;
+ }
+
+ public void Write(long value)
+ {
+ this.Buffer[this.Position++] = (byte)value;
+ this.Buffer[this.Position++] = (byte)(value >> 8);
+ this.Buffer[this.Position++] = (byte)(value >> 16);
+ this.Buffer[this.Position++] = (byte)(value >> 24);
+ this.Buffer[this.Position++] = (byte)(value >> 32);
+ this.Buffer[this.Position++] = (byte)(value >> 40);
+ this.Buffer[this.Position++] = (byte)(value >> 48);
+ this.Buffer[this.Position++] = (byte)(value >> 56);
+ if (this.Position > this.Length) this.Length = this.Position;
+ }
+
+ public unsafe void Write(float value)
+ {
+ fixed (byte* ptr = &this.Buffer[this.Position])
+ {
+ byte* valuePtr = (byte*)&value;
+
+ *ptr = *valuePtr;
+ *(ptr + 1) = *(valuePtr + 1);
+ *(ptr + 2) = *(valuePtr + 2);
+ *(ptr + 3) = *(valuePtr + 3);
+ }
+
+ this.Position += 4;
+ if (this.Position > this.Length) this.Length = this.Position;
+ }
+
+ public void Write(string value)
+ {
+ var bytes = UTF8Encoding.UTF8.GetBytes(value);
+ this.WritePacked(bytes.Length);
+ this.Write(bytes);
+ }
+
+ public void WriteBytesAndSize(byte[] bytes)
+ {
+ this.WritePacked((uint)bytes.Length);
+ this.Write(bytes);
+ }
+
+ public void WriteBytesAndSize(byte[] bytes, int length)
+ {
+ this.WritePacked((uint)length);
+ this.Write(bytes, length);
+ }
+
+ public void WriteBytesAndSize(byte[] bytes, int offset, int length)
+ {
+ this.WritePacked((uint)length);
+ this.Write(bytes, offset, length);
+ }
+
+ public void Write(byte[] bytes)
+ {
+ Array.Copy(bytes, 0, this.Buffer, this.Position, bytes.Length);
+ this.Position += bytes.Length;
+ if (this.Position > this.Length) this.Length = this.Position;
+ }
+
+ public void Write(byte[] bytes, int offset, int length)
+ {
+ Array.Copy(bytes, offset, this.Buffer, this.Position, length);
+ this.Position += length;
+ if (this.Position > this.Length) this.Length = this.Position;
+ }
+
+ public void Write(byte[] bytes, int length)
+ {
+ Array.Copy(bytes, 0, this.Buffer, this.Position, length);
+ this.Position += length;
+ if (this.Position > this.Length) this.Length = this.Position;
+ }
+
+ ///
+ public void WritePacked(int value)
+ {
+ this.WritePacked((uint)value);
+ }
+
+ ///
+ public void WritePacked(uint value)
+ {
+ do
+ {
+ byte b = (byte)(value & 0xFF);
+ if (value >= 0x80)
+ {
+ b |= 0x80;
+ }
+
+ this.Write(b);
+ value >>= 7;
+ } while (value > 0);
+ }
+#endregion
+
+ public void Write(MessageWriter msg)
+ {
+ this.Write(msg.Buffer, 0, msg.Length);
+ }
+
+ public unsafe static bool IsLittleEndian()
+ {
+ byte b;
+ unsafe
+ {
+ int i = 1;
+ byte* bp = (byte*)&i;
+ b = *bp;
+ }
+
+ return b == 1;
+ }
+ }
+}
diff --git a/MultiplayerToolkit/Assets/MultiplayerToolkit/MessageWriter.cs.meta b/MultiplayerToolkit/Assets/MultiplayerToolkit/MessageWriter.cs.meta
new file mode 100644
index 0000000..ec9023e
--- /dev/null
+++ b/MultiplayerToolkit/Assets/MultiplayerToolkit/MessageWriter.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8d9ee77993c8eff4ba8b0a9026505b40
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/MultiplayerToolkit/Assets/MultiplayerToolkit/ObjectPool.cs b/MultiplayerToolkit/Assets/MultiplayerToolkit/ObjectPool.cs
new file mode 100644
index 0000000..e42cdd6
--- /dev/null
+++ b/MultiplayerToolkit/Assets/MultiplayerToolkit/ObjectPool.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace MultiplayerToolkit
+{
+ /// <summary>
+ /// A fairly simple object pool for items that will be created a lot.
+ /// </summary>
+ /// <typeparam name="T">The type that is pooled.</typeparam>
+ /// <threadsafety static="true" instance="true"/>
+ public sealed class ObjectPool<T> where T : IRecyclable
+ {
+ private int numberCreated;
+ public int NumberCreated { get { return numberCreated; } }
+
+ public int NumberInUse { get { return this.inuse.Count; } }
+ public int NumberNotInUse { get { return this.pool.Count; } }
+ public int Size { get { return this.NumberInUse + this.NumberNotInUse; } }
+
+#if HAZEL_BAG
+ private readonly ConcurrentBag<T> pool = new ConcurrentBag<T>();
+#else
+ private readonly List<T> pool = new List<T>();
+#endif
+
+ // Unavailable objects
+ private readonly ConcurrentDictionary<T, bool> inuse = new ConcurrentDictionary<T, bool>();
+
+ /// <summary>
+ /// The generator for creating new objects.
+ /// </summary>
+ /// <returns></returns>
+ private readonly Func<T> objectFactory;
+
+ /// <summary>
+ /// Internal constructor for our ObjectPool.
+ /// </summary>
+ internal ObjectPool(Func<T> objectFactory)
+ {
+ this.objectFactory = objectFactory;
+ }
+
+ /// <summary>
+ /// Returns a pooled object of type T, if none are available another is created.
+ /// </summary>
+ /// <returns>An instance of T.</returns>
+ internal T GetObject()
+ {
+#if HAZEL_BAG
+ if (!pool.TryTake(out T item))
+ {
+ Interlocked.Increment(ref numberCreated);
+ item = objectFactory.Invoke();
+ }
+#else
+ T item;
+ lock (this.pool)
+ {
+ if (this.pool.Count > 0)
+ {
+ var idx = this.pool.Count - 1;
+ item = this.pool[idx];
+ this.pool.RemoveAt(idx);
+ }
+ else
+ {
+ Interlocked.Increment(ref numberCreated);
+ item = objectFactory.Invoke();
+ }
+ }
+#endif
+
+ if (!inuse.TryAdd(item, true))
+ {
+ throw new Exception("Duplicate pull " + typeof(T).Name);
+ }
+
+ return item;
+ }
+
+ /// <summary>
+ /// Returns an object to the pool.
+ /// </summary>
+ /// <param name="item">The item to return.</param>
+ internal void PutObject(T item)
+ {
+ if (inuse.TryRemove(item, out bool b))
+ {
+#if HAZEL_BAG
+ pool.Add(item);
+#else
+ lock (this.pool)
+ {
+ pool.Add(item);
+ }
+#endif
+ }
+ else
+ {
+#if DEBUG
+ throw new Exception("Duplicate add " + typeof(T).Name);
+#endif
+ }
+ }
+ }
+}
diff --git a/MultiplayerToolkit/Assets/MultiplayerToolkit/ObjectPool.cs.meta b/MultiplayerToolkit/Assets/MultiplayerToolkit/ObjectPool.cs.meta
new file mode 100644
index 0000000..82ce63a
--- /dev/null
+++ b/MultiplayerToolkit/Assets/MultiplayerToolkit/ObjectPool.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 752d8b9e476be7941a2b3d333d4e0f4d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/MultiplayerToolkit/Assets/MultiplayerToolkit/Packet.cs b/MultiplayerToolkit/Assets/MultiplayerToolkit/Packet.cs
index 4e73f80..96e13ca 100644
--- a/MultiplayerToolkit/Assets/MultiplayerToolkit/Packet.cs
+++ b/MultiplayerToolkit/Assets/MultiplayerToolkit/Packet.cs
@@ -6,12 +6,15 @@ using UnityEngine;
namespace MultiplayerToolkit
{
/// <summary>
+ /// MUCKģдͨõpacket̫
/// ͨýṹTCP\UDPSteamn
/// ṹ
+ /// --------------------------------------------------
/// 4bytes (ȣ4ֽڣ
/// 1byte (ЭͣЭ顢ԶЭ飩
/// (4bytes) (ԶЭ飬ṩһmodderΨһţ
/// 2bytes (ЭID
+ /// --------------------------------------------------
/// </summary>
public class Packet : IDisposable
{
@@ -24,6 +27,7 @@ namespace MultiplayerToolkit
{
this.writableBuffer = new List<byte>();
this.readPos = 0;
+ this.disposed = false;
}
/// <summary>
@@ -34,6 +38,7 @@ namespace MultiplayerToolkit
{
this.writableBuffer = new List<byte>();
this.readPos = 0;
+ this.disposed = false;
this.Write(_id);
}
@@ -41,6 +46,7 @@ namespace MultiplayerToolkit
{
this.writableBuffer = new List<byte>();
this.readPos = 0;
+ this.disposed = false;
this.SetBytes(_data);
}
diff --git a/MultiplayerToolkit/Assets/MultiplayerToolkit/Test/TestTcp/Test_TcpClient.cs b/MultiplayerToolkit/Assets/MultiplayerToolkit/Test/TestTcp/Test_TcpClient.cs
index 21c5329..2472538 100644
--- a/MultiplayerToolkit/Assets/MultiplayerToolkit/Test/TestTcp/Test_TcpClient.cs
+++ b/MultiplayerToolkit/Assets/MultiplayerToolkit/Test/TestTcp/Test_TcpClient.cs
@@ -25,10 +25,16 @@ public class Test_TcpClient : MonoBehaviour
client = new TcpClient(endpoint);
client.Connect("127.0.1.1", 42046);
NetworkStream stream = client.GetStream();
- Packet packet = new Packet();
- packet.Write((int)123);
- packet.Write("hello");
- stream.Write(packet.ToArray());
+ //Packet packet = new Packet();
+ //packet.Write((int)123);
+ //packet.Write("hello");
+ //stream.Write(packet.ToArray());
+
+ MessageWriter msg = MessageWriter.Get();
+ msg.StartMessage();
+ msg.Write("hello");
+ msg.EndMessage();
+ stream.Write(msg.ToByteArray());
Debug.Log("connected, " + client.Connected);
}
diff --git a/MultiplayerToolkit/Assets/MultiplayerToolkit/Test/TestTcp/Test_TcpServer.cs b/MultiplayerToolkit/Assets/MultiplayerToolkit/Test/TestTcp/Test_TcpServer.cs
index 7abd2ef..7a73b98 100644
--- a/MultiplayerToolkit/Assets/MultiplayerToolkit/Test/TestTcp/Test_TcpServer.cs
+++ b/MultiplayerToolkit/Assets/MultiplayerToolkit/Test/TestTcp/Test_TcpServer.cs
@@ -32,9 +32,6 @@ public class Test_TcpServer : MonoBehaviour
Debug.Log("Start, Thread=" + Thread.CurrentThread.ManagedThreadId);
- Foo2();
- Debug.Log("Foo2");
-
Listen();
Debug.Log("listen");
@@ -54,7 +51,7 @@ public class Test_TcpServer : MonoBehaviour
int readLen = await stream.ReadAsync(buffer, 0, BUFFER_SIZE);
Packet packet = new Packet();
packet.SetBytes(buffer, 0, readLen);
- int value = packet.ReadInt();
+ short value = packet.ReadShort();
string str = packet.ReadString();
ExecuteOnMainThread(() =>
{
@@ -64,27 +61,6 @@ public class Test_TcpServer : MonoBehaviour
}
}
- async Task<int> Foo2()
- {
- Debug.Log("Foo2, Thread=" + Thread.CurrentThread.ManagedThreadId);
- await Foo();
-
- Thread.Sleep(1000);
-
- await Task.Run(() => {
- int threadid = Thread.CurrentThread.ManagedThreadId;
- ExecuteOnMainThread(() => {
- Debug.Log("Task, Threadid=" + threadid);
- });
- for (int i = 0; i < 100; ++i)
- {
- Debug.Log(i);
- }
- });
-
- return 1;
- }
-
async Task<int> Foo()
{
return 1;
diff --git a/MultiplayerToolkit/ProjectSettings/ProjectSettings.asset b/MultiplayerToolkit/ProjectSettings/ProjectSettings.asset
index 7a0d1e1..ad659a4 100644
--- a/MultiplayerToolkit/ProjectSettings/ProjectSettings.asset
+++ b/MultiplayerToolkit/ProjectSettings/ProjectSettings.asset
@@ -3,7 +3,7 @@
--- !u!129 &1
PlayerSettings:
m_ObjectHideFlags: 0
- serializedVersion: 23
+ serializedVersion: 24
productGUID: 9f52a494a2dbecb4caa35f29277eb304
AndroidProfiler: 0
AndroidFilterTouchesWhenObscured: 0
@@ -121,6 +121,7 @@ PlayerSettings:
switchNVNOtherPoolsGranularity: 16777216
switchNVNMaxPublicTextureIDCount: 0
switchNVNMaxPublicSamplerIDCount: 0
+ switchMaxWorkerMultiple: 8
stadiaPresentMode: 0
stadiaTargetFramerate: 0
vulkanNumSwapchainBuffers: 3
@@ -177,10 +178,10 @@ PlayerSettings:
StripUnusedMeshComponents: 0
VertexChannelCompressionMask: 4054
iPhoneSdkVersion: 988
- iOSTargetOSVersionString: 11.0
+ iOSTargetOSVersionString: 12.0
tvOSSdkVersion: 0
tvOSRequireExtendedGameController: 0
- tvOSTargetOSVersionString: 11.0
+ tvOSTargetOSVersionString: 12.0
uIPrerenderedIcon: 0
uIRequiresPersistentWiFi: 0
uIRequiresFullScreen: 1
@@ -498,6 +499,7 @@ PlayerSettings:
m_Kind: 1
m_SubKind:
m_BuildTargetBatching: []
+ m_BuildTargetShaderSettings: []
m_BuildTargetGraphicsJobs: []
m_BuildTargetGraphicsJobMode: []
m_BuildTargetGraphicsAPIs:
@@ -508,6 +510,8 @@ PlayerSettings:
m_APIs: 0b00000008000000
m_Automatic: 0
m_BuildTargetVRSettings: []
+ m_DefaultShaderChunkSizeInMB: 16
+ m_DefaultShaderChunkCount: 0
openGLRequireES31: 0
openGLRequireES31AEP: 0
openGLRequireES32: 0
@@ -614,7 +618,6 @@ PlayerSettings:
switchReleaseVersion: 0
switchDisplayVersion: 1.0.0
switchStartupUserAccount: 0
- switchTouchScreenUsage: 0
switchSupportedLanguagesMask: 0
switchLogoType: 0
switchApplicationErrorCodeCategory:
@@ -656,6 +659,7 @@ PlayerSettings:
switchNativeFsCacheSize: 32
switchIsHoldTypeHorizontal: 0
switchSupportedNpadCount: 8
+ switchEnableTouchScreen: 1
switchSocketConfigEnabled: 0
switchTcpInitialSendBufferSize: 32
switchTcpInitialReceiveBufferSize: 64
@@ -668,6 +672,7 @@ PlayerSettings:
switchNetworkInterfaceManagerInitializeEnabled: 1
switchPlayerConnectionEnabled: 1
switchUseNewStyleFilepaths: 0
+ switchUseLegacyFmodPriorities: 1
switchUseMicroSleepForYield: 1
switchEnableRamDiskSupport: 0
switchMicroSleepForYieldTime: 25
@@ -767,16 +772,30 @@ PlayerSettings:
webGLLinkerTarget: 1
webGLThreadsSupport: 0
webGLDecompressionFallback: 0
+ webGLPowerPreference: 2
scriptingDefineSymbols:
Standalone: STEAMWORKS_NET
additionalCompilerArguments: {}
platformArchitecture: {}
scriptingBackend: {}
il2cppCompilerConfiguration: {}
- managedStrippingLevel: {}
+ managedStrippingLevel:
+ EmbeddedLinux: 1
+ GameCoreScarlett: 1
+ GameCoreXboxOne: 1
+ Lumin: 1
+ Nintendo Switch: 1
+ PS4: 1
+ PS5: 1
+ Stadia: 1
+ WebGL: 1
+ Windows Store Apps: 1
+ XboxOne: 1
+ iPhone: 1
+ tvOS: 1
incrementalIl2cppBuild: {}
suppressCommonWarnings: 1
- allowUnsafeCode: 0
+ allowUnsafeCode: 1
useDeterministicCompilation: 1
enableRoslynAnalyzers: 1
additionalIl2CppArgs:
@@ -857,6 +876,7 @@ PlayerSettings:
m_VersionName:
apiCompatibilityLevel: 6
activeInputHandler: 0
+ windowsGamepadBackendHint: 0
cloudProjectId:
framebufferDepthMemorylessMode: 0
qualitySettingsNames: []