Ticket #9: visualreplay-WIP-r16491_no_gui.patch

File visualreplay-WIP-r16491_no_gui.patch, 10.3 KB (added by elexis, 9 years ago)

Updated patch and removed GUI code. Replays a commands.txt file visually without GUI.

  • source/network/NetTurnManager.cpp

     
    3838#include <iomanip>
    3939
    4040static const int DEFAULT_TURN_LENGTH_MP = 500;
    41 static const int DEFAULT_TURN_LENGTH_SP = 200;
     41static const int DEFAULT_TURN_LENGTH_SP = 500;
    4242
    4343static const int COMMAND_DELAY = 2;
    4444
     
    467467
    468468
    469469
     470CNetReplayTurnManager::CNetReplayTurnManager(CSimulation2& simulation, IReplayLogger& replay) :
     471    CNetLocalTurnManager(simulation, replay)
     472{
     473}
     474
     475void CNetReplayTurnManager::StoreReplayCommand(u32 turn, int player, const std::string& command)
     476{
     477    m_ReplayCommands[turn][player].push_back(command);
     478}
     479
     480void CNetReplayTurnManager::NotifyFinishedUpdate(u32 turn)
     481{
     482    DoTurn(turn);
     483}
     484
     485void CNetReplayTurnManager::DoTurn(u32 turn)
     486{
     487    std::map<int, std::vector<std::string> > playerCommands = m_ReplayCommands[turn];
     488    std::map<int, std::vector<std::string> >::iterator it;
     489    for (it = playerCommands.begin(); it != playerCommands.end(); ++it)
     490    {
     491        int player = it->first;
     492        for (size_t i = 0; i < it->second.size(); ++i)
     493        {
     494            //JS::HandleValue data;
     495            JS::RootedValue data(m_Simulation2.GetScriptInterface().GetContext());
     496            // JS::MutableHandleValue data;
     497            m_Simulation2.GetScriptInterface().ParseJSON(it->second[i], &data);
     498            AddCommand(m_ClientId, player, data, m_CurrentTurn + 1);
     499        }
     500    }
     501}
     502
     503
     504
     505
    470506CNetServerTurnManager::CNetServerTurnManager(CNetServerWorker& server) :
    471507    m_NetServer(server), m_ReadyTurn(1), m_TurnLength(DEFAULT_TURN_LENGTH_MP)
    472508{
  • source/network/NetTurnManager.h

     
    2222
    2323#include <list>
    2424#include <map>
    25 
     25#include <vector>
    2626class CNetServerWorker;
    2727class CNetClient;
    2828class CSimulationMessage;
     
    189189    std::string m_QuickSaveMetadata;
    190190};
    191191
     192
    192193/**
    193194 * Implementation of CNetTurnManager for network clients.
    194195 */
     
    233234};
    234235
    235236
     237
    236238/**
     239 * Implementation of CNetTurnManager for replay games.
     240 */
     241class CNetReplayTurnManager : public CNetLocalTurnManager
     242{
     243public:
     244    CNetReplayTurnManager(CSimulation2& simulation, IReplayLogger& replay);
     245
     246    void StoreReplayCommand(u32 turn, int player, const std::string& command);
     247
     248protected:
     249    virtual void NotifyFinishedUpdate(u32 turn);
     250
     251    void DoTurn(u32 turn);
     252
     253    std::map<u32, std::map<int, std::vector<std::string> > > m_ReplayCommands;
     254};
     255/**
    237256 * The server-side counterpart to CNetClientTurnManager.
    238257 * Records the turn state of each client, and sends turn advancement messages
    239258 * when all clients are ready.
  • source/ps/Game.cpp

     
    6363 * Constructor
    6464 *
    6565 **/
    66 CGame::CGame(bool disableGraphics):
     66CGame::CGame(bool disableGraphics, bool replayLog):
    6767    m_World(new CWorld(this)),
    6868    m_Simulation2(new CSimulation2(&m_World->GetUnitManager(), g_ScriptRuntime, m_World->GetTerrain())),
    6969    m_GameView(disableGraphics ? NULL : new CGameView(this)),
     
    7171    m_Paused(false),
    7272    m_SimRate(1.0f),
    7373    m_PlayerID(-1),
    74     m_IsSavedGame(false)
     74    m_IsSavedGame(false),
     75    m_IsReplay(false),
     76    m_ReplayStream(NULL)
    7577{
    7678    m_ReplayLogger = new CReplayLogger(m_Simulation2->GetScriptInterface());
    77     // TODO: should use CDummyReplayLogger unless activated by cmd-line arg, perhaps?
     79    /* TODO: use CDummyReplayLogger ?
     80    if (replayLog)
     81        m_ReplayLogger = new CReplayLogger(m_Simulation2->GetScriptInterface());
     82    else
     83        m_ReplayLogger = new CDummyReplayLogger();
     84    */
    7885
    7986    // Need to set the CObjectManager references after various objects have
    8087    // been initialised, so do it here rather than via the initialisers above.
     
    8592
    8693    m_Simulation2->LoadDefaultScripts();
    8794}
     95int CGame::LoadReplayData()
     96{
     97    ENSURE(m_IsReplay);
     98    ENSURE(!m_ReplayPath.empty());
    8899
     100    CNetReplayTurnManager* replayTurnMgr = static_cast<CNetReplayTurnManager*>(GetTurnManager());
     101
     102    u32 currentTurn = 0;
     103    std::string type;
     104    while ((*m_ReplayStream >> type).good())
     105    {
     106        if (type == "turn")
     107        {
     108            u32 turn = 0;
     109            u32 turnLength = 0;
     110            *m_ReplayStream >> turn >> turnLength;
     111            ENSURE(turn == currentTurn);
     112        }
     113        else if (type == "cmd")
     114        {
     115            int player;
     116            *m_ReplayStream >> player;
     117
     118            std::string line;
     119            std::getline(*m_ReplayStream, line);
     120            replayTurnMgr->StoreReplayCommand(currentTurn, player, line);
     121        }
     122        else if (type == "hash" || type == "hash-quick")
     123        {
     124            // Ignored for now
     125            std::string replayHash;
     126            *m_ReplayStream >> replayHash;
     127        }
     128        else if (type == "end")
     129        {
     130            currentTurn++;
     131        }
     132        else
     133        {
     134            CancelLoad(L"Failed to load replay data (unrecognized content)");
     135        }
     136    }
     137    m_FinalReplayTurn = currentTurn + 1;
     138
     139    return 0;
     140}
     141void CGame::StartReplay(const std::string& replayPath)
     142{
     143    m_IsReplay = true;
     144    ScriptInterface& scriptInterface = m_Simulation2->GetScriptInterface();
     145
     146    SetTurnManager(new CNetReplayTurnManager(*m_Simulation2, GetReplayLogger()));
     147
     148    m_ReplayPath = replayPath;
     149    m_ReplayStream = new std::ifstream(m_ReplayPath.c_str());
     150    ENSURE(m_ReplayStream->good());
     151
     152    std::string type;
     153    ENSURE((*m_ReplayStream >> type).good() && type == "start");
     154
     155    std::string line;
     156    std::getline(*m_ReplayStream, line);
     157    JS::RootedValue attribs(scriptInterface.GetContext());
     158    scriptInterface.ParseJSON(line, &attribs);
     159    StartGame(&attribs, "");
     160}
    89161/**
    90162 * Destructor
    91163 *
     
    101173    delete m_Simulation2;
    102174    delete m_World;
    103175    delete m_ReplayLogger;
     176    delete m_ReplayStream;
    104177}
    105178
    106179void CGame::SetTurnManager(CNetTurnManager* turnManager)
     
    125198    ScriptInterface& scriptInterface = m_Simulation2->GetScriptInterface();
    126199    JSContext* cx = scriptInterface.GetContext();
    127200    JSAutoRequest rq(cx);
    128    
     201
    129202    m_InitialSavedState = savedState;
    130203    m_IsSavedGame = !savedState.empty();
    131204
     
    176249    if (m_IsSavedGame)
    177250        RegMemFun(this, &CGame::LoadInitialState, L"Loading game", 1000);
    178251
     252    if (m_IsReplay)
     253        RegMemFun(this, &CGame::LoadReplayData, L"Loading replay data", 1000);
     254
    179255    LDR_EndRegistering();
    180256}
    181257
     
    208284{
    209285    JSContext* cx = m_Simulation2->GetScriptInterface().GetContext();
    210286    JSAutoRequest rq(cx);
    211    
     287
    212288    // Call the script function InitGame only for new games, not saved games
    213289    if (!m_IsSavedGame)
    214290    {
     
    230306    Interpolate(0, 0);
    231307
    232308    m_GameStarted=true;
    233    
     309
    234310    // Render a frame to begin loading assets
    235311    if (CRenderer::IsInitialised())
    236312        Render();
     
    289365        return true;
    290366
    291367    const double deltaSimTime = deltaRealTime * m_SimRate;
    292    
     368
    293369    bool ok = true;
    294370    if (deltaSimTime)
    295371    {
     
    310386                PROFILE3("gui sim update");
    311387                g_GUI->SendEventToAll("SimulationUpdate");
    312388            }
     389             if (m_IsReplay && m_TurnManager->GetCurrentTurn() == m_FinalReplayTurn)
     390                 g_GUI->SendEventToAll("ReplayFinished");
    313391
    314392            GetView()->GetLOSTexture().MakeDirty();
    315393        }
    316        
     394
    317395        if (CRenderer::IsInitialised())
    318396            g_Renderer.GetTimeManager().Update(deltaSimTime);
    319397    }
  • source/ps/Game.h

     
    2020
    2121#include "ps/Errors.h"
    2222#include <vector>
    23 
     23#include <map>
    2424#include "scriptinterface/ScriptVal.h"
    2525
    2626class CWorld;
     
    6565    CNetTurnManager* m_TurnManager;
    6666
    6767public:
    68     CGame(bool disableGraphics = false);
     68    CGame(bool disableGraphics = false, bool replayLog = true);
    6969    ~CGame();
    7070
    7171    /**
     
    7676    void StartGame(JS::MutableHandleValue attribs, const std::string& savedState);
    7777    PSRETURN ReallyStartGame();
    7878
     79    void StartReplay(const std::string& replayPath);
     80
    7981    /**
    8082     * Periodic heartbeat that controls the process. performs all per-frame updates.
    8183     * Simulation update is called and game status update is called.
     
    171173    int LoadInitialState();
    172174    std::string m_InitialSavedState; // valid between RegisterInit and LoadInitialState
    173175    bool m_IsSavedGame; // true if loading a saved game; false for a new game
     176
     177    int LoadReplayData();
     178    std::string m_ReplayPath;
     179    bool m_IsReplay;
     180    std::istream* m_ReplayStream;
     181    u32 m_FinalReplayTurn;
    174182};
    175183
    176184extern CGame *g_Game;
  • source/ps/GameSetup/GameSetup.cpp

     
    880880}
    881881
    882882bool Autostart(const CmdLineArgs& args);
     883bool VisualReplay(const CmdLineArgs& args);
    883884
    884885bool Init(const CmdLineArgs& args, int flags)
    885886{
     
    10731074
    10741075    try
    10751076    {
    1076         if (!Autostart(args))
     1077        if (!VisualReplay(args) && !Autostart(args))
    10771078        {
    10781079            const bool setup_gui = ((flags & INIT_NO_GUI) == 0);
    10791080            // We only want to display the splash screen at startup
     
    14731474    return true;
    14741475}
    14751476
     1477bool VisualReplay(const CmdLineArgs& args)
     1478{
     1479    CStr replayPath = args.Get("replay-visual");
     1480    if (!replayPath.empty())
     1481    {
     1482        g_Game = new CGame(false, false);
     1483
     1484        g_Game->SetPlayerID(1);
     1485        g_Game->StartReplay(replayPath);
     1486
     1487        // TODO: Non progressive load can fail - need a decent way to handle this
     1488        LDR_NonprogressiveLoad();
     1489
     1490        PSRETURN ret = g_Game->ReallyStartGame();
     1491        ENSURE(ret == PSRETURN_OK);
     1492
     1493        ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface();
     1494
     1495        InitPs(true, L"page_replay.xml", &scriptInterface, JS::UndefinedHandleValue);
     1496        return true;
     1497    }
     1498
     1499    return false;
     1500}
     1501
    14761502void CancelLoad(const CStrW& message)
    14771503{
    14781504    shared_ptr<ScriptInterface> pScriptInterface = g_GUI->GetActiveGUI()->GetScriptInterface();