CMaster::SendHeartbeat
0x00202a90 · 2059 bytes · __thiscall
_ZN7CMaster13SendHeartbeatER8netadr_siP11CBaseServer
Decompiled
undefined (4 params)
/* CMaster::SendHeartbeat(netadr_s&, int, CBaseServer*) */
void __thiscall
CMaster::SendHeartbeat(CMaster *this,netadr_s *param_1,int param_2,CBaseServer *param_3)
{
int *piVar1;
char cVar2;
float *pfVar3;
char *pcVar4;
char *pcVar5;
int iVar6;
CMasterserver *pCVar7;
int iVar8;
int in_GS_OFFSET;
char local_94a [2];
int local_948;
int local_944;
int local_940;
double local_93c [3];
char local_924 [260];
char local_820 [2048];
int local_20;
local_20 = *(int *)(in_GS_OFFSET + 0x14);
if (((((*(int *)(sv_master_legacy_mode._28_4_ + 0x30) != 0) ||
(cVar2 = IsUsingMasterLegacyMode(), cVar2 != '\0')) &&
(cVar2 = (**(code **)(*(int *)param_3 + 0x68))(param_3), cVar2 != '\0')) &&
((cVar2 = CBaseServer::IsSinglePlayerGame(), cVar2 == '\0' &&
(cVar2 = CBaseServer::ShouldHideFromMasterServer(param_3), cVar2 == '\0')))) &&
(0 < *(int *)(this + 0x10))) {
iVar6 = 0;
iVar8 = 0;
do {
cVar2 = netadr_s::CompareAdr(param_1,(netadr_s *)(*(int *)(this + 4) + iVar6),false);
if (cVar2 != '\0') {
pCVar7 = (CMasterserver *)(iVar6 + *(int *)(this + 4));
if (((pCVar7 != (CMasterserver *)0x0) &&
(pfVar3 = (float *)GetHeartbeat(this,pCVar7,param_3), pfVar3 != (float *)0x0)) &&
(net_time - (double)*pfVar3 < (double)*(int *)(mm_heartbeat_timeout_legacy._28_4_ + 0x30)
)) {
*pfVar3 = 0.0;
pfVar3[1] = (float)param_2;
(**(code **)(*(int *)this + 8))(this);
_V_memset(SendHeartbeat(netadr_s&,int,CBaseServer*)::message,0,0x805);
CBaseServer::GetMasterServerPlayerCounts
((CBaseServer *)&sv,&local_948,&local_944,&local_940);
V_FileBase(com_gamedir,local_924,0x104);
iVar6 = (**(code **)(*(int *)param_3 + 0x74))(param_3);
_V_strcpy(local_94a,"l");
local_820[0] = '\0';
CBaseServer::UpdateGameType((CBaseServer *)&sv);
pcVar4 = (char *)va("%i",7);
Info_SetValueForKey(local_820,"protocol",pcVar4,0x800);
pcVar4 = (char *)va("%i",param_2);
Info_SetValueForKey(local_820,"challenge",pcVar4,0x800);
pcVar4 = (char *)va("%i",local_940);
Info_SetValueForKey(local_820,"bots",pcVar4,0x800);
if (*(int *)(tv_enable._28_4_ + 0x30) == 0) {
pcVar4 = (char *)va("%i",local_948);
Info_SetValueForKey(local_820,"players",pcVar4,0x800);
}
else {
iVar8 = 0;
if (0 < local_948) {
iVar8 = local_948 + -1;
}
pcVar4 = (char *)va("%i",iVar8);
Info_SetValueForKey(local_820,"players",pcVar4,0x800);
local_944 = local_944 + -1;
}
pcVar4 = (char *)va("%i",local_944);
Info_SetValueForKey(local_820,"max",pcVar4,0x800);
Info_SetValueForKey(local_820,"gamedir",local_924,0x800);
pcVar4 = (char *)(**(code **)(*(int *)param_3 + 0x3c))(param_3);
Info_SetValueForKey(local_820,"map",pcVar4,0x800);
pcVar4 = "1";
if (iVar6 == 0) {
pcVar4 = "0";
}
Info_SetValueForKey(local_820,"password",pcVar4,0x800);
Info_SetValueForKey(local_820,"os",local_94a,0x800);
iVar6 = Steam3Server();
pcVar4 = "0";
if (*(int *)(iVar6 + 0x98) == 1) {
pcVar4 = "1";
}
Info_SetValueForKey(local_820,"lan",pcVar4,0x800);
pcVar4 = "FCVAR_NEVER_AS_STRING";
if ((sv_region[0x15] & 0x10) == 0) {
pcVar4 = "";
if (*(char **)(sv_region._28_4_ + 0x24) != (char *)0x0) {
pcVar4 = *(char **)(sv_region._28_4_ + 0x24);
}
}
Info_SetValueForKey(local_820,"region",pcVar4,0x800);
pcVar5 = (char *)CBaseServer::GetGameType((CBaseServer *)&sv);
cVar2 = (**(code **)(*(int *)param_3 + 0x70))(param_3);
pcVar4 = "";
if (cVar2 == '\0') {
pcVar4 = pcVar5;
}
Info_SetValueForKey(local_820,"gametype",pcVar4,0x800);
cVar2 = (**(code **)(*(int *)param_3 + 0x70))(param_3);
if (cVar2 == '\0') {
cVar2 = (**(code **)(*(int *)param_3 + 0x60))(param_3);
pcVar4 = "d";
if (cVar2 == '\0') {
pcVar4 = "l";
}
Info_SetValueForKey(local_820,"type",pcVar4,0x800);
iVar6 = Steam3Server();
piVar1 = *(int **)(iVar6 + 4);
if ((piVar1 == (int *)0x0) ||
(cVar2 = (**(code **)(*piVar1 + 0x24))(piVar1), cVar2 == '\0')) {
pcVar4 = "0";
}
else {
pcVar4 = "1";
}
Info_SetValueForKey(local_820,"secure",pcVar4,0x800);
pcVar4 = (char *)GetHostVersionString();
Info_SetValueForKey(local_820,"version",pcVar4,0x800);
pcVar4 = (char *)GetHostProductString();
Info_SetValueForKey(local_820,"product",pcVar4,0x800);
}
else {
Info_SetValueForKey(local_820,"type","p",0x800);
Info_SetValueForKey(local_820,"secure","0",0x800);
Info_SetValueForKey(local_820,"version","1.0.0.0",0x800);
Info_SetValueForKey(local_820,"product","srctv",0x800);
}
iVar6 = getloadavg(local_93c,3);
if (iVar6 == 3) {
pcVar4 = (char *)va("%i",(int)(local_93c[0] * 16.0));
Info_SetValueForKey(local_820,"load",pcVar4,0x800);
}
V_snprintf(SendHeartbeat(netadr_s&,int,CBaseServer*)::message,0x805,"%c\n%s\n",0x30,
local_820);
iVar6 = _V_strlen(SendHeartbeat(netadr_s&,int,CBaseServer*)::message);
NET_SendPacket((INetChannel *)0x0,*(int *)(param_3 + 8),param_1,
SendHeartbeat(netadr_s&,int,CBaseServer*)::message,iVar6,(bf_write *)0x0,
false,0);
iVar6 = CBaseServer::GetGameData((CBaseServer *)&sv);
if ((iVar6 != 0) &&
(iVar6 = *(int *)(pCVar7 + 0xc),
iVar8 = CBaseServer::GetGameDataVersion((CBaseServer *)&sv), iVar6 != iVar8)) {
local_820[0] = '\0';
Info_SetValueForKeyInt(local_820,"protocol",7,0x800);
Info_SetValueForKeyInt(local_820,"challenge",param_2,0x800);
pcVar4 = "FCVAR_NEVER_AS_STRING";
if ((sv_region[0x15] & 0x10) == 0) {
pcVar4 = "";
if (*(char **)(sv_region._28_4_ + 0x24) != (char *)0x0) {
pcVar4 = *(char **)(sv_region._28_4_ + 0x24);
}
}
Info_SetValueForKey(local_820,"region",pcVar4,0x800);
pcVar4 = (char *)CBaseServer::GetGameData((CBaseServer *)&sv);
Info_SetValueForKey(local_820,"gamedata",pcVar4,0x800);
iVar6 = CBaseServer::GetGameDataVersion((CBaseServer *)&sv);
Info_SetValueForKeyInt(local_820,"gdversion",iVar6,0x800);
V_snprintf(SendHeartbeat(netadr_s&,int,CBaseServer*)::message,0x805,"%c\n%s\n",0x2b,
local_820);
iVar6 = _V_strlen(SendHeartbeat(netadr_s&,int,CBaseServer*)::message);
NET_SendPacket((INetChannel *)0x0,*(int *)(param_3 + 8),param_1,
SendHeartbeat(netadr_s&,int,CBaseServer*)::message,iVar6,(bf_write *)0x0,
false,0);
}
}
break;
}
iVar8 = iVar8 + 1;
iVar6 = iVar6 + 0x24;
} while (iVar8 < *(int *)(this + 0x10));
}
if (local_20 != *(int *)(in_GS_OFFSET + 0x14)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return;
}
SourceMod gamedata
paste intoaddons/sourcemod/gamedata/<your_plugin>.txt
used as the SourceMod key — change to fit your plugin's convention
SourceMod library name (server / engine / matchmaking)
Just a Signatures{} block, ready to drop into a gamedata
file. Wire it up in your plugin however you like - SDKCall, DHooks,
raw memory ops, or anything else.
Signatures + Functions block. The plugin uses
DHookCreateFromConf - DHooks reads return type, this-type,
calling convention, and argument types straight from the gamedata. Less
boilerplate in the plugin, types travel with the gamedata.
Gamedata KeyValues
DHooks plugin example
Type inference is best-effort from the C signature - sanity-check the DHooks types before shipping.