One of the issues I ran accross when first implementing Jailbreak was finding that even though players had a flag in the CHL2MP_Player class to mark them as in or out of jail and it was setup as a network var, this wasn’t always being sent down to all clients.

I later discovered this was due to the PVS (Potentially Visible Set). The PVS defines what you can currently see, and in order to conserve bandwidth, only data for players within that area is transmitted to you. This means that once another player is outside your current PVS, the bulk of their data is no longer kept up to date, including items such as position, velocity and so on.

If you have some data that should always be updated to all players, such as score, health, or in our case the jailed flag, you can make use of the CPlayerResource class which is designed for this very purpose.

The rest of this post will walk you through adding a new item of data to this class.

Server

We’ll start on the server side in player_resource.h, begin by finding

1
CNetworkArray( int, m_iHealth, MAX_PLAYERS+1 );

and adding the following below it:

1
CNetworkArray( int, m_bInJail, MAX_PLAYERS+1 );

This defines our new data item. Next we need to add this to the send table so that it gets transmitted to the client, so in player_resource.cpp find:

1
SendPropArray3( SENDINFO_ARRAY3(m_iHealth), SendPropInt( SENDINFO_ARRAY(m_iHealth), 10, SPROP_UNSIGNED ) ),

and add the following below it to make sure it gets transmitted:

1
SendPropArray3( SENDINFO_ARRAY3(m_bInJail), SendPropInt( SENDINFO_ARRAY(m_bInJail), 1, SPROP_UNSIGNED ) ),

Finally for the server side we just need to update the new array so that it gets transmitted, so in the same file find the UpdatePlayerData function, and underneath where m_iHealth is set, add the following:

1
2
3
4
5
6
//JB: set the jail state & perks
CHL2MP_Player* hl2Player = ToHL2MPPlayer(pPlayer);
if(hl2Player)
{
    m_bInJail.Set(i, hl2Player->IsInJail());
}

And add an include to the top of the file for hl2mp_player.h. This simply uses a function that I already added to CHL2MP_Player to determine if the player is in jail and sets the value accordingly.

It’s arguable whether this is the best approach as it could be better to subclass CPlayerResource and add things specific to our mod there, but this will do for now.

Client

Moving on to the client, we need to set it up to receive the new data we just added, so in c_playerresource.h find:

1
int m_iHealth[MAX_PLAYERS+1];

and add below it a variable to hold our new field:

1
bool m_bInJail[MAX_PLAYERS+1];

Whilst we’re here, we can also add a declaration for an accessor to get access to the new information, so in the public section of the class add:

1
virtual bool    IsInJail(int index);

Moving on to c_playerresource.cpp, first find:

1
RecvPropArray3( RECVINFO_ARRAY(m_iHealth), RecvPropInt( RECVINFO(m_iHealth[0]))),

and add:

1
RecvPropArray3( RECVINFO_ARRAY(m_bInJail), RecvPropInt( RECVINFO(m_bInJail[0]))),

and after:

1
DEFINE_PRED_ARRAY( m_iHealth, FIELD_INTEGER, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ),

add:

1
DEFINE_PRED_ARRAY( m_bInJail, FIELD_BOOLEAN, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ),

This sets up the receive table and prediction data to make sure the new field is kept up to date.

Now, in the constructor add the following to initialise the new field:

1
memset( m_bInJail, 0, sizeof( m_bInJail ) );

And finally add a definition for our accessor that we defined earlier to the end of the file:

1
2
3
4
bool C_PlayerResource::IsInJail(int index)
{
    return m_bInJail[index];
}

Summary

There you have it, the new field will now be kept up to date on all clients and is accesible through the player resource class:

1
g_PR->IsInJail( playerIndex )

One word of warning, as this structure is kept up to date to all clients, be sure not to add too much information to it as it could badly affect network performance.

You should carefully consider whether the data really needs to be kept up to date on every client, and if not, make use of one of the other methods of transferring data to the client.

2 Responses to “Keeping Players Updated With CPlayerResource”

  1. DuckSauce Says:

    It’s also worth noting that this is pretty much the ONLY way to add data to the scoreboard. I had to do this way back to show player lives on the scoreboard.

  2. Holymac Says:

    Hey Dogmeat, nice tutorial I am going to use this for my attempt at a CTF Gamemode for moddb.com/mods/jmod1 as I guess all players need to know whether the flag is capped or not. Please email me or something about this (crysisking_ownage922@hotmail.com) because if it’s not needed that would help. I am not really sure.

Leave a Reply