mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 19:55:23 +00:00
692 lines
19 KiB
C++
692 lines
19 KiB
C++
/*
|
|
* Descent 3
|
|
* Copyright (C) 2024 Parallax Software
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
--- HISTORICAL COMMENTS FOLLOW ---
|
|
|
|
* $Logfile: /DescentIII/Main/dmfc/dmfcpackets.cpp $
|
|
* $Revision: 1.1.1.1 $
|
|
* $Date: 2003/08/26 03:57:21 $
|
|
* $Author: kevinb $
|
|
*
|
|
* DMFC Special packet handling functions
|
|
*
|
|
* $Log: dmfcpackets.cpp,v $
|
|
* Revision 1.1.1.1 2003/08/26 03:57:21 kevinb
|
|
* initial 1.5 import
|
|
*
|
|
*
|
|
* 29 8/21/99 12:32a Jeff
|
|
* Changed the name of the GetRealGametime function to
|
|
* GetRealGametimePacket since it was confusing some compilers with the
|
|
* other GetRealGametime function.
|
|
*
|
|
* 28 7/09/99 2:54p Jeff
|
|
* handle gametime better (pause it when needed) if the server is 'waiting
|
|
* for players'
|
|
*
|
|
* 27 7/08/99 6:25p Jeff
|
|
* remote admin in and working
|
|
*
|
|
* 26 7/08/99 2:39a Jeff
|
|
* rough implementation of remote administration checked in. Still needs
|
|
* some polishing, but should work basically.
|
|
*
|
|
* 25 5/13/99 4:55p Ardussi
|
|
* changes for compiling on the Mac
|
|
*
|
|
* 24 5/12/99 11:05p Jeff
|
|
* dmfc and multiplayer games now have endian friendly packets (*whew*)
|
|
*
|
|
* 23 4/07/99 9:24p Jeff
|
|
* fixed bug in sending team names over
|
|
*
|
|
* 22 3/17/99 12:24p Jeff
|
|
* converted DMFC to be COM interface
|
|
*
|
|
* 21 2/11/99 12:51a Jeff
|
|
* changed names of exported variables
|
|
*
|
|
* 20 12/08/98 4:47p Jeff
|
|
* umm, various changes, fixed pilot pics so that they work for everyone
|
|
* now
|
|
*
|
|
* 19 12/08/98 12:17p Jeff
|
|
* various changes that include an improved Team Control dialog (doesn't
|
|
* switch teams until exit..) and spew/respawn players that change teams
|
|
*
|
|
* 18 11/17/98 12:36p Jeff
|
|
* fixed bug in sending new team name to clients
|
|
*
|
|
* 17 11/16/98 5:35p Jeff
|
|
* removed log functions, added support for changing team names, fixed ctf
|
|
* to work better with different team names
|
|
*
|
|
* 16 11/11/98 7:19p Jeff
|
|
* changes made so that a dedicated server's team is always -1 (team game
|
|
* or not)
|
|
*
|
|
* 15 10/29/98 7:01p Jeff
|
|
* creation of team placement dialog. Moved TranslateEvent into DMFC
|
|
*
|
|
* 14 10/23/98 11:22a Jeff
|
|
* changes to handle mixcase, and display the client netgame info
|
|
* correctly
|
|
*
|
|
* 13 10/20/98 12:16p Jeff
|
|
* added death message filter, hud callsign filter
|
|
*
|
|
* 12 10/08/98 3:37p Jeff
|
|
* general improvements (Netgame info things, save to registry). Changes
|
|
* so it would send packets on NETSEQ_OBJECTS
|
|
*
|
|
* 11 9/30/98 4:21p Jeff
|
|
* team changing is handled correctly
|
|
*
|
|
* 10 9/25/98 8:02p Jason
|
|
* added checks for jeff
|
|
*
|
|
* 9 9/21/98 7:11p Jeff
|
|
* made InputCommand interface API and moved existing input commands to
|
|
* the interface. Changed mprintf/ASSERT so they are valid in DMFC
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
#include "gamedll_header.h"
|
|
#include "DMFC.h"
|
|
#include "dmfcinternal.h"
|
|
|
|
|
|
// DMFCBase::RegisterPacketReceiver
|
|
//
|
|
// Sets up a handler for a Special Packet ID. When a special packet is recieved it's ID is compared
|
|
// to the ID's given to this function. If any match than it calls the handler given to process
|
|
// the packet.
|
|
// id = ID of the packet
|
|
// func = Function handler to handle the packet. Must be declared like void MyFunction(uint8_t *data);
|
|
void DMFCBase::RegisterPacketReceiver(uint8_t id, void (*func)(uint8_t *)) {
|
|
// go to the last handler
|
|
tSPHandler *current, *last;
|
|
|
|
if (!SPRoot) {
|
|
// handle special case for first node being added
|
|
SPRoot = (tSPHandler *)malloc(sizeof(tSPHandler));
|
|
if (!SPRoot)
|
|
return;
|
|
current = SPRoot;
|
|
} else {
|
|
last = current = SPRoot;
|
|
while (current) {
|
|
last = current;
|
|
current = current->next;
|
|
}
|
|
|
|
// allocate memory for the node
|
|
current = (tSPHandler *)malloc(sizeof(tSPHandler));
|
|
if (!current)
|
|
return;
|
|
// add it to the list
|
|
last->next = current;
|
|
}
|
|
|
|
// fill in the struct
|
|
current->next = NULL;
|
|
current->ID = id;
|
|
current->type = SPH_FUNC;
|
|
current->func = func;
|
|
}
|
|
void DMFCBase::RegisterPacketReceiver(uint8_t id, void (DMFCBase::*func)(uint8_t *)) {
|
|
// go to the last handler
|
|
tSPHandler *current, *last;
|
|
|
|
if (!SPRoot) {
|
|
// handle special case for first node being added
|
|
SPRoot = (tSPHandler *)malloc(sizeof(tSPHandler));
|
|
if (!SPRoot)
|
|
return;
|
|
current = SPRoot;
|
|
} else {
|
|
last = current = SPRoot;
|
|
while (current) {
|
|
last = current;
|
|
current = current->next;
|
|
}
|
|
|
|
// allocate memory for the node
|
|
current = (tSPHandler *)malloc(sizeof(tSPHandler));
|
|
if (!current)
|
|
return;
|
|
// add it to the list
|
|
last->next = current;
|
|
}
|
|
|
|
// fill in the struct
|
|
current->next = NULL;
|
|
current->ID = id;
|
|
current->type = SPH_DMFCFUNC;
|
|
current->DMFCfunc = func;
|
|
}
|
|
|
|
// DMFCBase::StartPacket
|
|
//
|
|
// Initializes a packet so it is ready to be sent out.
|
|
// data = pointer to buffer of data for packet. This buffer should be MAX_GAME_DATA_SIZE in size, even
|
|
// if you don't plan on using all that data, there is header information that is added
|
|
// in this function.
|
|
// id = ID of the Special packet. When the packet is recieved by whomever, this is the ID that determines which
|
|
// handler to
|
|
// call.
|
|
// count = pointer to your packet index pointer
|
|
void DMFCBase::StartPacket(uint8_t *data, uint8_t id, int *count) {
|
|
*count = 0;
|
|
|
|
MultiAddByte(id, data, count); // set the first byte (invisible to coder) as the id
|
|
}
|
|
|
|
// DMFCBase::SendPacket
|
|
//
|
|
// Ships a Special Packet away to the destination. This call must be preceeded by a StartPacket call
|
|
// data = buffer of data to be sent out (same buffer that was passed to StartPacket
|
|
// size = size (in bytes) of the packet
|
|
// destination = either a player number, SP_ALL for all the players or SP_SERVER to send to the server (if you are a
|
|
// client)
|
|
void DMFCBase::SendPacket(uint8_t *data, int size, int destination) {
|
|
ASSERT(size < MAX_GAME_DATA_SIZE - 2); // allow for a header by the d3
|
|
if (size >= MAX_GAME_DATA_SIZE - 2)
|
|
return;
|
|
|
|
// if we are the server and are trying to send to the server then exit out
|
|
if ((GetLocalRole() == LR_SERVER) && (destination == SP_SERVER)) {
|
|
return;
|
|
}
|
|
|
|
// we can safely send this packet out to it's appropriate destination
|
|
|
|
// see if we are trying to send to the server, it's specially handled
|
|
if (destination == SP_SERVER) {
|
|
DLLMultiClientSendSpecialPacket(data, size);
|
|
return;
|
|
}
|
|
|
|
// server trying to send to clients
|
|
if (GetLocalRole() == LR_CLIENT) {
|
|
// we can't send client to client
|
|
return;
|
|
}
|
|
|
|
// if server is trying to send to all the clients then we need to send to each individual
|
|
if (destination == SP_ALL) {
|
|
int pnum;
|
|
for (pnum = 0; pnum < DLLMAX_PLAYERS; pnum++) {
|
|
|
|
if ((pnum != GetPlayerNum()) && (PacketCheckPlayerNum(pnum))) {
|
|
// ship it!
|
|
DLLMultiSendSpecialPacket(pnum, data, size);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// we are only sending to one client
|
|
if (destination != GetPlayerNum())
|
|
DLLMultiSendSpecialPacket(destination, data, size);
|
|
}
|
|
|
|
// DMFCBase::GetGameStateRequest
|
|
//
|
|
// Receiver for the server from a client asking for the state of the game
|
|
void DMFCBase::GetGameStateRequest(uint8_t *data) {
|
|
int pnum;
|
|
int count = 0;
|
|
pnum = MultiGetInt(data, &count);
|
|
CallOnGameStateRequest(pnum);
|
|
}
|
|
|
|
// DMFCBase::SendTeamAssignment
|
|
//
|
|
// A DMFC Special Packet function, this sends a team assignment packet to all the players. Server only.
|
|
// playernum = player to change teams
|
|
// team = new team
|
|
void DMFCBase::SendTeamAssignment(int playernum, int team, bool spew_onrespawn) {
|
|
if (GetLocalRole() != LR_SERVER)
|
|
return;
|
|
|
|
uint8_t data[MAX_GAME_DATA_SIZE];
|
|
int count = 0;
|
|
|
|
StartPacket(data, SPID_TEAMASSIGNMENT, &count);
|
|
|
|
MultiAddByte((spew_onrespawn) ? 1 : 0, data, &count);
|
|
MultiAddInt(playernum, data, &count);
|
|
MultiAddInt(team, data, &count);
|
|
|
|
SendPacket(data, count, SP_ALL);
|
|
}
|
|
|
|
// DMFCBase::GetTeamAssignmentPacket
|
|
//
|
|
// Reciever for the team assignment packet.
|
|
void DMFCBase::GetTeamAssignmentPacket(uint8_t *data) {
|
|
int count = 0;
|
|
bool spew = MultiGetByte(data, &count) ? true : false;
|
|
|
|
int pnum = MultiGetInt(data, &count);
|
|
int team = MultiGetInt(data, &count);
|
|
|
|
if (CheckPlayerNum(pnum)) {
|
|
Players[pnum].team = team;
|
|
CallOnPlayerChangeTeam(pnum, team, true, spew);
|
|
}
|
|
}
|
|
|
|
// DMFCBase::GetChangeTeamPacket
|
|
//
|
|
// Reciever for the change team packet.(Server Only)
|
|
void DMFCBase::GetChangeTeamPacket(uint8_t *data) {
|
|
if (GetLocalRole() != LR_SERVER)
|
|
return;
|
|
// We recieved a request for a player to change teams
|
|
|
|
int count = 0;
|
|
|
|
bool spew_on_respawn = MultiGetByte(data, &count) ? true : false;
|
|
int pnum = MultiGetByte(data, &count);
|
|
int newteam = MultiGetByte(data, &count);
|
|
if (newteam == 255)
|
|
newteam = -1;
|
|
|
|
if (!AllowTeamChange()) {
|
|
return;
|
|
}
|
|
|
|
if (!CallOnCanChangeTeam(pnum, newteam)) {
|
|
return;
|
|
}
|
|
|
|
if (!CheckPlayerNum(pnum))
|
|
return;
|
|
|
|
if ((newteam < 0) || (newteam > m_iNumTeams))
|
|
return;
|
|
|
|
Players[pnum].team = newteam;
|
|
CallOnPlayerChangeTeam(pnum, newteam, true, spew_on_respawn);
|
|
SendTeamAssignment(pnum, newteam, spew_on_respawn);
|
|
}
|
|
|
|
// DMFCBase::SendChangeTeamRequest
|
|
//
|
|
// Sends a request to the server to change teams (Client Only)
|
|
void DMFCBase::SendChangeTeamRequest(int newteam, bool spew_onrespawn) {
|
|
uint8_t data[MAX_GAME_DATA_SIZE];
|
|
int count = 0;
|
|
|
|
StartPacket(data, SPID_CHANGETEAM, &count);
|
|
|
|
MultiAddByte((spew_onrespawn) ? 1 : 0, data, &count);
|
|
MultiAddByte(GetPlayerNum(), data, &count);
|
|
MultiAddByte((newteam == -1) ? 255 : newteam, data, &count);
|
|
|
|
SendPacket(data, count, SP_SERVER);
|
|
}
|
|
|
|
// DMFCBase::GetDMFCGameInfo
|
|
//
|
|
// Receives information about the DMFC game
|
|
void DMFCBase::GetDMFCGameInfo(uint8_t *data) {
|
|
int count = 0;
|
|
|
|
uint8_t level = MultiGetByte(data, &count); // server's HUD Callsign max level
|
|
m_bMakeClientsWait = MultiGetByte(data, &count) ? true : false;
|
|
SwitchServerHudCallsignLevel(level);
|
|
|
|
int num_teams = MultiGetByte(data, &count);
|
|
|
|
char buffer[256];
|
|
|
|
if (num_teams > 1) {
|
|
MultiGetString(buffer, data, &count);
|
|
SetTeamName(RED_TEAM, buffer, false);
|
|
|
|
MultiGetString(buffer, data, &count);
|
|
SetTeamName(BLUE_TEAM, buffer, false);
|
|
|
|
MultiGetString(buffer, data, &count);
|
|
SetTeamName(GREEN_TEAM, buffer, false);
|
|
|
|
MultiGetString(buffer, data, &count);
|
|
SetTeamName(YELLOW_TEAM, buffer, false);
|
|
}
|
|
|
|
WaitForServer(m_bMakeClientsWait);
|
|
}
|
|
|
|
// DMFCBase::SendDMFCGameInfo
|
|
//
|
|
// Sends information about the DMFC game
|
|
void DMFCBase::SendDMFCGameInfo(int player) {
|
|
int r_len, b_len, g_len, y_len;
|
|
int count = 0;
|
|
uint8_t data[MAX_GAME_DATA_SIZE];
|
|
|
|
StartPacket(data, SPID_DMFCGAMEINFO, &count);
|
|
|
|
if (GetNumTeams() > 1) {
|
|
// team game
|
|
r_len = strlen(GetTeamString(RED_TEAM)) + 1;
|
|
b_len = strlen(GetTeamString(BLUE_TEAM) + 1);
|
|
g_len = strlen(GetTeamString(GREEN_TEAM) + 1);
|
|
y_len = strlen(GetTeamString(YELLOW_TEAM) + 1);
|
|
|
|
MultiAddByte(m_iServerHUDCallsignLevel, data, &count);
|
|
MultiAddByte(m_bMakeClientsWait, data, &count);
|
|
MultiAddByte(GetNumTeams(), data, &count);
|
|
|
|
MultiAddString(GetTeamString(RED_TEAM), data, &count);
|
|
MultiAddString(GetTeamString(BLUE_TEAM), data, &count);
|
|
MultiAddString(GetTeamString(GREEN_TEAM), data, &count);
|
|
MultiAddString(GetTeamString(YELLOW_TEAM), data, &count);
|
|
|
|
} else {
|
|
// non-team game
|
|
MultiAddByte(m_iServerHUDCallsignLevel, data, &count);
|
|
MultiAddByte(m_bMakeClientsWait, data, &count);
|
|
MultiAddByte(GetNumTeams(), data, &count);
|
|
}
|
|
|
|
SendPacket(data, count, player);
|
|
|
|
SendRealGametime(player);
|
|
}
|
|
|
|
// DMFCBase::SendRealGametime
|
|
//
|
|
// Updates a player about the 'real' game time
|
|
void DMFCBase::SendRealGametime(int pnum) {
|
|
int count = 0;
|
|
uint8_t data[MAX_GAME_DATA_SIZE];
|
|
|
|
StartPacket(data, SPID_REALGAMETIME, &count);
|
|
|
|
MultiAddFloat(RealGametime, data, &count);
|
|
|
|
if (m_iProtectedFlags & DMFC_PRF_PAUSETIME) {
|
|
// time is paused
|
|
MultiAddByte(1, data, &count);
|
|
} else {
|
|
// time is not paused
|
|
MultiAddByte(0, data, &count);
|
|
}
|
|
|
|
SendPacket(data, count, pnum);
|
|
}
|
|
|
|
// DMFCBase::GetRealGametime
|
|
//
|
|
// handles a packet about updating the real game time
|
|
void DMFCBase::GetRealGametimePacket(uint8_t *data) {
|
|
int count = 0;
|
|
|
|
RealGametime = MultiGetFloat(data, &count);
|
|
|
|
if (MultiGetByte(data, &count)) {
|
|
// time is paused
|
|
ENABLE_FLAGS(m_iProtectedFlags, DMFC_PRF_PAUSETIME);
|
|
} else {
|
|
// time is not paused
|
|
DISABLE_FLAGS(m_iProtectedFlags, DMFC_PRF_PAUSETIME);
|
|
}
|
|
}
|
|
|
|
// DMFCBase::SendRemoteKey
|
|
//
|
|
// Sends out the players remote admin key
|
|
void DMFCBase::SendRemoteKey(int pnum) {
|
|
// Send this user's remote admin key
|
|
player_record *pr = PRec_GetPRecordByPnum(pnum);
|
|
int precnum = -1;
|
|
if (pr) {
|
|
precnum = translate_precptr_to_index(pr);
|
|
}
|
|
if (precnum != -1) {
|
|
int count = 0;
|
|
uint8_t data[MAX_GAME_DATA_SIZE];
|
|
|
|
StartPacket(data, SPID_REMOTEKEY, &count);
|
|
|
|
uint8_t *key = Remote_GetKey(precnum);
|
|
memcpy(&data[count], key, 8);
|
|
count += 8;
|
|
|
|
SendPacket(data, count, pnum);
|
|
} else {
|
|
Int3();
|
|
}
|
|
}
|
|
|
|
// DMFCBase::GetRemoteKey
|
|
//
|
|
// Handles a new remote key from the server
|
|
void DMFCBase::GetRemoteKey(uint8_t *data) {
|
|
int count = 0;
|
|
uint8_t key[8];
|
|
memcpy(key, &data[count], 8);
|
|
count += 8;
|
|
Remote_SetMyKey(key);
|
|
}
|
|
|
|
// DMFCBase::RequestGameState
|
|
//
|
|
// Sends a request to the server for the game state
|
|
void DMFCBase::RequestGameState(void) {
|
|
if (GetLocalRole() == LR_SERVER)
|
|
return;
|
|
int count = 0;
|
|
uint8_t data[MAX_GAME_DATA_SIZE];
|
|
StartPacket(data, SPID_REQGAMESTATE, &count);
|
|
|
|
MultiAddInt(GetPlayerNum(), data, &count);
|
|
|
|
SendPacket(data, count, SP_SERVER);
|
|
}
|
|
|
|
void DMFCBase::SendVersionToClient(int pnum) {
|
|
if (GetLocalRole() != LR_SERVER)
|
|
return;
|
|
int count = 0;
|
|
uint8_t data[MAX_GAME_DATA_SIZE];
|
|
|
|
StartPacket(data, SPID_VERSIONID, &count);
|
|
|
|
MultiAddInt(DMFC_VERSION_MAJOR, data, &count);
|
|
MultiAddInt(DMFC_VERSION_MINOR, data, &count);
|
|
|
|
SendPacket(data, count, pnum);
|
|
}
|
|
|
|
void DMFCBase::GetDMFCVersionCheck(uint8_t *data) {
|
|
int major, minor, count = 0;
|
|
|
|
major = MultiGetInt(data, &count);
|
|
minor = MultiGetInt(data, &count);
|
|
|
|
if ((major != DMFC_VERSION_MAJOR) || (minor != DMFC_VERSION_MINOR)) {
|
|
char buffer[200];
|
|
snprintf(buffer, sizeof(buffer), "Excpecting Version %d.%d, found %d.%d", major, minor, DMFC_VERSION_MAJOR,
|
|
DMFC_VERSION_MINOR);
|
|
FatalError(buffer);
|
|
}
|
|
}
|
|
|
|
// DMFCBase::SendRequestForPlayerRecords
|
|
//
|
|
//
|
|
// Sends a request to the server to send the player records
|
|
void DMFCBase::SendRequestForPlayerRecords(void) {
|
|
if (GetLocalRole() == LR_SERVER)
|
|
return;
|
|
int count = 0;
|
|
uint8_t data[MAX_GAME_DATA_SIZE];
|
|
StartPacket(data, SPID_PRECORDREQ, &count);
|
|
|
|
MultiAddByte(GetPlayerNum(), data, &count);
|
|
|
|
SendPacket(data, count, SP_SERVER);
|
|
}
|
|
|
|
// DMFCBase::ReceiveRequestForPlayerRecords
|
|
//
|
|
//
|
|
// Recieves and processes a request for a player record
|
|
void DMFCBase::ReceiveRequestForPlayerRecords(uint8_t *data) {
|
|
if (GetLocalRole() != LR_SERVER)
|
|
return;
|
|
int count = 0;
|
|
int pnum = MultiGetByte(data, &count);
|
|
PRec_SendPRecToPlayer(pnum);
|
|
|
|
// send the player his remote admin key
|
|
SendRemoteKey(pnum);
|
|
}
|
|
|
|
// DMFCBase::SendControlMessageToPlayer
|
|
//
|
|
//
|
|
// Sends a [1 byte] control message to a player
|
|
void DMFCBase::SendControlMessageToPlayer(int pnum, uint8_t msg) {
|
|
int count = 0;
|
|
uint8_t data[MAX_GAME_DATA_SIZE];
|
|
StartPacket(data, SPID_CONTROLMSG, &count);
|
|
|
|
MultiAddByte(msg, data, &count);
|
|
MultiAddByte(GetPlayerNum(), data, &count);
|
|
MultiAddByte(pnum, data, &count);
|
|
|
|
if (GetLocalRole() != LR_SERVER) {
|
|
// send it to the server to forward to a client
|
|
SendPacket(data, count, SP_SERVER);
|
|
} else
|
|
SendPacket(data, count, pnum);
|
|
}
|
|
|
|
// DMFCBase::ReceiveControlMessage
|
|
//
|
|
//
|
|
// Handles a control message
|
|
void DMFCBase::ReceiveControlMessage(uint8_t *data) {
|
|
int count = 0;
|
|
uint8_t msg = MultiGetByte(data, &count);
|
|
uint8_t src = MultiGetByte(data, &count);
|
|
uint8_t dst = MultiGetByte(data, &count);
|
|
|
|
if ((GetLocalRole() == LR_SERVER) && (dst != SP_SERVER || dst != GetPlayerNum())) {
|
|
// forward this packet to the correct player
|
|
uint8_t fdata[MAX_GAME_DATA_SIZE];
|
|
count = 0;
|
|
|
|
StartPacket(fdata, SPID_CONTROLMSG, &count);
|
|
MultiAddByte(msg, fdata, &count);
|
|
MultiAddByte(src, fdata, &count);
|
|
MultiAddByte(dst, fdata, &count);
|
|
SendPacket(fdata, count, dst);
|
|
} else {
|
|
// handle the packet
|
|
CallOnControlMessage(msg, src);
|
|
}
|
|
}
|
|
|
|
// DMFCBase::SendNetGameInfoSync
|
|
//
|
|
// Sends out a NetGame info sync packet to all the players
|
|
void DMFCBase::SendNetGameInfoSync(int to_who) {
|
|
if (GetLocalRole() != LR_SERVER)
|
|
return;
|
|
|
|
uint8_t data[MAX_GAME_DATA_SIZE];
|
|
int count = 0;
|
|
StartPacket(data, SPID_NETGAMESYNC, &count);
|
|
|
|
MultiAddByte(Netgame->packets_per_second, data, &count);
|
|
MultiAddByte((Netgame->flags & NF_KILLGOAL) ? 1 : 0, data, &count);
|
|
MultiAddByte((Netgame->flags & NF_TIMER) ? 1 : 0, data, &count);
|
|
|
|
MultiAddUshort(Netgame->timelimit, data, &count);
|
|
MultiAddUshort(Netgame->killgoal, data, &count);
|
|
MultiAddUshort(Netgame->respawn_time, data, &count);
|
|
MultiAddUshort(Netgame->max_players, data, &count);
|
|
|
|
SendPacket(data, count, to_who);
|
|
}
|
|
|
|
// DMFCBase::ReceiveNetGameInfoSync
|
|
//
|
|
// Receives a NetGame info sync packet from the server
|
|
void DMFCBase::ReceiveNetGameInfoSync(uint8_t *data) {
|
|
int count = 0;
|
|
|
|
Netgame->packets_per_second = MultiGetByte(data, &count);
|
|
if (MultiGetByte(data, &count))
|
|
Netgame->flags |= NF_KILLGOAL;
|
|
else
|
|
Netgame->flags &= ~NF_KILLGOAL;
|
|
if (MultiGetByte(data, &count))
|
|
Netgame->flags |= NF_TIMER;
|
|
else
|
|
Netgame->flags &= ~NF_TIMER;
|
|
|
|
Netgame->timelimit = MultiGetUshort(data, &count);
|
|
Netgame->killgoal = MultiGetUshort(data, &count);
|
|
Netgame->respawn_time = MultiGetUshort(data, &count);
|
|
Netgame->max_players = MultiGetUshort(data, &count);
|
|
}
|
|
|
|
// DMFCBase::SendNewTeamName
|
|
//
|
|
// Tells the clients about a team's new name
|
|
void DMFCBase::SendNewTeamName(int team) {
|
|
if (GetLocalRole() != LR_SERVER)
|
|
return;
|
|
|
|
int count = 0;
|
|
uint8_t data[MAX_GAME_DATA_SIZE];
|
|
StartPacket(data, SPID_NEWTEAMNAME, &count);
|
|
|
|
MultiAddByte(team, data, &count);
|
|
MultiAddString(DMFC_team_names[team], data, &count);
|
|
|
|
SendPacket(data, count, SP_ALL);
|
|
}
|
|
|
|
// DMFCBase::ReceiveNewTeamName
|
|
//
|
|
// The server is telling us about a new team name
|
|
void DMFCBase::ReceiveNewTeamName(uint8_t *data) {
|
|
int count = 0;
|
|
int team = MultiGetByte(data, &count);
|
|
|
|
ASSERT(team >= 0 && team < DLLMAX_TEAMS);
|
|
if (team < 0 || team >= DLLMAX_TEAMS)
|
|
return; // invalid team
|
|
|
|
char old_teamname[MAX_TEAMNAME_LEN];
|
|
strcpy(old_teamname, DMFC_team_names[team]);
|
|
|
|
MultiGetString(DMFC_team_names[team], data, &count);
|
|
|
|
CallOnTeamChangeName(team, old_teamname, DMFC_team_names[team]);
|
|
}
|