mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-17 13:00:25 +02:00
Halo plays in lockstep: every machine simulates every player from the inputs the host hands out each tick. The VR port's simulation read the headset directly (the weapon's aim and muzzle, the head's look, a seated gun's eyes, the grenade held and thrown by hand, a swing's melee strength), which only the headset's machine knows. These now make a VR block beside each action (game/players.h, in whole numbers so every machine, the host included, works with the same values; positions as offsets from the unit's camera), sampled where the input is built (player_control.c), carried by the queues beside the actions, and by the game update messages as a list of the players who have one (system link message version 3). The simulation reads the block, on every native build: a desktop machine simulates a VR player as the headset does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1575 lines
43 KiB
C
1575 lines
43 KiB
C
/*
|
|
NETWORK_CLIENT_MESSAGE_HANDLER.C
|
|
|
|
symbols in this file:
|
|
00116AB0 00b0:
|
|
_network_game_client_handle_message_server_game_advertise (0000)
|
|
00116B60 0090:
|
|
_network_game_client_handle_message_server_pong (0000)
|
|
00116BF0 00a0:
|
|
_network_game_client_handle_message_server_machine_accepted (0000)
|
|
00116C90 00a0:
|
|
_network_game_client_handle_message_server_machine_rejected (0000)
|
|
00116D30 0130:
|
|
_network_game_client_handle_message_server_game_settings_update (0000)
|
|
00116E60 0100:
|
|
_network_game_client_handle_message_server_pregame_countdown (0000)
|
|
00116F60 00e0:
|
|
_network_game_client_handle_message_server_pregame_keep_alive (0000)
|
|
00117040 00e0:
|
|
_network_game_client_handle_message_server_postgame_keep_alive (0000)
|
|
00117120 00d0:
|
|
_network_game_client_handle_message_server_begin_game (0000)
|
|
001171F0 00b0:
|
|
_network_game_client_handle_message_server_graceful_game_exit_pregame (0000)
|
|
001172A0 00c0:
|
|
_network_game_client_handle_message_server_game_update (0000)
|
|
00117360 00c0:
|
|
_network_game_client_handle_message_server_add_player_ingame (0000)
|
|
00117420 00c0:
|
|
_network_game_client_handle_message_server_remove_player_ingame (0000)
|
|
001174E0 00a0:
|
|
_network_game_client_handle_message_server_game_over (0000)
|
|
00117580 00c0:
|
|
_network_game_client_handle_message_server_switch_to_pregame (0000)
|
|
00117640 00b0:
|
|
_network_game_client_handle_message_server_graceful_game_exit_postgame (0000)
|
|
001176F0 0440:
|
|
_network_game_client_handle_message (0000)
|
|
00281928 0045:
|
|
??_C@_0EF@JEKJBGGG@ignoring?5an?5advertised?5game?5beca@ (0000)
|
|
00281970 0038:
|
|
??_C@_0DI@DKMFJKNC@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
002819A8 003e:
|
|
??_C@_0DO@KGHCHMKG@ignoring?5a?5pong?5message?5because?5@ (0000)
|
|
002819E8 002e:
|
|
??_C@_0CO@MNCKPDII@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00281A18 005e:
|
|
??_C@_0FO@MDHPOCDK@ignoring?5a?5message_server_machin@ (0000)
|
|
00281A78 003a:
|
|
??_C@_0DK@OHJLEEJA@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00281AB8 005e:
|
|
??_C@_0FO@KFHDMLDG@ignoring?5a?5message_server_machin@ (0000)
|
|
00281B18 003a:
|
|
??_C@_0DK@NPFONKEC@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00281B58 0048:
|
|
??_C@_0EI@MBCELKHN@ignoring?5a?5message_server_game_s@ (0000)
|
|
00281BA0 0055:
|
|
??_C@_0FF@MOCCMIII@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
00281BF8 003e:
|
|
??_C@_0DO@CFANMJHG@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00281C38 0033:
|
|
??_C@_0DD@BCJHCHJP@network_game_client_game_setting@ (0000)
|
|
00281C6C 0017:
|
|
??_C@_0BH@BJKENKMM@source_address?5?$CB?$DN?5NULL?$AA@ (0000)
|
|
00281C84 003b:
|
|
??_C@_0DL@LEGDIILJ@c?3?2halo?2SOURCE?2networking?2networ@ (0000)
|
|
00281CC0 0045:
|
|
??_C@_0EF@KFKEPLOD@ignoring?5a?5message_server_pregam@ (0000)
|
|
00281D08 0052:
|
|
??_C@_0FC@JHBFLLPP@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
00281D5C 003b:
|
|
??_C@_0DL@LHJKBMIA@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00281D98 0046:
|
|
??_C@_0EG@IAKPIALP@ignoring?5a?5message_server_pregam@ (0000)
|
|
00281DE0 0053:
|
|
??_C@_0FD@ECPEPJNC@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
00281E34 003c:
|
|
??_C@_0DM@GMAKBHHC@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00281E70 0047:
|
|
??_C@_0EH@IABGEGJI@ignoring?5a?5message_server_postga@ (0000)
|
|
00281EB8 0055:
|
|
??_C@_0FF@PKNMLFIC@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
00281F10 003d:
|
|
??_C@_0DN@BIGGNOLB@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00281F50 0046:
|
|
??_C@_0EG@KGCDAEPA@ignoring?5a?5message_server_begin_@ (0000)
|
|
00281F98 004c:
|
|
??_C@_0EM@LHDJIHFO@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
00281FE4 0034:
|
|
??_C@_0DE@OPOJGBIB@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00282018 002e:
|
|
??_C@_0CO@IDLMDGAP@network_game_client_game_has_sta@ (0000)
|
|
00282048 0056:
|
|
??_C@_0FG@NGBIOKLC@ignoring?5a?5message_server_gracef@ (0000)
|
|
002820A0 005c:
|
|
??_C@_0FM@DIGPPEBG@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
00282100 0044:
|
|
??_C@_0EE@ECCKOGDL@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00282148 0047:
|
|
??_C@_0EH@MEBMJMKF@ignoring?5a?5message_server_game_u@ (0000)
|
|
00282190 004a:
|
|
??_C@_0EK@HLKFMGH@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
002821DC 0035:
|
|
??_C@_0DF@IIILBLL@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00282214 0030:
|
|
??_C@_0DA@NKCCMGPH@network_game_client_handle_game_@ (0000)
|
|
00282248 004d:
|
|
??_C@_0EN@FKBHABAC@ignoring?5a?5message_server_add_pl@ (0000)
|
|
00282298 0050:
|
|
??_C@_0FA@NACEIJGI@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
002822E8 003b:
|
|
??_C@_0DL@FGDEKFMJ@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00282324 0030:
|
|
??_C@_0DA@ICGCINCO@network_game_client_add_player_t@ (0000)
|
|
00282358 0050:
|
|
??_C@_0FA@IBHOBKAI@ignoring?5a?5message_server_remove@ (0000)
|
|
002823A8 0053:
|
|
??_C@_0FD@OLBMGIKB@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
002823FC 003e:
|
|
??_C@_0DO@GODOOHMN@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
0028243C 002b:
|
|
??_C@_0CL@NBDIBGCC@network_game_client_remove_playe@ (0000)
|
|
00282468 0045:
|
|
??_C@_0EF@DDKCBEG@ignoring?5a?5message_server_game_o@ (0000)
|
|
002824B0 0048:
|
|
??_C@_0EI@BGOBBEDF@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
002824F8 0043:
|
|
??_C@_0ED@LKOOJPFP@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00282540 004d:
|
|
??_C@_0EN@IMILJCHD@ignoring?5a?5message_server_switch@ (0000)
|
|
00282590 0055:
|
|
??_C@_0FF@LPOEGCEN@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
002825E8 002f:
|
|
??_C@_0CP@KPJNEAOB@network_game_client_switch_to_pr@ (0000)
|
|
00282618 003b:
|
|
??_C@_0DL@DIFCCPGE@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00282658 0057:
|
|
??_C@_0FH@MFCGNFNN@ignoring?5a?5message_server_gracef@ (0000)
|
|
002826B0 005f:
|
|
??_C@_0FP@KCFNLJEN@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
00282710 0054:
|
|
??_C@_0FE@LHBDFEJN@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00282764 003a:
|
|
??_C@_0DK@BPCDJE@client?5received?5a?5malformed?1dama@ (0000)
|
|
002827A0 0039:
|
|
??_C@_0DJ@ILEOJBLB@client?5received?5low?9level?5error?5@ (0000)
|
|
002827DC 0038:
|
|
??_C@_0DI@MKDILEED@client?5received?5a?5bad?5message?5ty@ (0000)
|
|
00282814 0037:
|
|
??_C@_0DH@DOCAAFEI@unknown?5packet?5type?5received?5fro@ (0000)
|
|
00282850 004f:
|
|
??_C@_0EP@PCPAJAJP@network_game_client_handle_messa@ (0000)
|
|
002828A0 0045:
|
|
??_C@_0EF@GBNHBHMJ@network_game_client_handle_messa@ (0000)
|
|
002828E8 003d:
|
|
??_C@_0DN@ODDAPCAH@network_game_client_handle_messa@ (0000)
|
|
00282928 0048:
|
|
??_C@_0EI@EDFDAGJM@network_game_client_handle_messa@ (0000)
|
|
00282970 0045:
|
|
??_C@_0EF@HHBDNBDF@network_game_client_handle_messa@ (0000)
|
|
002829B8 003f:
|
|
??_C@_0DP@KPKJEOKA@network_game_client_handle_messa@ (0000)
|
|
002829F8 004e:
|
|
??_C@_0EO@BMIPGLHI@network_game_client_handle_messa@ (0000)
|
|
00282A48 003e:
|
|
??_C@_0DO@CAKHJPLK@network_game_client_handle_messa@ (0000)
|
|
00282A88 0047:
|
|
??_C@_0EH@IEIFIIEF@network_game_client_handle_messa@ (0000)
|
|
00282AD0 0046:
|
|
??_C@_0EG@NOAJAKOF@network_game_client_handle_messa@ (0000)
|
|
00282B18 0045:
|
|
??_C@_0EF@OEBFMPPP@network_game_client_handle_messa@ (0000)
|
|
00282B60 0048:
|
|
??_C@_0EI@JILEDHBD@network_game_client_handle_messa@ (0000)
|
|
00282BA8 0044:
|
|
??_C@_0EE@JFCCKCCI@network_game_client_handle_messa@ (0000)
|
|
00282BF0 0044:
|
|
??_C@_0EE@DBJLIDDD@network_game_client_handle_messa@ (0000)
|
|
00282C34 0038:
|
|
??_C@_0DI@MEGCHKLI@network_game_client_handle_messa@ (0000)
|
|
00282C70 0042:
|
|
??_C@_0EC@DCBNODDF@network_game_client_handle_messa@ (0000)
|
|
00282CB4 0037:
|
|
??_C@_0DH@OBKILCJH@client?5received?5a?5message?5with?5a@ (0000)
|
|
00282CEC 0032:
|
|
??_C@_0DC@OIBJKL@client?5received?5client?5message?5w@ (0000)
|
|
00282D20 0054:
|
|
??_C@_0FE@FDBDJMOG@client?5?$CG?$CG?5message?5?$CG?$CG?5?$CImessage_si@ (0000)
|
|
*/
|
|
|
|
/* ---------- headers */
|
|
|
|
#include "cseries.h"
|
|
#include "bungie_net/common/message_header.h"
|
|
#include "bungie_net/network/transport.h"
|
|
#include "bungie_net/network/transport_endpoint_winsock.h"
|
|
#include "game/game_engine.h"
|
|
#include "game/players.h"
|
|
#include "networking/network_client_manager.h"
|
|
#include "networking/network_client_message_handler.h"
|
|
#include "networking/network_messages.h"
|
|
|
|
/* ---------- constants */
|
|
|
|
#define NETWORK_CLIENT_MESSAGE_HANDLER_FILE "c:\\halo\\SOURCE\\networking\\network_client_message_handler.c"
|
|
|
|
enum
|
|
{
|
|
#ifdef HALO_LINUX
|
|
/* the native builds' protocol and session limits
|
|
(port/linux/include/halo_port_limits.h) */
|
|
NETWORK_GAME_MESSAGE_VERSION = HALO_PORT_NETWORK_GAME_MESSAGE_VERSION,
|
|
TRANSPORT_NONCE_LENGTH = 8,
|
|
TRANSPORT_ERROR_MESSAGE_TEXT_LENGTH = 0x80,
|
|
MAXIMUM_NETWORK_MACHINE_COUNT = HALO_PORT_MAXIMUM_NETWORK_MACHINES,
|
|
NETWORK_GAME_NAME_LENGTH = 16,
|
|
MAXIMUM_NUMBER_OF_PLAYERS = HALO_PORT_MAXIMUM_NETWORK_PLAYERS,
|
|
#else
|
|
NETWORK_GAME_MESSAGE_VERSION = 1,
|
|
TRANSPORT_NONCE_LENGTH = 8,
|
|
TRANSPORT_ERROR_MESSAGE_TEXT_LENGTH = 0x80,
|
|
MAXIMUM_NETWORK_MACHINE_COUNT = 4,
|
|
NETWORK_GAME_NAME_LENGTH = 16,
|
|
MAXIMUM_NUMBER_OF_PLAYERS = 16,
|
|
#endif
|
|
JOIN_GAME_TOKEN_LENGTH = 16,
|
|
};
|
|
|
|
#define MINIMUM_TRANSPORT_ERROR_MESSAGE_SIZE (sizeof(word) + TRANSPORT_ERROR_MESSAGE_TEXT_LENGTH + sizeof(byte))
|
|
|
|
enum
|
|
{
|
|
_message_type_error = 1,
|
|
_message_type_data = 2,
|
|
};
|
|
|
|
enum network_game_client_state
|
|
{
|
|
_network_game_client_state_searching,
|
|
_network_game_client_state_joining,
|
|
_network_game_client_state_pregame,
|
|
_network_game_client_state_ingame,
|
|
_network_game_client_state_postgame,
|
|
NUMBER_OF_NETWORK_GAME_CLIENT_STATES,
|
|
};
|
|
|
|
enum network_game_packet_class
|
|
{
|
|
_network_game_packet_class_advertisement = 1,
|
|
_network_game_packet_class_pregame = 2,
|
|
_network_game_packet_class_ingame = 4,
|
|
_network_game_packet_class_postgame = 6,
|
|
};
|
|
|
|
/* ---------- macros */
|
|
|
|
/* ---------- structures */
|
|
|
|
struct network_game_client;
|
|
|
|
struct network_machine
|
|
{
|
|
wchar_t name[32];
|
|
char machine_index;
|
|
byte padding41[3];
|
|
};
|
|
|
|
struct network_game_map
|
|
{
|
|
long unknown;
|
|
char name[0x80];
|
|
};
|
|
|
|
struct network_game_local_data
|
|
{
|
|
boolean game_objects_loaded;
|
|
byte padding431[3];
|
|
};
|
|
|
|
struct network_game
|
|
{
|
|
wchar_t name[NETWORK_GAME_NAME_LENGTH];
|
|
struct network_game_map map;
|
|
struct game_variant variant;
|
|
byte unknown10C;
|
|
char minimum_player_count;
|
|
#ifdef HALO_LINUX
|
|
/* 128 does not fit a signed char */
|
|
byte maximum_player_count;
|
|
#else
|
|
char maximum_player_count;
|
|
#endif
|
|
byte team_count;
|
|
short difficulty;
|
|
short machine_count;
|
|
struct network_machine machines[MAXIMUM_NETWORK_MACHINE_COUNT];
|
|
short player_count;
|
|
struct network_player players[MAXIMUM_NUMBER_OF_PLAYERS];
|
|
word reserved_after_players;
|
|
unsigned long random_seed;
|
|
long number_of_games_played;
|
|
struct network_game_local_data local_data;
|
|
};
|
|
|
|
#ifdef HALO_LINUX
|
|
typedef char network_game_players_offset_assert[
|
|
offsetof(struct network_game, players) == HALO_PORT_NETWORK_GAME_PLAYERS_OFFSET ? 1 : -1];
|
|
typedef char network_game_size_assert[
|
|
sizeof(struct network_game) == HALO_PORT_NETWORK_GAME_SIZE ? 1 : -1];
|
|
|
|
/* one piece of the game settings record, which no longer fits one message
|
|
(network_server_message_handler.c sends them in order) */
|
|
struct message_server_game_settings_update
|
|
{
|
|
word total_size;
|
|
word offset;
|
|
word length;
|
|
word pad;
|
|
byte data[HALO_PORT_NETWORK_GAME_SETTINGS_FRAGMENT_SIZE];
|
|
};
|
|
#endif
|
|
|
|
struct message_server_game_advertise
|
|
{
|
|
byte client_nonce[TRANSPORT_NONCE_LENGTH];
|
|
byte nonce[TRANSPORT_NONCE_LENGTH];
|
|
XNKID key_id;
|
|
XNKEY key;
|
|
XNADDR xnaddr;
|
|
word port;
|
|
word version;
|
|
word platform;
|
|
wchar_t game_name[NETWORK_GAME_NAME_LENGTH];
|
|
byte reserved[0x1A];
|
|
struct network_game_map map;
|
|
short engine_type;
|
|
short machine_count;
|
|
short player_count;
|
|
short maximum_player_count;
|
|
short variant_setting;
|
|
word flags;
|
|
byte join_game_token[JOIN_GAME_TOKEN_LENGTH];
|
|
};
|
|
|
|
struct message_server_pong
|
|
{
|
|
long timestamp;
|
|
};
|
|
|
|
struct message_server_machine_accepted
|
|
{
|
|
long random_seed;
|
|
short machine_index;
|
|
byte padding6[2];
|
|
};
|
|
|
|
struct message_server_machine_rejected
|
|
{
|
|
short reason;
|
|
};
|
|
|
|
struct message_server_pregame_countdown
|
|
{
|
|
short seconds_remaining;
|
|
};
|
|
|
|
struct message_server_pregame_keep_alive
|
|
{
|
|
short unused;
|
|
};
|
|
|
|
struct message_server_postgame_keep_alive
|
|
{
|
|
short unused;
|
|
};
|
|
|
|
struct message_server_begin_game
|
|
{
|
|
long unused;
|
|
};
|
|
|
|
struct message_server_graceful_game_exit_pregame
|
|
{
|
|
long unused;
|
|
};
|
|
|
|
struct message_server_game_update
|
|
{
|
|
unsigned long update_number;
|
|
long random_seed;
|
|
long game_time;
|
|
byte padding0C[2];
|
|
short local_player_count;
|
|
struct player_action player_actions[MAXIMUM_NUMBER_OF_PLAYERS];
|
|
#ifdef HALO_LINUX
|
|
PLAYER_ACTION_VR_TAIL(MAXIMUM_VR_PLAYERS_PER_UPDATE)
|
|
#endif
|
|
};
|
|
|
|
struct message_server_remove_player_ingame
|
|
{
|
|
struct network_player player;
|
|
long reason;
|
|
};
|
|
|
|
struct message_server_game_over
|
|
{
|
|
long unused;
|
|
};
|
|
|
|
struct message_server_switch_to_pregame
|
|
{
|
|
long unused;
|
|
};
|
|
|
|
struct message_server_graceful_game_exit_postgame
|
|
{
|
|
long unused;
|
|
};
|
|
|
|
/* ---------- prototypes */
|
|
|
|
static boolean network_game_client_handle_message_server_game_advertise(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_pong(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_machine_accepted(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_machine_rejected(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_game_settings_update(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_pregame_countdown(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_pregame_keep_alive(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_postgame_keep_alive(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_begin_game(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_graceful_game_exit_pregame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_game_update(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_add_player_ingame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_remove_player_ingame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_game_over(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_switch_to_pregame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_graceful_game_exit_postgame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
|
|
/* ---------- globals */
|
|
|
|
/* ---------- public code */
|
|
|
|
boolean network_game_client_handle_message(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = TRUE;
|
|
word message_type;
|
|
byte packet_type;
|
|
|
|
match_assert(
|
|
NETWORK_CLIENT_MESSAGE_HANDLER_FILE,
|
|
0x2F,
|
|
client && message && (message_size == GET_MESSAGE_SIZE(*message)) && source_address);
|
|
|
|
message_type = (byte)GET_MESSAGE_TYPE(*message);
|
|
if (GET_MESSAGE_FLAGS(*message))
|
|
{
|
|
network_event("client received client message with invalid flags");
|
|
}
|
|
else
|
|
{
|
|
switch (message_type)
|
|
{
|
|
case _message_type_packet:
|
|
packet_type = ((byte *)message)[message_size - 1];
|
|
switch (packet_type)
|
|
{
|
|
case _message_server_game_advertise:
|
|
result = network_game_client_handle_message_server_game_advertise(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_game_advertise() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_pong:
|
|
result = network_game_client_handle_message_server_pong(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_pong() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_machine_accepted:
|
|
result = network_game_client_handle_message_server_machine_accepted(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_machine_accepted() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_machine_rejected:
|
|
result = network_game_client_handle_message_server_machine_rejected(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_machine_rejected() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_game_settings_update:
|
|
result = network_game_client_handle_message_server_game_settings_update(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_game_settings_update() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_pregame_countdown:
|
|
result = network_game_client_handle_message_server_pregame_countdown(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_pregame_countdown() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_pregame_keep_alive:
|
|
result = network_game_client_handle_message_server_pregame_keep_alive(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_pregame_keep_alive() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_postgame_keep_alive:
|
|
result = network_game_client_handle_message_server_postgame_keep_alive(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_postgame_keep_alive() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_begin_game:
|
|
result = network_game_client_handle_message_server_begin_game(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_begin_game() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_graceful_game_exit_pregame:
|
|
result = network_game_client_handle_message_server_graceful_game_exit_pregame(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_graceful_game_exit_pregame() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_game_update:
|
|
result = network_game_client_handle_message_server_game_update(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_game_update() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_add_player_ingame:
|
|
result = network_game_client_handle_message_server_add_player_ingame(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_add_player_ingame() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_remove_player_ingame:
|
|
result = network_game_client_handle_message_server_remove_player_ingame(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_remove_player_ingame() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_game_over:
|
|
result = network_game_client_handle_message_server_game_over(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_game_over() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_switch_to_pregame:
|
|
result = network_game_client_handle_message_server_switch_to_pregame(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_switch_to_pregame() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_graceful_game_exit_postgame:
|
|
result = network_game_client_handle_message_server_graceful_game_exit_postgame(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_graceful_game_exit_postgame() failed");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
network_event(
|
|
"unknown packet type received from system @ address: %s",
|
|
transport_address_to_string(source_address));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case _message_type_data:
|
|
network_event("client received a bad message type (_message_type_data)");
|
|
break;
|
|
|
|
case _message_type_error:
|
|
if (message_size >= MINIMUM_TRANSPORT_ERROR_MESSAGE_SIZE)
|
|
{
|
|
byte *error_message = (byte *)(message + 1);
|
|
|
|
network_event(
|
|
"client received low-level error message: error= #%d (%s)",
|
|
error_message[TRANSPORT_ERROR_MESSAGE_TEXT_LENGTH],
|
|
error_message);
|
|
}
|
|
else
|
|
{
|
|
network_event("client received a malformed/damaged message from a server");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
network_event("client received a message with an unknown message type");
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* ---------- private code */
|
|
|
|
static boolean network_game_client_handle_message_server_game_advertise(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_searching)
|
|
{
|
|
struct message_server_game_advertise advertisement;
|
|
short packet_type = _message_server_game_advertise;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&advertisement,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_advertisement))
|
|
{
|
|
if (transport_is_nonce(&advertisement, TRANSPORT_NONCE_LENGTH))
|
|
{
|
|
network_game_client_new_advertised_game(client, &advertisement);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_game_advertise packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring an advertised game because we are not looking for new games");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_pong(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_searching)
|
|
{
|
|
struct message_server_pong pong;
|
|
short packet_type = _message_server_pong;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&pong,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_advertisement))
|
|
{
|
|
network_game_client_ponged(client, source_address, pong.timestamp);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_pong packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a pong message because we are not listening for them");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_machine_accepted(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = TRUE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address) &&
|
|
network_game_client_get_state(client, NULL) == _network_game_client_state_joining)
|
|
{
|
|
struct message_server_machine_accepted acceptance;
|
|
short packet_type = _message_server_machine_accepted;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&acceptance,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
network_game_client_accepted_into_game(client, source_address, &acceptance);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_machine_accepted packet");
|
|
result = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_machine_accepted message; either a bad machine or we aren't joining");
|
|
result = FALSE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_machine_rejected(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = TRUE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address) &&
|
|
network_game_client_get_state(client, NULL) == _network_game_client_state_joining)
|
|
{
|
|
struct message_server_machine_rejected rejection;
|
|
short packet_type = _message_server_machine_rejected;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&rejection,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
network_game_client_rejected_by_game(client, source_address, rejection.reason);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_machine_rejected packet");
|
|
result = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_machine_rejected message; either a bad machine or we aren't joining");
|
|
result = FALSE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
#ifdef HALO_LINUX
|
|
/* the game settings record as its pieces arrive; it is applied once the last
|
|
piece is in */
|
|
static struct network_game network_game_client_settings_staging;
|
|
static long network_game_client_settings_staging_size = 0;
|
|
|
|
static boolean network_game_client_receive_game_settings_piece(
|
|
struct network_game_client *client,
|
|
struct message_server_game_settings_update const *piece)
|
|
{
|
|
boolean result = TRUE;
|
|
|
|
if (piece->total_size != sizeof(network_game_client_settings_staging) ||
|
|
piece->length > sizeof(piece->data) ||
|
|
piece->offset + piece->length > sizeof(network_game_client_settings_staging))
|
|
{
|
|
network_event("got a message_server_game_settings_update piece for a different game layout");
|
|
network_game_client_settings_staging_size = 0;
|
|
result = FALSE;
|
|
}
|
|
else
|
|
{
|
|
/* each record is sent in order from its start, over a stream */
|
|
if (piece->offset == 0)
|
|
{
|
|
network_game_client_settings_staging_size = 0;
|
|
}
|
|
if (piece->offset != network_game_client_settings_staging_size)
|
|
{
|
|
network_event("got a message_server_game_settings_update piece out of order; waiting for the next record");
|
|
network_game_client_settings_staging_size = 0;
|
|
}
|
|
else
|
|
{
|
|
csmemcpy(
|
|
(byte *)&network_game_client_settings_staging + piece->offset,
|
|
piece->data,
|
|
piece->length);
|
|
network_game_client_settings_staging_size += piece->length;
|
|
if (network_game_client_settings_staging_size == piece->total_size)
|
|
{
|
|
network_game_client_settings_staging_size = 0;
|
|
result = network_game_client_game_settings_updated(client, &network_game_client_settings_staging);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_game_settings_updated() failed");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
static boolean network_game_client_handle_message_server_game_settings_update(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x169, client != NULL);
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x16A, source_address != NULL);
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_pregame)
|
|
{
|
|
#ifdef HALO_LINUX
|
|
struct message_server_game_settings_update piece;
|
|
short packet_type = _message_server_game_settings_update;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&piece,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
result = network_game_client_receive_game_settings_piece(client, &piece);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_game_settings_update packet");
|
|
}
|
|
#else
|
|
struct network_game game_settings;
|
|
short packet_type = _message_server_game_settings_update;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&game_settings,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
result = network_game_client_game_settings_updated(client, &game_settings);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_game_settings_updated() failed");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_game_settings_update packet");
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_game_settings_update message; not in pregame state");
|
|
result = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_game_settings_update; came from a bad machine");
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_pregame_countdown(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x19B, client != NULL);
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x19C, source_address != NULL);
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_pregame)
|
|
{
|
|
struct message_server_pregame_countdown countdown;
|
|
short packet_type = _message_server_pregame_countdown;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&countdown,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
network_game_client_countdown_timer_update(client, countdown.seconds_remaining);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_pregame_countdown packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_pregame_countdown message; not in pregame state");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_pregame_countdown; came from a bad machine");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_pregame_keep_alive(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x1C4, client != NULL);
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x1C5, source_address != NULL);
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_pregame)
|
|
{
|
|
struct message_server_pregame_keep_alive keep_alive;
|
|
short packet_type = _message_server_pregame_keep_alive;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (!decode_network_game_message(
|
|
&keep_alive,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
network_event("failed to decode a message_server_pregame_keep_alive packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_pregame_keep_alive message; not in pregame state");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_pregame_keep_alive; came from a bad machine");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_postgame_keep_alive(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x1EE, client != NULL);
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x1EF, source_address != NULL);
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_postgame)
|
|
{
|
|
struct message_server_postgame_keep_alive keep_alive;
|
|
short packet_type = _message_server_postgame_keep_alive;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (!decode_network_game_message(
|
|
&keep_alive,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_postgame))
|
|
{
|
|
network_event("failed to decode a message_server_postgame_keep_alive packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_postgame_keep_alive message; not in postgame state");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_postgame_keep_alive; came from a bad machine");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_begin_game(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_pregame)
|
|
{
|
|
struct message_server_begin_game begin_game;
|
|
short packet_type = _message_server_begin_game;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&begin_game,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
result = network_game_client_game_has_started(client);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_game_has_started() failed");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_begin_game packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_begin_game message; we are not in pregame");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_begin_game message; came from a bad machine");
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_graceful_game_exit_pregame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_pregame)
|
|
{
|
|
struct message_server_graceful_game_exit_pregame game_exit;
|
|
short packet_type = _message_server_graceful_game_exit_pregame;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&game_exit,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
network_game_client_game_shutdown(client);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_graceful_game_exit_pregame packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_graceful_game_exit_pregame message; we are not in pregame");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_graceful_game_exit_pregame message; came from a bad machine");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_game_update(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_ingame)
|
|
{
|
|
struct message_server_game_update game_update;
|
|
short packet_type = _message_server_game_update;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&game_update,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_ingame))
|
|
{
|
|
result = network_game_client_handle_game_update(client, &game_update);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_game_update() failed");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_game_update packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_game_update message; we are not in game");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_game_update message; came from a bad machine");
|
|
result = TRUE;
|
|
}
|
|
|
|
if (!result)
|
|
{
|
|
network_game_client_game_out_of_sync(client);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_add_player_ingame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_ingame)
|
|
{
|
|
struct network_player player;
|
|
short packet_type = _message_server_add_player_ingame;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&player,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_ingame))
|
|
{
|
|
result = network_game_client_add_player_to_game(client, &player);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_add_player_to_game() failed");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_add_player_ingame packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_add_player_ingame message; we are not in game");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_add_player_ingame message; came from a bad machine");
|
|
result = TRUE;
|
|
}
|
|
|
|
if (!result)
|
|
{
|
|
network_game_client_game_out_of_sync(client);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_remove_player_ingame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_ingame)
|
|
{
|
|
struct message_server_remove_player_ingame removal;
|
|
short packet_type = _message_server_remove_player_ingame;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&removal,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_ingame))
|
|
{
|
|
result = network_game_client_remove_player(client, &removal.player, removal.reason);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_remove_player() failed");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_remove_player_ingame packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_remove_player_ingame message; we are not in game");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_remove_player_ingame message; came from a bad machine");
|
|
result = TRUE;
|
|
}
|
|
|
|
if (!result)
|
|
{
|
|
network_game_client_game_out_of_sync(client);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_game_over(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_ingame)
|
|
{
|
|
struct message_server_game_over game_over;
|
|
short packet_type = _message_server_game_over;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (!decode_network_game_message(
|
|
&game_over,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_ingame))
|
|
{
|
|
network_event("failed to decode a message_server_game_over message (not critical)");
|
|
}
|
|
|
|
network_game_client_switch_to_postgame(client);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_game_over message; we are not in game");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_game_over message; came from a bad machine");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_switch_to_pregame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_postgame)
|
|
{
|
|
struct message_server_switch_to_pregame switch_to_pregame;
|
|
short packet_type = _message_server_switch_to_pregame;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (!decode_network_game_message(
|
|
&switch_to_pregame,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_postgame))
|
|
{
|
|
network_event("failed to decode a message_server_switch_to_pregame packet");
|
|
}
|
|
|
|
result = network_game_client_switch_to_pregame(client);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_switch_to_pregame() failed");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_switch_to_pregame message; we are not in post-game");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_switch_to_pregame message; came from a bad machine");
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_graceful_game_exit_postgame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_postgame)
|
|
{
|
|
struct message_server_graceful_game_exit_postgame game_exit;
|
|
short packet_type = _message_server_graceful_game_exit_postgame;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (!decode_network_game_message(
|
|
&game_exit,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_postgame))
|
|
{
|
|
network_event("failed to decode a message_server_graceful_game_exit_postgame packet (not critical)");
|
|
}
|
|
|
|
network_game_client_game_shutdown(client);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_graceful_game_exit_postgame message; we are not in post-game");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_graceful_game_exit_postgame message; came from a bad machine");
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|