Processing Game Messages
Now that the game messages have made their way into the message queue, the next
step is to remove the messages at each frame and process them. To keep things
running quickly, only 64 messages at a time are processed (as defined by the
MESSAGE_PER_FRAME macro in the server source code).
Message processing takes place
within the cApp::process_queued_msg function:
void cApp::process_queue_msg()
{
long count = 0;
// pull out messages to process
while(count != MESSAGES_PER_FRAME && m_msg_head != m_msg_tail)
{
// get pointer to 'tail' message
EnterCriticalSection(&m_msg_cs);
sMsg* msg = &m_msgs[m_msg_tail];
LeaveCriticalSection(&m_msg_cs);
// process a single message based on type
switch(msg->header.type)
{
case MSG_SEND_PLAYER_INFO:
send_player_info(msg, msg->header.player_id);
break;
case MSG_CREATE_PLAYER:
add_player(msg);
break;
case MSG_DESTROY_PLAYER:
remove_player(msg);
break;
case MSG_STATE_CHANGE:
player_state_change(msg);
break;
}
count++; // increase processed message count
// goto next message in list
EnterCriticalSection(&m_msg_cs);
m_msg_tail = (m_msg_tail + 1) % MAX_MESSAGES;
LeaveCriticalSection(&m_msg_cs);
}
}
As
process_queue_msg iterates through the
next 64 messages, it calls upon a separate
set of functions to handle the various game messages. Those message-handling
functions are described in the following sections.
cApp::add_player
Let’s face it—your game is
going to be cool, and before long you’ll have players joining
the game left and right. When a player joins the game (or at least tries to
join), a player
message is added to the queue, and when that message is processed, the
add_player function
is called to find room for the player. If no room exists, that player is
disconnected.
bool cApp::add_player(const sMsg* msg)
{
DPNID player_id = msg->header.player_id;
DWORD size = 0;
DPN_PLAYER_INFO* player_info = NULL;
// get the player information
HRESULT hr = m_server.get_server()->GetClientInfo(player_id, player_info, &size, 0);
if(FAILED(hr) && hr != DPNERR_BUFFERTOOSMALL)
return false;
// allocate player data buffer and try again
player_info = (DPN_PLAYER_INFO*) new byte[size];
if(player_info == NULL)
return false;
ZeroMemory(player_info, size);
player_info->dwSize = sizeof(DPN_PLAYER_INFO);
if(FAILED(m_server.get_server()->GetClientInfo(player_id, player_info, &size, 0)))
{
delete[] player_info;
return false;
}
// make sure not already in list
for(long i = 0; i < MAX_PLAYERS; i++)
{
if(m_players[i].player_id == player_id && m_players[i].connected)
{
delete[] player_info;
m_server.disconnect_player(player_id);
return false;
}
}
// search for an empty slot to put player
for(long i = 0; i < MAX_PLAYERS; i++)
{
if(! m_players[i].connected)
{
m_players[i].connected = true;
m_players[i].player_id = player_id;
m_players[i].x_pos = 0.0f;
m_players[i].y_pos = 0.0f;
m_players[i].z_pos = 0.0f;
m_players[i].direction = 0.0f;
m_players[i].speed = 512.0f;
m_players[i].last_state = STATE_IDLE;
m_players[i].latency = 0;
wcstombs(m_players[i].name, player_info->pwszName, sizeof(m_players[i].name));
// send add player information to all players in area
sCreatePlayerMsg create_msg;
create_msg.header.type = MSG_CREATE_PLAYER;
create_msg.header.size = sizeof(sCreatePlayerMsg);
create_msg.header.player_id = player_id;
create_msg.x_pos = m_players[i].x_pos;
create_msg.y_pos = m_players[i].y_pos;
create_msg.z_pos = m_players[i].z_pos;
create_msg.direction = m_players[i].direction;
send_network_msg(&create_msg, DPNSEND_NOLOOPBACK, ALL_CLIENT_PLAYERS);
m_connected_player_num++;
list_players();
delete[] player_info;
return true;
}
}
delete[] player_info;
m_server.disconnect_player(player_id);
return false;
}
///////////////////////////////////////////////////////////////////////////////////////
void cApp::list_players()
{
// clear player list
reset_listbox(m_controls[CONTROL_PLAYER_LIST]);
// count alll players and add names to list
for(long i = 0; i < MAX_PLAYERS; i++)
{
if(m_players[i].connected)
add_string_to_listbox(m_controls[CONTROL_PLAYER_LIST], m_players[i].name);
}
// display player count
if(m_connected_player_num == 0)
SetWindowText(m_controls[CONTROL_PLAYER_NUM], "No Connected Players");
else
{
char text[256];
sprintf(text, "%lu players connected", m_connected_player_num);
SetWindowText(m_controls[CONTROL_PLAYER_NUM], text);
}
}