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; }