diff --git a/.vs/CommunityServerAPI/DesignTimeBuild/.dtbcache.v2 b/.vs/CommunityServerAPI/DesignTimeBuild/.dtbcache.v2
new file mode 100644
index 0000000..440ed14
Binary files /dev/null and b/.vs/CommunityServerAPI/DesignTimeBuild/.dtbcache.v2 differ
diff --git a/.vs/CommunityServerAPI/FileContentIndex/026c4087-856f-4fee-9b51-b790775d2b15.vsidx b/.vs/CommunityServerAPI/FileContentIndex/026c4087-856f-4fee-9b51-b790775d2b15.vsidx
new file mode 100644
index 0000000..ffe58a3
Binary files /dev/null and b/.vs/CommunityServerAPI/FileContentIndex/026c4087-856f-4fee-9b51-b790775d2b15.vsidx differ
diff --git a/.vs/CommunityServerAPI/FileContentIndex/3a66ce49-204d-44a0-9e33-15bee7f794b5.vsidx b/.vs/CommunityServerAPI/FileContentIndex/3a66ce49-204d-44a0-9e33-15bee7f794b5.vsidx
new file mode 100644
index 0000000..e24349b
Binary files /dev/null and b/.vs/CommunityServerAPI/FileContentIndex/3a66ce49-204d-44a0-9e33-15bee7f794b5.vsidx differ
diff --git a/.vs/CommunityServerAPI/FileContentIndex/da7330ac-00fe-4d8d-afba-4cee117e0926.vsidx b/.vs/CommunityServerAPI/FileContentIndex/da7330ac-00fe-4d8d-afba-4cee117e0926.vsidx
new file mode 100644
index 0000000..bf4e1dc
Binary files /dev/null and b/.vs/CommunityServerAPI/FileContentIndex/da7330ac-00fe-4d8d-afba-4cee117e0926.vsidx differ
diff --git a/.vs/CommunityServerAPI/FileContentIndex/f95db37b-3de8-4b85-9e62-c24fa01b25b6.vsidx b/.vs/CommunityServerAPI/FileContentIndex/f95db37b-3de8-4b85-9e62-c24fa01b25b6.vsidx
new file mode 100644
index 0000000..0ebc807
Binary files /dev/null and b/.vs/CommunityServerAPI/FileContentIndex/f95db37b-3de8-4b85-9e62-c24fa01b25b6.vsidx differ
diff --git a/.vs/CommunityServerAPI/FileContentIndex/read.lock b/.vs/CommunityServerAPI/FileContentIndex/read.lock
new file mode 100644
index 0000000..e69de29
diff --git a/.vs/CommunityServerAPI/v17/.futdcache.v2 b/.vs/CommunityServerAPI/v17/.futdcache.v2
new file mode 100644
index 0000000..4461d21
Binary files /dev/null and b/.vs/CommunityServerAPI/v17/.futdcache.v2 differ
diff --git a/.vs/CommunityServerAPI/v17/.suo b/.vs/CommunityServerAPI/v17/.suo
new file mode 100644
index 0000000..562cfc0
Binary files /dev/null and b/.vs/CommunityServerAPI/v17/.suo differ
diff --git a/.vs/ProjectEvaluation/communityserverapi.metadata.v5.2 b/.vs/ProjectEvaluation/communityserverapi.metadata.v5.2
new file mode 100644
index 0000000..e897504
Binary files /dev/null and b/.vs/ProjectEvaluation/communityserverapi.metadata.v5.2 differ
diff --git a/.vs/ProjectEvaluation/communityserverapi.projects.v5.2 b/.vs/ProjectEvaluation/communityserverapi.projects.v5.2
new file mode 100644
index 0000000..7069791
Binary files /dev/null and b/.vs/ProjectEvaluation/communityserverapi.projects.v5.2 differ
diff --git a/BattleBitAPI/Client/Client.cs b/BattleBitAPI/Client/Client.cs
new file mode 100644
index 0000000..18192ca
--- /dev/null
+++ b/BattleBitAPI/Client/Client.cs
@@ -0,0 +1,93 @@
+using BattleBitAPI.Common.Enums;
+using BattleBitAPI.Common.Serialization;
+using BattleBitAPI.Networking;
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+namespace BattleBitAPI.Client
+{
+ // This class was created mainly for Unity Engine, for this reason, Task async was not implemented.
+ public class Client
+ {
+ // ---- Public Variables ----
+ public bool IsConnected { get; private set; }
+ public int Port { get; private set; }
+ public bool IsPasswordProtected { get; private set; }
+ public string ServerName { get; private set; }
+ public string Gamemode { get; private set; }
+ public string Map { get; private set; }
+ public MapSize MapSize { get; private set; }
+ public MapDayNight DayNight { get; private set; }
+ public int CurrentPlayers { get; private set; }
+ public int InQueuePlayers { get; private set; }
+ public int MaxPlayers { get; private set; }
+ public string LoadingScreenText { get; private set; }
+ public string ServerRulesText { get; private set; }
+
+ // ---- Private Variables ----
+ private TcpClient mClient;
+ private string mDestination;
+ private int mPort;
+ private bool mIsConnectingFlag;
+
+ // ---- Construction ----
+ public Client(string destination, int port)
+ {
+ this.mDestination = destination;
+ this.mPort = port;
+ }
+
+ // ---- Main Tick ----
+ public void Tick()
+ {
+ //Are we connecting?
+ if (mIsConnectingFlag)
+ return;
+
+ //Have we connected?
+ if (!this.IsConnected)
+ {
+ //Attempt to connect to server async.
+ this.mIsConnectingFlag = true;
+
+ var state = mClient.BeginConnect(mDestination, mPort, (x) =>
+ {
+ this.mIsConnectingFlag = false;
+
+ //Did we connect?
+ try { mClient.EndConnect(x); }
+ catch { return; }
+
+ using (var hail = BattleBitAPI.Common.Serialization.Stream.Get())
+ {
+ hail.Write((byte)NetworkCommuncation.Hail);
+ hail.Write((ushort)this.Port);
+ hail.Write(this.IsPasswordProtected);
+ hail.Write(this.ServerName);
+ hail.Write(this.Gamemode);
+ hail.Write(this.Map);
+ hail.Write((byte)this.MapSize);
+ hail.Write((byte)this.DayNight);
+ hail.Write((byte)this.CurrentPlayers);
+ hail.Write((byte)this.InQueuePlayers);
+ hail.Write((byte)this.MaxPlayers);
+ hail.Write(this.LoadingScreenText);
+ hail.Write(this.ServerRulesText);
+
+ //Send our hail package.
+ mClient.GetStream().Write(hail.Buffer, 0, hail.WritePosition);
+ }
+
+ }, null);
+
+ return;
+ }
+ }
+
+ // ---- Private ----
+
+
+
+ }
+}
diff --git a/BattleBitAPI/Common/Conts.cs b/BattleBitAPI/Common/Conts.cs
new file mode 100644
index 0000000..c7e398f
--- /dev/null
+++ b/BattleBitAPI/Common/Conts.cs
@@ -0,0 +1,40 @@
+namespace CommunityServerAPI.BattleBitAPI
+{
+ public static class Const
+ {
+ // ---- Networking ----
+ ///
+ /// Maximum data size for a single package. 4MB is default.
+ ///
+ public const int MaxNetworkPackageSize = 1024 * 1024 * 4;//4mb
+ ///
+ /// How long should server/client wait until connection is determined as timed out when no packages is being sent for long time.
+ ///
+ public const int NetworkTimeout = 60 * 1000;//60 seconds
+ ///
+ /// How frequently client/server will send keep alive to each other when no message is being sent to each other for a while.
+ ///
+ public const int NetworkKeepAlive = 15 * 1000;//15 seconds
+ ///
+ /// How long server will wait client to send their hail package. In miliseconds.
+ ///
+ public const int HailConnectTimeout = 2 * 1000;
+
+ // ---- Server Fields ----
+ public const int MinServerNameLength = 5;
+ public const int MaxServerNameLength = 400;
+
+ public const int MinGamemodeNameLength = 2;
+ public const int MaxGamemodeNameLength = 12;
+
+ public const int MinMapNameLength = 2;
+ public const int MaxMapNameLength = 36;
+
+ public const int MinLoadingScreenTextLength = 0;
+ public const int MaxLoadingScreenTextLength = 1024 * 8;
+
+ public const int MinServerRulesTextLength = 0;
+ public const int MaxServerRulesTextLength = 1024 * 8;
+
+ }
+}
diff --git a/BattleBitAPI/Common/Enums/MapDayNight.cs b/BattleBitAPI/Common/Enums/MapDayNight.cs
new file mode 100644
index 0000000..0a40c84
--- /dev/null
+++ b/BattleBitAPI/Common/Enums/MapDayNight.cs
@@ -0,0 +1,8 @@
+namespace BattleBitAPI.Common.Enums
+{
+ public enum MapDayNight : byte
+ {
+ Day = 0,
+ Night = 1,
+ }
+}
diff --git a/BattleBitAPI/Common/Enums/MapSize.cs b/BattleBitAPI/Common/Enums/MapSize.cs
new file mode 100644
index 0000000..87d1613
--- /dev/null
+++ b/BattleBitAPI/Common/Enums/MapSize.cs
@@ -0,0 +1,10 @@
+namespace BattleBitAPI.Common.Enums
+{
+ public enum MapSize : byte
+ {
+ _16vs16 = 0,
+ _32vs32 = 1,
+ _64vs64 = 2,
+ _127vs127 = 3,
+ }
+}
diff --git a/BattleBitAPI/Common/Extentions/Extentions.cs b/BattleBitAPI/Common/Extentions/Extentions.cs
new file mode 100644
index 0000000..3ef94dd
--- /dev/null
+++ b/BattleBitAPI/Common/Extentions/Extentions.cs
@@ -0,0 +1,82 @@
+using System.Net;
+using System.Net.Sockets;
+
+namespace BattleBitAPI.Common.Extentions
+{
+ public static class Extentions
+ {
+ public static long TickCount
+ {
+ get
+ {
+#if NETCOREAPP
+ return System.Environment.TickCount64;
+#else
+ return (long)Environment.TickCount;
+#endif
+ }
+ }
+ public unsafe static uint ToUInt(this IPAddress address)
+ {
+#if NETCOREAPP
+ return BitConverter.ToUInt32(address.GetAddressBytes());
+#else
+ return BitConverter.ToUInt32(address.GetAddressBytes(), 0);
+#endif
+ }
+
+ public static void SafeClose(this TcpClient client)
+ {
+ try { client.Close(); } catch { }
+ try { client.Dispose(); } catch { }
+ }
+ public static async Task Read(this NetworkStream networkStream, Serialization.Stream outputStream, int size, CancellationToken token = default)
+ {
+ int read = 0;
+ int readUntil = outputStream.WritePosition + size;
+
+ //Ensure we have space.
+ outputStream.EnsureWriteBufferSize(size);
+
+ //Continue reading until we have the package.
+ while (outputStream.WritePosition < readUntil)
+ {
+ int sizeToRead = readUntil - outputStream.WritePosition;
+ int received = await networkStream.ReadAsync(outputStream.Buffer, outputStream.WritePosition, sizeToRead, token);
+ if (received <= 0)
+ throw new Exception("NetworkStream was closed.");
+
+ read += received;
+ outputStream.WritePosition += received;
+ }
+
+ return read;
+ }
+ public static async Task TryRead(this NetworkStream networkStream, Serialization.Stream outputStream, int size, CancellationToken token = default)
+ {
+ try
+ {
+ int readUntil = outputStream.WritePosition + size;
+
+ //Ensure we have space.
+ outputStream.EnsureWriteBufferSize(size);
+
+ //Continue reading until we have the package.
+ while (outputStream.WritePosition < readUntil)
+ {
+ int sizeToRead = readUntil - outputStream.WritePosition;
+ int received = await networkStream.ReadAsync(outputStream.Buffer, outputStream.WritePosition, sizeToRead, token);
+ if (received <= 0)
+ throw new Exception("NetworkStream was closed.");
+ outputStream.WritePosition += received;
+ }
+
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+}
diff --git a/BattleBitAPI/Common/Serialization/IStreamSerializble.cs b/BattleBitAPI/Common/Serialization/IStreamSerializble.cs
new file mode 100644
index 0000000..61fcb6c
--- /dev/null
+++ b/BattleBitAPI/Common/Serialization/IStreamSerializble.cs
@@ -0,0 +1,8 @@
+namespace BattleBitAPI.Common.Serialization
+{
+ public interface IStreamSerializable
+ {
+ void Read(Stream ser);
+ void Write(Stream ser);
+ }
+}
diff --git a/BattleBitAPI/Common/Serialization/Stream.cs b/BattleBitAPI/Common/Serialization/Stream.cs
new file mode 100644
index 0000000..eddf56f
--- /dev/null
+++ b/BattleBitAPI/Common/Serialization/Stream.cs
@@ -0,0 +1,670 @@
+using BattleBitAPI.Common.Extentions;
+using System.Net;
+
+namespace BattleBitAPI.Common.Serialization
+{
+ public class Stream : IDisposable
+ {
+ public const int DefaultBufferSize = 1024 * 512;
+
+#if BIGENDIAN
+ public static readonly bool IsLittleEndian = false;
+#else
+ public static readonly bool IsLittleEndian = true;
+#endif
+
+ public byte[] Buffer;
+ public int WritePosition;
+ public int ReadPosition;
+ public bool InPool;
+
+ public bool CanRead(int size)
+ {
+ int readableLenght = WritePosition - ReadPosition;
+ return (readableLenght >= size);
+ }
+ public void EnsureWriteBufferSize(int requiredSize)
+ {
+ int bufferLenght = Buffer.Length;
+
+ int leftSpace = bufferLenght - WritePosition;
+ if (leftSpace < requiredSize)
+ {
+ int newSize = bufferLenght + Math.Max(requiredSize, 1024);
+ System.Array.Resize(ref Buffer, newSize);
+ }
+ }
+
+ // -------- Write ------
+ public void Write(byte value)
+ {
+ EnsureWriteBufferSize(1);
+ Buffer[WritePosition] = value;
+ WritePosition += 1;
+ }
+ public void Write(bool value)
+ {
+ EnsureWriteBufferSize(1);
+ Buffer[WritePosition] = value ? (byte)1 : (byte)0;
+ WritePosition += 1;
+ }
+ public unsafe void Write(short value)
+ {
+ EnsureWriteBufferSize(2);
+ fixed (byte* ptr = &Buffer[WritePosition])
+ *((short*)ptr) = value;
+ WritePosition += 2;
+ }
+ public unsafe void Write(ushort value)
+ {
+ EnsureWriteBufferSize(2);
+ fixed (byte* ptr = &Buffer[WritePosition])
+ *((ushort*)ptr) = value;
+ WritePosition += 2;
+ }
+ public unsafe void Write(int value)
+ {
+ EnsureWriteBufferSize(4);
+ fixed (byte* ptr = &Buffer[WritePosition])
+ *((int*)ptr) = value;
+ WritePosition += 4;
+ }
+ public unsafe void Write(uint value)
+ {
+ EnsureWriteBufferSize(4);
+ fixed (byte* ptr = &Buffer[WritePosition])
+ *((uint*)ptr) = value;
+ WritePosition += 4;
+ }
+ public unsafe void Write(long value)
+ {
+ EnsureWriteBufferSize(8);
+ fixed (byte* ptr = &Buffer[WritePosition])
+ *((long*)ptr) = value;
+ WritePosition += 8;
+ }
+ public unsafe void Write(ulong value)
+ {
+ EnsureWriteBufferSize(8);
+ fixed (byte* ptr = &Buffer[WritePosition])
+ *((ulong*)ptr) = value;
+ WritePosition += 8;
+ }
+ public unsafe void Write(decimal value)
+ {
+ EnsureWriteBufferSize(16);
+ fixed (byte* ptr = &Buffer[WritePosition])
+ *((decimal*)ptr) = value;
+ WritePosition += 16;
+ }
+ public unsafe void Write(double value)
+ {
+ EnsureWriteBufferSize(16);
+ fixed (byte* ptr = &Buffer[WritePosition])
+ *((double*)ptr) = value;
+ WritePosition += 16;
+ }
+ public unsafe void Write(float value)
+ {
+ int intValue = *((int*)&value);
+ EnsureWriteBufferSize(4);
+ fixed (byte* ptr = &Buffer[WritePosition])
+ *((int*)ptr) = intValue;
+ WritePosition += 4;
+ }
+ public unsafe void Write(string value)
+ {
+ int charCount = value.Length;
+ fixed (char* strPtr = value)
+ {
+ int size = System.Text.Encoding.UTF8.GetByteCount(strPtr, charCount);
+ EnsureWriteBufferSize(size + 2);
+
+
+ fixed (byte* buffPtr = &Buffer[WritePosition])
+ {
+ *((ushort*)buffPtr) = (ushort)size;
+ System.Text.Encoding.UTF8.GetBytes(strPtr, charCount, buffPtr + 2, size);
+ }
+ WritePosition += size + 2;
+ }
+ }
+ public unsafe void Write(DateTime value)
+ {
+ var utc = value.ToUniversalTime();
+
+ EnsureWriteBufferSize(8);
+ fixed (byte* ptr = &Buffer[WritePosition])
+ *((long*)ptr) = utc.Ticks;
+ WritePosition += 8;
+ }
+ public unsafe void Write(IPAddress value)
+ {
+ uint ip = value.ToUInt();
+ Write(ip);
+ }
+ public unsafe void Write(IPEndPoint value)
+ {
+ uint ip = value.Address.ToUInt();
+
+ Write(ip);
+ Write((ushort)value.Port);
+ }
+ public unsafe void WriteRaw(string value)
+ {
+ int charCount = value.Length;
+ fixed (char* strPtr = value)
+ {
+ int size = System.Text.Encoding.UTF8.GetByteCount(strPtr, charCount);
+ EnsureWriteBufferSize(size);
+
+ fixed (byte* buffPtr = &Buffer[WritePosition])
+ System.Text.Encoding.UTF8.GetBytes(strPtr, charCount, buffPtr, size);
+ WritePosition += size;
+ }
+ }
+ public unsafe void Write(T value) where T : IStreamSerializable
+ {
+ value.Write(this);
+ }
+ public void Write(byte[] source, int sourceIndex, int length)
+ {
+ if (length == 0)
+ return;
+
+ EnsureWriteBufferSize(length);
+ System.Array.Copy(source, sourceIndex, this.Buffer, this.WritePosition, length);
+ this.WritePosition += length;
+ }
+ public void Write(Stream source)
+ {
+ EnsureWriteBufferSize(source.WritePosition);
+ System.Array.Copy(source.Buffer, 0, this.Buffer, this.WritePosition, source.WritePosition);
+ this.WritePosition += source.WritePosition;
+ }
+
+ public unsafe void WriteAt(byte value, int position)
+ {
+ Buffer[position] = value;
+ }
+ public unsafe void WriteAt(short value, int position)
+ {
+ fixed (byte* ptr = &Buffer[position])
+ *((short*)ptr) = value;
+ }
+ public unsafe void WriteAt(ushort value, int position)
+ {
+ fixed (byte* ptr = &Buffer[position])
+ *((ushort*)ptr) = value;
+ }
+ public unsafe void WriteAt(int value, int position)
+ {
+ fixed (byte* ptr = &Buffer[position])
+ *((int*)ptr) = value;
+ }
+ public unsafe void WriteAt(uint value, int position)
+ {
+ fixed (byte* ptr = &Buffer[position])
+ *((uint*)ptr) = value;
+ }
+ public unsafe void WriteAt(long value, int position)
+ {
+ fixed (byte* ptr = &Buffer[position])
+ *((long*)ptr) = value;
+ }
+ public unsafe void WriteAt(ulong value, int position)
+ {
+ fixed (byte* ptr = &Buffer[position])
+ *((ulong*)ptr) = value;
+ }
+
+ // -------- Read ------
+ public byte ReadInt8()
+ {
+
+ var value = Buffer[ReadPosition];
+ ReadPosition++;
+
+ return value;
+ }
+ public bool ReadBool()
+ {
+
+
+ var value = Buffer[ReadPosition];
+ ReadPosition++;
+
+ return value == 1;
+ }
+ public unsafe short ReadInt16()
+ {
+ short value = 0;
+
+ fixed (byte* pbyte = &Buffer[ReadPosition])
+ {
+ if (ReadPosition % 2 == 0)
+ {
+ value = *((short*)pbyte);
+ }
+ else
+ {
+ if (IsLittleEndian)
+ {
+ value = (short)((*pbyte) | (*(pbyte + 1) << 8));
+ }
+ else
+ {
+ value = (short)((*pbyte << 8) | (*(pbyte + 1)));
+ }
+ }
+ }
+
+ ReadPosition += 2;
+ return value;
+ }
+ public unsafe ushort ReadUInt16()
+ {
+ ushort value = 0;
+
+ fixed (byte* pbyte = &Buffer[ReadPosition])
+ {
+ if (ReadPosition % 2 == 0)
+ {
+ value = *((ushort*)pbyte);
+ }
+ else
+ {
+ if (IsLittleEndian)
+ {
+ value = (ushort)((*pbyte) | (*(pbyte + 1) << 8));
+ }
+ else
+ {
+ value = (ushort)((*pbyte << 8) | (*(pbyte + 1)));
+ }
+ }
+ }
+
+ ReadPosition += 2;
+ return value;
+ }
+ public unsafe int ReadInt32()
+ {
+ int value = 0;
+ fixed (byte* pbyte = &Buffer[ReadPosition])
+ {
+ if (ReadPosition % 4 == 0)
+ {
+ value = *((int*)pbyte);
+ }
+ else
+ {
+ if (IsLittleEndian)
+ {
+ value = (int)((*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24));
+ }
+ else
+ {
+ value = (int)((*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3)));
+ }
+ }
+ }
+ ReadPosition += 4;
+
+ return value;
+ }
+ public unsafe uint ReadUInt32()
+ {
+ uint value = 0;
+ fixed (byte* pbyte = &Buffer[ReadPosition])
+ {
+ if (ReadPosition % 4 == 0)
+ {
+ value = *((uint*)pbyte);
+ }
+ else
+ {
+ if (IsLittleEndian)
+ {
+ value = (uint)((*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24));
+ }
+ else
+ {
+ value = (uint)((*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3)));
+ }
+ }
+ }
+ ReadPosition += 4;
+
+ return value;
+ }
+ public unsafe long ReadInt64()
+ {
+ long value = 0;
+ fixed (byte* pbyte = &Buffer[ReadPosition])
+ {
+ if (ReadPosition % 8 == 0)
+ {
+ value = *((long*)pbyte);
+ }
+ else
+ {
+ if (IsLittleEndian)
+ {
+ int i1 = (*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24);
+ int i2 = (*(pbyte + 4)) | (*(pbyte + 5) << 8) | (*(pbyte + 6) << 16) | (*(pbyte + 7) << 24);
+ value = (uint)i1 | ((long)i2 << 32);
+ }
+ else
+ {
+ int i1 = (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3));
+ int i2 = (*(pbyte + 4) << 24) | (*(pbyte + 5) << 16) | (*(pbyte + 6) << 8) | (*(pbyte + 7));
+ value = (uint)i2 | ((long)i1 << 32);
+ }
+ }
+ }
+ ReadPosition += 8;
+
+ return value;
+ }
+ public unsafe ulong ReadUInt64()
+ {
+ ulong value = 0;
+ fixed (byte* pbyte = &Buffer[ReadPosition])
+ {
+ if (ReadPosition % 8 == 0)
+ {
+ value = *((ulong*)pbyte);
+ }
+ else
+ {
+ if (IsLittleEndian)
+ {
+ int i1 = (*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24);
+ int i2 = (*(pbyte + 4)) | (*(pbyte + 5) << 8) | (*(pbyte + 6) << 16) | (*(pbyte + 7) << 24);
+ value = (uint)i1 | ((ulong)i2 << 32);
+ }
+ else
+ {
+ int i1 = (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3));
+ int i2 = (*(pbyte + 4) << 24) | (*(pbyte + 5) << 16) | (*(pbyte + 6) << 8) | (*(pbyte + 7));
+ value = (uint)i2 | ((ulong)i1 << 32);
+ }
+ }
+ }
+ ReadPosition += 8;
+
+ return value;
+ }
+ public unsafe decimal ReadInt128()
+ {
+
+
+ decimal value = 0;
+ fixed (byte* ptr = &Buffer[ReadPosition])
+ {
+ value = *((decimal*)ptr);
+ }
+ ReadPosition += 16;
+
+ return value;
+ }
+ public unsafe double ReadDouble()
+ {
+ double value = 0;
+ fixed (byte* ptr = &Buffer[ReadPosition])
+ {
+ value = *((double*)ptr);
+ }
+ ReadPosition += 16;
+
+ return value;
+ }
+ public unsafe float ReadFloat()
+ {
+ int value = 0;
+ fixed (byte* pbyte = &Buffer[ReadPosition])
+ {
+ if (ReadPosition % 4 == 0)
+ {
+ value = *((int*)pbyte);
+ }
+ else
+ {
+ if (IsLittleEndian)
+ {
+ value = (int)((*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24));
+ }
+ else
+ {
+ value = (int)((*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3)));
+ }
+ }
+ }
+ ReadPosition += 4;
+
+ return *(float*)&value;
+ }
+ public DateTime ReadDateTime()
+ {
+ long value = ReadInt64();
+ try
+ {
+ return new DateTime(value, DateTimeKind.Utc);
+ }
+ catch
+ {
+ return DateTime.MinValue;
+ }
+ }
+ public bool TryReadDateTime(out DateTime time)
+ {
+ long value = ReadInt64();
+ try
+ {
+ time = new DateTime(value, DateTimeKind.Utc);
+ return true;
+ }
+ catch { }
+
+ time = default;
+ return false;
+ }
+ public unsafe IPAddress ReadIPAddress()
+ {
+ uint ip = ReadUInt32();
+ return new IPAddress(ip);
+ }
+ public unsafe IPEndPoint ReadIPEndPoint()
+ {
+ uint ip = ReadUInt32();
+ ushort port = ReadUInt16();
+
+ return new IPEndPoint(ip, port);
+ }
+ public T Read() where T : IStreamSerializable
+ {
+ T value = default;
+ value.Read(this);
+ return value;
+ }
+
+ public byte[] ReadByteArray(int lenght)
+ {
+ if (lenght == 0)
+ return new byte[0];
+
+ byte[] newBuffer = new byte[lenght];
+ System.Array.Copy(this.Buffer, this.ReadPosition, newBuffer, 0, lenght);
+ this.ReadPosition += lenght;
+ return newBuffer;
+ }
+ public void ReadTo(byte[] buffer, int offset, int size)
+ {
+ System.Array.Copy(this.Buffer, this.ReadPosition, buffer, offset, size);
+ this.ReadPosition += size;
+ }
+ public unsafe string ReadString(int size)
+ {
+ string str;
+
+#if NETCOREAPP
+ fixed (byte* ptr = &Buffer[ReadPosition])
+ str = System.Text.Encoding.UTF8.GetString(ptr, size);
+#else
+ str = System.Text.Encoding.UTF8.GetString(Buffer, ReadPosition, size);
+#endif
+ ReadPosition += size;
+
+ return str;
+ }
+ public unsafe bool TryReadString(out string str)
+ {
+ if (!CanRead(2))
+ {
+ str = null;
+ return false;
+ }
+
+
+ int size = 0;
+ fixed (byte* ptr = &Buffer[ReadPosition])
+ size = *((ushort*)ptr);
+ ReadPosition += 2;
+
+ if (!CanRead(size))
+ {
+ str = null;
+ return false;
+ }
+
+#if NETCOREAPP
+ fixed (byte* ptr = &Buffer[ReadPosition])
+ str = System.Text.Encoding.UTF8.GetString(ptr, size);
+#else
+ str = System.Text.Encoding.UTF8.GetString(Buffer, ReadPosition, size);
+#endif
+
+ ReadPosition += size;
+
+ return true;
+ }
+ public unsafe bool TryReadString(out string str, int maximumSize = ushort.MaxValue)
+ {
+ if (!CanRead(2))
+ {
+ str = null;
+ return false;
+ }
+
+
+ int size = 0;
+ fixed (byte* ptr = &Buffer[ReadPosition])
+ size = *((ushort*)ptr);
+ ReadPosition += 2;
+
+ if (size > maximumSize)
+ {
+ str = null;
+ return false;
+ }
+
+ if (!CanRead(size))
+ {
+ str = null;
+ return false;
+ }
+
+#if NETCOREAPP
+ fixed (byte* ptr = &Buffer[ReadPosition])
+ str = System.Text.Encoding.UTF8.GetString(ptr, size);
+#else
+ str = System.Text.Encoding.UTF8.GetString(Buffer, ReadPosition, size);
+#endif
+
+ ReadPosition += size;
+
+ return true;
+ }
+ public unsafe bool TrySkipString()
+ {
+ if (!CanRead(2))
+ return false;
+
+ int size = 0;
+ fixed (byte* ptr = &Buffer[ReadPosition])
+ size = *((ushort*)ptr);
+ ReadPosition += 2;
+
+ if (!CanRead(size))
+ return false;
+
+ ReadPosition += size;
+ return true;
+ }
+
+ public int NumberOfBytesReadable
+ {
+ get => WritePosition - ReadPosition;
+ }
+ public void SkipWriting(int size)
+ {
+ EnsureWriteBufferSize(size);
+ WritePosition += size;
+ }
+ public void SkipReading(int size)
+ {
+ ReadPosition += size;
+ }
+
+ // -------- Finalizing ------
+ public byte[] AsByteArrayData()
+ {
+ var data = new byte[this.WritePosition];
+ System.Array.Copy(this.Buffer, 0, data, 0, this.WritePosition);
+ return data;
+ }
+
+ public void Reset()
+ {
+ this.ReadPosition = 0;
+ this.WritePosition = 0;
+ }
+
+ public void Dispose()
+ {
+ if (InPool)
+ return;
+ InPool = true;
+
+ lock (mPool)
+ mPool.Enqueue(this);
+ }
+
+ // ------- Pool -----
+ private static Queue mPool = new Queue(1024 * 256);
+ public static Stream Get()
+ {
+ lock (mPool)
+ {
+ if (mPool.Count > 0)
+ {
+ var item = mPool.Dequeue();
+ item.WritePosition = 0;
+ item.ReadPosition = 0;
+ item.InPool = false;
+
+ return item;
+ }
+ }
+
+ return new Stream()
+ {
+ Buffer = new byte[DefaultBufferSize],
+ InPool = false,
+ ReadPosition = 0,
+ WritePosition = 0,
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/BattleBitAPI/Common/Threading/ThreadSafe.cs b/BattleBitAPI/Common/Threading/ThreadSafe.cs
new file mode 100644
index 0000000..23f7431
--- /dev/null
+++ b/BattleBitAPI/Common/Threading/ThreadSafe.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+
+namespace BattleBitAPI.Common.Threading
+{
+ public class ThreadSafe
+ {
+ private System.Threading.ReaderWriterLockSlim mLock;
+ public T Value;
+
+ public ThreadSafe(T value)
+ {
+ this.Value = value;
+ this.mLock = new System.Threading.ReaderWriterLockSlim(System.Threading.LockRecursionPolicy.SupportsRecursion);
+ }
+
+ public SafeWriteHandle GetWriteHandle() => new SafeWriteHandle(this.mLock);
+ public SafeReadHandle GetReadHandle() => new SafeReadHandle(this.mLock);
+
+ ///
+ /// Swaps current value with new value and returns old one.
+ ///
+ ///
+ /// Old value
+ public T SwapValue(T newValue)
+ {
+ using (new SafeWriteHandle(this.mLock))
+ {
+ var oldValue = this.Value;
+ this.Value = newValue;
+ return oldValue;
+ }
+ }
+ }
+ public class SafeWriteHandle : System.IDisposable
+ {
+ private System.Threading.ReaderWriterLockSlim mLock;
+ private bool mDisposed;
+ public SafeWriteHandle(System.Threading.ReaderWriterLockSlim mLock)
+ {
+ this.mLock = mLock;
+ mLock.EnterWriteLock();
+ }
+ public void Dispose()
+ {
+ if (mDisposed)
+ return;
+ mDisposed = true;
+ mLock.ExitWriteLock();
+ }
+ }
+ public class SafeReadHandle : System.IDisposable
+ {
+ private System.Threading.ReaderWriterLockSlim mLock;
+ private bool mDisposed;
+ public SafeReadHandle(System.Threading.ReaderWriterLockSlim mLock)
+ {
+ this.mLock = mLock;
+ mLock.EnterReadLock();
+ }
+ public void Dispose()
+ {
+ if (mDisposed)
+ return;
+ mDisposed = true;
+
+ mLock.ExitReadLock();
+ }
+ }
+}
\ No newline at end of file
diff --git a/BattleBitAPI/Networking/NetworkCommuncation.cs b/BattleBitAPI/Networking/NetworkCommuncation.cs
new file mode 100644
index 0000000..d401591
--- /dev/null
+++ b/BattleBitAPI/Networking/NetworkCommuncation.cs
@@ -0,0 +1,9 @@
+namespace BattleBitAPI.Networking
+{
+ public enum NetworkCommuncation : byte
+ {
+ Hail = 0,
+
+
+ }
+}
diff --git a/BattleBitAPI/Server/GameServer.cs b/BattleBitAPI/Server/GameServer.cs
new file mode 100644
index 0000000..4c4f428
--- /dev/null
+++ b/BattleBitAPI/Server/GameServer.cs
@@ -0,0 +1,215 @@
+using System.Net;
+using System.Net.Sockets;
+using BattleBitAPI.Common.Enums;
+using BattleBitAPI.Common.Extentions;
+using BattleBitAPI.Networking;
+using CommunityServerAPI.BattleBitAPI;
+
+namespace BattleBitAPI.Server
+{
+ public class GameServer
+ {
+ // ---- Public Variables ----
+ public TcpClient Socket { get; private set; }
+
+ ///
+ /// Is game server connected to our server?
+ ///
+ public bool IsConnected { get; private set; }
+ public IPAddress IP { get; private set; }
+ public int Port { get; private set; }
+ public bool IsPasswordProtected { get; private set; }
+ public string ServerName { get; private set; }
+ public string Gamemode { get; private set; }
+ public string Map { get; private set; }
+ public MapSize MapSize { get; private set; }
+ public MapDayNight DayNight { get; private set; }
+ public int CurrentPlayers { get; private set; }
+ public int InQueuePlayers { get; private set; }
+ public int MaxPlayers { get; private set; }
+ public string LoadingScreenText { get; private set; }
+ public string ServerRulesText { get; private set; }
+
+ ///
+ /// Reason why connection was terminated.
+ ///
+ public string TerminationReason { get; private set; }
+
+ // ---- Private Variables ----
+ private byte[] mKeepAliveBuffer;
+ private Common.Serialization.Stream mWriteStream;
+ private Common.Serialization.Stream mReadStream;
+ private uint mReadPackageSize;
+ private long mLastPackageReceived;
+ private long mLastPackageSent;
+
+ // ---- Constrction ----
+ public GameServer(TcpClient socket, IPAddress iP, int port, bool isPasswordProtected, string serverName, string gamemode, string map, MapSize mapSize, MapDayNight dayNight, int currentPlayers, int inQueuePlayers, int maxPlayers, string loadingScreenText, string serverRulesText)
+ {
+ this.IsConnected = true;
+ this.Socket = socket;
+
+ this.IP = iP;
+ this.Port = port;
+ this.IsPasswordProtected = isPasswordProtected;
+ this.ServerName = serverName;
+ this.Gamemode = gamemode;
+ this.Map = map;
+ this.MapSize = mapSize;
+ this.DayNight = dayNight;
+ this.CurrentPlayers = currentPlayers;
+ this.InQueuePlayers = inQueuePlayers;
+ this.MaxPlayers = maxPlayers;
+ this.LoadingScreenText = loadingScreenText;
+ this.ServerRulesText = serverRulesText;
+
+ this.TerminationReason = string.Empty;
+
+ this.mWriteStream = new Common.Serialization.Stream()
+ {
+ Buffer = new byte[Const.MaxNetworkPackageSize],
+ InPool = false,
+ ReadPosition = 0,
+ WritePosition = 0,
+ };
+ this.mReadStream = new Common.Serialization.Stream()
+ {
+ Buffer = new byte[Const.MaxNetworkPackageSize],
+ InPool = false,
+ ReadPosition = 0,
+ WritePosition = 0,
+ };
+ this.mKeepAliveBuffer = new byte[4]
+ {
+ 0,0,0,0,
+ };
+ }
+
+ // ---- Tick ----
+ public async Task Tick()
+ {
+ if (!this.IsConnected)
+ return;
+
+ try
+ {
+ //Are we still connected on socket level?
+ if (!Socket.Connected)
+ {
+ mClose("Connection was terminated.");
+ return;
+ }
+
+ var networkStream = Socket.GetStream();
+
+ //Read network packages.
+ while (Socket.Available > 0)
+ {
+ this.mLastPackageReceived = Extentions.TickCount;
+
+ //Do we know the package size?
+ if (this.mReadPackageSize == 0)
+ {
+ const int sizeToRead = 4;
+ int leftSizeToRead = sizeToRead - this.mReadStream.WritePosition;
+
+ int read = await networkStream.ReadAsync(this.mReadStream.Buffer, this.mReadStream.WritePosition, leftSizeToRead);
+ if (read <= 0)
+ throw new Exception("Connection was terminated.");
+
+ this.mReadStream.WritePosition += read;
+
+ //Did we receive the package?
+ if (this.mReadStream.WritePosition >= 4)
+ {
+ //Read the package size
+ this.mReadPackageSize = this.mReadStream.ReadUInt32();
+
+ if (this.mReadPackageSize > Const.MaxNetworkPackageSize)
+ throw new Exception("Incoming package was larger than 'Conts.MaxNetworkPackageSize'");
+
+ //Reset the stream.
+ this.mReadStream.Reset();
+ }
+ }
+ else
+ {
+ int sizeToRead = (int)mReadPackageSize;
+ int leftSizeToRead = sizeToRead - this.mReadStream.WritePosition;
+
+ int read = await networkStream.ReadAsync(this.mReadStream.Buffer, this.mReadStream.WritePosition, leftSizeToRead);
+ if (read <= 0)
+ throw new Exception("Connection was terminated.");
+
+ this.mReadStream.WritePosition += read;
+
+ //Do we have the package?
+ if (this.mReadStream.WritePosition >= mReadPackageSize)
+ {
+ this.mReadPackageSize = 0;
+
+ await mExecutePackage(this.mReadStream);
+
+ //Reset
+ this.mReadStream.Reset();
+ }
+ }
+ }
+
+ //Send the network packages.
+ if (this.mWriteStream.WritePosition > 0)
+ {
+ lock (this.mWriteStream)
+ {
+ if (this.mWriteStream.WritePosition > 0)
+ {
+ networkStream.Write(this.mWriteStream.Buffer, 0, this.mWriteStream.WritePosition);
+ this.mWriteStream.WritePosition = 0;
+
+ this.mLastPackageSent = Extentions.TickCount;
+ }
+ }
+ }
+
+ //Are we timed out?
+ if ((Extentions.TickCount - this.mLastPackageReceived) > Const.NetworkTimeout)
+ throw new Exception("Game server timedout.");
+
+ //Send keep alive if needed
+ if ((Extentions.TickCount - this.mLastPackageSent) > Const.NetworkKeepAlive)
+ {
+ //Send keep alive.
+ networkStream.Write(this.mKeepAliveBuffer, 0, 4);
+
+ this.mLastPackageSent = Extentions.TickCount;
+ }
+ }
+ catch (Exception e)
+ {
+ mClose(e.Message);
+ }
+ }
+
+ // ---- Internal ----
+ private async Task mExecutePackage(Common.Serialization.Stream stream)
+ {
+ var communcation = (NetworkCommuncation)stream.ReadInt8();
+ switch (communcation)
+ {
+
+ }
+ }
+
+ private void mClose(string reason)
+ {
+ if (this.IsConnected)
+ {
+ this.TerminationReason = reason;
+ this.IsConnected = false;
+
+ this.mWriteStream = null;
+ this.mReadStream = null;
+ }
+ }
+ }
+}
diff --git a/BattleBitAPI/Server/ServerListener.cs b/BattleBitAPI/Server/ServerListener.cs
new file mode 100644
index 0000000..967e1cb
--- /dev/null
+++ b/BattleBitAPI/Server/ServerListener.cs
@@ -0,0 +1,344 @@
+using System.Net;
+using System.Net.Sockets;
+using BattleBitAPI.Common.Enums;
+using BattleBitAPI.Common.Extentions;
+using BattleBitAPI.Networking;
+using CommunityServerAPI.BattleBitAPI;
+
+namespace BattleBitAPI.Server
+{
+ public class ServerListener : IDisposable
+ {
+ // --- Public ---
+ public bool IsListening { get; private set; }
+ public bool IsDisposed { get; private set; }
+ public int ListeningPort { get; private set; }
+
+ // --- Events ---
+ ///
+ /// Fired when an attempt made to connect to the server.
+ /// Connection will be allowed if function returns true, otherwise will be blocked.
+ /// Default, any connection attempt will be accepted.
+ ///
+ public Func> OnGameServerConnecting { get; set; }
+
+ ///
+ /// Fired when a game server connects.
+ ///
+ public Func OnGameServerConnected { get; set; }
+ ///
+ /// Fired when a game server disconnects. Check (server.TerminationReason) to see the reason.
+ ///
+ public Func OnGameServerDisconnected { get; set; }
+
+ // --- Private ---
+ private TcpListener mSocket;
+
+ // --- Construction ---
+ public ServerListener() { }
+
+ // --- Starting ---
+ public void Start(IPAddress bindIP, int port)
+ {
+ if (this.IsDisposed)
+ throw new ObjectDisposedException(this.GetType().FullName);
+ if (bindIP == null)
+ throw new ArgumentNullException(nameof(bindIP));
+ if (IsListening)
+ throw new Exception("Server is already listening.");
+
+ this.mSocket = new TcpListener(bindIP, port);
+ this.mSocket.Start();
+
+ this.ListeningPort = port;
+ this.IsListening = true;
+
+ mMainLoop();
+ }
+ public void Start(int port)
+ {
+ Start(IPAddress.Loopback, port);
+ }
+
+ // --- Stopping ---
+ public void Stop()
+ {
+ if (this.IsDisposed)
+ throw new ObjectDisposedException(this.GetType().FullName);
+ if (!IsListening)
+ throw new Exception("Already not running.");
+
+ try
+ {
+ mSocket.Stop();
+ }
+ catch { }
+
+ this.mSocket = null;
+ this.ListeningPort = 0;
+ this.IsListening = true;
+ }
+
+ // --- Main Loop ---
+ private async Task mMainLoop()
+ {
+ while (IsListening)
+ {
+ var client = await mSocket.AcceptTcpClientAsync();
+ mInternalOnClientConnecting(client);
+ }
+ }
+ private async Task mInternalOnClientConnecting(TcpClient client)
+ {
+ var ip = (client.Client.RemoteEndPoint as IPEndPoint).Address;
+
+ bool allow = true;
+ if (OnGameServerConnecting != null)
+ allow = await OnGameServerConnecting(ip);
+
+ if (!allow)
+ {
+ //Connection is not allowed from this IP.
+ client.SafeClose();
+ return;
+ }
+
+ GameServer server = null;
+ try
+ {
+ using (CancellationTokenSource source = new CancellationTokenSource(Const.HailConnectTimeout))
+ {
+ using (var readStream = Common.Serialization.Stream.Get())
+ {
+ var networkStream = client.GetStream();
+
+ //Read package type
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, 1, source.Token))
+ throw new Exception("Unable to read the package type");
+ NetworkCommuncation type = (NetworkCommuncation)readStream.ReadInt8();
+ if (type != NetworkCommuncation.Hail)
+ throw new Exception("Incoming package wasn't hail.");
+ }
+
+ //Read port
+ int gamePort;
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, 2, source.Token))
+ throw new Exception("Unable to read the Port");
+ gamePort = readStream.ReadUInt16();
+ }
+
+ //Read is Port protected
+ bool isPasswordProtected;
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, 1, source.Token))
+ throw new Exception("Unable to read the IsPasswordProtected");
+ isPasswordProtected = readStream.ReadBool();
+ }
+
+ //Read the server name
+ string serverName;
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, 2, source.Token))
+ throw new Exception("Unable to read the ServerName Size");
+
+ int stringSize = readStream.ReadUInt16();
+ if (stringSize < Const.MinServerNameLength || stringSize > Const.MaxServerNameLength)
+ throw new Exception("Invalid server name size");
+
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, stringSize, source.Token))
+ throw new Exception("Unable to read the ServerName");
+
+ serverName = readStream.ReadString(stringSize);
+ }
+
+ //Read the gamemode
+ string gameMode;
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, 2, source.Token))
+ throw new Exception("Unable to read the gamemode Size");
+
+ int stringSize = readStream.ReadUInt16();
+ if (stringSize < Const.MinGamemodeNameLength || stringSize > Const.MaxGamemodeNameLength)
+ throw new Exception("Invalid gamemode size");
+
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, stringSize, source.Token))
+ throw new Exception("Unable to read the gamemode");
+
+ gameMode = readStream.ReadString(stringSize);
+ }
+
+ //Read the gamemap
+ string gamemap;
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, 2, source.Token))
+ throw new Exception("Unable to read the map size");
+
+ int stringSize = readStream.ReadUInt16();
+ if (stringSize < Const.MinMapNameLength || stringSize > Const.MaxMapNameLength)
+ throw new Exception("Invalid map size");
+
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, stringSize, source.Token))
+ throw new Exception("Unable to read the map");
+
+ gamemap = readStream.ReadString(stringSize);
+ }
+
+ //Read the mapSize
+ MapSize size;
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, 1, source.Token))
+ throw new Exception("Unable to read the MapSize");
+ size = (MapSize)readStream.ReadInt8();
+ }
+
+ //Read the day night
+ MapDayNight dayNight;
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, 1, source.Token))
+ throw new Exception("Unable to read the MapDayNight");
+ dayNight = (MapDayNight)readStream.ReadInt8();
+ }
+
+ //Current Players
+ int currentPlayers;
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, 1, source.Token))
+ throw new Exception("Unable to read the Current Players");
+ currentPlayers = readStream.ReadInt8();
+ }
+
+ //Queue Players
+ int queuePlayers;
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, 1, source.Token))
+ throw new Exception("Unable to read the Queue Players");
+ queuePlayers = readStream.ReadInt8();
+ }
+
+ //Max Players
+ int maxPlayers;
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, 1, source.Token))
+ throw new Exception("Unable to read the Max Players");
+ maxPlayers = readStream.ReadInt8();
+ }
+
+ //Read Loading Screen Text
+ string loadingScreenText;
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, 2, source.Token))
+ throw new Exception("Unable to read the Loading Screen Text Size");
+
+ int stringSize = readStream.ReadUInt16();
+ if (stringSize < Const.MinLoadingScreenTextLength || stringSize > Const.MaxLoadingScreenTextLength)
+ throw new Exception("Invalid server Loading Screen Text Size");
+
+ if (stringSize > 0)
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, stringSize, source.Token))
+ throw new Exception("Unable to read the Loading Screen Text");
+
+ loadingScreenText = readStream.ReadString(stringSize);
+ }
+ else
+ {
+ loadingScreenText = string.Empty;
+ }
+ }
+
+ //Read Server Rules Text
+ string serverRulesText;
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, 2, source.Token))
+ throw new Exception("Unable to read the Server Rules Text Size");
+
+ int stringSize = readStream.ReadUInt16();
+ if (stringSize < Const.MinServerRulesTextLength || stringSize > Const.MaxServerRulesTextLength)
+ throw new Exception("Invalid server Server Rules Text Size");
+
+ if (stringSize > 0)
+ {
+ readStream.Reset();
+ if (!await networkStream.TryRead(readStream, stringSize, source.Token))
+ throw new Exception("Unable to read the Server Rules Text");
+
+ serverRulesText = readStream.ReadString(stringSize);
+ }
+ else
+ {
+ serverRulesText = string.Empty;
+ }
+ }
+
+ server = new GameServer(client, ip, gamePort, isPasswordProtected, serverName, gameMode, gamemap, size, dayNight, currentPlayers, queuePlayers, maxPlayers, loadingScreenText, serverRulesText);
+ }
+ }
+ }
+ catch
+ {
+ client.SafeClose();
+ return;
+ }
+
+ //Did server connected successfully?
+ if (server == null)
+ {
+ client.SafeClose();
+ return;
+ }
+
+ //Call the callback.
+ if (OnGameServerConnected != null)
+ await OnGameServerConnected.Invoke(server);
+
+ //Set the buffer sizes.
+ client.ReceiveBufferSize = Const.MaxNetworkPackageSize;
+ client.SendBufferSize = Const.MaxNetworkPackageSize;
+
+ //Join to main server loop.
+ await mHandleGameServer(server);
+ }
+ private async Task mHandleGameServer(GameServer server)
+ {
+ while (server.IsConnected)
+ {
+ await server.Tick();
+ await Task.Delay(1);
+ }
+
+ if (OnGameServerDisconnected != null)
+ await OnGameServerDisconnected.Invoke(server);
+ }
+
+ // --- Disposing ---
+ public void Dispose()
+ {
+ //Already disposed?
+ if (this.IsDisposed)
+ return;
+ this.IsDisposed = true;
+
+ if (IsListening)
+ Stop();
+ }
+ }
+}
diff --git a/CommunityServerAPI.csproj b/CommunityServerAPI.csproj
new file mode 100644
index 0000000..2fb5483
--- /dev/null
+++ b/CommunityServerAPI.csproj
@@ -0,0 +1,11 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ disable
+ True
+
+
+
diff --git a/CommunityServerAPI.sln b/CommunityServerAPI.sln
new file mode 100644
index 0000000..1a7e5a7
--- /dev/null
+++ b/CommunityServerAPI.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.4.33205.214
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityServerAPI", "CommunityServerAPI.csproj", "{787887A1-8AEE-43E4-AF9B-A3883DE04486}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {787887A1-8AEE-43E4-AF9B-A3883DE04486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {787887A1-8AEE-43E4-AF9B-A3883DE04486}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {787887A1-8AEE-43E4-AF9B-A3883DE04486}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {787887A1-8AEE-43E4-AF9B-A3883DE04486}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {107CE7B8-8DB9-4467-AF24-1F22E52469E5}
+ EndGlobalSection
+EndGlobal
diff --git a/Program.cs b/Program.cs
new file mode 100644
index 0000000..3f2aac5
--- /dev/null
+++ b/Program.cs
@@ -0,0 +1,28 @@
+using BattleBitAPI.Server;
+using System.Net;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ ServerListener server = new ServerListener();
+ server.OnGameServerConnecting += OnClientConnecting;
+ server.OnGameServerConnected += OnGameServerConnected;
+ server.OnGameServerDisconnected += OnGameServerDisconnected;
+
+ server.Start(29294);
+ }
+
+ private static async Task OnClientConnecting(IPAddress ip)
+ {
+ return true;
+ }
+ private static async Task OnGameServerConnected(GameServer server)
+ {
+ Console.WriteLine("Server "+server.ServerName+" was connected.");
+ }
+ private static async Task OnGameServerDisconnected(GameServer server)
+ {
+ Console.WriteLine("Server " + server.ServerName + " was disconnected.");
+ }
+}
\ No newline at end of file
diff --git a/bin/Debug/net6.0/CommunityServerAPI.deps.json b/bin/Debug/net6.0/CommunityServerAPI.deps.json
new file mode 100644
index 0000000..d656064
--- /dev/null
+++ b/bin/Debug/net6.0/CommunityServerAPI.deps.json
@@ -0,0 +1,23 @@
+{
+ "runtimeTarget": {
+ "name": ".NETCoreApp,Version=v6.0",
+ "signature": ""
+ },
+ "compilationOptions": {},
+ "targets": {
+ ".NETCoreApp,Version=v6.0": {
+ "CommunityServerAPI/1.0.0": {
+ "runtime": {
+ "CommunityServerAPI.dll": {}
+ }
+ }
+ }
+ },
+ "libraries": {
+ "CommunityServerAPI/1.0.0": {
+ "type": "project",
+ "serviceable": false,
+ "sha512": ""
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/Debug/net6.0/CommunityServerAPI.dll b/bin/Debug/net6.0/CommunityServerAPI.dll
new file mode 100644
index 0000000..d945abc
Binary files /dev/null and b/bin/Debug/net6.0/CommunityServerAPI.dll differ
diff --git a/bin/Debug/net6.0/CommunityServerAPI.exe b/bin/Debug/net6.0/CommunityServerAPI.exe
new file mode 100644
index 0000000..b200a82
Binary files /dev/null and b/bin/Debug/net6.0/CommunityServerAPI.exe differ
diff --git a/bin/Debug/net6.0/CommunityServerAPI.pdb b/bin/Debug/net6.0/CommunityServerAPI.pdb
new file mode 100644
index 0000000..c7a402d
Binary files /dev/null and b/bin/Debug/net6.0/CommunityServerAPI.pdb differ
diff --git a/bin/Debug/net6.0/CommunityServerAPI.runtimeconfig.json b/bin/Debug/net6.0/CommunityServerAPI.runtimeconfig.json
new file mode 100644
index 0000000..4986d16
--- /dev/null
+++ b/bin/Debug/net6.0/CommunityServerAPI.runtimeconfig.json
@@ -0,0 +1,9 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "framework": {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ }
+ }
+}
\ No newline at end of file
diff --git a/obj/CommunityServerAPI.csproj.nuget.dgspec.json b/obj/CommunityServerAPI.csproj.nuget.dgspec.json
new file mode 100644
index 0000000..46f8c21
--- /dev/null
+++ b/obj/CommunityServerAPI.csproj.nuget.dgspec.json
@@ -0,0 +1,63 @@
+{
+ "format": 1,
+ "restore": {
+ "C:\\Projects\\BattleBit\\BattleBitRemastered\\Servers\\CommunityServerAPI\\BattleBit-Community-Server-API\\CommunityServerAPI.csproj": {}
+ },
+ "projects": {
+ "C:\\Projects\\BattleBit\\BattleBitRemastered\\Servers\\CommunityServerAPI\\BattleBit-Community-Server-API\\CommunityServerAPI.csproj": {
+ "version": "1.0.0",
+ "restore": {
+ "projectUniqueName": "C:\\Projects\\BattleBit\\BattleBitRemastered\\Servers\\CommunityServerAPI\\BattleBit-Community-Server-API\\CommunityServerAPI.csproj",
+ "projectName": "CommunityServerAPI",
+ "projectPath": "C:\\Projects\\BattleBit\\BattleBitRemastered\\Servers\\CommunityServerAPI\\BattleBit-Community-Server-API\\CommunityServerAPI.csproj",
+ "packagesPath": "C:\\Users\\okidoki\\.nuget\\packages\\",
+ "outputPath": "C:\\Projects\\BattleBit\\BattleBitRemastered\\Servers\\CommunityServerAPI\\BattleBit-Community-Server-API\\obj\\",
+ "projectStyle": "PackageReference",
+ "configFilePaths": [
+ "C:\\Users\\okidoki\\AppData\\Roaming\\NuGet\\NuGet.Config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
+ ],
+ "originalTargetFrameworks": [
+ "net6.0"
+ ],
+ "sources": {
+ "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
+ "https://api.nuget.org/v3/index.json": {}
+ },
+ "frameworks": {
+ "net6.0": {
+ "targetAlias": "net6.0",
+ "projectReferences": {}
+ }
+ },
+ "warningProperties": {
+ "warnAsError": [
+ "NU1605"
+ ]
+ }
+ },
+ "frameworks": {
+ "net6.0": {
+ "targetAlias": "net6.0",
+ "imports": [
+ "net461",
+ "net462",
+ "net47",
+ "net471",
+ "net472",
+ "net48",
+ "net481"
+ ],
+ "assetTargetFallback": true,
+ "warn": true,
+ "frameworkReferences": {
+ "Microsoft.NETCore.App": {
+ "privateAssets": "all"
+ }
+ },
+ "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\7.0.101\\RuntimeIdentifierGraph.json"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/obj/CommunityServerAPI.csproj.nuget.g.props b/obj/CommunityServerAPI.csproj.nuget.g.props
new file mode 100644
index 0000000..c0ffeaa
--- /dev/null
+++ b/obj/CommunityServerAPI.csproj.nuget.g.props
@@ -0,0 +1,15 @@
+
+
+
+ True
+ NuGet
+ $(MSBuildThisFileDirectory)project.assets.json
+ $(UserProfile)\.nuget\packages\
+ C:\Users\okidoki\.nuget\packages\
+ PackageReference
+ 6.4.0
+
+
+
+
+
\ No newline at end of file
diff --git a/obj/CommunityServerAPI.csproj.nuget.g.targets b/obj/CommunityServerAPI.csproj.nuget.g.targets
new file mode 100644
index 0000000..3dc06ef
--- /dev/null
+++ b/obj/CommunityServerAPI.csproj.nuget.g.targets
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/obj/Debug/net6.0/.NETCoreApp,Version=v6.0.AssemblyAttributes.cs b/obj/Debug/net6.0/.NETCoreApp,Version=v6.0.AssemblyAttributes.cs
new file mode 100644
index 0000000..ed92695
--- /dev/null
+++ b/obj/Debug/net6.0/.NETCoreApp,Version=v6.0.AssemblyAttributes.cs
@@ -0,0 +1,4 @@
+//
+using System;
+using System.Reflection;
+[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
diff --git a/obj/Debug/net6.0/CommunityServerAPI.AssemblyInfo.cs b/obj/Debug/net6.0/CommunityServerAPI.AssemblyInfo.cs
new file mode 100644
index 0000000..25b5ac6
--- /dev/null
+++ b/obj/Debug/net6.0/CommunityServerAPI.AssemblyInfo.cs
@@ -0,0 +1,23 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+using System;
+using System.Reflection;
+
+[assembly: System.Reflection.AssemblyCompanyAttribute("CommunityServerAPI")]
+[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
+[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
+[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
+[assembly: System.Reflection.AssemblyProductAttribute("CommunityServerAPI")]
+[assembly: System.Reflection.AssemblyTitleAttribute("CommunityServerAPI")]
+[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
+
+// Generated by the MSBuild WriteCodeFragment class.
+
diff --git a/obj/Debug/net6.0/CommunityServerAPI.AssemblyInfoInputs.cache b/obj/Debug/net6.0/CommunityServerAPI.AssemblyInfoInputs.cache
new file mode 100644
index 0000000..86235ae
--- /dev/null
+++ b/obj/Debug/net6.0/CommunityServerAPI.AssemblyInfoInputs.cache
@@ -0,0 +1 @@
+21fb1a9498e672664d0dba2f17f71ec14a2f15d4
diff --git a/obj/Debug/net6.0/CommunityServerAPI.GeneratedMSBuildEditorConfig.editorconfig b/obj/Debug/net6.0/CommunityServerAPI.GeneratedMSBuildEditorConfig.editorconfig
new file mode 100644
index 0000000..89f2395
--- /dev/null
+++ b/obj/Debug/net6.0/CommunityServerAPI.GeneratedMSBuildEditorConfig.editorconfig
@@ -0,0 +1,11 @@
+is_global = true
+build_property.TargetFramework = net6.0
+build_property.TargetPlatformMinVersion =
+build_property.UsingMicrosoftNETSdkWeb =
+build_property.ProjectTypeGuids =
+build_property.InvariantGlobalization =
+build_property.PlatformNeutralAssembly =
+build_property.EnforceExtendedAnalyzerRules =
+build_property._SupportedPlatformList = Linux,macOS,Windows
+build_property.RootNamespace = CommunityServerAPI
+build_property.ProjectDir = C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\
diff --git a/obj/Debug/net6.0/CommunityServerAPI.GlobalUsings.g.cs b/obj/Debug/net6.0/CommunityServerAPI.GlobalUsings.g.cs
new file mode 100644
index 0000000..8578f3d
--- /dev/null
+++ b/obj/Debug/net6.0/CommunityServerAPI.GlobalUsings.g.cs
@@ -0,0 +1,8 @@
+//
+global using global::System;
+global using global::System.Collections.Generic;
+global using global::System.IO;
+global using global::System.Linq;
+global using global::System.Net.Http;
+global using global::System.Threading;
+global using global::System.Threading.Tasks;
diff --git a/obj/Debug/net6.0/CommunityServerAPI.assets.cache b/obj/Debug/net6.0/CommunityServerAPI.assets.cache
new file mode 100644
index 0000000..9f9f1cb
Binary files /dev/null and b/obj/Debug/net6.0/CommunityServerAPI.assets.cache differ
diff --git a/obj/Debug/net6.0/CommunityServerAPI.csproj.AssemblyReference.cache b/obj/Debug/net6.0/CommunityServerAPI.csproj.AssemblyReference.cache
new file mode 100644
index 0000000..05f814f
Binary files /dev/null and b/obj/Debug/net6.0/CommunityServerAPI.csproj.AssemblyReference.cache differ
diff --git a/obj/Debug/net6.0/CommunityServerAPI.csproj.CoreCompileInputs.cache b/obj/Debug/net6.0/CommunityServerAPI.csproj.CoreCompileInputs.cache
new file mode 100644
index 0000000..cbca712
--- /dev/null
+++ b/obj/Debug/net6.0/CommunityServerAPI.csproj.CoreCompileInputs.cache
@@ -0,0 +1 @@
+76e36c3de7385f6b24db215b47c9a35739cb1496
diff --git a/obj/Debug/net6.0/CommunityServerAPI.csproj.FileListAbsolute.txt b/obj/Debug/net6.0/CommunityServerAPI.csproj.FileListAbsolute.txt
new file mode 100644
index 0000000..0d5776d
--- /dev/null
+++ b/obj/Debug/net6.0/CommunityServerAPI.csproj.FileListAbsolute.txt
@@ -0,0 +1,30 @@
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\bin\Debug\net6.0\CommunityServerAPI.exe
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\bin\Debug\net6.0\CommunityServerAPI.deps.json
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\bin\Debug\net6.0\CommunityServerAPI.runtimeconfig.json
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\bin\Debug\net6.0\CommunityServerAPI.dll
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\bin\Debug\net6.0\CommunityServerAPI.pdb
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\obj\Debug\net6.0\CommunityServerAPI.csproj.AssemblyReference.cache
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\obj\Debug\net6.0\CommunityServerAPI.GeneratedMSBuildEditorConfig.editorconfig
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\obj\Debug\net6.0\CommunityServerAPI.AssemblyInfoInputs.cache
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\obj\Debug\net6.0\CommunityServerAPI.AssemblyInfo.cs
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\obj\Debug\net6.0\CommunityServerAPI.csproj.CoreCompileInputs.cache
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\obj\Debug\net6.0\CommunityServerAPI.dll
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\obj\Debug\net6.0\refint\CommunityServerAPI.dll
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\obj\Debug\net6.0\CommunityServerAPI.pdb
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\obj\Debug\net6.0\CommunityServerAPI.genruntimeconfig.cache
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\CommunityServerAPI\obj\Debug\net6.0\ref\CommunityServerAPI.dll
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\bin\Debug\net6.0\CommunityServerAPI.exe
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\bin\Debug\net6.0\CommunityServerAPI.deps.json
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\bin\Debug\net6.0\CommunityServerAPI.runtimeconfig.json
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\bin\Debug\net6.0\CommunityServerAPI.dll
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\bin\Debug\net6.0\CommunityServerAPI.pdb
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\obj\Debug\net6.0\CommunityServerAPI.csproj.AssemblyReference.cache
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\obj\Debug\net6.0\CommunityServerAPI.GeneratedMSBuildEditorConfig.editorconfig
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\obj\Debug\net6.0\CommunityServerAPI.AssemblyInfoInputs.cache
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\obj\Debug\net6.0\CommunityServerAPI.AssemblyInfo.cs
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\obj\Debug\net6.0\CommunityServerAPI.csproj.CoreCompileInputs.cache
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\obj\Debug\net6.0\CommunityServerAPI.dll
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\obj\Debug\net6.0\refint\CommunityServerAPI.dll
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\obj\Debug\net6.0\CommunityServerAPI.pdb
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\obj\Debug\net6.0\CommunityServerAPI.genruntimeconfig.cache
+C:\Projects\BattleBit\BattleBitRemastered\Servers\CommunityServerAPI\BattleBit-Community-Server-API\obj\Debug\net6.0\ref\CommunityServerAPI.dll
diff --git a/obj/Debug/net6.0/CommunityServerAPI.dll b/obj/Debug/net6.0/CommunityServerAPI.dll
new file mode 100644
index 0000000..d945abc
Binary files /dev/null and b/obj/Debug/net6.0/CommunityServerAPI.dll differ
diff --git a/obj/Debug/net6.0/CommunityServerAPI.genruntimeconfig.cache b/obj/Debug/net6.0/CommunityServerAPI.genruntimeconfig.cache
new file mode 100644
index 0000000..73b72f4
--- /dev/null
+++ b/obj/Debug/net6.0/CommunityServerAPI.genruntimeconfig.cache
@@ -0,0 +1 @@
+7bb18fdad0a682ea33c476da54a2e3d1ac669888
diff --git a/obj/Debug/net6.0/CommunityServerAPI.pdb b/obj/Debug/net6.0/CommunityServerAPI.pdb
new file mode 100644
index 0000000..c7a402d
Binary files /dev/null and b/obj/Debug/net6.0/CommunityServerAPI.pdb differ
diff --git a/obj/Debug/net6.0/apphost.exe b/obj/Debug/net6.0/apphost.exe
new file mode 100644
index 0000000..b200a82
Binary files /dev/null and b/obj/Debug/net6.0/apphost.exe differ
diff --git a/obj/Debug/net6.0/ref/CommunityServerAPI.dll b/obj/Debug/net6.0/ref/CommunityServerAPI.dll
new file mode 100644
index 0000000..655a9b6
Binary files /dev/null and b/obj/Debug/net6.0/ref/CommunityServerAPI.dll differ
diff --git a/obj/Debug/net6.0/refint/CommunityServerAPI.dll b/obj/Debug/net6.0/refint/CommunityServerAPI.dll
new file mode 100644
index 0000000..655a9b6
Binary files /dev/null and b/obj/Debug/net6.0/refint/CommunityServerAPI.dll differ
diff --git a/obj/project.assets.json b/obj/project.assets.json
new file mode 100644
index 0000000..5ac13e0
--- /dev/null
+++ b/obj/project.assets.json
@@ -0,0 +1,68 @@
+{
+ "version": 3,
+ "targets": {
+ "net6.0": {}
+ },
+ "libraries": {},
+ "projectFileDependencyGroups": {
+ "net6.0": []
+ },
+ "packageFolders": {
+ "C:\\Users\\okidoki\\.nuget\\packages\\": {}
+ },
+ "project": {
+ "version": "1.0.0",
+ "restore": {
+ "projectUniqueName": "C:\\Projects\\BattleBit\\BattleBitRemastered\\Servers\\CommunityServerAPI\\BattleBit-Community-Server-API\\CommunityServerAPI.csproj",
+ "projectName": "CommunityServerAPI",
+ "projectPath": "C:\\Projects\\BattleBit\\BattleBitRemastered\\Servers\\CommunityServerAPI\\BattleBit-Community-Server-API\\CommunityServerAPI.csproj",
+ "packagesPath": "C:\\Users\\okidoki\\.nuget\\packages\\",
+ "outputPath": "C:\\Projects\\BattleBit\\BattleBitRemastered\\Servers\\CommunityServerAPI\\BattleBit-Community-Server-API\\obj\\",
+ "projectStyle": "PackageReference",
+ "configFilePaths": [
+ "C:\\Users\\okidoki\\AppData\\Roaming\\NuGet\\NuGet.Config",
+ "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
+ ],
+ "originalTargetFrameworks": [
+ "net6.0"
+ ],
+ "sources": {
+ "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
+ "https://api.nuget.org/v3/index.json": {}
+ },
+ "frameworks": {
+ "net6.0": {
+ "targetAlias": "net6.0",
+ "projectReferences": {}
+ }
+ },
+ "warningProperties": {
+ "warnAsError": [
+ "NU1605"
+ ]
+ }
+ },
+ "frameworks": {
+ "net6.0": {
+ "targetAlias": "net6.0",
+ "imports": [
+ "net461",
+ "net462",
+ "net47",
+ "net471",
+ "net472",
+ "net48",
+ "net481"
+ ],
+ "assetTargetFallback": true,
+ "warn": true,
+ "frameworkReferences": {
+ "Microsoft.NETCore.App": {
+ "privateAssets": "all"
+ }
+ },
+ "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\7.0.101\\RuntimeIdentifierGraph.json"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/obj/project.nuget.cache b/obj/project.nuget.cache
new file mode 100644
index 0000000..e3f7341
--- /dev/null
+++ b/obj/project.nuget.cache
@@ -0,0 +1,8 @@
+{
+ "version": 2,
+ "dgSpecHash": "tHrDsfp7Nn2iQbhzfDTWk4twPq5Pi+pgCx3I0zLLSYzA9F0842gK5lxqUvfvU4ZOILIzNQ8CS3k53iBPaAm5CQ==",
+ "success": true,
+ "projectFilePath": "C:\\Projects\\BattleBit\\BattleBitRemastered\\Servers\\CommunityServerAPI\\BattleBit-Community-Server-API\\CommunityServerAPI.csproj",
+ "expectedPackageFiles": [],
+ "logs": []
+}
\ No newline at end of file