Ticket #3258: replay_menu_wip_v1.patch

File replay_menu_wip_v1.patch, 26.0 KB (added by elexis, 9 years ago)

Works, but the GUI should be enriched. Adds a main menu entry for listing replays and starting or deleting them. Cleans visual replay a bit. Saves engine_version.txt. Prevents the creation of empty commands.txt.

  • binaries/data/mods/public/gui/page_replay.xml

     
     1<?xml version="1.0" encoding="utf-8"?>
     2<page>
     3    <include>common/modern/setup.xml</include>
     4    <include>common/modern/styles.xml</include>
     5    <include>common/modern/sprites.xml</include>
     6
     7    <include>common/setup.xml</include>
     8    <include>common/sprite1.xml</include>
     9    <include>common/styles.xml</include>
     10    <include>common/common_sprites.xml</include>
     11    <include>common/common_styles.xml</include>
     12
     13    <include>replay/replay.xml</include>
     14</page>
  • binaries/data/mods/public/gui/pregame/mainmenu.xml

     
    471471                        closeMenu();
    472472                        openMenu("submenuMultiplayer", (this.parent.size.top+this.size.top), (this.size.bottom-this.size.top), 3);
    473473                    </action>
    474474                </object>
    475475
     476                <!-- REPLAY BUTTON -->
     477                <object name="menuReplayButton"
     478                    type="button"
     479                    style="StoneButtonFancy"
     480                    size="4 100 100%-4 128"
     481                    tooltip_style="pgToolTip"
     482                >
     483                    <translatableAttribute id="caption">Replay</translatableAttribute>
     484                    <translatableAttribute id="tooltip">Visually replays a past game.</translatableAttribute>
     485                    <action on="Press">
     486                        closeMenu();
     487                        Engine.PushGuiPage("page_replay.xml");
     488                    </action>
     489                </object>
     490               
    476491                <!-- TOOLS AND OPTIONS BUTTON -->
    477492                <object name="menuToolsAndOptionsButton"
    478493                    style="StoneButtonFancy"
    479494                    type="button"
    480                     size="4 100 100%-4 128"
     495                    size="4 132 100%-4 160"
    481496                    tooltip_style="pgToolTip"
    482497                >
    483498                    <translatableAttribute id="caption">Tools &amp; Options</translatableAttribute>
    484499                    <translatableAttribute id="tooltip">Game options and scenario design tools.</translatableAttribute>
    485500                    <action on="Press">
     
    490505
    491506                <!-- EXIT BUTTON -->
    492507                <object name="menuExitButton"
    493508                    type="button"
    494509                    style="StoneButtonFancy"
    495                     size="4 132 100%-4 160"
     510                    size="4 162 100%-4 192"
    496511                    tooltip_style="pgToolTip"
    497512                >
    498513                    <translatableAttribute id="caption">Exit</translatableAttribute>
    499514                    <translatableAttribute id="tooltip">Exits the game.</translatableAttribute>
    500515                    <action on="Press">exitGamePressed();</action>
  • binaries/data/mods/public/gui/replay/replay.js

     
     1function init()
     2{
     3    // Engine.UpdateReplayCache() // TODO: call it less often even?
     4
     5    var replaySelection = Engine.GetGUIObjectByName("replaySelection");
     6
     7    // Get a list of replays
     8    var replays = Engine.GetReplays();
     9    if (replays.length == 0)
     10    {
     11        replaySelection.list = [translate("No replays found")];
     12        replaySelection.selected = 0;
     13        Engine.GetGUIObjectByName("loadReplayButton").enabled = false;
     14        Engine.GetGUIObjectByName("deleteReplayButton").enabled = false;
     15        return;
     16    }
     17
     18    // TODO: use a COList and allow for better sorting based on columns
     19    replays.sort();
     20
     21    // Get current game version and loaded mods
     22    var engineInfo = Engine.GetEngineInfo();
     23
     24    // Fill list with items
     25    var replayListIds = [ replay.file for each (replay in replays) ];
     26    var replayListLabels = [ generateReplayLabel(replay) for each (replay in replays) ];
     27
     28    replaySelection.list = replayListLabels;
     29    replaySelection.list_data = replayListIds;
     30    if (replaySelection.selected == -1)
     31        replaySelection.selected = 0;
     32    else if (replaySelection.selected >= replays.length)    // happen when we delete the last replay
     33        replaySelection.selected = replays.length - 1;
     34}
     35
     36function generateReplayLabel(replay)
     37{
     38    return replay.file;
     39}
     40
     41function loadReplay()
     42{
     43    var replaySelection = Engine.GetGUIObjectByName("replaySelection");
     44    var replayFile = replaySelection.list_data[replaySelection.selected];
     45   
     46    // TODO: check replay compatibility before really loading it (similar to savegames)
     47    reallyStartVisualReplay(replayFile);
     48}
     49
     50function reallyStartVisualReplay(replayFile)
     51{
     52    Engine.StartVisualReplay(replayFile);
     53   
     54    Engine.SwitchGuiPage("page_loading.xml", {
     55        "attribs": Engine.GetVisualReplayAttributes(replayFile),
     56        "isNetworked" : false,
     57        "playerAssignments": {},
     58        "savedGUIData": ""
     59    });
     60}
     61
     62function deleteReplay()
     63{
     64    var replaySelection = Engine.GetGUIObjectByName("replaySelection");
     65    var replayLabel = replaySelection.list[replaySelection.selected];
     66    var replayFile = replaySelection.list_data[replaySelection.selected];
     67
     68    // Ask for confirmation
     69    var btCaptions = [translate("Yes"), translate("No")];
     70    var btCode = [function(){ reallyDeleteReplay(replayFile); }, null];
     71    messageBox(500, 200, sprintf(translate("\"%(label)s\""), { label: replayLabel }) + "\n" + translate("Are you sure to delete this replay permanently?"), translate("DELETE"), 0, btCaptions, btCode);
     72}
     73
     74function deleteReplayWithoutConfirmation()
     75{
     76    var replaySelection = Engine.GetGUIObjectByName("replaySelection");
     77    var replayFile = replaySelection.list_data[replaySelection.selected];
     78    reallyDeleteReplay(replayFile);
     79}
     80
     81function reallyDeleteReplay(replayFile)
     82{
     83    if (!Engine.DeleteReplay(replayFile))
     84        error(sprintf("Could not delete replay '%(id)s'", { id: replayFile }));
     85
     86    // Refresh replay list
     87    init();
     88}
     89
  • binaries/data/mods/public/gui/replay/replay.xml

     
     1<?xml version="1.0" encoding="utf-8"?>
     2
     3<objects>
     4
     5    <script file="gui/common/functions_global_object.js" />
     6    <script file="gui/replay/replay.js" />
     7
     8    <!-- Add a translucent black background to fade out the menu page -->
     9    <object type="image" z="0" sprite="BackgroundTranslucent"/>
     10
     11    <object type="image" style="ModernDialog" size="50%-300 50%-200 50%+300 50%+200">
     12
     13        <object type="text" style="TitleText" size="50%-128 -18 50%+128 14">
     14            <translatableAttribute id="caption">Visual replay of past games</translatableAttribute>
     15        </object>
     16
     17        <object name="replaySelection"
     18            style="ModernList"
     19            type="list"
     20            size="24 24 100%-24 100%-100">
     21        </object>
     22
     23        <object type="button" size="0%+25 100%-60 33%+10 100%-32" style="StoneButton">
     24            <translatableAttribute id="caption">Cancel</translatableAttribute>
     25            <action on="Press">Engine.PopGuiPage();</action>
     26        </object>
     27
     28        <object name="deleteReplayButton" type="button" size="33%+20 100%-60 66%-15 100%-32" style="StoneButton" hotkey="session.savedgames.delete">
     29            <translatableAttribute id="caption">Delete</translatableAttribute>
     30            <action on="Press">
     31                if (!this.enabled)
     32                    return;
     33                if (Engine.HotkeyIsPressed("session.savedgames.noConfirmation"))
     34                    deleteReplayWithoutConfirmation();
     35                else
     36                    deleteReplay();
     37            </action>
     38        </object>
     39
     40        <object name="loadReplayButton" type="button" style="StoneButton" size="66%-5 100%-60 100%-25 100%-32">
     41            <translatableAttribute id="caption">Load</translatableAttribute>
     42            <action on="Press">loadReplay();</action>
     43        </object>
     44
     45    </object>
     46
     47</objects>
  • build/svn_revision/engine_version.txt

     
     1L"0.0.19"
  • source/gui/scripting/ScriptFunctions.cpp

     
    4848#include "ps/Globals.h" // g_frequencyFilter
    4949#include "ps/Hotkey.h"
    5050#include "ps/ProfileViewer.h"
    5151#include "ps/Pyrogenesis.h"
    5252#include "ps/SavedGame.h"
     53#include "ps/VisualReplay.h"
    5354#include "ps/UserReport.h"
    5455#include "ps/World.h"
    5556#include "ps/scripting/JSInterface_ConfigDB.h"
    5657#include "ps/scripting/JSInterface_Console.h"
    5758#include "ps/scripting/JSInterface_Mod.h"
     
    281282    shared_ptr<ScriptInterface::StructuredClone> GUIMetadataClone = pCxPrivate->pScriptInterface->WriteStructuredClone(GUIMetadata);
    282283    if (SavedGames::SavePrefix(prefix, description, *g_Game->GetSimulation2(), GUIMetadataClone, g_Game->GetPlayerID()) < 0)
    283284        LOGERROR("Failed to save game");
    284285}
    285286
     287JS::Value StartVisualReplay(ScriptInterface::CxPrivate* pCxPrivate, std::wstring name)
     288{
     289    JSContext* cxGui = pCxPrivate->pScriptInterface->GetContext();
     290    JSAutoRequest rq(cxGui);
     291    JS::RootedValue guiContextMetadata(cxGui);
     292
     293    ENSURE(!g_NetServer);
     294    ENSURE(!g_NetClient);
     295    ENSURE(!g_Game);
     296
     297    CStrW replayFilePath = OsPath(VisualReplay::GetDirectoryName() / name).string();
     298    std::string replayFile( replayFilePath.begin(), replayFilePath.end() );
     299
     300    if (FileExists(OsPath(replayFile)))
     301    {
     302        g_Game = new CGame(false, false);
     303        g_Game->StartReplay(replayFile);
     304    }
     305
     306    return guiContextMetadata;
     307}
     308
     309JS::Value GetVisualReplayAttributes(ScriptInterface::CxPrivate* pCxPrivate, std::wstring name)
     310{
     311    CStrW replayFilePath = OsPath(VisualReplay::GetDirectoryName() / name).string();
     312    std::string replayFile( replayFilePath.begin(), replayFilePath.end() );
     313
     314    if (!FileExists(OsPath(replayFile)))
     315        return {};
     316
     317    std::ifstream* replayStream = new std::ifstream(replayFile.c_str());
     318    std::string type, line;
     319    ENSURE((*replayStream >> type).good() && type == "start");
     320
     321    std::getline(*replayStream, line);
     322    JS::RootedValue attribs(pCxPrivate->pScriptInterface->GetContext());
     323    pCxPrivate->pScriptInterface->ParseJSON(line, &attribs);
     324
     325    return attribs;
     326}
     327
    286328void SetNetworkGameAttributes(ScriptInterface::CxPrivate* pCxPrivate, JS::HandleValue attribs1)
    287329{
    288330    ENSURE(g_NetServer);
    289331    //TODO: This is a workaround because we need to pass a MutableHandle to a JSAPI functions somewhere
    290332    // (with no obvious reason).
     
    415457bool DeleteSavedGame(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring name)
    416458{
    417459    return SavedGames::DeleteSavedGame(name);
    418460}
    419461
     462JS::Value GetReplays(ScriptInterface::CxPrivate* pCxPrivate)
     463{
     464    return VisualReplay::GetReplays(*(pCxPrivate->pScriptInterface));
     465}
     466
     467bool DeleteReplay(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring replayFile)
     468{
     469    return VisualReplay::DeleteReplay(replayFile);
     470}
     471
    420472void OpenURL(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string url)
    421473{
    422474    sys_open_url(url);
    423475}
    424476
     
    9741026    scriptInterface.RegisterFunction<void, std::wstring, std::wstring, JS::HandleValue, &SaveGame>("SaveGame");
    9751027    scriptInterface.RegisterFunction<void, std::wstring, std::wstring, JS::HandleValue, &SaveGamePrefix>("SaveGamePrefix");
    9761028    scriptInterface.RegisterFunction<void, &QuickSave>("QuickSave");
    9771029    scriptInterface.RegisterFunction<void, &QuickLoad>("QuickLoad");
    9781030
     1031    // Visual replay
     1032    scriptInterface.RegisterFunction<JS::Value, &GetReplays>("GetReplays");
     1033    scriptInterface.RegisterFunction<bool, std::wstring, &DeleteReplay>("DeleteReplay");
     1034    scriptInterface.RegisterFunction<JS::Value, std::wstring, &StartVisualReplay>("StartVisualReplay");
     1035    scriptInterface.RegisterFunction<JS::Value, std::wstring, &GetVisualReplayAttributes>("GetVisualReplayAttributes");
     1036
    9791037    // Misc functions
    9801038    scriptInterface.RegisterFunction<std::wstring, std::wstring, &SetCursor>("SetCursor");
    9811039    scriptInterface.RegisterFunction<int, &GetPlayerID>("GetPlayerID");
    9821040    scriptInterface.RegisterFunction<void, int, &SetPlayerID>("SetPlayerID");
    9831041    scriptInterface.RegisterFunction<void, std::string, &OpenURL>("OpenURL");
  • source/lib/svn_revision.cpp

     
    1 /* Copyright (c) 2010 Wildfire Games
     1/* Copyright (c) 2015 Wildfire Games
    22 *
    33 * Permission is hereby granted, free of charge, to any person obtaining
    44 * a copy of this software and associated documentation files (the
    55 * "Software"), to deal in the Software without restriction, including
    66 * without limitation the rights to use, copy, modify, merge, publish,
     
    2323#include "precompiled.h"
    2424
    2525wchar_t svn_revision[] =
    2626#include "../../build/svn_revision/svn_revision.txt"
    2727;
     28
     29wchar_t engine_version[] =
     30#include "../../build/svn_revision/engine_version.txt"
     31;
  • source/lib/svn_revision.h

     
    1 /* Copyright (c) 2010 Wildfire Games
     1/* Copyright (c) 2015 Wildfire Games
    22 *
    33 * Permission is hereby granted, free of charge, to any person obtaining
    44 * a copy of this software and associated documentation files (the
    55 * "Software"), to deal in the Software without restriction, including
    66 * without limitation the rights to use, copy, modify, merge, publish,
     
    1919 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    2020 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    2121 */
    2222
    2323extern wchar_t svn_revision[];
     24extern wchar_t engine_version[];
  • source/lobby/XmppClient.cpp

     
    1 /* Copyright (C) 2014 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
    55 * it under the terms of the GNU General Public License as published by
    66 * the Free Software Foundation, either version 2 of the License, or
     
    1616 */
    1717
    1818#include "precompiled.h"
    1919#include "XmppClient.h"
    2020#include "StanzaExtensions.h"
    21 
    2221#include "glooxwrapper/glooxwrapper.h"
    2322#include "i18n/L10n.h"
     23#include "lib/svn_revision.h"
    2424#include "lib/utf8.h"
    2525#include "ps/CLogger.h"
    2626#include "ps/ConfigDB.h"
    2727#include "scriptinterface/ScriptInterface.h"
    2828
     
    9393    // if the server doesn't list any supported SASL mechanism or the response
    9494    // has been modified to exclude those.
    9595    const int mechs = gloox::SaslMechAll ^ gloox::SaslMechPlain;
    9696    m_client->setSASLMechanisms(mechs);
    9797
     98    // copy engine version string
     99    std::wstring ev(engine_version);
     100    std::string ev_str(ev.begin(), ev.end());
    98101    m_client->registerConnectionListener(this);
    99102    m_client->setPresence(gloox::Presence::Available, -1);
    100     m_client->disco()->setVersion("Pyrogenesis", "0.0.19");
     103    m_client->disco()->setVersion("Pyrogenesis", ev_str);
    101104    m_client->disco()->setIdentity("client", "bot");
    102105    m_client->setCompression(false);
    103106
    104107    m_client->registerStanzaExtension(new GameListQuery());
    105108    m_client->registerIqHandler(this, ExtGameListQuery);
  • source/ps/Game.cpp

     
    173173{
    174174    m_IsReplay = true;
    175175    ScriptInterface& scriptInterface = m_Simulation2->GetScriptInterface();
    176176
    177177    SetTurnManager(new CNetReplayTurnManager(*m_Simulation2, GetReplayLogger()));
     178    SetPlayerID(-1);
    178179
    179180    m_ReplayPath = replayPath;
    180181    m_ReplayStream = new std::ifstream(m_ReplayPath.c_str());
    181182
    182183    std::string type;
  • source/ps/GameSetup/GameSetup.cpp

     
    879879    srand(time(NULL));  // NOTE: this rand should *not* be used for simulation!
    880880}
    881881
    882882bool Autostart(const CmdLineArgs& args);
    883883
    884 // Returns true if and only if the user has intended to replay a file
    885 bool VisualReplay(const std::string replayFile);
     884bool StartVisualReplay(const std::string replayFile);
    886885
    887886bool Init(const CmdLineArgs& args, int flags)
    888887{
    889888    h_mgr_init();
    890889
     
    10771076    // TODO: Is this the best place for this?
    10781077    CXeromyces::AddValidator(g_VFS, "map", "maps/scenario.rng");
    10791078
    10801079    try
    10811080    {
    1082         if (!VisualReplay(args.Get("replay-visual")) && !Autostart(args))
     1081        if (!StartVisualReplay(args.Get("replay-visual")) && !Autostart(args))
    10831082        {
    10841083            const bool setup_gui = ((flags & INIT_NO_GUI) == 0);
    10851084            // We only want to display the splash screen at startup
    10861085            shared_ptr<ScriptInterface> scriptInterface = g_GUI->GetScriptInterface();
    10871086            JSContext* cx = scriptInterface->GetContext();
     
    14741473    }
    14751474
    14761475    return true;
    14771476}
    14781477
    1479 bool VisualReplay(const std::string replayFile)
     1478bool StartVisualReplay(const std::string replayFile)
    14801479{
    14811480    if (!FileExists(OsPath(replayFile)))
    14821481        return false;
    14831482
    14841483    g_Game = new CGame(false, false);
    1485     g_Game->SetPlayerID(-1);
    14861484    g_Game->StartReplay(replayFile);
    14871485
    14881486    // TODO: Non progressive load can fail - need a decent way to handle this
    14891487    LDR_NonprogressiveLoad();
    14901488
  • source/ps/Pyrogenesis.cpp

     
    1 /* Copyright (C) 2009 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
    55 * it under the terms of the GNU General Public License as published by
    66 * the Free Software Foundation, either version 2 of the License, or
     
    7171
    7272// for user convenience, bundle all logs into this file:
    7373void psBundleLogs(FILE* f)
    7474{
    7575    fwprintf(f, L"SVN Revision: %ls\n\n", svn_revision);
     76    fwprintf(f, L"Engine Version: %ls\n\n", engine_version);
    7677
    7778    fwprintf(f, L"System info:\n\n");
    7879    OsPath path1 = psLogDir()/"system_info.txt";
    7980    AppendAsciiFile(f, path1);
    8081    fwprintf(f, L"\n\n====================================\n\n");
  • source/ps/Replay.cpp

     
    5252}
    5353
    5454CReplayLogger::CReplayLogger(ScriptInterface& scriptInterface) :
    5555    m_ScriptInterface(scriptInterface)
    5656{
     57    m_Stream = NULL;
     58}
     59
     60CReplayLogger::~CReplayLogger()
     61{
     62    delete m_Stream;
     63}
     64
     65void CReplayLogger::StartGame(JS::MutableHandleValue attribs)
     66{
    5767    // Construct the directory name based on the PID, to be relatively unique.
    5868    // Append "-1", "-2" etc if we run multiple matches in a single session,
    5969    // to avoid accidentally overwriting earlier logs.
    6070
    6171    std::wstringstream name;
     
    6676        name << "-" << run;
    6777
    6878    OsPath path = psLogDir() / L"sim_log" / name.str() / L"commands.txt";
    6979    CreateDirectories(path.Parent(), 0700);
    7080    m_Stream = new std::ofstream(OsString(path).c_str(), std::ofstream::out | std::ofstream::trunc);
    71 }
    72 
    73 CReplayLogger::~CReplayLogger()
    74 {
    75     delete m_Stream;
    76 }
    77 
    78 void CReplayLogger::StartGame(JS::MutableHandleValue attribs)
    79 {
    8081    *m_Stream << "start " << m_ScriptInterface.StringifyJSON(attribs, false) << "\n";
    8182}
    8283
    8384void CReplayLogger::Turn(u32 n, u32 turnLength, std::vector<SimulationCommand>& commands)
    8485{
     
    157158    JSContext* cx = g_Game->GetSimulation2()->GetScriptInterface().GetContext();
    158159    JSAutoRequest rq(cx);
    159160    std::string type;
    160161    while ((*m_Stream >> type).good())
    161162    {
    162 //      if (turn >= 1400) break;
    163 
    164163        if (type == "start")
    165164        {
    166165            std::string line;
    167166            std::getline(*m_Stream, line);
    168167            JS::RootedValue attribs(cx);
  • source/ps/SavedGame.cpp

     
    1 /* Copyright (C) 2014 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
    55 * it under the terms of the GNU General Public License as published by
    66 * the Free Software Foundation, either version 2 of the License, or
     
    2929#include "ps/Filesystem.h"
    3030#include "ps/Game.h"
    3131#include "ps/Mod.h"
    3232#include "scriptinterface/ScriptInterface.h"
    3333#include "simulation2/Simulation2.h"
     34#include "lib/svn_revision.h"
    3435
    3536static const int SAVED_GAME_VERSION_MAJOR = 1; // increment on incompatible changes to the format
    3637static const int SAVED_GAME_VERSION_MINOR = 0; // increment on compatible changes to the format
    3738
    3839// TODO: we ought to check version numbers when loading files
     
    296297    JSContext* cx = scriptInterface.GetContext();
    297298    JSAutoRequest rq(cx);
    298299   
    299300    JS::RootedValue metainfo(cx);
    300301    scriptInterface.Eval("({})", &metainfo);
    301     scriptInterface.SetProperty(metainfo, "version_major", SAVED_GAME_VERSION_MAJOR);
    302     scriptInterface.SetProperty(metainfo, "version_minor", SAVED_GAME_VERSION_MINOR);
    303     scriptInterface.SetProperty(metainfo, "mods"         , g_modsLoaded);
     302    scriptInterface.SetProperty(metainfo, "version_major", SAVED_GAME_VERSION_MAJOR);
     303    scriptInterface.SetProperty(metainfo, "version_minor", SAVED_GAME_VERSION_MINOR);
     304
     305    std::wstring eng(engine_version);
     306    scriptInterface.SetProperty(metainfo, "engine_version", eng);
     307
     308    scriptInterface.SetProperty(metainfo, "mods", g_modsLoaded);
    304309    return metainfo;
    305310}
    306311
  • source/ps/VisualReplay.cpp

     
     1/* Copyright (C) 2015 Wildfire Games.
     2 * This file is part of 0 A.D.
     3 *
     4 * 0 A.D. is free software: you can redistribute it and/or modify
     5 * it under the terms of the GNU General Public License as published by
     6 * the Free Software Foundation, either version 2 of the License, or
     7 * (at your option) any later version.
     8 *
     9 * 0 A.D. is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 * GNU General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU General Public License
     15 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18#include "precompiled.h"
     19
     20#include "VisualReplay.h"
     21
     22#include "graphics/GameView.h"
     23#include "gui/GUIManager.h"
     24#include "lib/allocators/shared_ptr.h"
     25#include "lib/svn_revision.h"
     26#include "lib/utf8.h"
     27#include "ps/CLogger.h"
     28#include "ps/Filesystem.h"
     29#include "ps/Game.h"
     30#include "scriptinterface/ScriptInterface.h"
     31
     32OsPath VisualReplay::GetDirectoryName()
     33{
     34    return OsPath(psLogDir() / L"sim_log");
     35}
     36
     37JS::Value VisualReplay::GetReplays(ScriptInterface& scriptInterface)
     38{
     39    TIMER(L"GetReplays");
     40    JSContext* cx = scriptInterface.GetContext();
     41    JSAutoRequest rq(cx);
     42   
     43    int i = 0;
     44    DirectoryNames directories;
     45    JS::RootedObject replays(cx, JS_NewArrayObject(cx, 0));
     46    GetDirectoryEntries(GetDirectoryName(), NULL, &directories);
     47    for (auto& directory : directories)
     48    {
     49        OsPath replayFile(directory / L"commands.txt");
     50
     51        CFileInfo fileInfo;
     52        //WARN_RETURN_STATUS_IF_ERR(GetFileInfo(replayFile, &fileInfo));
     53
     54        JS::RootedValue replay(cx);
     55        scriptInterface.Eval("({})", &replay);
     56        scriptInterface.SetProperty(replay, "file", replayFile);
     57        scriptInterface.SetProperty(replay, "directory", directory);
     58        //scriptInterface.SetProperty(replay, "mtime", fileInfo.MTime());
     59        JS_SetElement(cx, replays, i++, replay);
     60    }
     61    return JS::ObjectValue(*replays);
     62}
     63
     64bool VisualReplay::DeleteReplay(const std::wstring& replayFile)
     65{
     66    const OsPath directory = OsPath(GetDirectoryName() / replayFile).Parent();
     67    return DirectoryExists(directory) && DeleteDirectory(directory) == INFO::OK;
     68}
  • source/ps/VisualReplay.h

     
     1/* Copyright (C) 2015 Wildfire Games.
     2 * This file is part of 0 A.D.
     3 *
     4 * 0 A.D. is free software: you can redistribute it and/or modify
     5 * it under the terms of the GNU General Public License as published by
     6 * the Free Software Foundation, either version 2 of the License, or
     7 * (at your option) any later version.
     8 *
     9 * 0 A.D. is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 * GNU General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU General Public License
     15 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18#ifndef INCLUDED_REPlAY
     19#define INCLUDED_REPlAY
     20
     21#include "scriptinterface/ScriptInterface.h"
     22class CSimulation2;
     23class CGUIManager;
     24
     25/**
     26 * Contains functions for visually replaying past games.
     27 */
     28
     29namespace VisualReplay
     30{
     31
     32/**
     33 * Start replaying the given commands.txt.
     34 *
     35 * @param name filename of the commands.txt file (including path)
     36 * @param scriptInterface
     37 * @param[out] savedState serialized simulation state stored as string of bytes,
     38 *  loaded from simulation.dat inside the archive.
     39 * @return INFO::OK if successfully loaded, else an error Status
     40 */
     41Status Load(const std::wstring& name, ScriptInterface& scriptInterface, std::string& savedState);
     42
     43/**
     44 * Returns the path to the sim-log directory (that contains the directories with the replay files.
     45 *
     46 * @param scriptInterface the ScriptInterface in which to create the return data.
     47 * @return OsPath with an absolte file path
     48 */
     49OsPath GetDirectoryName();
     50
     51/**
     52 * Get a list of replays (filenames and timestamps [later more information like playernames]) for GUI script usage
     53 *
     54 * @param scriptInterface the ScriptInterface in which to create the return data.
     55 * @return array of objects containing saved game data
     56 */
     57JS::Value GetReplays(ScriptInterface& scriptInterface);
     58
     59/**
     60 * Permanently deletes the visual replay (including the parent directory)
     61 *
     62 * @param replayFile path to commands.txt, whose parent directory will be deleted
     63 * @return true if deletion was successful, or false on error
     64 */
     65bool DeleteReplay(const std::wstring& replayFile);
     66}
     67
     68#endif