]> git.deb.at Git - rhonda/impostor.git/commitdiff
Rename project files
authorAeonLucid <aeonlucid@gmail.com>
Sun, 20 Sep 2020 23:28:19 +0000 (01:28 +0200)
committerAeonLucid <aeonlucid@gmail.com>
Sun, 20 Sep 2020 23:28:19 +0000 (01:28 +0200)
80 files changed:
src/AmongUs.Agent/AmongUs.Agent.vcxproj [deleted file]
src/AmongUs.Agent/AmongUs.Agent.vcxproj.filters [deleted file]
src/AmongUs.Agent/logger.cpp [deleted file]
src/AmongUs.Agent/logger.h [deleted file]
src/AmongUs.Agent/main.cpp [deleted file]
src/AmongUs.Client/AmongUs.Client.csproj [deleted file]
src/AmongUs.Client/Program.cs [deleted file]
src/AmongUs.Server/AmongUs.Server.csproj [deleted file]
src/AmongUs.Server/Data/DisconnectMessages.cs [deleted file]
src/AmongUs.Server/Exceptions/AmongUsException.cs [deleted file]
src/AmongUs.Server/Extensions/ConnectionExtensions.cs [deleted file]
src/AmongUs.Server/Net/Client.cs [deleted file]
src/AmongUs.Server/Net/ClientManager.cs [deleted file]
src/AmongUs.Server/Net/ClientPlayer.cs [deleted file]
src/AmongUs.Server/Net/Game.cs [deleted file]
src/AmongUs.Server/Net/GameManager.cs [deleted file]
src/AmongUs.Server/Net/GameStates.cs [deleted file]
src/AmongUs.Server/Net/Matchmaker.cs [deleted file]
src/AmongUs.Server/Net/Response/Message1DisconnectReason.cs [deleted file]
src/AmongUs.Server/Net/Response/MessageBase.cs [deleted file]
src/AmongUs.Server/Net/Response/MessageFlag.cs [deleted file]
src/AmongUs.Server/Program.cs [deleted file]
src/AmongUs.Shared/AmongUs.Shared.csproj [deleted file]
src/AmongUs.Shared/Innersloth/Data/AlterGameTags.cs [deleted file]
src/AmongUs.Shared/Innersloth/Data/DisconnectReason.cs [deleted file]
src/AmongUs.Shared/Innersloth/Data/GameKeywords.cs [deleted file]
src/AmongUs.Shared/Innersloth/Data/GameStates.cs [deleted file]
src/AmongUs.Shared/Innersloth/Data/LimboStates.cs [deleted file]
src/AmongUs.Shared/Innersloth/Data/RequestFlag.cs [deleted file]
src/AmongUs.Shared/Innersloth/GameCode.cs [deleted file]
src/AmongUs.Shared/Innersloth/GameOptionsData.cs [deleted file]
src/AmongUs.Shared/Innersloth/RegionInfo.cs [deleted file]
src/AmongUs.Shared/Innersloth/ServerInfo.cs [deleted file]
src/AmongUs.Shared/Utils/HexUtils.cs [deleted file]
src/AmongUs.Tests/AmongUs.Tests.csproj [deleted file]
src/AmongUs.Tests/GameCodeTests.cs [deleted file]
src/AmongUs.Tools.Proxy/AmongUs.Tools.Proxy.csproj [deleted file]
src/AmongUs.Tools.Proxy/HexUtils.cs [deleted file]
src/AmongUs.Tools.Proxy/Program.cs [deleted file]
src/AmongUsServer.sln [deleted file]
src/Impostor.Agent/Impostor.Agent.vcxproj [new file with mode: 0644]
src/Impostor.Agent/Impostor.Agent.vcxproj.filters [new file with mode: 0644]
src/Impostor.Agent/logger.cpp [new file with mode: 0644]
src/Impostor.Agent/logger.h [new file with mode: 0644]
src/Impostor.Agent/main.cpp [new file with mode: 0644]
src/Impostor.Client/Impostor.Client.csproj [new file with mode: 0644]
src/Impostor.Client/Program.cs [new file with mode: 0644]
src/Impostor.Server/Data/DisconnectMessages.cs [new file with mode: 0644]
src/Impostor.Server/Exceptions/AmongUsException.cs [new file with mode: 0644]
src/Impostor.Server/Extensions/ConnectionExtensions.cs [new file with mode: 0644]
src/Impostor.Server/Impostor.Server.csproj [new file with mode: 0644]
src/Impostor.Server/Net/Client.cs [new file with mode: 0644]
src/Impostor.Server/Net/ClientManager.cs [new file with mode: 0644]
src/Impostor.Server/Net/ClientPlayer.cs [new file with mode: 0644]
src/Impostor.Server/Net/Game.cs [new file with mode: 0644]
src/Impostor.Server/Net/GameManager.cs [new file with mode: 0644]
src/Impostor.Server/Net/GameStates.cs [new file with mode: 0644]
src/Impostor.Server/Net/Matchmaker.cs [new file with mode: 0644]
src/Impostor.Server/Net/Response/Message1DisconnectReason.cs [new file with mode: 0644]
src/Impostor.Server/Net/Response/MessageBase.cs [new file with mode: 0644]
src/Impostor.Server/Net/Response/MessageFlag.cs [new file with mode: 0644]
src/Impostor.Server/Program.cs [new file with mode: 0644]
src/Impostor.Shared/Impostor.Shared.csproj [new file with mode: 0644]
src/Impostor.Shared/Innersloth/Data/AlterGameTags.cs [new file with mode: 0644]
src/Impostor.Shared/Innersloth/Data/DisconnectReason.cs [new file with mode: 0644]
src/Impostor.Shared/Innersloth/Data/GameKeywords.cs [new file with mode: 0644]
src/Impostor.Shared/Innersloth/Data/GameStates.cs [new file with mode: 0644]
src/Impostor.Shared/Innersloth/Data/LimboStates.cs [new file with mode: 0644]
src/Impostor.Shared/Innersloth/Data/RequestFlag.cs [new file with mode: 0644]
src/Impostor.Shared/Innersloth/GameCode.cs [new file with mode: 0644]
src/Impostor.Shared/Innersloth/GameOptionsData.cs [new file with mode: 0644]
src/Impostor.Shared/Innersloth/RegionInfo.cs [new file with mode: 0644]
src/Impostor.Shared/Innersloth/ServerInfo.cs [new file with mode: 0644]
src/Impostor.Shared/Utils/HexUtils.cs [new file with mode: 0644]
src/Impostor.Tests/GameCodeTests.cs [new file with mode: 0644]
src/Impostor.Tests/Impostor.Tests.csproj [new file with mode: 0644]
src/Impostor.Tools.Proxy/HexUtils.cs [new file with mode: 0644]
src/Impostor.Tools.Proxy/Impostor.Tools.Proxy.csproj [new file with mode: 0644]
src/Impostor.Tools.Proxy/Program.cs [new file with mode: 0644]
src/Impostor.sln [new file with mode: 0644]

diff --git a/src/AmongUs.Agent/AmongUs.Agent.vcxproj b/src/AmongUs.Agent/AmongUs.Agent.vcxproj
deleted file mode 100644 (file)
index 9350e62..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <VCProjectVersion>16.0</VCProjectVersion>
-    <Keyword>Win32Proj</Keyword>
-    <ProjectGuid>{097be795-88e9-4e7b-92f3-f6dddbe3f012}</ProjectGuid>
-    <RootNamespace>AmongUsAgent</RootNamespace>
-    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <PlatformToolset>v142</PlatformToolset>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v142</PlatformToolset>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="Shared">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <OutDir>$(ProjectDir)build\$(Platform)\$(Configuration)\</OutDir>
-    <IntDir>$(ProjectDir)build\$(Platform)\$(Configuration)\Intermediate\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <OutDir>$(ProjectDir)build\$(Platform)\$(Configuration)\</OutDir>
-    <IntDir>$(ProjectDir)build\$(Platform)\$(Configuration)\Intermediate\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <SDLCheck>true</SDLCheck>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <ConformanceMode>true</ConformanceMode>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <ConformanceMode>true</ConformanceMode>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="logger.cpp" />
-    <ClCompile Include="main.cpp" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="logger.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/src/AmongUs.Agent/AmongUs.Agent.vcxproj.filters b/src/AmongUs.Agent/AmongUs.Agent.vcxproj.filters
deleted file mode 100644 (file)
index 85ba1c7..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
-      <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
-      <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
-    </Filter>
-    <Filter Include="Resource Files">
-      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
-      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="main.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="logger.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="logger.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/src/AmongUs.Agent/logger.cpp b/src/AmongUs.Agent/logger.cpp
deleted file mode 100644 (file)
index 4b45c1d..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-#include "logger.h"
-#include <cstdio>
-#include <Windows.h>
-
-HANDLE h_out = nullptr, h_old_out = nullptr;
-HANDLE h_err = nullptr, h_old_err = nullptr;
-HANDLE h_in = nullptr, h_old_in = nullptr;
-
-namespace Logger
-{
-       void Attach()
-       {
-               h_old_out = GetStdHandle(STD_OUTPUT_HANDLE);
-               h_old_err = GetStdHandle(STD_ERROR_HANDLE);
-               h_old_in = GetStdHandle(STD_INPUT_HANDLE);
-
-               AllocConsole() && AttachConsole(GetCurrentProcessId());
-
-               h_out = GetStdHandle(STD_OUTPUT_HANDLE);
-               h_err = GetStdHandle(STD_ERROR_HANDLE);
-               h_in = GetStdHandle(STD_INPUT_HANDLE);
-
-               SetConsoleMode(h_out,
-                       ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
-
-               SetConsoleMode(h_in,
-                       ENABLE_INSERT_MODE | ENABLE_EXTENDED_FLAGS |
-                       ENABLE_PROCESSED_INPUT | ENABLE_QUICK_EDIT_MODE);
-       }
-
-       void Detach()
-       {
-               if (h_out && h_err && h_in) {
-                       FreeConsole();
-
-                       if (h_old_out)
-                       {
-                               SetStdHandle(STD_OUTPUT_HANDLE, h_old_out);
-                       }
-
-                       if (h_old_err)
-                       {
-                               SetStdHandle(STD_ERROR_HANDLE, h_old_err);
-                       }
-
-                       if (h_old_in)
-                       {
-                               SetStdHandle(STD_INPUT_HANDLE, h_old_in);
-                       }
-               }
-       }
-
-       bool Print(const char* fmt, ...)
-       {
-               if (!h_out)
-               {
-                       return false;
-               }
-
-               char buf[1024];
-               va_list va;
-
-               va_start(va, fmt);
-               _vsnprintf_s(buf, 1024, fmt, va);
-               va_end(va);
-
-               return !!WriteConsoleA(h_out, buf, static_cast<DWORD>(strlen(buf)), nullptr, nullptr);
-       }
-
-       char ReadKey()
-       {
-               if (!h_in)
-               {
-                       return -1;
-               }
-
-               auto key = char{ 0 };
-               auto keysread = DWORD{ 0 };
-
-               ReadConsoleA(h_in, &key, 1, &keysread, nullptr);
-
-               return key;
-       }
-};
\ No newline at end of file
diff --git a/src/AmongUs.Agent/logger.h b/src/AmongUs.Agent/logger.h
deleted file mode 100644 (file)
index fc22e15..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-
-namespace Logger
-{
-       void Attach();
-       void Detach();
-       bool Print(const char* fmt, ...);
-       char ReadKey();
-};
\ No newline at end of file
diff --git a/src/AmongUs.Agent/main.cpp b/src/AmongUs.Agent/main.cpp
deleted file mode 100644 (file)
index 40b5ff0..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <Windows.h>
-#include "logger.h"
-
-DWORD WINAPI OnDllAttach(LPVOID base)
-{
-       Logger::Attach();
-       Logger::Print("[AmongUs.Agent] DLL Attached\n");
-
-       FreeLibraryAndExitThread(static_cast<HMODULE>(base), 1);
-}
-
-BOOL WINAPI OnDllDetach()
-{
-       Logger::Print("[AmongUs.Agent] DLL Detached\n");
-       Logger::Detach();
-
-       return true;
-}
-
-BOOL WINAPI DllMain(
-       const _In_      HINSTANCE hinstDll,
-       const _In_      DWORD fdwReason,
-       const _In_opt_  LPVOID lpvReserved
-)
-{
-       switch (fdwReason)
-       {
-       case DLL_PROCESS_ATTACH:
-               DisableThreadLibraryCalls(hinstDll);
-               CreateThread(nullptr, 0, OnDllAttach, hinstDll, 0, nullptr);
-               return true;
-
-       case DLL_PROCESS_DETACH:
-               if (lpvReserved == nullptr)
-                       return OnDllDetach();
-               return true;
-       default:
-               return true;
-       }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Client/AmongUs.Client.csproj b/src/AmongUs.Client/AmongUs.Client.csproj
deleted file mode 100644 (file)
index be6c4f5..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <OutputType>Exe</OutputType>
-        <TargetFramework>netcoreapp3.1</TargetFramework>
-    </PropertyGroup>
-
-    <ItemGroup>
-      <ProjectReference Include="..\AmongUs.Shared\AmongUs.Shared.csproj" />
-    </ItemGroup>
-
-</Project>
diff --git a/src/AmongUs.Client/Program.cs b/src/AmongUs.Client/Program.cs
deleted file mode 100644 (file)
index a643609..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-using System;
-using System.IO;
-using AmongUs.Shared.Innersloth;
-
-namespace AmongUs.Client
-{
-    internal static class Program
-    {
-        private static void Main(string[] args)
-        {
-            var appData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "..\\LocalLow");
-            var regionFile = Path.Combine(appData, "Innersloth", "Among Us", "regionInfo.dat");
-            var region = new RegionInfo("Private", "192.168.1.211", new []
-            {
-                new ServerInfo("Private-Master-1", "192.168.1.211", 22023)
-            });
-            
-            using (var file = File.Open(regionFile, FileMode.Create, FileAccess.Write))
-            using (var writer = new BinaryWriter(file))
-            {
-                region.Serialize(writer);
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Server/AmongUs.Server.csproj b/src/AmongUs.Server/AmongUs.Server.csproj
deleted file mode 100644 (file)
index 77f0970..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <OutputType>Exe</OutputType>
-        <TargetFramework>netcoreapp3.1</TargetFramework>
-    </PropertyGroup>
-
-    <ItemGroup>
-      <ProjectReference Include="..\..\submodules\Hazel-Networking\Hazel\Hazel.csproj" />
-      <ProjectReference Include="..\AmongUs.Shared\AmongUs.Shared.csproj" />
-    </ItemGroup>
-
-    <ItemGroup>
-      <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
-    </ItemGroup>
-
-</Project>
diff --git a/src/AmongUs.Server/Data/DisconnectMessages.cs b/src/AmongUs.Server/Data/DisconnectMessages.cs
deleted file mode 100644 (file)
index ab3be88..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace AmongUs.Server.Data
-{
-    public static class DisconnectMessages
-    {
-        public const string Error = "There was an internal server error. " +
-                                    "Check the server console for more information. " +
-                                    "Please report the issue on the AmongUsServer GitHub if it keeps happening.";
-
-        public const string Destroyed = "The game you tried to join is being destroyed. " +
-                                        "Please create a new game.";
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Server/Exceptions/AmongUsException.cs b/src/AmongUs.Server/Exceptions/AmongUsException.cs
deleted file mode 100644 (file)
index 1009b87..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace AmongUs.Server.Exceptions
-{
-    public class AmongUsException : Exception
-    {
-        public AmongUsException()
-        {
-        }
-
-        protected AmongUsException(SerializationInfo info, StreamingContext context) : base(info, context)
-        {
-        }
-
-        public AmongUsException(string? message) : base(message)
-        {
-        }
-
-        public AmongUsException(string? message, Exception? innerException) : base(message, innerException)
-        {
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Server/Extensions/ConnectionExtensions.cs b/src/AmongUs.Server/Extensions/ConnectionExtensions.cs
deleted file mode 100644 (file)
index 63bb31c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-using AmongUs.Server.Net.Response;
-using Hazel;
-
-namespace AmongUs.Server.Extensions
-{
-    internal static class ConnectionExtensions
-    {
-        public static void Send(this Connection connection, MessageBase message)
-        {
-            using (message)
-            {
-                connection.Send(message.Write());
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Server/Net/Client.cs b/src/AmongUs.Server/Net/Client.cs
deleted file mode 100644 (file)
index 0596666..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-using System;
-using AmongUs.Server.Data;
-using AmongUs.Server.Extensions;
-using AmongUs.Server.Net.Response;
-using AmongUs.Shared.Innersloth;
-using AmongUs.Shared.Innersloth.Data;
-using Hazel;
-using Serilog;
-using ILogger = Serilog.ILogger;
-
-namespace AmongUs.Server.Net
-{
-    public class Client
-    {
-        private static readonly ILogger Logger = Log.ForContext<Client>();
-        
-        private readonly ClientManager _clientManager;
-        private readonly GameManager _gameManager;
-
-        public Client(ClientManager clientManager, GameManager gameManager, int id, string name, Connection connection)
-        {
-            _clientManager = clientManager;
-            _gameManager = gameManager;
-            Id = id;
-            Name = name;
-            Connection = connection;
-            Connection.DataReceived += OnDataReceived;
-            Connection.Disconnected += OnDisconnected;
-            Player = new ClientPlayer(this);
-        }
-
-        public int Id { get; }
-        public string Name { get; }
-        public Connection Connection { get; }
-        public ClientPlayer Player { get; }
-
-        public void Send(MessageWriter writer)
-        {
-            Connection.Send(writer);
-        }
-        
-        private bool IsPacketAllowed(MessageReader message, bool hostOnly)
-        {
-            var game = Player.Game;
-            if (game == null)
-            {
-                return false;
-            }
-
-            // GameCode must match code of the current game assigned to the player.
-            if (message.ReadInt32() != game.Code)
-            {
-                return false;
-            }
-            
-            // Some packets should only be sent by the host of the game.
-            if (hostOnly)
-            {
-                if (game.HostId == Id)
-                {
-                    return true;
-                }
-                
-                Logger.Warning("[{0}] Client sent packet only allowed by the host ({1}).", Id, game.HostId);
-                return false;
-            }
-
-            return true;
-        }
-
-        private void OnDataReceived(DataReceivedEventArgs e)
-        {
-            try
-            {
-                while (true)
-                {
-                    if (e.Message.Position >= e.Message.Length)
-                    {
-                        break;
-                    }
-
-                    OnMessageReceived(e.Message.ReadMessage(), e.SendOption);
-                }
-            }
-            catch (Exception ex)
-            {
-                Logger.Error(ex, "Exception caught in client data handler.");
-                Connection.Send(new Message1DisconnectReason(DisconnectReason.Custom, DisconnectMessages.Error));
-            }
-        }
-
-        private void OnMessageReceived(MessageReader message, SendOption sendOption)
-        {
-            var flag = (RequestFlag) message.Tag;
-            
-            Logger.Verbose("[{0}] Server got {1}.", Id, flag);
-            
-            switch (flag)
-            {
-                case RequestFlag.HostGame:
-                {
-                    // Read game settings.
-                    var gameInfoBytes = message.ReadBytesAndSize();
-                    var gameInfo = GameOptionsData.Deserialize(gameInfoBytes);
-                    
-                    // Create game.
-                    var game = _gameManager.Create(this, gameInfo);
-                    if (game == null)
-                    {
-                        Connection.Send(new Message1DisconnectReason(DisconnectReason.ServerFull));
-                        return;
-                    }
-
-                    // Code in the packet below will be used in JoinGame.
-                    using (var writer = MessageWriter.Get(SendOption.Reliable))
-                    {
-                        writer.StartMessage(0);
-                        writer.Write(game.Code);
-                        writer.EndMessage();
-                
-                        Connection.Send(writer);
-                    }
-                    break;
-                }
-                
-                case RequestFlag.JoinGame:
-                {
-                    var gameCode = message.ReadInt32();
-                    var unknown = message.ReadByte();
-                    var game = _gameManager.Find(gameCode);
-                    if (game == null)
-                    {
-                        Connection.Send(new Message1DisconnectReason(DisconnectReason.GameMissing));
-                        return;
-                    }
-
-                    game.HandleJoinGame(Player);
-                    break;
-                }
-
-                case RequestFlag.StartGame:
-                {
-                    if (!IsPacketAllowed(message, true))
-                    {
-                        return;
-                    }
-
-                    Player.Game.HandleStartGame(message);
-                    break;
-                }
-                
-                // No idea how this flag is triggered.
-                case RequestFlag.RemoveGame:
-                    break;
-                
-                case RequestFlag.RemovePlayer:
-                {
-                    if (!IsPacketAllowed(message, true))
-                    {
-                        return;
-                    }
-
-                    var playerId = message.ReadPackedInt32();
-                    var reason = message.ReadByte();
-
-                    Player.Game.HandleRemovePlayer(playerId, (DisconnectReason) reason);
-                    break;
-                }
-                
-                case RequestFlag.GameData:
-                case RequestFlag.GameDataTo:
-                {
-                    if (!IsPacketAllowed(message, false))
-                    {
-                        return;
-                    }
-
-                    // Broadcast packet to all other players.
-                    using (var writer = MessageWriter.Get(sendOption))
-                    {
-                        if (flag == RequestFlag.GameDataTo)
-                        {
-                            var target = message.ReadPackedInt32();
-                            writer.CopyFrom(message);
-                            Player.Game.SendTo(writer, target);
-                        }
-                        else
-                        {
-                            writer.CopyFrom(message);
-                            Player.Game.SendToAllExcept(writer, Player);
-                        }
-                    }
-                    break;
-                }
-                
-                case RequestFlag.EndGame:
-                {
-                    if (!IsPacketAllowed(message, true))
-                    {
-                        return;
-                    }
-
-                    Player.Game.HandleEndGame(message);
-                    break;
-                }
-
-                case RequestFlag.AlterGame:
-                {
-                    if (!IsPacketAllowed(message, true))
-                    {
-                        return;
-                    }
-
-                    if (message.ReadByte() != (byte) AlterGameTags.ChangePrivacy)
-                    {
-                        return;
-                    }
-
-                    var isPublic = message.ReadByte() == 1;
-                    
-                    Player.Game.HandleAlterGame(message, Player, isPublic);
-                    break;
-                }
-
-                case RequestFlag.KickPlayer:
-                {
-                    if (!IsPacketAllowed(message, true))
-                    {
-                        return;
-                    }
-
-                    var playerId = message.ReadPackedInt32();
-                    var isBan = message.ReadBoolean();
-
-                    Player.Game.HandleKickPlayer(playerId, isBan);
-                    break;
-                }
-                
-                default:
-                    Logger.Warning("Server received unknown flag {0}.", flag);
-                    break;
-            }
-
-            if (flag != RequestFlag.GameData &&
-                flag != RequestFlag.GameDataTo &&
-                flag != RequestFlag.EndGame &&
-                message.Position < message.Length)
-            {
-                Logger.Warning("Server did not consume all bytes from {0} ({1} < {2}).", 
-                    flag, 
-                    message.Position, 
-                    message.Length);
-            }
-        }
-        
-        private void OnDisconnected(object sender, DisconnectedEventArgs e)
-        {
-            try
-            {
-                if (Player.Game != null)
-                {
-                    Player.Game.HandleRemovePlayer(Id, DisconnectReason.ExitGame);
-                }
-            }
-            catch (Exception ex)
-            {
-                Logger.Error(ex, "Exception caught in client disconnection.");
-            }
-
-            _clientManager.Remove(this);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Server/Net/ClientManager.cs b/src/AmongUs.Server/Net/ClientManager.cs
deleted file mode 100644 (file)
index 9a3cb7b..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-using System.Collections.Concurrent;
-using AmongUs.Server.Exceptions;
-using Serilog;
-
-namespace AmongUs.Server.Net
-{
-    public class ClientManager
-    {
-        private static readonly ILogger Logger = Log.ForContext<ClientManager>();
-        
-        private readonly ConcurrentDictionary<int, Client> _clients;
-        private readonly object _idLock;
-        private int _idLast;
-        
-        public ClientManager()
-        {
-            _clients = new ConcurrentDictionary<int, Client>();
-            _idLock = new object();
-            _idLast = 0;
-        }
-
-        // No idea what a good way for this is.
-        public int NextId()
-        {
-            lock (_idLock)
-            {
-                // 3 Attempts.
-                for (var i = 0; i < 3; i++)
-                {
-                    // It is important that ids start from 1, a 0 id causes issues.
-                    var result = ++_idLast;
-
-                    if (_idLast == int.MaxValue)
-                    {
-                        _idLast = 0;
-                    }
-
-                    if (_clients.ContainsKey(_idLast))
-                    {
-                        continue;
-                    }
-            
-                    return result;
-                }
-                
-                throw new AmongUsException("Unable to generate a client id.");
-            }
-        }
-        
-        public void Add(Client client)
-        {
-            Logger.Information("Client connected.");
-
-            _clients.TryAdd(client.Id, client);
-        }
-
-        public void Remove(Client client)
-        {
-            Logger.Information("Client disconnected.");
-
-            _clients.TryRemove(client.Id, out _);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Server/Net/ClientPlayer.cs b/src/AmongUs.Server/Net/ClientPlayer.cs
deleted file mode 100644 (file)
index 1b9322c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-using AmongUs.Shared.Innersloth.Data;
-
-namespace AmongUs.Server.Net
-{
-    public class ClientPlayer
-    {
-        public ClientPlayer(Client client)
-        {
-            Client = client;
-        }
-        
-        public Client Client { get; }
-        public Game Game { get; set; }
-        public LimboStates LimboState { get; set; }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Server/Net/Game.cs b/src/AmongUs.Server/Net/Game.cs
deleted file mode 100644 (file)
index 723280c..0000000
+++ /dev/null
@@ -1,387 +0,0 @@
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net;
-using AmongUs.Server.Data;
-using AmongUs.Server.Exceptions;
-using AmongUs.Server.Extensions;
-using AmongUs.Server.Net.Response;
-using AmongUs.Shared.Innersloth;
-using AmongUs.Shared.Innersloth.Data;
-using Hazel;
-using Serilog;
-using ILogger = Serilog.ILogger;
-
-namespace AmongUs.Server.Net
-{
-    public class Game
-    {
-        private static readonly ILogger Logger = Log.ForContext<Game>();
-        
-        private readonly GameManager _gameManager;
-        private readonly ConcurrentDictionary<int, ClientPlayer> _players;
-        private readonly HashSet<IPAddress> _bannedIps;
-
-        public Game(GameManager gameManager, int code, GameOptionsData options)
-        {
-            _gameManager = gameManager;
-            _players = new ConcurrentDictionary<int, ClientPlayer>();
-            _bannedIps = new HashSet<IPAddress>();
-            
-            Code = code;
-            CodeStr = GameCode.IntToGameName(code);
-            HostId = -1;
-            GameState = GameStates.NotStarted;
-            Options = options;
-        }
-        
-        public int Code { get; }
-        public string CodeStr { get; }
-        public bool IsPublic { get; private set; }
-        public int HostId { get; private set; }
-        public GameStates GameState { get; private set; }
-        public GameOptionsData Options { get; }
-
-        public void SendToAllExcept(MessageWriter message, ClientPlayer sender)
-        {
-            foreach (var (_, player) in _players.Where(x => x.Value != sender))
-            {
-                if (player.Client.Connection.State != ConnectionState.Connected)
-                {
-                    Logger.Warning("[{0}] Tried to sent data to a disconnected player ({1}).", sender?.Client.Id, player.Client.Id);
-                    continue;
-                }
-                
-                player.Client.Send(message);
-            }
-        }
-
-        public void SendTo(MessageWriter message, int playerId)
-        {
-            if (_players.TryGetValue(playerId, out var player))
-            {
-                if (player.Client.Connection.State != ConnectionState.Connected)
-                {
-                    Logger.Warning("[{0}] Sending data to {1} failed, player is not connected.", CodeStr, player.Client.Id);
-                    return;
-                }
-                
-                player.Client.Send(message);
-            }
-            else
-            {
-                Logger.Warning("[{0}] Sending data to {1} failed, player does not exist.", CodeStr, playerId);
-            }
-        }
-
-        public void HandleStartGame(MessageReader message)
-        {
-            GameState = GameStates.Started;
-            
-            using (var packet = MessageWriter.Get(SendOption.Reliable))
-            {
-                packet.CopyFrom(message);
-                SendToAllExcept(packet, null);
-            }
-        }
-
-        public void HandleJoinGame(ClientPlayer sender)
-        {
-            if (_bannedIps.Contains(sender.Client.Connection.EndPoint.Address))
-            {
-                sender.Client.Connection.Send(new Message1DisconnectReason(DisconnectReason.Banned));
-                return;
-            }
-            
-            switch (GameState)
-            {
-                case GameStates.NotStarted:
-                    HandleJoinGameNew(sender);
-                    break;
-                case GameStates.Ended:
-                    HandleJoinGameNext(sender);
-                    break;
-                case GameStates.Started:
-                    sender.Client.Connection.Send(new Message1DisconnectReason(DisconnectReason.GameStarted));
-                    return;
-                case GameStates.Destroyed:
-                    sender.Client.Connection.Send(new Message1DisconnectReason(DisconnectReason.Custom, DisconnectMessages.Destroyed));
-                    return;
-                default:
-                    throw new ArgumentOutOfRangeException();
-            }
-        }
-
-        public void HandleEndGame(MessageReader message)
-        {
-            GameState = GameStates.Ended;
-            
-            // Broadcast end of the game.
-            using (var packet = MessageWriter.Get(SendOption.Reliable))
-            {
-                packet.CopyFrom(message);
-                SendToAllExcept(packet, null);
-            }
-            
-            // Remove all players from this game.
-            foreach (var player in _players)
-            {
-                player.Value.Game = null;
-            }
-            
-            _players.Clear();
-        }
-
-        public void HandleAlterGame(MessageReader message, ClientPlayer sender, bool isPublic)
-        {
-            IsPublic = isPublic;
-            
-            using (var packet = MessageWriter.Get(SendOption.Reliable))
-            {
-                packet.CopyFrom(message);
-                SendToAllExcept(packet, sender);
-            }
-        }
-        
-        public void HandleRemovePlayer(int playerId, DisconnectReason reason)
-        {
-            if (_players.TryRemove(playerId, out var player))
-            {
-                player.Game = null;
-            }
-            
-            Logger.Information("{0} - Player {1} ({2}) has left.", CodeStr, player?.Client.Name, playerId);
-
-            // Game is empty, remove it.
-            if (_players.Count == 0)
-            {
-                GameState = GameStates.Destroyed;
-
-                // Remove instance reference.
-                _gameManager.Remove(Code);
-                return;
-            }
-
-            // Host migration.
-            if (HostId == playerId)
-            {
-                var newHost = _players.First().Value;
-                HostId = newHost.Client.Id;
-                Logger.Information("{0} - Assigned {1} ({2}) as new host.", CodeStr, newHost.Client.Name, newHost.Client.Id);
-            }
-
-            using (var packet = MessageWriter.Get(SendOption.Reliable))
-            {
-                WriteRemovePlayerMessage(packet, false, playerId, reason);
-                SendToAllExcept(packet, player);
-            }
-        }
-
-        public void HandleKickPlayer(int playerId, bool isBan)
-        {
-            _players.TryGetValue(playerId, out var p);
-            Logger.Information("{0} - Player {1} ({2}) has left.", CodeStr, p?.Client.Name, playerId);
-            
-            using (var message = MessageWriter.Get(SendOption.Reliable))
-            {
-                WriteKickPlayerMessage(message, false, playerId, isBan);
-                SendToAllExcept(message, null);
-                
-                if (_players.TryRemove(playerId, out var player))
-                {
-                    player.Game = null;
-
-                    if (isBan)
-                    {
-                        _bannedIps.Add(player.Client.Connection.EndPoint.Address);
-                    }
-                }
-                
-                WriteRemovePlayerMessage(message, true, playerId, isBan 
-                    ? DisconnectReason.Banned 
-                    : DisconnectReason.Kicked);
-                SendToAllExcept(message, player);
-            }
-        }
-        
-        private void HandleJoinGameNew(ClientPlayer sender)
-        {
-            Logger.Information("{0} - Player {1} ({2}) is joining.", CodeStr, sender.Client.Name, sender.Client.Id);
-            
-            // Store player.
-            if (!_players.TryAdd(sender.Client.Id, sender))
-            {
-                throw new AmongUsException("Failed to add player to game.");
-            }
-            
-            // Assign player to this game for future packets.
-            sender.Game = this;
-
-            // Assign hostId if none is set.
-            if (HostId == -1)
-            {
-                HostId = sender.Client.Id;
-            }
-
-            if (HostId == sender.Client.Id)
-            {
-                sender.LimboState = LimboStates.NotLimbo;
-            }
-
-            using (var message = MessageWriter.Get(SendOption.Reliable))
-            {
-                WriteJoinedGameMessage(message, false, sender);
-                WriteAlterGameMessage(message, false);
-                
-                sender.Client.Send(message);
-
-                BroadcastJoinMessage(message, true, sender);
-            }
-        }
-
-        private void HandleJoinGameNext(ClientPlayer sender)
-        {
-            Logger.Information("{0} - Player {1} ({2}) is rejoining.", CodeStr, sender.Client.Name, sender.Client.Id);
-            
-            if (sender.Client.Id == HostId)
-            {
-                GameState = GameStates.NotStarted;
-                HandleJoinGameNew(sender);
-
-                using (var message = MessageWriter.Get(SendOption.Reliable))
-                {
-                    foreach (var (_, player) in _players.Where(x => x.Value != sender))
-                    {
-                        WriteJoinedGameMessage(message, true, player);
-                        WriteAlterGameMessage(message, false);
-                        player.Client.Send(message);
-                    }
-                }
-                
-                return;
-            }
-
-            if (_players.Count >= 9)
-            {
-                sender.Client.Connection.Send(new Message1DisconnectReason(DisconnectReason.GameFull));
-                return;
-            }
-
-            // Store player.
-            if (!_players.TryAdd(sender.Client.Id, sender))
-            {
-                throw new AmongUsException("Failed to add player to game.");
-            }
-            
-            // Assign player to this game for future packets.
-            sender.Game = this;
-            
-            // Limbo, yes.
-            sender.LimboState = LimboStates.WaitingForHost;
-
-            using (var packet = MessageWriter.Get(SendOption.Reliable))
-            {
-                WriteWaitForHostMessage(packet, false, sender);
-                sender.Client.Send(packet);
-
-                BroadcastJoinMessage(packet, true, sender);
-            }
-        }
-
-        private void WriteRemovePlayerMessage(MessageWriter message, bool clear, int playerId, DisconnectReason reason)
-        {
-            // Only a subset of DisconnectReason shows an unique message.
-            // ExitGame, Banned and Kicked.
-            if (clear)
-            {
-                message.Clear(SendOption.Reliable);
-            }
-            
-            message.StartMessage((byte) RequestFlag.RemovePlayer);
-            message.Write(Code);
-            message.Write(playerId);
-            message.Write(HostId);
-            message.Write((byte) reason);
-            message.EndMessage();
-        }
-        
-        private void WriteJoinedGameMessage(MessageWriter message, bool clear, ClientPlayer player)
-        {
-            if (clear)
-            {
-                message.Clear(SendOption.Reliable);
-            }
-            
-            message.StartMessage((byte) RequestFlag.JoinedGame);
-            message.Write(Code);
-            message.Write(player.Client.Id);
-            message.Write(HostId);
-            message.WritePacked(_players.Count - 1);
-            
-            foreach (var (_, p) in _players.Where(x => x.Value != player))
-            {
-                message.WritePacked(p.Client.Id);
-            }
-            
-            message.EndMessage();
-        }
-
-        private void WriteAlterGameMessage(MessageWriter message, bool clear)
-        {
-            if (clear)
-            {
-                message.Clear(SendOption.Reliable);
-            }
-            
-            message.StartMessage((byte) RequestFlag.AlterGame);
-            message.Write(Code);
-            message.Write((byte) AlterGameTags.ChangePrivacy);
-            message.Write(IsPublic);
-            message.EndMessage();
-        }
-
-        private void WriteKickPlayerMessage(MessageWriter message, bool clear, int playerId, bool isBan)
-        {
-            if (clear)
-            {
-                message.Clear(SendOption.Reliable);
-            }
-            
-            message.StartMessage((byte) RequestFlag.KickPlayer);
-            message.Write(Code);
-            message.WritePacked(playerId);
-            message.Write(isBan);
-            message.EndMessage();
-        }
-        
-        private void WriteWaitForHostMessage(MessageWriter message, bool clear, ClientPlayer player)
-        {
-            if (clear)
-            {
-                message.Clear(SendOption.Reliable);
-            }
-            
-            message.StartMessage((byte) RequestFlag.WaitForHost);
-            message.Write(Code);
-            message.Write(player.Client.Id);
-            message.EndMessage();
-        }
-        
-        private void BroadcastJoinMessage(MessageWriter message, bool clear, ClientPlayer player)
-        {
-            if (clear)
-            {
-                message.Clear(SendOption.Reliable);
-            }
-            
-            message.StartMessage((byte) RequestFlag.JoinGame);
-            message.Write(Code);
-            message.Write(player.Client.Id);
-            message.Write(HostId);
-            message.EndMessage();
-            
-            SendToAllExcept(message, player);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Server/Net/GameManager.cs b/src/AmongUs.Server/Net/GameManager.cs
deleted file mode 100644 (file)
index 100e146..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-using System.Collections.Concurrent;
-using AmongUs.Shared.Innersloth;
-using Serilog;
-
-namespace AmongUs.Server.Net
-{
-    public class GameManager
-    {
-        private static readonly ILogger Logger = Log.ForContext<GameManager>();
-        
-        private readonly ConcurrentDictionary<int, Game> _games;
-
-        public GameManager()
-        {
-            _games = new ConcurrentDictionary<int, Game>();
-        }
-        
-        public Game Create(Client owner, GameOptionsData options)
-        {
-            var gameCode = GameCode.GenerateCode(6);
-            var game = new Game(this, gameCode, options);
-
-            if (_games.TryAdd(gameCode, game))
-            {
-                Logger.Debug("Created game with code {0} ({1}).", GameCode.IntToGameName(gameCode), gameCode);        
-                return game;
-            }
-
-            Logger.Warning("Failed to create game.");
-            return null;
-        }
-
-        public Game Find(int gameCode)
-        {
-            _games.TryGetValue(gameCode, out var game);
-            return game;
-        }
-
-        public void Remove(int gameCode)
-        {
-            Logger.Debug("Remove game with code {0} ({1}).", GameCode.IntToGameName(gameCode), gameCode);   
-            _games.TryRemove(gameCode, out _);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Server/Net/GameStates.cs b/src/AmongUs.Server/Net/GameStates.cs
deleted file mode 100644 (file)
index a50e9e3..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace AmongUs.Server.Net
-{
-    public enum GameStates : byte
-    {
-        NotStarted = 0,
-        Started = 1,
-        Ended = 2,
-        Destroyed = 3
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Server/Net/Matchmaker.cs b/src/AmongUs.Server/Net/Matchmaker.cs
deleted file mode 100644 (file)
index 5c2dc77..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-using System.Net;
-using AmongUs.Server.Extensions;
-using AmongUs.Server.Net.Response;
-using AmongUs.Shared.Innersloth.Data;
-using Hazel;
-using Hazel.Udp;
-using Serilog;
-using ILogger = Serilog.ILogger;
-
-namespace AmongUs.Server.Net
-{
-    public class Matchmaker
-    {
-        private static readonly ILogger Logger = Log.ForContext<Matchmaker>();
-
-        private readonly GameManager _gameManager;
-        private readonly ClientManager _clientManager;
-        private readonly UdpConnectionListener _connection;
-        
-        public Matchmaker(IPAddress ip, int port)
-        {
-            _gameManager = new GameManager();
-            _clientManager = new ClientManager();
-            _connection = new UdpConnectionListener(new IPEndPoint(ip, port), IPMode.IPv4, s =>
-            {
-                Logger.Warning("Log from Hazel: {0}", s);
-            });
-            
-            _connection.NewConnection += OnNewConnection;
-        }
-
-        private void OnNewConnection(NewConnectionEventArgs e)
-        {
-            // Handshake.
-            var clientVersion = e.HandshakeData.ReadInt32();
-            var clientName = e.HandshakeData.ReadString();
-
-            e.HandshakeData.Recycle();
-                
-            if (clientVersion != 50516550)
-            {
-                e.Connection.Send(new Message1DisconnectReason(DisconnectReason.IncorrectVersion));
-                return;
-            }
-            
-            // Register client.
-            _clientManager.Add(new Client(_clientManager, _gameManager, _clientManager.NextId(), clientName, e.Connection));
-        }
-
-        public void Start()
-        {
-            _connection.Start();
-        }
-
-        public void Stop()
-        {
-            _connection.Dispose();
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Server/Net/Response/Message1DisconnectReason.cs b/src/AmongUs.Server/Net/Response/Message1DisconnectReason.cs
deleted file mode 100644 (file)
index 86362aa..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-using AmongUs.Shared.Innersloth.Data;
-using Hazel;
-
-namespace AmongUs.Server.Net.Response
-{
-    public class Message1DisconnectReason : MessageBase
-    {
-        private readonly DisconnectReason _reason;
-        private readonly string _message;
-
-        // Notes:
-        // - Specifying no reason does something with ban minutes left.
-        // - (?) You were disconnected because Among Us was suspended by another app.
-        public Message1DisconnectReason(DisconnectReason reason, string message = null) : base(SendOption.Reliable, MessageFlag.DisconnectReason)
-        {
-            _reason = reason;
-            _message = message;
-        }
-
-        protected override void WriteMessage(MessageWriter writer)
-        {
-            writer.Write((int) _reason);
-
-            if (_reason == DisconnectReason.Custom)
-            {
-                writer.Write(_message);
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Server/Net/Response/MessageBase.cs b/src/AmongUs.Server/Net/Response/MessageBase.cs
deleted file mode 100644 (file)
index dd18790..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-using System;
-using Hazel;
-
-namespace AmongUs.Server.Net.Response
-{
-    public abstract class MessageBase : IDisposable
-    {
-        private readonly MessageWriter _writer;
-        private readonly MessageFlag _flag;
-
-        protected MessageBase(SendOption option, MessageFlag flag)
-        {
-            _writer = MessageWriter.Get(option);
-            _flag = flag;
-        }
-
-        public MessageWriter Write()
-        {
-            _writer.StartMessage((byte) _flag);
-            WriteMessage(_writer);
-            _writer.EndMessage();
-            return _writer;
-        }
-
-        protected abstract void WriteMessage(MessageWriter writer);
-
-        public void Dispose()
-        {
-            _writer.Dispose();
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Server/Net/Response/MessageFlag.cs b/src/AmongUs.Server/Net/Response/MessageFlag.cs
deleted file mode 100644 (file)
index 68cbe4b..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace AmongUs.Server.Net.Response
-{
-    public enum MessageFlag : byte
-    {
-        DisconnectReason = 1
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Server/Program.cs b/src/AmongUs.Server/Program.cs
deleted file mode 100644 (file)
index 7857696..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-using System;
-using System.Net;
-using System.Threading;
-using AmongUs.Server.Net;
-using Serilog;
-
-namespace AmongUs.Server
-{
-    internal static class Program
-    {
-        private static readonly ManualResetEvent QuitEvent = new ManualResetEvent(false);
-        
-        private static void Main(string[] args)
-        {
-            // Listen for CTRL+C.
-            Console.CancelKeyPress += (sender, e) =>
-            {
-                e.Cancel = true;
-                QuitEvent.Set();
-            };
-            
-            // Configure logger.
-            Log.Logger = new LoggerConfiguration()
-#if DEBUG
-                .MinimumLevel.Verbose()
-#else
-                .MinimumLevel.Information()
-#endif
-                .WriteTo.Console()
-                .CreateLogger();
-
-            // Initialize matchmaker.
-            var matchMaker = new Matchmaker(IPAddress.Any, 22023);
-            matchMaker.Start();
-            Log.Logger.Information("Matchmaker is running on *:22023.");
-            QuitEvent.WaitOne();
-            Log.Logger.Warning("Matchmaker is shutting down!");
-            matchMaker.Stop();
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Shared/AmongUs.Shared.csproj b/src/AmongUs.Shared/AmongUs.Shared.csproj
deleted file mode 100644 (file)
index 8642d92..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <TargetFramework>netcoreapp3.1</TargetFramework>
-    </PropertyGroup>
-
-</Project>
diff --git a/src/AmongUs.Shared/Innersloth/Data/AlterGameTags.cs b/src/AmongUs.Shared/Innersloth/Data/AlterGameTags.cs
deleted file mode 100644 (file)
index a89c628..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace AmongUs.Shared.Innersloth.Data
-{
-    public enum AlterGameTags : byte
-    {
-        ChangePrivacy = 1
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Shared/Innersloth/Data/DisconnectReason.cs b/src/AmongUs.Shared/Innersloth/Data/DisconnectReason.cs
deleted file mode 100644 (file)
index 8d5149d..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-namespace AmongUs.Shared.Innersloth.Data
-{
-    public enum DisconnectReason
-    {
-        ExitGame = 0,
-        Destroy = 16,
-        // The game you tried to join is full.
-        // Check with the host to see if you can join next round.
-        GameFull = 1,
-        // The game you tried to join already started.
-        // Check with the host to see if you can join next round.
-        GameStarted = 2,
-        // Could not find the game you're looking for.
-        GameMissing = 3,
-        IncorrectGame = 18,
-        // For these a message can be given, specifying an empty message shows
-        // "An unknown error disconnected you from the server."
-        CustomMessage1 = 4,
-        Custom = 8,
-        // CustomMessage3 = 11,
-        // CustomMessage4 = 12,
-        // CustomMessage5 = 13,
-        // CustomMessage6 = 14,
-        // CustomMessage7 = 15,
-        // You are running an older version of the game.
-        // Please update to play with others.
-        IncorrectVersion = 5,
-        // You cannot rejoin that room.
-        // You were banned
-        Banned = 6,
-        // You can rejoin if the room hasn't started
-        // You were kicked
-        Kicked = 7,
-        // Server refused username: %USERNAME%
-        InvalidName = 9,
-        // You were banned for hacking.
-        // Please stop.
-        Hacking = 10,
-        // You disconnected from the host.
-        // If this happens often, check your WiFi strength.
-        //
-        // You disconnected from the server.
-        // If this happens often, check your network strength.
-        // This may also be a server issue.
-        Error = 17,
-        // The server stopped this game. Possibly due to inactivity.
-        ServerRequest = 19,
-        // The Among Us servers are overloaded.
-        // Sorry! Please try again later!
-        ServerFull = 20,
-        FocusLostBackground = 207,
-        IntentionalLeaving = 208,
-        FocusLost = 209,
-        NewConnection = 210
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Shared/Innersloth/Data/GameKeywords.cs b/src/AmongUs.Shared/Innersloth/Data/GameKeywords.cs
deleted file mode 100644 (file)
index 5478153..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-using System;
-
-namespace AmongUs.Shared.Innersloth.Data
-{
-    [Flags]
-    public enum GameKeywords : uint
-    {
-        All = 0,
-        Other = 1,
-        Spanish = 2,
-        Korean = 4,
-        Russian = 8,
-        Portuguese = 16,
-        Arabic = 32,
-        Filipone = 64,
-        Polish = 128,
-        English = 256
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Shared/Innersloth/Data/GameStates.cs b/src/AmongUs.Shared/Innersloth/Data/GameStates.cs
deleted file mode 100644 (file)
index b43c7a0..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace AmongUs.Shared.Innersloth.Data
-{
-    public enum GameStates : byte
-    {
-        NotStarted,
-        Started,
-        Ended,
-        Destroyed
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Shared/Innersloth/Data/LimboStates.cs b/src/AmongUs.Shared/Innersloth/Data/LimboStates.cs
deleted file mode 100644 (file)
index e81e4da..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace AmongUs.Shared.Innersloth.Data
-{
-    public enum LimboStates
-    {
-        PreSpawn,
-        NotLimbo,
-        WaitingForHost,
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Shared/Innersloth/Data/RequestFlag.cs b/src/AmongUs.Shared/Innersloth/Data/RequestFlag.cs
deleted file mode 100644 (file)
index 8d82426..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace AmongUs.Shared.Innersloth.Data
-{
-    public enum RequestFlag : byte
-    {
-        HostGame = 0,
-        JoinGame = 1,
-        StartGame = 2,
-        RemoveGame = 3,
-        RemovePlayer = 4,
-        GameData = 5,
-        GameDataTo = 6,
-        JoinedGame = 7,
-        EndGame = 8,
-        GetGameList = 9,
-        AlterGame = 10,
-        KickPlayer = 11,
-        WaitForHost = 12,
-        Redirect = 13,
-        ReselectServer = 14,
-        GetGameListV2 = 16,
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Shared/Innersloth/GameCode.cs b/src/AmongUs.Shared/Innersloth/GameCode.cs
deleted file mode 100644 (file)
index 152048b..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-using System;
-using System.Buffers.Binary;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Text;
-
-namespace AmongUs.Shared.Innersloth
-{
-    public static class GameCode
-    {
-        private const string V2 = "QWXRTYLPESDFGHUJKZOCVBINMA";
-        private static readonly int[] V2Map = {
-            25,
-            21,
-            19,
-            10,
-            8,
-            11,
-            12,
-            13,
-            22,
-            15,
-            16,
-            6,
-            24,
-            23,
-            18,
-            7,
-            0,
-            3,
-            9,
-            4,
-            14,
-            20,
-            1,
-            2,
-            5,
-            17
-        };
-        private static readonly RNGCryptoServiceProvider Random = new RNGCryptoServiceProvider();
-        
-        public static string IntToGameName(int input)
-        {
-            // V2.
-            if (input < -1)
-            {
-                return IntToGameNameV2(input);
-            }
-
-            // V1.
-            Span<byte> code = stackalloc byte[4];
-            BinaryPrimitives.WriteInt32LittleEndian(code, input);
-            return Encoding.UTF8.GetString(code.Slice(0, 4));
-        }
-
-        private static string IntToGameNameV2(int input)
-        {
-            var a = input & 0x3FF;
-            var b = (input >> 10) & 0xFFFFF;
-
-            return new string(new []
-            {
-                V2[a % 26],
-                V2[a / 26],
-                V2[b % 26],
-                V2[b / 26 % 26],
-                V2[b / (26 * 26) % 26],
-                V2[b / (26 * 26 * 26) % 26]
-            });
-        }
-
-        public static int GameNameToInt(string code)
-        {
-            var upper = code.ToUpperInvariant();
-            if (upper.Any(x => !char.IsLetter(x)))
-            {
-                return -1;
-            }
-            
-            var len = code.Length;
-            if (len == 6)
-            {
-                return GameNameToIntV2(upper);
-            }
-
-            if (len == 4)
-            {
-                return code[0] | ((code[1] | ((code[2] | (code[3] << 8)) << 8)) << 8);
-            }
-            
-            return -1;
-        }
-        
-        private static int GameNameToIntV2(string code)
-        {
-            var a = V2Map[code[0] - 65];
-            var b = V2Map[code[1] - 65];
-            var c = V2Map[code[2] - 65];
-            var d = V2Map[code[3] - 65];
-            var e = V2Map[code[4] - 65];
-            var f = V2Map[code[5] - 65];
-
-            var one = (a + 26 * b) & 0x3FF;
-            var two = (c + 26 * (d + 26 * (e + 26 * f)));
-
-            return (int) (one | ((two << 10) & 0x3FFFFC00) | 0x80000000);
-        }
-
-        public static int GenerateCode(int len)
-        {
-            if (len != 4 && len != 6)
-            {
-                throw new ArgumentException("should be 4 or 6", nameof(len));
-            }
-            
-            // Generate random bytes.
-            Span<byte> data = stackalloc byte[len];
-            Random.GetBytes(data);
-            
-            // Convert to their char representation.
-            Span<char> dataChar = stackalloc char[len];
-            for (var i = 0; i < len; i++)
-            {
-                dataChar[i] = V2[V2Map[data[i] % 26]];
-            }
-            
-            return GameNameToInt(new string(dataChar));
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Shared/Innersloth/GameOptionsData.cs b/src/AmongUs.Shared/Innersloth/GameOptionsData.cs
deleted file mode 100644 (file)
index 4fd19f6..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-using System;
-using System.IO;
-using AmongUs.Shared.Innersloth.Data;
-
-namespace AmongUs.Shared.Innersloth
-{
-    public class GameOptionsData
-    {
-        public byte Version { get; set; }
-        public byte MaxPlayers { get; set; }
-        public GameKeywords Keywords { get; set; }
-        public byte MapId { get; set; }
-        public float PlayerSpeedMod { get; set; }
-        public float CrewLightMod { get; set; }
-        public float ImpostorLightMod { get; set; }
-        public float KillCooldown { get; set; }
-        public int NumCommonTasks { get; set; }
-        public int NumLongTasks { get; set; }
-        public int NumShortTasks { get; set; }
-        public int NumEmergencyMeetings { get; set; }
-        public int EmergencyCooldown { get; set; }
-        public int NumImpostors { get; set; }
-        public bool GhostsDoTasks { get; set; }
-        public int KillDistance { get; set; }
-        public int DiscussionTime { get; set; }
-        public int VotingTime { get; set; }
-        public bool ConfirmImpostor { get; set; }
-        public bool VisualTasks { get; set; }
-        public bool IsDefaults { get; set; }
-        
-        public void Serialize(BinaryWriter writer, byte version)
-        {
-            throw new NotImplementedException();
-        }
-
-        public static GameOptionsData Deserialize(byte[] bytes)
-        {
-            using (var stream = new MemoryStream(bytes))
-            using (var reader = new BinaryReader(stream))
-            {
-                var result = new GameOptionsData();
-
-                result.Version = reader.ReadByte();
-                result.MaxPlayers = reader.ReadByte();
-                result.Keywords = (GameKeywords) reader.ReadUInt32();
-                result.MapId = reader.ReadByte();
-                result.PlayerSpeedMod = reader.ReadSingle();
-                result.CrewLightMod = reader.ReadSingle();
-                result.ImpostorLightMod = reader.ReadSingle();
-                result.KillCooldown = reader.ReadSingle();
-                result.NumCommonTasks = reader.ReadByte();
-                result.NumLongTasks = reader.ReadByte();
-                result.NumShortTasks = reader.ReadByte();
-                result.NumEmergencyMeetings = reader.ReadInt32();
-                result.NumImpostors = reader.ReadByte();
-                result.KillDistance = reader.ReadByte();
-                result.DiscussionTime = reader.ReadInt32();
-                result.VotingTime = reader.ReadInt32();
-                result.IsDefaults = reader.ReadBoolean();
-
-                if (result.Version > 1)
-                {
-                    result.EmergencyCooldown = reader.ReadByte();
-                }
-
-                if (result.Version > 2)
-                {
-                    result.ConfirmImpostor = reader.ReadBoolean();
-                    result.VisualTasks = reader.ReadBoolean();
-                }
-                
-                return result;
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Shared/Innersloth/RegionInfo.cs b/src/AmongUs.Shared/Innersloth/RegionInfo.cs
deleted file mode 100644 (file)
index ce23e5d..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-using System.Collections.Generic;
-using System.IO;
-
-namespace AmongUs.Shared.Innersloth
-{
-    public class RegionInfo
-    {
-        public RegionInfo(string name, string ping, IReadOnlyList<ServerInfo> servers)
-        {
-            Name = name;
-            Ping = ping;
-            Servers = servers;
-        }
-        
-        public string Name { get; }
-        public string Ping { get; }
-        public IReadOnlyList<ServerInfo> Servers { get; }
-        
-        public void Serialize(BinaryWriter writer)
-        {
-            writer.Write(0);
-            writer.Write(Name);
-            writer.Write(Ping);
-            writer.Write(Servers.Count);
-            
-            foreach (var server in Servers)
-            {
-                server.Serialize(writer);
-            }
-        }
-
-        public static RegionInfo Deserialize(BinaryReader reader)
-        {
-            var unknown = reader.ReadInt32();
-            var name = reader.ReadString();
-            var ping = reader.ReadString();
-            var servers = new List<ServerInfo>();
-            var serverCount = reader.ReadInt32();
-
-            for (var i = 0; i < serverCount; i++)
-            {
-                servers.Add(ServerInfo.Deserialize(reader)); 
-            }
-            
-            return new RegionInfo(name, ping, servers);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Shared/Innersloth/ServerInfo.cs b/src/AmongUs.Shared/Innersloth/ServerInfo.cs
deleted file mode 100644 (file)
index 2be6924..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-using System.IO;
-using System.Net;
-
-namespace AmongUs.Shared.Innersloth
-{
-    public class ServerInfo
-    {
-        public string Name { get; }
-        public string Ip { get; }
-        public ushort Port { get; }
-
-        public ServerInfo(string name, string ip, ushort port)
-        {
-            Name = name;
-            Ip = ip;
-            Port = port;
-        }
-        
-        public void Serialize(BinaryWriter writer)
-        {
-            writer.Write(Name);
-            writer.Write(IPAddress.Parse(Ip).GetAddressBytes());
-            writer.Write(Port);
-            writer.Write(0);
-        }
-
-        public static ServerInfo Deserialize(BinaryReader reader)
-        {
-            var name = reader.ReadString();
-            var ip = new IPAddress(reader.ReadBytes(4)).ToString();
-            var port = reader.ReadUInt16();
-            var unknown = reader.ReadInt32();
-            
-            return new ServerInfo(name, ip, port);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Shared/Utils/HexUtils.cs b/src/AmongUs.Shared/Utils/HexUtils.cs
deleted file mode 100644 (file)
index 55b9cc0..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-using System;
-using System.Text;
-
-namespace AmongUs.Shared.Utils
-{
-    public static class HexUtils
-    {
-        public static string HexDump(byte[] bytes, int bytesPerLine = 16)
-        {
-            if (bytes == null) return "<null>";
-            int bytesLength = bytes.Length;
-
-            char[] HexChars = "0123456789ABCDEF".ToCharArray();
-
-            int firstHexColumn =
-                  8                   // 8 characters for the address
-                + 3;                  // 3 spaces
-
-            int firstCharColumn = firstHexColumn
-                + bytesPerLine * 3       // - 2 digit for the hexadecimal value and 1 space
-                + (bytesPerLine - 1) / 8 // - 1 extra space every 8 characters from the 9th
-                + 2;                  // 2 spaces 
-
-            int lineLength = firstCharColumn
-                + bytesPerLine           // - characters to show the ascii value
-                + Environment.NewLine.Length; // Carriage return and line feed (should normally be 2)
-
-            char[] line = (new String(' ', lineLength - Environment.NewLine.Length) + Environment.NewLine).ToCharArray();
-            int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine;
-            StringBuilder result = new StringBuilder(expectedLines * lineLength);
-
-            for (int i = 0; i < bytesLength; i += bytesPerLine)
-            {
-                line[0] = HexChars[(i >> 28) & 0xF];
-                line[1] = HexChars[(i >> 24) & 0xF];
-                line[2] = HexChars[(i >> 20) & 0xF];
-                line[3] = HexChars[(i >> 16) & 0xF];
-                line[4] = HexChars[(i >> 12) & 0xF];
-                line[5] = HexChars[(i >> 8) & 0xF];
-                line[6] = HexChars[(i >> 4) & 0xF];
-                line[7] = HexChars[(i >> 0) & 0xF];
-
-                int hexColumn = firstHexColumn;
-                int charColumn = firstCharColumn;
-
-                for (int j = 0; j < bytesPerLine; j++)
-                {
-                    if (j > 0 && (j & 7) == 0) hexColumn++;
-                    if (i + j >= bytesLength)
-                    {
-                        line[hexColumn] = ' ';
-                        line[hexColumn + 1] = ' ';
-                        line[charColumn] = ' ';
-                    }
-                    else
-                    {
-                        byte b = bytes[i + j];
-                        line[hexColumn] = HexChars[(b >> 4) & 0xF];
-                        line[hexColumn + 1] = HexChars[b & 0xF];
-                        line[charColumn] = (b < 32 ? '·' : (char)b);
-                    }
-                    hexColumn += 3;
-                    charColumn++;
-                }
-                result.Append(line);
-            }
-            return result.ToString();
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Tests/AmongUs.Tests.csproj b/src/AmongUs.Tests/AmongUs.Tests.csproj
deleted file mode 100644 (file)
index a754dfb..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <TargetFramework>netcoreapp3.1</TargetFramework>
-
-        <IsPackable>false</IsPackable>
-    </PropertyGroup>
-
-    <ItemGroup>
-        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
-        <PackageReference Include="xunit" Version="2.4.0" />
-        <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
-        <PackageReference Include="coverlet.collector" Version="1.2.0" />
-    </ItemGroup>
-
-    <ItemGroup>
-      <ProjectReference Include="..\AmongUs.Shared\AmongUs.Shared.csproj" />
-    </ItemGroup>
-
-</Project>
diff --git a/src/AmongUs.Tests/GameCodeTests.cs b/src/AmongUs.Tests/GameCodeTests.cs
deleted file mode 100644 (file)
index 7fc6582..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-using AmongUs.Shared.Innersloth;
-using Xunit;
-
-namespace AmongUs.Tests
-{
-    public class GameCodeTests
-    {
-        [Fact]
-        public void CodeV1()
-        {
-            const string code = "ABCD";
-            const int codeInt = 0x44434241;
-            
-            Assert.Equal(code, GameCode.IntToGameName(codeInt));
-            Assert.Equal(codeInt, GameCode.GameNameToInt(code));
-        }
-        
-        [Fact]
-        public void CodeV2()
-        {
-            const string code = "ABCDEF";
-            const int codeInt = -1943683525;
-            
-            Assert.Equal(code, GameCode.IntToGameName(codeInt));
-            Assert.Equal(codeInt, GameCode.GameNameToInt(code));
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Tools.Proxy/AmongUs.Tools.Proxy.csproj b/src/AmongUs.Tools.Proxy/AmongUs.Tools.Proxy.csproj
deleted file mode 100644 (file)
index 1a89dbd..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <OutputType>Exe</OutputType>
-        <TargetFramework>net452</TargetFramework>
-    </PropertyGroup>
-
-    <ItemGroup>
-      <PackageReference Include="Pcap.Net.x64" Version="1.0.4.1" />
-    </ItemGroup>
-
-    <ItemGroup>
-      <ProjectReference Include="..\..\submodules\Hazel-Networking\Hazel\Hazel.csproj" />
-    </ItemGroup>
-
-</Project>
diff --git a/src/AmongUs.Tools.Proxy/HexUtils.cs b/src/AmongUs.Tools.Proxy/HexUtils.cs
deleted file mode 100644 (file)
index c2a3398..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-using System;
-using System.Text;
-
-namespace AmongUs.Tools.Proxy
-{
-    public static class HexUtils
-    {
-        public static string HexDump(byte[] bytes, int bytesPerLine = 16)
-        {
-            if (bytes == null) return "<null>";
-            int bytesLength = bytes.Length;
-
-            char[] HexChars = "0123456789ABCDEF".ToCharArray();
-
-            int firstHexColumn =
-                  8                   // 8 characters for the address
-                + 3;                  // 3 spaces
-
-            int firstCharColumn = firstHexColumn
-                + bytesPerLine * 3       // - 2 digit for the hexadecimal value and 1 space
-                + (bytesPerLine - 1) / 8 // - 1 extra space every 8 characters from the 9th
-                + 2;                  // 2 spaces 
-
-            int lineLength = firstCharColumn
-                + bytesPerLine           // - characters to show the ascii value
-                + Environment.NewLine.Length; // Carriage return and line feed (should normally be 2)
-
-            char[] line = (new String(' ', lineLength - Environment.NewLine.Length) + Environment.NewLine).ToCharArray();
-            int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine;
-            StringBuilder result = new StringBuilder(expectedLines * lineLength);
-
-            for (int i = 0; i < bytesLength; i += bytesPerLine)
-            {
-                line[0] = HexChars[(i >> 28) & 0xF];
-                line[1] = HexChars[(i >> 24) & 0xF];
-                line[2] = HexChars[(i >> 20) & 0xF];
-                line[3] = HexChars[(i >> 16) & 0xF];
-                line[4] = HexChars[(i >> 12) & 0xF];
-                line[5] = HexChars[(i >> 8) & 0xF];
-                line[6] = HexChars[(i >> 4) & 0xF];
-                line[7] = HexChars[(i >> 0) & 0xF];
-
-                int hexColumn = firstHexColumn;
-                int charColumn = firstCharColumn;
-
-                for (int j = 0; j < bytesPerLine; j++)
-                {
-                    if (j > 0 && (j & 7) == 0) hexColumn++;
-                    if (i + j >= bytesLength)
-                    {
-                        line[hexColumn] = ' ';
-                        line[hexColumn + 1] = ' ';
-                        line[charColumn] = ' ';
-                    }
-                    else
-                    {
-                        byte b = bytes[i + j];
-                        line[hexColumn] = HexChars[(b >> 4) & 0xF];
-                        line[hexColumn + 1] = HexChars[b & 0xF];
-                        line[charColumn] = (b < 32 ? '·' : (char)b);
-                    }
-                    hexColumn += 3;
-                    charColumn++;
-                }
-                result.Append(line);
-            }
-            return result.ToString();
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/AmongUs.Tools.Proxy/Program.cs b/src/AmongUs.Tools.Proxy/Program.cs
deleted file mode 100644 (file)
index 6136f50..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Hazel;
-using Hazel.Udp;
-using PcapDotNet.Core;
-using PcapDotNet.Packets;
-
-namespace AmongUs.Tools.Proxy
-{
-    internal static class Program
-    {
-        private const string DeviceName = "Intel(R) I211 Gigabit Network Connection";
-
-        private static readonly Dictionary<byte, string> TagMap = new Dictionary<byte, string>
-        {
-            {0, "HostGame"},
-            {1, "JoinGame"},
-            {2, "StartGame"},
-            {3, "RemoveGame"},
-            {4, "RemovePlayer"},
-            {5, "GameData"},
-            {6, "GameDataTo"},
-            {7, "JoinedGame"},
-            {8, "EndGame"},
-            {9, "GetGameList"},
-            {10, "AlterGame"},
-            {11, "KickPlayer"},
-            {12, "WaitForHost"},
-            {13, "Redirect"},
-            {14, "ReselectServer"},
-            {16, "GetGameListV2"}
-        };
-        
-        private static void Main(string[] args)
-        {
-            var devices = LivePacketDevice.AllLocalMachine;
-            if (devices.Count == 0)
-            {
-                Console.WriteLine("No interfaces found! Make sure WinPcap is installed.");
-                return;
-            }
-
-            var device = devices.FirstOrDefault(x => x.Description.Contains(DeviceName));
-            if (device == null)
-            {
-                Console.WriteLine("Unable to find configured device.");
-                return;
-            }
-
-            using (var communicator = device.Open(65536, PacketDeviceOpenAttributes.Promiscuous, 1000))
-            {
-                using (var filter = communicator.CreateFilter("udp and port 22023"))
-                {
-                    communicator.SetFilter(filter);
-                }
-
-                communicator.ReceivePackets(0, PacketHandler);
-            }
-        }
-
-        private static void PacketHandler(Packet packet)
-        {
-            var ip = packet.Ethernet.IpV4;
-            var ipSrc = ip.Source.ToString();
-            var udp = ip.Udp;
-            
-            // True if this is our own packet.
-            using (var stream = udp.Payload.ToMemoryStream())
-            {
-                var reader = MessageReader.Get(stream.ToArray());
-                if (reader.Buffer[0] == (byte) SendOption.Reliable)
-                {
-                    reader.Offset = 3;
-                    reader.Length = udp.Payload.Length - 3;
-                    reader.Position = 0;
-                }
-                else if (reader.Buffer[0] == (byte) UdpSendOption.Acknowledgement ||
-                         reader.Buffer[0] == (byte) UdpSendOption.Ping ||
-                         reader.Buffer[0] == (byte) UdpSendOption.Hello ||
-                         reader.Buffer[0] == (byte) UdpSendOption.Disconnect)
-                {
-                    return;
-                }
-                else
-                {
-                    reader.Offset = 1;
-                    reader.Length = udp.Payload.Length - 1;
-                    reader.Position = 0;
-                }
-                
-                var isSent = ipSrc.StartsWith("192.");
-                
-                while (true)
-                {
-                    if (reader.Position >= reader.Length)
-                    {
-                        break;
-                    }
-
-                    var message = reader.ReadMessage();
-                    if (isSent)
-                    {
-                        HandleToServer(ipSrc, message);
-                    }
-                    else
-                    {
-                        HandleToClient(ipSrc, message);
-                    }
-                    
-                    if (message.Position < message.Length)
-                    {
-                        Console.ForegroundColor = ConsoleColor.Red;
-                        Console.WriteLine("- Did not consume all bytes.");
-                    }
-                }
-            }
-        }
-
-        private static void HandleToClient(string source, MessageReader packet)
-        {
-            var tagName = TagMap.ContainsKey(packet.Tag) ? TagMap[packet.Tag] : "Unknown";
-            Console.ForegroundColor = ConsoleColor.Cyan;
-            Console.WriteLine($"{source,-15} Client received: {packet.Tag,-2} {tagName}");
-
-            switch (packet.Tag)
-            {
-                case 14:
-                case 13:
-                    packet.Position = packet.Length;
-                    break;
-                case 0:
-                    Console.WriteLine("- GameCode        " + packet.ReadInt32());
-                    break;
-                case 5:
-                case 6:
-                    Console.WriteLine(HexUtils.HexDump(packet.Buffer.Take(packet.Length).ToArray()));
-                    packet.Position = packet.Length;
-                    break;
-                case 7:
-                    Console.WriteLine("- GameCode        " + packet.ReadInt32());
-                    Console.WriteLine("- PlayerId        " + packet.ReadInt32());
-                    Console.WriteLine("- Host            " + packet.ReadInt32());
-                    var playerCount = packet.ReadPackedInt32();
-                    Console.WriteLine("- PlayerCount     " + playerCount);
-                    for (var i = 0; i < playerCount; i++)
-                    {
-                        Console.WriteLine("-     PlayerId    " + packet.ReadPackedInt32());
-                    }
-                    break;
-                case 10:
-                    Console.WriteLine("- GameCode        " + packet.ReadInt32());
-                    Console.WriteLine("- Flag            " + packet.ReadSByte());
-                    Console.WriteLine("- Value           " + packet.ReadBoolean());
-                    break;
-            }
-        }
-
-        private static void HandleToServer(string source, MessageReader packet)
-        {
-            var tagName = TagMap.ContainsKey(packet.Tag) ? TagMap[packet.Tag] : "Unknown";
-            Console.ForegroundColor = ConsoleColor.White;
-            Console.WriteLine($"{source,-15} Server received: {packet.Tag,-2} {tagName}");
-
-            switch (packet.Tag)
-            {
-                case 0:
-                    Console.WriteLine("- GameInfo length " + packet.ReadBytesAndSize().Length);
-                    break;
-                case 1:
-                    Console.WriteLine("- GameCode        " + packet.ReadInt32());
-                    Console.WriteLine("- Unknown         " + packet.ReadByte());
-                    break;
-                case 5:
-                case 6:
-                    Console.WriteLine("- GameCode        " + packet.ReadInt32());
-                    Console.WriteLine(HexUtils.HexDump(packet.Buffer.Take(packet.Length).ToArray()));
-                    packet.Position = packet.Length;
-                    break;
-            }
-        }
-    }
-}
diff --git a/src/AmongUsServer.sln b/src/AmongUsServer.sln
deleted file mode 100644 (file)
index 391da3d..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30503.244
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AmongUs.Agent", "AmongUs.Agent\AmongUs.Agent.vcxproj", "{097BE795-88E9-4E7B-92F3-F6DDDBE3F012}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AmongUs.Server", "AmongUs.Server\AmongUs.Server.csproj", "{1B0390AF-A4F3-4FE4-B093-708B0135C0B3}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AmongUs.Client", "AmongUs.Client\AmongUs.Client.csproj", "{24F07173-D4A7-41C6-BA51-4516AB68343C}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AmongUs.Shared", "AmongUs.Shared\AmongUs.Shared.csproj", "{1D109A96-FADF-41B9-A845-457A7A5C0C5A}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "submodules", "submodules", "{DFA3CC6A-A27C-4713-876D-A55912C78C45}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hazel", "..\submodules\Hazel-Networking\Hazel\Hazel.csproj", "{02CFBD30-D77D-400F-94B2-700F60EFDD7F}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AmongUs.Tests", "AmongUs.Tests\AmongUs.Tests.csproj", "{C1385C67-A7DD-46D2-80F6-FA428B85FB22}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{56DD9707-D811-4056-9E2C-8A9CC2479B07}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AmongUs.Tools.Proxy", "AmongUs.Tools.Proxy\AmongUs.Tools.Proxy.csproj", "{D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}"
-EndProject
-Global
-       GlobalSection(SolutionConfigurationPlatforms) = preSolution
-               Debug|Any CPU = Debug|Any CPU
-               Debug|x86 = Debug|x86
-               Release|Any CPU = Release|Any CPU
-               Release|x86 = Release|x86
-       EndGlobalSection
-       GlobalSection(ProjectConfigurationPlatforms) = postSolution
-               {097BE795-88E9-4E7B-92F3-F6DDDBE3F012}.Debug|Any CPU.ActiveCfg = Debug|Win32
-               {097BE795-88E9-4E7B-92F3-F6DDDBE3F012}.Debug|x86.ActiveCfg = Debug|Win32
-               {097BE795-88E9-4E7B-92F3-F6DDDBE3F012}.Debug|x86.Build.0 = Debug|Win32
-               {097BE795-88E9-4E7B-92F3-F6DDDBE3F012}.Release|Any CPU.ActiveCfg = Release|Win32
-               {097BE795-88E9-4E7B-92F3-F6DDDBE3F012}.Release|x86.ActiveCfg = Release|Win32
-               {097BE795-88E9-4E7B-92F3-F6DDDBE3F012}.Release|x86.Build.0 = Release|Win32
-               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Debug|x86.Build.0 = Debug|Any CPU
-               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
-               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Release|Any CPU.Build.0 = Release|Any CPU
-               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Release|x86.ActiveCfg = Release|Any CPU
-               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Release|x86.Build.0 = Release|Any CPU
-               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Debug|x86.Build.0 = Debug|Any CPU
-               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Release|Any CPU.ActiveCfg = Release|Any CPU
-               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Release|Any CPU.Build.0 = Release|Any CPU
-               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Release|x86.ActiveCfg = Release|Any CPU
-               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Release|x86.Build.0 = Release|Any CPU
-               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Debug|x86.Build.0 = Debug|Any CPU
-               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
-               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Release|Any CPU.Build.0 = Release|Any CPU
-               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Release|x86.ActiveCfg = Release|Any CPU
-               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Release|x86.Build.0 = Release|Any CPU
-               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Debug|x86.Build.0 = Debug|Any CPU
-               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
-               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Release|Any CPU.Build.0 = Release|Any CPU
-               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Release|x86.ActiveCfg = Release|Any CPU
-               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Release|x86.Build.0 = Release|Any CPU
-               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Debug|x86.Build.0 = Debug|Any CPU
-               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Release|Any CPU.ActiveCfg = Release|Any CPU
-               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Release|Any CPU.Build.0 = Release|Any CPU
-               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Release|x86.ActiveCfg = Release|Any CPU
-               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Release|x86.Build.0 = Release|Any CPU
-               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Debug|x86.Build.0 = Debug|Any CPU
-               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Release|Any CPU.ActiveCfg = Release|Any CPU
-               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Release|Any CPU.Build.0 = Release|Any CPU
-               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Release|x86.ActiveCfg = Release|Any CPU
-               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Release|x86.Build.0 = Release|Any CPU
-       EndGlobalSection
-       GlobalSection(SolutionProperties) = preSolution
-               HideSolutionNode = FALSE
-       EndGlobalSection
-       GlobalSection(ExtensibilityGlobals) = postSolution
-               SolutionGuid = {06245255-E585-483C-A4AD-71B7B568C6C8}
-       EndGlobalSection
-       GlobalSection(NestedProjects) = preSolution
-               {02CFBD30-D77D-400F-94B2-700F60EFDD7F} = {DFA3CC6A-A27C-4713-876D-A55912C78C45}
-               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D} = {56DD9707-D811-4056-9E2C-8A9CC2479B07}
-       EndGlobalSection
-EndGlobal
diff --git a/src/Impostor.Agent/Impostor.Agent.vcxproj b/src/Impostor.Agent/Impostor.Agent.vcxproj
new file mode 100644 (file)
index 0000000..9350e62
--- /dev/null
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>16.0</VCProjectVersion>
+    <Keyword>Win32Proj</Keyword>
+    <ProjectGuid>{097be795-88e9-4e7b-92f3-f6dddbe3f012}</ProjectGuid>
+    <RootNamespace>AmongUsAgent</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)build\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)build\$(Platform)\$(Configuration)\Intermediate\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(ProjectDir)build\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)build\$(Platform)\$(Configuration)\Intermediate\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="logger.cpp" />
+    <ClCompile Include="main.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="logger.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/Impostor.Agent/Impostor.Agent.vcxproj.filters b/src/Impostor.Agent/Impostor.Agent.vcxproj.filters
new file mode 100644 (file)
index 0000000..85ba1c7
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="main.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="logger.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="logger.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/src/Impostor.Agent/logger.cpp b/src/Impostor.Agent/logger.cpp
new file mode 100644 (file)
index 0000000..4b45c1d
--- /dev/null
@@ -0,0 +1,84 @@
+#include "logger.h"
+#include <cstdio>
+#include <Windows.h>
+
+HANDLE h_out = nullptr, h_old_out = nullptr;
+HANDLE h_err = nullptr, h_old_err = nullptr;
+HANDLE h_in = nullptr, h_old_in = nullptr;
+
+namespace Logger
+{
+       void Attach()
+       {
+               h_old_out = GetStdHandle(STD_OUTPUT_HANDLE);
+               h_old_err = GetStdHandle(STD_ERROR_HANDLE);
+               h_old_in = GetStdHandle(STD_INPUT_HANDLE);
+
+               AllocConsole() && AttachConsole(GetCurrentProcessId());
+
+               h_out = GetStdHandle(STD_OUTPUT_HANDLE);
+               h_err = GetStdHandle(STD_ERROR_HANDLE);
+               h_in = GetStdHandle(STD_INPUT_HANDLE);
+
+               SetConsoleMode(h_out,
+                       ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
+
+               SetConsoleMode(h_in,
+                       ENABLE_INSERT_MODE | ENABLE_EXTENDED_FLAGS |
+                       ENABLE_PROCESSED_INPUT | ENABLE_QUICK_EDIT_MODE);
+       }
+
+       void Detach()
+       {
+               if (h_out && h_err && h_in) {
+                       FreeConsole();
+
+                       if (h_old_out)
+                       {
+                               SetStdHandle(STD_OUTPUT_HANDLE, h_old_out);
+                       }
+
+                       if (h_old_err)
+                       {
+                               SetStdHandle(STD_ERROR_HANDLE, h_old_err);
+                       }
+
+                       if (h_old_in)
+                       {
+                               SetStdHandle(STD_INPUT_HANDLE, h_old_in);
+                       }
+               }
+       }
+
+       bool Print(const char* fmt, ...)
+       {
+               if (!h_out)
+               {
+                       return false;
+               }
+
+               char buf[1024];
+               va_list va;
+
+               va_start(va, fmt);
+               _vsnprintf_s(buf, 1024, fmt, va);
+               va_end(va);
+
+               return !!WriteConsoleA(h_out, buf, static_cast<DWORD>(strlen(buf)), nullptr, nullptr);
+       }
+
+       char ReadKey()
+       {
+               if (!h_in)
+               {
+                       return -1;
+               }
+
+               auto key = char{ 0 };
+               auto keysread = DWORD{ 0 };
+
+               ReadConsoleA(h_in, &key, 1, &keysread, nullptr);
+
+               return key;
+       }
+};
\ No newline at end of file
diff --git a/src/Impostor.Agent/logger.h b/src/Impostor.Agent/logger.h
new file mode 100644 (file)
index 0000000..fc22e15
--- /dev/null
@@ -0,0 +1,9 @@
+#pragma once
+
+namespace Logger
+{
+       void Attach();
+       void Detach();
+       bool Print(const char* fmt, ...);
+       char ReadKey();
+};
\ No newline at end of file
diff --git a/src/Impostor.Agent/main.cpp b/src/Impostor.Agent/main.cpp
new file mode 100644 (file)
index 0000000..40b5ff0
--- /dev/null
@@ -0,0 +1,40 @@
+#include <Windows.h>
+#include "logger.h"
+
+DWORD WINAPI OnDllAttach(LPVOID base)
+{
+       Logger::Attach();
+       Logger::Print("[AmongUs.Agent] DLL Attached\n");
+
+       FreeLibraryAndExitThread(static_cast<HMODULE>(base), 1);
+}
+
+BOOL WINAPI OnDllDetach()
+{
+       Logger::Print("[AmongUs.Agent] DLL Detached\n");
+       Logger::Detach();
+
+       return true;
+}
+
+BOOL WINAPI DllMain(
+       const _In_      HINSTANCE hinstDll,
+       const _In_      DWORD fdwReason,
+       const _In_opt_  LPVOID lpvReserved
+)
+{
+       switch (fdwReason)
+       {
+       case DLL_PROCESS_ATTACH:
+               DisableThreadLibraryCalls(hinstDll);
+               CreateThread(nullptr, 0, OnDllAttach, hinstDll, 0, nullptr);
+               return true;
+
+       case DLL_PROCESS_DETACH:
+               if (lpvReserved == nullptr)
+                       return OnDllDetach();
+               return true;
+       default:
+               return true;
+       }
+}
\ No newline at end of file
diff --git a/src/Impostor.Client/Impostor.Client.csproj b/src/Impostor.Client/Impostor.Client.csproj
new file mode 100644 (file)
index 0000000..6794e8f
--- /dev/null
@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+    <PropertyGroup>
+        <OutputType>Exe</OutputType>
+        <TargetFramework>netcoreapp3.1</TargetFramework>
+    </PropertyGroup>
+
+    <ItemGroup>
+      <ProjectReference Include="..\Impostor.Shared\Impostor.Shared.csproj" />
+    </ItemGroup>
+
+</Project>
diff --git a/src/Impostor.Client/Program.cs b/src/Impostor.Client/Program.cs
new file mode 100644 (file)
index 0000000..7cd684c
--- /dev/null
@@ -0,0 +1,25 @@
+using System;
+using System.IO;
+using Impostor.Shared.Innersloth;
+
+namespace Impostor.Client
+{
+    internal static class Program
+    {
+        private static void Main(string[] args)
+        {
+            var appData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "..\\LocalLow");
+            var regionFile = Path.Combine(appData, "Innersloth", "Among Us", "regionInfo.dat");
+            var region = new RegionInfo("Private", "192.168.1.211", new []
+            {
+                new ServerInfo("Private-Master-1", "192.168.1.211", 22023)
+            });
+            
+            using (var file = File.Open(regionFile, FileMode.Create, FileAccess.Write))
+            using (var writer = new BinaryWriter(file))
+            {
+                region.Serialize(writer);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Server/Data/DisconnectMessages.cs b/src/Impostor.Server/Data/DisconnectMessages.cs
new file mode 100644 (file)
index 0000000..1c16173
--- /dev/null
@@ -0,0 +1,12 @@
+namespace Impostor.Server.Data
+{
+    public static class DisconnectMessages
+    {
+        public const string Error = "There was an internal server error. " +
+                                    "Check the server console for more information. " +
+                                    "Please report the issue on the AmongUsServer GitHub if it keeps happening.";
+
+        public const string Destroyed = "The game you tried to join is being destroyed. " +
+                                        "Please create a new game.";
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Server/Exceptions/AmongUsException.cs b/src/Impostor.Server/Exceptions/AmongUsException.cs
new file mode 100644 (file)
index 0000000..0d5ff20
--- /dev/null
@@ -0,0 +1,24 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Impostor.Server.Exceptions
+{
+    public class AmongUsException : Exception
+    {
+        public AmongUsException()
+        {
+        }
+
+        protected AmongUsException(SerializationInfo info, StreamingContext context) : base(info, context)
+        {
+        }
+
+        public AmongUsException(string? message) : base(message)
+        {
+        }
+
+        public AmongUsException(string? message, Exception? innerException) : base(message, innerException)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Server/Extensions/ConnectionExtensions.cs b/src/Impostor.Server/Extensions/ConnectionExtensions.cs
new file mode 100644 (file)
index 0000000..21ef19e
--- /dev/null
@@ -0,0 +1,16 @@
+using Hazel;
+using Impostor.Server.Net.Response;
+
+namespace Impostor.Server.Extensions
+{
+    internal static class ConnectionExtensions
+    {
+        public static void Send(this Connection connection, MessageBase message)
+        {
+            using (message)
+            {
+                connection.Send(message.Write());
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Server/Impostor.Server.csproj b/src/Impostor.Server/Impostor.Server.csproj
new file mode 100644 (file)
index 0000000..46ef7fa
--- /dev/null
@@ -0,0 +1,17 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+    <PropertyGroup>
+        <OutputType>Exe</OutputType>
+        <TargetFramework>netcoreapp3.1</TargetFramework>
+    </PropertyGroup>
+
+    <ItemGroup>
+      <ProjectReference Include="..\..\submodules\Hazel-Networking\Hazel\Hazel.csproj" />
+      <ProjectReference Include="..\Impostor.Shared\Impostor.Shared.csproj" />
+    </ItemGroup>
+
+    <ItemGroup>
+      <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
+    </ItemGroup>
+
+</Project>
diff --git a/src/Impostor.Server/Net/Client.cs b/src/Impostor.Server/Net/Client.cs
new file mode 100644 (file)
index 0000000..b3a041e
--- /dev/null
@@ -0,0 +1,273 @@
+using System;
+using Hazel;
+using Impostor.Server.Data;
+using Impostor.Server.Extensions;
+using Impostor.Server.Net.Response;
+using Impostor.Shared.Innersloth;
+using Impostor.Shared.Innersloth.Data;
+using Serilog;
+using ILogger = Serilog.ILogger;
+
+namespace Impostor.Server.Net
+{
+    public class Client
+    {
+        private static readonly ILogger Logger = Log.ForContext<Client>();
+        
+        private readonly ClientManager _clientManager;
+        private readonly GameManager _gameManager;
+
+        public Client(ClientManager clientManager, GameManager gameManager, int id, string name, Connection connection)
+        {
+            _clientManager = clientManager;
+            _gameManager = gameManager;
+            Id = id;
+            Name = name;
+            Connection = connection;
+            Connection.DataReceived += OnDataReceived;
+            Connection.Disconnected += OnDisconnected;
+            Player = new ClientPlayer(this);
+        }
+
+        public int Id { get; }
+        public string Name { get; }
+        public Connection Connection { get; }
+        public ClientPlayer Player { get; }
+
+        public void Send(MessageWriter writer)
+        {
+            Connection.Send(writer);
+        }
+        
+        private bool IsPacketAllowed(MessageReader message, bool hostOnly)
+        {
+            var game = Player.Game;
+            if (game == null)
+            {
+                return false;
+            }
+
+            // GameCode must match code of the current game assigned to the player.
+            if (message.ReadInt32() != game.Code)
+            {
+                return false;
+            }
+            
+            // Some packets should only be sent by the host of the game.
+            if (hostOnly)
+            {
+                if (game.HostId == Id)
+                {
+                    return true;
+                }
+                
+                Logger.Warning("[{0}] Client sent packet only allowed by the host ({1}).", Id, game.HostId);
+                return false;
+            }
+
+            return true;
+        }
+
+        private void OnDataReceived(DataReceivedEventArgs e)
+        {
+            try
+            {
+                while (true)
+                {
+                    if (e.Message.Position >= e.Message.Length)
+                    {
+                        break;
+                    }
+
+                    OnMessageReceived(e.Message.ReadMessage(), e.SendOption);
+                }
+            }
+            catch (Exception ex)
+            {
+                Logger.Error(ex, "Exception caught in client data handler.");
+                Connection.Send(new Message1DisconnectReason(DisconnectReason.Custom, DisconnectMessages.Error));
+            }
+        }
+
+        private void OnMessageReceived(MessageReader message, SendOption sendOption)
+        {
+            var flag = (RequestFlag) message.Tag;
+            
+            Logger.Verbose("[{0}] Server got {1}.", Id, flag);
+            
+            switch (flag)
+            {
+                case RequestFlag.HostGame:
+                {
+                    // Read game settings.
+                    var gameInfoBytes = message.ReadBytesAndSize();
+                    var gameInfo = GameOptionsData.Deserialize(gameInfoBytes);
+                    
+                    // Create game.
+                    var game = _gameManager.Create(this, gameInfo);
+                    if (game == null)
+                    {
+                        Connection.Send(new Message1DisconnectReason(DisconnectReason.ServerFull));
+                        return;
+                    }
+
+                    // Code in the packet below will be used in JoinGame.
+                    using (var writer = MessageWriter.Get(SendOption.Reliable))
+                    {
+                        writer.StartMessage(0);
+                        writer.Write(game.Code);
+                        writer.EndMessage();
+                
+                        Connection.Send(writer);
+                    }
+                    break;
+                }
+                
+                case RequestFlag.JoinGame:
+                {
+                    var gameCode = message.ReadInt32();
+                    var unknown = message.ReadByte();
+                    var game = _gameManager.Find(gameCode);
+                    if (game == null)
+                    {
+                        Connection.Send(new Message1DisconnectReason(DisconnectReason.GameMissing));
+                        return;
+                    }
+
+                    game.HandleJoinGame(Player);
+                    break;
+                }
+
+                case RequestFlag.StartGame:
+                {
+                    if (!IsPacketAllowed(message, true))
+                    {
+                        return;
+                    }
+
+                    Player.Game.HandleStartGame(message);
+                    break;
+                }
+                
+                // No idea how this flag is triggered.
+                case RequestFlag.RemoveGame:
+                    break;
+                
+                case RequestFlag.RemovePlayer:
+                {
+                    if (!IsPacketAllowed(message, true))
+                    {
+                        return;
+                    }
+
+                    var playerId = message.ReadPackedInt32();
+                    var reason = message.ReadByte();
+
+                    Player.Game.HandleRemovePlayer(playerId, (DisconnectReason) reason);
+                    break;
+                }
+                
+                case RequestFlag.GameData:
+                case RequestFlag.GameDataTo:
+                {
+                    if (!IsPacketAllowed(message, false))
+                    {
+                        return;
+                    }
+
+                    // Broadcast packet to all other players.
+                    using (var writer = MessageWriter.Get(sendOption))
+                    {
+                        if (flag == RequestFlag.GameDataTo)
+                        {
+                            var target = message.ReadPackedInt32();
+                            writer.CopyFrom(message);
+                            Player.Game.SendTo(writer, target);
+                        }
+                        else
+                        {
+                            writer.CopyFrom(message);
+                            Player.Game.SendToAllExcept(writer, Player);
+                        }
+                    }
+                    break;
+                }
+                
+                case RequestFlag.EndGame:
+                {
+                    if (!IsPacketAllowed(message, true))
+                    {
+                        return;
+                    }
+
+                    Player.Game.HandleEndGame(message);
+                    break;
+                }
+
+                case RequestFlag.AlterGame:
+                {
+                    if (!IsPacketAllowed(message, true))
+                    {
+                        return;
+                    }
+
+                    if (message.ReadByte() != (byte) AlterGameTags.ChangePrivacy)
+                    {
+                        return;
+                    }
+
+                    var isPublic = message.ReadByte() == 1;
+                    
+                    Player.Game.HandleAlterGame(message, Player, isPublic);
+                    break;
+                }
+
+                case RequestFlag.KickPlayer:
+                {
+                    if (!IsPacketAllowed(message, true))
+                    {
+                        return;
+                    }
+
+                    var playerId = message.ReadPackedInt32();
+                    var isBan = message.ReadBoolean();
+
+                    Player.Game.HandleKickPlayer(playerId, isBan);
+                    break;
+                }
+                
+                default:
+                    Logger.Warning("Server received unknown flag {0}.", flag);
+                    break;
+            }
+
+            if (flag != RequestFlag.GameData &&
+                flag != RequestFlag.GameDataTo &&
+                flag != RequestFlag.EndGame &&
+                message.Position < message.Length)
+            {
+                Logger.Warning("Server did not consume all bytes from {0} ({1} < {2}).", 
+                    flag, 
+                    message.Position, 
+                    message.Length);
+            }
+        }
+        
+        private void OnDisconnected(object sender, DisconnectedEventArgs e)
+        {
+            try
+            {
+                if (Player.Game != null)
+                {
+                    Player.Game.HandleRemovePlayer(Id, DisconnectReason.ExitGame);
+                }
+            }
+            catch (Exception ex)
+            {
+                Logger.Error(ex, "Exception caught in client disconnection.");
+            }
+
+            _clientManager.Remove(this);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Server/Net/ClientManager.cs b/src/Impostor.Server/Net/ClientManager.cs
new file mode 100644 (file)
index 0000000..2a43d14
--- /dev/null
@@ -0,0 +1,64 @@
+using System.Collections.Concurrent;
+using Impostor.Server.Exceptions;
+using Serilog;
+
+namespace Impostor.Server.Net
+{
+    public class ClientManager
+    {
+        private static readonly ILogger Logger = Log.ForContext<ClientManager>();
+        
+        private readonly ConcurrentDictionary<int, Client> _clients;
+        private readonly object _idLock;
+        private int _idLast;
+        
+        public ClientManager()
+        {
+            _clients = new ConcurrentDictionary<int, Client>();
+            _idLock = new object();
+            _idLast = 0;
+        }
+
+        // No idea what a good way for this is.
+        public int NextId()
+        {
+            lock (_idLock)
+            {
+                // 3 Attempts.
+                for (var i = 0; i < 3; i++)
+                {
+                    // It is important that ids start from 1, a 0 id causes issues.
+                    var result = ++_idLast;
+
+                    if (_idLast == int.MaxValue)
+                    {
+                        _idLast = 0;
+                    }
+
+                    if (_clients.ContainsKey(_idLast))
+                    {
+                        continue;
+                    }
+            
+                    return result;
+                }
+                
+                throw new AmongUsException("Unable to generate a client id.");
+            }
+        }
+        
+        public void Add(Client client)
+        {
+            Logger.Information("Client connected.");
+
+            _clients.TryAdd(client.Id, client);
+        }
+
+        public void Remove(Client client)
+        {
+            Logger.Information("Client disconnected.");
+
+            _clients.TryRemove(client.Id, out _);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Server/Net/ClientPlayer.cs b/src/Impostor.Server/Net/ClientPlayer.cs
new file mode 100644 (file)
index 0000000..a0b7866
--- /dev/null
@@ -0,0 +1,16 @@
+using Impostor.Shared.Innersloth.Data;
+
+namespace Impostor.Server.Net
+{
+    public class ClientPlayer
+    {
+        public ClientPlayer(Client client)
+        {
+            Client = client;
+        }
+        
+        public Client Client { get; }
+        public Game Game { get; set; }
+        public LimboStates LimboState { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Server/Net/Game.cs b/src/Impostor.Server/Net/Game.cs
new file mode 100644 (file)
index 0000000..be982d7
--- /dev/null
@@ -0,0 +1,387 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using Hazel;
+using Impostor.Server.Data;
+using Impostor.Server.Exceptions;
+using Impostor.Server.Extensions;
+using Impostor.Server.Net.Response;
+using Impostor.Shared.Innersloth;
+using Impostor.Shared.Innersloth.Data;
+using Serilog;
+using ILogger = Serilog.ILogger;
+
+namespace Impostor.Server.Net
+{
+    public class Game
+    {
+        private static readonly ILogger Logger = Log.ForContext<Game>();
+        
+        private readonly GameManager _gameManager;
+        private readonly ConcurrentDictionary<int, ClientPlayer> _players;
+        private readonly HashSet<IPAddress> _bannedIps;
+
+        public Game(GameManager gameManager, int code, GameOptionsData options)
+        {
+            _gameManager = gameManager;
+            _players = new ConcurrentDictionary<int, ClientPlayer>();
+            _bannedIps = new HashSet<IPAddress>();
+            
+            Code = code;
+            CodeStr = GameCode.IntToGameName(code);
+            HostId = -1;
+            GameState = GameStates.NotStarted;
+            Options = options;
+        }
+        
+        public int Code { get; }
+        public string CodeStr { get; }
+        public bool IsPublic { get; private set; }
+        public int HostId { get; private set; }
+        public GameStates GameState { get; private set; }
+        public GameOptionsData Options { get; }
+
+        public void SendToAllExcept(MessageWriter message, ClientPlayer sender)
+        {
+            foreach (var (_, player) in _players.Where(x => x.Value != sender))
+            {
+                if (player.Client.Connection.State != ConnectionState.Connected)
+                {
+                    Logger.Warning("[{0}] Tried to sent data to a disconnected player ({1}).", sender?.Client.Id, player.Client.Id);
+                    continue;
+                }
+                
+                player.Client.Send(message);
+            }
+        }
+
+        public void SendTo(MessageWriter message, int playerId)
+        {
+            if (_players.TryGetValue(playerId, out var player))
+            {
+                if (player.Client.Connection.State != ConnectionState.Connected)
+                {
+                    Logger.Warning("[{0}] Sending data to {1} failed, player is not connected.", CodeStr, player.Client.Id);
+                    return;
+                }
+                
+                player.Client.Send(message);
+            }
+            else
+            {
+                Logger.Warning("[{0}] Sending data to {1} failed, player does not exist.", CodeStr, playerId);
+            }
+        }
+
+        public void HandleStartGame(MessageReader message)
+        {
+            GameState = GameStates.Started;
+            
+            using (var packet = MessageWriter.Get(SendOption.Reliable))
+            {
+                packet.CopyFrom(message);
+                SendToAllExcept(packet, null);
+            }
+        }
+
+        public void HandleJoinGame(ClientPlayer sender)
+        {
+            if (_bannedIps.Contains(sender.Client.Connection.EndPoint.Address))
+            {
+                sender.Client.Connection.Send(new Message1DisconnectReason(DisconnectReason.Banned));
+                return;
+            }
+            
+            switch (GameState)
+            {
+                case GameStates.NotStarted:
+                    HandleJoinGameNew(sender);
+                    break;
+                case GameStates.Ended:
+                    HandleJoinGameNext(sender);
+                    break;
+                case GameStates.Started:
+                    sender.Client.Connection.Send(new Message1DisconnectReason(DisconnectReason.GameStarted));
+                    return;
+                case GameStates.Destroyed:
+                    sender.Client.Connection.Send(new Message1DisconnectReason(DisconnectReason.Custom, DisconnectMessages.Destroyed));
+                    return;
+                default:
+                    throw new ArgumentOutOfRangeException();
+            }
+        }
+
+        public void HandleEndGame(MessageReader message)
+        {
+            GameState = GameStates.Ended;
+            
+            // Broadcast end of the game.
+            using (var packet = MessageWriter.Get(SendOption.Reliable))
+            {
+                packet.CopyFrom(message);
+                SendToAllExcept(packet, null);
+            }
+            
+            // Remove all players from this game.
+            foreach (var player in _players)
+            {
+                player.Value.Game = null;
+            }
+            
+            _players.Clear();
+        }
+
+        public void HandleAlterGame(MessageReader message, ClientPlayer sender, bool isPublic)
+        {
+            IsPublic = isPublic;
+            
+            using (var packet = MessageWriter.Get(SendOption.Reliable))
+            {
+                packet.CopyFrom(message);
+                SendToAllExcept(packet, sender);
+            }
+        }
+        
+        public void HandleRemovePlayer(int playerId, DisconnectReason reason)
+        {
+            if (_players.TryRemove(playerId, out var player))
+            {
+                player.Game = null;
+            }
+            
+            Logger.Information("{0} - Player {1} ({2}) has left.", CodeStr, player?.Client.Name, playerId);
+
+            // Game is empty, remove it.
+            if (_players.Count == 0)
+            {
+                GameState = GameStates.Destroyed;
+
+                // Remove instance reference.
+                _gameManager.Remove(Code);
+                return;
+            }
+
+            // Host migration.
+            if (HostId == playerId)
+            {
+                var newHost = _players.First().Value;
+                HostId = newHost.Client.Id;
+                Logger.Information("{0} - Assigned {1} ({2}) as new host.", CodeStr, newHost.Client.Name, newHost.Client.Id);
+            }
+
+            using (var packet = MessageWriter.Get(SendOption.Reliable))
+            {
+                WriteRemovePlayerMessage(packet, false, playerId, reason);
+                SendToAllExcept(packet, player);
+            }
+        }
+
+        public void HandleKickPlayer(int playerId, bool isBan)
+        {
+            _players.TryGetValue(playerId, out var p);
+            Logger.Information("{0} - Player {1} ({2}) has left.", CodeStr, p?.Client.Name, playerId);
+            
+            using (var message = MessageWriter.Get(SendOption.Reliable))
+            {
+                WriteKickPlayerMessage(message, false, playerId, isBan);
+                SendToAllExcept(message, null);
+                
+                if (_players.TryRemove(playerId, out var player))
+                {
+                    player.Game = null;
+
+                    if (isBan)
+                    {
+                        _bannedIps.Add(player.Client.Connection.EndPoint.Address);
+                    }
+                }
+                
+                WriteRemovePlayerMessage(message, true, playerId, isBan 
+                    ? DisconnectReason.Banned 
+                    : DisconnectReason.Kicked);
+                SendToAllExcept(message, player);
+            }
+        }
+        
+        private void HandleJoinGameNew(ClientPlayer sender)
+        {
+            Logger.Information("{0} - Player {1} ({2}) is joining.", CodeStr, sender.Client.Name, sender.Client.Id);
+            
+            // Store player.
+            if (!_players.TryAdd(sender.Client.Id, sender))
+            {
+                throw new AmongUsException("Failed to add player to game.");
+            }
+            
+            // Assign player to this game for future packets.
+            sender.Game = this;
+
+            // Assign hostId if none is set.
+            if (HostId == -1)
+            {
+                HostId = sender.Client.Id;
+            }
+
+            if (HostId == sender.Client.Id)
+            {
+                sender.LimboState = LimboStates.NotLimbo;
+            }
+
+            using (var message = MessageWriter.Get(SendOption.Reliable))
+            {
+                WriteJoinedGameMessage(message, false, sender);
+                WriteAlterGameMessage(message, false);
+                
+                sender.Client.Send(message);
+
+                BroadcastJoinMessage(message, true, sender);
+            }
+        }
+
+        private void HandleJoinGameNext(ClientPlayer sender)
+        {
+            Logger.Information("{0} - Player {1} ({2}) is rejoining.", CodeStr, sender.Client.Name, sender.Client.Id);
+            
+            if (sender.Client.Id == HostId)
+            {
+                GameState = GameStates.NotStarted;
+                HandleJoinGameNew(sender);
+
+                using (var message = MessageWriter.Get(SendOption.Reliable))
+                {
+                    foreach (var (_, player) in _players.Where(x => x.Value != sender))
+                    {
+                        WriteJoinedGameMessage(message, true, player);
+                        WriteAlterGameMessage(message, false);
+                        player.Client.Send(message);
+                    }
+                }
+                
+                return;
+            }
+
+            if (_players.Count >= 9)
+            {
+                sender.Client.Connection.Send(new Message1DisconnectReason(DisconnectReason.GameFull));
+                return;
+            }
+
+            // Store player.
+            if (!_players.TryAdd(sender.Client.Id, sender))
+            {
+                throw new AmongUsException("Failed to add player to game.");
+            }
+            
+            // Assign player to this game for future packets.
+            sender.Game = this;
+            
+            // Limbo, yes.
+            sender.LimboState = LimboStates.WaitingForHost;
+
+            using (var packet = MessageWriter.Get(SendOption.Reliable))
+            {
+                WriteWaitForHostMessage(packet, false, sender);
+                sender.Client.Send(packet);
+
+                BroadcastJoinMessage(packet, true, sender);
+            }
+        }
+
+        private void WriteRemovePlayerMessage(MessageWriter message, bool clear, int playerId, DisconnectReason reason)
+        {
+            // Only a subset of DisconnectReason shows an unique message.
+            // ExitGame, Banned and Kicked.
+            if (clear)
+            {
+                message.Clear(SendOption.Reliable);
+            }
+            
+            message.StartMessage((byte) RequestFlag.RemovePlayer);
+            message.Write(Code);
+            message.Write(playerId);
+            message.Write(HostId);
+            message.Write((byte) reason);
+            message.EndMessage();
+        }
+        
+        private void WriteJoinedGameMessage(MessageWriter message, bool clear, ClientPlayer player)
+        {
+            if (clear)
+            {
+                message.Clear(SendOption.Reliable);
+            }
+            
+            message.StartMessage((byte) RequestFlag.JoinedGame);
+            message.Write(Code);
+            message.Write(player.Client.Id);
+            message.Write(HostId);
+            message.WritePacked(_players.Count - 1);
+            
+            foreach (var (_, p) in _players.Where(x => x.Value != player))
+            {
+                message.WritePacked(p.Client.Id);
+            }
+            
+            message.EndMessage();
+        }
+
+        private void WriteAlterGameMessage(MessageWriter message, bool clear)
+        {
+            if (clear)
+            {
+                message.Clear(SendOption.Reliable);
+            }
+            
+            message.StartMessage((byte) RequestFlag.AlterGame);
+            message.Write(Code);
+            message.Write((byte) AlterGameTags.ChangePrivacy);
+            message.Write(IsPublic);
+            message.EndMessage();
+        }
+
+        private void WriteKickPlayerMessage(MessageWriter message, bool clear, int playerId, bool isBan)
+        {
+            if (clear)
+            {
+                message.Clear(SendOption.Reliable);
+            }
+            
+            message.StartMessage((byte) RequestFlag.KickPlayer);
+            message.Write(Code);
+            message.WritePacked(playerId);
+            message.Write(isBan);
+            message.EndMessage();
+        }
+        
+        private void WriteWaitForHostMessage(MessageWriter message, bool clear, ClientPlayer player)
+        {
+            if (clear)
+            {
+                message.Clear(SendOption.Reliable);
+            }
+            
+            message.StartMessage((byte) RequestFlag.WaitForHost);
+            message.Write(Code);
+            message.Write(player.Client.Id);
+            message.EndMessage();
+        }
+        
+        private void BroadcastJoinMessage(MessageWriter message, bool clear, ClientPlayer player)
+        {
+            if (clear)
+            {
+                message.Clear(SendOption.Reliable);
+            }
+            
+            message.StartMessage((byte) RequestFlag.JoinGame);
+            message.Write(Code);
+            message.Write(player.Client.Id);
+            message.Write(HostId);
+            message.EndMessage();
+            
+            SendToAllExcept(message, player);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Server/Net/GameManager.cs b/src/Impostor.Server/Net/GameManager.cs
new file mode 100644 (file)
index 0000000..664f640
--- /dev/null
@@ -0,0 +1,45 @@
+using System.Collections.Concurrent;
+using Impostor.Shared.Innersloth;
+using Serilog;
+
+namespace Impostor.Server.Net
+{
+    public class GameManager
+    {
+        private static readonly ILogger Logger = Log.ForContext<GameManager>();
+        
+        private readonly ConcurrentDictionary<int, Game> _games;
+
+        public GameManager()
+        {
+            _games = new ConcurrentDictionary<int, Game>();
+        }
+        
+        public Game Create(Client owner, GameOptionsData options)
+        {
+            var gameCode = GameCode.GenerateCode(6);
+            var game = new Game(this, gameCode, options);
+
+            if (_games.TryAdd(gameCode, game))
+            {
+                Logger.Debug("Created game with code {0} ({1}).", GameCode.IntToGameName(gameCode), gameCode);        
+                return game;
+            }
+
+            Logger.Warning("Failed to create game.");
+            return null;
+        }
+
+        public Game Find(int gameCode)
+        {
+            _games.TryGetValue(gameCode, out var game);
+            return game;
+        }
+
+        public void Remove(int gameCode)
+        {
+            Logger.Debug("Remove game with code {0} ({1}).", GameCode.IntToGameName(gameCode), gameCode);   
+            _games.TryRemove(gameCode, out _);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Server/Net/GameStates.cs b/src/Impostor.Server/Net/GameStates.cs
new file mode 100644 (file)
index 0000000..f24ecc5
--- /dev/null
@@ -0,0 +1,10 @@
+namespace Impostor.Server.Net
+{
+    public enum GameStates : byte
+    {
+        NotStarted = 0,
+        Started = 1,
+        Ended = 2,
+        Destroyed = 3
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Server/Net/Matchmaker.cs b/src/Impostor.Server/Net/Matchmaker.cs
new file mode 100644 (file)
index 0000000..8acc9d6
--- /dev/null
@@ -0,0 +1,60 @@
+using System.Net;
+using Hazel;
+using Hazel.Udp;
+using Impostor.Server.Extensions;
+using Impostor.Server.Net.Response;
+using Impostor.Shared.Innersloth.Data;
+using Serilog;
+using ILogger = Serilog.ILogger;
+
+namespace Impostor.Server.Net
+{
+    public class Matchmaker
+    {
+        private static readonly ILogger Logger = Log.ForContext<Matchmaker>();
+
+        private readonly GameManager _gameManager;
+        private readonly ClientManager _clientManager;
+        private readonly UdpConnectionListener _connection;
+        
+        public Matchmaker(IPAddress ip, int port)
+        {
+            _gameManager = new GameManager();
+            _clientManager = new ClientManager();
+            _connection = new UdpConnectionListener(new IPEndPoint(ip, port), IPMode.IPv4, s =>
+            {
+                Logger.Warning("Log from Hazel: {0}", s);
+            });
+            
+            _connection.NewConnection += OnNewConnection;
+        }
+
+        private void OnNewConnection(NewConnectionEventArgs e)
+        {
+            // Handshake.
+            var clientVersion = e.HandshakeData.ReadInt32();
+            var clientName = e.HandshakeData.ReadString();
+
+            e.HandshakeData.Recycle();
+                
+            if (clientVersion != 50516550)
+            {
+                e.Connection.Send(new Message1DisconnectReason(DisconnectReason.IncorrectVersion));
+                return;
+            }
+            
+            // Register client.
+            _clientManager.Add(new Client(_clientManager, _gameManager, _clientManager.NextId(), clientName, e.Connection));
+        }
+
+        public void Start()
+        {
+            _connection.Start();
+        }
+
+        public void Stop()
+        {
+            _connection.Dispose();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Server/Net/Response/Message1DisconnectReason.cs b/src/Impostor.Server/Net/Response/Message1DisconnectReason.cs
new file mode 100644 (file)
index 0000000..0ab5be4
--- /dev/null
@@ -0,0 +1,30 @@
+using Hazel;
+using Impostor.Shared.Innersloth.Data;
+
+namespace Impostor.Server.Net.Response
+{
+    public class Message1DisconnectReason : MessageBase
+    {
+        private readonly DisconnectReason _reason;
+        private readonly string _message;
+
+        // Notes:
+        // - Specifying no reason does something with ban minutes left.
+        // - (?) You were disconnected because Among Us was suspended by another app.
+        public Message1DisconnectReason(DisconnectReason reason, string message = null) : base(SendOption.Reliable, MessageFlag.DisconnectReason)
+        {
+            _reason = reason;
+            _message = message;
+        }
+
+        protected override void WriteMessage(MessageWriter writer)
+        {
+            writer.Write((int) _reason);
+
+            if (_reason == DisconnectReason.Custom)
+            {
+                writer.Write(_message);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Server/Net/Response/MessageBase.cs b/src/Impostor.Server/Net/Response/MessageBase.cs
new file mode 100644 (file)
index 0000000..d9fceab
--- /dev/null
@@ -0,0 +1,32 @@
+using System;
+using Hazel;
+
+namespace Impostor.Server.Net.Response
+{
+    public abstract class MessageBase : IDisposable
+    {
+        private readonly MessageWriter _writer;
+        private readonly MessageFlag _flag;
+
+        protected MessageBase(SendOption option, MessageFlag flag)
+        {
+            _writer = MessageWriter.Get(option);
+            _flag = flag;
+        }
+
+        public MessageWriter Write()
+        {
+            _writer.StartMessage((byte) _flag);
+            WriteMessage(_writer);
+            _writer.EndMessage();
+            return _writer;
+        }
+
+        protected abstract void WriteMessage(MessageWriter writer);
+
+        public void Dispose()
+        {
+            _writer.Dispose();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Server/Net/Response/MessageFlag.cs b/src/Impostor.Server/Net/Response/MessageFlag.cs
new file mode 100644 (file)
index 0000000..a29135d
--- /dev/null
@@ -0,0 +1,7 @@
+namespace Impostor.Server.Net.Response
+{
+    public enum MessageFlag : byte
+    {
+        DisconnectReason = 1
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Server/Program.cs b/src/Impostor.Server/Program.cs
new file mode 100644 (file)
index 0000000..9dab491
--- /dev/null
@@ -0,0 +1,41 @@
+using System;
+using System.Net;
+using System.Threading;
+using Impostor.Server.Net;
+using Serilog;
+
+namespace Impostor.Server
+{
+    internal static class Program
+    {
+        private static readonly ManualResetEvent QuitEvent = new ManualResetEvent(false);
+        
+        private static void Main(string[] args)
+        {
+            // Listen for CTRL+C.
+            Console.CancelKeyPress += (sender, e) =>
+            {
+                e.Cancel = true;
+                QuitEvent.Set();
+            };
+            
+            // Configure logger.
+            Log.Logger = new LoggerConfiguration()
+#if DEBUG
+                .MinimumLevel.Verbose()
+#else
+                .MinimumLevel.Information()
+#endif
+                .WriteTo.Console()
+                .CreateLogger();
+
+            // Initialize matchmaker.
+            var matchMaker = new Matchmaker(IPAddress.Any, 22023);
+            matchMaker.Start();
+            Log.Logger.Information("Matchmaker is running on *:22023.");
+            QuitEvent.WaitOne();
+            Log.Logger.Warning("Matchmaker is shutting down!");
+            matchMaker.Stop();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Shared/Impostor.Shared.csproj b/src/Impostor.Shared/Impostor.Shared.csproj
new file mode 100644 (file)
index 0000000..8642d92
--- /dev/null
@@ -0,0 +1,7 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+    <PropertyGroup>
+        <TargetFramework>netcoreapp3.1</TargetFramework>
+    </PropertyGroup>
+
+</Project>
diff --git a/src/Impostor.Shared/Innersloth/Data/AlterGameTags.cs b/src/Impostor.Shared/Innersloth/Data/AlterGameTags.cs
new file mode 100644 (file)
index 0000000..c246183
--- /dev/null
@@ -0,0 +1,7 @@
+namespace Impostor.Shared.Innersloth.Data
+{
+    public enum AlterGameTags : byte
+    {
+        ChangePrivacy = 1
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Shared/Innersloth/Data/DisconnectReason.cs b/src/Impostor.Shared/Innersloth/Data/DisconnectReason.cs
new file mode 100644 (file)
index 0000000..f3f9b66
--- /dev/null
@@ -0,0 +1,56 @@
+namespace Impostor.Shared.Innersloth.Data
+{
+    public enum DisconnectReason
+    {
+        ExitGame = 0,
+        Destroy = 16,
+        // The game you tried to join is full.
+        // Check with the host to see if you can join next round.
+        GameFull = 1,
+        // The game you tried to join already started.
+        // Check with the host to see if you can join next round.
+        GameStarted = 2,
+        // Could not find the game you're looking for.
+        GameMissing = 3,
+        IncorrectGame = 18,
+        // For these a message can be given, specifying an empty message shows
+        // "An unknown error disconnected you from the server."
+        CustomMessage1 = 4,
+        Custom = 8,
+        // CustomMessage3 = 11,
+        // CustomMessage4 = 12,
+        // CustomMessage5 = 13,
+        // CustomMessage6 = 14,
+        // CustomMessage7 = 15,
+        // You are running an older version of the game.
+        // Please update to play with others.
+        IncorrectVersion = 5,
+        // You cannot rejoin that room.
+        // You were banned
+        Banned = 6,
+        // You can rejoin if the room hasn't started
+        // You were kicked
+        Kicked = 7,
+        // Server refused username: %USERNAME%
+        InvalidName = 9,
+        // You were banned for hacking.
+        // Please stop.
+        Hacking = 10,
+        // You disconnected from the host.
+        // If this happens often, check your WiFi strength.
+        //
+        // You disconnected from the server.
+        // If this happens often, check your network strength.
+        // This may also be a server issue.
+        Error = 17,
+        // The server stopped this game. Possibly due to inactivity.
+        ServerRequest = 19,
+        // The Among Us servers are overloaded.
+        // Sorry! Please try again later!
+        ServerFull = 20,
+        FocusLostBackground = 207,
+        IntentionalLeaving = 208,
+        FocusLost = 209,
+        NewConnection = 210
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Shared/Innersloth/Data/GameKeywords.cs b/src/Impostor.Shared/Innersloth/Data/GameKeywords.cs
new file mode 100644 (file)
index 0000000..daefefe
--- /dev/null
@@ -0,0 +1,19 @@
+using System;
+
+namespace Impostor.Shared.Innersloth.Data
+{
+    [Flags]
+    public enum GameKeywords : uint
+    {
+        All = 0,
+        Other = 1,
+        Spanish = 2,
+        Korean = 4,
+        Russian = 8,
+        Portuguese = 16,
+        Arabic = 32,
+        Filipone = 64,
+        Polish = 128,
+        English = 256
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Shared/Innersloth/Data/GameStates.cs b/src/Impostor.Shared/Innersloth/Data/GameStates.cs
new file mode 100644 (file)
index 0000000..ec2a2f2
--- /dev/null
@@ -0,0 +1,10 @@
+namespace Impostor.Shared.Innersloth.Data
+{
+    public enum GameStates : byte
+    {
+        NotStarted,
+        Started,
+        Ended,
+        Destroyed
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Shared/Innersloth/Data/LimboStates.cs b/src/Impostor.Shared/Innersloth/Data/LimboStates.cs
new file mode 100644 (file)
index 0000000..e501614
--- /dev/null
@@ -0,0 +1,9 @@
+namespace Impostor.Shared.Innersloth.Data
+{
+    public enum LimboStates
+    {
+        PreSpawn,
+        NotLimbo,
+        WaitingForHost,
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Shared/Innersloth/Data/RequestFlag.cs b/src/Impostor.Shared/Innersloth/Data/RequestFlag.cs
new file mode 100644 (file)
index 0000000..d07eefa
--- /dev/null
@@ -0,0 +1,22 @@
+namespace Impostor.Shared.Innersloth.Data
+{
+    public enum RequestFlag : byte
+    {
+        HostGame = 0,
+        JoinGame = 1,
+        StartGame = 2,
+        RemoveGame = 3,
+        RemovePlayer = 4,
+        GameData = 5,
+        GameDataTo = 6,
+        JoinedGame = 7,
+        EndGame = 8,
+        GetGameList = 9,
+        AlterGame = 10,
+        KickPlayer = 11,
+        WaitForHost = 12,
+        Redirect = 13,
+        ReselectServer = 14,
+        GetGameListV2 = 16,
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Shared/Innersloth/GameCode.cs b/src/Impostor.Shared/Innersloth/GameCode.cs
new file mode 100644 (file)
index 0000000..8f01fde
--- /dev/null
@@ -0,0 +1,130 @@
+using System;
+using System.Buffers.Binary;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Impostor.Shared.Innersloth
+{
+    public static class GameCode
+    {
+        private const string V2 = "QWXRTYLPESDFGHUJKZOCVBINMA";
+        private static readonly int[] V2Map = {
+            25,
+            21,
+            19,
+            10,
+            8,
+            11,
+            12,
+            13,
+            22,
+            15,
+            16,
+            6,
+            24,
+            23,
+            18,
+            7,
+            0,
+            3,
+            9,
+            4,
+            14,
+            20,
+            1,
+            2,
+            5,
+            17
+        };
+        private static readonly RNGCryptoServiceProvider Random = new RNGCryptoServiceProvider();
+        
+        public static string IntToGameName(int input)
+        {
+            // V2.
+            if (input < -1)
+            {
+                return IntToGameNameV2(input);
+            }
+
+            // V1.
+            Span<byte> code = stackalloc byte[4];
+            BinaryPrimitives.WriteInt32LittleEndian(code, input);
+            return Encoding.UTF8.GetString(code.Slice(0, 4));
+        }
+
+        private static string IntToGameNameV2(int input)
+        {
+            var a = input & 0x3FF;
+            var b = (input >> 10) & 0xFFFFF;
+
+            return new string(new []
+            {
+                V2[a % 26],
+                V2[a / 26],
+                V2[b % 26],
+                V2[b / 26 % 26],
+                V2[b / (26 * 26) % 26],
+                V2[b / (26 * 26 * 26) % 26]
+            });
+        }
+
+        public static int GameNameToInt(string code)
+        {
+            var upper = code.ToUpperInvariant();
+            if (upper.Any(x => !char.IsLetter(x)))
+            {
+                return -1;
+            }
+            
+            var len = code.Length;
+            if (len == 6)
+            {
+                return GameNameToIntV2(upper);
+            }
+
+            if (len == 4)
+            {
+                return code[0] | ((code[1] | ((code[2] | (code[3] << 8)) << 8)) << 8);
+            }
+            
+            return -1;
+        }
+        
+        private static int GameNameToIntV2(string code)
+        {
+            var a = V2Map[code[0] - 65];
+            var b = V2Map[code[1] - 65];
+            var c = V2Map[code[2] - 65];
+            var d = V2Map[code[3] - 65];
+            var e = V2Map[code[4] - 65];
+            var f = V2Map[code[5] - 65];
+
+            var one = (a + 26 * b) & 0x3FF;
+            var two = (c + 26 * (d + 26 * (e + 26 * f)));
+
+            return (int) (one | ((two << 10) & 0x3FFFFC00) | 0x80000000);
+        }
+
+        public static int GenerateCode(int len)
+        {
+            if (len != 4 && len != 6)
+            {
+                throw new ArgumentException("should be 4 or 6", nameof(len));
+            }
+            
+            // Generate random bytes.
+            Span<byte> data = stackalloc byte[len];
+            Random.GetBytes(data);
+            
+            // Convert to their char representation.
+            Span<char> dataChar = stackalloc char[len];
+            for (var i = 0; i < len; i++)
+            {
+                dataChar[i] = V2[V2Map[data[i] % 26]];
+            }
+            
+            return GameNameToInt(new string(dataChar));
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Shared/Innersloth/GameOptionsData.cs b/src/Impostor.Shared/Innersloth/GameOptionsData.cs
new file mode 100644 (file)
index 0000000..711edb1
--- /dev/null
@@ -0,0 +1,76 @@
+using System;
+using System.IO;
+using Impostor.Shared.Innersloth.Data;
+
+namespace Impostor.Shared.Innersloth
+{
+    public class GameOptionsData
+    {
+        public byte Version { get; set; }
+        public byte MaxPlayers { get; set; }
+        public GameKeywords Keywords { get; set; }
+        public byte MapId { get; set; }
+        public float PlayerSpeedMod { get; set; }
+        public float CrewLightMod { get; set; }
+        public float ImpostorLightMod { get; set; }
+        public float KillCooldown { get; set; }
+        public int NumCommonTasks { get; set; }
+        public int NumLongTasks { get; set; }
+        public int NumShortTasks { get; set; }
+        public int NumEmergencyMeetings { get; set; }
+        public int EmergencyCooldown { get; set; }
+        public int NumImpostors { get; set; }
+        public bool GhostsDoTasks { get; set; }
+        public int KillDistance { get; set; }
+        public int DiscussionTime { get; set; }
+        public int VotingTime { get; set; }
+        public bool ConfirmImpostor { get; set; }
+        public bool VisualTasks { get; set; }
+        public bool IsDefaults { get; set; }
+        
+        public void Serialize(BinaryWriter writer, byte version)
+        {
+            throw new NotImplementedException();
+        }
+
+        public static GameOptionsData Deserialize(byte[] bytes)
+        {
+            using (var stream = new MemoryStream(bytes))
+            using (var reader = new BinaryReader(stream))
+            {
+                var result = new GameOptionsData();
+
+                result.Version = reader.ReadByte();
+                result.MaxPlayers = reader.ReadByte();
+                result.Keywords = (GameKeywords) reader.ReadUInt32();
+                result.MapId = reader.ReadByte();
+                result.PlayerSpeedMod = reader.ReadSingle();
+                result.CrewLightMod = reader.ReadSingle();
+                result.ImpostorLightMod = reader.ReadSingle();
+                result.KillCooldown = reader.ReadSingle();
+                result.NumCommonTasks = reader.ReadByte();
+                result.NumLongTasks = reader.ReadByte();
+                result.NumShortTasks = reader.ReadByte();
+                result.NumEmergencyMeetings = reader.ReadInt32();
+                result.NumImpostors = reader.ReadByte();
+                result.KillDistance = reader.ReadByte();
+                result.DiscussionTime = reader.ReadInt32();
+                result.VotingTime = reader.ReadInt32();
+                result.IsDefaults = reader.ReadBoolean();
+
+                if (result.Version > 1)
+                {
+                    result.EmergencyCooldown = reader.ReadByte();
+                }
+
+                if (result.Version > 2)
+                {
+                    result.ConfirmImpostor = reader.ReadBoolean();
+                    result.VisualTasks = reader.ReadBoolean();
+                }
+                
+                return result;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Shared/Innersloth/RegionInfo.cs b/src/Impostor.Shared/Innersloth/RegionInfo.cs
new file mode 100644 (file)
index 0000000..926bd8d
--- /dev/null
@@ -0,0 +1,48 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace Impostor.Shared.Innersloth
+{
+    public class RegionInfo
+    {
+        public RegionInfo(string name, string ping, IReadOnlyList<ServerInfo> servers)
+        {
+            Name = name;
+            Ping = ping;
+            Servers = servers;
+        }
+        
+        public string Name { get; }
+        public string Ping { get; }
+        public IReadOnlyList<ServerInfo> Servers { get; }
+        
+        public void Serialize(BinaryWriter writer)
+        {
+            writer.Write(0);
+            writer.Write(Name);
+            writer.Write(Ping);
+            writer.Write(Servers.Count);
+            
+            foreach (var server in Servers)
+            {
+                server.Serialize(writer);
+            }
+        }
+
+        public static RegionInfo Deserialize(BinaryReader reader)
+        {
+            var unknown = reader.ReadInt32();
+            var name = reader.ReadString();
+            var ping = reader.ReadString();
+            var servers = new List<ServerInfo>();
+            var serverCount = reader.ReadInt32();
+
+            for (var i = 0; i < serverCount; i++)
+            {
+                servers.Add(ServerInfo.Deserialize(reader)); 
+            }
+            
+            return new RegionInfo(name, ping, servers);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Shared/Innersloth/ServerInfo.cs b/src/Impostor.Shared/Innersloth/ServerInfo.cs
new file mode 100644 (file)
index 0000000..c76a7e4
--- /dev/null
@@ -0,0 +1,37 @@
+using System.IO;
+using System.Net;
+
+namespace Impostor.Shared.Innersloth
+{
+    public class ServerInfo
+    {
+        public string Name { get; }
+        public string Ip { get; }
+        public ushort Port { get; }
+
+        public ServerInfo(string name, string ip, ushort port)
+        {
+            Name = name;
+            Ip = ip;
+            Port = port;
+        }
+        
+        public void Serialize(BinaryWriter writer)
+        {
+            writer.Write(Name);
+            writer.Write(IPAddress.Parse(Ip).GetAddressBytes());
+            writer.Write(Port);
+            writer.Write(0);
+        }
+
+        public static ServerInfo Deserialize(BinaryReader reader)
+        {
+            var name = reader.ReadString();
+            var ip = new IPAddress(reader.ReadBytes(4)).ToString();
+            var port = reader.ReadUInt16();
+            var unknown = reader.ReadInt32();
+            
+            return new ServerInfo(name, ip, port);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Shared/Utils/HexUtils.cs b/src/Impostor.Shared/Utils/HexUtils.cs
new file mode 100644 (file)
index 0000000..04e497b
--- /dev/null
@@ -0,0 +1,70 @@
+using System;
+using System.Text;
+
+namespace Impostor.Shared.Utils
+{
+    public static class HexUtils
+    {
+        public static string HexDump(byte[] bytes, int bytesPerLine = 16)
+        {
+            if (bytes == null) return "<null>";
+            int bytesLength = bytes.Length;
+
+            char[] HexChars = "0123456789ABCDEF".ToCharArray();
+
+            int firstHexColumn =
+                  8                   // 8 characters for the address
+                + 3;                  // 3 spaces
+
+            int firstCharColumn = firstHexColumn
+                + bytesPerLine * 3       // - 2 digit for the hexadecimal value and 1 space
+                + (bytesPerLine - 1) / 8 // - 1 extra space every 8 characters from the 9th
+                + 2;                  // 2 spaces 
+
+            int lineLength = firstCharColumn
+                + bytesPerLine           // - characters to show the ascii value
+                + Environment.NewLine.Length; // Carriage return and line feed (should normally be 2)
+
+            char[] line = (new String(' ', lineLength - Environment.NewLine.Length) + Environment.NewLine).ToCharArray();
+            int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine;
+            StringBuilder result = new StringBuilder(expectedLines * lineLength);
+
+            for (int i = 0; i < bytesLength; i += bytesPerLine)
+            {
+                line[0] = HexChars[(i >> 28) & 0xF];
+                line[1] = HexChars[(i >> 24) & 0xF];
+                line[2] = HexChars[(i >> 20) & 0xF];
+                line[3] = HexChars[(i >> 16) & 0xF];
+                line[4] = HexChars[(i >> 12) & 0xF];
+                line[5] = HexChars[(i >> 8) & 0xF];
+                line[6] = HexChars[(i >> 4) & 0xF];
+                line[7] = HexChars[(i >> 0) & 0xF];
+
+                int hexColumn = firstHexColumn;
+                int charColumn = firstCharColumn;
+
+                for (int j = 0; j < bytesPerLine; j++)
+                {
+                    if (j > 0 && (j & 7) == 0) hexColumn++;
+                    if (i + j >= bytesLength)
+                    {
+                        line[hexColumn] = ' ';
+                        line[hexColumn + 1] = ' ';
+                        line[charColumn] = ' ';
+                    }
+                    else
+                    {
+                        byte b = bytes[i + j];
+                        line[hexColumn] = HexChars[(b >> 4) & 0xF];
+                        line[hexColumn + 1] = HexChars[b & 0xF];
+                        line[charColumn] = (b < 32 ? '·' : (char)b);
+                    }
+                    hexColumn += 3;
+                    charColumn++;
+                }
+                result.Append(line);
+            }
+            return result.ToString();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Tests/GameCodeTests.cs b/src/Impostor.Tests/GameCodeTests.cs
new file mode 100644 (file)
index 0000000..24e6171
--- /dev/null
@@ -0,0 +1,28 @@
+using Impostor.Shared.Innersloth;
+using Xunit;
+
+namespace Impostor.Tests
+{
+    public class GameCodeTests
+    {
+        [Fact]
+        public void CodeV1()
+        {
+            const string code = "ABCD";
+            const int codeInt = 0x44434241;
+            
+            Assert.Equal(code, GameCode.IntToGameName(codeInt));
+            Assert.Equal(codeInt, GameCode.GameNameToInt(code));
+        }
+        
+        [Fact]
+        public void CodeV2()
+        {
+            const string code = "ABCDEF";
+            const int codeInt = -1943683525;
+            
+            Assert.Equal(code, GameCode.IntToGameName(codeInt));
+            Assert.Equal(codeInt, GameCode.GameNameToInt(code));
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Tests/Impostor.Tests.csproj b/src/Impostor.Tests/Impostor.Tests.csproj
new file mode 100644 (file)
index 0000000..88929eb
--- /dev/null
@@ -0,0 +1,20 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+    <PropertyGroup>
+        <TargetFramework>netcoreapp3.1</TargetFramework>
+
+        <IsPackable>false</IsPackable>
+    </PropertyGroup>
+
+    <ItemGroup>
+        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
+        <PackageReference Include="xunit" Version="2.4.0" />
+        <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
+        <PackageReference Include="coverlet.collector" Version="1.2.0" />
+    </ItemGroup>
+
+    <ItemGroup>
+      <ProjectReference Include="..\Impostor.Shared\Impostor.Shared.csproj" />
+    </ItemGroup>
+
+</Project>
diff --git a/src/Impostor.Tools.Proxy/HexUtils.cs b/src/Impostor.Tools.Proxy/HexUtils.cs
new file mode 100644 (file)
index 0000000..79517b4
--- /dev/null
@@ -0,0 +1,70 @@
+using System;
+using System.Text;
+
+namespace Impostor.Tools.Proxy
+{
+    public static class HexUtils
+    {
+        public static string HexDump(byte[] bytes, int bytesPerLine = 16)
+        {
+            if (bytes == null) return "<null>";
+            int bytesLength = bytes.Length;
+
+            char[] HexChars = "0123456789ABCDEF".ToCharArray();
+
+            int firstHexColumn =
+                  8                   // 8 characters for the address
+                + 3;                  // 3 spaces
+
+            int firstCharColumn = firstHexColumn
+                + bytesPerLine * 3       // - 2 digit for the hexadecimal value and 1 space
+                + (bytesPerLine - 1) / 8 // - 1 extra space every 8 characters from the 9th
+                + 2;                  // 2 spaces 
+
+            int lineLength = firstCharColumn
+                + bytesPerLine           // - characters to show the ascii value
+                + Environment.NewLine.Length; // Carriage return and line feed (should normally be 2)
+
+            char[] line = (new String(' ', lineLength - Environment.NewLine.Length) + Environment.NewLine).ToCharArray();
+            int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine;
+            StringBuilder result = new StringBuilder(expectedLines * lineLength);
+
+            for (int i = 0; i < bytesLength; i += bytesPerLine)
+            {
+                line[0] = HexChars[(i >> 28) & 0xF];
+                line[1] = HexChars[(i >> 24) & 0xF];
+                line[2] = HexChars[(i >> 20) & 0xF];
+                line[3] = HexChars[(i >> 16) & 0xF];
+                line[4] = HexChars[(i >> 12) & 0xF];
+                line[5] = HexChars[(i >> 8) & 0xF];
+                line[6] = HexChars[(i >> 4) & 0xF];
+                line[7] = HexChars[(i >> 0) & 0xF];
+
+                int hexColumn = firstHexColumn;
+                int charColumn = firstCharColumn;
+
+                for (int j = 0; j < bytesPerLine; j++)
+                {
+                    if (j > 0 && (j & 7) == 0) hexColumn++;
+                    if (i + j >= bytesLength)
+                    {
+                        line[hexColumn] = ' ';
+                        line[hexColumn + 1] = ' ';
+                        line[charColumn] = ' ';
+                    }
+                    else
+                    {
+                        byte b = bytes[i + j];
+                        line[hexColumn] = HexChars[(b >> 4) & 0xF];
+                        line[hexColumn + 1] = HexChars[b & 0xF];
+                        line[charColumn] = (b < 32 ? '·' : (char)b);
+                    }
+                    hexColumn += 3;
+                    charColumn++;
+                }
+                result.Append(line);
+            }
+            return result.ToString();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Impostor.Tools.Proxy/Impostor.Tools.Proxy.csproj b/src/Impostor.Tools.Proxy/Impostor.Tools.Proxy.csproj
new file mode 100644 (file)
index 0000000..1a89dbd
--- /dev/null
@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+    <PropertyGroup>
+        <OutputType>Exe</OutputType>
+        <TargetFramework>net452</TargetFramework>
+    </PropertyGroup>
+
+    <ItemGroup>
+      <PackageReference Include="Pcap.Net.x64" Version="1.0.4.1" />
+    </ItemGroup>
+
+    <ItemGroup>
+      <ProjectReference Include="..\..\submodules\Hazel-Networking\Hazel\Hazel.csproj" />
+    </ItemGroup>
+
+</Project>
diff --git a/src/Impostor.Tools.Proxy/Program.cs b/src/Impostor.Tools.Proxy/Program.cs
new file mode 100644 (file)
index 0000000..539463c
--- /dev/null
@@ -0,0 +1,183 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Hazel;
+using Hazel.Udp;
+using PcapDotNet.Core;
+using PcapDotNet.Packets;
+
+namespace Impostor.Tools.Proxy
+{
+    internal static class Program
+    {
+        private const string DeviceName = "Intel(R) I211 Gigabit Network Connection";
+
+        private static readonly Dictionary<byte, string> TagMap = new Dictionary<byte, string>
+        {
+            {0, "HostGame"},
+            {1, "JoinGame"},
+            {2, "StartGame"},
+            {3, "RemoveGame"},
+            {4, "RemovePlayer"},
+            {5, "GameData"},
+            {6, "GameDataTo"},
+            {7, "JoinedGame"},
+            {8, "EndGame"},
+            {9, "GetGameList"},
+            {10, "AlterGame"},
+            {11, "KickPlayer"},
+            {12, "WaitForHost"},
+            {13, "Redirect"},
+            {14, "ReselectServer"},
+            {16, "GetGameListV2"}
+        };
+        
+        private static void Main(string[] args)
+        {
+            var devices = LivePacketDevice.AllLocalMachine;
+            if (devices.Count == 0)
+            {
+                Console.WriteLine("No interfaces found! Make sure WinPcap is installed.");
+                return;
+            }
+
+            var device = devices.FirstOrDefault(x => x.Description.Contains(DeviceName));
+            if (device == null)
+            {
+                Console.WriteLine("Unable to find configured device.");
+                return;
+            }
+
+            using (var communicator = device.Open(65536, PacketDeviceOpenAttributes.Promiscuous, 1000))
+            {
+                using (var filter = communicator.CreateFilter("udp and port 22023"))
+                {
+                    communicator.SetFilter(filter);
+                }
+
+                communicator.ReceivePackets(0, PacketHandler);
+            }
+        }
+
+        private static void PacketHandler(Packet packet)
+        {
+            var ip = packet.Ethernet.IpV4;
+            var ipSrc = ip.Source.ToString();
+            var udp = ip.Udp;
+            
+            // True if this is our own packet.
+            using (var stream = udp.Payload.ToMemoryStream())
+            {
+                var reader = MessageReader.Get(stream.ToArray());
+                if (reader.Buffer[0] == (byte) SendOption.Reliable)
+                {
+                    reader.Offset = 3;
+                    reader.Length = udp.Payload.Length - 3;
+                    reader.Position = 0;
+                }
+                else if (reader.Buffer[0] == (byte) UdpSendOption.Acknowledgement ||
+                         reader.Buffer[0] == (byte) UdpSendOption.Ping ||
+                         reader.Buffer[0] == (byte) UdpSendOption.Hello ||
+                         reader.Buffer[0] == (byte) UdpSendOption.Disconnect)
+                {
+                    return;
+                }
+                else
+                {
+                    reader.Offset = 1;
+                    reader.Length = udp.Payload.Length - 1;
+                    reader.Position = 0;
+                }
+                
+                var isSent = ipSrc.StartsWith("192.");
+                
+                while (true)
+                {
+                    if (reader.Position >= reader.Length)
+                    {
+                        break;
+                    }
+
+                    var message = reader.ReadMessage();
+                    if (isSent)
+                    {
+                        HandleToServer(ipSrc, message);
+                    }
+                    else
+                    {
+                        HandleToClient(ipSrc, message);
+                    }
+                    
+                    if (message.Position < message.Length)
+                    {
+                        Console.ForegroundColor = ConsoleColor.Red;
+                        Console.WriteLine("- Did not consume all bytes.");
+                    }
+                }
+            }
+        }
+
+        private static void HandleToClient(string source, MessageReader packet)
+        {
+            var tagName = TagMap.ContainsKey(packet.Tag) ? TagMap[packet.Tag] : "Unknown";
+            Console.ForegroundColor = ConsoleColor.Cyan;
+            Console.WriteLine($"{source,-15} Client received: {packet.Tag,-2} {tagName}");
+
+            switch (packet.Tag)
+            {
+                case 14:
+                case 13:
+                    packet.Position = packet.Length;
+                    break;
+                case 0:
+                    Console.WriteLine("- GameCode        " + packet.ReadInt32());
+                    break;
+                case 5:
+                case 6:
+                    Console.WriteLine(HexUtils.HexDump(packet.Buffer.Take(packet.Length).ToArray()));
+                    packet.Position = packet.Length;
+                    break;
+                case 7:
+                    Console.WriteLine("- GameCode        " + packet.ReadInt32());
+                    Console.WriteLine("- PlayerId        " + packet.ReadInt32());
+                    Console.WriteLine("- Host            " + packet.ReadInt32());
+                    var playerCount = packet.ReadPackedInt32();
+                    Console.WriteLine("- PlayerCount     " + playerCount);
+                    for (var i = 0; i < playerCount; i++)
+                    {
+                        Console.WriteLine("-     PlayerId    " + packet.ReadPackedInt32());
+                    }
+                    break;
+                case 10:
+                    Console.WriteLine("- GameCode        " + packet.ReadInt32());
+                    Console.WriteLine("- Flag            " + packet.ReadSByte());
+                    Console.WriteLine("- Value           " + packet.ReadBoolean());
+                    break;
+            }
+        }
+
+        private static void HandleToServer(string source, MessageReader packet)
+        {
+            var tagName = TagMap.ContainsKey(packet.Tag) ? TagMap[packet.Tag] : "Unknown";
+            Console.ForegroundColor = ConsoleColor.White;
+            Console.WriteLine($"{source,-15} Server received: {packet.Tag,-2} {tagName}");
+
+            switch (packet.Tag)
+            {
+                case 0:
+                    Console.WriteLine("- GameInfo length " + packet.ReadBytesAndSize().Length);
+                    break;
+                case 1:
+                    Console.WriteLine("- GameCode        " + packet.ReadInt32());
+                    Console.WriteLine("- Unknown         " + packet.ReadByte());
+                    break;
+                case 5:
+                case 6:
+                    Console.WriteLine("- GameCode        " + packet.ReadInt32());
+                    Console.WriteLine(HexUtils.HexDump(packet.Buffer.Take(packet.Length).ToArray()));
+                    packet.Position = packet.Length;
+                    break;
+            }
+        }
+    }
+}
diff --git a/src/Impostor.sln b/src/Impostor.sln
new file mode 100644 (file)
index 0000000..6f6f969
--- /dev/null
@@ -0,0 +1,97 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30503.244
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Imposter.Agent", "Imposter.Agent\Imposter.Agent.vcxproj", "{097BE795-88E9-4E7B-92F3-F6DDDBE3F012}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Imposter.Server", "Imposter.Server\Imposter.Server.csproj", "{1B0390AF-A4F3-4FE4-B093-708B0135C0B3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Imposter.Client", "Imposter.Client\Imposter.Client.csproj", "{24F07173-D4A7-41C6-BA51-4516AB68343C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Imposter.Shared", "Imposter.Shared\Imposter.Shared.csproj", "{1D109A96-FADF-41B9-A845-457A7A5C0C5A}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "submodules", "submodules", "{DFA3CC6A-A27C-4713-876D-A55912C78C45}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hazel", "..\submodules\Hazel-Networking\Hazel\Hazel.csproj", "{02CFBD30-D77D-400F-94B2-700F60EFDD7F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Imposter.Tests", "Imposter.Tests\Imposter.Tests.csproj", "{C1385C67-A7DD-46D2-80F6-FA428B85FB22}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{56DD9707-D811-4056-9E2C-8A9CC2479B07}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Imposter.Tools.Proxy", "Imposter.Tools.Proxy\Imposter.Tools.Proxy.csproj", "{D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Any CPU = Debug|Any CPU
+               Debug|x86 = Debug|x86
+               Release|Any CPU = Release|Any CPU
+               Release|x86 = Release|x86
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {097BE795-88E9-4E7B-92F3-F6DDDBE3F012}.Debug|Any CPU.ActiveCfg = Debug|Win32
+               {097BE795-88E9-4E7B-92F3-F6DDDBE3F012}.Debug|x86.ActiveCfg = Debug|Win32
+               {097BE795-88E9-4E7B-92F3-F6DDDBE3F012}.Debug|x86.Build.0 = Debug|Win32
+               {097BE795-88E9-4E7B-92F3-F6DDDBE3F012}.Release|Any CPU.ActiveCfg = Release|Win32
+               {097BE795-88E9-4E7B-92F3-F6DDDBE3F012}.Release|x86.ActiveCfg = Release|Win32
+               {097BE795-88E9-4E7B-92F3-F6DDDBE3F012}.Release|x86.Build.0 = Release|Win32
+               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Debug|x86.Build.0 = Debug|Any CPU
+               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Release|Any CPU.Build.0 = Release|Any CPU
+               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Release|x86.ActiveCfg = Release|Any CPU
+               {1B0390AF-A4F3-4FE4-B093-708B0135C0B3}.Release|x86.Build.0 = Release|Any CPU
+               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Debug|x86.Build.0 = Debug|Any CPU
+               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Release|Any CPU.Build.0 = Release|Any CPU
+               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Release|x86.ActiveCfg = Release|Any CPU
+               {24F07173-D4A7-41C6-BA51-4516AB68343C}.Release|x86.Build.0 = Release|Any CPU
+               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Debug|x86.Build.0 = Debug|Any CPU
+               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Release|Any CPU.Build.0 = Release|Any CPU
+               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Release|x86.ActiveCfg = Release|Any CPU
+               {1D109A96-FADF-41B9-A845-457A7A5C0C5A}.Release|x86.Build.0 = Release|Any CPU
+               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Debug|x86.Build.0 = Debug|Any CPU
+               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Release|Any CPU.Build.0 = Release|Any CPU
+               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Release|x86.ActiveCfg = Release|Any CPU
+               {02CFBD30-D77D-400F-94B2-700F60EFDD7F}.Release|x86.Build.0 = Release|Any CPU
+               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Debug|x86.Build.0 = Debug|Any CPU
+               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Release|Any CPU.Build.0 = Release|Any CPU
+               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Release|x86.ActiveCfg = Release|Any CPU
+               {C1385C67-A7DD-46D2-80F6-FA428B85FB22}.Release|x86.Build.0 = Release|Any CPU
+               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Debug|x86.Build.0 = Debug|Any CPU
+               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Release|Any CPU.Build.0 = Release|Any CPU
+               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Release|x86.ActiveCfg = Release|Any CPU
+               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D}.Release|x86.Build.0 = Release|Any CPU
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+       GlobalSection(ExtensibilityGlobals) = postSolution
+               SolutionGuid = {06245255-E585-483C-A4AD-71B7B568C6C8}
+       EndGlobalSection
+       GlobalSection(NestedProjects) = preSolution
+               {02CFBD30-D77D-400F-94B2-700F60EFDD7F} = {DFA3CC6A-A27C-4713-876D-A55912C78C45}
+               {D16B8DE9-8EE2-4F6A-9352-305D5AB0233D} = {56DD9707-D811-4056-9E2C-8A9CC2479B07}
+       EndGlobalSection
+EndGlobal