Skip to content

Instantly share code, notes, and snippets.

@Tobba
Last active October 30, 2017 12:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Tobba/f9893d48da6fd9137de4e5b3b93edde8 to your computer and use it in GitHub Desktop.
Save Tobba/f9893d48da6fd9137de4e5b3b93edde8 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdint.h>
#include <ISmmPlugin.h>
#include <igameevents.h>
#include <sh_vector.h>
#include <inetchannelinfo.h>
class RatePlugin : public ISmmPlugin, public IMetamodListener
{
public:
bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late);
bool Unload(char *error, size_t maxlen);
void SetRate(edict_t *pEntity, int rate);
void Hook_ClientSettingsChanged(edict_t *pEdict);
public:
const char *GetAuthor();
const char *GetName();
const char *GetDescription();
const char *GetURL();
const char *GetLicense();
const char *GetVersion();
const char *GetDate();
const char *GetLogTag();
};
RatePlugin g_RatePlugin;
PLUGIN_GLOBALVARS();
SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, char const *);
SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *);
IVEngineServer *engine = NULL;
ICvar *icvar = NULL;
IServerGameClients *gameclients = NULL;
CGlobalVars *gpGlobals = NULL;
int EntIndex(const edict_t *pEdict) {
return (int)(pEdict - gpGlobals->pEdicts);
}
ConVar net_forcerate("net_forcerate", "0", 0);
class BaseAccessor : public IConCommandBaseAccessor
{
public:
bool RegisterConCommandBase(ConCommandBase *pCommandBase) {
return META_REGCVAR(pCommandBase);
}
} s_BaseAccessor;
PLUGIN_EXPOSE(RatePlugin, g_RatePlugin);
bool RatePlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late) {
PLUGIN_SAVEVARS();
GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);
GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION);
GET_V_IFACE_ANY(GetServerFactory, gameclients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS);
gpGlobals = ismm->GetCGlobals();
SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, gameclients, this, &RatePlugin::Hook_ClientSettingsChanged, false);
#if SOURCE_ENGINE >= SE_ORANGEBOX
g_pCVar = icvar;
ConVar_Register(0, &s_BaseAccessor);
#else
ConCommandBaseMgr::OneTimeInit(&s_BaseAccessor);
#endif
return true;
}
bool RatePlugin::Unload(char * error, size_t maxlen) {
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, gameclients, this, &RatePlugin::Hook_ClientSettingsChanged, false);
return true;
}
class CNetChan;
void RatePlugin::SetRate(edict_t *pEntity, int rate) {
INetChannelInfo *chaninfo = engine->GetPlayerNetInfo(EntIndex(pEntity));
if (chaninfo) { // overwrite m_Rate
*(int*)((uint8_t*)chaninfo + 0x118) = rate; // same offset on win32 and linux
}
}
void RatePlugin::Hook_ClientSettingsChanged(edict_t *pEdict) {
int force_rate = net_forcerate.GetInt();
if (force_rate)
SetRate(pEdict, force_rate);
}
const char *RatePlugin::GetLicense() {
return "Apache";
}
const char *RatePlugin::GetVersion() {
return "1.0.0.0";
}
const char *RatePlugin::GetDate() {
return __DATE__;
}
const char *RatePlugin::GetLogTag() {
return "FORCERATE";
}
const char *RatePlugin::GetAuthor() {
return "Tobba";
}
const char *RatePlugin::GetDescription() {
return "Forces network rates beyond normal limits";
}
const char *RatePlugin::GetName() {
return "Forcerate";
}
const char *RatePlugin::GetURL() {
return "";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment