L L4D2node

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 into addons/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.



        

        

          

Type inference is best-effort from the C signature - sanity-check the DHooks types before shipping.

Return-type handling cheatsheet (DHookReturn)