Ticket #9: visualreplay-WIP-r14723.patch

File visualreplay-WIP-r14723.patch, 16.2 KB (added by alpha123, 10 years ago)

Update for SVN r14723. May also work on A15.

  • binaries/data/mods/public/gui/session/selection_details.js

     
    298298}
    299299
    300300// Updates middle entity Selection Details Panel
    301 function updateSelectionDetails()
     301function updateSelectionDetails(replay)
    302302{
    303303    var supplementalDetailsPanel = Engine.GetGUIObjectByName("supplementalSelectionDetails");
    304304    var detailsPanel = Engine.GetGUIObjectByName("selectionDetails");
     
    340340    commandsPanel.hidden = false;
    341341
    342342    // Fill out commands panel for specific unit selected (or first unit of primary group)
    343     updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection);
     343    updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection, replay);
    344344}
  • binaries/data/mods/public/gui/session/unit_commands.js

     
    779779                        trainNum = buildingsCountToTrainFullBatch * fullBatchSize + remainderBatch;
    780780                        button_disableable = !Engine.HotkeyIsPressed("selection.remove");
    781781                    }
    782                     Engine.GetGUIObjectByName("unit"+guiName+"Count["+i+"]").caption = (batchTrainingCount > 0) ? batchTrainingCount : "";
     782                    var batchOverlayText = Engine.GetGUIObjectByName("unit" + guiName + "Count[" + i + "]");
     783                    if (batchOverlayText)
     784                        batchOverlayText.caption = (batchTrainingCount > 0) ? batchTrainingCount : "";
    783785                }
    784786
    785787                // Walls have no cost defined.
     
    10011003 * @param commandsPanel Reference to the "commandsPanel" GUI Object
    10021004 * @param selection Array of currently selected entity IDs.
    10031005 */
    1004 function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection)
     1006function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection, replay)
    10051007{
    10061008    // Panels that are active
    10071009    var usedPanels = {};
     
    10141016    var simState = GetSimState();
    10151017    var playerState = simState.players[player];
    10161018
    1017     if (entState.player == player || g_DevSettings.controlAll)
     1019    if (replay || entState.player == player || g_DevSettings.controlAll)
    10181020    {
    10191021        if (selection.length > 1)
    10201022            setupUnitPanel(SELECTION, usedPanels, entState, playerState, g_Selection.groups.getTemplateNames(),
    10211023                function (entType, rightPressed) { changePrimarySelectionGroup(entType, rightPressed); } );
    10221024
    1023         var commands = getEntityCommandsList(entState);
    1024         if (commands.length)
    1025             setupUnitPanel(COMMAND, usedPanels, entState, playerState, commands,
    1026                 function (item) { performCommand(entState.id, item.name); } );
     1025    if (!replay)
     1026    {
     1027          var commands = getEntityCommandsList(entState);
     1028          if (commands.length)
     1029              setupUnitPanel(COMMAND, usedPanels, entState, playerState, commands,
     1030                  function (item) { performCommand(entState.id, item.name); } );
     1031        }
    10271032
    10281033        if (entState.garrisonHolder)
    10291034        {
     
    12361241        var panel = Engine.GetGUIObjectByName("unit" + panelName + "Panel");
    12371242        if (usedPanels[panelName])
    12381243            panel.hidden = false;
    1239         else
     1244        else if (panel)
    12401245            panel.hidden = true;
    12411246    }
    12421247}
     
    12451250function hideUnitCommands()
    12461251{
    12471252    for each (var panelName in g_unitPanels)
    1248         Engine.GetGUIObjectByName("unit" + panelName + "Panel").hidden = true;
     1253    {
     1254        var panel = Engine.GetGUIObjectByName("unit" + panelName + "Panel");
     1255        if (panel)
     1256            panel.hidden = true;
     1257    }
    12491258}
    12501259
    12511260// Get all of the available entities which can be trained by the selected entities
  • source/gui/scripting/ScriptFunctions.cpp

     
    153153    return EntitySelection::PickEntitiesAtPoint(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x, y, g_Game->GetPlayerID(), false, range);
    154154}
    155155
     156std::vector<entity_id_t> PickEntitiesInRect(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int x0, int y0, int x1, int y1)
     157{
     158    return EntitySelection::PickEntitiesInRect(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x0, y0, x1, y1, INVALID_PLAYER, false);
     159}
     160
    156161std::vector<entity_id_t> PickFriendlyEntitiesInRect(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int x0, int y0, int x1, int y1, int player)
    157162{
    158163    return EntitySelection::PickEntitiesInRect(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x0, y0, x1, y1, player, false);
    159164}
    160165
     166std::vector<entity_id_t> PickEntitiesOnScreen(ScriptInterface::CxPrivate* pCxPrivate)
     167{
     168    return PickEntitiesInRect(pCxPrivate, 0, 0, g_xres, g_yres);
     169}
     170
    161171std::vector<entity_id_t> PickFriendlyEntitiesOnScreen(ScriptInterface::CxPrivate* pCxPrivate, int player)
    162172{
    163173    return PickFriendlyEntitiesInRect(pCxPrivate, 0, 0, g_xres, g_yres, player);
    164174}
    165175
     176std::vector<entity_id_t> PickSimilarEntities(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string templateName, bool includeOffScreen, bool matchRank, bool allowFoundations)
     177{
     178    return EntitySelection::PickSimilarEntities(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), templateName, INVALID_PLAYER, includeOffScreen, matchRank, false, allowFoundations);
     179}
     180
    166181std::vector<entity_id_t> PickSimilarFriendlyEntities(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string templateName, bool includeOffScreen, bool matchRank, bool allowFoundations)
    167182{
    168183    return EntitySelection::PickSimilarEntities(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), templateName, g_Game->GetPlayerID(), includeOffScreen, matchRank, false, allowFoundations);
     
    810825
    811826    // Entity picking
    812827    scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, int, int, &PickEntitiesAtPoint>("PickEntitiesAtPoint");
     828    scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, int, int, int, &PickEntitiesInRect>("PickEntitiesInRect");
    813829    scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, int, int, int, int, &PickFriendlyEntitiesInRect>("PickFriendlyEntitiesInRect");
     830    scriptInterface.RegisterFunction<std::vector<entity_id_t>, &PickEntitiesOnScreen>("PickEntitiesOnScreen");
    814831    scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, &PickFriendlyEntitiesOnScreen>("PickFriendlyEntitiesOnScreen");
     832    scriptInterface.RegisterFunction<std::vector<entity_id_t>, std::string, bool, bool, bool, &PickSimilarEntities>("PickSimilarEntities");
    815833    scriptInterface.RegisterFunction<std::vector<entity_id_t>, std::string, bool, bool, bool, &PickSimilarFriendlyEntities>("PickSimilarFriendlyEntities");
    816834    scriptInterface.RegisterFunction<CFixedVector3D, int, int, &GetTerrainAtScreenPoint>("GetTerrainAtScreenPoint");
    817835
  • 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
     
    464464
    465465
    466466
     467CNetReplayTurnManager::CNetReplayTurnManager(CSimulation2& simulation, IReplayLogger& replay) :
     468    CNetLocalTurnManager(simulation, replay)
     469{
     470}
     471
     472void CNetReplayTurnManager::StoreReplayCommand(u32 turn, int player, const std::string& command)
     473{
     474    m_ReplayCommands[turn][player].push_back(command);
     475}
     476
     477void CNetReplayTurnManager::NotifyFinishedUpdate(u32 turn)
     478{
     479    DoTurn(turn);
     480}
     481
     482void CNetReplayTurnManager::DoTurn(u32 turn)
     483{
     484    std::map<int, std::vector<std::string> > playerCommands = m_ReplayCommands[turn];
     485    std::map<int, std::vector<std::string> >::iterator it;
     486    for (it = playerCommands.begin(); it != playerCommands.end(); ++it)
     487    {
     488        int player = it->first;
     489        for (size_t i = 0; i < it->second.size(); ++i)
     490        {
     491            CScriptValRooted data = m_Simulation2.GetScriptInterface().ParseJSON(it->second[i]);
     492            AddCommand(m_ClientId, player, data, m_CurrentTurn + 1);
     493        }
     494    }
     495}
     496
     497
     498
     499
    467500CNetServerTurnManager::CNetServerTurnManager(CNetServerWorker& server) :
    468501    m_NetServer(server), m_ReadyTurn(1), m_TurnLength(DEFAULT_TURN_LENGTH_MP)
    469502{
  • source/network/NetTurnManager.h

     
    2222
    2323#include <list>
    2424#include <map>
     25#include <vector>
    2526
    2627class CNetServerWorker;
    2728class CNetClient;
     
    227228    virtual void NotifyFinishedUpdate(u32 turn);
    228229};
    229230
     231/**
     232 * Implementation of CNetTurnManager for replay games.
     233 */
     234class CNetReplayTurnManager : public CNetLocalTurnManager
     235{
     236public:
     237    CNetReplayTurnManager(CSimulation2& simulation, IReplayLogger& replay);
    230238
     239    void StoreReplayCommand(u32 turn, int player, const std::string& command);
     240
     241protected:
     242    virtual void NotifyFinishedUpdate(u32 turn);
     243
     244    void DoTurn(u32 turn);
     245
     246    std::map<u32, std::map<int, std::vector<std::string> > > m_ReplayCommands;
     247};
     248
     249
    231250/**
    232251 * The server-side counterpart to CNetClientTurnManager.
    233252 * Records the turn state of each client, and sends turn advancement messages
  • source/ps/Game.cpp

     
    6262 * Constructor
    6363 *
    6464 **/
    65 CGame::CGame(bool disableGraphics):
     65CGame::CGame(bool disableGraphics, bool replayLog):
    6666    m_World(new CWorld(this)),
    6767    m_Simulation2(new CSimulation2(&m_World->GetUnitManager(), g_ScriptRuntime, m_World->GetTerrain())),
    6868    m_GameView(disableGraphics ? NULL : new CGameView(this)),
     
    7070    m_Paused(false),
    7171    m_SimRate(1.0f),
    7272    m_PlayerID(-1),
    73     m_IsSavedGame(false)
     73    m_IsSavedGame(false),
     74    m_IsReplay(false),
     75    m_ReplayStream(NULL)
    7476{
    75     m_ReplayLogger = new CReplayLogger(m_Simulation2->GetScriptInterface());
    7677    // TODO: should use CDummyReplayLogger unless activated by cmd-line arg, perhaps?
     78    if (replayLog)
     79        m_ReplayLogger = new CReplayLogger(m_Simulation2->GetScriptInterface());
     80    else
     81        m_ReplayLogger = new CDummyReplayLogger();
    7782
    7883    // Need to set the CObjectManager references after various objects have
    7984    // been initialised, so do it here rather than via the initialisers above.
     
    100105    delete m_Simulation2;
    101106    delete m_World;
    102107    delete m_ReplayLogger;
     108    delete m_ReplayStream;
    103109}
    104110
    105111void CGame::SetTurnManager(CNetTurnManager* turnManager)
     
    170176    if (m_IsSavedGame)
    171177        RegMemFun(this, &CGame::LoadInitialState, L"Loading game", 1000);
    172178
     179    if (m_IsReplay)
     180        RegMemFun(this, &CGame::LoadReplayData, L"Loading replay data", 1000);
     181
    173182    LDR_EndRegistering();
    174183}
    175184
     
    193202    return 0;
    194203}
    195204
     205int CGame::LoadReplayData()
     206{
     207    ENSURE(m_IsReplay);
     208    ENSURE(!m_ReplayPath.empty());
     209
     210    CNetReplayTurnManager* replayTurnMgr = static_cast<CNetReplayTurnManager*>(GetTurnManager());
     211
     212    u32 currentTurn = 0;
     213    std::string type;
     214    while ((*m_ReplayStream >> type).good())
     215    {
     216        if (type == "turn")
     217        {
     218            u32 turn = 0;
     219            u32 turnLength = 0;
     220            *m_ReplayStream >> turn >> turnLength;
     221            ENSURE(turn == currentTurn);
     222        }
     223        else if (type == "cmd")
     224        {
     225            int player;
     226            *m_ReplayStream >> player;
     227
     228            std::string line;
     229            std::getline(*m_ReplayStream, line);
     230            replayTurnMgr->StoreReplayCommand(currentTurn, player, line);
     231        }
     232        else if (type == "hash" || type == "hash-quick")
     233        {
     234            // Ignored for now
     235            std::string replayHash;
     236            *m_ReplayStream >> replayHash;
     237        }
     238        else if (type == "end")
     239        {
     240            currentTurn++;
     241        }
     242        else
     243        {
     244            CancelLoad(L"Failed to load replay data (unrecognized content)");
     245        }
     246    }
     247    m_FinalReplayTurn = currentTurn + 1;
     248
     249    return 0;
     250}
     251
     252void CGame::StartReplay(const std::string& replayPath)
     253{
     254    m_IsReplay = true;
     255
     256    SetTurnManager(new CNetReplayTurnManager(*m_Simulation2, GetReplayLogger()));
     257
     258    m_ReplayPath = replayPath;
     259    m_ReplayStream = new std::ifstream(m_ReplayPath.c_str());
     260    ENSURE(m_ReplayStream->good());
     261
     262    std::string type;
     263    ENSURE((*m_ReplayStream >> type).good() && type == "start");
     264
     265    std::string line;
     266    std::getline(*m_ReplayStream, line);
     267    CScriptValRooted attribs = m_Simulation2->GetScriptInterface().ParseJSON(line);
     268    StartGame(attribs, "");
     269}
     270
    196271/**
    197272 * Game initialization has been completed. Set game started flag and start the session.
    198273 *
     
    306381                g_GUI->SendEventToAll("SimulationUpdate");
    307382            }
    308383
     384            if (m_IsReplay && m_TurnManager->GetCurrentTurn() == m_FinalReplayTurn)
     385                g_GUI->SendEventToAll("ReplayFinished");
     386
    309387            GetView()->GetLOSTexture().MakeDirty();
    310388        }
    311389       
  • source/ps/Game.h

     
    1919#define INCLUDED_GAME
    2020
    2121#include "ps/Errors.h"
     22#include <map>
    2223#include <vector>
    2324
    2425#include "scriptinterface/ScriptVal.h"
     
    6566    CNetTurnManager* m_TurnManager;
    6667
    6768public:
    68     CGame(bool disableGraphics = false);
     69    CGame(bool disableGraphics = false, bool replayLog = true);
    6970    ~CGame();
    7071
    7172    /**
     
    7677    void StartGame(const CScriptValRooted& attribs, const std::string& savedState);
    7778    PSRETURN ReallyStartGame();
    7879
     80    void StartReplay(const std::string& replayPath);
     81
    7982    /**
    8083     * Periodic heartbeat that controls the process. performs all per-frame updates.
    8184     * Simulation update is called and game status update is called.
     
    171174    int LoadInitialState();
    172175    std::string m_InitialSavedState; // valid between RegisterInit and LoadInitialState
    173176    bool m_IsSavedGame; // true if loading a saved game; false for a new game
     177
     178    int LoadReplayData();
     179    std::string m_ReplayPath;
     180    bool m_IsReplay;
     181    std::istream* m_ReplayStream;
     182    u32 m_FinalReplayTurn;
    174183};
    175184
    176185extern CGame *g_Game;
  • source/ps/GameSetup/GameSetup.cpp

     
    843843}
    844844
    845845bool Autostart(const CmdLineArgs& args);
     846bool VisualReplay(const CmdLineArgs& args);
    846847
    847848void Init(const CmdLineArgs& args, int flags)
    848849{
     
    10121013
    10131014    try
    10141015    {
    1015         if (!Autostart(args))
     1016        if (!VisualReplay(args) && !Autostart(args))
    10161017        {
    10171018            const bool setup_gui = ((flags & INIT_NO_GUI) == 0);
    10181019            // We only want to display the splash screen at startup
     
    10541055    g_DoRenderCursor = RenderingState;
    10551056}
    10561057
     1058bool VisualReplay(const CmdLineArgs& args)
     1059{
     1060    CStr replayPath = args.Get("replay-visual");
     1061    if (!replayPath.empty())
     1062    {
     1063        g_Game = new CGame(false, false);
     1064       
     1065        g_Game->SetPlayerID(1);
     1066        g_Game->StartReplay(replayPath);
     1067
     1068        // TODO: Non progressive load can fail - need a decent way to handle this
     1069        LDR_NonprogressiveLoad();
     1070
     1071        PSRETURN ret = g_Game->ReallyStartGame();
     1072        ENSURE(ret == PSRETURN_OK);
     1073
     1074        InitPs(true, L"page_replay.xml", g_GUI->GetScriptInterface().get(), JSVAL_VOID);
     1075        return true;
     1076    }
     1077
     1078    return false;
     1079}
     1080
    10571081bool Autostart(const CmdLineArgs& args)
    10581082{
    10591083    /*
  • source/ps/Replay.cpp

     
    129129    g_ProfileViewer.AddRootTable(g_ScriptStatsTable);
    130130    g_ScriptRuntime = ScriptInterface::CreateRuntime(128 * 1024 * 1024);
    131131
    132     CGame game(true);
     132    CGame game(true, false);
    133133    g_Game = &game;
    134134
    135135    // Need some stuff for terrain movement costs:
  • source/simulation2/helpers/Selection.cpp

     
    212212
    213213        // Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld)
    214214        // In this case, the checking is done to avoid selecting garrisoned units
    215         if (cmpRangeManager->GetLosVisibility(handle, owner) == ICmpRangeManager::VIS_HIDDEN)
     215        if (owner != INVALID_PLAYER && cmpRangeManager->GetLosVisibility(handle, owner) == ICmpRangeManager::VIS_HIDDEN)
    216216            continue;
    217217
    218218        // Ignore entities not owned by 'owner'