From d0a771c712c26cacefcbef4a4f6849cd324c8ec0 Mon Sep 17 00:00:00 2001 From: elexis Date: Wed, 4 Apr 2018 18:46:36 +0000 Subject: [PATCH] Use the loading screen for autostart singleplayer/bot matches and replays too (not only for autostarted multiplayer matches), refs #4822. Add an autostart-player option, so that one can start as an observer too and watch some knockout bots. Precise the "Needed for autostart loading option" comment from d5bd374586 which become increasingly incomprehensible with each a68d5dae0d, 506350d6fa, 9f796068f8 and 6c5a8269f3. This was SVN commit r21659. --- .../data/mods/public/gui/session/session.js | 21 +++--- binaries/system/readme.txt | 6 ++ source/ps/GameSetup/GameSetup.cpp | 72 +++++++++++++------ 3 files changed, 68 insertions(+), 31 deletions(-) diff --git a/binaries/data/mods/public/gui/session/session.js b/binaries/data/mods/public/gui/session/session.js index 2a295c6127..892ffcecf1 100644 --- a/binaries/data/mods/public/gui/session/session.js +++ b/binaries/data/mods/public/gui/session/session.js @@ -122,12 +122,11 @@ var g_StatusBarUpdate = 200; */ var g_ReplaySelectionData; -var g_PlayerAssignments = { - "local": { - "name": singleplayerName(), - "player": 1 - } -}; +/** + * Remembers which clients are assigned to which player slots. + * The keys are guids or "local" in Singleplayer. + */ +var g_PlayerAssignments; /** * Cache dev-mode settings that are frequently or widely used. @@ -261,17 +260,21 @@ function init(initData, hotloadData) return; } + // Fallback used by atlas + g_PlayerAssignments = initData ? initData.playerAssignments : { "local": { "player": 1 } }; + + // Fallback used by atlas and autostart games + if (g_PlayerAssignments.local && !g_PlayerAssignments.local.name) + g_PlayerAssignments.local.name = singleplayerName(); + if (initData) { - g_PlayerAssignments = initData.playerAssignments; g_ReplaySelectionData = initData.replaySelectionData; g_HasRejoined = initData.isRejoining; if (initData.savedGUIData) restoreSavedGameData(initData.savedGUIData); } - else if (g_IsReplay)// Needed for autostart loading option - g_PlayerAssignments.local.player = -1; LoadModificationTemplates(); updatePlayerData(); diff --git a/binaries/system/readme.txt b/binaries/system/readme.txt index 2f1ff04af4..0e922761da 100644 --- a/binaries/system/readme.txt +++ b/binaries/system/readme.txt @@ -12,6 +12,7 @@ Autostart: -autostart-ai=PLAYER:AI sets the AI for PLAYER (e.g. 2:petra) -autostart-aidiff=PLAYER:DIFF sets the DIFFiculty of PLAYER's AI (0: sandbox, 5: very hard) -autostart-aiseed=AISEED sets the seed used for the AI random generator (default 0, use -1 for random) +-autostart-player=NUMBER sets the playerID in non-networked games (default 1, use -1 for observer) -autostart-civ=PLAYER:CIV sets PLAYER's civilisation to CIV (skirmish and random maps only) -autostart-team=PLAYER:TEAM sets the team for PLAYER (e.g. 2:2). -autostart-ceasefire=NUM sets a ceasefire duration NUM (default 0 minutes) @@ -32,8 +33,13 @@ Multiplayer: Examples: 1) "Bob" will host a 2 player game on the Arcadia map: -autostart="scenarios/Arcadia" -autostart-host -autostart-host-players=2 -autostart-playername="Bob" + "Alice" joins the match as player 2: + -autostart="scenarios/Arcadia" -autostart-client=127.0.0.1 -autostart-playername="Alice" + The players use the developer overlay to control players. 2) Load Alpine Lakes random map with random seed, 2 players (Athens and Britons), and player 2 is PetraBot: -autostart="random/alpine_lakes" -autostart-seed=-1 -autostart-players=2 -autostart-civ=1:athen -autostart-civ=2:brit -autostart-ai=2:petra +3) Observe the PetraBot on a triggerscript map: + -autostart="random/jebel_barkal" -autostart-seed=-1 -autostart-players=2 -autostart-civ=1:athen -autostart-civ=2:brit -autostart-ai=1:petra -autostart-ai=2:petra -autostart-player=-1 Configuration: -conf=KEY:VALUE set a config value diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index 657899ba5e..395d325815 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -495,6 +495,32 @@ static void InitPs(bool setup_gui, const CStrW& gui_page, ScriptInterface* srcSc g_GUI->SwitchPage(gui_page, srcScriptInterface, initData); } +void InitPsAutostart(bool networked, JS::HandleValue attrs) +{ + // The GUI has not been initialized yet, so use the simulation scriptinterface for this variable + ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface(); + JSContext* cx = scriptInterface.GetContext(); + JSAutoRequest rq(cx); + + JS::RootedValue playerAssignments(cx); + scriptInterface.Eval("({})", &playerAssignments); + + if (!networked) + { + JS::RootedValue localPlayer(cx); + scriptInterface.Eval("({})", &localPlayer); + scriptInterface.SetProperty(localPlayer, "player", g_Game->GetPlayerID()); + scriptInterface.SetProperty(playerAssignments, "local", localPlayer); + } + + JS::RootedValue sessionInitData(cx); + scriptInterface.Eval("({})", &sessionInitData); + scriptInterface.SetProperty(sessionInitData, "attribs", attrs); + scriptInterface.SetProperty(sessionInitData, "playerAssignments", playerAssignments); + + InitPs(true, L"page_loading.xml", &scriptInterface, sessionInitData); +} + static void InitInput() { @@ -1149,6 +1175,7 @@ CStr8 LoadSettingsOfScenarioMap(const VfsPath &mapPath) * (0: sandbox, 5: very hard) * -autostart-aiseed=AISEED sets the seed used for the AI random * generator (default 0, use -1 for random) + * -autostart-player=NUMBER sets the playerID in non-networked games (default 1, use -1 for observer) * -autostart-civ=PLAYER:CIV sets PLAYER's civilisation to CIV * (skirmish and random maps only) * -autostart-team=PLAYER:TEAM sets the team for PLAYER (e.g. 2:2). @@ -1180,10 +1207,16 @@ CStr8 LoadSettingsOfScenarioMap(const VfsPath &mapPath) * Examples: * 1) "Bob" will host a 2 player game on the Arcadia map: * -autostart="scenarios/Arcadia" -autostart-host -autostart-host-players=2 -autostart-playername="Bob" + * "Alice" joins the match as player 2: + * -autostart="scenarios/Arcadia" -autostart-client=127.0.0.1 -autostart-playername="Alice" + * The players use the developer overlay to control players. * * 2) Load Alpine Lakes random map with random seed, 2 players (Athens and Britons), and player 2 is PetraBot: * -autostart="random/alpine_lakes" -autostart-seed=-1 -autostart-players=2 -autostart-civ=1:athen -autostart-civ=2:brit -autostart-ai=2:petra -*/ + * + * 3) Observe the PetraBot on a triggerscript map: + * -autostart="random/jebel_barkal" -autostart-seed=-1 -autostart-players=2 -autostart-civ=1:athen -autostart-civ=2:brit -autostart-ai=1:petra -autostart-ai=2:petra -autostart-player=-1 + */ bool Autostart(const CmdLineArgs& args) { CStr autoStartName = args.Get("autostart"); @@ -1448,10 +1481,6 @@ bool Autostart(const CmdLineArgs& args) // Add map settings to game attributes scriptInterface.SetProperty(attrs, "settings", settings); - JS::RootedValue mpInitData(cx); - scriptInterface.Eval("({isNetworked:true, playerAssignments:{}})", &mpInitData); - scriptInterface.SetProperty(mpInitData, "attribs", attrs); - // Get optional playername CStrW userName = L"anonymous"; if (args.Has("autostart-playername")) @@ -1524,7 +1553,7 @@ bool Autostart(const CmdLineArgs& args) if (args.Has("autostart-host")) { - InitPs(true, L"page_loading.xml", &scriptInterface, mpInitData); + InitPsAutostart(true, attrs); size_t maxPlayers = 2; if (args.Has("autostart-host-players")) @@ -1543,7 +1572,7 @@ bool Autostart(const CmdLineArgs& args) } else if (args.Has("autostart-client")) { - InitPs(true, L"page_loading.xml", &scriptInterface, mpInitData); + InitPsAutostart(true, attrs); g_NetClient = new CNetClient(g_Game, false); g_NetClient->SetUserName(userName); @@ -1557,18 +1586,18 @@ bool Autostart(const CmdLineArgs& args) } else { - g_Game->SetPlayerID(1); + g_Game->SetPlayerID(args.Has("autostart-player") ? args.Get("autostart-player").ToInt() : 1); + g_Game->StartGame(&attrs, ""); - LDR_NonprogressiveLoad(); - - PSRETURN ret = g_Game->ReallyStartGame(); - ENSURE(ret == PSRETURN_OK); - if (nonVisual) - return true; - - InitPs(true, L"page_session.xml", NULL, JS::UndefinedHandleValue); + { + // TODO: Non progressive load can fail - need a decent way to handle this + LDR_NonprogressiveLoad(); + ENSURE(g_Game->ReallyStartGame() == PSRETURN_OK); + } + else + InitPsAutostart(false, attrs); } return true; @@ -1583,14 +1612,13 @@ bool AutostartVisualReplay(const std::string& replayFile) g_Game->SetPlayerID(-1); g_Game->StartVisualReplay(replayFile); - // TODO: Non progressive load can fail - need a decent way to handle this - LDR_NonprogressiveLoad(); - - ENSURE(g_Game->ReallyStartGame() == PSRETURN_OK); - ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface(); + JSContext* cx = scriptInterface.GetContext(); + JSAutoRequest rq(cx); + JS::RootedValue attrs(cx, g_Game->GetSimulation2()->GetInitAttributes()); + + InitPsAutostart(false, attrs); - InitPs(true, L"page_session.xml", &scriptInterface, JS::UndefinedHandleValue); return true; }