Files
source/Multiplayer/server.cpp
T
42b947d470 give three temporaries a name before taking their address
Each of these takes the address of an object that has no name:

    bool b = client->Startup(1,30,&SocketDescriptor(), 1);
    OutputToStream(msg, &(SGP_LOG(s_log.id)));

MSVC allows it as an extension. The temporary lives to the end of the full
expression, which is past the call, so all three happen to work; clang rejects
the address-of outright.

Naming the object changes nothing about when it is built or what is passed,
only that the pointer now refers to something that outlives the statement.
MemMan.cpp already does this with the same logger call:

    sgp::Logger::LogInstance memLeak = SGP_LOG(log_id);

Verification:

    ninja -C build parse         # address-of-temporary class gone: 24 -> 21 sites
    ninja -C build -k 0          # Release, four applications, green
    ninja -C build-debug -k 0    # Debug, four applications, green

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:29:55 -03:00

1234 lines
41 KiB
C++

#include "MessageIdentifiers.h"
#include "RakNetworkFactory.h"
#include "RakPeerInterface.h"
#include "RakNetStatistics.h"
#include "RakNetTypes.h"
#include "FileListTransfer.h"
#include "FileListTransferCBInterface.h"
#include "FileOperations.h"
#include "SuperFastHash.h"
#include "RakAssert.h"
#include "IncrementalReadInterface.h"
#include "BitStream.h"
#include "RakSleep.h"
#include <assert.h>
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <list>
#include "connect.h"
#include "types.h"
#include "GameSettings.h"
#include "message.h"
#include "FileMan.h"
#include "INIReader.h"
#include <vfs/Core/vfs.h>
#include "transfer_rules.h"
#include "MPJoinScreen.h"
#include "Game Init.h"
#include "Text.h"
#include "network.h"
#include "message.h"
#include "Overhead.h"
#include "fresh_header.h"
#include "Debug Control.h"
#include "MPXmlTeams.hpp"
extern CHAR16 gzFileTransferDirectory[100];
// WANNE: FILE TRANSFER
unsigned int setID;
// Sender progress notification
class ServerFileListProgress : public FileListProgress
{
virtual void OnFilePush(const char *fileName, unsigned int fileLengthBytes, unsigned int offset, unsigned int bytesBeingSent, bool done, SystemAddress targetSystem)
{
// WANNE: Removed output in strategy log screen, because otherwise we do not see chat messages easily
/*
if (done)
{
char* filename = ExtractFilename((char*)fileName);
ScreenMsg( FONT_RED, MSG_MPSYSTEM, MPServerMessage[10], filename);
}
*/
}
char *ExtractFilename(char *pathname)
{
char *s;
if ((s=strrchr(pathname, '\\')) != NULL) s++;
else if ((s=strrchr(pathname, '/')) != NULL) s++;
else if ((s=strrchr(pathname, ':')) != NULL) s++;
else s = pathname;
return s;
}
} serverFileListProgress;
// ------------------------------
// Global Server Variables from ja2_mp.ini
// ------------------------------
char gKitBag[100];
UINT8 gMaxMercs;
UINT8 gDisableMorale;
UINT8 gReportHiredMerc;
UINT8 gDisableBobbyRay;
UINT8 gDisableMercEquipment;
UINT8 gSameMercAllowed;
float gDamageMultiplier;
UINT8 gMaxClients ;
UINT8 gGameType;
UINT8 gDifficultyLevel;
UINT8 gSkillTraits;
UINT8 gSyncGameDirectory;
INT32 gSecondsPerTick;
INT32 gStartingCash;
float gStartingTime;
UINT8 gWeaponReadyBonus;
UINT8 gInventoryAttachment;
UINT8 gDisableSpectatorMode;
UINT8 gMaxEnemiesEnabled;
// ------------------------------
UINT16 nc; //number of open connection
UINT16 ncr; //number of ready confirmed connections
//something keep record of ready connections ..
int mercs_ready[255];
unsigned char SGetPacketIdentifier(Packet *p);
unsigned char SpacketIdentifier;
RakPeerInterface *server;
// WANNE: FILE TRANSFER
FileListTransfer fltServer; // flt1
IncrementalReadInterface incrementalReadInterface;
FileList fileList;
// OJW - 20090405
long fileListTotalBytes=0;
int numreadyteams;
int readyteamreg[10];
bool Sawarded;
SystemAddress blank;
typedef struct
{
SystemAddress address;
int cl_number;
}client_data;
client_data client_d[4];
int client_mercteam[4] = { 0 , 1 , 2 , 3 }; // random index of random_merc_teams per player
bool inline can_joingame();
char *ReplaceCharactersInString_Server(char *str, char *orig, char *rep)
{
static char buffer[4096];
char *p;
if(!(p = strstr(str, orig))) // Is 'orig' even in 'str'?
return str;
strncpy(buffer, str, p-str); // Copy characters from 'str' start to 'orig' st$
buffer[p-str] = '\0';
sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig));
return buffer;
}
int f_rec_num(int mode, SystemAddress sender)//from client data
{
int x;
client_data cl_record;
for ( x=0; x<4;x++)
{
cl_record = client_d[x];
if(mode==0)//find empty slot for new record
{
if(cl_record.address.binaryAddress==0)
return(x);
}
if(mode==1)//wipe clean all
{
client_d[x].address.binaryAddress=0;
client_d[x].address.port=0;
client_d[x].cl_number=0;
}
if(mode==2)//clear one record
{
if(cl_record.address.binaryAddress==sender.binaryAddress && cl_record.address.port==sender.port)
{
client_d[x].address.port=0;
client_d[x].cl_number=0;
client_d[x].address.binaryAddress=0;
return(254);
}
}
// OJW - 090212 - look up client number
if (mode == 3)
{
if(cl_record.address.binaryAddress==sender.binaryAddress && cl_record.address.port==sender.port)
{
return (x);
}
}
}
if(mode == 0)//'no free slots'
{
ScreenMsg( FONT_RED, MSG_MPSYSTEM, L"Client Record Error, Restart Server, and Report Error." );
return (255);
}
return(254);
}
// use UNASSIGNED_SYSTEM_ADDRESS instead of rpcParameters->sender to send it back to yourself (the sender)
// there is very little in here dependant on the game engine and originally started out as an independant dedicated server .exe, and could if go ther again ... hayden.
//********* RPC SECTION ************
void sendPATH(RPCParameters *rpcParameters)
{
server->RPC("recievePATH",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
// OJW - 20090405
void sendDOWNLOADSTATUS(RPCParameters *rpcParameters)
{
server->RPC("recieveDOWNLOADSTATUS",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendSTANCE(RPCParameters *rpcParameters)
{
server->RPC("recieveSTANCE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendDIR(RPCParameters *rpcParameters)
{
server->RPC("recieveDIR",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendFIRE(RPCParameters *rpcParameters)
{
server->RPC("recieveFIRE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendHIT(RPCParameters *rpcParameters)
{
EV_S_WEAPONHIT* hit = (EV_S_WEAPONHIT*)rpcParameters->input;
int team = hit->ubAttackerID->bTeam;
// AI
if (team == 1)
team = 4;
// Client
else if (team >= 6)
team -= 6;
else if (team == 0)
team = CLIENT_NUM-1; // this case should not be possible, including as a precaution
Assert(team<5); // FIXME
gMPPlayerStats[team].hits++;
server->RPC("recieveHIT",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendDISMISS(RPCParameters *rpcParameters)
{
server->RPC("recieveDISMISS",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendHIRE(RPCParameters *rpcParameters)
{
server->RPC("recieveHIRE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendguiPOS(RPCParameters *rpcParameters)
{
server->RPC("recieveguiPOS",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendguiDIR(RPCParameters *rpcParameters)
{
server->RPC("recieveguiDIR",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendEndTurn(RPCParameters *rpcParameters)
{
server->RPC("recieveEndTurn",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendAI(RPCParameters *rpcParameters)
{
server->RPC("recieveAI",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendSTOP(RPCParameters *rpcParameters)
{
server->RPC("recieveSTOP",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendINTERRUPT(RPCParameters *rpcParameters)
{
server->RPC("recieveINTERRUPT",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendREADY(RPCParameters *rpcParameters)
{
server->RPC("recieveREADY",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendGUI(RPCParameters *rpcParameters)
{
server->RPC("recieveGUI",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendBULLET(RPCParameters *rpcParameters)
{
server->RPC("recieveBULLET",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendGRENADE(RPCParameters *rpcParameters)
{
server->RPC("recieveGRENADE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendGRENADERESULT(RPCParameters *rpcParameters)
{
server->RPC("recieveGRENADERESULT",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendPLANTEXPLOSIVE(RPCParameters *rpcParameters)
{
server->RPC("recievePLANTEXPLOSIVE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendDETONATEEXPLOSIVE(RPCParameters *rpcParameters)
{
server->RPC("recieveDETONATEEXPLOSIVE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendDISARMEXPLOSIVE(RPCParameters *rpcParameters)
{
server->RPC("recieveDISARMEXPLOSIVE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendSPREADEFFECT(RPCParameters *rpcParameters)
{
server->RPC("recieveSPREADEFFECT",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendNEWSMOKEEFFECT(RPCParameters *rpcParameters)
{
server->RPC("recieveNEWSMOKEEFFECT",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendEXPLOSIONDAMAGE(RPCParameters *rpcParameters)
{
server->RPC("recieveEXPLOSIONDAMAGE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendSTATE(RPCParameters *rpcParameters)
{
server->RPC("recieveSTATE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendDEATH(RPCParameters *rpcParameters)
{
// the master copy of the scoreboard is kept on the server
death_struct* nDeath = (death_struct*)rpcParameters->input;
// Save Stats on the server side
gMPPlayerStats[nDeath->soldier_team-1].deaths++;
gMPPlayerStats[nDeath->attacker_team-1].kills++;
// get the client number of the client sending the message
int iCLnum = f_rec_num(3,rpcParameters->sender)+1;
server->RPC("recieveDEATH",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
#ifdef JA2BETAVERSION
wchar_t ateam[5];
wchar_t steam[5];
wchar_t clnum[5];
_itow(nDeath->attacker_team,ateam,10);
_itow(nDeath->soldier_team,steam,10);
_itow(iCLnum,clnum,10);
ScreenMsg( FONT_LTBLUE, MSG_MPSYSTEM, L"DEBUG: Soldier Killed : Attacking team %s , Soldier Team %s, Sender %s",ateam,steam,clnum);
char logmsg[100];
sprintf( logmsg, "MP DEBUG: Soldier Killed #%i : Attacking team %i , Soldier Team %i, Sender %i\n", nDeath->soldier_id.i, nDeath->attacker_team, nDeath->soldier_team, iCLnum );
MPDebugMsg( logmsg );
#endif
}
void sendhitSTRUCT(RPCParameters *rpcParameters)
{
EV_S_STRUCTUREHIT* miss = (EV_S_STRUCTUREHIT*)rpcParameters->input;
if ( miss->ubAttackerID != NOBODY)
{
int team = miss->ubAttackerID->bTeam;
// AI
if (team == 1)
team = 4;
// Clients
else if (team >= 6)
team -= 6;
else if (team == 0)
team = CLIENT_NUM-1; // this case should not be possible, including as a precaution
Assert(team<5); // FIXME
gMPPlayerStats[team].misses++;
}
server->RPC("recievehitSTRUCT",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendhitWINDOW(RPCParameters *rpcParameters)
{
EV_S_WINDOWHIT* miss = (EV_S_WINDOWHIT*)rpcParameters->input;
if ( miss->ubAttackerID != NOBODY)
{
int team = miss->ubAttackerID->bTeam;
// AI
if (team == 1)
team = 4;
// Clients
else if (team >= 6)
team -= 6;
else if (team == 0)
team = CLIENT_NUM-1; // this case should not be possible, including as a precaution
Assert(team<5); // FIXME
gMPPlayerStats[team].misses++;
}
server->RPC("recievehitWINDOW",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendMISS(RPCParameters *rpcParameters)
{
EV_S_MISS* miss = (EV_S_MISS*)rpcParameters->input;
if ( miss->ubAttackerID != NOBODY)
{
int team = miss->ubAttackerID->bTeam;
// AI
if (team == 1)
team = 4;
// Clients
else if (team >= 6)
team -= 6;
else if (team == 0)
team = CLIENT_NUM-1; // this case should not be possible, including as a precaution
Assert(team<5); // FIXME
gMPPlayerStats[team].misses++;
}
server->RPC("recieveMISS",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void updatenetworksoldier(RPCParameters *rpcParameters)
{
server->RPC("UpdateSoldierFromNetwork",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void Snull_team(RPCParameters *rpcParameters)
{
server->RPC("null_team",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendFIREW(RPCParameters *rpcParameters)
{
server->RPC("recieve_fireweapon",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendDOOR(RPCParameters *rpcParameters)
{
server->RPC("recieve_door",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void endINTERRUPT(RPCParameters *rpcParameters)
{
server->RPC("resume_turn",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendWIPE(RPCParameters *rpcParameters)
{
server->RPC("recieve_wipe",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendHEAL(RPCParameters *rpcParameters)
{
server->RPC("recieve_heal",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
// OJW - edge and team changes
void sendEDGECHANGE(RPCParameters *rpcParameters)
{
server->RPC("recieveEDGECHANGE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendTEAMCHANGE(RPCParameters *rpcParameters)
{
server->RPC("recieveTEAMCHANGE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void requestSETID(SystemAddress addr)
{
server->RPC("requestSETID","", 0, HIGH_PRIORITY, RELIABLE, 0, addr, false, 0, UNASSIGNED_NETWORK_ID,0);
}
void receiveSETID(RPCParameters *rpcParameters)
{
setID = atoi((const char *)rpcParameters->input);
// WANNE: FILE TRANSFER: Send the files to the client
fltServer.Send(&fileList,server,rpcParameters->sender,setID,MEDIUM_PRIORITY,0,false, &incrementalReadInterface, 5000);
}
void startCOMBAT(RPCParameters *rpcParameters)
{
if(!( gTacticalStatus.uiFlags & INCOMBAT ))
{
gTacticalStatus.uiFlags |= INCOMBAT;
sc_struct* data = (sc_struct*)rpcParameters->input;
EndTurn( data->ubStartingTeam );
}
}
void sendREAL(RPCParameters *rpcParameters)
{
real_struct* rData = (real_struct*)rpcParameters->input;
if(readyteamreg[rData->bteam]==0)
{
readyteamreg[rData->bteam]=1;//register vote, to prevent double voting ;p~ //hayden
numreadyteams++;
int numactiveteams=0;
int b;
for(int i=6;i<=LAST_TEAM;i++)
{
if(i==6)
b=0;
else
b=i;
if(gTacticalStatus.Team[ b ].bTeamActive)
numactiveteams++;
}
//check # clients ready for realtime
if (numreadyteams >= numactiveteams)
{
//if all send notification for realtime changeover
//ScreenMsg( FONT_LTBLUE, MSG_MPSYSTEM, L"Switching to realtime..." );
numreadyteams=0;
memset( &readyteamreg , 0 , sizeof (int) * 10);
server->RPC("gotoRT",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0);
}
}
}
// 20081222 - OJW
void sendGAMEOVER(RPCParameters *rpcParameters)
{
// ignore the RPCParams and send the server side scoreboard
server->RPC("recieveGAMEOVER",(const char*)gMPPlayerStats, sizeof(gMPPlayerStats)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0);
}
void sendCHATMSG(RPCParameters *rpcParameters)
{
// ignore the RPCParams and send the server side scoreboard
server->RPC("recieveCHATMSG",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0);
}
// OJW - 20081223
// fix client disconnecting mid game, allowing the game to proceed
void HandleDisconnect(SystemAddress sender)
{
// find the CLIENT_NUM of the player
int x;
client_data cl_record;
for ( x=0; x<4;x++)
{
cl_record = client_d[x];
if(cl_record.address.binaryAddress==sender.binaryAddress && cl_record.address.port==sender.port)
{
// notify all the clients of the disconnect
server->RPC("recieveDISCONNECT",(const char*)&cl_record.cl_number , sizeof(int)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0);
f_rec_num(2,sender); // remove from server's client list
break;
}
}
}
// OJW - 20081218
// shuffle an integer array
//<TODO> remove shuffledList and put directly into arr[]
void rSortArray(int* arr, int len)
{
std::list<int> tmpList;
std::list<int> shuffledList;
std::list<int>::iterator Iter;
int i=0;
// add all our array items
for(i=0; i<len; i++)
tmpList.push_front(arr[i]);
// shuffle the items
while(tmpList.size())
{
int iRandPos = rand() % tmpList.size();
for(Iter = tmpList.begin(); iRandPos>0; iRandPos--, Iter++);
shuffledList.push_front(*Iter);
tmpList.erase(Iter);
}
// add all our elements
for(i=0; i<len; i++)
{
arr[i] = shuffledList.back();
shuffledList.pop_back();
}
}
// WANNE: FILE TRANSFER: Send all the settings the client needs to know for the file transfer before file transfer starts
void requestFILE_TRANSFER_SETTINGS(RPCParameters *rpcParameters)
{
SystemAddress sender = rpcParameters->sender;//get senders address
filetransfersettings_struct fts;
fts.syncClientsDirectory = gSyncGameDirectory;
strcpy(fts.fileTransferDirectory, s_ServerId.getServerId(vfs::Path(gzFileTransferDirectory)).utf8().c_str());
strcpy(fts.serverName, cServerName);
fts.totalTransferBytes = fileListTotalBytes;
// OJW - 200907819 - Only send to the client that asked for it
server->RPC("recieveFILE_TRANSFER_SETTINGS",(const char*)&fts, (int)sizeof(filetransfersettings_struct)*8, HIGH_PRIORITY, RELIABLE, 0, sender, false, 0, UNASSIGNED_NETWORK_ID,0);
}
//************************* //UNASSIGNED_SYSTEM_ADDRESS
//START INTERNAL SERVER
//*************************
//void send_settings (void)//send server settings to client
void requestSETTINGS(RPCParameters *rpcParameters )
{
// dont generate or send settings to a new user if they are about to be disconnected
// because no more players can join the the game
if (can_joingame())
{
client_info* clinf = (client_info*)rpcParameters->input;
// OJW - 20090507
// Disconnect if version is wrong
if (strcmp(clinf->client_version,MPVERSION)!=0)
{
CHAR16 verErrMsg[255];
swprintf(verErrMsg,255, MPClientMessage[66], clinf->client_version,MPVERSION);
// send disconnect reason only to this client
server->RPC("recieveDISCONNECTREASON",(const char*)&verErrMsg, (int)sizeof(CHAR16)*255*8, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, false, 0, UNASSIGNED_NETWORK_ID,0);
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, L"CONNECTION REJECTED - CLIENT HAS WRONG VERSION");
// disconnect this client
server->CloseConnection(rpcParameters->sender, true);
return;
}
//server assigned client numbers - hayden.
SystemAddress sender = rpcParameters->sender;//get senders address
int bslot = f_rec_num(0,blank);//get empty record slot
client_d[bslot].address=sender; //record clients address
int new_cl_num = bslot+1;//client number to assign
client_d[bslot].cl_number=new_cl_num; //record clients number
settings_struct lan;
lan.client_num = new_cl_num; //new server assigned number
strcpy(lan.client_name , clinf->client_name);
lan.randomStartingEdge = gRandomStartingEdge;
lan.randomMercs = gRandomMercs;
lan.maxClients = gMaxClients;
memcpy(lan.kitBag , gKitBag,sizeof (char)*100);
lan.damageMultiplier = gDamageMultiplier;
lan.sameMercAllowed = gSameMercAllowed;
lan.gsMercArriveSectorX = gsMercArriveSectorX;
lan.gsMercArriveSectorY = gsMercArriveSectorY;
lan.enemyEnabled = gEnemyEnabled;
lan.creatureEnabled = gCreatureEnabled;
lan.militiaEnabled = gMilitiaEnabled;
lan.civEnabled = gCivEnabled;
lan.gameType = gGameType;
lan.disableMorale = gDisableMorale;
lan.reportHiredMerc = gReportHiredMerc;
lan.secondsPerTick = gSecondsPerTick;
// WANNE.MP: Check
lan.soubBobbyRayQuality = BR_AWESOME;
lan.soubBobbyRayQuantity = BR_AWESOME;
lan.sofGunNut = TRUE;
lan.soubGameStyle = STYLE_REALISTIC;
lan.soubDifficultyLevel = gDifficultyLevel;
lan.soubSkillTraits = gSkillTraits;
lan.sofTurnTimeLimit = TRUE;
lan.sofIronManMode = FALSE;
lan.startingCash = gStartingCash;
// Old/Old
if (gInventoryAttachment == INVENTORY_OLD)
{
lan.inventoryAttachment = 0;
}
else
{
// New/Old
if (gGameOptions.ubAttachmentSystem == ATTACHMENT_OLD)
{
lan.inventoryAttachment = 1; // New/Old
}
// New/New
else
{
lan.inventoryAttachment = 2; // New/New
}
}
lan.disableBobbyRay=gDisableBobbyRay;
lan.disableMercEquipment=gDisableMercEquipment;
lan.maxMercs = gMaxMercs;
memcpy( lan.client_names , client_names, sizeof( char ) * 4 * 30 );
lan.team=clinf->team;
// OJW - 20090530 - fix teams not initialised properly
client_teams[ lan.client_num - 1 ] = lan.team;
// OJW - 20081218
if (gRandomStartingEdge)
{
// Get the edge from the randomized "client_edges"
lan.startingSectorEdge = client_edges[lan.client_num-1];
}
else
{
// WANNE: on DM, each client should get a unique starting edge per default
if (gGameType == MP_TYPE_DEATHMATCH || gGameType == MP_TYPE_TEAMDEATMATCH)
{
client_edges[0] = MP_EDGE_NORTH; // client 1
client_edges[1] = MP_EDGE_SOUTH; // client 2
client_edges[2] = MP_EDGE_EAST; // client 3
client_edges[3] = MP_EDGE_WEST; // client 4
lan.startingSectorEdge = client_edges[lan.client_num-1];
}
else
{
lan.startingSectorEdge=clinf->cl_edge;
}
}
// OJW - 20081223
if (gRandomMercs)
{
mpTeams.SerializeProfiles(lan.random_mercs);
}
lan.startingTime = gStartingTime;
lan.weaponReadyBonus = gWeaponReadyBonus;
lan.inventoryAttachment = gInventoryAttachment;
lan.disableSpectatorMode = gDisableSpectatorMode;
// OJW - 20081204
strcpy(lan.server_name , cServerName);
memcpy(lan.client_edges,client_edges,sizeof(int)*5);
memcpy(lan.client_teams,client_teams,sizeof(int)*4);
// OJW - 20091024 - send servers random table
memcpy(lan.random_table,guiPreRandomNums,sizeof(UINT32)*MAX_PREGENERATED_NUMS);
// OJW - 20090507
// send server version to client
strcpy(lan.server_version,MPVERSION);
server->RPC("recieveSETTINGS",(const char*)&lan, (int)sizeof(settings_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0);
// WANNE: FILE TRANSFER: A client connected -> start the file transfer!
if (gSyncGameDirectory)
requestSETID(rpcParameters->sender);
}
}
// added 081201 by Owen , allow the server to change the map while its still not in laptop mode
void send_mapchange(void)
{
if (is_server && !allowlaptop)
{
mapchange_struct lan;
lan.gsMercArriveSectorX=gsMercArriveSectorX;
lan.gsMercArriveSectorY=gsMercArriveSectorY;
lan.startingTime = gStartingTime;
server->RPC("recieveMAPCHANGE",(const char*)&lan, (int)sizeof(mapchange_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0);
}
else
{
ScreenMsg( FONT_LTBLUE, MSG_MPSYSTEM, MPServerMessage[45]);
}
}
// OJW 090212
bool inline can_joingame()
{
return !allowlaptop;
}
// Allow server to disconnect incoming clients after the game has started
void CheckIncomingConnection(Packet* p)
{
// some clients might reconnect after disconnecting, either after the laptop is unlocked
// or after the game has started
// we dont want to allow this as thier game will be out of state
if (!can_joingame())
{
ScreenMsg( FONT_LTBLUE, MSG_MPSYSTEM, L"CONNECTION REJECTED - GAME HAS STARTED");
// disconnect this client, no need to notify them as they will know if they disconnected
// before receiving a settings packet that they were not allowed to join
server->CloseConnection(p->systemAddress, true);
}
}
void AddFilesToSendList()
{
// we cannot just iterate over "*/*" as we would get ALL files and we don't want to send all files
// instead we only iterate over the files in the "_MULTIPLAYER" profile
vfs::CProfileStack *PS = getVFS()->getProfileStack();
vfs::CVirtualProfile *prof = PS->getProfile("_MULTIPLAYER");
if(prof != PS->topProfile())
{
// there is not supposed to be another profile?
// output error message
return;
}
CTransferRules transferRules;
transferRules.initFromTxtFile("transfer_rules.txt");
vfs::IBaseLocation* loc = prof->getLocation("");
SGP_THROW_IFFALSE(loc != NULL, "MP profile was successfully created, but the root directory is not included");
vfs::IBaseLocation::Iterator it = loc->begin();
int i=0;
for(; !it.end(); it.next(), i++)
{
vfs::Path const& valid_path = it.value()->getPath();
if(transferRules.applyRule(valid_path()) == CTransferRules::ACCEPT)
{
// transfer only those files that are not on the ignore list
vfs::tReadableFile* rfile = vfs::tReadableFile::cast(it.value());
if(!rfile)
{
continue;
}
vfs::size_t fsize = rfile->getSize();
fileListTotalBytes += (long)fsize;
if( (fsize>0) && rfile->openRead())
{
std::vector<vfs::Byte> data(fsize,0);
rfile->read(&data[0], fsize);
rfile->close();
fileList.AddFile(vfs::String::as_utf8(valid_path()).c_str(),&data[0], fsize,fsize,FileListNodeContext(0,0), false);
}
}
}
}
void start_server (void)
{
if(!is_server)
{
f_rec_num(1,blank);//wipe clean
// ----------------------------
// Read from ja2_mp.ini
// ----------------------------
CIniReader iniReader(JA2MP_INI_FILENAME); // Wird nur fr Strings gebraucht
strncpy(cServerName, iniReader.ReadString(JA2MP_INI_INITIAL_SECTION, JA2MP_SERVER_NAME, "My JA2 Server"), 30 );
strncpy(gKitBag, iniReader.ReadString(JA2MP_INI_INITIAL_SECTION,JA2MP_KIT_BAG, ""), 100);
vfs::PropertyContainer props;
props.initFromIniFile(JA2MP_INI_FILENAME);
UINT16 serverPort = (UINT16)props.getIntProperty(JA2MP_INI_INITIAL_SECTION, JA2MP_SERVER_PORT, 60005);
UINT8 maxClients = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION,JA2MP_MAX_CLIENTS, 4);
UINT8 sameMercAllowed = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION,JA2MP_SAME_MERC, 1);
UINT8 civEnabled = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION,JA2MP_CIV_ENABLED, 0);
UINT8 gameType = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION,JA2MP_GAME_MODE, 0);
UINT8 difficultyLevel = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION,JA2MP_DIFFICULT_LEVEL, 3);
UINT8 skillTraits = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION,JA2MP_NEW_TRAITS, 0);
UINT8 randomMercs = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION,JA2MP_RANDOM_MERCS, 0);
UINT8 randomStartingEdge = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION, JA2MP_RANDOM_EDGES, 0);
UINT8 damageSelection = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION, JA2MP_DAMAGE_MULTIPLIER, 1);
UINT8 maxEnemiesEnabled = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION, JA2MP_OVERRIDE_MAX_AI, 0);
UINT8 syncGameDirectory = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION, JA2MP_SYNC_CLIENTS_MP_DIR, 1);
UINT8 reportHiredMerc = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION, JA2MP_REPORT_NAME, 1);
UINT8 startingCashSelection = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION, JA2MP_STARTING_BALANCE, 25000);
UINT8 timeTurnsSelection = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION, JA2MP_TIMED_TURN_SECS_PER_TICK, 2);
UINT8 disableBobbyRay = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION, JA2MP_DISABLE_BOBBY_RAYS, 0);
UINT8 maxMercs = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION, JA2MP_MAX_MERCS, 6);
UINT8 timeSelection = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION, JA2MP_TIME, 1);
UINT8 inventoryAttachment = (UINT8)props.getIntProperty(JA2MP_INI_INITIAL_SECTION, JA2MP_ALLOW_CUSTOM_NIV, 0);
// ----------------------------
// Save to global values
// ----------------------------
gMaxClients = maxClients;
gMaxEnemiesEnabled = 0;
gDisableMorale = 0;
gSyncGameDirectory = syncGameDirectory;
gReportHiredMerc = reportHiredMerc;
gDisableBobbyRay = disableBobbyRay;
gDisableMercEquipment = 0; // Disable AIM and MERC equipment
gMaxMercs = maxMercs;
gGameType = gameType;
gDifficultyLevel = difficultyLevel + 1;
gSkillTraits = skillTraits;
gEnemyEnabled = 0;
gCreatureEnabled = 0;
gMilitiaEnabled = 0;
gCivEnabled = 0;
gRandomMercs = randomMercs;
gRandomStartingEdge = randomStartingEdge;
gWeaponReadyBonus = 0;
gDisableSpectatorMode = 0;
gInventoryAttachment = inventoryAttachment;
if (gRandomStartingEdge)
{
// create random starting edges
int spawns[5] = { 0 , 1 , 2 , 3, 9 }; // 9 == Center
// Randomize spawns
rSortArray(spawns,5);
memcpy(client_edges,spawns,sizeof(int)*5);
}
if (gRandomMercs)
{
// randomly sort team indexes to give client
// one of four random merc teams
rSortArray(client_mercteam,4);
mpTeams.HandleServerStarted();
}
if(gGameType == MP_TYPE_COOP)//only enable ai during coop
{
gEnemyEnabled = 1; // always enable enemies in co-op
gMilitiaEnabled = 0; // always disable militia
gCivEnabled = civEnabled;
gMaxEnemiesEnabled = maxEnemiesEnabled;
}
// random_mercs implies same_merc
gSameMercAllowed = gRandomMercs ? 1 : sameMercAllowed;
switch (damageSelection)
{
case 0: // Very Low
gDamageMultiplier = 0.2f;
break;
case 1: // Low
gDamageMultiplier = 0.7f;
break;
case 2: // Normal
gDamageMultiplier = 1.0f;
break;
}
switch (timeTurnsSelection)
{
case 0: // Never
gSecondsPerTick = 0;
break;
case 1: // Slow
gSecondsPerTick = 5;
break;
case 2: // Medium
gSecondsPerTick = 100;
break;
case 3: // Fast
gSecondsPerTick = 400;
break;
}
switch (startingCashSelection)
{
case 0: // Low
gStartingCash = 5000;
break;
case 1: // Medium
gStartingCash = 50000;
break;
case 2: // High
gStartingCash = 100000;
break;
case 3: // Unlimited
gStartingCash = 999999999;
break;
}
switch (timeSelection)
{
case 0: // Morning
gStartingTime = 7.00f;
break;
case 1: // Afternoon
gStartingTime = 13.00f;
break;
case 2: // Night
gStartingTime = 2.00;
break;
}
//**********************
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, MPServerMessage[0] );
server=RakNetworkFactory::GetRakPeerInterface();
// WANNE: Set higher timeout than default (30 seconds)
server->SetTimeoutTime(120000, UNASSIGNED_SYSTEM_ADDRESS); // 120 Seconds
SocketDescriptor socketDescriptor(serverPort,0);
bool b = server->Startup(gMaxClients, 30, &socketDescriptor, 1);
server->SetMaximumIncomingConnections((gMaxClients));
server->SetOccasionalPing(true);
//RPC's
REGISTER_STATIC_RPC(server, sendPATH);
REGISTER_STATIC_RPC(server, sendDOWNLOADSTATUS);
REGISTER_STATIC_RPC(server, sendSTANCE);
REGISTER_STATIC_RPC(server, sendDIR);
REGISTER_STATIC_RPC(server, sendFIRE);
REGISTER_STATIC_RPC(server, sendHIT);
REGISTER_STATIC_RPC(server, sendHIRE);
REGISTER_STATIC_RPC(server, sendDISMISS);
REGISTER_STATIC_RPC(server, sendguiPOS);
REGISTER_STATIC_RPC(server, sendguiDIR);
REGISTER_STATIC_RPC(server, sendEndTurn);
REGISTER_STATIC_RPC(server, sendAI);
REGISTER_STATIC_RPC(server, sendSTOP);
REGISTER_STATIC_RPC(server, sendINTERRUPT);
REGISTER_STATIC_RPC(server, sendREADY);
REGISTER_STATIC_RPC(server, sendGUI);
REGISTER_STATIC_RPC(server, sendBULLET);
REGISTER_STATIC_RPC(server, sendGRENADE);
REGISTER_STATIC_RPC(server, sendGRENADERESULT);
REGISTER_STATIC_RPC(server, sendPLANTEXPLOSIVE);
REGISTER_STATIC_RPC(server, sendDETONATEEXPLOSIVE);
REGISTER_STATIC_RPC(server, sendDISARMEXPLOSIVE);
REGISTER_STATIC_RPC(server, sendSPREADEFFECT);
REGISTER_STATIC_RPC(server, sendNEWSMOKEEFFECT);
REGISTER_STATIC_RPC(server, sendEXPLOSIONDAMAGE);
REGISTER_STATIC_RPC(server, requestSETTINGS);
REGISTER_STATIC_RPC(server, requestFILE_TRANSFER_SETTINGS);
REGISTER_STATIC_RPC(server, sendSTATE);
REGISTER_STATIC_RPC(server, sendDEATH);
REGISTER_STATIC_RPC(server, sendhitSTRUCT);
REGISTER_STATIC_RPC(server, sendhitWINDOW);
REGISTER_STATIC_RPC(server, sendMISS);
REGISTER_STATIC_RPC(server, updatenetworksoldier);
REGISTER_STATIC_RPC(server, Snull_team);
REGISTER_STATIC_RPC(server, sendFIREW);
REGISTER_STATIC_RPC(server, sendDOOR);
REGISTER_STATIC_RPC(server, endINTERRUPT);
REGISTER_STATIC_RPC(server, sendREAL);
REGISTER_STATIC_RPC(server, startCOMBAT);
REGISTER_STATIC_RPC(server, sendWIPE);
REGISTER_STATIC_RPC(server, sendHEAL);
REGISTER_STATIC_RPC(server, sendEDGECHANGE);
REGISTER_STATIC_RPC(server, sendTEAMCHANGE);
REGISTER_STATIC_RPC(server, sendGAMEOVER);
REGISTER_STATIC_RPC(server, sendCHATMSG);
REGISTER_STATIC_RPC(server, receiveSETID);
if (b)
{
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, MPServerMessage[1]);
is_server = true;
// WANNE: FILE TRANSFER
server->AttachPlugin(&fltServer);
server->SetSplitMessageProgressInterval(1);
fltServer.SetCallback(&serverFileListProgress);
fileListTotalBytes=0;
if (gSyncGameDirectory == 1)
{
AddFilesToSendList();
}
connect_client();//connect client to server
}
else
{
ScreenMsg( FONT_LTBLUE, MSG_MPSYSTEM, MPServerMessage[4]);
}
}
else
{
ScreenMsg( FONT_LTBLUE, MSG_MPSYSTEM, MPServerMessage[3]);
}
}
// recieve and process server info packets
void server_packet ( void )
{
Packet* p;
if (is_server)
{
p = server->Receive();
while(p)
{
//continue; // Didn't get any packets
// We got a packet, get the identifier with our handy function
SpacketIdentifier = SGetPacketIdentifier(p);
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"packet recieved");
// Check if this is a network message packet
switch (SpacketIdentifier)
{
case ID_DISCONNECTION_NOTIFICATION://client disconnected purposefullly
// Connection lost normally
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, L"ID_DISCONNECTION_NOTIFICATION");
HandleDisconnect(p->systemAddress);//clear record
break;
case ID_ALREADY_CONNECTED:
// Connection lost normally
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, L"ID_ALREADY_CONNECTED");
break;
case ID_REMOTE_DISCONNECTION_NOTIFICATION: // Server telling the clients of another client disconnecting gracefully. You can manually broadcast this in a peer to peer enviroment if you want.
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, L"ID_REMOTE_DISCONNECTION_NOTIFICATION");
break;
case ID_REMOTE_CONNECTION_LOST: // Server telling the clients of another client disconnecting forcefully. You can manually broadcast this in a peer to peer enviroment if you want.
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, L"ID_REMOTE_CONNECTION_LOST");
break;
case ID_REMOTE_NEW_INCOMING_CONNECTION: // Server telling the clients of another client connecting. You can manually broadcast this in a peer to peer enviroment if you want.
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, L"ID_REMOT/MING_CONNECTION");
break;
case ID_CONNECTION_ATTEMPT_FAILED:
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, L"ID_CONNECTION_ATTEMPT_FAILED");
break;
case ID_NO_FREE_INCOMING_CONNECTIONS:
// Sorry, the server is full. I don't do anything here but
// A real app should tell the user
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, L"ID_NO_FREE_INCOMING_CONNECTIONS");
break;
case ID_CONNECTION_LOST:
// Couldn't deliver a reliable packet - i.e. the other system was abnormally
// terminated
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, L"ID_CONNECTION_LOST");//client dropped
HandleDisconnect(p->systemAddress);//clear record
break;
case ID_CONNECTION_REQUEST_ACCEPTED:
// This tells the client they have connected
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, L"ID_CONNECTION_REQUEST_ACCEPTED");
break;
case ID_NEW_INCOMING_CONNECTION:
//tells server client has connected
#ifdef JA2BETAVERSION
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, L"ID_NEW_INCOMING_CONNECTION");
#endif
// make sure they can connect
CheckIncomingConnection(p);
//send_settings();//send off server set settings
break;
case ID_MODIFIED_PACKET:
// Cheater!
#ifdef JA2BETAVERSION
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, L"ID_MODIFIED_PACKET");
#endif
break;
default:
#ifdef JA2BETAVERSION
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, L"** a packet has been recieved for which i dont know what to do... **");
#endif
break;
}
// We're done with the packet, get more :)
server->DeallocatePacket(p);
p = server->Receive();
}
}
}
// Copied from Multiplayer.cpp
// If the first byte is ID_TIMESTAMP, then we want the 5th byte
// Otherwise we want the 1st byte
unsigned char SGetPacketIdentifier(Packet *p)
{
if (p==0)
return 255;
if ((unsigned char)p->data[0] == ID_TIMESTAMP)
{
assert(p->length > sizeof(unsigned char) + sizeof(unsigned long));
return (unsigned char) p->data[sizeof(unsigned char) + sizeof(unsigned long)];
}
else
return (unsigned char) p->data[0];
}
void server_disconnect (void)
{
if(is_server)
{
server->DetachPlugin(&fltServer);
server->Shutdown(300);
is_server = false;
fileList.Clear();
// We're done with the network
RakNetworkFactory::DestroyRakPeerInterface(server);
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, MPServerMessage[6]);
}
else
{
ScreenMsg( FONT_ORANGE, MSG_MPSYSTEM, MPServerMessage[7]);
}
}