diff --git a/FullUpdate_nide_1.12/gamedata/FullUpdate.games.txt b/FullUpdate_nide_1.12/gamedata/FullUpdate.games.txt new file mode 100644 index 00000000..911e9dbb --- /dev/null +++ b/FullUpdate_nide_1.12/gamedata/FullUpdate.games.txt @@ -0,0 +1,165 @@ +"Games" +{ + "#default" + { + "#supported" + { + "engine" "orangebox_valve" + "engine" "css" + "engine" "csgo" + } + + "Addresses" + { + "CBaseServer" + { + "windows" + { + "signature" "CVEngineServer::CreateFakeClient" + "read" "8" + } + "linux" + { + "signature" "sv" + } + "mac" + { + "signature" "sv" + } + } + } + + "Signatures" + { + "CVEngineServer::CreateFakeClient" + { + "library" "engine" + "windows" "\x55\x8B\xEC\x56\xFF\x2A\x2A\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B" + } + + "sv" + { + "library" "engine" + "linux" "@sv" + "mac" "@sv" + } + } + } + + "#default" + { + "#supported" + { + "engine" "orangebox" + "engine" "left4dead" + "engine" "left4dead2" + } + + "Addresses" + { + "CBaseServer" + { + "windows" + { + "signature" "CVEngineServer::CreateFakeClient" + "read" "6" + } + "linux" + { + "signature" "sv" + } + "mac" + { + "signature" "sv" + } + } + } + + "Signatures" + { + "CVEngineServer::CreateFakeClient" + { + "library" "engine" + "windows" "\x8B\x44\x24\x04\x50\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x85\xC0" + } + + "sv" + { + "library" "engine" + "linux" "@sv" + "mac" "@sv" + } + } + } + + "#default" + { + "#supported" + { + "engine" "orangebox" + "engine" "orangebox_valve" + "engine" "css" + } + + "Offsets" + { + "CBaseServer::GetClient" + { + "windows" "6" + "linux" "7" + "mac" "7" + } + "CBaseClient::UpdateAcknowledgedFramecount" + { + "linux" "44" + } + } + } + + "#default" + { + "#supported" + { + "engine" "left4dead" + "engine" "left4dead2" + "engine" "csgo" + } + + "Offsets" + { + "CBaseServer::GetClient" + { + "windows" "6" + "linux" "7" + "mac" "7" + } + } + } + + "csgo" + { + "Offsets" + { + // a1[134] * 4 + "m_nDeltaTick" + { + "linux" "536" + } + // a1[206] * 4 + "m_nForceWaitForTick" + { + "linux" "824" + } + } + + "Signatures" + { + // Str: "Sending full update to Client %s (%s)\n" ^ CBaseClient::OnRequestFullUpdate + "CBaseClient::OnRequestFullUpdate" + { + "library" "engine" + "linux" "\x55\x89\xE5\x53\x83\xEC\x14\x8B\x5D\x08\xC7\x44\x24\x04\x00\x00\x00\x00\x8D\x83\x24\x02\x00\x00" + } + } + } +} diff --git a/FullUpdate_nide_1.12/scripting/FullUpdate.sp b/FullUpdate_nide_1.12/scripting/FullUpdate.sp new file mode 100644 index 00000000..22d56dce --- /dev/null +++ b/FullUpdate_nide_1.12/scripting/FullUpdate.sp @@ -0,0 +1,218 @@ +#pragma semicolon 1 +#pragma newdecls required + +#include +#include +#include + +Handle g_hCBaseClient_UpdateAcknowledgedFramecount; +Handle g_hCBaseClient_OnRequestFullUpdate; +Handle g_hGetClient; + +Address m_nDeltaTick; +Address m_nForceWaitForTick; + +Address g_pBaseServer; + +int g_iLastFullUpdate[MAXPLAYERS + 1] = { 0, ... }; + +public Plugin myinfo = +{ + name = "FullUpdate", + author = "BotoX, PŠΣ™ SHUFEN, maxime1907", + description = "Serverside cl_fullupdate", + version = "1.3.0" +} + +public void OnPluginStart() +{ + GameData hGameData = new GameData("FullUpdate.games"); + if (hGameData == null) { + SetFailState("Couldn't load FullUpdate.games game config!"); + return; + } + +#if !defined GetClientIClient + g_pBaseServer = GameConfGetAddress(hGameData, "CBaseServer"); + if(g_pBaseServer == Address_Null) + { + SetFailState("Couldn't get BaseServer address!"); + return; + } + + StartPrepSDKCall(SDKCall_Raw); + if (!PrepSDKCall_SetFromConf(hGameData, SDKConf_Virtual, "CBaseServer::GetClient")) + { + delete hGameData; + SetFailState("PrepSDKCall_SetFromConf(hGameData, SDKConf_Virtual, \"CBaseServer::GetClient\" failed!"); + return; + } + PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); + g_hGetClient = EndPrepSDKCall(); +#endif + + if (GetEngineVersion() != Engine_CSGO) + { + // void CBaseClient::UpdateAcknowledgedFramecount() + StartPrepSDKCall(SDKCall_Raw); + + if(!PrepSDKCall_SetFromConf(hGameData, SDKConf_Virtual, "CBaseClient::UpdateAcknowledgedFramecount")) + { + delete hGameData; + SetFailState("PrepSDKCall_SetFromConf(hGameData, SDKConf_Virtual, \"CBaseClient::UpdateAcknowledgedFramecount\" failed!"); + return; + } + + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); + + g_hCBaseClient_UpdateAcknowledgedFramecount = EndPrepSDKCall(); + } + else + { + // void CBaseClient::OnRequestFullUpdate(char const *pchReason) + StartPrepSDKCall(SDKCall_Raw); + if (!PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CBaseClient::OnRequestFullUpdate")) { + delete hGameData; + SetFailState("PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, \"CBaseClient::OnRequestFullUpdate\") failed!"); + return; + } + PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); + g_hCBaseClient_OnRequestFullUpdate = EndPrepSDKCall(); + + int offset = hGameData.GetOffset("m_nDeltaTick"); + if (offset == -1) { + delete hGameData; + SetFailState("Cannot get offset CBaseClient->m_nDeltaTick"); + return; + } + m_nDeltaTick = view_as
(offset); + + offset = hGameData.GetOffset("m_nForceWaitForTick"); + if (offset == -1) { + delete hGameData; + SetFailState("Cannot get offset CBaseClient->m_nForceWaitForTick"); + return; + } + m_nForceWaitForTick = view_as
(offset); + } + + delete hGameData; + + RegConsoleCmd("sm_fullupdate", Command_FullUpdate); + AddCommandListener(Command_cl_fullupdate, "cl_fullupdate"); + RegConsoleCmd("fullupdate", Command_FullUpdate); +} + +public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) +{ + CreateNative("ClientFullUpdate", Native_FullUpdate); + RegPluginLibrary("FullUpdate"); + + return APLRes_Success; +} + +public void OnClientConnected(int client) +{ + g_iLastFullUpdate[client] = 0; +} + +bool FullUpdate(int client) +{ + if(g_iLastFullUpdate[client] + 1 > GetTime()) + return false; + + if (IsFakeClient(client)) + return false; + + if (GetEngineVersion() != Engine_CSGO) + { + Address pIClient = GetBaseClient(client); + if (!pIClient) + return false; + + SDKCall(g_hCBaseClient_UpdateAcknowledgedFramecount, pIClient, -1); + } + else + { + Address pIClient = GetBaseClient(client); + if (!pIClient) + return false; + + int iDeltaTick = LoadFromAddress(pIClient + m_nDeltaTick, NumberType_Int32); + int iForceWaitForTick = LoadFromAddress(pIClient + m_nForceWaitForTick, NumberType_Int32); + + if (iForceWaitForTick > 0) { + return false; + } + else { + if (iDeltaTick == -1) + return false; + + char sReason[128]; + FormatEx(sReason, sizeof(sReason), "%N called this function by 'sm_fullupdate' command", client); + + SDKCall(g_hCBaseClient_OnRequestFullUpdate, pIClient, sReason); + } + + // get acknowledged client frame + StoreToAddress(pIClient + m_nDeltaTick, -1, NumberType_Int32); + } + + g_iLastFullUpdate[client] = GetTime(); + return true; +} + +public int Native_FullUpdate(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + + if(client > MaxClients || client <= 0) + { + ThrowNativeError(SP_ERROR_NATIVE, "Client is not valid."); + return 0; + } + + if(!IsClientInGame(client)) + { + ThrowNativeError(SP_ERROR_NATIVE, "Client is not in-game."); + return 0; + } + + if(IsFakeClient(client)) + { + ThrowNativeError(SP_ERROR_NATIVE, "Client is fake-client."); + return 0; + } + + return FullUpdate(client); +} + +public Action Command_cl_fullupdate(int client, const char[] command, int args) +{ + Command_FullUpdate(client, -1); + return Plugin_Handled; +} + +public Action Command_FullUpdate(int client, int args) +{ + FullUpdate(client); + return Plugin_Handled; +} + +#if !defined GetClientIClient +stock Address GetClientIClient(int client) +{ + return SDKCall(g_hGetClient, g_pBaseServer, client-1); +} +#endif + +stock Address GetBaseClient(int client) +{ + Address pIClientTmp = GetClientIClient(client); + if(!pIClientTmp) + return Address_Null; + + // The IClient vtable is +4 from the IGameEventListener2 (CBaseClient) vtable due to multiple inheritance. + return pIClientTmp - view_as
(4); +} diff --git a/FullUpdate_nide_1.12/scripting/include/FullUpdate.inc b/FullUpdate_nide_1.12/scripting/include/FullUpdate.inc new file mode 100644 index 00000000..0b026c81 --- /dev/null +++ b/FullUpdate_nide_1.12/scripting/include/FullUpdate.inc @@ -0,0 +1,24 @@ +#if defined _FullUpdate_Included + #endinput +#endif +#define _FullUpdate_Included + +native bool ClientFullUpdate(int client); + +public SharedPlugin __pl_FullUpdate = +{ + name = "FullUpdate", + file = "FullUpdate.smx", +#if defined REQUIRE_PLUGIN + required = 1, +#else + required = 0, +#endif +}; + +#if !defined REQUIRE_PLUGIN +public __pl_FullUpdate_SetNTVOptional() +{ + MarkNativeAsOptional("ClientFullUpdate"); +} +#endif