Add A2S_Rules fix for CS:GO to CStrike extension. (#614)

* Add A2S_Rules fix for CS:GO to CStrike extension.

* Dont force set the cvar. Add checks before patching.

* Remove incorrect and useless check.

* Remove checking value as it is in the signature.

* Update build script changes to AMBuild 2.1 API to fix build.

* Fix bad check and ConVarRef being resolved too early.

* Whoops. This line is kinda important. Got nuked when refactoring.

* Remove unused variable.

* Updatet gamedata.

* Switch to "Addresses" gamedata lookup

* Add linux64 gamedata

* Fix mac build

Co-authored-by: Ruben Gonzalez <drifter01620@gmail.com>
Co-authored-by: Peace-Maker <peace-maker@wcfan.de>
This commit is contained in:
Nicholas Hastings 2021-03-08 17:42:32 -05:00 committed by GitHub
parent 6c2be9bdcc
commit ae485c3115
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 377 additions and 3 deletions

View File

@ -24,11 +24,46 @@ for sdk_name in ['css', 'csgo']:
if sdk_name not in SM.sdks:
continue
sdk = SM.sdks[sdk_name]
if sdk_name == 'csgo':
project.sources += ['rulesfix.cpp']
for cxx in builder.targets:
if not cxx.target.arch in sdk.platformSpec[cxx.target.platform]:
continue
cxx.defines += ['HAVE_STRING_H'];
SM.HL2ExtConfig(project, builder, cxx, 'game.cstrike.ext.' + sdk.ext, sdk)
cxx.defines += ['HAVE_STRING_H']
binary = SM.HL2ExtConfig(project, builder, cxx, 'game.cstrike.ext.' + sdk.ext, sdk)
if sdk_name == 'csgo':
compiler = binary.compiler
compiler.cxxincludes += [os.path.join(sdk.path, 'public', 'steam')]
compiler.defines += ['VERSION_SAFE_STEAM_API_INTERFACES']
library_name = ''
if cxx.target.platform == 'windows':
compiler.linkflags += [os.path.join(sdk.path, 'lib', 'public', 'steam_api.lib')]
elif cxx.target.platform == 'linux':
library_name = 'libsteam_api.so'
if cxx.target.arch == 'x86_64':
source_path = os.path.join(sdk.path, 'lib', 'linux64')
else:
source_path = os.path.join(sdk.path, 'lib', 'linux')
elif cxx.target.platform == 'mac':
library_name = 'libsteam_api.dylib'
if cxx.target.arch == 'x86_64':
source_path = os.path.join(sdk.path, 'lib', 'osx64')
else:
source_path = os.path.join(sdk.path, 'lib', 'mac')
if library_name:
source_path = os.path.join(source_path, library_name)
output_path = os.path.join(binary.localFolder, library_name)
# Ensure the output path exists.
builder.AddFolder(binary.localFolder)
output = builder.AddSymlink(source_path, output_path)
compiler.weaklinkdeps += [output]
compiler.linkflags[0:0] = [library_name]
SM.extensions += builder.Add(project)

View File

@ -36,6 +36,9 @@
#include "iplayerinfo.h"
#include "ISDKTools.h"
#include "forwards.h"
#if SOURCE_ENGINE == SE_CSGO
#include "rulesfix.h"
#endif
#include "util_cstrike.h"
/**
@ -88,6 +91,10 @@ bool CStrike::SDK_OnLoad(char *error, size_t maxlength, bool late)
playerhelpers->RegisterCommandTargetProcessor(this);
#if SOURCE_ENGINE == SE_CSGO
rulesfix.OnLoad();
#endif
CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf);
g_pHandleBuyForward = forwards->CreateForward("CS_OnBuyCommand", ET_Event, 2, NULL, Param_Cell, Param_String);
@ -110,6 +117,12 @@ bool CStrike::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool
GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);
gpGlobals = ismm->GetCGlobals();
#if SOURCE_ENGINE == SE_CSGO
ICvar *icvar;
GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION);
g_pCVar = icvar;
#endif
return true;
}
@ -153,6 +166,7 @@ void CStrike::SDK_OnUnload()
forwards->ReleaseForward(g_pCSWeaponDropForward);
#if SOURCE_ENGINE == SE_CSGO
rulesfix.OnUnload();
ClearHashMaps();
#endif
}

View File

@ -0,0 +1,232 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Counter-Strike:Source Extension
* Copyright (C) 2017 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "rulesfix.h"
#include "extension.h"
#include <sh_memory.h>
// Grab the convar ref
ConVar *host_rules_show = nullptr;
bool bPatched = false;
RulesFix rulesfix;
SH_DECL_HOOK1_void(IServerGameDLL, GameServerSteamAPIActivated, SH_NOATTRIB, 0, bool);
RulesFix::RulesFix() :
m_OnSteamServersConnected(this, &RulesFix::OnSteamServersConnected)
{
}
void SetMTUMax(int iValue)
{
static int iOriginalValue = -1;
static int *m_pMaxMTU = nullptr;
//If we never changed skip resetting
if (iOriginalValue == -1 && iValue == -1)
return;
if (m_pMaxMTU == nullptr)
{
if (!g_pGameConf->GetAddress("MaxMTU", (void **)&m_pMaxMTU))
{
g_pSM->LogMessage(myself, "[CStrike] Failed to locate NET_SendPacket signature.");
return;
}
SourceHook::SetMemAccess(m_pMaxMTU, sizeof(int), SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC);
iOriginalValue = *m_pMaxMTU;
}
if (iValue == -1)
*m_pMaxMTU = iOriginalValue;
else
*m_pMaxMTU = iValue;
}
void RulesFix::OnLoad()
{
host_rules_show = g_pCVar->FindVar("host_rules_show");
if (host_rules_show)
{
// Default to enabled. Explicit disable via cfg will still be obeyed.
host_rules_show->SetValue(true);
SetMTUMax(5000);
bPatched = true;
}
SH_ADD_HOOK(IServerGameDLL, GameServerSteamAPIActivated, gamedll, SH_MEMBER(this, &RulesFix::Hook_GameServerSteamAPIActivated), true);
}
void RulesFix::OnUnload()
{
SetMTUMax(-1);
SH_REMOVE_HOOK(IServerGameDLL, GameServerSteamAPIActivated, gamedll, SH_MEMBER(this, &RulesFix::Hook_GameServerSteamAPIActivated), true);
}
void NotifyAllCVars()
{
ICvar::Iterator iter(g_pCVar);
for (iter.SetFirst(); iter.IsValid(); iter.Next())
{
ConCommandBase *cmd = iter.Get();
if (!cmd->IsCommand() && cmd->IsFlagSet(FCVAR_NOTIFY))
{
rulesfix.OnNotifyConVarChanged((ConVar *)cmd);
}
}
}
void RulesFix::OnSteamServersConnected(SteamServersConnected_t *)
{
// The engine clears all after the Steam interfaces become available after they've been gone.
NotifyAllCVars();
}
static void OnConVarChanged(IConVar *var, const char *pOldValue, float flOldValue)
{
if (host_rules_show && var == host_rules_show)
{
if (host_rules_show->GetBool())
{
if (!bPatched)
{
SetMTUMax(5000);
bPatched = true;
NotifyAllCVars();
}
}
else
{
if (bPatched)
{
SetMTUMax(-1);
bPatched = false;
}
}
}
if (var->IsFlagSet(FCVAR_NOTIFY))
{
rulesfix.OnNotifyConVarChanged((ConVar *)var);
}
}
void RulesFix::OnNotifyConVarChanged(ConVar *pVar)
{
if (!bPatched)
return;
if (m_Steam.SteamMasterServerUpdater())
{
if (pVar->IsFlagSet(FCVAR_PROTECTED))
{
if (!pVar->GetString()[0])
{
m_Steam.SteamMasterServerUpdater()->SetKeyValue(pVar->GetName(), "0");
}
else
{
m_Steam.SteamMasterServerUpdater()->SetKeyValue(pVar->GetName(), "1");
}
}
else
{
m_Steam.SteamMasterServerUpdater()->SetKeyValue(pVar->GetName(), pVar->GetString());
}
}
}
void RulesFix::Hook_GameServerSteamAPIActivated(bool bActivated)
{
if (bActivated)
{
FixSteam();
m_Steam.Init();
g_pCVar->InstallGlobalChangeCallback(OnConVarChanged);
OnSteamServersConnected(nullptr);
}
else
{
g_pCVar->RemoveGlobalChangeCallback(OnConVarChanged);
m_Steam.Clear();
}
}
void RulesFix::FixSteam()
{
if (!g_pSteamClientGameServer)
{
void *(*pGSInternalCreateAddress)(const char *) = nullptr;
void *(*pInternalCreateAddress)(const char *) = nullptr;
// CS:GO currently uses the old name, but will use the new name when they update to a
// newer Steamworks SDK. Stay compatible.
const char *pGSInternalFuncName = "SteamGameServerInternal_CreateInterface";
const char *pInternalFuncName = "SteamInternal_CreateInterface";
ILibrary *pLibrary = libsys->OpenLibrary(
#if defined ( PLATFORM_WINDOWS )
"steam_api.dll"
#elif defined( PLATFORM_LINUX )
"libsteam_api.so"
#elif defined( PLATFORM_APPLE )
"libsteam_api.dylib"
#else
#error Unsupported platform
#endif
, nullptr, 0);
if (pLibrary != nullptr)
{
if (pGSInternalCreateAddress == nullptr)
{
pGSInternalCreateAddress = reinterpret_cast<void *(*)(const char *)>(pLibrary->GetSymbolAddress(pGSInternalFuncName));
}
if (pInternalCreateAddress == nullptr)
{
pInternalCreateAddress = reinterpret_cast<void *(*)(const char *)>(pLibrary->GetSymbolAddress(pInternalFuncName));
}
pLibrary->CloseLibrary();
}
if (pGSInternalCreateAddress != nullptr)
g_pSteamClientGameServer = reinterpret_cast<ISteamClient *>((*pGSInternalCreateAddress)(STEAMCLIENT_INTERFACE_VERSION));
if (g_pSteamClientGameServer == nullptr && pInternalCreateAddress != nullptr)
g_pSteamClientGameServer = reinterpret_cast<ISteamClient *>((*pInternalCreateAddress)(STEAMCLIENT_INTERFACE_VERSION));
}
}

View File

@ -0,0 +1,52 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Counter-Strike:Source Extension
* Copyright (C) 2017 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#pragma once
#include <steam_gameserver.h>
class ConVar;
class RulesFix
{
public:
RulesFix();
void OnLoad();
void OnUnload();
void OnNotifyConVarChanged(ConVar *pVar);
void Hook_GameServerSteamAPIActivated(bool bActivated);
private:
void FixSteam();
private:
CSteamGameServerAPIContext m_Steam;
STEAM_GAMESERVER_CALLBACK(RulesFix, OnSteamServersConnected, SteamServersConnected_t, m_OnSteamServersConnected);
};
extern RulesFix rulesfix;

View File

@ -68,7 +68,9 @@
#define SMEXT_ENABLE_GAMEHELPERS
#define SMEXT_ENABLE_TIMERSYS
//#define SMEXT_ENABLE_THREADER
//#define SMEXT_ENABLE_LIBSYS
#if SOURCE_ENGINE == SE_CSGO
#define SMEXT_ENABLE_LIBSYS
#endif
#define SMEXT_ENABLE_USERMSGS
#define SMEXT_ENABLE_PLUGINSYS

View File

@ -264,4 +264,43 @@
}
}
}
"#default"
{
"Addresses"
{
// Offset from NET_SendPacket sig to MTU
"MaxMTU"
{
"windows"
{
"signature" "NET_SendPacket"
"offset" "6"
}
"linux"
{
"signature" "NET_SendPacket"
"offset" "5"
}
"linux64"
{
"signature" "NET_SendPacket"
"offset" "4"
}
}
}
"Signatures"
{
// This isn't the start of the function, but closer to where we want to patch, including the exact bytes we will replace
"NET_SendPacket"
{
"library" "engine"
// "[NET] Cannot send %d-byte packet to %s. MTU is %u. %02x %02x %02x %02x %02x\n"
"windows" "\x89\x4C\x24\x14\x81\xFF\xB0\x04\x00\x00\x7E"
// _Z14NET_SendPacketP11INetChanneliRK10ns_addressPKhiP8bf_writebj
"linux" "\x8B\x7D\x10\x81\xFE\xB0\x04\x00\x00\x0F"
"linux64" "\x31\xC0\x81\xF9\xB0\x04\x00\x00\x0F"
}
}
}
}