void GameClient::ExecuteNWF()
{
    // Geschickte Network Commands der Spieler ausführen und ggf. im Replay aufzeichnen

    AsyncChecksum checksum(RANDOM.GetCurrentRandomValue());

    for(unsigned char i = 0; i < players.getCount(); ++i)
    {
        if(players[i].isUsed())
        {
            GameMessage_GameCommand& msg = players[i].gc_queue.front();

            // Command im Replay aufzeichnen (wenn nicht gerade eins schon läuft xD)
            // Nur Commands reinschreiben, KEINE PLATZHALTER (nc_count = 0)
            if(!msg.gcs.empty() && !replay_mode)
            {
                // Aktuelle Checksumme reinschreiben
                msg.checksum = checksum;
                Serializer ser;
                msg.Serialize(ser);
                replayinfo.replay.AddGameCommand(framesinfo.gf_nr, ser.GetLength(), ser.GetData());
            }

            // Das ganze Zeug soll die andere Funktion ausführen
            ExecuteAllGCs(msg);

            // Nachricht abwerfen :)
            players[i].gc_queue.pop();
        }
    }

    // Send GC message for this NWF
    send_queue.push(new GameMessage_GameCommand(playerId_, checksum, gameCommands_));
    LOG.write("CLIENT >>> GC %u\n", playerId_);

    // alles gesendet --> Liste löschen
    gameCommands_.clear();

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

    RTTR_Assert(replayinfo.next_gf >= framesinfo.gf_nr || framesinfo.gf_nr > replayinfo.replay.lastGF_);

    // Commands alle aus der Datei lesen
    while(replayinfo.next_gf == framesinfo.gf_nr) // Schon an der Zeit?
    {
        // RC-Type auslesen
        Replay::ReplayCommand rc = replayinfo.replay.ReadRCType();

        // Chat Command?
        if(rc == Replay::RC_CHAT)
        {
            unsigned char player, dest;
            std::string message;
            replayinfo.replay.ReadChatCommand(&player, &dest, message);

            // Nächsten Zeitpunkt lesen
            replayinfo.replay.ReadGF(&replayinfo.next_gf);

            if(ci)
                ci->CI_Chat(player, ChatDestination(dest), message);
        }
        // Game Command?
        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);
            // Nächsten Zeitpunkt lesen
            replayinfo.replay.ReadGF(&replayinfo.next_gf);

            // NCs ausführen (4 Bytes Checksumme und 1 Byte Player-ID überspringen)
            ExecuteAllGCs(msg);

            // Replay ist NSYNC äh ASYNC!
            if(msg.checksum.randState != 0 &&  msg.checksum != checksum)
            {
                if(replayinfo.async == 0)
                {
                    // Meldung mit GF erzeugen
                    char text[256];
                    sprintf(text, _("Warning: The played replay is not in sync with the original match. (GF: %u)"), framesinfo.gf_nr);

                    // Messenger im Game (prints to console too)
                    if(ci)
                        ci->CI_ReplayAsync(text);

                    LOG.lprintf("Async at GF %u: Checksum %i:%i ObjCt %u:%u ObjIdCt %u:%u\n", framesinfo.gf_nr,
                        msg.checksum.randState, checksum.randState,
                        msg.checksum.objCt, checksum.objCt,
                        msg.checksum.objIdCt, checksum.objIdCt);

                    // pausieren
                    framesinfo.isPaused = true;
                }

                replayinfo.async++;
            }

            // resync random generator, so replay "can't" be async.
            // (of course it can, since we resynchronize only after each command, the command itself could be use multiple rand values)
            //RANDOM.ReplaySet(msg.checksum);
        }
    }

    // Frame ausführen
    NextGF();

    // Replay zu Ende?
    if(framesinfo.gf_nr == replayinfo.replay.lastGF_)
    {
        // Replay zu Ende

        // Meldung erzeugen
        char text[256];
        sprintf(text, _("Notice: The played replay has ended. (GF: %u, %dh %dmin %ds, TF: %u, AVG_FPS: %u)"), framesinfo.gf_nr, GAMEMANAGER.GetRuntime() / 3600, ((GAMEMANAGER.GetRuntime()) % 3600) / 60, (GameManager::inst().GetRuntime()) % 3600 % 60, GameManager::inst().GetFrameCount(), GameManager::inst().GetAverageFPS());

        // Messenger im Game
        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;

        // pausieren
        framesinfo.isPaused = true;
    }
}
예제 #4
0
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;
    }
}