Ticket #9: visualreplay-WIP-r15054.patch

File visualreplay-WIP-r15054.patch, 16.2 KB (added by sanderd17, 10 years ago)
  • binaries/data/mods/public/gui/session/selection_details.js

     
    360360}
    361361
    362362// Updates middle entity Selection Details Panel
    363 function updateSelectionDetails()
     363function updateSelectionDetails(replay)
    364364{
    365365    var supplementalDetailsPanel = Engine.GetGUIObjectByName("supplementalSelectionDetails");
    366366    var detailsPanel = Engine.GetGUIObjectByName("selectionDetails");
     
    408408    else
    409409    {
    410410        // Fill out commands panel for specific unit selected (or first unit of primary group)
    411         updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection);
     411        updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection, replay);
    412412        // Show panels
    413413        supplementalDetailsPanel.hidden = false;
    414414        commandsPanel.hidden = false;
  • binaries/data/mods/public/gui/session/unit_commands.js

     
    824824                        trainNum = buildingsCountToTrainFullBatch * fullBatchSize + remainderBatch;
    825825                        button_disableable = !Engine.HotkeyIsPressed("selection.remove");
    826826                    }
    827                     Engine.GetGUIObjectByName("unit"+guiName+"Count["+i+"]").caption = (batchTrainingCount > 0) ? batchTrainingCount : "";
     827                    var batchOverlayText = Engine.GetGUIObjectByName("unit" + guiName + "Count[" + i + "]");
     828                    if (batchOverlayText)
     829                        batchOverlayText.caption = (batchTrainingCount > 0) ? batchTrainingCount : "";
    828830                }
    829831
    830832                // Walls have no cost defined.
     
    10461048 * @param commandsPanel Reference to the "commandsPanel" GUI Object
    10471049 * @param selection Array of currently selected entity IDs.
    10481050 */
    1049 function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection)
     1051function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection, replay)
    10501052{
    10511053    // Panels that are active
    10521054    var usedPanels = {};
     
    10591061    var simState = GetSimState();
    10601062    var playerState = simState.players[player];
    10611063
    1062     if (entState.player == player || g_DevSettings.controlAll)
     1064    if (replay || entState.player == player || g_DevSettings.controlAll)
    10631065    {
    10641066        if (selection.length > 1)
    10651067            setupUnitPanel(SELECTION, usedPanels, entState, playerState, g_Selection.groups.getTemplateNames(),
    10661068                function (entType, rightPressed) { changePrimarySelectionGroup(entType, rightPressed); } );
    10671069
    1068         var commands = getEntityCommandsList(entState);
    1069         if (commands.length)
    1070             setupUnitPanel(COMMAND, usedPanels, entState, playerState, commands,
    1071                 function (item) { performCommand(entState.id, item.name); } );
     1070    if (!replay)
     1071    {
     1072          var commands = getEntityCommandsList(entState);
     1073          if (commands.length)
     1074              setupUnitPanel(COMMAND, usedPanels, entState, playerState, commands,
     1075                  function (item) { performCommand(entState.id, item.name); } );
     1076        }
    10721077
    10731078        if (entState.garrisonHolder)
    10741079        {
     
    13141319        var panel = Engine.GetGUIObjectByName("unit" + panelName + "Panel");
    13151320        if (usedPanels[panelName])
    13161321            panel.hidden = false;
    1317         else
     1322        else if (panel)
    13181323            panel.hidden = true;
    13191324    }
    13201325}
     
    13231328function hideUnitCommands()
    13241329{
    13251330    for each (var panelName in g_unitPanels)
    1326         Engine.GetGUIObjectByName("unit" + panelName + "Panel").hidden = true;
     1331    {
     1332        var panel = Engine.GetGUIObjectByName("unit" + panelName + "Panel");
     1333        if (panel)
     1334            panel.hidden = true;
     1335    }
    13271336}
    13281337
    13291338// Get all of the available entities which can be trained by the selected entities
  • source/gui/scripting/ScriptFunctions.cpp

     
    150150    return EntitySelection::PickEntitiesAtPoint(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x, y, g_Game->GetPlayerID(), false, range);
    151151}
    152152
     153std::vector<entity_id_t> PickEntitiesInRect(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int x0, int y0, int x1, int y1)
     154{
     155    return EntitySelection::PickEntitiesInRect(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x0, y0, x1, y1, INVALID_PLAYER, false);
     156}
     157
    153158std::vector<entity_id_t> PickFriendlyEntitiesInRect(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int x0, int y0, int x1, int y1, int player)
    154159{
    155160    return EntitySelection::PickEntitiesInRect(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x0, y0, x1, y1, player, false);
    156161}
    157162
     163std::vector<entity_id_t> PickEntitiesOnScreen(ScriptInterface::CxPrivate* pCxPrivate)
     164{
     165    return PickEntitiesInRect(pCxPrivate, 0, 0, g_xres, g_yres);
     166}
     167
    158168std::vector<entity_id_t> PickFriendlyEntitiesOnScreen(ScriptInterface::CxPrivate* pCxPrivate, int player)
    159169{
    160170    return PickFriendlyEntitiesInRect(pCxPrivate, 0, 0, g_xres, g_yres, player);
    161171}
    162172
     173std::vector<entity_id_t> PickSimilarEntities(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string templateName, bool includeOffScreen, bool matchRank, bool allowFoundations)
     174{
     175    return EntitySelection::PickSimilarEntities(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), templateName, INVALID_PLAYER, includeOffScreen, matchRank, false, allowFoundations);
     176}
     177
    163178std::vector<entity_id_t> PickSimilarFriendlyEntities(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string templateName, bool includeOffScreen, bool matchRank, bool allowFoundations)
    164179{
    165180    return EntitySelection::PickSimilarEntities(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), templateName, g_Game->GetPlayerID(), includeOffScreen, matchRank, false, allowFoundations);
     
    867882
    868883    // Entity picking
    869884    scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, int, int, &PickEntitiesAtPoint>("PickEntitiesAtPoint");
     885    scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, int, int, int, &PickEntitiesInRect>("PickEntitiesInRect");
    870886    scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, int, int, int, int, &PickFriendlyEntitiesInRect>("PickFriendlyEntitiesInRect");
     887    scriptInterface.RegisterFunction<std::vector<entity_id_t>, &PickEntitiesOnScreen>("PickEntitiesOnScreen");
    871888    scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, &PickFriendlyEntitiesOnScreen>("PickFriendlyEntitiesOnScreen");
     889    scriptInterface.RegisterFunction<std::vector<entity_id_t>, std::string, bool, bool, bool, &PickSimilarEntities>("PickSimilarEntities");
    872890    scriptInterface.RegisterFunction<std::vector<entity_id_t>, std::string, bool, bool, bool, &PickSimilarFriendlyEntities>("PickSimilarFriendlyEntities");
    873891    scriptInterface.RegisterFunction<CFixedVector3D, int, int, &GetTerrainAtScreenPoint>("GetTerrainAtScreenPoint");
    874892
  • 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
     
    469469
    470470
    471471
     472CNetReplayTurnManager::CNetReplayTurnManager(CSimulation2& simulation, IReplayLogger& replay) :
     473    CNetLocalTurnManager(simulation, replay)
     474{
     475}
     476
     477void CNetReplayTurnManager::StoreReplayCommand(u32 turn, int player, const std::string& command)
     478{
     479    m_ReplayCommands[turn][player].push_back(command);
     480}
     481
     482void CNetReplayTurnManager::NotifyFinishedUpdate(u32 turn)
     483{
     484    DoTurn(turn);
     485}
     486
     487void CNetReplayTurnManager::DoTurn(u32 turn)
     488{
     489    std::map<int, std::vector<std::string> > playerCommands = m_ReplayCommands[turn];
     490    std::map<int, std::vector<std::string> >::iterator it;
     491    for (it = playerCommands.begin(); it != playerCommands.end(); ++it)
     492    {
     493        int player = it->first;
     494        for (size_t i = 0; i < it->second.size(); ++i)
     495        {
     496            CScriptValRooted data = m_Simulation2.GetScriptInterface().ParseJSON(it->second[i]);
     497            AddCommand(m_ClientId, player, data, m_CurrentTurn + 1);
     498        }
     499    }
     500}
     501
     502
     503
     504
    472505CNetServerTurnManager::CNetServerTurnManager(CNetServerWorker& server) :
    473506    m_NetServer(server), m_ReadyTurn(1), m_TurnLength(DEFAULT_TURN_LENGTH_MP)
    474507{
  • source/network/NetTurnManager.h

     
    2222
    2323#include <list>
    2424#include <map>
     25#include <vector>
    2526
    2627class CNetServerWorker;
    2728class CNetClient;
     
    232233    virtual void NotifyFinishedUpdate(u32 turn);
    233234};
    234235
     236/**
     237 * Implementation of CNetTurnManager for replay games.
     238 */
     239class CNetReplayTurnManager : public CNetLocalTurnManager
     240{
     241public:
     242    CNetReplayTurnManager(CSimulation2& simulation, IReplayLogger& replay);
    235243
     244    void StoreReplayCommand(u32 turn, int player, const std::string& command);
     245
     246protected:
     247    virtual void NotifyFinishedUpdate(u32 turn);
     248
     249    void DoTurn(u32 turn);
     250
     251    std::map<u32, std::map<int, std::vector<std::string> > > m_ReplayCommands;
     252};
     253
     254
    236255/**
    237256 * The server-side counterpart to CNetClientTurnManager.
    238257 * 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

     
    850850}
    851851
    852852bool Autostart(const CmdLineArgs& args);
     853bool VisualReplay(const CmdLineArgs& args);
    853854
    854855void Init(const CmdLineArgs& args, int flags)
    855856{
     
    10171018
    10181019    try
    10191020    {
    1020         if (!Autostart(args))
     1021        if (!VisualReplay(args) && !Autostart(args))
    10211022        {
    10221023            const bool setup_gui = ((flags & INIT_NO_GUI) == 0);
    10231024            // We only want to display the splash screen at startup
     
    10591060    g_DoRenderCursor = RenderingState;
    10601061}
    10611062
     1063bool VisualReplay(const CmdLineArgs& args)
     1064{
     1065    CStr replayPath = args.Get("replay-visual");
     1066    if (!replayPath.empty())
     1067    {
     1068        g_Game = new CGame(false, false);
     1069       
     1070        g_Game->SetPlayerID(1);
     1071        g_Game->StartReplay(replayPath);
     1072
     1073        // TODO: Non progressive load can fail - need a decent way to handle this
     1074        LDR_NonprogressiveLoad();
     1075
     1076        PSRETURN ret = g_Game->ReallyStartGame();
     1077        ENSURE(ret == PSRETURN_OK);
     1078
     1079        InitPs(true, L"page_replay.xml", g_GUI->GetScriptInterface().get(), JSVAL_VOID);
     1080        return true;
     1081    }
     1082
     1083    return false;
     1084}
     1085
    10621086bool Autostart(const CmdLineArgs& args)
    10631087{
    10641088    /*
  • source/ps/Replay.cpp

     
    129129    g_ProfileViewer.AddRootTable(g_ScriptStatsTable);
    130130    g_ScriptRuntime = ScriptInterface::CreateRuntime(384 * 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'