mirror of
https://github.com/1dot13/source.git
synced 2026-07-29 13:52:17 +02:00
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>
1234 lines
41 KiB
C++
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 f�r 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]);
|
|
}
|
|
}
|