void GameClient::ExecuteNWF() { // Geschickte Network Commands der Spieler ausführen und ggf. im Replay aufzeichnen AsyncChecksum checksum = AsyncChecksum::create(*game); const unsigned curGF = GetGFNumber(); for(const NWFPlayerInfo& player : nwfInfo->getPlayerInfos()) { const PlayerGameCommands& currentGCs = player.commands.front(); // Command im Replay aufzeichnen (wenn nicht gerade eins schon läuft xD) // Nur Commands reinschreiben, KEINE PLATZHALTER (nc_count = 0) if(!currentGCs.gcs.empty() && replayinfo && replayinfo->replay.IsRecording()) { // Set the current checksum as the GF checksum. The checksum from the command is from the last NWF! PlayerGameCommands replayCmds(checksum, currentGCs.gcs); replayinfo->replay.AddGameCommand(curGF, player.id, replayCmds); } // Das ganze Zeug soll die andere Funktion ausführen ExecuteAllGCs(player.id, currentGCs); } // Send GC message for this NWF // First for all potential AIs as we need to combine the AI cmds of the local player with our own ones for(AIPlayer& ai : game->aiPlayers_) { const std::vector<gc::GameCommandPtr> aiGCs = ai.FetchGameCommands(); /// Cmds from own AI get added to our gcs if(ai.GetPlayerId() == GetPlayerId()) gameCommands_.insert(gameCommands_.end(), aiGCs.begin(), aiGCs.end()); else mainPlayer.sendMsgAsync(new GameMessage_GameCommand(ai.GetPlayerId(), checksum, aiGCs)); } mainPlayer.sendMsgAsync(new GameMessage_GameCommand(0xFF, checksum, gameCommands_)); gameCommands_.clear(); }
void GameClient::ExecuteGameFrame_Replay() { randcheckinfo.rand = RANDOM.GetCurrentRandomValue(); AsyncChecksum checksum(randcheckinfo.rand); const unsigned curGF = GetGFNumber(); RTTR_Assert(replayinfo.next_gf >= curGF || curGF > replayinfo.replay.lastGF_); // Execute all commands from the replay for the current GF while(replayinfo.next_gf == curGF) { // What type of command follows? Replay::ReplayCommand rc = replayinfo.replay.ReadRCType(); if(rc == Replay::RC_CHAT) { unsigned char player, dest; std::string message; replayinfo.replay.ReadChatCommand(&player, &dest, message); if(ci) ci->CI_Chat(player, ChatDestination(dest), message); } else if(rc == Replay::RC_GAME) { std::vector<unsigned char> gcData = replayinfo.replay.ReadGameCommand(); Serializer ser(&gcData.front(), gcData.size()); GameMessage_GameCommand msg; msg.Deserialize(ser); // Execute them ExecuteAllGCs(msg); // Check for async if checksum data is valid if(msg.checksum.randState != 0 && msg.checksum != checksum) { // Show message if this is the first async GF if(replayinfo.async == 0) { char text[256]; sprintf(text, _("Warning: The played replay is not in sync with the original match. (GF: %u)"), curGF); if(ci) ci->CI_ReplayAsync(text); LOG.write("Async at GF %u: Checksum %i:%i ObjCt %u:%u ObjIdCt %u:%u\n") % curGF % msg.checksum.randState % checksum.randState % msg.checksum.objCt % checksum.objCt % msg.checksum.objIdCt % checksum.objIdCt; // and pause the game for further investigation framesinfo.isPaused = true; } replayinfo.async++; } } // Read GF of next command replayinfo.replay.ReadGF(&replayinfo.next_gf); } // Run game simulation NextGF(); // Check for game end if(curGF == replayinfo.replay.lastGF_) { char text[256]; sprintf(text, _("Notice: The played replay has ended. (GF: %u, %dh %dmin %ds, TF: %u, AVG_FPS: %u)"), curGF, GAMEMANAGER.GetRuntime() / 3600, ((GAMEMANAGER.GetRuntime()) % 3600) / 60, (GameManager::inst().GetRuntime()) % 3600 % 60, GameManager::inst().GetFrameCount(), GameManager::inst().GetAverageFPS()); if(ci) ci->CI_ReplayEndReached(text); if(replayinfo.async != 0) { char text[256]; sprintf(text, _("Notice: Overall asynchronous frame count: %u"), replayinfo.async); // Messenger im Game if(ci) ci->CI_ReplayEndReached(text); } replayinfo.end = true; framesinfo.isPaused = true; } }