Skip to main content

Overview

The c_client_state class manages the client’s connection state, network information, and synchronization data with the game server. It contains critical data for networking, prediction, and command processing.
This class is essential for understanding client-server synchronization, command acknowledgment, and tick-based game simulation.

Class Definition

Location: game/sdk/classes/c_client_state.h:10
class c_client_state
{
public:
    PAD(0x9C);
    i_net_channel_info* net_channel;
    int challenge_nr;
    PAD(0x64);
    int signon_state;
    PAD(0x8);
    float next_command_time;
    int server_count;
    int current_sequence;
    PAD(0x54);
    int delta_tick;
    bool paused;
    PAD(0x7);
    int view_entity;
    int player_slot;
    char level_name[MAX_PATH];
    char level_name_short[80];
    char map_group_name[80];
    char last_level_name_short[80];
    PAD(0xC);
    int max_clients;
    PAD(0x498C);
    float last_server_tick_time;
    bool in_simulation;
    PAD(0x3);
    int old_tick_count;
    float tick_remainder;
    float frame_time;
    int last_outgoing_command;
    int choked_commands;
    int last_command_ack;
    int command_ack;
    int sound_sequence;
    PAD(0x50);
    math::vec3 view_point;
    PAD(0xD0);
    c_event_info* events;
};

Members

Network Connection

net_channel
i_net_channel_info*
Pointer to the network channel interface. Provides latency, packet loss, and flow statistics.
challenge_nr
int
Challenge number for server authentication.
signon_state
int
Current connection state:
  • 0: SIGNONSTATE_NONE
  • 1: SIGNONSTATE_CHALLENGE
  • 2: SIGNONSTATE_CONNECTED
  • 3: SIGNONSTATE_NEW
  • 4: SIGNONSTATE_PRESPAWN
  • 5: SIGNONSTATE_SPAWN
  • 6: SIGNONSTATE_FULL (fully connected)

Server Information

server_count
int
Server session identifier. Changes on map load or server restart.
max_clients
int
Maximum number of clients allowed on the server.
view_entity
int
Entity index of the current view entity (usually the local player).
player_slot
int
Local player’s slot index (0-based).

Map Information

level_name
char[MAX_PATH]
Full path to the current map (e.g., “maps/de_dust2.bsp”).
level_name_short
char[80]
Short map name without path or extension (e.g., “de_dust2”).
map_group_name
char[80]
Map group identifier for matchmaking.
last_level_name_short
char[80]
Previous map’s short name.

Timing & Simulation

next_command_time
float
Time when the next command should be sent to the server.
last_server_tick_time
float
Timestamp of the last server tick received.
frame_time
float
Duration of the current frame in seconds.
tick_remainder
float
Fractional tick time carried over between frames.
in_simulation
bool
True when the client is currently running simulation/prediction.
paused
bool
True when the game is paused.
old_tick_count
int
Previous tick count for delta calculations.

Command Processing

current_sequence
int
Current command sequence number being processed.
last_outgoing_command
int
Sequence number of the last command sent to the server.
choked_commands
int
Number of commands queued but not yet sent (used for lag compensation).
last_command_ack
int
Last command sequence acknowledged by the server.
command_ack
int
Most recent command acknowledged by the server.
delta_tick
int
Tick difference for delta compression.

Events & View

sound_sequence
int
Sound event sequence number.
view_point
math::vec3
Current view position in world space.
events
c_event_info*
Pointer to client-side event information array.

Usage Examples

Accessing Client State

// Get client state from engine
auto client_state = **reinterpret_cast<c_client_state***>(
    pattern::find("engine.dll", "A1 ? ? ? ? 33 D2 6A 00 6A 00 33 C9 89 B0") + 1
);

if (client_state)
{
    // Access client state members
    int ping = client_state->net_channel->get_avg_latency(FLOW_OUTGOING);
    bool connected = client_state->signon_state == SIGNONSTATE_FULL;
}

Network Statistics

float get_ping(c_client_state* client_state)
{
    if (!client_state || !client_state->net_channel)
        return 0.0f;

    // Get average latency in seconds
    float latency = client_state->net_channel->get_avg_latency(FLOW_OUTGOING);
    
    // Convert to milliseconds
    return latency * 1000.0f;
}

Command Timing

// Check if we should send a new command
bool should_send_command(c_client_state* client_state)
{
    if (!client_state)
        return false;

    // Check if enough time has passed since last command
    float current_time = g_globals->curtime;
    return current_time >= client_state->next_command_time;
}

// Calculate command choke for lag compensation
int get_choke_amount(c_client_state* client_state)
{
    if (!client_state)
        return 0;

    // Number of commands waiting to be sent
    return client_state->choked_commands;
}

Map Detection

bool is_on_map(c_client_state* client_state, const char* map_name)
{
    if (!client_state)
        return false;

    return strcmp(client_state->level_name_short, map_name) == 0;
}

void on_map_load(c_client_state* client_state)
{
    if (!client_state)
        return;

    console->info("Loaded map: %s", client_state->level_name_short);
    console->info("Max players: %d", client_state->max_clients);
    console->info("Player slot: %d", client_state->player_slot);
}

Connection State Monitoring

const char* get_signon_state_name(int state)
{
    switch (state)
    {
        case 0: return "NONE";
        case 1: return "CHALLENGE";
        case 2: return "CONNECTED";
        case 3: return "NEW";
        case 4: return "PRESPAWN";
        case 5: return "SPAWN";
        case 6: return "FULL";
        default: return "UNKNOWN";
    }
}

void monitor_connection(c_client_state* client_state)
{
    static int last_signon_state = -1;
    
    if (!client_state)
        return;

    if (client_state->signon_state != last_signon_state)
    {
        console->info("Connection state changed: %s -> %s",
            get_signon_state_name(last_signon_state),
            get_signon_state_name(client_state->signon_state));
        
        last_signon_state = client_state->signon_state;
    }
}

Prediction Timing

void setup_prediction_timing(c_client_state* client_state)
{
    if (!client_state || !client_state->in_simulation)
        return;

    // Store original values
    float old_curtime = g_globals->curtime;
    float old_frametime = g_globals->frametime;
    int old_tickcount = g_globals->tickcount;

    // Set prediction timing
    g_globals->curtime = client_state->last_server_tick_time;
    g_globals->frametime = client_state->frame_time;
    g_globals->tickcount = client_state->old_tick_count + 1;

    // Run prediction...

    // Restore original values
    g_globals->curtime = old_curtime;
    g_globals->frametime = old_frametime;
    g_globals->tickcount = old_tickcount;
}
  • c_user_cmd - User commands processed using client state timing
  • c_input - Input manager that creates commands based on client state
  • Game Interfaces - Other game interfaces including network channel

Build docs developers (and LLMs) love