diff --git a/r5dev/engine/client/client.cpp b/r5dev/engine/client/client.cpp index a24c7192..be2e0b50 100644 --- a/r5dev/engine/client/client.cpp +++ b/r5dev/engine/client/client.cpp @@ -25,7 +25,7 @@ CClient* CClient::GetClient(int nIndex) const //--------------------------------------------------------------------------------- // Purpose: gets the handle of this client //--------------------------------------------------------------------------------- -uint16_t CClient::GetHandle(void) const +edict_t CClient::GetHandle(void) const { return m_nHandle; } @@ -89,7 +89,7 @@ const char* CClient::GetClientName(void) const //--------------------------------------------------------------------------------- // Purpose: sets the handle of this client //--------------------------------------------------------------------------------- -void CClient::SetHandle(uint16_t nHandle) +void CClient::SetHandle(edict_t nHandle) { m_nHandle = nHandle; } diff --git a/r5dev/engine/client/client.h b/r5dev/engine/client/client.h index 66cff761..ff469d3d 100644 --- a/r5dev/engine/client/client.h +++ b/r5dev/engine/client/client.h @@ -2,6 +2,7 @@ #include "vpc/keyvalues.h" #include "common/protocol.h" #include "engine/net_chan.h" +#include "public/edict.h" //----------------------------------------------------------------------------- // Enumerations @@ -26,7 +27,7 @@ class CClient : IClientMessageHandler, INetChannelHandler { public: CClient* GetClient(int nIndex) const; - uint16_t GetHandle(void) const; + edict_t GetHandle(void) const; uint32_t GetUserID(void) const; uint64_t GetNucleusID(void) const; SIGNONSTATE GetSignonState(void) const; @@ -34,7 +35,7 @@ public: CNetChan* GetNetChan(void) const; const char* GetServerName(void) const; const char* GetClientName(void) const; - void SetHandle(uint16_t nHandle); + void SetHandle(edict_t nHandle); void SetUserID(uint32_t nUserID); void SetNucleusID(uint64_t nNucleusID); void SetSignonState(SIGNONSTATE nSignonState); @@ -56,7 +57,7 @@ public: private: uint32_t m_nUserID; //0x0010 - uint16_t m_nHandle; //0x0014 + edict_t m_nHandle; //0x0014 char m_szServerName[64]; //0x0016 int64_t m_nReputation; //0x0058 char pad_0014[182]; //0x0060 diff --git a/r5dev/game/server/gameinterface.cpp b/r5dev/game/server/gameinterface.cpp index c2078d56..acb67e01 100644 --- a/r5dev/game/server/gameinterface.cpp +++ b/r5dev/game/server/gameinterface.cpp @@ -9,6 +9,7 @@ #include "engine/server/sv_main.h" #include "game/server/gameinterface.h" #include "public/server_class.h" +#include "public/eiface.h" //----------------------------------------------------------------------------- // This is called when a new game is started. (restart, map) @@ -91,6 +92,6 @@ void CServerGameDLL_Detach() #endif } -// Pointer to CServerGameDLL virtual function table. CServerGameDLL* g_pServerGameDLL = nullptr; CServerGameClients* g_pServerGameClients = nullptr; +CServerGameEnts* g_pServerGameEntities = nullptr; diff --git a/r5dev/game/server/gameinterface.h b/r5dev/game/server/gameinterface.h index fae5fc15..f7994987 100644 --- a/r5dev/game/server/gameinterface.h +++ b/r5dev/game/server/gameinterface.h @@ -4,9 +4,16 @@ // // $NoKeywords: $ //=============================================================================// +#include "public/eiface.h" +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- class ServerClass; +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- class CServerGameDLL { public: @@ -19,7 +26,18 @@ public: static void __fastcall OnReceivedSayTextMessage(void* thisptr, int senderId, const char* text, bool isTeamChat); }; -class CServerGameClients + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +class CServerGameClients : public IServerGameClients +{ +}; + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +class CServerGameEnts : public IServerGameEnts { }; @@ -28,6 +46,7 @@ inline auto CServerGameDLL__OnReceivedSayTextMessage = p_CServerGameDLL__OnRecei extern CServerGameDLL* g_pServerGameDLL; extern CServerGameClients* g_pServerGameClients; +extern CServerGameEnts* g_pServerGameEntities; void CServerGameDLL_Attach(); void CServerGameDLL_Detach(); @@ -40,22 +59,17 @@ class VServerGameDLL : public IDetour spdlog::debug("| FUN: OnReceivedSayTextMessage : {:#18x} |\n", p_CServerGameDLL__OnReceivedSayTextMessage.GetPtr()); spdlog::debug("| VAR: g_pServerGameDLL : {:#18x} |\n", reinterpret_cast(g_pServerGameDLL)); spdlog::debug("| VAR: g_pServerGameClients : {:#18x} |\n", reinterpret_cast(g_pServerGameClients)); + spdlog::debug("| VAR: g_pServerGameEntities : {:#18x} |\n", reinterpret_cast(g_pServerGameEntities)); spdlog::debug("+----------------------------------------------------------------+\n"); } virtual void GetFun(void) const { #if defined(GAMEDLL_S3) p_CServerGameDLL__OnReceivedSayTextMessage = g_GameDll.FindPatternSIMD("85 D2 0F 8E ?? ?? ?? ?? 4C 8B DC"); - CServerGameDLL__OnReceivedSayTextMessage = p_CServerGameDLL__OnReceivedSayTextMessage.RCast(); #endif } - virtual void GetVar(void) const - { - g_pServerGameDLL = p_SV_CreateBaseline.Offset(0x0).FindPatternSelf("48 8B", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).Deref().RCast(); - g_pServerGameClients = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 81 EC ?? ?? ?? ?? 0F B7 51 14"). - FindPatternSelf("48 8B 0D", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); - } + virtual void GetVar(void) const { } virtual void GetCon(void) const { } virtual void Attach(void) const { } virtual void Detach(void) const { } diff --git a/r5dev/launcher/IApplication.cpp b/r5dev/launcher/IApplication.cpp index c4cf6452..92804d9e 100644 --- a/r5dev/launcher/IApplication.cpp +++ b/r5dev/launcher/IApplication.cpp @@ -21,6 +21,9 @@ #include "server/vengineserver_impl.h" #include "client/cdll_engine_int.h" #include "engine/enginetrace.h" +#ifndef CLIENT_DLL +#include "game/server/gameinterface.h" +#endif // !CLIENT_DLL #ifndef DEDICATED #include "gameui/IConsole.h" #endif // !DEDICATED @@ -68,9 +71,17 @@ bool CModAppSystemGroup::Create(CModAppSystemGroup* pModAppSystemGroup) //InitPluginSystem(pModAppSystemGroup); //CALL_PLUGIN_CALLBACKS(g_pPluginSystem->GetCreateCallbacks(), pModAppSystemGroup); +#ifndef CLIENT_DLL + g_pServerGameDLL = g_pFactory->GetFactoryPtr(INTERFACEVERSION_SERVERGAMEDLL, false).RCast(); + g_pServerGameClients = g_pFactory->GetFactoryPtr(INTERFACEVERSION_SERVERGAMECLIENTS_NEW, false).RCast(); + if (!g_pServerGameClients) + g_pServerGameClients = g_pFactory->GetFactoryPtr(INTERFACEVERSION_SERVERGAMECLIENTS, false).RCast(); + g_pServerGameEntities = g_pFactory->GetFactoryPtr(INTERFACEVERSION_SERVERGAMEENTS, false).RCast(); +#endif // !CLIENT_DLL + #ifndef DEDICATED - g_pClientEntityList = g_pFactory->GetFactoryPtr("VClientEntityList003", false).RCast(); - g_pEngineTrace = g_pFactory->GetFactoryPtr("EngineTraceClient004", false).RCast(); + g_pClientEntityList = g_pFactory->GetFactoryPtr(VCLIENTENTITYLIST_INTERFACE_VERSION, false).RCast(); + g_pEngineTrace = g_pFactory->GetFactoryPtr(INTERFACEVERSION_ENGINETRACE_CLIENT, false).RCast(); g_pImGuiConfig->Load(); // Load ImGui configs. for (auto& map : g_pCVar->DumpToMap()) diff --git a/r5dev/public/edict.h b/r5dev/public/edict.h index 06d10d5b..118acf91 100644 --- a/r5dev/public/edict.h +++ b/r5dev/public/edict.h @@ -7,6 +7,7 @@ #include "engine/server/sv_main.h" #endif // !CLIENT_DLL +typedef uint16_t edict_t; //----------------------------------------------------------------------------- // Purpose: Defines the ways that a map can be loaded. diff --git a/r5dev/public/eiface.h b/r5dev/public/eiface.h new file mode 100644 index 00000000..efc6f6a9 --- /dev/null +++ b/r5dev/public/eiface.h @@ -0,0 +1,174 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// +#ifndef EIFACE_H +#define EIFACE_H +#include "edict.h" +#include "tier1/bitbuf.h" +#include "vpc/keyvalues.h" + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CRecipientFilter; // TODO: Reverse. + +//----------------------------------------------------------------------------- +// Purpose: Interface to get at server clients +//----------------------------------------------------------------------------- +abstract_class IServerGameClients +{ +public: + // Get server max players and lower bound for same + virtual void GetPlayerLimits(int& nMinPlayers, int& nMaxPlayers, int& nDefaultMaxPlayers) const = 0; + + // Client is connecting to server ( return false to reject the connection ) + // You can specify a rejection message by writing it into pszReject + virtual bool ClientConnect(edict_t nEntity, char const* pszName, char const* pszAddress, char* pszReject, int nMaxRejectLen) = 0; + + // Client is going active + // If bLoadGame is true, don't spawn the player because its state is already setup. + virtual void ClientActive(edict_t nEntity, bool bLoadGame) = 0; + virtual void ClientFullyConnect(edict_t nEntity, bool bRestore) = 0; +}; + +//----------------------------------------------------------------------------- +// Purpose: Interface to get at server entities +//----------------------------------------------------------------------------- +abstract_class IServerGameEnts +{ +public: + virtual ~IServerGameEnts() = 0; + // !TODO +}; + +//----------------------------------------------------------------------------- +// Purpose: Interface the engine exposes to the game DLL +//----------------------------------------------------------------------------- +abstract_class IVEngineServer +{ +public: + virtual int GetNumGameSlots(void) const = 0; + // Tell engine to change level ( "changelevel s1\n" ) + virtual void ChangeLevel( const char *szLevelName ) = 0; + // Ask engine whether the specified map is a valid map file (exists and has valid version number). + virtual bool IsMapValid(const char* szFileName) = 0; + // Is this a dedicated server? + virtual bool IsDedicatedServer(void) = 0; + // Is this server active? + virtual bool IsActive(void) = 0; + virtual void NullSub0(void) = 0; + // get arbitrary launch options + virtual KeyValues* GetLaunchOptions(void) = 0; + + // Add to the server/client lookup/precache table, the specified string is given a unique index + // NOTE: The indices for PrecacheModel are 1 based + // a 0 returned from those methods indicates the model or sound was not correctly precached + // However, generic and decal are 0 based + // If preload is specified, the file is loaded into the server/client's cache memory before level startup, otherwise + // it'll only load when actually used (which can cause a disk i/o hitch if it occurs during play of a level). + virtual int PrecacheModel(const char* szName) = 0; + virtual int PrecacheDecal(const char* szName) = 0; + + virtual int GetNumEdicts(void) const = 0; + + // !TODO: + virtual void sub_140313E70(void) = 0; + virtual void sub_140313EC0(void) = 0; + virtual void sub_140313F10(void) = 0; + virtual void sub_140313F70(void) = 0; + virtual void sub_140313FB0(void) = 0; + virtual void sub_140314020(void) = 0; + virtual void sub_140314060(void) = 0; + virtual void sub_140314080(void) = 0; + virtual void sub_1403140C0(void) = 0; + virtual void sub_140314140(void) = 0; + virtual void sub_140314150(void) = 0; + + + virtual bool EmptyEdictSlotsAvailable(void) const = 0; + + // Fade out the client's volume level toward silence (or fadePercent) + virtual void FadeClientVolume(const edict_t* pEdict, float flFadePercent, float flFadeOutSeconds, float flHoldTime, float flFadeInSeconds) = 0; + + // Issue a command to the command parser as if it was typed at the server console. + virtual void ServerCommand(const char* szCommand) = 0; + virtual void ServerCommandTokenized(const char* szCommand) = 0; + // Execute any commands currently in the command parser immediately (instead of once per frame) + virtual void ServerExecute(void) = 0; + // Issue the specified command to the specified client (mimics that client typing the command at the console). + virtual void ClientCommand(edict_t* pEdict, PRINTF_FORMAT_STRING const char* szFmt, ...) FMTFUNCTION(3, 4) = 0; + + // Set the lightstyle to the specified value and network the change to any connected clients. Note that val must not + // change place in memory (use MAKE_STRING) for anything that's not compiled into your mod. + virtual void LightStyle( int nStyle, PRINTF_FORMAT_STRING const char *szVal ) = 0; + + virtual bf_write* UserMessageBegin(CRecipientFilter* filter, int a3, char* szMessageName, int nMsgIdx) = 0; + virtual void MessageEnd(void) = 0; + virtual void MessageCancel(void) = 0; + + // Print szMsg to the client console. + virtual void ClientPrintf(edict_t nEdict, const char* szMsg) = 0; + + // SINGLE PLAYER/LISTEN SERVER ONLY (just matching the client .dll api for this) + // Prints the formatted string to the notification area of the screen ( down the right hand edge + // numbered lines starting at position 0 + virtual void Con_NPrintf( int nPos, const char *szFmt, ... ) = 0; // Might not work, this vtable pointer points to a implementation that has a signature similar to 'Con_NXPrintf'. + // SINGLE PLAYER/LISTEN SERVER ONLY(just matching the client .dll api for this) + // Similar to Con_NPrintf, but allows specifying custom text color and duration information + virtual void Con_NXPrintf( const struct con_nprint_s *pInfo, const char *szFmt, ... ) = 0; + + // Change a specified player's "view entity" (i.e., use the view entity position/orientation for rendering the client view) + virtual void SetView(const edict_t nClient, const edict_t nViewEnt) = 0; + + // returns 'pViewent'. + virtual void Unk0(const edict_t nClient, const edict_t nViewEnt) = 0; + // TODO: similar to 'SetView' + virtual void Unk1(const edict_t nClient, const edict_t nViewEnt) = 0; + virtual void Unk2(const edict_t nClient, const edict_t nViewEnt) = 0; + + // Set the player's crosshair angle + virtual void CrosshairAngle(const edict_t nClient, float flPitch, float flYaw) = 0; + virtual bool GrantClientSidePickup(const edict_t nClient, int a3, int a4, int* a5, int a6, int a7, int a8) = 0; + + // Get the current game directory (hl2, tf2, hl1, cstrike, etc.) + virtual void GetGameDir(char* szGetGameDir, int nMaxlength) = 0; + // Used by AI node graph code to determine if .bsp and .ain files are out of date + virtual int CompareFileTime(const char* szFileName1, const char* szFileName2, int* iCompare) = 0; + + // Locks/unlocks the network string tables (.e.g, when adding bots to server, this needs to happen). + // Be sure to reset the lock after executing your code!!! + virtual bool LockNetworkStringTables( bool bLock ) = 0; + + virtual int GetNumConnectedPlayers(void) const = 0; + virtual int GetNumTotalPlayers(void) const = 0; + virtual int GetNumFakePlayers(void) const = 0; + virtual int GetNumHumanPlayers(void) const = 0; + + // Create a bot with the given name. Returns -1 if fake client can't be created + virtual edict_t CreateFakeClient(const char* szName, int nTeam) = 0; + + // Get a convar keyvalue for specified client + virtual const char* GetClientConVarValue(int nClientIndex, const char* szConVarName) = 0; + + +#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) + virtual void NullSub1(void) = 0; // Additional nullsub only present in s0 and s1 gamedll's +#endif // GAMEDLL_S0 || GAMEDLL_S1 + + // Returns the name as represented on the server of specified client + virtual const char* GetClientServerName(int nClientIndex) = 0; + // Returns the network address of specified client + virtual const char* GetClientNetworkAddress(int nClientIndex) = 0; + // !TODO: Returns float field in CCLient from specified client, needs to be reversed still + virtual float Unk3(int nClientIndex) = 0; + + virtual bool ReplayEnabled(void) const = 0; + + // !TODO: the rest.. +}; + +#endif // EIFACE_H diff --git a/r5dev/server/vengineserver_impl.cpp b/r5dev/server/vengineserver_impl.cpp index dc64b5e3..d7b955c2 100644 --- a/r5dev/server/vengineserver_impl.cpp +++ b/r5dev/server/vengineserver_impl.cpp @@ -13,7 +13,7 @@ //----------------------------------------------------------------------------- // Purpose: sets the persistence var in the CClient instance to 'ready' //----------------------------------------------------------------------------- -bool HIVEngineServer__PersistenceAvailable(void* entidx, int clienthandle) +bool CVEngineServer::PersistenceAvailable(void* entidx, int clienthandle) { CClient* pClient = g_pClient->GetClient(clienthandle); // Get client instance. pClient->SetPersistenceState(PERSISTENCE::PERSISTENCE_READY); // Set the client instance to 'ready'. @@ -42,13 +42,16 @@ bool HIVEngineServer__PersistenceAvailable(void* entidx, int clienthandle) void IVEngineServer_Attach() { - DetourAttach((LPVOID*)&IVEngineServer__PersistenceAvailable, &HIVEngineServer__PersistenceAvailable); + DetourAttach((LPVOID*)&IVEngineServer__PersistenceAvailable, &CVEngineServer::PersistenceAvailable); } void IVEngineServer_Detach() { - DetourDetach((LPVOID*)&IVEngineServer__PersistenceAvailable, &HIVEngineServer__PersistenceAvailable); + DetourDetach((LPVOID*)&IVEngineServer__PersistenceAvailable, &CVEngineServer::PersistenceAvailable); } /////////////////////////////////////////////////////////////////////////////// ServerPlayer_t g_ServerPlayer[MAX_PLAYERS]; + +IVEngineServer* g_pEngineServerVFTable = nullptr; +CVEngineServer* g_pEngineServer = reinterpret_cast(&g_pEngineServerVFTable); \ No newline at end of file diff --git a/r5dev/server/vengineserver_impl.h b/r5dev/server/vengineserver_impl.h index 8ffd7d86..04bd127b 100644 --- a/r5dev/server/vengineserver_impl.h +++ b/r5dev/server/vengineserver_impl.h @@ -1,26 +1,17 @@ #pragma once +#include "public/edict.h" +#include "public/eiface.h" /* ==== CVENGINESERVER ================================================================================================================================================== */ inline CMemory p_IVEngineServer__PersistenceAvailable; inline auto IVEngineServer__PersistenceAvailable = p_IVEngineServer__PersistenceAvailable.RCast(); -inline CMemory p_IVEngineServer__IsDedicatedServer; -inline auto IVEngineServer__IsDedicatedServer = p_IVEngineServer__IsDedicatedServer.RCast(); - -inline CMemory p_IVEngineServer__GetNumHumanPlayers; -inline auto IVEngineServer__GetNumHumanPlayers = p_IVEngineServer__GetNumHumanPlayers.RCast(); - -inline CMemory p_IVEngineServer__GetNumFakeClients; -inline auto IVEngineServer__GetNumFakeClients = p_IVEngineServer__GetNumFakeClients.RCast(); - //inline CMemory p_RunFrameServer; //inline auto v_RunFrameServer = p_RunFrameServer.RCast(); inline bool* g_bDedicated = nullptr; /////////////////////////////////////////////////////////////////////////////// -bool HIVEngineServer__PersistenceAvailable(void* entidx, int clientidx); - void IVEngineServer_Attach(); void IVEngineServer_Detach(); @@ -53,36 +44,40 @@ struct ServerPlayer_t extern ServerPlayer_t g_ServerPlayer[MAX_PLAYERS]; +class CVEngineServer : public IVEngineServer +{ +public: + static bool PersistenceAvailable(void* entidx, int clientidx); + // Implementation in GameDLL. +}; +extern CVEngineServer* g_pEngineServer; +extern IVEngineServer* g_pEngineServerVFTable; + /////////////////////////////////////////////////////////////////////////////// class HVEngineServer : public IDetour { virtual void GetAdr(void) const { - spdlog::debug("| FUN: IVEngineServer::PersistenceAvailable : {:#18x} |\n", p_IVEngineServer__PersistenceAvailable.GetPtr()); - spdlog::debug("| FUN: IVEngineServer::IsDedicatedServer : {:#18x} |\n", p_IVEngineServer__IsDedicatedServer.GetPtr()); - spdlog::debug("| FUN: IVEngineServer::GetNumHumanPlayers : {:#18x} |\n", p_IVEngineServer__GetNumHumanPlayers.GetPtr()); - spdlog::debug("| FUN: IVEngineServer::GetNumFakeClients : {:#18x} |\n", p_IVEngineServer__GetNumFakeClients.GetPtr()); + spdlog::debug("| FUN: CVEngineServer::PersistenceAvailable : {:#18x} |\n", p_IVEngineServer__PersistenceAvailable.GetPtr()); //spdlog::debug("| FUN: RunFrameServer : {:#18x} |\n", p_RunFrameServer.GetPtr()); spdlog::debug("| VAR: g_bDedicated : {:#18x} |\n", reinterpret_cast(g_bDedicated)); + spdlog::debug("| VAR: g_pEngineServerVFTable : {:#18x} |\n", reinterpret_cast(g_pEngineServerVFTable)); spdlog::debug("+----------------------------------------------------------------+\n"); } virtual void GetFun(void) const { p_IVEngineServer__PersistenceAvailable = g_GameDll.FindPatternSIMD("3B 15 ?? ?? ?? ?? 7D 33"); - p_IVEngineServer__IsDedicatedServer = g_GameDll.FindPatternSIMD("0F B6 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 48 8B 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 40 53"); - p_IVEngineServer__GetNumHumanPlayers = g_GameDll.FindPatternSIMD("8B 15 ?? ?? ?? ?? 33 C0 85 D2 7E 24"); - p_IVEngineServer__GetNumFakeClients = g_GameDll.FindPatternSIMD("8B 05 ?? ?? ?? ?? 33 C9 85 C0 7E 2D"); // p_RunFrameServer = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 30 0F 29 74 24 ?? 48 8D 0D ?? ?? ?? ??"); - IVEngineServer__PersistenceAvailable = p_IVEngineServer__PersistenceAvailable.RCast(); /*3B 15 ?? ?? ?? ?? 7D 33*/ - IVEngineServer__IsDedicatedServer = p_IVEngineServer__IsDedicatedServer.RCast(); /*0F B6 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 48 8B 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 40 53*/ - IVEngineServer__GetNumHumanPlayers = p_IVEngineServer__GetNumHumanPlayers.RCast(); /*8B 15 ?? ?? ?? ?? 33 C0 85 D2 7E 24*/ - IVEngineServer__GetNumFakeClients = p_IVEngineServer__GetNumFakeClients.RCast(); /*8B 05 ?? ?? ?? ?? 33 C9 85 C0 7E 2D*/ -// v_RunFrameServer = p_RunFrameServer.RCast(); /*48 89 5C 24 ?? 57 48 83 EC 30 0F 29 74 24 ?? 48 8D 0D ?? ?? ?? ??*/ + IVEngineServer__PersistenceAvailable = p_IVEngineServer__PersistenceAvailable.RCast(); /*3B 15 ?? ?? ?? ?? 7D 33*/ +// v_RunFrameServer = p_RunFrameServer.RCast(); /*48 89 5C 24 ?? 57 48 83 EC 30 0F 29 74 24 ?? 48 8D 0D ?? ?? ?? ??*/ } virtual void GetVar(void) const { - g_bDedicated = p_IVEngineServer__IsDedicatedServer.ResolveRelativeAddress(0x3, 0x7).RCast(); + CMemory pEngineServerVFTable = g_GameDll.GetVirtualMethodTable(".?AVCVEngineServer@@", 0); + + g_pEngineServerVFTable = pEngineServerVFTable.RCast(); + g_bDedicated = pEngineServerVFTable.WalkVTableSelf(3).DerefSelf().ResolveRelativeAddress(0x3, 0x7).RCast(); } virtual void GetCon(void) const { } virtual void Attach(void) const { } diff --git a/r5dev/tier1/cmd.cpp b/r5dev/tier1/cmd.cpp index 7248a24f..02d15d51 100644 --- a/r5dev/tier1/cmd.cpp +++ b/r5dev/tier1/cmd.cpp @@ -343,7 +343,7 @@ void ConCommand::Init(void) ConCommand::Create("sv_banid", "Bans a client from the server by handle, nucleus id or ip address | Usage: sv_banid \"\"/\"/\".", FCVAR_RELEASE, Host_BanID_f, nullptr); ConCommand::Create("sv_unban", "Unbans a client from the server by nucleus id or ip address | Usage: sv_unban \"\"/\"\".", FCVAR_RELEASE, Host_Unban_f, nullptr); ConCommand::Create("sv_reloadbanlist", "Reloads the banned list.", FCVAR_RELEASE, Host_ReloadBanList_f, nullptr); - + ConCommand::Create("sv_addbot", "Creates a bot on the server.", FCVAR_RELEASE, CC_CreateFakePlayer_f, nullptr); ConCommand::Create("navmesh_hotswap", "Hot swap the NavMesh for all hulls.", FCVAR_DEVELOPMENTONLY, Detour_HotSwap_f, nullptr); #endif // !CLIENT_DLL #ifndef DEDICATED diff --git a/r5dev/vpc/interfaces.h b/r5dev/vpc/interfaces.h index 32bd57d0..9b9e3aff 100644 --- a/r5dev/vpc/interfaces.h +++ b/r5dev/vpc/interfaces.h @@ -14,7 +14,8 @@ #define MATERIALSYSTEM_CONFIG_VERSION "VMaterialSystemConfig004" #define SERVER_DLL_SHARED_APPSYSTEMS "VServerDllSharedAppSystems001" -#define INTERFACEVERSION_SERVERGAMECLIENTS "ServerGameClients004" +#define INTERFACEVERSION_SERVERGAMECLIENTS_NEW "ServerGameClients004" +#define INTERFACEVERSION_SERVERGAMECLIENTS "ServerGameClients003" #define INTERFACEVERSION_SERVERGAMEENTS "ServerGameEnts002" #define INTERFACEVERSION_SERVERGAMEDLL "ServerGameDLL005" diff --git a/r5dev/vproj/clientsdk.vcxproj b/r5dev/vproj/clientsdk.vcxproj index f930b00c..4ac86294 100644 --- a/r5dev/vproj/clientsdk.vcxproj +++ b/r5dev/vproj/clientsdk.vcxproj @@ -274,6 +274,7 @@ + diff --git a/r5dev/vproj/clientsdk.vcxproj.filters b/r5dev/vproj/clientsdk.vcxproj.filters index 0e46eed9..d6cfba05 100644 --- a/r5dev/vproj/clientsdk.vcxproj.filters +++ b/r5dev/vproj/clientsdk.vcxproj.filters @@ -1886,6 +1886,9 @@ sdk\public\utility + + sdk\public + diff --git a/r5dev/vproj/dedicated.vcxproj b/r5dev/vproj/dedicated.vcxproj index 6f73deaf..4c1fd527 100644 --- a/r5dev/vproj/dedicated.vcxproj +++ b/r5dev/vproj/dedicated.vcxproj @@ -221,6 +221,7 @@ + diff --git a/r5dev/vproj/dedicated.vcxproj.filters b/r5dev/vproj/dedicated.vcxproj.filters index 2f492f76..b46b8504 100644 --- a/r5dev/vproj/dedicated.vcxproj.filters +++ b/r5dev/vproj/dedicated.vcxproj.filters @@ -1290,6 +1290,9 @@ sdk\public\utility + + sdk\public + diff --git a/r5dev/vproj/gamesdk.vcxproj b/r5dev/vproj/gamesdk.vcxproj index b498b2cb..40725f59 100644 --- a/r5dev/vproj/gamesdk.vcxproj +++ b/r5dev/vproj/gamesdk.vcxproj @@ -302,6 +302,7 @@ + diff --git a/r5dev/vproj/gamesdk.vcxproj.filters b/r5dev/vproj/gamesdk.vcxproj.filters index b6c6a329..8c1a20f1 100644 --- a/r5dev/vproj/gamesdk.vcxproj.filters +++ b/r5dev/vproj/gamesdk.vcxproj.filters @@ -1988,6 +1988,9 @@ sdk\public\utility + + sdk\public + diff --git a/r5dev/vstdlib/callback.cpp b/r5dev/vstdlib/callback.cpp index 6b3f9422..ba9ee0c2 100644 --- a/r5dev/vstdlib/callback.cpp +++ b/r5dev/vstdlib/callback.cpp @@ -51,6 +51,7 @@ #endif // !DEDICATED #ifndef CLIENT_DLL #include "game/server/detour_impl.h" +#include "game/server/gameinterface.h" #endif // !CLIENT_DLL #ifndef DEDICATED #include "game/client/viewrender.h" @@ -1230,3 +1231,29 @@ void CVFlag_f(const CCommand& args) { cv->CvarFindFlags_f(args); } + +/* +===================== +CC_CreateFakePlayer_f + + Creates a fake player + on the server +===================== +*/ +void CC_CreateFakePlayer_f(const CCommand& args) +{ +#ifndef CLIENT_DLL + if (args.ArgC() < 3) + { + DevMsg(eDLL_T::SERVER, "usage: sv_addbot name teamid\n"); + return; + } + + g_pEngineServer->LockNetworkStringTables(true); + + edict_t nHandle = g_pEngineServer->CreateFakeClient(args.Arg(1), std::stoi(args.Arg(2))); + g_pServerGameClients->ClientFullyConnect(nHandle, false); + + g_pEngineServer->LockNetworkStringTables(false); +#endif // !CLIENT_DLL +} \ No newline at end of file diff --git a/r5dev/vstdlib/callback.h b/r5dev/vstdlib/callback.h index 715b42b6..ed85788f 100644 --- a/r5dev/vstdlib/callback.h +++ b/r5dev/vstdlib/callback.h @@ -70,6 +70,8 @@ void CVHelp_f(const CCommand& args); void CVList_f(const CCommand& args); void CVDiff_f(const CCommand& args); void CVFlag_f(const CCommand& args); + +void CC_CreateFakePlayer_f(const CCommand& args); /////////////////////////////////////////////////////////////////////////////// class VCallback : public IDetour {