Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
1991 lines
56 KiB
C++
1991 lines
56 KiB
C++
CMRPFull g_MRF;
|
|
extern DPSESSIONDESC2 CurrentSession;
|
|
extern DWORD MyDirectPlayID;
|
|
extern bool IAmTheServer;
|
|
extern bool InNetworkGame;
|
|
extern char GameNameBuffer[];
|
|
extern char PasswordBuffer[];
|
|
extern DWORD gInSecureGame;
|
|
extern ListOfNames* CurrentPlayers;
|
|
extern char *LocalIPAddress; // extern SCRIPTVAR_STR(LocalIPAddress);
|
|
|
|
extern int ConnectionIndex;
|
|
|
|
DWORD g_dwMR_Meta = 0xab9a655f;
|
|
DWORD g_dwMR_MetaOldA = 0xab9a654f;
|
|
|
|
bool g_bMRTest = false;
|
|
const char* g_pcszGameDataExtMR = ".mr";
|
|
|
|
#if !defined(SCRIPTCALLBACK)
|
|
#define SCRIPTCALLBACK(func) int __stdcall func( void * instance, int args, void * arg[])
|
|
#endif // !defined(SCRIPTCALLBACK)
|
|
|
|
#if !defined(FREE_PTR)
|
|
#define FREE_PTR(ptr) if ((void *)ptr) { gos_Free((void *)ptr); (ptr)=NULL; }
|
|
#endif // !defined(FREE_PTR)
|
|
|
|
extern bool g_bCOOP; // COin OPeration
|
|
|
|
extern void RegisterData(void);
|
|
extern void UnRegisterData(void);
|
|
extern SCRIPTCALLBACK(CancelDialup);
|
|
extern SCRIPTCALLBACK(PreConnect);
|
|
extern SCRIPTCALLBACK(LoadMPConnectionSettings);
|
|
extern SCRIPTCALLBACK(InitConnectionWizard);
|
|
|
|
extern void _stdcall gos_RealRemovePlayerFromGame( ListOfNames** pListOfPlayers, char* Name, DPID dpId );
|
|
extern void _stdcall gos_RealAddPlayerToGame( ListOfNames** pListOfPlayers, char* Name, DPID dpId );
|
|
|
|
extern void _stdcall CTCL_SetMissionParamsBy(void* pNMP, int nSize);
|
|
|
|
void __stdcall MRP_OnGameOpen(const char* pcszGameName, DWORD dwMyID, const char* pcszPlayer, const char* pcszPassword);
|
|
void __stdcall NET_AddPlayerToGame(void/*ListOfNames*/** pListOfPlayers, char* Name, DPID dpId);
|
|
void __stdcall NET_RemovePlayerFromGame(void/*ListOfNames*/** pListOfPlayers, char* Name, DPID dpId);
|
|
void __stdcall NET_AddRemoveConnection(bool bAdd, void* pConnection);
|
|
void __stdcall NET_SessionLost();
|
|
|
|
void* __stdcall MRP_NetInformation(gosNetInfo Info, DWORD Parameter, char* Name);
|
|
void __stdcall MRP_NetServerCommands(gos_NetCommands Command, DWORD Data1);
|
|
NetPacket* __stdcall MRP_NETGETMESSAGE();
|
|
bool _stdcall MRP_LOCALSENDNETMESSAGE(int message_type, void/*Stuff::MemoryStream*/* message);
|
|
void __stdcall MRP_BACKGROUNDTACK();
|
|
bool __stdcall MRP_NETSENDMESSAGE(NetPacket* Message);
|
|
|
|
#define STRING_SIZE 256
|
|
|
|
void _inline AllocString(char * &sptr)
|
|
{
|
|
sptr = (char *)gos_Malloc(STRING_SIZE);
|
|
sptr[0] = 0;
|
|
}
|
|
|
|
void _inline FreeString(char * &sptr)
|
|
{
|
|
FREE_PTR(sptr);
|
|
}
|
|
|
|
void __stdcall MRP_OnGameOpen(const char* pcszGameName, DWORD dwMyID, const char* pcszPlayer, const char* pcszPassword)
|
|
{
|
|
g_MRF.OnGameOpen(pcszGameName, dwMyID, pcszPlayer, pcszPassword);
|
|
}
|
|
|
|
void __stdcall NET_AddPlayerToGame(void/*ListOfNames*/** pListOfPlayers, char* Name, DPID dpId)
|
|
{
|
|
g_MRF.AddRemovePlayerToGame(MRP_ADD_PLAYER_NAME, Name, dpId);
|
|
}
|
|
|
|
void __stdcall NET_RemovePlayerFromGame(void/*ListOfNames*/** pListOfPlayers, char* Name, DPID dpId)
|
|
{
|
|
g_MRF.AddRemovePlayerToGame(MRP_REMOVE_PLAYER_NAME, Name, dpId);
|
|
}
|
|
|
|
void __stdcall NET_AddRemoveConnection(bool bAdd, void* pConnection)
|
|
{
|
|
g_MRF.AddRemoveConnection(bAdd, (Connection*)pConnection);
|
|
}
|
|
|
|
void __stdcall NET_SessionLost()
|
|
{
|
|
g_MRF.SessionLost();
|
|
}
|
|
|
|
void* __stdcall MRP_NetInformation(gosNetInfo Info, DWORD Parameter, char* Name)
|
|
{
|
|
return g_MRF.NetInformation(Info, Parameter, Name);
|
|
}
|
|
|
|
void __stdcall MRP_NetServerCommands(gos_NetCommands Command, DWORD Data1)
|
|
{
|
|
g_MRF.NetServerCommands(Command, Data1);
|
|
}
|
|
|
|
NetPacket* __stdcall MRP_NETGETMESSAGE()
|
|
{
|
|
return g_MRF.NetGetMessage();
|
|
}
|
|
|
|
bool _stdcall MRP_LOCALSENDNETMESSAGE(int message_type, void/*Stuff::MemoryStream*/* message)
|
|
{
|
|
return g_MRF.LocalSendNetMessage(message_type, *(Stuff::MemoryStream*)message);
|
|
}
|
|
|
|
void __stdcall MRP_BACKGROUNDTACK()
|
|
{
|
|
g_MRF.BackgroundTack();
|
|
}
|
|
|
|
bool __stdcall MRP_NETSENDMESSAGE(NetPacket* Message)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
int SMRP::GetMemSize() const
|
|
{
|
|
return sizeof(SMRP) + m_nLen;
|
|
}
|
|
|
|
CMRPPack* AllocMRPPack(int nCount, PMRP* ppMRP)
|
|
{
|
|
CMRPPack* pMRPPack = (CMRPPack*)malloc(sizeof(CMRPPack) + sizeof(PMRP) * nCount);
|
|
pMRPPack->Construct(nCount, ppMRP);
|
|
|
|
return pMRPPack;
|
|
}
|
|
|
|
void FreeMRPPack(CMRPPack* pMRPPack)
|
|
{
|
|
if (pMRPPack) {
|
|
pMRPPack->Destruct();
|
|
free(pMRPPack);
|
|
}
|
|
}
|
|
|
|
void CMRPPack::Construct(int nCount, PMRP* ppMRP)
|
|
{
|
|
m_pPrev = NULL;
|
|
m_pNext = NULL;
|
|
m_fFrameTime = 0.0f;
|
|
m_nCount = nCount;
|
|
if (ppMRP)
|
|
memcpy(&m_pa[0], ppMRP, sizeof(PMRP) * nCount);
|
|
}
|
|
|
|
void CMRPPack::Destruct()
|
|
{
|
|
PMRP* ppStart = &m_pa[0];
|
|
PMRP* ppEnd = &m_pa[m_nCount];
|
|
while(ppEnd-- > ppStart) {
|
|
free(*ppEnd);
|
|
}
|
|
}
|
|
|
|
int CMRPPack::GetMemSize() const
|
|
{
|
|
int nSize = sizeof(CMRPPack);
|
|
for(int i = 0; i < m_nCount; i++) {
|
|
nSize += m_pa[i]->GetMemSize();
|
|
}
|
|
|
|
return nSize;
|
|
}
|
|
|
|
void CMRPPack::Save(Stuff::DynamicMemoryStream& mf)
|
|
{
|
|
mf.WriteBytes(&m_fFrameTime, sizeof(m_fFrameTime));
|
|
for(int i = 0; i < m_nCount; i++) {
|
|
PMRP pMRP = m_pa[i];
|
|
mf.WriteBytes(&pMRP->m_nCommand, sizeof(pMRP->m_nCommand));
|
|
mf.WriteBytes(&pMRP->m_nType, sizeof(pMRP->m_nType));
|
|
mf.WriteBytes(&pMRP->m_nLen, sizeof(pMRP->m_nLen));
|
|
mf.WriteBytes(pMRP->m_ba, pMRP->m_nLen);
|
|
}
|
|
}
|
|
|
|
void CMRPPack::Load(Stuff::MemoryStream& mf, DWORD dwMeta)
|
|
{
|
|
if (dwMeta != g_dwMR_MetaOldA) {
|
|
mf.ReadBytes(&m_fFrameTime, sizeof(m_fFrameTime));
|
|
}
|
|
for(int i = 0; i < m_nCount; i++) {
|
|
int nCommand;
|
|
int nType;
|
|
int nLen;
|
|
mf.ReadBytes(&nCommand, sizeof(nCommand));
|
|
mf.ReadBytes(&nType, sizeof(nType));
|
|
mf.ReadBytes(&nLen, sizeof(nLen));
|
|
PMRP pMRP = (PMRP)malloc(sizeof(SMRP) + nLen);
|
|
pMRP->m_nCommand = nCommand;
|
|
pMRP->m_nType = nType;
|
|
pMRP->m_nLen = nLen;
|
|
mf.ReadBytes(pMRP->m_ba, nLen);
|
|
m_pa[i] = pMRP;
|
|
}
|
|
}
|
|
|
|
CMRPPlayer::CMRPPlayer()
|
|
: m_pPrev(NULL), m_pNext(NULL), m_bBOT(false), m_strName(""), m_strClan(""), m_strScript(""), m_connection_id(0), m_pilotTeam(0), m_pilotDecals(0), m_teamDecals(0), m_mechChasisID(0), m_pilotSkins(0), m_tonnage(0), m_pBufVCM(NULL), m_vehicleCreateMessage(NULL)
|
|
{
|
|
}
|
|
|
|
CMRPPlayer::~CMRPPlayer()
|
|
{
|
|
if (m_vehicleCreateMessage) {
|
|
delete m_vehicleCreateMessage;
|
|
m_vehicleCreateMessage = NULL;
|
|
}
|
|
if (m_pBufVCM) {
|
|
free(m_pBufVCM);
|
|
m_pBufVCM = NULL;
|
|
}
|
|
}
|
|
|
|
int CMRPPlayer::GetMemSize() const
|
|
{
|
|
int nSize = sizeof(CMRPPlayer);
|
|
|
|
nSize += m_strName.GetLength() + 1;
|
|
nSize += m_strClan.GetLength() + 1;
|
|
nSize += m_strScript.GetLength() + 1;
|
|
nSize += m_vehicleCreateMessage->GetSize();
|
|
|
|
return nSize;
|
|
}
|
|
|
|
void CMRPPlayer::Save(Stuff::DynamicMemoryStream& mf)
|
|
{
|
|
mf.WriteBit(m_bBOT);
|
|
mf.WriteByteAlign();
|
|
mf << m_strName;
|
|
mf << m_strClan;
|
|
mf << m_strScript;
|
|
mf.WriteBytes(&m_connection_id, sizeof(m_connection_id));
|
|
mf.WriteBytes(&m_pilotTeam, sizeof(m_pilotTeam));
|
|
mf.WriteBytes(&m_pilotDecals, sizeof(m_pilotDecals));
|
|
mf.WriteBytes(&m_teamDecals, sizeof(m_teamDecals));
|
|
mf.WriteBytes(&m_mechChasisID, sizeof(m_mechChasisID));
|
|
mf.WriteBytes(&m_pilotSkins, sizeof(m_pilotSkins));
|
|
mf.WriteBytes(&m_tonnage, sizeof(m_tonnage));
|
|
// for bot only - start
|
|
mf << m_aiModel;
|
|
int n = m_vehicleCreateMessage->GetSize();
|
|
mf.WriteBytes(&n, sizeof(n));
|
|
mf.WriteBytes(m_pBufVCM, n);
|
|
}
|
|
|
|
void CMRPPlayer::Load(Stuff::MemoryStream& mf)
|
|
{
|
|
mf.ReadBit(m_bBOT);
|
|
mf.ReadByteAlign();
|
|
mf >> m_strName;
|
|
mf >> m_strClan;
|
|
mf >> m_strScript;
|
|
mf.ReadBytes(&m_connection_id, sizeof(m_connection_id));
|
|
mf.ReadBytes(&m_pilotTeam, sizeof(m_pilotTeam));
|
|
mf.ReadBytes(&m_pilotDecals, sizeof(m_pilotDecals));
|
|
mf.ReadBytes(&m_teamDecals, sizeof(m_teamDecals));
|
|
mf.ReadBytes(&m_mechChasisID, sizeof(m_mechChasisID));
|
|
mf.ReadBytes(&m_pilotSkins, sizeof(m_pilotSkins));
|
|
mf.ReadBytes(&m_tonnage, sizeof(m_tonnage));
|
|
// for bot only - start
|
|
mf >> m_aiModel;
|
|
int n;
|
|
mf.ReadBytes(&n, sizeof(n));
|
|
m_pBufVCM = (BYTE*)malloc(n);
|
|
mf.ReadBytes(m_pBufVCM, n);
|
|
m_vehicleCreateMessage = new MemoryStream(m_pBufVCM, n);
|
|
}
|
|
|
|
CMRPFull::CMRPFull()
|
|
: m_strGameName(""), m_dwMyDirectPlayID(0), m_strPlayer(""), m_strPassword(""),
|
|
m_bStarting(false), m_bStarted(false), m_bStopping(false), m_bStopped(false),
|
|
m_nMissionParamSize(0), m_pMissionParam(NULL), m_bTeamGame(false), m_pMRPPlayers(NULL), m_nCount(-1), m_fFrameTime(0.0), m_pMRPPackStart(NULL),
|
|
m_pCurMRPPack(NULL)
|
|
{
|
|
m_nBOTPlayers = 0;
|
|
m_nLoadingPlayers = 0;
|
|
m_nBroadCastPlayers = 0;
|
|
}
|
|
|
|
CMRPFull::~CMRPFull()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
MWApplication* CMRPFull::Check()
|
|
{
|
|
MWApplication* app = MWApplication::GetInstance();
|
|
if (app) {
|
|
if (app->networkingFlag) {
|
|
if (app->serverFlag)
|
|
return app;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
bool CMRPFull::IsValidData() const
|
|
{
|
|
if (m_pMissionParam) {
|
|
if (m_pMRPPlayers) {
|
|
if (m_pMRPPackStart) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void CMRPFull::Reset()
|
|
{
|
|
FreeString(LocalIPAddress);
|
|
m_bStarting = false;
|
|
m_bStarted = false;
|
|
m_bStopping = false;
|
|
m_bStopped = false;
|
|
while(m_pMRPPackStart) {
|
|
CMRPPack* pNext = m_pMRPPackStart->m_pNext;
|
|
|
|
FreeMRPPack(m_pMRPPackStart);
|
|
m_pMRPPackStart = pNext;
|
|
}
|
|
while(m_pMRPPlayers) {
|
|
CMRPPlayer* pNext = m_pMRPPlayers->m_pNext;
|
|
|
|
delete m_pMRPPlayers;
|
|
m_pMRPPlayers = pNext;
|
|
}
|
|
if (m_pMissionParam) {
|
|
delete [] m_pMissionParam;
|
|
m_pMissionParam = NULL;
|
|
}
|
|
|
|
m_strGameName = (const char*)NULL;
|
|
m_strPlayer = (const char*)NULL;
|
|
m_strPassword = (const char*)NULL;
|
|
|
|
m_nMissionParamSize = 0;
|
|
m_nBOTPlayers = 0;
|
|
m_nLoadingPlayers = 0;
|
|
m_nBroadCastPlayers = 0;
|
|
|
|
int i;
|
|
for(i = 0; i < m_nCount; i++) {
|
|
free(m_pa[i]);
|
|
}
|
|
m_nCount = -1;
|
|
m_fFrameTime = 0.0;
|
|
|
|
m_pCurMRPPack = NULL;
|
|
m_pLastDictionary = m_pLastDictionaryToBeSent = NULL;
|
|
}
|
|
|
|
bool CMRPFull::IsValid() const
|
|
{
|
|
if (m_bStarted && (m_nLoadingPlayers > 0) && m_pMRPPackStart) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void CMRPFull::Loading()
|
|
{
|
|
}
|
|
|
|
void CMRPFull::Loaded()
|
|
{
|
|
}
|
|
|
|
void CMRPFull::PreRendering()
|
|
{
|
|
}
|
|
|
|
void CMRPFull::PreRendered()
|
|
{
|
|
}
|
|
|
|
void CMRPFull::Starting()
|
|
{
|
|
if (Check()) {
|
|
if (g_nMR == 1)
|
|
m_bStarting = true;
|
|
}
|
|
}
|
|
|
|
void CMRPFull::Started()
|
|
{
|
|
MWApplication* app = Check();
|
|
if (app) {
|
|
if (g_nMR == 1) {
|
|
NetMissionParameters::MWNetMissionParameters* params = app->GetLocalNetParams();
|
|
|
|
DynamicMemoryStream stream;
|
|
params->SaveParameters(&stream);
|
|
stream.WriteByteAlign();
|
|
stream.Rewind();
|
|
|
|
m_pMissionParam = new BYTE[stream.GetBufferBytesUsed()];
|
|
memcpy(m_pMissionParam, stream.GetPointer(), stream.GetBufferBytesUsed());
|
|
m_nMissionParamSize = stream.GetBufferBytesUsed();
|
|
m_bTeamGame = !!params->m_teamAllowed;
|
|
|
|
m_bStarted = true;
|
|
} else {
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMRPFull::StartFrame()
|
|
{
|
|
MWApplication* app = Check();
|
|
if (app) {
|
|
if (g_nMR == 1) {
|
|
if (m_bStarted) {
|
|
MWMission* mission = Cast_Object(MWMission*, MWMission::GetInstance());
|
|
if (mission && (m_nCount == -1)) {
|
|
m_nCount++;
|
|
m_fFrameTime = mission->GetMissionTime();
|
|
}
|
|
}
|
|
} else {
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMRPFull::StopFrame()
|
|
{
|
|
if (m_nCount != -1) {
|
|
MWApplication* app = Check();
|
|
if (app && (m_nCount > 0)) {
|
|
CMRPPack* pMRPPack = AllocMRPPack(m_nCount, &m_pa[0]);
|
|
if (m_pMRPPackStart) {
|
|
CMRPPack* p = m_pMRPPackStart;
|
|
while(p->m_pNext) {
|
|
p = p->m_pNext;
|
|
}
|
|
p->m_pNext = pMRPPack;
|
|
pMRPPack->m_pPrev = p;
|
|
} else {
|
|
m_pMRPPackStart = pMRPPack;
|
|
}
|
|
pMRPPack->m_fFrameTime = m_fFrameTime;
|
|
}
|
|
m_nCount = -1;
|
|
}
|
|
}
|
|
|
|
void CMRPFull::ReduceFrame()
|
|
{
|
|
}
|
|
|
|
void CMRPFull::Stopping()
|
|
{
|
|
if (g_nMR == 1) {
|
|
m_bStopping = true;
|
|
}
|
|
}
|
|
|
|
void CMRPFull::Stopped()
|
|
{
|
|
OnGameClose();
|
|
}
|
|
|
|
PMRPPlayer CMRPFull::AddMRPPlayer(bool bBOT)
|
|
{
|
|
PMRPPlayer p = NULL;
|
|
if (g_nMR == 1) {
|
|
MWApplication* app = Check();
|
|
if (app) {
|
|
if (g_nMR == 1) {
|
|
p = new CMRPPlayer();
|
|
PMRPPlayer pList = m_pMRPPlayers;
|
|
|
|
if (pList) {
|
|
while(pList->m_pNext) {
|
|
pList = pList->m_pNext;
|
|
}
|
|
pList->m_pNext = p;
|
|
p->m_pPrev = pList;
|
|
} else {
|
|
m_pMRPPlayers = p;
|
|
}
|
|
p->m_bBOT = bBOT;
|
|
if (bBOT) {
|
|
m_nBOTPlayers++;
|
|
} else {
|
|
if (!m_bStarted) {
|
|
if (m_bStarting) {
|
|
m_nBroadCastPlayers++;
|
|
} else {
|
|
m_nLoadingPlayers++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
PMRP CMRPFull::AddMRP(int nCommand, int nType, int nLen)
|
|
{
|
|
gosASSERT(g_nMR == 1);
|
|
if (m_nCount < 0) {
|
|
// should be frame started...
|
|
StartFrame();
|
|
}
|
|
|
|
PMRP pRet = (PMRP)malloc(sizeof(SMRP) + nLen);
|
|
pRet->m_nCommand = nCommand;
|
|
pRet->m_nType = nType;
|
|
pRet->m_nLen = nLen;
|
|
|
|
m_pa[m_nCount++] = pRet;
|
|
|
|
return pRet;
|
|
}
|
|
|
|
void CMRPFull::OnGameOpen(const char* pcszGameName, DWORD dwMyID, const char* pcszPlayer, const char* pcszPassword)
|
|
{
|
|
Reset();
|
|
g_nMR = 0;
|
|
if (!CTCL_IsConsole()) {
|
|
if (!g_bCOOP && CTCL_IsConsoleX()) {
|
|
gosASSERT(g_bIsServer);
|
|
if (g_nMissionReview)
|
|
g_nMR = 1;
|
|
} else {
|
|
if (g_bMRTest)
|
|
g_nMR = 1;
|
|
}
|
|
}
|
|
m_CurrentSession = CurrentSession;
|
|
m_strGameName = pcszGameName;
|
|
m_dwMyDirectPlayID = dwMyID;
|
|
m_strPlayer = pcszPlayer;
|
|
m_strPassword = pcszPassword;
|
|
}
|
|
|
|
void CMRPFull::OnGameClose()
|
|
{
|
|
if (g_nMR == 1) {
|
|
StopFrame();
|
|
m_bStopped = true;
|
|
DbgReport();
|
|
if (IsValidData()) {
|
|
char szFile[256];
|
|
if (!g_bCOOP && CTCL_IsConsoleX()) {
|
|
GetFileName4GUID(szFile, "c:", g_pcszGameDataSavePath, g_pcszGameDataExtMR, g_guidGameDatas);
|
|
if (SaveMR(szFile)) {
|
|
CTCL_SendFile(g_SysTime, g_guidGameDatas, 1);
|
|
}
|
|
} else {
|
|
if (g_bMRTest) {
|
|
GetFileName4GUID(szFile, "c:", g_pcszGameDataSavePath, g_pcszGameDataExtMR);
|
|
SaveMR(szFile);
|
|
}
|
|
}
|
|
}
|
|
} else if (g_nMR == 2) {
|
|
QuitReplay();
|
|
}
|
|
g_nMR = 0;
|
|
}
|
|
|
|
void CMRPFull::AddRemovePlayerToGame(int nCommand, char* Name, DPID dpId)
|
|
{
|
|
if (!Name)
|
|
Name = "";
|
|
#if defined(_DEBUG) && 0 // jcem - for MR test
|
|
{
|
|
char Buffer[128];
|
|
sprintf(Buffer, "Network::RoutePacket() Player(\"%s\") %s\n", Name, (nCommand == MRP_ADD_PLAYER_NAME) ? "Added": "Deleted");
|
|
OutputDebugString(Buffer);
|
|
}
|
|
#endif // _DEBUG && ...
|
|
/*
|
|
PMRP pMRP = AddMRP(nCommand, 0, strlen(Name) + 1);
|
|
|
|
SMRP_PLAYER_NAME& PN = pMRP->m_PlayerName[0];
|
|
PN.m_dpId = dpId;
|
|
strcpy(PN.m_szName, Name);
|
|
*/
|
|
}
|
|
|
|
void CMRPFull::AddRemoveConnection(bool bAdd, Connection* pConnection)
|
|
{
|
|
gosASSERT(pConnection);
|
|
#if defined(_DEBUG) && 0 // jcem - for MR test
|
|
{
|
|
char Buffer[128];
|
|
sprintf(Buffer, "Network::RoutePacket() Connection %s\n", bAdd ? "Added": "Deleted");
|
|
OutputDebugString(Buffer);
|
|
}
|
|
#endif // _DEBUG && ...
|
|
/*
|
|
PMRP pMRP = AddMRP(bAdd ? gosNet_PlayerAdded: gosNet_PlayerDeleted, 0, sizeof(DWORD));
|
|
pMRP->m_dpID = pConnection->GetNetworkAddress();
|
|
*/
|
|
}
|
|
|
|
void CMRPFull::SessionLost()
|
|
{
|
|
#if defined(_DEBUG) && 0 // jcem - for MR test
|
|
{
|
|
char Buffer[128];
|
|
sprintf(Buffer, "Network::RoutePacket() SessionLost\n");
|
|
OutputDebugString(Buffer);
|
|
}
|
|
#endif // _DEBUG && ...
|
|
/*
|
|
AddMRP(gosNet_GameEnded, 0, 0);
|
|
*/
|
|
}
|
|
|
|
void* CMRPFull::NetInformation(gosNetInfo Info, DWORD Parameter, char* Name)
|
|
{
|
|
gosASSERT(g_nMR == 2);
|
|
gosASSERT(InNetworkGame);
|
|
gosASSERT(IAmTheServer);
|
|
|
|
static char Buffer[256];
|
|
void* result=0;
|
|
|
|
switch( Info )
|
|
{
|
|
//
|
|
// Returns TRUE if in a networked game
|
|
//
|
|
case gos_Networking:
|
|
{
|
|
result=(void*)1;
|
|
return result;
|
|
}
|
|
//
|
|
// Returns TRUE if you created the game (FALSE=Joined)
|
|
//
|
|
case gos_GameSecure:
|
|
{
|
|
result=(void*)(CurrentSession.dwFlags&DPSESSION_SECURESERVER);
|
|
return result;
|
|
}
|
|
//
|
|
// Returns NULL or pointer to password string
|
|
//
|
|
case gos_GamePassword:
|
|
{
|
|
if( PasswordBuffer[0] )
|
|
result=PasswordBuffer;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns TRUE if the host created the game as a secure game
|
|
//
|
|
case gos_AmITheServer:
|
|
{
|
|
result=(void*)1;
|
|
return result;
|
|
}
|
|
//
|
|
// Returns the number of player in the current game
|
|
//
|
|
case gos_NumberOfPlayers:
|
|
{
|
|
DWORD NumPlayers=0;
|
|
ListOfNames* pThis=CurrentPlayers;
|
|
while( pThis )
|
|
{
|
|
NumPlayers++;
|
|
pThis=pThis->pNext;
|
|
}
|
|
result=(void*)NumPlayers;
|
|
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Returns a char* for the ip address
|
|
//
|
|
case gos_MyIPAddress:
|
|
{
|
|
result=(void*)MyIPAddress;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Returns a DWORD for this machines player NUMBER
|
|
//
|
|
case gos_MyID:
|
|
{
|
|
result=(void*)MyDirectPlayID;
|
|
return result;
|
|
}
|
|
//
|
|
// Returns a DWORD for the servers player NUMBER
|
|
//
|
|
case gos_ServerID:
|
|
{
|
|
if( Environment.NetworkGame && Connected )
|
|
result=(void*)DPID_SERVERPLAYER;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns a DWORD for ALL players (broadcast)
|
|
//
|
|
case gos_AllID:
|
|
{
|
|
if( Environment.NetworkGame && Connected )
|
|
result=(void*)DPID_ALLPLAYERS;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns a player ID for the player NUMBER passed in the parameter
|
|
//
|
|
case gos_PlayerID:
|
|
{
|
|
DWORD NumPlayers=0;
|
|
ListOfNames* pThis=CurrentPlayers;
|
|
while( pThis )
|
|
{
|
|
if( NumPlayers==Parameter )
|
|
{
|
|
result=(void*)pThis->Data;
|
|
break;
|
|
}
|
|
NumPlayers++;
|
|
pThis=pThis->pNext;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns a NUMBER for the player ID passed in the parameter (or 0xffffffff if not found)
|
|
//
|
|
case gos_PlayerNumber:
|
|
{
|
|
result=(void*)0xffffffff;
|
|
DWORD NumPlayers=0;
|
|
ListOfNames* pThis=CurrentPlayers;
|
|
while( pThis )
|
|
{
|
|
if( pThis->Data==Parameter )
|
|
{
|
|
result=(void*)NumPlayers;
|
|
break;
|
|
}
|
|
NumPlayers++;
|
|
pThis=pThis->pNext;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns a char* for the player NUMBER passed in the parameter
|
|
//
|
|
case gos_PlayerName:
|
|
{
|
|
result=(void*)"";
|
|
DWORD NumPlayers=0;
|
|
ListOfNames* pThis=CurrentPlayers;
|
|
while( pThis )
|
|
{
|
|
if( NumPlayers==Parameter )
|
|
{
|
|
result=(void*)pThis->Name;
|
|
}
|
|
NumPlayers++;
|
|
pThis=pThis->pNext;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns if the game is currently locked
|
|
//
|
|
case gos_LockedStatus:
|
|
{
|
|
result=(void*)(CurrentSession.dwFlags&DPSESSION_JOINDISABLED ? 1 : 0);
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns number of packets sent in the past frame to the player NUMBER passed
|
|
//
|
|
case gos_PacketsSentLastFrame:
|
|
{
|
|
PacketLogging* pThis=pDebugPacketLog;
|
|
DWORD PlayerID=(DWORD)gos_NetInformation(gos_PlayerID);
|
|
DWORD Counter=0;
|
|
/*while( pThis )
|
|
{
|
|
if( CurrentFrameNumber-1==pThis->FrameNumber && PlayerID==pThis->ToID )
|
|
Counter++;
|
|
pThis=pThis->pNext;
|
|
}*/
|
|
result=(void*)Counter;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns number of packets recieved in the past Frame from the player NUMBER passed
|
|
//
|
|
case gos_PacketsFromLastFrame:
|
|
{
|
|
PacketLogging* pThis=pDebugPacketLog;
|
|
DWORD PlayerID=(DWORD)gos_NetInformation(gos_PlayerID);
|
|
DWORD Counter=0;
|
|
/*while( pThis )
|
|
{
|
|
if( CurrentFrameNumber-1==pThis->FrameNumber && PlayerID==pThis->FromID )
|
|
Counter++;
|
|
pThis=pThis->pNext;
|
|
}*/
|
|
result=(void*)Counter;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns number of bytes sent in the past Frame to the player NUMBER passed
|
|
//
|
|
case gos_BytesSentLastFrame:
|
|
{
|
|
PacketLogging* pThis=pDebugPacketLog;
|
|
DWORD PlayerID=(DWORD)gos_NetInformation(gos_PlayerID);
|
|
DWORD Counter=0;
|
|
/*while( pThis )
|
|
{
|
|
if( CurrentFrameNumber-1==pThis->FrameNumber && PlayerID==pThis->ToID )
|
|
Counter+=pThis->Size;
|
|
pThis=pThis->pNext;
|
|
}*/
|
|
result=(void*)Counter;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns number of bytes recieved in the past Frame from the player NUMBER passed
|
|
//
|
|
case gos_BytesFromLastFrame:
|
|
{
|
|
PacketLogging* pThis=pDebugPacketLog;
|
|
DWORD PlayerID=(DWORD)gos_NetInformation(gos_PlayerID);
|
|
DWORD Counter=0;
|
|
/*while( pThis )
|
|
{
|
|
if( CurrentFrameNumber-1==pThis->FrameNumber && PlayerID==pThis->FromID )
|
|
Counter+=pThis->Size;
|
|
pThis=pThis->pNext;
|
|
}*/
|
|
result=(void*)Counter;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns total number of bytes sent in the past Frame to the player NUMBER passed (including packet overhead)
|
|
//
|
|
case gos_BandwithSentLastFrame:
|
|
{
|
|
PacketLogging* pThis=pDebugPacketLog;
|
|
DWORD PlayerID=(DWORD)gos_NetInformation(gos_PlayerID);
|
|
DWORD Counter=0;
|
|
/*while( pThis )
|
|
{
|
|
if( CurrentFrameNumber-1==pThis->FrameNumber && PlayerID==pThis->ToID )
|
|
Counter+=pThis->Size+PACKET_OVERHEAD;
|
|
pThis=pThis->pNext;
|
|
}*/
|
|
result=(void*)Counter;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns total number of bytes recieved in the past Frame from the player NUMBER passed (including packet overhead)
|
|
//
|
|
case gos_BandwithFromLastFrame:
|
|
{
|
|
PacketLogging* pThis=pDebugPacketLog;
|
|
DWORD PlayerID=(DWORD)gos_NetInformation(gos_PlayerID);
|
|
DWORD Counter=0;
|
|
/*while( pThis )
|
|
{
|
|
if( CurrentFrameNumber-1==pThis->FrameNumber && PlayerID==pThis->FromID )
|
|
Counter+=pThis->Size+PACKET_OVERHEAD;
|
|
pThis=pThis->pNext;
|
|
}*/
|
|
result=(void*)Counter;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns number of packets lost from the player NUMBER passed (based on packet numbers and retries)
|
|
//
|
|
case gos_PacketsLostLastFrame:
|
|
{
|
|
return (void*)0;
|
|
}
|
|
//
|
|
// Returns the average ping time for any guaranteed packets sent in the last frame to the player NUMBER
|
|
//
|
|
case gos_LatencyLastFrame:
|
|
{
|
|
return (void*)0;
|
|
}
|
|
//
|
|
// Returns the number of packets still in the send queue
|
|
//
|
|
case gos_GetMessageSendQueue:
|
|
{
|
|
result=(void*)0;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns the number of Games found on network (or 1 if in a network game)
|
|
//
|
|
case gos_NumberOfGames:
|
|
{
|
|
result=(void*)1;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns the name of the Game with the parameter passed (If in a game, returns this games name)
|
|
//
|
|
case gos_NameOfGame:
|
|
{
|
|
result=(void*)"";
|
|
|
|
if( 0==Parameter )
|
|
result=(void*)CurrentSession.lpszSessionNameA;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns true if the game name passed is passworded, Name=Game Name
|
|
//
|
|
case gos_IsGamePassworded:
|
|
{
|
|
result=(void*)((CurrentSession.dwFlags&DPSESSION_PASSWORDREQUIRED) ? 1 : 0);
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns true if the game name passed is secure, Name=Game Name
|
|
//
|
|
case gos_IsGameSecure:
|
|
{
|
|
result=(void*)((CurrentSession.dwFlags&DPSESSION_SECURESERVER) ? 1 : 0);
|
|
return result;
|
|
}
|
|
//
|
|
// Returns true if the game name passed is locked so no more players can enter, Name=Game Name
|
|
//
|
|
case gos_IsGameLocked:
|
|
{
|
|
result=(void*)((CurrentSession.dwFlags&DPSESSION_JOINDISABLED) ? 1 : 0);
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns maximum number of players in a game, Name=Game Name
|
|
//
|
|
case gos_MaxPlayersInGame:
|
|
{
|
|
result=(void*)CurrentSession.dwMaxPlayers;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns a pointer to 16 bytes of information from the game, Name=Game Name (Games set this in Environment.NetGameInfo)
|
|
//
|
|
case gos_InformationAboutGame:
|
|
{
|
|
result=(void*)&CurrentSession.dwUser1;
|
|
return result;
|
|
}
|
|
//
|
|
// Returns number of players in a game, Name=Game Name (If in a game, returns player in this game)
|
|
//
|
|
case gos_NumberOfPlayersInGame:
|
|
{
|
|
result=gos_NetInformation(gos_NumberOfPlayers);
|
|
return result;
|
|
}
|
|
//
|
|
// Return players name - Parameter=Player #, Name=Game Name. (If in a game, returns players name in this game)
|
|
//
|
|
case gos_NameOfPlayersInGame:
|
|
{
|
|
result=gos_NetInformation(gos_PlayerName,Parameter);
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns the number of modems installed
|
|
//
|
|
case gos_NumberOfModems:
|
|
{
|
|
DWORD ModemNumber=0;
|
|
result=(void*)ModemNumber;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns the name of the modem number passed
|
|
//
|
|
case gos_NameOfModem:
|
|
{
|
|
result=(void*)"";
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns the number of serial ports installed
|
|
//
|
|
case gos_NumberOfSerialPorts:
|
|
{
|
|
DWORD PortNumber=0;
|
|
result=(void*)PortNumber;
|
|
|
|
return result;
|
|
}
|
|
//
|
|
// Returns the name of the serial port number passed
|
|
//
|
|
case gos_NameOfSerialPort:
|
|
{
|
|
result=(void*)"";
|
|
|
|
return result;
|
|
}
|
|
/* To be added once UI queries required decided
|
|
//
|
|
// Returns the status of the ZoneTech matchmaking connect attempt for game server
|
|
// 0 is success, 1 not yet tried, 2 pending, 3 failed, 4 lost connection
|
|
//
|
|
case gos_GameRegistrationStatus:
|
|
{
|
|
DWORD status = 1;
|
|
|
|
IZoneAsync::STATUS actual =IZoneAsync::STATUS_FAILED;
|
|
|
|
if (g_pZMAsync)
|
|
{
|
|
g_pZMAsync->GetStatus(&actual);
|
|
switch (actual)
|
|
{
|
|
case IZoneAsync::STATUS_COMPLETED:
|
|
status =0;
|
|
break;
|
|
case IZoneAsync::STATUS_STARTING:
|
|
status = 2;
|
|
break;
|
|
default:
|
|
status = 3;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (void*) status;
|
|
|
|
}
|
|
//
|
|
// Returns the status of the ZoneTech matchmaking connect attempt for game joiner
|
|
// 0 is success, 1 not yet tried, 2 pending, 3 failed, 4 lost connection
|
|
//
|
|
case gos_GameBrowseStatus:
|
|
{
|
|
DWORD status = 1;
|
|
|
|
IZoneAsync::STATUS actual =IZoneAsync::STATUS_FAILED;
|
|
|
|
if (g_pZMAsync)
|
|
{
|
|
g_pZMAsync->GetStatus(&actual);
|
|
switch (actual)
|
|
{
|
|
case IZoneAsync::STATUS_COMPLETED:
|
|
status =0;
|
|
break;
|
|
case IZoneAsync::STATUS_STARTING:
|
|
status = 2;
|
|
break;
|
|
default:
|
|
status = 3;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (void*) status;
|
|
|
|
}
|
|
//
|
|
//
|
|
//
|
|
*/
|
|
#ifdef OUTBOUND_WINDOW
|
|
case gos_GetNumOutboudWindows:
|
|
OutboundWindow * pOW;
|
|
pOW = OutboundWindow::m_pHead;
|
|
int i;
|
|
i=0;
|
|
while (pOW)
|
|
{
|
|
i++;
|
|
pOW = pOW->m_pNext;
|
|
}
|
|
return (void *)i;
|
|
break;
|
|
|
|
case gos_GetOutboundWindowSize:
|
|
pOW = OutboundWindow::m_pHead;
|
|
while (pOW)
|
|
{
|
|
if (Parameter==0)
|
|
break;
|
|
Parameter--;
|
|
pOW = pOW->m_pNext;
|
|
}
|
|
if (Parameter != 0)
|
|
return (void *)-1;
|
|
return (void *)(pOW->m_NextPacketNumberToSend - pOW->m_LastPacketTheyReceived);
|
|
break;
|
|
|
|
case gos_GetOutboundWindowSizeDpid:
|
|
pOW=OutboundWindow::Find(Parameter);
|
|
if (pOW)
|
|
{
|
|
return (void *)(pOW->m_NextPacketNumberToSend - pOW->m_LastPacketTheyReceived);
|
|
}
|
|
|
|
return (void *)-10000;
|
|
|
|
break;
|
|
|
|
case gos_GetOB_NxtPkt2Send:
|
|
pOW = OutboundWindow::m_pHead;
|
|
while (pOW)
|
|
{
|
|
if (Parameter==0)
|
|
break;
|
|
Parameter--;
|
|
pOW = pOW->m_pNext;
|
|
}
|
|
if (Parameter != 0)
|
|
return (void *)-1;
|
|
return (void *)(pOW->m_NextPacketNumberToSend);
|
|
break;
|
|
|
|
case gos_GetOB_LstPktRcvd:
|
|
pOW = OutboundWindow::m_pHead;
|
|
while (pOW)
|
|
{
|
|
if (Parameter==0)
|
|
break;
|
|
Parameter--;
|
|
pOW = pOW->m_pNext;
|
|
}
|
|
if (Parameter != 0)
|
|
return (void *)-1;
|
|
return (void *)(pOW->m_LastPacketWeReceived);
|
|
break;
|
|
|
|
case gos_GetOB_LstPktTheyRcvd:
|
|
pOW = OutboundWindow::m_pHead;
|
|
while (pOW)
|
|
{
|
|
if (Parameter==0)
|
|
break;
|
|
Parameter--;
|
|
pOW = pOW->m_pNext;
|
|
}
|
|
if (Parameter != 0)
|
|
return (void *)-1;
|
|
return (void *)(pOW->m_LastPacketTheyReceived);
|
|
break;
|
|
|
|
#else
|
|
case gos_GetNumOutboudWindows:
|
|
case gos_GetOutboundWindowSize:
|
|
case gos_GetOB_NxtPkt2Send:
|
|
case gos_GetOB_LstPktRcvd:
|
|
case gos_GetOB_LstPktTheyRcvd:
|
|
return 0;
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
STOP(( "Unknown info %d",Info ));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void CMRPFull::NetServerCommands(gos_NetCommands Command, DWORD Data1)
|
|
{
|
|
gosASSERT(g_nMR == 2);
|
|
|
|
switch( Command )
|
|
{
|
|
//
|
|
// Remove the player with PlayerID == Data1 from the game
|
|
//
|
|
case gos_Command_KillPlayer:
|
|
{
|
|
gosASSERT( InNetworkGame && IAmTheServer && Data1!=MyDirectPlayID ); // Not allowed to delete yourself like this
|
|
//wDestroyPlayer( dplay4, Data1 ); // Allow any ID - so players already dead / dieing don't cause an error
|
|
return;
|
|
}
|
|
//
|
|
// Datat1=1 to lock the game, 0=to unlock the game - no more players can join when a game is locked
|
|
//
|
|
case gos_Command_LockGame:
|
|
{
|
|
gosASSERT( InNetworkGame && IAmTheServer );
|
|
|
|
CurrentSession.dwFlags&=~(DPSESSION_JOINDISABLED|DPSESSION_NEWPLAYERSDISABLED);
|
|
if( Data1 )
|
|
CurrentSession.dwFlags|=DPSESSION_JOINDISABLED|DPSESSION_NEWPLAYERSDISABLED;
|
|
break;
|
|
}
|
|
//
|
|
// Updates the 'game data' from Environment.NetGameInfo - so players enumerating games can see the changes
|
|
//
|
|
case gos_Command_UpdateGameData:
|
|
{
|
|
gosASSERT( InNetworkGame && IAmTheServer );
|
|
break;
|
|
}
|
|
//
|
|
// Updates the number of maximum players allowed in a game from Environment.NetworkMaxPlayers
|
|
//
|
|
case gos_Commend_UpdateMaxPlayers:
|
|
{
|
|
gosASSERT( InNetworkGame && IAmTheServer );
|
|
|
|
CurrentSession.dwMaxPlayers=Environment.NetworkMaxPlayers;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
STOP(( "Bad command" ));
|
|
}
|
|
}
|
|
|
|
NetPacket* CMRPFull::NetGetMessage()
|
|
{
|
|
gosASSERT(g_nMR == 2);
|
|
MWApplication* app = Check();
|
|
if (app && app->GetApplicationState() == ApplicationStateEngine::RunningGameState) {
|
|
}
|
|
return (NetPacket*)NULL;
|
|
}
|
|
|
|
bool CMRPFull::LocalSendNetMessage(int message_type, Stuff::MemoryStream& message)
|
|
{
|
|
if (g_nMR == 1) {
|
|
switch(message_type) {
|
|
case MWEntityManager::DictionaryIndexMessageID:
|
|
case MWEntityManager::WeaponBundleMessageID:
|
|
case MWApplication::ScoreFormatMessageID:
|
|
case MWApplication::ScoreMessageID:
|
|
SendMessage(message_type, &message);
|
|
return false;
|
|
default:
|
|
if ((MWEntityManager::DictionaryPage0MessageID <= message_type) && (message_type < MWEntityManager::DictionaryPageMaxMessageID)) {
|
|
SendMessage(message_type, &message);
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
} else if (g_nMR == 2) {
|
|
switch(message_type) {
|
|
case MWApplication::RequestNewDictionaryMessageID:
|
|
if (m_pLastDictionary) {
|
|
m_pLastDictionaryToBeSent = m_pLastDictionary;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CMRPFull::BackgroundTack()
|
|
{
|
|
gosASSERT(g_nMR == 2);
|
|
MWApplication* app = Check();
|
|
if (app) {
|
|
if (app->GetApplicationState() == ApplicationStateEngine::RunningGameState) {
|
|
MWEntityManager* pMWENTMGR = MWEntityManager::GetInstance();
|
|
if (m_pLastDictionaryToBeSent) {
|
|
PMRP pMRP = m_pLastDictionaryToBeSent;
|
|
m_pLastDictionaryToBeSent = NULL;
|
|
Stuff::MemoryStream message(&pMRP->m_ba[0], pMRP->m_nLen);
|
|
pMWENTMGR->UpdateClientEntites(1, pMRP->m_nType, &message);
|
|
return;
|
|
}
|
|
if (m_pCurMRPPack) {
|
|
MWMission* mission = Cast_Object(MWMission*, MWMission::GetInstance());
|
|
Scalar fFrameTime = mission->GetMissionTime();
|
|
if (m_pCurMRPPack->m_fFrameTime <= fFrameTime) {
|
|
int i;
|
|
|
|
for(i = 0; i < Maximum_Players; ++i)
|
|
{
|
|
if (app->servedConnectionData[i].clientLoaded) {
|
|
if (pMWENTMGR->serverController->waitingForRespawn[i]) {
|
|
Mech *vehicle = (Mech *)app->servedConnectionData[i].clientPlayer->vehicle; // pMWENTMGR->playerVehicle[i];
|
|
if (vehicle) {
|
|
pMWENTMGR->serverController->waitingForRespawn[i] = false;
|
|
Point3D trans;
|
|
YawPitchRoll rot;
|
|
vehicle->GetDeadReckonedNetworkPosition(trans, rot);
|
|
vehicle->ClearNetworkPosition();
|
|
LinearMatrix4D drop_position;
|
|
drop_position.BuildTranslation(trans);
|
|
drop_position.BuildRotation(rot);
|
|
|
|
vehicle->SetNewLocalToParent(drop_position);
|
|
vehicle->SyncMatrices(true);
|
|
Map::GetInstance()->UpdateZone(vehicle);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int nCount = m_pCurMRPPack->m_nCount;
|
|
for(i = 0; i < nCount; i++) {
|
|
PMRP pMRP = m_pCurMRPPack->m_pa[i];
|
|
switch(pMRP->m_nCommand) {
|
|
case 0:
|
|
{
|
|
Stuff::MemoryStream message(&pMRP->m_ba[0], pMRP->m_nLen);
|
|
switch(pMRP->m_nType)
|
|
{
|
|
case MWApplication::ScoreFormatMessageID:
|
|
case MWApplication::ScoreMessageID:
|
|
app->ReceiveDirectMessage(1, pMRP->m_nType, &message);
|
|
break;
|
|
default:
|
|
pMWENTMGR->UpdateClientEntites(1, pMRP->m_nType, &message);
|
|
if (pMRP->m_nType == MWEntityManager::DictionaryIndexMessageID) {
|
|
m_pLastDictionary = pMRP;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case MRP_RESPAWNMESSAGEID:
|
|
{
|
|
Stuff::MemoryStream message(&pMRP->m_ba[0], pMRP->m_nLen);
|
|
|
|
int nIdx = pMRP->m_nType;
|
|
if (nIdx < 0) {
|
|
nIdx++;
|
|
nIdx = -nIdx; // lancemate...
|
|
app->lancemateConnectionData[nIdx].lancemateMech->respawnCount+=1;
|
|
app->RespawnLancemateMessageHandler(1, &message);
|
|
} else {
|
|
app->servedConnectionData[nIdx].clientPlayer->GetVehicle()->respawnCount += 1;
|
|
EntityManager::GetInstance()->SetPlayerReady(app->servedConnectionData[nIdx].clientPlayer->vehicle);
|
|
app->RespawnMessageHandler(1, &message);
|
|
}
|
|
break;
|
|
}
|
|
case MRP_FULLCONFIRM:
|
|
{
|
|
int nWritten = pMRP->m_nType;
|
|
Stuff::MemoryStream message(&pMRP->m_ba[0], pMRP->m_nLen);
|
|
int version = 0;
|
|
message.ReadBits(&version,8);
|
|
|
|
Dictionary *dictionary = pMWENTMGR->GetDictionaryManager(1)->GetDictionary(version);
|
|
|
|
if (dictionary != NULL)
|
|
{
|
|
int rate_type = pMWENTMGR->bitManager->GetUpdateRate(UpdateManager::MechPositionUpdateID, dictionary->dictionaryBandwidth).m_ActiveRate;
|
|
Scalar rate = DictionaryPage::CalculateSeconds(rate_type);
|
|
|
|
while(nWritten-- > 0) {
|
|
BYTE connectionID;
|
|
WORD localID;
|
|
message.ReadBits(&connectionID, 8);
|
|
message.ReadBits(&localID, 16);
|
|
|
|
ReplicatorID id(connectionID, localID);
|
|
|
|
Entity* pEntity = NULL;
|
|
Connection* con2 = Network::GetInstance()->GetConnection(id.connectionID);
|
|
if (con2 != NULL) {
|
|
Check_Object(con2);
|
|
pEntity = (Entity*)con2->FindReplicator(id);
|
|
if (pEntity && !pEntity->IsDerivedFrom(MechWarrior4::Mech::DefaultData)) {
|
|
pEntity = NULL;
|
|
}
|
|
}
|
|
if (pEntity) {
|
|
MechPositionUpdate::Decode(pEntity, &message, 0.0, 0.0f, 1, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth, rate);
|
|
ExternalJumpJetUpdate::Decode(pEntity, &message, 0.0, 0.0f, 1, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth, rate);
|
|
MechInternalDamageUpdate::Decode(pEntity, &message, 0.0, 0.0f, 1, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth, rate);
|
|
} else {
|
|
MechPositionUpdate::Skip(&message, 0, 0.0, 1, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
|
|
ExternalJumpJetUpdate::Skip(&message, 0, 0.0, 1, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
|
|
MechInternalDamageUpdate::Skip(&message, 0, 0.0, 1, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
|
|
}
|
|
|
|
message.ReadByteAlign();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case MRP_MECHDAMAGETAKEN:
|
|
{
|
|
const SMRP_MECH_DAMAGETAKEN& t = pMRP->m_MDT[0];
|
|
ReplicatorID victim(t.m_bCon1, t.m_wLID1);
|
|
Connection *vicConn = Network::GetInstance()->GetConnection(victim.connectionID);
|
|
if (vicConn != 0)
|
|
{
|
|
Check_Object(vicConn);
|
|
Replicator* repVict = vicConn->FindReplicator(victim);
|
|
|
|
if (repVict)
|
|
{
|
|
ReplicatorID inflicting(t.m_bCon2, t.m_wLID2);
|
|
Connection *inflConn = Network::GetInstance()->GetConnection(inflicting.connectionID);
|
|
if (inflConn != 0)
|
|
{
|
|
Check_Object(inflConn);
|
|
Replicator* repInfl = inflConn->FindReplicator(inflicting);
|
|
|
|
if (repInfl)
|
|
{
|
|
// pass attacker and victim to spectator state engine
|
|
if ((t.m_damageType == BeamDamageType) || (t.m_damageType == MissileDamageType) || (t.m_damageType == ProjectileDamageType)) {
|
|
Mech_CheckDamage(repVict, repInfl);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
m_pCurMRPPack = m_pCurMRPPack->m_pNext;
|
|
}
|
|
} else {
|
|
app->QueStopGame();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
PMRP CMRPFull::SendMessage(int message_type, Stuff::MemoryStream *message, int nCommand/* = 0*/)
|
|
{
|
|
gosASSERT(g_nMR == 1);
|
|
PMRP pMRP;
|
|
if (message) {
|
|
message->WriteByteAlign();
|
|
message->Rewind();
|
|
int nLen = message->GetBufferBytesUsed();
|
|
const unsigned char* pSrc = (const unsigned char*)message->GetPointer();
|
|
|
|
pMRP = AddMRP(nCommand, message_type, nLen);
|
|
if (nLen > 0) {
|
|
memcpy(&pMRP->m_ba[0], pSrc, nLen);
|
|
}
|
|
} else {
|
|
pMRP = AddMRP(nCommand, message_type, 0);
|
|
}
|
|
|
|
return pMRP;
|
|
}
|
|
|
|
void g_MRF_MechDamageTaken(ReplicatorID id1, ReplicatorID id2, Stuff::Scalar damage_taken, int weaponID, int damageType)
|
|
{
|
|
g_MRF.MechDamageTaken(id1, id2, damage_taken, weaponID, damageType);
|
|
}
|
|
|
|
void CMRPFull::MechDamageTaken(ReplicatorID mech1, ReplicatorID mech2, Stuff::Scalar damage_taken, int weaponID, int damageType)
|
|
{
|
|
PMRP pMRP = AddMRP(MRP_MECHDAMAGETAKEN, 0, sizeof(SMRP_MECH_DAMAGETAKEN));
|
|
SMRP_MECH_DAMAGETAKEN& t = pMRP->m_MDT[0];
|
|
t.m_fDamage = damage_taken;
|
|
t.m_bCon1 = mech1.connectionID;
|
|
t.m_weaponID = weaponID;
|
|
t.m_wLID1 = mech1.localID;
|
|
t.m_bCon2 = mech2.connectionID;
|
|
t.m_damageType = damageType;
|
|
t.m_wLID2 = mech2.localID;
|
|
}
|
|
|
|
void _cdecl CMRPFull::SendCommand(int nCommand, ...)
|
|
{
|
|
}
|
|
|
|
void CMRPFull::DoReplay()
|
|
{
|
|
g_nMR = 2;
|
|
CTCL_SetGameState(_EGS_Preparing);
|
|
|
|
MWApplication* app = MWApplication::GetInstance();
|
|
|
|
g_pfn_NETINFORMATION = MRP_NetInformation;
|
|
g_pfn_NETSERVERCOMMANDS = MRP_NetServerCommands;
|
|
g_pfn_NETGETMESSAGE = MRP_NETGETMESSAGE;
|
|
g_pfn_BACKGROUNDTACK = MRP_BACKGROUNDTACK;
|
|
m_pCurMRPPack = m_pMRPPackStart;
|
|
m_pLastDictionary = NULL;
|
|
m_pLastDictionaryToBeSent = NULL;
|
|
g_pfn_NETSENDMESSAGE = MRP_NETSENDMESSAGE;
|
|
// see - CTCL_DoCreateGame() for full processing
|
|
|
|
// see - gos_NetStartGame
|
|
// store secure state
|
|
gInSecureGame=MWApplication::SecureNetGame; // true;
|
|
|
|
// initialize GameOS variables
|
|
gos_InitializeNetworking();
|
|
|
|
// get the ip address
|
|
//
|
|
UnRegisterData();
|
|
RegisterData();
|
|
AllocString(LocalIPAddress);
|
|
|
|
CancelDialup(NULL, 0, NULL);
|
|
LoadMPConnectionSettings(NULL, 0, NULL);
|
|
InitConnectionWizard(NULL, 0, NULL);
|
|
|
|
ConnectionIndex = 0;
|
|
PreConnect(NULL, 0, NULL);
|
|
|
|
// Mech4CreateGame -> gos_CreateGame -> InternalCreateGame
|
|
#ifdef OUTBOUND_WINDOW
|
|
OutboundWindow::CleanAll();
|
|
#endif
|
|
CurrentSession = m_CurrentSession;
|
|
MyDirectPlayID = m_dwMyDirectPlayID;
|
|
gosASSERT(m_strGameName.GetLength() > 0);
|
|
|
|
GUID guid = gos_GenerateUniqueGUID();
|
|
sprintf(GameNameBuffer, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
|
guid.Data1, guid.Data2, guid.Data3,
|
|
guid.Data4[0], guid.Data4[1],
|
|
guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
|
|
// strcpy(GameNameBuffer, m_strGameName);
|
|
|
|
if ((const char*)m_strPassword)
|
|
strcpy(PasswordBuffer, m_strPassword);
|
|
else
|
|
PasswordBuffer[0] = '\0';
|
|
InNetworkGame=1;
|
|
IAmTheServer=1;
|
|
|
|
// GetCurrentPlayers();
|
|
CMRPPlayer* pPlayer;
|
|
|
|
// find server
|
|
pPlayer = m_pMRPPlayers;
|
|
while(pPlayer->m_bBOT || (pPlayer->m_connection_id != 1)) {
|
|
pPlayer = pPlayer->m_pNext;
|
|
gosASSERT(pPlayer);
|
|
}
|
|
|
|
// add server...
|
|
gos_RealAddPlayerToGame(&CurrentPlayers, pPlayer->m_strName, MyDirectPlayID);
|
|
|
|
// see - CTCL_DoGame1st()
|
|
g_bIsServer = true;
|
|
app->networkingFlag = true;
|
|
app->serverFlag = true;
|
|
|
|
if (Network::GetInstance() == NULL)
|
|
{
|
|
gos_PushCurrentHeap(MechWarrior4::Heap);
|
|
Verify(!Network::GetInstance());
|
|
GlobalPointers::AddGlobalPointer(new Network, NetworkGlobalPointerIndex);
|
|
Register_Object(Network::GetInstance());
|
|
gos_PopCurrentHeap();
|
|
}
|
|
|
|
app->SaveServerOptions();
|
|
|
|
#if defined(LAB_ONLY)
|
|
MWGameInfo::g_lastGameType = MWGameInfo::g_currentGameType;
|
|
MWGameInfo::g_currentGameType = MWGameInfo::MultiServer;
|
|
#endif
|
|
|
|
//app->LoadServerOptions();
|
|
//app->SendRequestConnectionMessage();
|
|
|
|
for (int i = 0; i < Maximum_Lancemates; ++i)
|
|
{
|
|
app->lancemateConnectionData[i].Disconnect();
|
|
}
|
|
|
|
app->memoryDiffKiller.Init();
|
|
|
|
gosASSERT(MW4Shell::NetConnectedToServer(NULL, 0, NULL));
|
|
|
|
CTCL_InitMechDatas();
|
|
|
|
MW4Shell::Instance->InitNetworkScenarios(NULL, 0, (void**)NULL);
|
|
|
|
// see - CTCL_SetMissionParams();
|
|
CTCL_SetMissionParamsBy(m_pMissionParam, m_nMissionParamSize);
|
|
|
|
// MWApplication::AcceptConnectionMessageHandler(int connection, Stuff::MemoryStream *message)
|
|
// add bot !players
|
|
pPlayer = m_pMRPPlayers;
|
|
while(pPlayer) {
|
|
if (pPlayer->m_bBOT) {
|
|
MechWarrior4::LancemateConnectionData& lcd = app->lancemateConnectionData[pPlayer->m_connection_id];
|
|
lcd.lancemateConnected = true;
|
|
lcd.lancemateVehicleAccepted = true;
|
|
|
|
strcpy(lcd.lancemateName, pPlayer->m_strName);
|
|
strcpy(lcd.lancemateClan, pPlayer->m_strClan);
|
|
strcpy(lcd.scriptName, pPlayer->m_strScript);
|
|
lcd.aiModel = pPlayer->m_aiModel;
|
|
|
|
lcd.pilotTeam = pPlayer->m_pilotTeam;
|
|
//lcd.pilotDecals = pPlayer->m_pilotDecals;
|
|
//lcd.teamDecals = pPlayer->m_teamDecals;
|
|
lcd.mechChasisID = pPlayer->m_mechChasisID;
|
|
//lcd.pilotSkins = pPlayer->m_pilotSkins;
|
|
lcd.tonnage = pPlayer->m_tonnage;
|
|
//lcd.clientKey = 1000;
|
|
MemoryStream* pVCM = pPlayer->m_vehicleCreateMessage;
|
|
BYTE* pData = new BYTE[pVCM->GetSize()];
|
|
memcpy(pData, pVCM->GetPointer(), pVCM->GetSize());
|
|
lcd.lancemateCreateMessage = new MemoryStream(pData, pVCM->GetSize());
|
|
}
|
|
pPlayer = pPlayer->m_pNext;
|
|
}
|
|
// add players !bot
|
|
pPlayer = m_pMRPPlayers;
|
|
while(pPlayer) {
|
|
if (!pPlayer->m_bBOT) {
|
|
MechWarrior4::ServedConnectionData& scd = app->servedConnectionData[pPlayer->m_connection_id];
|
|
if (pPlayer->m_connection_id != 1) {
|
|
gos_RealAddPlayerToGame(&CurrentPlayers, pPlayer->m_strName, 0);
|
|
|
|
Network::GetInstance()->Set_nextConnectionID(pPlayer->m_connection_id);
|
|
Network::GetInstance()->net_AddPlayer(pPlayer->m_strName, pPlayer->m_connection_id);
|
|
}
|
|
gosASSERT(scd.clientConnected);
|
|
if (scd.clanName)
|
|
{
|
|
delete scd.clanName;
|
|
scd.clanName = NULL;
|
|
}
|
|
|
|
int clan_size = strlen(pPlayer->m_strClan) + 1;
|
|
|
|
scd.clanName = new char[clan_size];
|
|
strcpy(scd.clanName, pPlayer->m_strClan);
|
|
|
|
scd.clientVehicleAccepted = true;
|
|
|
|
scd.clientReady = true;
|
|
scd.clientSentScoreFormat = false;
|
|
scd.clientAllowTransfer = false;
|
|
scd.clientQuedForLaunch = true;
|
|
|
|
scd.pilotTeam = pPlayer->m_pilotTeam;
|
|
scd.pilotDecals = pPlayer->m_pilotDecals;
|
|
scd.teamDecals = pPlayer->m_teamDecals;
|
|
scd.mechChasisID = pPlayer->m_mechChasisID;
|
|
scd.pilotSkins = pPlayer->m_pilotSkins;
|
|
scd.tonnage = pPlayer->m_tonnage;
|
|
//scd.clientKey = 1000;
|
|
MemoryStream* pVCM = pPlayer->m_vehicleCreateMessage;
|
|
BYTE* pData = new BYTE[pVCM->GetSize()];
|
|
memcpy(pData, pVCM->GetPointer(), pVCM->GetSize());
|
|
scd.vehicleCreateMessage = new MemoryStream(pData, pVCM->GetSize());
|
|
}
|
|
pPlayer = pPlayer->m_pNext;
|
|
}
|
|
|
|
// see - CTCL_SetMechs();
|
|
|
|
// see - CTCL_CheckClientReady();
|
|
app->lastMapCRC = -1;
|
|
app->haveNetworkMap = true;
|
|
|
|
// see - CTCL_CheckServerReady()
|
|
// app->VerifyAllPlayerVehicles();
|
|
|
|
// void CTCL_StartGame(BOOL bRealLaunch -> false)
|
|
MW4Shell::Instance->EndAllScripts();
|
|
MW4Shell::Instance->currentShellRunning = MW4Shell::MainShellRunning; //MW4Shell::NoShellRunning;
|
|
MW4Shell::Instance->shellCommand = MW4Shell::StartNetworkGameCommand;
|
|
MW4Shell::Instance->shellStart = MW4Shell::MainShellStart;
|
|
|
|
// app->CTCL_CheckRunningStart();
|
|
// if (GetApplicationState() == ApplicationStateEngine::PreRenderState)
|
|
// CTCL_StartGame(TRUE);
|
|
}
|
|
|
|
void CMRPFull::QuitReplay()
|
|
{
|
|
gos_ShutdownNetwork();
|
|
|
|
g_pfn_NETSENDMESSAGE = NULL;
|
|
g_pfn_BACKGROUNDTACK = NULL;
|
|
m_pLastDictionaryToBeSent = NULL;
|
|
m_pLastDictionary = NULL;
|
|
m_pCurMRPPack = NULL;
|
|
g_pfn_NETGETMESSAGE = NULL;
|
|
g_pfn_NETSERVERCOMMANDS = NULL;
|
|
g_pfn_NETINFORMATION = NULL;
|
|
}
|
|
|
|
int CMRPFull::GetMemSize() const
|
|
{
|
|
int nSize = sizeof(CMRPFull);
|
|
|
|
nSize += m_strGameName.GetLength() + 1;
|
|
nSize += m_strPlayer.GetLength() + 1;
|
|
nSize += m_strPassword.GetLength() + 1;
|
|
nSize += m_nMissionParamSize;
|
|
|
|
CMRPPlayer* p1 = m_pMRPPlayers;
|
|
while(p1) {
|
|
nSize += p1->GetMemSize();
|
|
nSize += sizeof(int);
|
|
p1 = p1->m_pNext;
|
|
}
|
|
|
|
CMRPPack* p2 = m_pMRPPackStart;
|
|
while(p2) {
|
|
nSize += p2->GetMemSize();
|
|
nSize += sizeof(int);
|
|
nSize += p2->m_nCount;
|
|
p2 = p2->m_pNext;
|
|
}
|
|
|
|
return nSize;
|
|
}
|
|
|
|
void CMRPFull::DbgReport() const
|
|
{
|
|
#if 0
|
|
MString str;
|
|
char Buffer[128];
|
|
|
|
str = "";
|
|
sprintf(Buffer, "CMRPFull: %d, m_CurrentSession: %d, m_nMissionParamSize: %d\n", sizeof(CMRPFull), sizeof(m_CurrentSession), m_nMissionParamSize);
|
|
str += Buffer;
|
|
OutputDebugString(Buffer);
|
|
|
|
int nPlayersSize = 0;
|
|
CMRPPlayer* p1 = m_pMRPPlayers;
|
|
while(p1) {
|
|
nPlayersSize = p1->GetMemSize();
|
|
p1 = p1->m_pNext;
|
|
}
|
|
sprintf(Buffer, "nPlayersSize: %d, %f, m_nBOTPlayers: %d, m_nLoadingPlayers: %d\n", nPlayersSize, (1.0 * nPlayersSize) / (1.0 * (m_nBOTPlayers + m_nLoadingPlayers + m_nBroadCastPlayers)), m_nBOTPlayers, m_nLoadingPlayers);
|
|
str += Buffer;
|
|
OutputDebugString(Buffer);
|
|
|
|
int nMRPPacks = 0;
|
|
int nMRPPackSize = 0;
|
|
CMRPPack* p2 = m_pMRPPackStart;
|
|
while(p2) {
|
|
nMRPPackSize += p2->GetMemSize();
|
|
nMRPPacks++;
|
|
p2 = p2->m_pNext;
|
|
}
|
|
sprintf(Buffer, "nMRPPacks: %d, nMRPPackSize: %d, %f\n", nMRPPacks, nMRPPackSize, (1.0 * nMRPPackSize) / (1.0 * nMRPPacks));
|
|
str += Buffer;
|
|
OutputDebugString(Buffer);
|
|
|
|
Scalar f;
|
|
//(m_fFrameTime / 60): total = 1: f
|
|
// f = total * 60 / m_fFrameTime;
|
|
f = 60.0 * (nPlayersSize + nMRPPackSize) / m_fFrameTime;
|
|
f /= 1024.0;
|
|
sprintf(Buffer, "====\nTotalSize: %f kb, %f seconds(%f kb per minutes)\n", (1.0 * (nPlayersSize + nMRPPackSize)) / 1024.0, m_fFrameTime, f);
|
|
str += Buffer;
|
|
OutputDebugString(Buffer);
|
|
|
|
FILE* file = fopen("c:\\mr-info.txt", "wb");
|
|
if (file) {
|
|
fputs(str, file);
|
|
fclose(file);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
bool CMRPFull::SaveMR(const char* pcszFile)
|
|
{
|
|
gosASSERT(pcszFile && pcszFile[0]);
|
|
|
|
FILE* f = fopen(pcszFile, "wb");
|
|
if (f) {
|
|
Stuff::DynamicMemoryStream mf(GetMemSize());
|
|
|
|
mf.WriteBytes(&g_dwMR_Meta, sizeof(g_dwMR_Meta));
|
|
mf.WriteBytes(&m_CurrentSession, sizeof(m_CurrentSession));
|
|
mf << m_strGameName;
|
|
mf.WriteBytes(&m_dwMyDirectPlayID, sizeof(m_dwMyDirectPlayID));
|
|
mf << m_strPlayer;
|
|
mf << m_strPassword;
|
|
mf.WriteBit(m_bStarting);
|
|
mf.WriteBit(m_bStarted);
|
|
mf.WriteBit(m_bStopping);
|
|
mf.WriteBit(m_bStopped);
|
|
mf.WriteBit(m_bTeamGame);
|
|
mf.WriteByteAlign();
|
|
mf.WriteBytes(&m_nMissionParamSize, sizeof(m_nMissionParamSize));
|
|
mf.WriteBytes(m_pMissionParam, m_nMissionParamSize);
|
|
mf.WriteBytes(&m_nBOTPlayers, sizeof(m_nBOTPlayers));
|
|
mf.WriteBytes(&m_nLoadingPlayers, sizeof(m_nLoadingPlayers));
|
|
mf.WriteBytes(&m_nBroadCastPlayers, sizeof(m_nBroadCastPlayers));
|
|
int n = m_nBOTPlayers + m_nLoadingPlayers + m_nBroadCastPlayers;
|
|
CMRPPlayer* p1 = m_pMRPPlayers;
|
|
while(n-- > 0) {
|
|
p1->Save(mf);
|
|
p1 = p1->m_pNext;
|
|
}
|
|
mf.WriteBytes(&m_fFrameTime, sizeof(m_fFrameTime));
|
|
|
|
CMRPPack* p2 = m_pMRPPackStart;
|
|
n = 0;
|
|
while(p2) {
|
|
n++;
|
|
p2 = p2->m_pNext;
|
|
}
|
|
mf.WriteBytes(&n, sizeof(n));
|
|
|
|
p2 = m_pMRPPackStart;
|
|
while(p2) {
|
|
mf.WriteBytes(&p2->m_nCount, sizeof(p2->m_nCount));
|
|
p2->Save(mf);
|
|
p2 = p2->m_pNext;
|
|
}
|
|
mf.WriteByteAlign();
|
|
fwrite(mf.GetStreamStart(), mf.GetBytesUsed(), 1, f);
|
|
fclose(f);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CMRPFull::LoadDefaultMR()
|
|
{
|
|
char szFile[256];
|
|
|
|
GetFileName4GUID(szFile, "c:", g_pcszGameDataSavePath, g_pcszGameDataExtMR);
|
|
return LoadMR(szFile);
|
|
}
|
|
|
|
bool CMRPFull::LoadMR(const char* pcszFile)
|
|
{
|
|
gosASSERT(pcszFile && pcszFile[0]);
|
|
|
|
bool bRet = false;
|
|
|
|
FILE* f = fopen(pcszFile, "rb");
|
|
if (f) {
|
|
Reset();
|
|
|
|
long lSize = _filelength(fileno(f));
|
|
BYTE* pBuf = (BYTE*)malloc(lSize);
|
|
fread(pBuf, lSize, 1, f);
|
|
MemoryStream mf(pBuf, lSize);
|
|
|
|
DWORD dwMeta;
|
|
mf.ReadBytes(&dwMeta, sizeof(dwMeta));
|
|
if ((dwMeta == g_dwMR_Meta) || (dwMeta == g_dwMR_MetaOldA)) {
|
|
mf.ReadBytes(&m_CurrentSession, sizeof(m_CurrentSession));
|
|
mf >> m_strGameName;
|
|
mf.ReadBytes(&m_dwMyDirectPlayID, sizeof(m_dwMyDirectPlayID));
|
|
mf >> m_strPlayer;
|
|
mf >> m_strPassword;
|
|
mf.ReadBit(m_bStarting);
|
|
mf.ReadBit(m_bStarted);
|
|
mf.ReadBit(m_bStopping);
|
|
mf.ReadBit(m_bStopped);
|
|
mf.ReadBit(m_bTeamGame);
|
|
mf.ReadByteAlign();
|
|
mf.ReadBytes(&m_nMissionParamSize, sizeof(m_nMissionParamSize));
|
|
m_pMissionParam = new BYTE[m_nMissionParamSize];
|
|
mf.ReadBytes(m_pMissionParam, m_nMissionParamSize);
|
|
mf.ReadBytes(&m_nBOTPlayers, sizeof(m_nBOTPlayers));
|
|
mf.ReadBytes(&m_nLoadingPlayers, sizeof(m_nLoadingPlayers));
|
|
mf.ReadBytes(&m_nBroadCastPlayers, sizeof(m_nBroadCastPlayers));
|
|
|
|
int n;
|
|
n = m_nBOTPlayers + m_nLoadingPlayers + m_nBroadCastPlayers;
|
|
CMRPPlayer* p1Last = NULL;
|
|
while(n-- > 0) {
|
|
CMRPPlayer* p1 = new CMRPPlayer;
|
|
if (p1Last) {
|
|
p1Last->m_pNext = p1;
|
|
p1->m_pPrev = p1Last;
|
|
} else {
|
|
m_pMRPPlayers = p1;
|
|
}
|
|
p1Last = p1;
|
|
p1->Load(mf);
|
|
}
|
|
mf.ReadBytes(&m_fFrameTime, sizeof(m_fFrameTime));
|
|
|
|
mf.ReadBytes(&n, sizeof(n));
|
|
CMRPPack* p2Last = NULL;
|
|
while(n-- > 0) {
|
|
int nCount;
|
|
mf.ReadBytes(&nCount, sizeof(nCount));
|
|
CMRPPack* p2 = AllocMRPPack(nCount, (PMRP*)NULL);
|
|
if (p2Last) {
|
|
p2Last->m_pNext = p2;
|
|
p2->m_pPrev = p2Last;
|
|
} else {
|
|
m_pMRPPackStart = p2;
|
|
}
|
|
p2Last = p2;
|
|
p2->Load(mf, dwMeta);
|
|
}
|
|
mf.Rewind();
|
|
|
|
bRet = true;
|
|
}
|
|
|
|
free(pBuf);
|
|
fclose(f);
|
|
//if (!bRet) {
|
|
// remove(pcszFile);
|
|
//}
|
|
|
|
return true;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
Stuff::Scalar CMRPFull::EndMissionTime() const
|
|
{
|
|
Stuff::Scalar fTime = 0.0f;
|
|
CMRPPack* pMRPP = m_pMRPPackStart;
|
|
while(pMRPP) {
|
|
if (pMRPP->m_fFrameTime > fTime)
|
|
fTime = pMRPP->m_fFrameTime;
|
|
pMRPP = pMRPP->m_pNext;
|
|
}
|
|
|
|
if (fTime > m_fFrameTime)
|
|
return fTime + 0.5;
|
|
return m_fFrameTime + 0.5f;
|
|
}
|
|
|
|
void MRP_Setup()
|
|
{
|
|
g_pfn_ONGAMEOPEN = MRP_OnGameOpen;
|
|
g_pfn_ADDPLAYERTOGAME = NET_AddPlayerToGame;
|
|
g_pfn_REMOVEPLAYERFROMGAME = NET_RemovePlayerFromGame;
|
|
g_pfn_ADDREMOVE_CONNECTION = NET_AddRemoveConnection;
|
|
g_pfn_LOCALSENDNETMESSAGE = MRP_LOCALSENDNETMESSAGE;
|
|
|
|
g_nMR = 0;
|
|
}
|
|
|
|
void MRP_Cleanup()
|
|
{
|
|
g_MRF.Reset();
|
|
|
|
g_pfn_LOCALSENDNETMESSAGE = NULL;
|
|
g_pfn_ADDREMOVE_CONNECTION = NULL;
|
|
g_pfn_REMOVEPLAYERFROMGAME = NULL;
|
|
g_pfn_ADDPLAYERTOGAME = NULL;
|
|
g_pfn_ONGAMEOPEN = NULL;
|
|
}
|