Entity Commands - zeroKilo/GROBackendWV GitHub Wiki

Memory Layout

struct Command
{
  _DWORD pVMT;
  _DWORD dword4;
  _DWORD cmdID;
  _DWORD targetID;
  Data optionalData;
};

Networking

Format

Entity commands are sent inside of broadcast messages. They are first converted into a BitBuffer structure, which is then serialized into BM parameters and sent.

BitBuffer-to-BM-params conversion looks like this:

const char *__cdecl BitBuffer::WriteToBM(BitBuffer *this, int msgId, unsigned __int8 a3)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

  AIDLL::BM_ResetNetPushQueue(msgId, a3);
  begin = this->bufferBitSize;
  shift = this->bufferBitSize >> 3;
  if ( begin & 7 )
    ++shift;
  result = AIDLL::BM_PushNetParamI8(msgId, a3, 8 * shift - begin);// write buffer size
  if ( this->bufferByteSize )
    buff = this->buffer;
  else
    buff = 0;
  for ( ; shift; --shift )                      // write buffer
    result = AIDLL::BM_PushNetParamI8(msgId, a3, *buff++);
  return result;
}

Broadcast messages

Broadcast messages that store entity commands are:

  • 0x96 (standard entity commands)
  • 0xA7 (setting sequence casts)
  • 0x226 (some animation events for AI_EntityPlayer/AI_EntityHuman)

Command List

0x00 Invalid

0x01 HasHitATarget

0x02 ThrowGrenade

0x03 WillBeBump

0x04 MoveToPos

0x05 SetInvincible

0x06 EntityHeartBeat

0x07 Freeze

0x08 Teleport

0x09 DamageTaken

0x0A DamageGivenFeedback

0x0B PlayDead

0x0C PlayerRefillAmmo

0x0D PlayerRepAmmoInfo

0x0E PowerButtonStateChangePC

0x0F ForcePowerStatePC

0x10 PowerOverchargingStartedPC

0x11 PowerOverchargingStoppedPC

0x12 PowerOverchargedPC

0x13 PowerCoolingDownPC

0x14 BlackedOutPC

0x15 CreateBlackoutExplosion

0x16 EnemyDetectedWithHBS

0x17 SetADSFlags

0x18 SetADSConeAngle

0x19 SetADSExtraFOV

0x1A CancelBlitz

0x1B HeartBeat

0x1C FallingDamage

0x1D HasMissATarget

0x1E UpdateHealth

0x1F UpdateDefaultHealth

0x20 UpdateHealthState

0x21 BulletStartMarker

0x22 BulletEndMarker

0x23 ShowTotalDamage

0x24 Melee

0x25 PushbackEffect

0x26 LaserSightInfo

0x27 LaserWaypoint

0x28 Gesture

0x29 GestureAnimIdx

0x2A GestureAnimIdxStanceIdx - sets player's stance (prone/crouch/standing)

0x2B Cover

0x2C CoverEnter

0x2D CoverPeekSide

0x2E CoverPeekUp

0x2F AmmoLootAddedInServer

0x30 AmmoLootTakenConfirmedInServer

0x31 AmmoLootRemovedInMaster

0x32 ReloadInventory

0x33 AbstractPlayerChangeState

0x34 AbstractPlayerRequestSpawn

0x35 AbstractPlayerClientReady

0x36 FireAction

0x37 DecreaseAegisOwnerEnergy

0x38 Suicide

0x39 Kill

0x3A BlitzShieldHit

0x3B ReduceAmmoBoostClipByOne

0x3C ToggleAmmoBoost

0x3D CheatCommand

0x3E Count

Target List

0x00 All

0x01 Server

0x02 Master

0x03 Count

Processing

Only master or server entities can process commands. targetId defines who can process a command (from AI_Entity::ProcessCmdFromBuffer):

targetId = cmd->targetID;
    v6 = 0;
    v41 = -1;
    if ( !targetId )                            // targetId 0 - All
    {
      (this->pVMT->AI_EntityPlayer::ProcessCmd)(cmd);// target 0 processes cmds everytime
      v11 = cmd->pVMT->Command::WriteToBitBuffer;
      v39 = v35;
      v11(cmd, &bitBuff3);
      v9 = v35;
      bTarget0 = 1;
LABEL_18:
      v6 = v9 - v39;
      goto LABEL_19;
    }
    targetMinus1 = targetId - 1;
    if ( !targetMinus1 )                        // targetId 1 - Server
    {
      if ( this->serializationFlags & 2 )       // server
      {
        (this->pVMT->AI_EntityPlayer::ProcessCmd)(cmd);// target 1 server processes server cmds
      }
      else                                      // client
      {
        v10 = cmd->pVMT->Command::WriteToBitBuffer;
        v39 = v27;
        v10(cmd, &bitBuff1);
        v6 = v27 - v39;
        v41 = AI_NetworkManager::Get()->serverId;
        bClient = 1;
      }
      goto LABEL_19;
    }
    if ( targetMinus1 == 1 )                    // targetId 2 - Master
    {
      if ( this->serializationFlags & 1 )       // master
      {
        (this->pVMT->AI_EntityPlayer::ProcessCmd)(cmd);// target 2 master processes master cmds
        goto LABEL_19;
      }
      v8 = cmd->pVMT->Command::WriteToBitBuffer;// replica
      v39 = v31;
      v8(cmd, &bitBuff2);
      v9 = v31;
      v41 = this->playerStationID;
      bReplica = 1;
      goto LABEL_18;
    }