diff --git a/r5dedicated/console.cpp b/r5dedicated/console.cpp
index a9be9e56..6cdc996a 100644
--- a/r5dedicated/console.cpp
+++ b/r5dedicated/console.cpp
@@ -1,5 +1,6 @@
 #include "pch.h"
 #include "hooks.h"
+#include "opcodes.h"
 #include "console.h"
 
 //#############################################################################
@@ -80,6 +81,7 @@ DWORD __stdcall ProcessConsoleWorker(LPVOID)
 		// Exec toggles
 		if (sCommand == "1") { addr_CommandExecute(NULL, "exec autoexec_dev"); }
 		if (sCommand == "2") { g_bDebugLoading = !g_bDebugLoading; continue; }
+		if (sCommand == "3") { SetCHostState(); continue; } // TEST
 
 		///////////////////////////////////////////////////////////////////////
 		// Execute the command in the r5 SQVM
diff --git a/r5dedicated/csourceappsystemgroup.cpp b/r5dedicated/csourceappsystemgroup.cpp
new file mode 100644
index 00000000..bffa7cc3
--- /dev/null
+++ b/r5dedicated/csourceappsystemgroup.cpp
@@ -0,0 +1,36 @@
+#include "pch.h"
+#include "hooks.h"
+
+namespace Hooks
+{
+	CSourceAppSystemGroup_CreateFn originalCSourceAppSystemGroup_Create = nullptr;
+}
+auto g_bIsDedicated = (uint8_t*)0x162C61208;
+
+//-----------------------------------------------------------------------------
+// Purpose: sets 'EbisuSDK' globals required in certain engine callbacks.
+//-----------------------------------------------------------------------------
+void HEbisuSDK_Init()
+{
+	auto ofs000 = (uint8_t*)0x1634F1690;
+	auto ofs001 = (uint8_t*)0x1634F16B0;
+	auto ofs002 = (uint8_t*)0x1634F1695;
+	auto ofs003 = (uint8_t*)0x1634F30D8;
+	auto ofs004 = (uint8_t*)0x1634F31D8;
+
+	*(char*)(ofs000) = (char)0x1; // <-- | 1st EbisuSDK boolean to be checked.
+	*(char*)(ofs001) = (char)0x1; // <-- | 2nd EbisuSDK boolean to be checked.
+	*(char*)(ofs002) = (char)0x1; // <-- | 3rd EbisuSDK boolean to be checked.
+	*(char*)(ofs003) = (char)0x1; // <-- | Gets tested on listenserver for certain ConCommands.
+	*(char*)(ofs004) = (char)0x0; // <-- | TODO: enforces Necleus cvars when not equal to NULL.
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: hook 'SourceAppSystemGroup::Create' and set m_bIsDedicated to true.
+//-----------------------------------------------------------------------------
+char __fastcall Hooks::CSourceAppSystemGroup_Create(__int64 a1)
+{
+	*g_bIsDedicated = 1; // HAS TO BE HERE!!!
+	HEbisuSDK_Init();
+	return originalCSourceAppSystemGroup_Create(a1);
+}
\ No newline at end of file
diff --git a/r5dedicated/dllmain.cpp b/r5dedicated/dllmain.cpp
index 89df758c..4dc7cc24 100644
--- a/r5dedicated/dllmain.cpp
+++ b/r5dedicated/dllmain.cpp
@@ -11,6 +11,7 @@ void InitializeR5Dedicated()
 {
     SetupConsole();
     Hooks::InstallHooks();
+    Hooks::DedicatedPatch();
     printf("+-----------------------------------------------------------------------------+\n");
     printf("|   R5 DEDICATED SERVER ---------------------------------------------------   |\n");
     printf("+-----------------------------------------------------------------------------+\n");
diff --git a/r5dedicated/enums.h b/r5dedicated/enums.h
new file mode 100644
index 00000000..f3ff58b5
--- /dev/null
+++ b/r5dedicated/enums.h
@@ -0,0 +1,422 @@
+#pragma once
+
+/* Enumerations */
+enum class D3D11DeviceVTbl : short
+{
+    // IUnknown
+    QueryInterface                       = 0,
+    AddRef                               = 1,
+    Release                              = 2,
+
+    // ID3D11Device
+    CreateBuffer                         = 3,
+    CreateTexture1D                      = 4,
+    CreateTexture2D                      = 5,
+    CreateTexture3D                      = 6,
+    CreateShaderResourceView             = 7,
+    CreateUnorderedAccessView            = 8,
+    CreateRenderTargetView               = 9,
+    CreateDepthStencilView               = 10,
+    CreateInputLayout                    = 11,
+    CreateVertexShader                   = 12,
+    CreateGeometryShader                 = 13,
+    CreateGeometryShaderWithStreamOutput = 14,
+    CreatePixelShader                    = 15,
+    CreateHullShader                     = 16,
+    CreateDomainShader                   = 17,
+    CreateComputeShader                  = 18,
+    CreateClassLinkage                   = 19,
+    CreateBlendState                     = 20,
+    CreateDepthStencilState              = 21,
+    CreateRasterizerState                = 22,
+    CreateSamplerState                   = 23,
+    CreateQuery                          = 24,
+    CreatePredicate                      = 25,
+    CreateCounter                        = 26,
+    CreateDeferredContext                = 27,
+    OpenSharedResource                   = 28,
+    CheckFormatSupport                   = 29,
+    CheckMultisampleQualityLevels        = 30,
+    CheckCounterInfo                     = 31,
+    CheckCounter                         = 32,
+    CheckFeatureSupport                  = 33,
+    GetPrivateData                       = 34,
+    SetPrivateData                       = 35,
+    SetPrivateDataInterface              = 36,
+    GetFeatureLevel                      = 37,
+    GetCreationFlags                     = 38,
+    GetDeviceRemovedReason               = 39,
+    GetImmediateContext                  = 40,
+    SetExceptionMode                     = 41,
+    GetExceptionMode                     = 42,
+};
+
+enum class DXGISwapChainVTbl : short
+{
+    // IUnknown
+    QueryInterface                       = 0,
+    AddRef                               = 1,
+    Release                              = 2,
+
+    // IDXGIObject
+    SetPrivateData                       = 3,
+    SetPrivateDataInterface              = 4,
+    GetPrivateData                       = 5,
+    GetParent                            = 6,
+
+    // IDXGIDeviceSubObject
+    GetDevice                            = 7,
+
+    // IDXGISwapChain
+    Present                              = 8,
+    GetBuffer                            = 9,
+    SetFullscreenState                   = 10,
+    GetFullscreenState                   = 11,
+    GetDesc                              = 12,
+    ResizeBuffers                        = 13,
+    ResizeTarget                         = 14,
+    GetContainingOutput                  = 15,
+    GetFrameStatistics                   = 16,
+    GetLastPresentCount                  = 17,
+};
+
+#define MAX_SPLITSCREEN_CLIENT_BITS 2
+#define MAX_SPLITSCREEN_CLIENTS	( 1 << MAX_SPLITSCREEN_CLIENT_BITS ) // 4
+
+enum
+{
+	MAX_JOYSTICKS = MAX_SPLITSCREEN_CLIENTS,
+	MOUSE_BUTTON_COUNT = 5,
+};
+
+enum JoystickAxis_t
+{
+	JOY_AXIS_X = 0,
+	JOY_AXIS_Y,
+	JOY_AXIS_Z,
+	JOY_AXIS_R,
+	JOY_AXIS_U,
+	JOY_AXIS_V,
+	MAX_JOYSTICK_AXES,
+};
+
+enum
+{
+	JOYSTICK_MAX_BUTTON_COUNT = 32,
+	JOYSTICK_POV_BUTTON_COUNT = 4,
+	JOYSTICK_AXIS_BUTTON_COUNT = MAX_JOYSTICK_AXES * 2,
+};
+
+#define JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_BUTTON + ((_joystick) * JOYSTICK_MAX_BUTTON_COUNT) + (_button) )
+#define JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_POV_BUTTON + ((_joystick) * JOYSTICK_POV_BUTTON_COUNT) + (_button) )
+#define JOYSTICK_AXIS_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_AXIS_BUTTON + ((_joystick) * JOYSTICK_AXIS_BUTTON_COUNT) + (_button) )
+
+#define JOYSTICK_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) )
+#define JOYSTICK_POV_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) )
+#define JOYSTICK_AXIS_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_AXIS_BUTTON_INTERNAL( _joystick, _button ) )
+
+enum ButtonCode_t
+{
+	BUTTON_CODE_INVALID = -1,
+	BUTTON_CODE_NONE = 0,
+
+	KEY_FIRST = 0,
+
+	KEY_NONE = KEY_FIRST,
+	KEY_0,
+	KEY_1,
+	KEY_2,
+	KEY_3,
+	KEY_4,
+	KEY_5,
+	KEY_6,
+	KEY_7,
+	KEY_8,
+	KEY_9,
+	KEY_A,
+	KEY_B,
+	KEY_C,
+	KEY_D,
+	KEY_E,
+	KEY_F,
+	KEY_G,
+	KEY_H,
+	KEY_I,
+	KEY_J,
+	KEY_K,
+	KEY_L,
+	KEY_M,
+	KEY_N,
+	KEY_O,
+	KEY_P,
+	KEY_Q,
+	KEY_R,
+	KEY_S,
+	KEY_T,
+	KEY_U,
+	KEY_V,
+	KEY_W,
+	KEY_X,
+	KEY_Y,
+	KEY_Z,
+	KEY_PAD_0,
+	KEY_PAD_1,
+	KEY_PAD_2,
+	KEY_PAD_3,
+	KEY_PAD_4,
+	KEY_PAD_5,
+	KEY_PAD_6,
+	KEY_PAD_7,
+	KEY_PAD_8,
+	KEY_PAD_9,
+	KEY_PAD_DIVIDE,
+	KEY_PAD_MULTIPLY,
+	KEY_PAD_MINUS,
+	KEY_PAD_PLUS,
+	KEY_PAD_ENTER,
+	KEY_PAD_DECIMAL,
+	KEY_LBRACKET,
+	KEY_RBRACKET,
+	KEY_SEMICOLON,
+	KEY_APOSTROPHE,
+	KEY_BACKQUOTE,
+	KEY_COMMA,
+	KEY_PERIOD,
+	KEY_SLASH,
+	KEY_BACKSLASH,
+	KEY_MINUS,
+	KEY_EQUAL,
+	KEY_ENTER,
+	KEY_SPACE,
+	KEY_BACKSPACE,
+	KEY_TAB,
+	KEY_CAPSLOCK,
+	KEY_NUMLOCK,
+	KEY_ESCAPE,
+	KEY_SCROLLLOCK,
+	KEY_INSERT,
+	KEY_DELETE,
+	KEY_HOME,
+	KEY_END,
+	KEY_PAGEUP,
+	KEY_PAGEDOWN,
+	KEY_BREAK,
+	KEY_LSHIFT,
+	KEY_RSHIFT,
+	KEY_LALT,
+	KEY_RALT,
+	KEY_LCONTROL,
+	KEY_RCONTROL,
+	KEY_LWIN,
+	KEY_RWIN,
+	KEY_APP,
+	KEY_UP,
+	KEY_LEFT,
+	KEY_DOWN,
+	KEY_RIGHT,
+	KEY_F1,
+	KEY_F2,
+	KEY_F3,
+	KEY_F4,
+	KEY_F5,
+	KEY_F6,
+	KEY_F7,
+	KEY_F8,
+	KEY_F9,
+	KEY_F10,
+	KEY_F11,
+	KEY_F12,
+	KEY_CAPSLOCKTOGGLE,
+	KEY_NUMLOCKTOGGLE,
+	KEY_SCROLLLOCKTOGGLE,
+
+	KEY_LAST = KEY_SCROLLLOCKTOGGLE,
+	KEY_COUNT = KEY_LAST - KEY_FIRST + 1,
+
+	// Mouse
+	MOUSE_FIRST = KEY_LAST + 1,
+
+	MOUSE_LEFT = MOUSE_FIRST,
+	MOUSE_RIGHT,
+	MOUSE_MIDDLE,
+	MOUSE_4,
+	MOUSE_5,
+	MOUSE_WHEEL_UP,		// A fake button which is 'pressed' and 'released' when the wheel is moved up
+	MOUSE_WHEEL_DOWN,	// A fake button which is 'pressed' and 'released' when the wheel is moved down
+
+	MOUSE_LAST = MOUSE_WHEEL_DOWN,
+	MOUSE_COUNT = MOUSE_LAST - MOUSE_FIRST + 1,
+
+	// Joystick
+	JOYSTICK_FIRST = MOUSE_LAST + 1,
+
+	JOYSTICK_FIRST_BUTTON = JOYSTICK_FIRST,
+	JOYSTICK_LAST_BUTTON = JOYSTICK_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_MAX_BUTTON_COUNT - 1),
+	JOYSTICK_FIRST_POV_BUTTON,
+	JOYSTICK_LAST_POV_BUTTON = JOYSTICK_POV_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_POV_BUTTON_COUNT - 1),
+	JOYSTICK_FIRST_AXIS_BUTTON,
+	JOYSTICK_LAST_AXIS_BUTTON = JOYSTICK_AXIS_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_AXIS_BUTTON_COUNT - 1),
+
+	JOYSTICK_LAST = JOYSTICK_LAST_AXIS_BUTTON,
+
+	BUTTON_CODE_LAST,
+	BUTTON_CODE_COUNT = BUTTON_CODE_LAST - KEY_FIRST + 1,
+
+	// Helpers for XBox 360
+	KEY_XBUTTON_UP = JOYSTICK_FIRST_POV_BUTTON,	// POV buttons
+	KEY_XBUTTON_RIGHT,
+	KEY_XBUTTON_DOWN,
+	KEY_XBUTTON_LEFT,
+
+	KEY_XBUTTON_A = JOYSTICK_FIRST_BUTTON,		// Buttons
+	KEY_XBUTTON_B,
+	KEY_XBUTTON_X,
+	KEY_XBUTTON_Y,
+	KEY_XBUTTON_LEFT_SHOULDER,
+	KEY_XBUTTON_RIGHT_SHOULDER,
+	KEY_XBUTTON_BACK,
+	KEY_XBUTTON_START,
+	KEY_XBUTTON_STICK1,
+	KEY_XBUTTON_STICK2,
+	KEY_XBUTTON_INACTIVE_START,
+
+	KEY_XSTICK1_RIGHT = JOYSTICK_FIRST_AXIS_BUTTON,	// XAXIS POSITIVE
+	KEY_XSTICK1_LEFT,							// XAXIS NEGATIVE
+	KEY_XSTICK1_DOWN,							// YAXIS POSITIVE
+	KEY_XSTICK1_UP,								// YAXIS NEGATIVE
+	KEY_XBUTTON_LTRIGGER,						// ZAXIS POSITIVE
+	KEY_XBUTTON_RTRIGGER,						// ZAXIS NEGATIVE
+	KEY_XSTICK2_RIGHT,							// UAXIS POSITIVE
+	KEY_XSTICK2_LEFT,							// UAXIS NEGATIVE
+	KEY_XSTICK2_DOWN,							// VAXIS POSITIVE
+	KEY_XSTICK2_UP,								// VAXIS NEGATIVE
+};
+
+// Buttons are not confirmed to be the same. They have been always the same throughout the source engine. Lets hope they did not change them.
+
+enum KeyValuesTypes
+{
+	TYPE_NONE = 0x0,
+	TYPE_STRING = 0x1,
+	TYPE_INT = 0x2,
+	TYPE_FLOAT = 0x3,
+	TYPE_PTR = 0x4,
+	TYPE_WSTRING = 0x5,
+	TYPE_COLOR = 0x6,
+	TYPE_UINT64 = 0x7,
+	TYPE_COMPILED_INT_BYTE = 0x8,
+	TYPE_COMPILED_INT_0 = 0x9,
+	TYPE_COMPILED_INT_1 = 0xA,
+	TYPE_NUMTYPES = 0xB,
+};
+
+enum ClientFrameStage_t
+{
+	FRAME_UNDEFINED = -1,			// (haven't run any frames yet)
+	FRAME_START,
+
+	// A network packet is being recieved
+	FRAME_NET_UPDATE_START,
+	// Data has been received and we're going to start calling PostDataUpdate
+	FRAME_NET_UPDATE_POSTDATAUPDATE_START,
+	// Data has been received and we've called PostDataUpdate on all data recipients
+	FRAME_NET_UPDATE_POSTDATAUPDATE_END,
+	// We've received all packets, we can now do interpolation, prediction, etc..
+	FRAME_NET_UPDATE_END,
+
+	// We're about to start rendering the scene
+	FRAME_RENDER_START,
+	// We've finished rendering the scene.
+	FRAME_RENDER_END,
+
+	FRAME_NET_FULL_FRAME_UPDATE_ON_REMOVE
+};
+
+enum HostStates_t
+{
+	HS_NEW_GAME = 0x0,
+	HS_LOAD_GAME = 0x1,
+	HS_CHANGE_LEVEL_SP = 0x2,
+	HS_CHANGE_LEVEL_MP = 0x3,
+	HS_RUN = 0x4,
+	HS_GAME_SHUTDOWN = 0x5,
+	HS_SHUTDOWN = 0x6,
+	HS_RESTART = 0x7,
+};
+
+enum SIGNONSTATE
+{
+	SIGNONSTATE_NONE = 0, // no state yet; about to connect
+	SIGNONSTATE_CHALLENGE = 1, // client challenging server; all OOB packets
+	SIGNONSTATE_CONNECTED = 2, // client is connected to server; netchans ready
+	SIGNONSTATE_NEW = 3, // just got serverinfo and string tables
+	SIGNONSTATE_PRESPAWN = 4, // received signon buffers
+	SIGNONSTATE_GETTING_DATA = 5, // getting persistence data I assume?
+	SIGNONSTATE_SPAWN = 6, // ready to receive entity packets
+	SIGNONSTATE_FIRST_SNAP = 7, // ???
+	SIGNONSTATE_FULL = 8, // we are fully connected; first non-delta packet received
+	SIGNONSTATE_CHANGELEVEL = 9, // server is changing level; please wait
+};
+
+enum FileWarningLevel_t
+{
+	FILESYSTEM_WARNING = -1,
+	FILESYSTEM_WARNING_QUIET = 0,
+	FILESYSTEM_WARNING_REPORTUNCLOSED,
+	FILESYSTEM_WARNING_REPORTUSAGE,
+	FILESYSTEM_WARNING_REPORTALLACCESSES,
+	FILESYSTEM_WARNING_REPORTALLACCESSES_READ,
+	FILESYSTEM_WARNING_REPORTALLACCESSES_READWRITE,
+	FILESYSTEM_WARNING_REPORTALLACCESSES_ASYNC
+};
+
+#define FCVAR_NONE				0 
+
+// Command to ConVars and ConCommands
+// ConVar Systems
+#define FCVAR_UNREGISTERED		(1<<0)	// If this is set, don't add to linked list, etc.
+#define FCVAR_DEVELOPMENTONLY	(1<<1)	// Hidden in released products. Flag is removed automatically if ALLOW_DEVELOPMENT_CVARS is defined.
+#define FCVAR_GAMEDLL			(1<<2)	// defined by the game DLL
+#define FCVAR_CLIENTDLL			(1<<3)  // defined by the client DLL
+#define FCVAR_HIDDEN			(1<<4)	// Hidden. Doesn't appear in find or auto complete. Like DEVELOPMENTONLY, but can't be compiled out.
+
+// ConVar only
+#define FCVAR_PROTECTED			(1<<5)  // It's a server cvar, but we don't send the data since it's a password, etc.  Sends 1 if it's not bland/zero, 0 otherwise as value
+#define FCVAR_SPONLY			(1<<6)  // This cvar cannot be changed by clients connected to a multiplayer server.
+#define	FCVAR_ARCHIVE			(1<<7)	// set to cause it to be saved to vars.rc
+#define	FCVAR_NOTIFY			(1<<8)	// notifies players when changed
+#define	FCVAR_USERINFO			(1<<9)	// changes the client's info string
+
+#define FCVAR_PRINTABLEONLY		(1<<10)  // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
+
+#define FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS		(1<<10)  // When on concommands this allows remote clients to execute this cmd on the server. 
+														 // We are changing the default behavior of concommands to disallow execution by remote clients without
+														 // this flag due to the number existing concommands that can lag or crash the server when clients abuse them.
+
+#define FCVAR_UNLOGGED			(1<<11)  // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
+#define FCVAR_NEVER_AS_STRING	(1<<12)  // never try to print that cvar
+
+// It's a ConVar that's shared between the client and the server.
+// At signon, the values of all such ConVars are sent from the server to the client (skipped for local
+//  client, of course )
+// If a change is requested it must come from the console (i.e., no remote client changes)
+// If a value is changed while a server is active, it's replicated to all connected clients
+#define FCVAR_REPLICATED		(1<<13)	// server setting enforced on clients, TODO rename to FCAR_SERVER at some time
+#define FCVAR_CHEAT				(1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats
+#define FCVAR_SS				(1<<15) // causes varnameN where N == 2 through max splitscreen slots for mod to be autogenerated
+#define FCVAR_DEMO				(1<<16) // record this cvar when starting a demo file
+#define FCVAR_DONTRECORD		(1<<17) // don't record these command in demofiles
+#define FCVAR_SS_ADDED			(1<<18) // This is one of the "added" FCVAR_SS variables for the splitscreen players
+#define FCVAR_RELEASE			(1<<19) // Cvars tagged with this are the only cvars avaliable to customers
+#define FCVAR_RELOAD_MATERIALS	(1<<20)	// If this cvar changes, it forces a material reload
+#define FCVAR_RELOAD_TEXTURES	(1<<21)	// If this cvar changes, if forces a texture reload
+
+#define FCVAR_NOT_CONNECTED		(1<<22)	// cvar cannot be changed by a client that is connected to a server
+#define FCVAR_MATERIAL_SYSTEM_THREAD (1<<23)	// Indicates this cvar is read from the material system thread
+#define FCVAR_ARCHIVE_GAMECONSOLE	(1<<24) // cvar written to config.cfg on the Xbox
+
+#define FCVAR_SERVER_CAN_EXECUTE	(1<<28)// the server is allowed to execute this command on clients via ClientCommand/NET_StringCmd/CBaseClientState::ProcessStringCmd.
+#define FCVAR_SERVER_CANNOT_QUERY	(1<<29)// If this is set, then the server is not allowed to query this cvar's value (via IServerPluginHelpers::StartQueryCvarValue).
+#define FCVAR_CLIENTCMD_CAN_EXECUTE	(1<<30)	// IVEngineClient::ClientCmd is allowed to execute this command.
+
+#define MAX_PLAYERS 128 // Max R5 players.
diff --git a/r5dedicated/gameclasses.cpp b/r5dedicated/gameclasses.cpp
new file mode 100644
index 00000000..9f9cf1e4
--- /dev/null
+++ b/r5dedicated/gameclasses.cpp
@@ -0,0 +1,470 @@
+#include "pch.h"
+#include "enums.h"
+#include "gameclasses.h"
+
+//  Need this for a re-factor later.
+//	Interface* interfaces = *reinterpret_cast<Interface**>(0x167F4FA48);
+
+//	for (Interface* current = interfaces; current; current = reinterpret_cast<Interface*>(current->NextInterfacePtr))
+//	{
+//		printf("%s: %p\n", current->InterfaceName, current->InterfacePtr);
+//	}
+
+namespace GameGlobals
+{
+	bool IsInitialized = false;
+	CHostState* HostState = nullptr;
+	CInputSystem* InputSystem = nullptr;
+	CCVar* Cvar = nullptr;
+	CClient* Client = nullptr;
+	BanList* BanSystem = new BanList();
+
+	CKeyValuesSystem* KeyValuesSystem = nullptr;
+	KeyValues** PlaylistKeyValues = nullptr;	
+
+	std::vector<std::string> allPlaylists = { "none" };
+
+	namespace CustomCommandVariations
+	{
+
+		void Kick_Callback(CCommand* cmd)
+		{
+			std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
+			if (argSize < 2) // Do we atleast have 2 arguments?
+				return;
+
+			CCommand& cmdReference = *cmd; // Get reference.
+			const char* firstArg = cmdReference[1]; // Get first arg.
+
+			for (int i = 0; i < MAX_PLAYERS; i++) // Loop through all possible client instances.
+			{
+				CClient* client = GameGlobals::Client->GetClientInstance(i); // Get client instance.
+				if (!client)
+					continue;
+
+				if (!client->GetNetChan()) // Netchan valid?
+					continue;
+
+				void* clientNamePtr = (void**)(((std::uintptr_t)client->GetNetChan()) + 0x1A8D); // Get client name from netchan.
+				std::string clientName((char*)clientNamePtr, 32); // Get full name.
+
+				if (clientName.empty()) // Empty name?
+					continue;
+
+				if (strcmp(firstArg, clientName.c_str()) != 0) // Our wanted name?
+					continue;
+
+				DisconnectClient(client, "Kicked from Server", 0, 1); // Disconnect client.
+			}
+		}
+
+		void KickID_Callback(CCommand* cmd)
+		{
+			static auto HasOnlyDigits = [](const std::string& string)
+			{
+				for (const char& character : string)
+				{
+					if (std::isdigit(character) == 0)
+						return false;
+				}
+				return true;
+			};
+
+			std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
+			if (argSize < 2) // Do we atleast have 2 arguments?
+				return;
+
+			CCommand& cmdReference = *cmd; // Get reference.
+			std::string firstArg = cmdReference[1]; // Get first arg.
+
+			try
+			{
+				bool onlyDigits = HasOnlyDigits(firstArg); // Only has digits?
+				for (int i = 0; i < MAX_PLAYERS; i++) // Loop through all possible client instances.
+				{
+					CClient* client = GameGlobals::Client->GetClientInstance(i); // Get client instance.
+					if (!client)
+						continue;
+
+					if (!client->GetNetChan()) // Netchan valid?
+						continue;
+
+					std::string finalIPAddress = "null"; // If this stays null they modified the packet somehow.
+					MemoryAddress ipAddressField = MemoryAddress(((std::uintptr_t)client->GetNetChan()) + 0x1AC0); // Get client ip from netchan.
+					if (ipAddressField)
+					{
+						std::stringstream ss;
+						ss << std::to_string(ipAddressField.GetValue<std::uint8_t>()) << "."
+							<< std::to_string(ipAddressField.Offset(0x1).GetValue<std::uint8_t>()) << "."
+							<< std::to_string(ipAddressField.Offset(0x2).GetValue<std::uint8_t>()) << "."
+							<< std::to_string(ipAddressField.Offset(0x3).GetValue<std::uint8_t>());
+
+						finalIPAddress = ss.str();
+					}
+
+					if (onlyDigits)
+					{
+						std::int64_t ID = static_cast<std::int64_t>(std::stoll(firstArg));
+						if (ID > MAX_PLAYERS) // Is it a possible originID?
+						{
+							std::int64_t originID = client->m_iOriginID;
+							if (originID != ID) // See if they match.
+								continue;
+						}
+						else // If its not try by userID.
+						{
+							std::int64_t clientID = static_cast<std::int64_t>(client->m_iUserID + 1); // Get UserID + 1.
+							if (clientID != ID) // See if they match.
+								continue;
+						}
+
+						DisconnectClient(client, "Kicked from Server", 0, 1); // Disconnect client.
+					}
+					else
+					{
+						if (firstArg.compare(finalIPAddress) != NULL) // Do the string equal?
+							continue;
+
+						DisconnectClient(client, "Kicked from Server", 0, 1); // Disconnect client.
+					}
+				}
+			}
+			catch (std::exception& e)
+			{
+				std::cout << "Kick UID asked for a userID or originID :( You can get the userID with the 'status' command. Error: " << e.what() << std::endl;
+				return;
+			}
+		}
+
+		void Unban_Callback(CCommand* cmd)
+		{
+			static auto HasOnlyDigits = [](const std::string& string)
+			{
+				for (const char& character : string)
+				{
+					if (std::isdigit(character) == 0)
+						return false;
+				}
+				return true;
+			};
+
+			std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
+			if (argSize < 2) // Do we atleast have 2 arguments?
+				return;
+
+			CCommand& cmdReference = *cmd; // Get reference.
+
+			try
+			{
+				const char* firstArg = cmdReference[1];
+				if (HasOnlyDigits(firstArg)) // Check if we have an ip address or origin ID.
+				{
+					GameGlobals::BanSystem->DeleteEntry("noIP", std::stoll(firstArg)); // Delete ban entry.
+					GameGlobals::BanSystem->Save(); // Save modified vector to file.
+				}
+				else
+				{
+					GameGlobals::BanSystem->DeleteEntry(firstArg, 1); // Delete ban entry.
+					GameGlobals::BanSystem->Save(); // Save modified vector to file.
+				}
+			}
+			catch (std::exception& e)
+			{
+				std::cout << "Unban Error: " << e.what() << std::endl;
+				return;
+			}
+		}
+
+		void ReloadBanList_Callback(CCommand* cmd)
+		{
+			GameGlobals::BanSystem->Load(); // Reload banlist.
+		}
+
+		void Ban_Callback(CCommand* cmd)
+		{
+			std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
+			if (argSize < 2) // Do we atleast have 2 arguments?
+				return;
+
+			CCommand& cmdReference = *cmd; // Get reference.
+			const char* firstArg = cmdReference[1]; // Get first arg.
+
+			for (int i = 0; i < MAX_PLAYERS; i++) // Loop through all possible client instances.
+			{
+				CClient* client = GameGlobals::Client->GetClientInstance(i); // Get client instance.
+				if (!client)
+					continue;
+
+				if (!client->GetNetChan()) // Netchan valid?
+					continue;
+
+				void* clientNamePtr = (void**)(((std::uintptr_t)client->GetNetChan()) + 0x1A8D); // Get client name from netchan.
+				std::string clientName((char*)clientNamePtr, 32); // Get full name.
+
+				if (clientName.empty()) // Empty name?
+					continue;
+
+				if (strcmp(firstArg, clientName.c_str()) != 0) // Our wanted name?
+					continue;
+
+				std::string finalIPAddress = "null"; // If this stays null they modified the packet somehow.
+				MemoryAddress ipAddressField = MemoryAddress(((std::uintptr_t)client->GetNetChan()) + 0x1AC0); // Get client ip from netchan.
+				if (ipAddressField && ipAddressField.GetValue<int>() != 0x0)
+				{
+					std::stringstream ss;
+					ss << std::to_string(ipAddressField.GetValue<std::uint8_t>()) << "."
+						<< std::to_string(ipAddressField.Offset(0x1).GetValue<std::uint8_t>()) << "."
+						<< std::to_string(ipAddressField.Offset(0x2).GetValue<std::uint8_t>()) << "."
+						<< std::to_string(ipAddressField.Offset(0x3).GetValue<std::uint8_t>());
+
+					finalIPAddress = ss.str();
+				}
+
+				GameGlobals::BanSystem->AddEntry(finalIPAddress, client->m_iOriginID); // Add ban entry.
+				GameGlobals::BanSystem->Save(); // Save ban list.
+				DisconnectClient(client, "Banned from Server", 0, 1); // Disconnect client.
+			}
+		}
+
+		void BanID_Callback(CCommand* cmd)
+		{
+			static auto HasOnlyDigits = [](const std::string& string)
+			{
+				for (const char& character : string)
+				{
+					if (std::isdigit(character) == 0)
+						return false;
+				}
+				return true;
+			};
+
+			std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
+			if (argSize < 2) // Do we atleast have 2 arguments?
+				return;
+
+			CCommand& cmdReference = *cmd; // Get reference.
+			std::string firstArg = cmdReference[1];
+
+			try
+			{
+				bool onlyDigits = HasOnlyDigits(firstArg); // Only has digits?
+				for (int i = 0; i < MAX_PLAYERS; i++) // Loop through all possible client instances.
+				{
+					CClient* client = GameGlobals::Client->GetClientInstance(i); // Get client instance.
+					if (!client)
+						continue;
+
+					if (!client->GetNetChan()) // Netchan valid?
+						continue;
+
+					std::string finalIPAddress = "null"; // If this stays null they modified the packet somehow.
+					MemoryAddress ipAddressField = MemoryAddress(((std::uintptr_t)client->GetNetChan()) + 0x1AC0); // Get client ip from netchan.
+					if (ipAddressField)
+					{
+						std::stringstream ss;
+						ss << std::to_string(ipAddressField.GetValue<std::uint8_t>()) << "."
+							<< std::to_string(ipAddressField.Offset(0x1).GetValue<std::uint8_t>()) << "."
+							<< std::to_string(ipAddressField.Offset(0x2).GetValue<std::uint8_t>()) << "."
+							<< std::to_string(ipAddressField.Offset(0x3).GetValue<std::uint8_t>());
+
+						finalIPAddress = ss.str();
+					}
+
+					if (onlyDigits)
+					{
+						std::int64_t ID = static_cast<std::int64_t>(std::stoll(firstArg));
+						if (ID > MAX_PLAYERS) // Is it a possible originID?
+						{
+							std::int64_t originID = client->m_iOriginID;
+							if (originID != ID) // See if they match.
+								continue;
+						}
+						else // If its not try by userID.
+						{
+							std::int64_t clientID = static_cast<std::int64_t>(client->m_iUserID + 1); // Get UserID + 1.
+							if (clientID != ID) // See if they match.
+								continue;
+						}
+
+						GameGlobals::BanSystem->AddEntry(finalIPAddress, client->m_iOriginID); // Add ban entry.
+						GameGlobals::BanSystem->Save(); // Save ban list.
+						DisconnectClient(client, "Banned from Server", 0, 1); // Disconnect client.
+					}
+					else
+					{
+						if (firstArg.compare(finalIPAddress) != NULL) // Do the string equal?
+							continue;
+
+						GameGlobals::BanSystem->AddEntry(finalIPAddress, client->m_iOriginID); // Add ban entry.
+						GameGlobals::BanSystem->Save(); // Save ban list.
+						DisconnectClient(client, "Banned from Server", 0, 1); // Disconnect client.
+					}
+				}
+			}
+			catch (std::exception& e)
+			{
+				std::cout << "Banid Error: " << e.what() << std::endl;
+				return;
+			}
+		}
+	}
+
+	void NullHostNames()
+	{
+		const char* hostnameArray[] =
+		{
+			"pin_telemetry_hostname",
+			"assetdownloads_hostname",
+			"users_hostname",
+			"persistence_hostname",
+			"speechtotexttoken_hostname",
+			"communities_hostname",
+			"persistenceDef_hostname",
+			"party_hostname",
+			"speechtotext_hostname",
+			"serverReports_hostname",
+			"subscription_hostname",
+			"steamlink_hostname",
+			"staticfile_hostname",
+			"matchmaking_hostname",
+			"skill_hostname",
+			"publication_hostname",
+			"stats_hostname"
+		};
+
+		for (int i = 0; i < 17; i++)
+		{
+			const char* name = hostnameArray[i];
+			Cvar->FindVar(name)->m_pzsCurrentValue = "0.0.0.0";
+		}
+	}
+
+	void InitGameGlobals()
+	{
+		HostState = reinterpret_cast<CHostState*>(0x141736120); // Get CHostState from memory.
+		InputSystem = *reinterpret_cast<CInputSystem**>(0x14D40B380); // Get IInputSystem from memory.
+		Cvar = *reinterpret_cast<CCVar**>(0x14D40B348); // Get CCVar from memory.
+		//KeyValuesSystem = reinterpret_cast<CKeyValuesSystem*>(0x141F105C0); // Get CKeyValuesSystem from memory.
+		//PlaylistKeyValues = reinterpret_cast<KeyValues**>(0x16705B980); // Get the KeyValue for the playlist file.
+		//Client = reinterpret_cast<CClient*>(0x16073B200);
+
+		//NullHostNames(); // Null all hostnames.
+		//InitAllCommandVariations(); // Initialize our custom ConVars.
+		//*(char*)addr_m_bRestrictServerCommands = true; // Restrict commands.
+		//void* disconnect = Cvar->FindCommand("disconnect");
+		//*(std::int32_t*)((std::uintptr_t)disconnect + 0x38) |= FCVAR_SERVER_CAN_EXECUTE; // Make sure server is not restricted to this.
+
+		//std::thread t1(InitPlaylist); // Start thread to grab playlists.
+		//t1.detach(); // Detach thread from current one.
+
+		IsInitialized = true;
+	}
+	
+	void InitPlaylist()
+	{
+		while (true)
+		{
+			if ((*PlaylistKeyValues))
+			{
+				KeyValues* playlists = (*PlaylistKeyValues)->FindKey("Playlists", false); // Find playlists key.
+				if (playlists)
+				{
+					allPlaylists.clear();
+					for (KeyValues* dat = playlists->m_pSub; dat != nullptr; dat = dat->m_pPeer) // Parse through all sub keys.
+					{
+						allPlaylists.push_back(dat->GetName()); // Get all playlist names.
+					}
+
+					break; // Break if playlist got filled.
+				}
+				std::this_thread::sleep_for(std::chrono::milliseconds(50));
+			}
+			std::this_thread::sleep_for(std::chrono::milliseconds(50));
+		}
+	}
+
+	void InitAllCommandVariations()
+	{
+		void* KickConCommand          = CreateCustomConCommand("kick", "Kick a client from the Server via name. | Usage: kick (name).", 0, CustomCommandVariations::Kick_Callback, nullptr);
+		void* KickIDConCommand        = CreateCustomConCommand("kickid", "Kick a client from the Server via userID or originID | Usage: kickid (originID/userID)", 0, CustomCommandVariations::KickID_Callback, nullptr);
+		void* UnbanConCommand         = CreateCustomConCommand("unban", "Unbans a client from the Server via IP or originID | Usage: unban (originID/ipAddress)", 0, CustomCommandVariations::Unban_Callback, nullptr);
+		void* ReloadBanListConCommand = CreateCustomConCommand("reloadbanlist", "Reloads the ban list from disk.", 0, CustomCommandVariations::ReloadBanList_Callback, nullptr);
+		void* BanConCommand           = CreateCustomConCommand("ban", "Bans a client from the Server via name. | Usage: ban (name)", 0, CustomCommandVariations::Ban_Callback, nullptr);
+		void* BanIDConCommand         = CreateCustomConCommand("banid", "Bans a client from the Server via originID, userID or IP | Usage: banid (originID/ipAddress/userID)", 0, CustomCommandVariations::BanID_Callback, nullptr);
+	}
+
+	void* CreateCustomConCommand(const char* name, const char* helpString, int flags, void* callback, void* callbackAfterExecution)
+	{
+		static MemoryAddress ConCommandVtable = MemoryAddress(0x14136BD70);
+		static MemoryAddress NullSub = MemoryAddress(0x1401B3280);
+		static MemoryAddress CallbackCompletion = MemoryAddress(0x1401E3990);
+		static MemoryAddress RegisterConCommand = MemoryAddress(0x14046F470);
+
+		void* command = reinterpret_cast<void*>(addr_MemAlloc_Wrapper(0x68)); // Allocate new memory with StdMemAlloc else we crash.
+		memset(command, 0, 0x68); // Set all to null.
+		std::uintptr_t commandPtr = reinterpret_cast<std::uintptr_t>(command); // To ptr.
+
+		*(void**)commandPtr = ConCommandVtable.RCast<void*>(); // 0x0 to ConCommand vtable.
+		*(const char**)(commandPtr + 0x18) = name; // 0x18 to ConCommand Name.
+		*(const char**)(commandPtr + 0x20) = helpString; // 0x20 to ConCommand help string.
+		*(std::int32_t*)(commandPtr + 0x38) = flags; // 0x38 to ConCommand Flags.
+		*(void**)(commandPtr + 0x40) = NullSub.RCast<void*>(); // 0x40 Nullsub since every concommand has it.
+		*(void**)(commandPtr + 0x50) = callback; // 0x50 has function callback.
+		*(std::int32_t*)(commandPtr + 0x60) = 2; // 0x60 Set to use callback and newcommand callback.
+
+		if (callbackAfterExecution) // Do we wanna have a callback after execution?
+		{
+			*(void**)(commandPtr + 0x58) = callbackAfterExecution; // 0x58 to our callback after execution.
+		}
+		else
+		{
+			*(void**)(commandPtr + 0x58) = CallbackCompletion.RCast<void*>(); // 0x58 nullsub.
+		}
+
+		RegisterConCommand.RCast<void(*)(void*)>()((void*)commandPtr); // Register command in ConVarAccessor.
+
+		return command;
+	}
+
+	ConVar* CreateCustomConVar(const char* name, const char* defaultValue, int flags, const char* helpString, bool bMin, float fMin, bool bMax, float fMax, void* callback, void* unk)
+	{
+		static MemoryAddress ConVarVtable = MemoryAddress(0x14046FB50).Offset(0x12).ResolveRelativeAddress(); // Get vtable ptr for ConVar table.
+		static MemoryAddress ICvarVtable = MemoryAddress(0x14046FB50).Offset(0x29).ResolveRelativeAddress(); // Get vtable ptr for ICvar table.
+		static MemoryAddress CreateConVar = MemoryAddress(0x140470540); // Get CreateConvar address.
+
+		ConVar* allocatedConvar = reinterpret_cast<ConVar*>(addr_MemAlloc_Wrapper(0xA0)); // Allocate new memory with StdMemAlloc else we crash.
+		memset(allocatedConvar, 0, 0xA0); // Set all to null.
+		std::uintptr_t cvarPtr = reinterpret_cast<std::uintptr_t>(allocatedConvar); // To ptr.
+
+		*(void**)(cvarPtr + 0x40) = ICvarVtable.RCast<void*>(); // 0x40 to ICvar table.
+		*(void**)cvarPtr = ConVarVtable.RCast<void*>(); // 0x0 to ConVar vtable.
+
+		CreateConVar.RCast<void(*)(ConVar*, const char*, const char*, int, const char*, bool, float, bool, float, void*, void*)>() // Call to create ConVar.
+			(allocatedConvar, name, defaultValue, flags, helpString, bMin, fMin, bMax, fMax, callback, unk);
+
+		return allocatedConvar; // Return allocated ConVar.
+	}
+
+	void DisconnectClient(CClient* client, const char* reason, unsigned __int8 unk1, char unk2)
+	{
+		if (!client) //	Client valid?
+			return;
+
+		if (std::strlen(reason) == NULL) // Is reason null?
+			return;
+
+		if (!client->GetNetChan())
+			return;
+
+		addr_NetChan_Shutdown(client->GetNetChan(), reason, unk1, unk2); // Shutdown netchan.
+		client->GetNetChan() = nullptr; // Null netchan.
+		MemoryAddress(0x140302FD0).RCast<void(*)(CClient*)>()(client); // Reset CClient instance for client.
+	}
+}
+
+#pragma region KeyValues
+const char* KeyValues::GetName()
+{
+	return GameGlobals::KeyValuesSystem->GetStringForSymbol(MAKE_3_BYTES_FROM_1_AND_2(m_iKeyNameCaseSensitive, m_iKeyNameCaseSensitive2));
+}
+#pragma endregion
\ No newline at end of file
diff --git a/r5dedicated/gameclasses.h b/r5dedicated/gameclasses.h
new file mode 100644
index 00000000..39ebf687
--- /dev/null
+++ b/r5dedicated/gameclasses.h
@@ -0,0 +1,487 @@
+#pragma once
+#include "pch.h"
+#include "hooks.h"
+#include "enums.h"
+#include "banlist.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// Classes and Structs
+class CInputSystem
+{
+public:
+	void EnableInput(bool bEnabled)// @0x14039F100 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = void(__thiscall*)(CInputSystem*, bool);
+		(*reinterpret_cast<OriginalFn**>(this))[10](this, bEnabled); 
+	}
+
+	void EnableMessagePump(bool bEnabled) // @0x14039F110 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = void(__thiscall*)(CInputSystem*, bool);
+		(*reinterpret_cast<OriginalFn**>(this))[11](this, bEnabled); 
+	}
+
+	bool IsButtonDown(ButtonCode_t Button) // @0x1403A0140 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = bool(__thiscall*)(CInputSystem*, ButtonCode_t);
+		return (*reinterpret_cast<OriginalFn**>(this))[13](this, Button); 
+	}
+
+private:
+	char pad_0000[16]; //0x0000
+public:
+	bool m_bEnabled; //0x0010 IsInputEnabled variable.
+	bool m_bPumpEnabled; //0x0011 EnabledMessagePump variable.
+};
+
+typedef int HKeySymbol;
+
+#define MAKE_3_BYTES_FROM_1_AND_2( x1, x2 ) (( (( std::uint16_t )x2) << 8 ) | (std::uint8_t)(x1))
+
+class CKeyValuesSystem // VTABLE @ 0x1413AA1E8 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+{
+public:
+
+	void RegisterSizeofKeyValues(__int64 size) //@0x1413AA1F0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = void(__thiscall*)(CKeyValuesSystem*, __int64);
+		(*reinterpret_cast<OriginalFn**>(this))[0](this, size);
+	}
+
+	void* AllocKeyValuesMemory(__int64 size) // @0x1413AA1F8 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = void* (__thiscall*)(CKeyValuesSystem*, __int64);
+		return (*reinterpret_cast<OriginalFn**>(this))[1](this, size);
+	}
+
+	void FreeKeyValuesMemory(void* pMem) // @0x1413AA200 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = void(__thiscall*)(CKeyValuesSystem*, void*);
+		(*reinterpret_cast<OriginalFn**>(this))[2](this, pMem);
+	}
+
+	HKeySymbol GetSymbolForString(const char* name, bool bCreate) // @0x1413AA208 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = HKeySymbol(__thiscall*)(CKeyValuesSystem*, const char*, bool);
+		return (*reinterpret_cast<OriginalFn**>(this))[3](this, name, bCreate);
+	}
+
+	const char* GetStringForSymbol(HKeySymbol symbol) // @0x1413AA210 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = const char* (__thiscall*)(CKeyValuesSystem*, HKeySymbol);
+		return (*reinterpret_cast<OriginalFn**>(this))[4](this, symbol);
+	}
+
+	//	void __fastcall CKeyValuesSystem::FreeKeyValuesMemory(CKeyValuesSystem* this_arg, void* ptr_mem_arg)
+	//	{
+	//		__int64* v2; // rax
+	//		__int64 v4; // rax
+	//		__int64* v5; // rax
+	// 
+	//		v2 = qword_14D40B538;
+	//		if (!qword_14D40B538)
+	//		{
+	//			v2 = sub_140462930();
+	//			qword_14D40B538 = v2;
+	//		}
+	//		v4 = (*(*v2 + 48))(v2, ptr_mem_arg);
+	//		if (v4 > 0)
+	//			CKeyValuesSystem::m_pMemPool -= v4;
+	//		v5 = qword_14D40B538;
+	//		if (!qword_14D40B538)
+	//		{
+	//			v5 = sub_140462930();
+	//			qword_14D40B538 = v5;
+	//		}
+	//		(*(*v5 + 40))(v5, ptr_mem_arg);
+	//	}
+
+	// GetMemPool return a global variable called m_pMemPool it gets modified by AllocKeyValuesMemory and FreeKeyValuesMemory above you can see where the find it in FreeKeyValuesMemory.
+	void* GetMemPool() // @0x1413AA228 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		return reinterpret_cast<void*>(0x14D412768); // May need to dereference is once more not sure right now.
+	}
+
+	void SetKeyValuesExpressionSymbol(const char* name, bool bValue) // @0x1413AA230 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = void(__thiscall*)(CKeyValuesSystem*, const char*, bool);
+		(*reinterpret_cast<OriginalFn**>(this))[8](this, name, bValue);
+	}
+
+	bool GetKeyValuesExpressionSymbol(const char* name) // @0x1413AA238 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = bool(__thiscall*)(CKeyValuesSystem*, const char*);
+		return (*reinterpret_cast<OriginalFn**>(this))[9](this, name);
+	}
+
+	HKeySymbol GetSymbolForStringCaseSensitive(HKeySymbol& hCaseInsensitiveSymbol, const char* name, bool bCreate) // @0x1413AA240 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = HKeySymbol(__thiscall*)(CKeyValuesSystem*, HKeySymbol&, const char*, bool);
+		return (*reinterpret_cast<OriginalFn**>(this))[10](this, hCaseInsensitiveSymbol, name, bCreate);
+	}
+
+	// Datatypes aren't accurate. But full fill the actual byte distance.
+public:
+	void* vtable; // 0x0000
+	__int64 m_iMaxKeyValuesSize; // 0x0008
+private:
+	char gap10[240]; // 0x0010
+public:
+	__int32 m_KvConditionalSymbolTable; // 0x0100
+private:
+	char gap104[4]; // 0x0104
+public:
+	__int64 field_108; // 0x0108
+private:
+	char gap110[32]; // 0x0110
+public:
+	int m_mutex; // 0x0130
+};
+
+class KeyValues
+{
+public:
+
+	KeyValues* FindKey(const char* keyName, bool bCreate)
+	{
+		static auto func = reinterpret_cast<KeyValues*(__thiscall*)(KeyValues*, const char*, bool)>(addr_KeyValues_FindKey);
+		return func(this, keyName, bCreate);
+	}
+
+	const char* GetName();
+
+	int GetInt(const char* keyName, int defaultValue)
+	{
+		KeyValues* dat = FindKey(keyName, false);
+
+		if (!dat)
+			return defaultValue;
+
+		switch (dat->m_iDataType)
+		{
+		case TYPE_STRING:
+			return atoi(dat->m_sValue);
+		case TYPE_FLOAT:
+			return static_cast<int>(m_flValue());
+		case TYPE_WSTRING:
+			return _wtoi(dat->m_wsValue);
+		case TYPE_UINT64:
+			return 0;
+		default:
+			return dat->m_iValue();
+		}
+
+		return defaultValue;
+	}
+
+	void SetInt(const char* keyName, int iValue)
+	{
+		KeyValues* dat = FindKey(keyName, true);
+		if (dat)
+		{
+			dat->m_iValue() = iValue;
+			dat->m_iDataType = TYPE_INT;
+		}
+	}
+
+	void SetFloat(const char* keyName, float flValue)
+	{
+		KeyValues* dat = FindKey(keyName, true);
+		if (dat)
+		{
+			dat->m_flValue() = flValue;
+			dat->m_iDataType = TYPE_FLOAT;
+		}
+	}
+
+	// Compiler makes it so m_Value shares the offset spot with m_flValue that why we cast it like this.
+	float& m_flValue()
+	{
+		static __int32 offset = 0x18;
+		return *(float*)((std::uintptr_t)this + offset);
+	}
+
+	int& m_iValue()
+	{
+		static __int32 offset = 0x18;
+		return *(int*)((std::uintptr_t)this + offset);
+	}
+
+public:
+	unsigned __int32 m_iKeyName : 24; // 0x0000
+	unsigned __int32 m_iKeyNameCaseSensitive : 8; // 0x0003
+	char* m_sValue; // 0x0008
+	wchar_t* m_wsValue; // 0x0010
+	int m_Value; // 0x0018
+private:
+	char gap1C[12]; // 0x0020
+public:
+	char m_iDataType; // 0x0028
+	unsigned __int16 m_iKeyNameCaseSensitive2; // 0x002A
+	KeyValues* m_pPeer; // 0x0030
+	KeyValues* m_pSub; // 0x0038
+	KeyValues* m_pChain; // 0x0040
+};
+
+struct Vector3 // Implement the proper class of this at some point.
+{
+	float x; // 0x0000
+	float y; // 0x0004
+	float z; // 0x0008
+};
+
+struct QAngle // Implement the proper class of this at some point.
+{
+	float pitch; //0x0000
+	float yaw; // 0x0004
+	float roll; // 0x0008
+};
+
+class CHostState
+{
+public:
+	int m_iCurrentState; //0x0000
+	int m_iNextState; //0x0004
+	Vector3 m_vecLocation; //0x0008
+	QAngle m_angLocation; //0x0014
+	char m_levelName[64]; //0x0020
+	char m_mapGroupName[256]; //0x0060
+	char m_landMarkName[256]; //0x0160
+	float m_flShortFrameTime; //0x0260
+	bool m_bActiveGame; //0x0264
+	bool m_bRememberLocation; //0x0265
+	bool m_bBackgroundLevel; //0x0266
+	bool m_bWaitingForConnection; //0x0267
+	bool m_bSplitScreenConnect; //0x0268
+	bool m_bGameHasShutDownAndFlushedMemory; //0x0269
+	bool m_bWorkshopMapDownloadPending; //0x026A
+};
+
+class CHLClient
+{
+public:
+	void FrameStageNotify(ClientFrameStage_t curStage) // @0x1405C0740 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = void(__thiscall*)(CHLClient*, ClientFrameStage_t);
+		(*reinterpret_cast<OriginalFn**>(this))[58](this, curStage); /* 48 83 EC 28 89 15 ? ? ? ? */
+	}
+};
+
+class CClient
+{
+public:
+	inline CClient* GetClientInstance(int index)
+	{
+		return (CClient*)(std::uintptr_t)(0x16073B200 + (index * (std::uintptr_t)0x4A4C0));
+	}
+
+	void*& GetNetChan()
+	{
+		return m_nNetChannel;
+	}
+private:
+	char pad_0000[16]; //0x0000
+public:
+	int m_iUserID; //0x0010
+private:
+	char pad_0014[908]; //0x0014
+public:
+	void* m_nNetChannel; //0x03A0
+private:
+	char pad_03A8[8]; //0x03A8
+public:
+	int m_iSignonstate; //0x03B0
+private:
+	char pad_03B4[4]; //0x03B4
+public:
+	std::int64_t m_iOriginID; //0x03B8
+private:
+	char pad_03C0[303360]; //0x03C0
+};
+
+class CCommand
+{
+private:
+	enum
+	{
+		COMMAND_MAX_ARGC = 64,
+		COMMAND_MAX_LENGTH = 512,
+	};
+
+public:
+	CCommand() = delete;
+
+	inline int MaxCommandLength()
+	{
+		return COMMAND_MAX_LENGTH - 1;
+	}
+
+	inline int64_t ArgC() const
+	{
+		return m_nArgc;
+	}
+
+	inline const char** ArgV() const
+	{
+		return m_nArgc ? (const char**)m_ppArgv : NULL;
+	}
+
+	inline const char* ArgS() const
+	{
+		return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
+	}
+
+	inline const char* GetCommandString() const
+	{
+		return m_nArgc ? m_pArgSBuffer : "";
+	}
+
+	inline const char* Arg(int nIndex) const
+	{
+		// FIXME: Many command handlers appear to not be particularly careful
+		// about checking for valid argc range. For now, we're going to
+		// do the extra check and return an empty string if it's out of range
+		if (nIndex < 0 || nIndex >= m_nArgc)
+			return "";
+		return m_ppArgv[nIndex];
+	}
+
+	inline const char* operator[](int nIndex) const
+	{
+		return Arg(nIndex);
+	}
+
+private:
+	std::int64_t m_nArgc;
+	std::int64_t m_nArgv0Size;
+	char         m_pArgSBuffer[COMMAND_MAX_LENGTH];
+	char         m_pArgvBuffer[COMMAND_MAX_LENGTH];
+	const char*  m_ppArgv[COMMAND_MAX_ARGC];
+};
+
+class ConCommandBase
+{
+public:
+	void* m_pConCommandBaseVTable; //0x0000
+	ConCommandBase* m_pNext; //0x0008
+	bool m_bRegistered; //0x0010
+private:
+	char pad_0011[7]; //0x0011
+public:
+	const char* m_pszName; //0x0018
+	const char* m_pszHelpString; //0x0020
+private:
+	char pad_0028[16]; //0x0028
+public:
+	__int32 m_nFlags; //0x0038
+private:
+	char pad_003C[4]; //0x003C
+}; //Size: 0x0038
+
+class ConVar
+{
+public:
+	ConCommandBase m_ConCommandBase; // 0x0000
+	void* m_pConVarVTable; //0x0040
+	ConVar* m_pParent; //0x0048
+	const char* n_pszDefaultValue; //0x0050
+	const char* m_pzsCurrentValue; //0x0058
+	__int64 m_iStringLength; //0x0060
+	float m_flValue; //0x0068
+	int m_iValue; //0x006C
+	bool m_bHasMin; //0x0070
+	float m_flMinValue; //0x0074
+	bool m_bHasMax; //0x0078
+	float m_flMaxValue; //0x007C
+	char pad_0080[32]; //0x0080
+}; //Size: 0x00A0
+
+class CCVarIteratorInternal // Fully reversed table, just look at the virtual function table and rename the function.
+{
+public:
+	virtual void            SetFirst(void) = 0; //0
+	virtual void            Next(void)     = 0; //1
+	virtual	bool            IsValid(void)  = 0; //2
+	virtual ConCommandBase* Get(void)      = 0; //3
+};
+
+class CCVar
+{
+public:
+	ConCommandBase* FindCommandBase(const char* szCommandName) // @0x1405983A0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = ConCommandBase*(__thiscall*)(CCVar*, const char*);
+		return (*reinterpret_cast<OriginalFn**>(this))[14](this, szCommandName);
+	}
+
+	ConVar* FindVar(const char* szVarName) // @0x1405983B0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = ConVar*(__thiscall*)(CCVar*, const char*);
+		return (*reinterpret_cast<OriginalFn**>(this))[16](this, szVarName);
+	}
+
+	void* /*Implement ConCommand class.*/ FindCommand(const char* szCommandName) // @0x1405983F0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = void*(__thiscall*)(CCVar*, const char*);
+		return (*reinterpret_cast<OriginalFn**>(this))[18](this, szCommandName);
+	}
+
+	CCVarIteratorInternal* FactoryInternalIterator() // @0x140597C10 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
+	{
+		using OriginalFn = CCVarIteratorInternal*(__thiscall*)(CCVar*);
+		return (*reinterpret_cast<OriginalFn**>(this))[41](this);
+	}
+
+	std::unordered_map<std::string, ConCommandBase*> DumpToMap()
+	{
+		std::stringstream ss;
+		CCVarIteratorInternal* itint = FactoryInternalIterator(); // Allocatd new InternalIterator.
+
+		std::unordered_map<std::string, ConCommandBase*> allConVars;
+
+		for (itint->SetFirst(); itint->IsValid(); itint->Next()) // Loop through all instances.
+		{
+			ConCommandBase* command = itint->Get();
+			const char* commandName = command->m_pszName;
+			allConVars[commandName] = command;
+		}
+
+		return allConVars;
+	}
+};
+
+struct Interface
+{
+	__int64 (*InterfacePtr)(void);
+	const char* InterfaceName;
+	__int64* NextInterfacePtr;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Initialize Game Globals
+namespace GameGlobals
+{
+	// Class Instances
+	extern CHostState* HostState;
+	extern CInputSystem* InputSystem;
+	extern CCVar* Cvar;
+	extern KeyValues** PlaylistKeyValues;
+	extern CKeyValuesSystem* KeyValuesSystem;
+	extern CClient* Client;
+	extern BanList* BanSystem;
+	
+	// Var
+	ConVar* CreateCustomConVar(const char* name, const char* defaultValue, int flags, const char* helpString, bool bMin, float fMin, bool bMax, float fMax, void* callback, void* unk);
+	void* CreateCustomConCommand(const char* name, const char* helpString, int flags, void* callback, void* callbackAfterExecution);
+
+	// Init
+	void InitGameGlobals();
+	void InitAllCommandVariations();
+	void InitPlaylist();
+
+	extern std::vector<std::string> allPlaylists;
+	extern bool IsInitialized;
+
+	// Utility
+	void DisconnectClient(CClient* client, const char* reason, unsigned __int8 unk1, char unk2);
+}
\ No newline at end of file
diff --git a/r5dedicated/hooks.cpp b/r5dedicated/hooks.cpp
index 2b590d4b..ad488c56 100644
--- a/r5dedicated/hooks.cpp
+++ b/r5dedicated/hooks.cpp
@@ -1,6 +1,7 @@
 #include "pch.h"
 #include "hooks.h"
 #include "opcodes.h"
+#include "gameclasses.h"
 
 void Hooks::InstallHooks()
 {
@@ -8,6 +9,11 @@ void Hooks::InstallHooks()
 	// Initialize Minhook
 	MH_Initialize();
 
+	///////////////////////////////////////////////////////////////////////////////
+	// Hook SourceAppSystemGroup functions
+	MH_CreateHook(addr_CSourceAppSystemGroup_Create, &Hooks::CSourceAppSystemGroup_Create, reinterpret_cast<void**>(&originalCSourceAppSystemGroup_Create));
+
+	///////////////////////////////////////////////////////////////////////////////
 	// Hook Squirrel functions
 	MH_CreateHook(addr_SQVM_Print, &Hooks::SQVM_Print, NULL);
 	MH_CreateHook(addr_SQVM_LoadRson, &Hooks::SQVM_LoadRson, reinterpret_cast<void**>(&originalSQVM_LoadRson));
@@ -32,6 +38,10 @@ void Hooks::InstallHooks()
 	// Hook Utility functions
 	MH_CreateHook(addr_MSG_EngineError, &Hooks::MSG_EngineError, reinterpret_cast<void**>(&originalMSG_EngineError));
 
+	///////////////////////////////////////////////////////////////////////////////
+	// Enable SourceAppSystemGroup hooks
+	MH_EnableHook(addr_CSourceAppSystemGroup_Create);
+
 	///////////////////////////////////////////////////////////////////////////////
 	// Enable Squirrel hooks
 	MH_EnableHook(addr_SQVM_Print);
@@ -52,11 +62,17 @@ void Hooks::InstallHooks()
 	// Enabled Utility hooks
 	MH_EnableHook(addr_MSG_EngineError);
 
-	InstallOpcodes();
+	///////////////////////////////////////////////////////////////////////////////
+	// Set global variables
+	GameGlobals::InitGameGlobals();
 }
 
 void Hooks::RemoveHooks()
 {
+	///////////////////////////////////////////////////////////////////////////////
+	// Hook SourceAppSystemGroup functions
+	MH_RemoveHook(addr_CSourceAppSystemGroup_Create);
+
 	///////////////////////////////////////////////////////////////////////////////
 	// Unhook Squirrel functions
 	MH_RemoveHook(addr_SQVM_Print);
diff --git a/r5dedicated/hooks.h b/r5dedicated/hooks.h
index be69c6ca..360bddc7 100644
--- a/r5dedicated/hooks.h
+++ b/r5dedicated/hooks.h
@@ -5,6 +5,10 @@ namespace
 {
 	Module r5_patterns = Module("r5apex.exe"); // Create module class instance.
 
+#pragma region CSourceAppSystemGroup
+	FUNC_AT_ADDRESS(addr_CSourceAppSystemGroup_Create, char(*)(__int64), r5_patterns.PatternSearch("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 48 8B F9 E8 ? ? ? ? 33 C9").GetPtr());
+#pragma endregion
+
 #pragma region Console
 	/*0x140202090*/
 	FUNC_AT_ADDRESS(addr_CommandExecute, void(*)(void*, const char*), r5_patterns.PatternSearch("48 89 5C 24 ? 57 48 83 EC 20 48 8D 0D ? ? ? ? 41 8B D8").GetPtr());
@@ -36,6 +40,9 @@ namespace
 
 	/*0x1402662D0*/
 	FUNC_AT_ADDRESS(addr_NET_SendDatagram, int(*)(SOCKET, const char*, int, int), r5_patterns.PatternSearch("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 56 41 57 48 81 EC ? 05 ? ?").GetPtr());
+
+	/*0x14025F190*/
+	FUNC_AT_ADDRESS(addr_NetChan_Shutdown, void(*)(void*, const char*, unsigned __int8, char), r5_patterns.StringSearch("Disconnect by server.\n").FindPatternSelf("E8 ? ? ? ? 4C 89 B3 ? ? ? ?", MemoryAddress::Direction::DOWN).FollowNearCallSelf().GetPtr());
 #pragma endregion
 
 #pragma region CHLClient
@@ -43,6 +50,11 @@ namespace
 	FUNC_AT_ADDRESS(addr_CHLClient_FrameStageNotify, void(*)(void* rcx, int curStage), r5_patterns.PatternSearch("48 83 EC 28 89 15 ?? ?? ?? ??").GetPtr());
 #pragma endregion
 
+#pragma region CClientState
+	/*0x1418223E4*/
+	FUNC_AT_ADDRESS(addr_m_bRestrictServerCommands, void*, r5_patterns.StringSearch("DevShotGenerator_Init()").FindPatternSelf("88 05", MemoryAddress::Direction::UP).ResolveRelativeAddressSelf(0x2).OffsetSelf(0x2).GetPtr());
+#pragma endregion
+
 #pragma region CVEngineServer
 	/*0x140315CF0*/
 	FUNC_AT_ADDRESS(addr_CVEngineServer_IsPersistenceDataAvailable, bool(*)(__int64, int), r5_patterns.PatternSearch("3B 15 ?? ?? ?? ?? 7D 33").GetPtr());
@@ -51,13 +63,23 @@ namespace
 #pragma region Utility
 	/*0x140295600*/
 	FUNC_AT_ADDRESS(addr_MSG_EngineError, int(*)(char*, va_list), r5_patterns.PatternSearch("48 89 5C 24 08 48 89 74 24 10 57 48 81 EC 30 08 00 00 48 8B DA").GetPtr());
+
+	/*0x1401B31C0*/
+	FUNC_AT_ADDRESS(addr_MemAlloc_Wrapper, void* (*)(__int64), r5_patterns.StringSearch("ConversionModeMenu").FindPatternSelf("E8 ? ? ? ? 48", MemoryAddress::Direction::UP).FollowNearCallSelf().GetPtr());
 #pragma endregion
 	// Un-used atm.
 	// DWORD64 p_KeyValues_FindKey = /*1404744E0*/ reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "40 56 57 41 57 48 81 EC ?? ?? ?? ?? 45"));
 
+#pragma region KeyValues
+/*0x1404744E0*/
+	FUNC_AT_ADDRESS(addr_KeyValues_FindKey, void* (*)(void*, const char*, bool), r5_patterns.PatternSearch("40 56 57 41 57 48 81 EC ?? ?? ?? ?? 45").GetPtr());
+#pragma endregion
+
+
 	void PrintHAddress() // Test the sigscan results
 	{
 		std::cout << "+--------------------------------------------------------+" << std::endl;
+		PRINT_ADDRESS("CSourceAppSystemGroup::Create", addr_CSourceAppSystemGroup_Create);
 		PRINT_ADDRESS("CommandExecute", addr_CommandExecute);
 		PRINT_ADDRESS("ConVar_IsFlagSet", addr_ConVar_IsFlagSet);
 		PRINT_ADDRESS("ConCommand_IsFlagSet", addr_ConCommand_IsFlagSet);
@@ -66,9 +88,12 @@ namespace
 		PRINT_ADDRESS("SQVM_LoadRson", addr_SQVM_LoadRson);
 		PRINT_ADDRESS("NET_ReceiveDatagram", addr_NET_ReceiveDatagram);
 		PRINT_ADDRESS("NET_SendDatagram ", addr_NET_SendDatagram);
+		PRINT_ADDRESS("NetChan_Shutdown ", addr_NetChan_Shutdown);
 		PRINT_ADDRESS("CHLClient::FrameStageNotify", addr_CHLClient_FrameStageNotify);
 		PRINT_ADDRESS("CVEngineServer::IsPersistenceDataAvailable", addr_CVEngineServer_IsPersistenceDataAvailable);
 		PRINT_ADDRESS("MSG_EngineError", addr_MSG_EngineError);
+		PRINT_ADDRESS("MemAlloc_Wrapper", addr_MemAlloc_Wrapper);
+		PRINT_ADDRESS("KeyValues_FindKey", addr_KeyValues_FindKey);
 		std::cout << "+--------------------------------------------------------+" << std::endl;
 		// TODO implement error handling when sigscan fails or result is 0
 	}
@@ -80,6 +105,13 @@ inline bool g_bDebugConsole = false;
 
 namespace Hooks
 {
+#pragma region CSourceAppSystemGroup
+	char __fastcall CSourceAppSystemGroup_Create(__int64 a1);
+
+	using CSourceAppSystemGroup_CreateFn = char(*)(__int64);
+	extern CSourceAppSystemGroup_CreateFn originalCSourceAppSystemGroup_Create;
+#pragma endregion
+
 #pragma region CHLClient
 //	void __fastcall FrameStageNotify(CHLClient* rcx, ClientFrameStage_t curStage);
 
@@ -122,7 +154,7 @@ namespace Hooks
 	bool ConCommand_IsFlagSet(int* cmd, int flag);
 #pragma endregion
 
-#pragma region Other
+#pragma region Utility
 	int MSG_EngineError(char* fmt, va_list args);
 
 	using MSG_EngineErrorFn = int(*)(char*, va_list);
@@ -133,4 +165,5 @@ namespace Hooks
 	void RemoveHooks();
 	void ToggleNetTrace();
 	void ToggleDevCommands();
+	void DedicatedPatch();
 }
\ No newline at end of file
diff --git a/r5dedicated/opcodes.cpp b/r5dedicated/opcodes.cpp
index d91b6b44..dbcd45fd 100644
--- a/r5dedicated/opcodes.cpp
+++ b/r5dedicated/opcodes.cpp
@@ -1,29 +1,152 @@
 #include "pch.h"
+#include "hooks.h"
+#include "enums.h"
 #include "opcodes.h"
+#include "gameclasses.h"
 
 /*-----------------------------------------------------------------------------
  * _opcodes.cpp
  *-----------------------------------------------------------------------------*/
 
-void InstallOpcodes() /* .TEXT */
+void DisableRenderer()
 {
 	//-------------------------------------------------------------------------
-	// JNZ --> JMP | Prevent OriginSDK from initializing on the client
-	//Origin_Init.Offset(0x0B).Patch({ 0xE9, 0x63, 0x02, 0x00, 0x00, 0x00 });
-	//Origin_SetState.Offset(0x0E).Patch({ 0xE9, 0xCB, 0x03, 0x00, 0x00 });
+	// FUN --> RET | Called from CEngineClient and CEngineVGUI (Init()?).
+	r0.Patch({ 0xC3 }); // This patch is likely not required if client.dll isn't initialized.
 	//-------------------------------------------------------------------------
-	// JNE --> JMP | Allow games to be loaded without the optional texture streaming file
-	dst002.Offset(0x8E5).Patch({ 0xEB, 0x19 });
+	// FUN --> RET | Skip ShaderSetup(). CShaderGlue.
+	r1.Patch({ 0xC3 });
 	//-------------------------------------------------------------------------
-	// JNE --> JMP | Prevent connect command from crashing by invalid call to UI function
-	dst004.Offset(0x1D6).Patch({ 0xEB, 0x27 });
+	// FUN --> RET | Skip Matsync. Called from CMaterialSystem.
+	r2.Patch({ 0xC3 });
 	//-------------------------------------------------------------------------
-	// JNE --> JMP | Prevent connect localhost from being executed after listenserver init
-	//Host_NewGame.Offset(0x637).Patch({ 0xE9, 0xC1, 0x00, 0x00, 0x00});
+	// JE  --> JMP | Matsys mode init (CMaterialSystem).
+	r3.Offset(0x22).Patch({ 0xEB, 0x66 });
 	//-------------------------------------------------------------------------
-	// JA  --> JMP | Disable server-side verification for duplicate accounts on the server
-	CServer_Auth.Offset(0x284).Patch({ 0x90, 0x90 });
+	// FUN --> RET | Clear render buffer? Called from CMatRenderContext and CTexture.
+	r4.Patch({ 0xC3 });
 	//-------------------------------------------------------------------------
-	// JA  --> JMP | Prevent FairFight anti-cheat from initializing on the server
+	// FUN --> RET | Heavy render stuff. Called from CMatRenderContext.
+	r5.Patch({ 0xC3 });
+	//-------------------------------------------------------------------------
+	// FUN --> RET | Set shader resource.
+	r6.Patch({ 0xC3 });
+	//-------------------------------------------------------------------------
+	// FUN --> RET | Begin.
+	r7.Patch({ 0xC3, 0x90, 0x90, 0x90, 0x90 });
+	//-------------------------------------------------------------------------
+	// FUN --> RET | End.
+	r8.Patch({ 0xC3, 0x90, 0x90, 0x90, 0x90, 0x90 });
+}
+
+void DisableClient()
+{
+	//-------------------------------------------------------------------------
+	// JNZ --> JMP | Prevent EbisuSDK from initializing on the engine and server.
+	Origin_Init.Offset(0x0B).Patch({ 0xE9, 0x63, 0x02, 0x00, 0x00, 0x00 });
+	Origin_SetState.Offset(0x0E).Patch({ 0xE9, 0xCB, 0x03, 0x00, 0x00 });
+	//-------------------------------------------------------------------------
+	// JE  --> JMP | Skip CreateGameWindow initialization code.
+	CreateGameWindow.Offset(0x3DD).Patch({ 0xEB, 0x6D });
+	//-------------------------------------------------------------------------
+	// JNZ --> JMP | Skip CreateGameWindow validation code.
+	CreateGameWindow.Offset(0x44C).Patch({ 0xEB, 0x49 });
+	//-------------------------------------------------------------------------
+	// PUS --> XOR | Prevent ShowWindow and CreateGameWindow from being initialized.
+	c1.Patch({ 0x30, 0xC0, 0xC3 });
+	//-------------------------------------------------------------------------
+	// PUS --> XOR | Prevent ShowWindow and CreateGameWindow from being initialized.
+	c1.Patch({ 0x30, 0xC0, 0xC3 });
+	//-------------------------------------------------------------------------
+	// JNE --> NOP | TODO: NOP 'particle_script' instead.
+	c2.Offset(0x23C).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 });
+	//-------------------------------------------------------------------------
+	// MOV --> NOP | TODO: NOP 'particle_script' instead.
+	c2.Offset(0x2BD).Patch({ 0x90, 0x90, 0x90 });
+	//-------------------------------------------------------------------------
+	// MOV --> NOP | TODO: NOP 'highlight_system' instead.
+	c3.Offset(0xA9).Patch({ 0x90, 0x90, 0x90, 0x90 });
+}
+
+void DisableVGUI()
+{
+	//-------------------------------------------------------------------------
+	// CMP --> XOR | Skip VGUI initialization jumptable.
+	v0.Patch({ 0x48, 0x33, 0xC0, 0xC3, 0x90, 0x90, 0x90 });
+	//-------------------------------------------------------------------------
+	// JNE --> JMP | Skip call to VGUI loadscreen func.
+	SCR_BeginLoadingPlaque.Offset(0x427).Patch({ 0xEB, 0x09 });
+}
+
+void Hooks::DedicatedPatch()
+{
+	//Sleep(10000);
+	// for future reference 14171A9B4 - matsys mode
+
+	*(uintptr_t*)0x14D415040 = 0x1417304E8;
+	*(uintptr_t*)0x14B37C3C0 = 0x141F10CA0;
+
+	*(uintptr_t*)0x14B3800D7 = 0x1; // bDedicated
+
+	DisableRenderer();
+	DisableClient();
+	DisableVGUI();
+
+	//-------------------------------------------------------------------------
+	// CAL --> NOP | HLClient call inside eng->frame.
+	addr_CEngine_Frame.Offset(0x410).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 });
+	//-------------------------------------------------------------------------
+	// JA  --> JMP | Prevent FairFight anti-cheat from initializing on the server.
+	// TODO: fix and re-enable this.
 	FairFight_Init.Offset(0x61).Patch({ 0xE9, 0xED, 0x00, 0x00, 0x00, 0x00 });
+	//-------------------------------------------------------------------------
+	// JNE --> JMP | Take dedicated initialization routine instead.
+	s0.Offset(0x19).Patch({ 0xEB, 0x6E });
+	//-------------------------------------------------------------------------
+	// JE  --> JMP | Skip client.dll Init_PostVideo() validation code.
+	s0.Offset(0x609).Patch({ 0xEB, 0x2B });
+	//-------------------------------------------------------------------------
+	// JNE --> JMP | Skip client.dll Init_PostVideo() validation code.
+	s0.Offset(0x621).Patch({ 0xEB, 0x0C });
+	//-------------------------------------------------------------------------
+	// JE  --> JMP | Skip NULL call as client is never initialized.
+	s0.Offset(0x658).Patch({ 0xE9, 0x8C, 0x00, 0x00, 0x00 });
+	//-------------------------------------------------------------------------
+	// JNE --> JMP | Skip shader preloading as cvar can't be checked due to client being NULL.
+	s0.Offset(0x6E9).Patch({ 0xE9, 0xB0, 0x00, 0x00, 0x00 });
+	//-------------------------------------------------------------------------
+	// JNE --> JMP | Return early in _Host_RunFrame() for debugging perposes.
+	//s1.Offset(0x1C6).Patch({ 0xE9, 0xAD, 0x11, 0x00, 0x00 }); // <-- this one was only used to debug.
+	//-------------------------------------------------------------------------
+	// JNE --> JMP | Return early in _Host_RunFrame() for debugging perposes.
+	s1.Offset(0x1010).Patch({ 0xEB, 0x14 });
+	//-------------------------------------------------------------------------
+	// CAL --> NOP | NOP NULL call as client is never initialized.
+	s1.Offset(0x1023).Patch({ 0x90, 0x90, 0x90 });
+	//-------------------------------------------------------------------------
+	// JS  --> JMP | Skip ListenServer HeartBeat.
+	s2.Offset(0xF).Patch({ 0xE9, 0x22, 0x01, 0x00, 0x00 });
+
+	//-------------------------------------------------------------------------
+	// CAL --> NOP | NOP call to UI texture asset preloading.
+	e0.Offset(0x182).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90 });
+	//-------------------------------------------------------------------------
+	// JNE --> JNP | Skip client.dll library initialization.
+	e0.Offset(0xA7D).Patch({ 0xE9, 0xF0, 0x01, 0x00, 0x00 });
+	//-------------------------------------------------------------------------
+	// JNE --> NOP | Skip settings field loading for client texture assets.
+	// TODO: this is also used by server.dll library.
+	e1.Offset(0x213).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 });
+
+	//-------------------------------------------------------------------------
+	// ??? 1403DFC30 = 0x94490 ??? // an expensive stuff that wasted many CPU cycles, this one seems to be the best candidate to return
+}
+
+// TEST
+void SetCHostState()
+{
+	static std::string ServerMap = std::string();
+	ServerMap = "mp_rr_canyonlands_64k_x_64k";
+	strncpy_s(GameGlobals::HostState->m_levelName, ServerMap.c_str(), 64); // Copy new map into hoststate levelname. 64 is size of m_levelname.
+	GameGlobals::HostState->m_iNextState = HostStates_t::HS_NEW_GAME; // Force CHostState::FrameUpdate to start a server.
 }
\ No newline at end of file
diff --git a/r5dedicated/opcodes.h b/r5dedicated/opcodes.h
index 4c44dcd5..48d4c2f0 100644
--- a/r5dedicated/opcodes.h
+++ b/r5dedicated/opcodes.h
@@ -1,7 +1,7 @@
 #pragma once
 
-void InstallOpcodes();
 inline HANDLE GameProcess = GetCurrentProcess();
+void SetCHostState();
 
 namespace
 {
@@ -36,6 +36,42 @@ namespace
 	MemoryAddress FairFight_Init = r5_op.PatternSearch("40 53 48 83 EC 20 8B 81 B0 03 ? ? 48 8B D9 C6");
 #pragma endregion
 
+
+	// TODO: create patterns instead and rename to function names.
+	// Renderer
+	MemoryAddress r0 = 0x00000001402FE280; //
+	MemoryAddress r1 = 0x00000001403B3A50; //
+	MemoryAddress r2 = 0x00000001403DEE90; //
+	MemoryAddress r3 = 0x00000001403BD120; //
+	MemoryAddress r4 = 0x0000000140404380; //
+	MemoryAddress r5 = 0x000000014040D850; //
+	MemoryAddress r6 = 0x0000000140413260; //
+	MemoryAddress r7 = 0x00000001404093F0; //
+	MemoryAddress r8 = 0x00000001403D2E60; //
+	MemoryAddress d3d11init = 0x000000014043CDF0; //
+
+	// Engine
+	MemoryAddress e0 = 0x0000000140236E40; // main Host_Init()?
+	MemoryAddress e1 = 0x0000000140FB2F10; // also used by CServerGameDLL
+	MemoryAddress addr_CEngine_Frame = 0x00000001402970E0;
+
+	// SERVER
+	MemoryAddress s0 = 0x0000000140237B00; // server Host_Init()?
+	MemoryAddress s1 = 0x0000000140231C00; // _Host_RunFrame() with inlined CFrameTimer::MarkFrame()?
+	MemoryAddress s2 = 0x00000001402312A0; // server HeartBeat? (baseserver.cpp)
+
+	// CLIENT
+	MemoryAddress c0 = 0x0000000140236640; // client Host_Init()?
+	MemoryAddress c1 = 0x0000000140299100; // CreateGameWindowInit()?
+	MemoryAddress c2 = 0x00000001403F4360; // 1403DF870 --> 1403F4360
+	MemoryAddress c3 = 0x00000001403F8A80; // 1403DF870 --> 1403F8A40
+	MemoryAddress CreateGameWindow = 0x0000000140343DE0;
+
+	// VGUI
+	MemoryAddress v0 = 0x0000000140282E40; // jumptable
+	MemoryAddress SCR_BeginLoadingPlaque = 0x000000014023E870;
+
+
 	void PrintOAddress() // Test the sigscan results
 	{
 		std::cout << "+--------------------------------------------------------+" << std::endl;
diff --git a/r5dedicated/pch.h b/r5dedicated/pch.h
index d81d5c4d..9a8b7cc6 100644
--- a/r5dedicated/pch.h
+++ b/r5dedicated/pch.h
@@ -1,5 +1,5 @@
 #pragma once
-#pragma message("Pre-compiling headers.\n")
+#pragma message("[DEDICATED] pre-compiling headers.\n")
 
 #define WIN32_LEAN_AND_MEAN // Prevent winsock2 redefinition.
 #include <windows.h>
@@ -27,8 +27,8 @@
 #include "sinks/stdout_sinks.h"
 #include "sinks/ostream_sink.h"
 #include "utility.h"
-//#include "httplib.h"
-//#include "json.hpp"
+#include "httplib.h"
+#include "json.hpp"
 
 #include "address.h"
 
diff --git a/r5dedicated/r5dedicated.vcxproj b/r5dedicated/r5dedicated.vcxproj
index 961013f0..5a98ecbe 100644
--- a/r5dedicated/r5dedicated.vcxproj
+++ b/r5dedicated/r5dedicated.vcxproj
@@ -185,7 +185,9 @@
   <ItemGroup>
     <ClCompile Include="..\shared\utility.cpp" />
     <ClCompile Include="console.cpp" />
+    <ClCompile Include="csourceappsystemgroup.cpp" />
     <ClCompile Include="dllmain.cpp" />
+    <ClCompile Include="gameclasses.cpp" />
     <ClCompile Include="hooks.cpp" />
     <ClCompile Include="iconvar.cpp" />
     <ClCompile Include="msgbox.cpp" />
@@ -300,6 +302,8 @@
     <ClInclude Include="..\shared\include\utility.h" />
     <ClInclude Include="console.h" />
     <ClInclude Include="dllmain.h" />
+    <ClInclude Include="enums.h" />
+    <ClInclude Include="gameclasses.h" />
     <ClInclude Include="hooks.h" />
     <ClInclude Include="opcodes.h" />
     <ClInclude Include="pch.h" />
diff --git a/r5dedicated/r5dedicated.vcxproj.filters b/r5dedicated/r5dedicated.vcxproj.filters
index c95890fb..43adb38d 100644
--- a/r5dedicated/r5dedicated.vcxproj.filters
+++ b/r5dedicated/r5dedicated.vcxproj.filters
@@ -50,36 +50,36 @@
     <Filter Include="shared\libraries\minhook\include">
       <UniqueIdentifier>{485b5648-149f-4664-a961-be9cd520e9e3}</UniqueIdentifier>
     </Filter>
-    <Filter Include="r5-sdk">
-      <UniqueIdentifier>{f5326cf2-826e-4499-98de-e818e096939d}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="r5-sdk\include">
-      <UniqueIdentifier>{4c680991-cc41-4265-a6f3-b46d698bd72f}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="r5-sdk\src">
-      <UniqueIdentifier>{8aac7eb6-9810-4fa2-bbfe-499fb2950f01}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="hooks\src">
-      <UniqueIdentifier>{f28b1a49-9b41-48d2-9462-1674af3d72a2}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="hooks\src\other">
-      <UniqueIdentifier>{cc424eef-0c7a-4fb0-9d84-30bf8db2e253}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="hooks\src\squirrel">
-      <UniqueIdentifier>{74afa89f-72af-4e13-aa90-70f7a1957154}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="hooks\src\netchannel">
-      <UniqueIdentifier>{05e6e9a7-801b-49b0-9c5a-21c4868befb7}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="hooks\src\iconvar">
-      <UniqueIdentifier>{06affed3-5a59-4b95-88ca-72d92c91909b}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="hooks\src\cvengineserver">
-      <UniqueIdentifier>{338a4fb7-7519-4628-9206-679d33824965}</UniqueIdentifier>
-    </Filter>
     <Filter Include="hooks\include">
       <UniqueIdentifier>{31cdde4d-3641-497c-9b34-20d3d7c89d87}</UniqueIdentifier>
     </Filter>
+    <Filter Include="hooks\cvengineserver">
+      <UniqueIdentifier>{338a4fb7-7519-4628-9206-679d33824965}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="hooks\iconvar">
+      <UniqueIdentifier>{06affed3-5a59-4b95-88ca-72d92c91909b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="hooks\netchannel">
+      <UniqueIdentifier>{05e6e9a7-801b-49b0-9c5a-21c4868befb7}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="hooks\other">
+      <UniqueIdentifier>{cc424eef-0c7a-4fb0-9d84-30bf8db2e253}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="hooks\squirrel">
+      <UniqueIdentifier>{74afa89f-72af-4e13-aa90-70f7a1957154}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="hooks\csourceappsystemgroup">
+      <UniqueIdentifier>{9381fa63-cf89-4980-8e5a-bf6e43cb2283}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="r5-sdk">
+      <UniqueIdentifier>{7fd080e8-390a-430b-a94c-e19c5792bf10}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="r5-sdk\src">
+      <UniqueIdentifier>{e7e154b6-398e-42f9-bfb9-e80cd306254e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="r5-sdk\include">
+      <UniqueIdentifier>{3c89e0ef-e415-4a91-86b7-2a04a5f03340}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\shared\include\address.h">
@@ -388,12 +388,18 @@
     <ClInclude Include="..\external\minhook\include\MinHook.h">
       <Filter>shared\libraries\minhook\include</Filter>
     </ClInclude>
-    <ClInclude Include="opcodes.h">
-      <Filter>r5-sdk\include</Filter>
-    </ClInclude>
     <ClInclude Include="hooks.h">
       <Filter>hooks\include</Filter>
     </ClInclude>
+    <ClInclude Include="opcodes.h">
+      <Filter>hooks\include</Filter>
+    </ClInclude>
+    <ClInclude Include="gameclasses.h">
+      <Filter>r5-sdk\include</Filter>
+    </ClInclude>
+    <ClInclude Include="enums.h">
+      <Filter>r5-sdk\include</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="console.cpp">
@@ -406,28 +412,34 @@
       <Filter>core</Filter>
     </ClCompile>
     <ClCompile Include="net.cpp">
-      <Filter>hooks\src\netchannel</Filter>
+      <Filter>hooks\netchannel</Filter>
     </ClCompile>
     <ClCompile Include="cvengineserver.cpp">
-      <Filter>hooks\src\cvengineserver</Filter>
+      <Filter>hooks\cvengineserver</Filter>
     </ClCompile>
     <ClCompile Include="sqvm.cpp">
-      <Filter>hooks\src\squirrel</Filter>
+      <Filter>hooks\squirrel</Filter>
     </ClCompile>
     <ClCompile Include="msgbox.cpp">
-      <Filter>hooks\src\other</Filter>
+      <Filter>hooks\other</Filter>
     </ClCompile>
     <ClCompile Include="..\shared\utility.cpp">
       <Filter>shared</Filter>
     </ClCompile>
     <ClCompile Include="iconvar.cpp">
-      <Filter>hooks\src\iconvar</Filter>
+      <Filter>hooks\iconvar</Filter>
     </ClCompile>
     <ClCompile Include="opcodes.cpp">
-      <Filter>r5-sdk\src</Filter>
+      <Filter>hooks</Filter>
     </ClCompile>
     <ClCompile Include="hooks.cpp">
-      <Filter>hooks\src</Filter>
+      <Filter>hooks</Filter>
+    </ClCompile>
+    <ClCompile Include="csourceappsystemgroup.cpp">
+      <Filter>hooks\csourceappsystemgroup</Filter>
+    </ClCompile>
+    <ClCompile Include="gameclasses.cpp">
+      <Filter>r5-sdk\src</Filter>
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
diff --git a/r5dev/include/pch.h b/r5dev/include/pch.h
index b42160e0..de793c13 100644
--- a/r5dev/include/pch.h
+++ b/r5dev/include/pch.h
@@ -1,5 +1,5 @@
 #pragma once
-#pragma message("Pre-compiling headers.\n")
+#pragma message("[DEV] pre-compiling headers.\n")
 
 #define WIN32_LEAN_AND_MEAN // Prevent winsock2 redefinition.
 #include <windows.h>
diff --git a/shared/include/banlist.h b/shared/include/banlist.h
index 71889965..3ed13f42 100644
--- a/shared/include/banlist.h
+++ b/shared/include/banlist.h
@@ -1,4 +1,5 @@
 #pragma once
+#include "pch.h"
 
 class BanList
 {