aboutsummaryrefslogtreecommitdiff
path: root/Projects/Packet
diff options
context:
space:
mode:
authorchai <215380520@qq.com>2023-10-16 11:32:53 +0800
committerchai <215380520@qq.com>2023-10-16 11:32:53 +0800
commit01903c7e4451cc1ecd2dd0a3a4c71408a7b5f612 (patch)
tree131bb9fdcff444c7110a562abd46ee46fe6cc699 /Projects/Packet
parent852e4d13026c2a3af0bfc5d67dbca24cace16a7f (diff)
+ Packet
Diffstat (limited to 'Projects/Packet')
-rw-r--r--Projects/Packet/Packet/.gitignore194
-rw-r--r--Projects/Packet/Packet/MultiplayerToolkit/Packet.cs389
-rw-r--r--Projects/Packet/Packet/Packet.csproj69
-rw-r--r--Projects/Packet/Packet/Packet.sln25
-rw-r--r--Projects/Packet/Packet/Properties/AssemblyInfo.cs20
-rw-r--r--Projects/Packet/Packet/UnitTest1.cs72
-rw-r--r--Projects/Packet/Packet/packages.config5
7 files changed, 774 insertions, 0 deletions
diff --git a/Projects/Packet/Packet/.gitignore b/Projects/Packet/Packet/.gitignore
new file mode 100644
index 0000000..9bf6cfb
--- /dev/null
+++ b/Projects/Packet/Packet/.gitignore
@@ -0,0 +1,194 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+.vs/
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+x64/
+build/
+bld/
+[Bb]in/
+[Oo]bj/
+
+#Sandcastle generated documentation
+[Hh]elp/
+
+# Roslyn cache directories
+*.ide/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+#NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding addin-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+## TODO: Comment the next line if you want to checkin your
+## web deploy settings but do note that will include unencrypted
+## passwords
+#*.pubxml
+
+# NuGet Packages Directory
+packages/*
+## TODO: If the tool you use requires repositories.config
+## uncomment the next line
+#!packages/repositories.config
+
+# Enable "build/" folder in the NuGet Packages folder since
+# NuGet packages use it for MSBuild targets.
+# This line needs to be after the ignore of the build folder
+# (and the packages folder if the line above has been uncommented)
+!packages/build/
+
+# Windows Azure Build Output
+csx/
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Others
+sql/
+*.Cache
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# LightSwitch generated files
+GeneratedArtifacts/
+_Pvt_Extensions/
+ModelManifest.xml
+*.ide
diff --git a/Projects/Packet/Packet/MultiplayerToolkit/Packet.cs b/Projects/Packet/Packet/MultiplayerToolkit/Packet.cs
new file mode 100644
index 0000000..bce39b0
--- /dev/null
+++ b/Projects/Packet/Packet/MultiplayerToolkit/Packet.cs
@@ -0,0 +1,389 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices.WindowsRuntime;
+using System.Text;
+#if UNITY_5_3_OR_NEWER
+using UnityEngine;
+#endif
+
+namespace MultiplayerToolkit
+{
+ public enum EPacketMode
+ {
+ Write = 0,
+ Read = 1,
+ }
+
+ /// <summary>
+ /// 读写通用的简易packet
+ /// 网络包,通用结构,无论是TCP\UDP还是Steamn
+ /// 结构:
+ /// --------------------------------------------------
+ /// 2bytes (ushort)包长度,不含这2字节)
+ /// (--------------------------------------------------
+ /// 1byte 消息类型,内置消息、玩家自定义消息
+ /// (2byte) (如果是玩家自定义消息,提供一个mod序号,Steam.UGC.Item的id是ulong 8bytes有点大,换成序号,最多支持65535个mod)
+ /// 2byte (ushort)消息ID 0-65535
+ /// 内容
+ /// --------------------------------------------------)
+ /// </summary>
+ public class Packet : IDisposable
+ {
+ // 写入缓冲区
+ private List<byte> writableBuffer;
+
+ // 读取缓冲区,有效数据一定是从头开始
+ private byte[] readableBuffer;
+ private int readPos;
+
+ private EPacketMode m_Mode;
+ public EPacketMode mode { get { return m_Mode; } }
+
+ private bool disposed;
+
+ #region 创建
+
+ public static Packet GetWritablePacket()
+ {
+ Packet packet = new Packet();
+ packet.m_Mode = EPacketMode.Write;
+ packet.writableBuffer = new List<byte>();
+ packet.readableBuffer = null;
+ packet.readPos = 0;
+ return packet;
+ }
+
+ public static Packet GetWritablePacket(Packet readable)
+ {
+ if (readable.mode != EPacketMode.Read)
+ return null;
+ Packet packet = GetWritablePacket();
+ packet.Write(readable.readableBuffer);
+ return packet;
+ }
+
+ public static Packet GetReadablePacket(byte[] srcToCopy, int offset = 0, int length = -1)
+ {
+ Packet packet = new Packet();
+ packet.m_Mode = EPacketMode.Read;
+ packet.writableBuffer = null;
+ int len = length;
+ if (length == -1)
+ {
+ len = srcToCopy.Length - offset;
+ }
+ packet.readableBuffer = new byte[len];
+ Array.Copy(srcToCopy, offset, packet.readableBuffer, 0, len);
+ packet.readPos = 0;
+ return packet;
+ }
+
+ public static Packet GetReadablePacket(Packet writable)
+ {
+ if (writable.mode != EPacketMode.Write)
+ return null;
+ Packet packet = GetReadablePacket(writable.ToArray());
+ return packet;
+ }
+
+ #endregion
+
+ private Packet()
+ {
+ this.disposed = false;
+ }
+
+ public void Reset(bool bReset = true)
+ {
+ if (!bReset)
+ {
+ return;
+ }
+ if (mode == EPacketMode.Write)
+ {
+ this.writableBuffer.Clear();
+ }
+ else if (mode == EPacketMode.Read)
+ {
+ Array.Clear(this.readableBuffer, 0, this.readableBuffer.Length);
+ readPos = 0;
+ }
+ }
+
+ private static T[] SubArray<T>(T[] data, int index, int length)
+ {
+ T[] result = new T[length];
+ Array.Copy(data, index, result, 0, length);
+ return result;
+ }
+
+ #region 写入
+ /// <summary>
+ /// 开头写入一个int为当前writableBuffer长度,不含这个长度
+ /// </summary>
+ public void InsertLength()
+ {
+ this.writableBuffer.InsertRange(0, BitConverter.GetBytes(this.writableBuffer.Count));
+ }
+
+ /// <summary>
+ /// 开头写入一个int
+ /// </summary>
+ /// <param name="_value"></param>
+ public void InsertInt(int _value)
+ {
+ this.writableBuffer.InsertRange(0, BitConverter.GetBytes(_value));
+ }
+
+ /// <summary>
+ /// 返回创建的数组,不要频繁调用
+ /// </summary>
+ /// <returns></returns>
+ public byte[] ToArray()
+ {
+ if (this.mode != EPacketMode.Write)
+ return null;
+ return this.writableBuffer.ToArray();
+ }
+
+ /// <summary>
+ /// 写入了多少内容
+ /// </summary>
+ /// <returns></returns>
+ public int GetWritableBufferLength()
+ {
+ return this.writableBuffer.Count;
+ }
+
+ public void Write(byte _value)
+ {
+ this.writableBuffer.Add(_value);
+ }
+
+ public void Write(byte[] _value)
+ {
+ this.writableBuffer.AddRange(_value);
+ }
+
+ public void Write(short _value)
+ {
+ this.writableBuffer.AddRange(BitConverter.GetBytes(_value));
+ }
+
+ public void Write(int _value)
+ {
+ this.writableBuffer.AddRange(BitConverter.GetBytes(_value));
+ }
+
+ public void Write(long _value)
+ {
+ this.writableBuffer.AddRange(BitConverter.GetBytes(_value));
+ }
+
+ public void Write(float _value)
+ {
+ this.writableBuffer.AddRange(BitConverter.GetBytes(_value));
+ }
+
+ public void Write(bool _value)
+ {
+ this.writableBuffer.AddRange(BitConverter.GetBytes(_value));
+ }
+
+ public void Write(string _value)
+ {
+ this.Write((int)_value.Length);
+ this.writableBuffer.AddRange(Encoding.ASCII.GetBytes(_value));
+ }
+
+#if UNITY_5_3_OR_NEWER
+
+ public void Write(Vector3 _value)
+ {
+ this.Write(_value.x);
+ this.Write(_value.y);
+ this.Write(_value.z);
+ }
+
+ public void Write(Quaternion _value)
+ {
+ this.Write(_value.x);
+ this.Write(_value.y);
+ this.Write(_value.z);
+ this.Write(_value.w);
+ }
+#endif
+
+ #endregion
+
+ #region 读取
+
+ public void RewindReadPos(int step, bool bRewind = true)
+ {
+ if (bRewind)
+ {
+ this.readPos -= step;
+ }
+ }
+
+ public int GetUnreadLength()
+ {
+ return this.readableBuffer.Length - this.readPos;
+ }
+
+ public byte ReadByte(bool _moveReadPos = true)
+ {
+ if (this.readableBuffer.Length > this.readPos)
+ {
+ byte value = this.readableBuffer[this.readPos];
+ if (_moveReadPos)
+ {
+ this.readPos++;
+ }
+ return value;
+ }
+ throw new Exception("Could not read value of type 'byte'!");
+ }
+
+ public byte[] ReadBytes(int _length, bool _moveReadPos = true)
+ {
+ if (this.readableBuffer.Length > this.readPos)
+ {
+ byte[] value = SubArray(this.readableBuffer, this.readPos, _length);
+ if (_moveReadPos)
+ {
+ this.readPos += _length;
+ }
+ return value;
+ }
+ throw new Exception("Could not read value of type 'byte[]'!");
+ }
+
+ public short ReadShort(bool _moveReadPos = true)
+ {
+ if (this.readableBuffer.Length > this.readPos)
+ {
+ short value = BitConverter.ToInt16(this.readableBuffer, this.readPos);
+ if (_moveReadPos)
+ {
+ this.readPos += 2;
+ }
+ return value;
+ }
+ throw new Exception("Could not read value of type 'short'!");
+ }
+
+ public int ReadInt(bool _moveReadPos = true)
+ {
+ if (this.readableBuffer.Length > this.readPos)
+ {
+ int value = BitConverter.ToInt32(this.readableBuffer, this.readPos);
+ if (_moveReadPos)
+ {
+ this.readPos += 4;
+ }
+ return value;
+ }
+ throw new Exception("Could not read value of type 'int'!");
+ }
+
+ public long ReadLong(bool _moveReadPos = true)
+ {
+ if (this.readableBuffer.Length > this.readPos)
+ {
+ long value = BitConverter.ToInt64(this.readableBuffer, this.readPos);
+ if (_moveReadPos)
+ {
+ this.readPos += 8;
+ }
+ return value;
+ }
+ throw new Exception("Could not read value of type 'long'!");
+ }
+
+ public float ReadFloat(bool _moveReadPos = true)
+ {
+ if (this.readableBuffer.Length > this.readPos)
+ {
+ float value = BitConverter.ToSingle(this.readableBuffer, this.readPos);
+ if (_moveReadPos)
+ {
+ this.readPos += 4;
+ }
+ return value;
+ }
+ throw new Exception("Could not read value of type 'float'!");
+ }
+
+ public bool ReadBool(bool _moveReadPos = true)
+ {
+ if (this.readableBuffer.Length > this.readPos)
+ {
+ bool value = BitConverter.ToBoolean(this.readableBuffer, this.readPos);
+ if (_moveReadPos)
+ {
+ this.readPos++;
+ }
+ return value;
+ }
+ throw new Exception("Could not read value of type 'bool'!");
+ }
+
+ public string ReadString(bool _moveReadPos = true)
+ {
+ string result;
+ try
+ {
+ int num = this.ReadInt(true);
+ string @string = Encoding.ASCII.GetString(this.readableBuffer, this.readPos, num);
+ if (_moveReadPos && @string.Length > 0)
+ {
+ this.readPos += num;
+ }
+ result = @string;
+ }
+ catch (Exception e)
+ {
+ throw new Exception("Could not read value of type 'string'!");
+ }
+ return result;
+ }
+
+#if UNITY_5_3_OR_NEWER
+
+ public Vector3 ReadVector3(bool moveReadPos = true)
+ {
+ return new Vector3(this.ReadFloat(moveReadPos), this.ReadFloat(moveReadPos), this.ReadFloat(moveReadPos));
+ }
+
+ public Quaternion ReadQuaternion(bool moveReadPos = true)
+ {
+ return new Quaternion(this.ReadFloat(moveReadPos), this.ReadFloat(moveReadPos), this.ReadFloat(moveReadPos), this.ReadFloat(moveReadPos));
+ }
+#endif
+
+ #endregion
+
+ protected virtual void Dispose(bool _disposing)
+ {
+ if (!this.disposed)
+ {
+ if (_disposing)
+ {
+ this.writableBuffer = null;
+ this.readableBuffer = null;
+ this.readPos = 0;
+ }
+ this.disposed = true;
+ }
+ }
+
+ public void Dispose()
+ {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ }
+}
diff --git a/Projects/Packet/Packet/Packet.csproj b/Projects/Packet/Packet/Packet.csproj
new file mode 100644
index 0000000..fc2068c
--- /dev/null
+++ b/Projects/Packet/Packet/Packet.csproj
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="packages\MSTest.TestAdapter.2.2.7\build\net45\MSTest.TestAdapter.props" Condition="Exists('packages\MSTest.TestAdapter.2.2.7\build\net45\MSTest.TestAdapter.props')" />
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{602EEAD0-42FE-4473-9B41-70C14D3AD156}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Packet</RootNamespace>
+ <AssemblyName>Packet</AssemblyName>
+ <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
+ <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
+ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
+ <IsCodedUITest>False</IsCodedUITest>
+ <TestProjectType>UnitTest</TestProjectType>
+ <NuGetPackageImportStamp>
+ </NuGetPackageImportStamp>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <HintPath>packages\MSTest.TestFramework.2.2.7\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <HintPath>packages\MSTest.TestFramework.2.2.7\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="MultiplayerToolkit\Packet.cs" />
+ <Compile Include="UnitTest1.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('packages\MSTest.TestAdapter.2.2.7\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\MSTest.TestAdapter.2.2.7\build\net45\MSTest.TestAdapter.props'))" />
+ <Error Condition="!Exists('packages\MSTest.TestAdapter.2.2.7\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\MSTest.TestAdapter.2.2.7\build\net45\MSTest.TestAdapter.targets'))" />
+ </Target>
+ <Import Project="packages\MSTest.TestAdapter.2.2.7\build\net45\MSTest.TestAdapter.targets" Condition="Exists('packages\MSTest.TestAdapter.2.2.7\build\net45\MSTest.TestAdapter.targets')" />
+</Project> \ No newline at end of file
diff --git a/Projects/Packet/Packet/Packet.sln b/Projects/Packet/Packet/Packet.sln
new file mode 100644
index 0000000..0849e6b
--- /dev/null
+++ b/Projects/Packet/Packet/Packet.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.4.33213.308
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Packet", "Packet.csproj", "{602EEAD0-42FE-4473-9B41-70C14D3AD156}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {602EEAD0-42FE-4473-9B41-70C14D3AD156}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {602EEAD0-42FE-4473-9B41-70C14D3AD156}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {602EEAD0-42FE-4473-9B41-70C14D3AD156}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {602EEAD0-42FE-4473-9B41-70C14D3AD156}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {0AA0B9B6-7243-4120-9F50-2D4B6D59E1C9}
+ EndGlobalSection
+EndGlobal
diff --git a/Projects/Packet/Packet/Properties/AssemblyInfo.cs b/Projects/Packet/Packet/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..808412c
--- /dev/null
+++ b/Projects/Packet/Packet/Properties/AssemblyInfo.cs
@@ -0,0 +1,20 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("Packet")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("P R C")]
+[assembly: AssemblyProduct("Packet")]
+[assembly: AssemblyCopyright("Copyright © P R C 2023")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: ComVisible(false)]
+
+[assembly: Guid("602eead0-42fe-4473-9b41-70c14d3ad156")]
+
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Projects/Packet/Packet/UnitTest1.cs b/Projects/Packet/Packet/UnitTest1.cs
new file mode 100644
index 0000000..c014389
--- /dev/null
+++ b/Projects/Packet/Packet/UnitTest1.cs
@@ -0,0 +1,72 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+
+namespace MultiplayerToolkit
+{
+ [TestClass]
+ public class MultiplayerToolkitTest
+ {
+ [TestMethod]
+ public void TestReadAndWrite()
+ {
+ Packet packet = Packet.GetWritablePacket();
+
+ Assert.AreEqual(packet.mode, EPacketMode.Write);
+ packet.Write(1);
+ packet.Write(false);
+ packet.Write("hello, world");
+ packet.Write((byte)13);
+ packet.Write(12312.3333f);
+ packet.Write((short)1245);
+ packet.Write(long.MaxValue);
+ packet.Write(long.MinValue);
+ packet.InsertLength();
+
+ Packet read = Packet.GetReadablePacket(packet);
+
+ Assert.AreEqual(read.mode, EPacketMode.Read);
+ read.ReadInt(); // length
+ Assert.AreEqual(1, read.ReadInt());
+ Assert.AreEqual(false, read.ReadBool());
+ Assert.AreEqual("hello, world", read.ReadString());
+ Assert.AreEqual((byte)13, read.ReadByte());
+ Assert.AreEqual(12312.3333f, read.ReadFloat());
+ Assert.AreEqual((short)1245, read.ReadShort());
+ Assert.AreEqual((long)long.MaxValue, read.ReadLong());
+ Assert.AreEqual((long)long.MinValue, read.ReadLong());
+ }
+
+ [TestMethod]
+ public void TestReadAndWrite2()
+ {
+ Packet packet = Packet.GetWritablePacket();
+
+ Assert.AreEqual(packet.mode, EPacketMode.Write);
+ packet.Write(1);
+ packet.Write(false);
+ packet.Write("hello, world");
+ packet.Write((byte)13);
+ packet.Write(12312.3333f);
+ packet.Write((short)1245);
+ packet.Write(long.MaxValue);
+ packet.Write(long.MinValue);
+ packet.InsertLength();
+
+ Packet read = Packet.GetReadablePacket(packet.ToArray());
+
+ Assert.AreEqual(read.mode, EPacketMode.Read);
+ read.ReadInt(); // length
+ Assert.AreEqual(1, read.ReadInt());
+ read.RewindReadPos(4);
+ read.ReadInt();
+ Assert.AreEqual(false, read.ReadBool());
+ Assert.AreEqual("hello, world", read.ReadString());
+ Assert.AreEqual((byte)13, read.ReadByte());
+ Assert.AreEqual(12312.3333f, read.ReadFloat());
+ Assert.AreEqual((short)1245, read.ReadShort());
+ Assert.AreEqual((long)long.MaxValue, read.ReadLong());
+ Assert.AreEqual((long)long.MinValue, read.ReadLong());
+ }
+
+ }
+}
diff --git a/Projects/Packet/Packet/packages.config b/Projects/Packet/Packet/packages.config
new file mode 100644
index 0000000..54eb31a
--- /dev/null
+++ b/Projects/Packet/Packet/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="MSTest.TestAdapter" version="2.2.7" targetFramework="net472" />
+ <package id="MSTest.TestFramework" version="2.2.7" targetFramework="net472" />
+</packages> \ No newline at end of file