Index: ps/trunk/binaries/data/mods/public/gui/autostart/autostart.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/autostart/autostart.js
+++ ps/trunk/binaries/data/mods/public/gui/autostart/autostart.js
@@ -1,17 +1,12 @@
function init(initData)
{
let settings = new GameSettings().init();
- settings.fromInitAttributes(initData);
- let assignments = {
- "local": {
- "player": 1,
- "name": Engine.ConfigDB_GetValue("user", "playername.singleplayer") || Engine.GetSystemUsername()
- }
- };
- settings.launchGame(assignments);
+ settings.fromInitAttributes(initData.attribs);
+
+ settings.launchGame(initData.playerAssignments, initData.storeReplay);
Engine.SwitchGuiPage("page_loading.xml", {
"attribs": settings.finalizedAttributes,
- "playerAssignments": assignments
+ "playerAssignments": initData.playerAssignments
});
}
Index: ps/trunk/binaries/data/mods/public/gui/autostart/autostart.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/autostart/autostart.xml
+++ ps/trunk/binaries/data/mods/public/gui/autostart/autostart.xml
@@ -4,5 +4,5 @@
-
+
Index: ps/trunk/binaries/data/mods/public/gui/autostart/autostart_client.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/autostart/autostart_client.js
+++ ps/trunk/binaries/data/mods/public/gui/autostart/autostart_client.js
@@ -0,0 +1,54 @@
+class AutoStartClient
+{
+ constructor(initData)
+ {
+ Engine.GetGUIObjectByName("ticker").onTick = this.onTick.bind(this);
+
+ this.playerAssignments = {};
+
+ try
+ {
+ Engine.StartNetworkJoin(initData.playerName, initData.ip, initData.port, initData.storeReplay);
+ }
+ catch (e)
+ {
+ messageBox(
+ 400, 200,
+ sprintf(translate("Cannot join game: %(message)s."), { "message": e.message }),
+ translate("Error")
+ );
+ }
+ }
+
+ onTick()
+ {
+ while (true)
+ {
+ const message = Engine.PollNetworkClient();
+ if (!message)
+ break;
+
+ switch (message.type)
+ {
+ case "players":
+ this.playerAssignments = message.newAssignments;
+ break;
+ case "start":
+ Engine.SwitchGuiPage("page_loading.xml", {
+ "attribs": message.initAttributes,
+ "isRejoining": true,
+ "playerAssignments": this.playerAssignments
+ });
+
+ // Process further pending netmessages in the session page.
+ return;
+ default:
+ }
+ }
+ }
+}
+
+function init(initData)
+{
+ new AutoStartClient(initData);
+}
Index: ps/trunk/binaries/data/mods/public/gui/autostart/autostart_client.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/autostart/autostart_client.xml
+++ ps/trunk/binaries/data/mods/public/gui/autostart/autostart_client.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
Index: ps/trunk/binaries/data/mods/public/gui/autostart/autostart_host.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/autostart/autostart_host.js
+++ ps/trunk/binaries/data/mods/public/gui/autostart/autostart_host.js
@@ -0,0 +1,61 @@
+class AutoStartHost
+{
+ constructor(initData)
+ {
+ this.maxPlayers = initData.maxPlayers;
+ this.storeReplay = initData.storeReplay;
+ this.playerAssignments = {};
+
+ Engine.GetGUIObjectByName("ticker").onTick = this.onTick.bind(this);
+
+ try
+ {
+ // Stun and password not implemented for autostart.
+ Engine.StartNetworkHost(initData.playerName, initData.port, false, "", initData.storeReplay);
+ }
+ catch (e)
+ {
+ messageBox(
+ 400, 200,
+ sprintf(translate("Cannot host game: %(message)s."), { "message": e.message }),
+ translate("Error")
+ );
+ }
+
+ this.settings = new GameSettings().init();
+ this.settings.fromInitAttributes(initData.attribs);
+ }
+
+ onTick()
+ {
+ while (true)
+ {
+ const message = Engine.PollNetworkClient();
+ if (!message)
+ break;
+
+ switch (message.type)
+ {
+ case "players":
+ this.playerAssignments = message.newAssignments;
+ break;
+ default:
+ }
+ }
+
+ if (Object.keys(this.playerAssignments).length == this.maxPlayers)
+ {
+ this.settings.launchGame(this.playerAssignments, this.storeReplay);
+
+ Engine.SwitchGuiPage("page_loading.xml", {
+ "attribs": this.settings.finalizedAttributes,
+ "playerAssignments": this.playerAssignments
+ });
+ }
+ }
+}
+
+function init(initData)
+{
+ new AutoStartHost(initData);
+}
Index: ps/trunk/binaries/data/mods/public/gui/autostart/autostart_host.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/autostart/autostart_host.xml
+++ ps/trunk/binaries/data/mods/public/gui/autostart/autostart_host.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
Index: ps/trunk/binaries/data/mods/public/gui/campaigns/default_menu/CampaignMenu.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/campaigns/default_menu/CampaignMenu.js
+++ ps/trunk/binaries/data/mods/public/gui/campaigns/default_menu/CampaignMenu.js
@@ -95,7 +95,7 @@
return;
}
- gameSettings.launchGame(assignments);
+ gameSettings.launchGame(assignments, true);
Engine.SwitchGuiPage("page_loading.xml", {
"attribs": gameSettings.finalizedAttributes,
"playerAssignments": assignments
Index: ps/trunk/binaries/data/mods/public/gui/gamesettings/GameSettings.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/gamesettings/GameSettings.js
+++ ps/trunk/binaries/data/mods/public/gui/gamesettings/GameSettings.js
@@ -125,7 +125,7 @@
* since you'll need a GameSettings object anyways.
* @param playerAssignments - A dict of 'local'/GUID per player and their name/slot.
*/
- launchGame(playerAssignments)
+ launchGame(playerAssignments, storeReplay)
{
this.pickRandomItems();
@@ -142,9 +142,9 @@
// NB: for multiplayer support, the clients must be listening to "start" net messages.
if (this.isNetworked)
- Engine.StartNetworkGame(this.finalizedAttributes);
+ Engine.StartNetworkGame(this.finalizedAttributes, storeReplay);
else
- Engine.StartGame(this.finalizedAttributes, playerAssignments.local.player);
+ Engine.StartGame(this.finalizedAttributes, playerAssignments.local.player, storeReplay);
}
}
Index: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/CircularMap.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/CircularMap.js
+++ ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/CircularMap.js
@@ -16,7 +16,8 @@
fromInitAttributes(attribs)
{
- this.value = !!this.getLegacySetting(attribs, "CircularMap");
+ if (this.getLegacySetting(attribs, "CircularMap") !== undefined)
+ this.value = !!this.getLegacySetting(attribs, "CircularMap");
}
onMapChange()
Index: ps/trunk/binaries/data/mods/public/gui/gamesetup/Controllers/GameSettingsController.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/gamesetup/Controllers/GameSettingsController.js
+++ ps/trunk/binaries/data/mods/public/gui/gamesetup/Controllers/GameSettingsController.js
@@ -270,7 +270,7 @@
// This will resolve random settings & send game start messages.
// TODO: this will trigger observers, which is somewhat wasteful.
- g_GameSettings.launchGame(g_PlayerAssignments);
+ g_GameSettings.launchGame(g_PlayerAssignments, true);
// Switch to the loading page right away,
// the GUI will otherwise show the unrandomised settings.
Index: ps/trunk/binaries/data/mods/public/gui/gamesetup_mp/gamesetup_mp.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/gamesetup_mp/gamesetup_mp.js
+++ ps/trunk/binaries/data/mods/public/gui/gamesetup_mp/gamesetup_mp.js
@@ -366,7 +366,7 @@
try
{
- Engine.StartNetworkHost(playername + (g_UserRating ? " (" + g_UserRating + ")" : ""), port, useSTUN, password);
+ Engine.StartNetworkHost(playername + (g_UserRating ? " (" + g_UserRating + ")" : ""), port, useSTUN, password, true);
}
catch (e)
{
@@ -395,7 +395,7 @@
{
try
{
- Engine.StartNetworkJoin(playername, ip, port);
+ Engine.StartNetworkJoin(playername, ip, port, true);
}
catch (e)
{
Index: ps/trunk/binaries/data/mods/public/gui/page_autostart.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/page_autostart.xml
+++ ps/trunk/binaries/data/mods/public/gui/page_autostart.xml
@@ -2,7 +2,7 @@
autostart/autostart.xml
Index: ps/trunk/binaries/data/mods/public/gui/page_autostart_client.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/page_autostart_client.xml
+++ ps/trunk/binaries/data/mods/public/gui/page_autostart_client.xml
@@ -0,0 +1,10 @@
+
+
+
+ common/modern/styles.xml
+
+ autostart/autostart_client.xml
+
Index: ps/trunk/binaries/data/mods/public/gui/page_autostart_host.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/page_autostart_host.xml
+++ ps/trunk/binaries/data/mods/public/gui/page_autostart_host.xml
@@ -0,0 +1,10 @@
+
+
+
+ common/modern/styles.xml
+
+ autostart/autostart_host.xml
+
Index: ps/trunk/binaries/data/mods/public/gui/pregame/MainMenuItems.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/pregame/MainMenuItems.js
+++ ps/trunk/binaries/data/mods/public/gui/pregame/MainMenuItems.js
@@ -15,11 +15,20 @@
"tooltip": translate("Start the economic tutorial."),
"onPress": () => {
Engine.SwitchGuiPage("page_autostart.xml", {
- "mapType": "scenario",
- "map": "maps/tutorials/starting_economy_walkthrough",
- "settings": {
- "CheatsEnabled": true
- }
+ "attribs": {
+ "mapType": "scenario",
+ "map": "maps/tutorials/starting_economy_walkthrough",
+ "settings": {
+ "CheatsEnabled": true
+ },
+ },
+ "playerAssignments": {
+ "local": {
+ "player": 1,
+ "name": Engine.ConfigDB_GetValue("user", "playername.singleplayer") || Engine.GetSystemUsername()
+ }
+ },
+ "storeReplay": true
});
}
},
Index: ps/trunk/binaries/system/readme.txt
===================================================================
--- ps/trunk/binaries/system/readme.txt
+++ ps/trunk/binaries/system/readme.txt
@@ -13,7 +13,7 @@
-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-civ=PLAYER:CIV sets PLAYER's civilisation to CIV (skirmish and random maps only). Use random for a random civ.
-autostart-team=PLAYER:TEAM sets the team for PLAYER (e.g. 2:2).
-autostart-ceasefire=NUM sets a ceasefire duration NUM (default 0 minutes)
-autostart-nonvisual disable any graphics and sounds
@@ -33,9 +33,9 @@
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"
+ -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"
+ -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
Index: ps/trunk/source/network/NetServer.h
===================================================================
--- ps/trunk/source/network/NetServer.h
+++ ps/trunk/source/network/NetServer.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2021 Wildfire Games.
+/* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -110,10 +110,9 @@
public:
/**
* Construct a new network server.
- * @param autostartPlayers - if positive then StartGame will be called automatically
* once this many players are connected (intended for the command-line testing mode).
*/
- CNetServer(bool useLobbyAuth = false, int autostartPlayers = -1);
+ CNetServer(bool useLobbyAuth = false);
~CNetServer();
@@ -236,7 +235,7 @@
friend class CNetServer;
friend class CNetFileReceiveTask_ServerRejoin;
- CNetServerWorker(bool useLobbyAuth, int autostartPlayers);
+ CNetServerWorker(bool useLobbyAuth);
~CNetServerWorker();
bool CheckPassword(const std::string& password, const std::string& salt) const;
@@ -350,8 +349,6 @@
*/
JS::PersistentRootedValue m_InitAttributes;
- int m_AutostartPlayers;
-
/**
* Whether this match requires lobby authentication.
*/
Index: ps/trunk/source/network/NetServer.cpp
===================================================================
--- ps/trunk/source/network/NetServer.cpp
+++ ps/trunk/source/network/NetServer.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2021 Wildfire Games.
+/* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -145,8 +145,7 @@
* See http://trac.wildfiregames.com/ticket/654
*/
-CNetServerWorker::CNetServerWorker(bool useLobbyAuth, int autostartPlayers) :
- m_AutostartPlayers(autostartPlayers),
+CNetServerWorker::CNetServerWorker(bool useLobbyAuth) :
m_LobbyAuth(useLobbyAuth),
m_Shutdown(false),
m_ScriptInterface(NULL),
@@ -429,10 +428,6 @@
if (!RunStep())
break;
- // Implement autostart mode
- if (m_State == SERVER_STATE_PREGAME && (int)m_PlayerAssignments.size() == m_AutostartPlayers)
- StartGame(Script::StringifyJSON(ScriptRequest(m_ScriptInterface), &m_InitAttributes));
-
// Update profiler stats
m_Stats->LatchHostState(m_Host);
}
@@ -1624,8 +1619,8 @@
-CNetServer::CNetServer(bool useLobbyAuth, int autostartPlayers) :
- m_Worker(new CNetServerWorker(useLobbyAuth, autostartPlayers)),
+CNetServer::CNetServer(bool useLobbyAuth) :
+ m_Worker(new CNetServerWorker(useLobbyAuth)),
m_LobbyAuth(useLobbyAuth), m_UseSTUN(false), m_PublicIp(""), m_PublicPort(20595), m_Password()
{
}
Index: ps/trunk/source/network/scripting/JSInterface_Network.cpp
===================================================================
--- ps/trunk/source/network/scripting/JSInterface_Network.cpp
+++ ps/trunk/source/network/scripting/JSInterface_Network.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2021 Wildfire Games.
+/* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -62,7 +62,7 @@
return !!g_NetClient;
}
-void StartNetworkHost(const ScriptRequest& rq, const CStrW& playerName, const u16 serverPort, bool useSTUN, const CStr& password)
+void StartNetworkHost(const ScriptRequest& rq, const CStrW& playerName, const u16 serverPort, bool useSTUN, const CStr& password, bool storeReplay)
{
ENSURE(!g_NetClient);
ENSURE(!g_NetServer);
@@ -100,7 +100,7 @@
std::string secret = ps_generate_guid();
g_NetServer->SetControllerSecret(secret);
- g_Game = new CGame(true);
+ g_Game = new CGame(storeReplay);
g_NetClient = new CNetClient(g_Game);
g_NetClient->SetUserName(playerName);
@@ -141,13 +141,13 @@
}
}
-void StartNetworkJoin(const ScriptRequest& rq, const CStrW& playerName, const CStr& serverAddress, u16 serverPort)
+void StartNetworkJoin(const ScriptRequest& rq, const CStrW& playerName, const CStr& serverAddress, u16 serverPort, bool storeReplay)
{
ENSURE(!g_NetClient);
ENSURE(!g_NetServer);
ENSURE(!g_Game);
- g_Game = new CGame(true);
+ g_Game = new CGame(storeReplay);
g_NetClient = new CNetClient(g_Game);
g_NetClient->SetUserName(playerName);
g_NetClient->SetupServerData(serverAddress, serverPort, false);
Index: ps/trunk/source/ps/GameSetup/GameSetup.cpp
===================================================================
--- ps/trunk/source/ps/GameSetup/GameSetup.cpp
+++ ps/trunk/source/ps/GameSetup/GameSetup.cpp
@@ -219,34 +219,6 @@
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();
- ScriptRequest rq(scriptInterface);
-
- JS::RootedValue playerAssignments(rq.cx);
- Script::CreateObject(rq, &playerAssignments);
-
- if (!networked)
- {
- JS::RootedValue localPlayer(rq.cx);
- Script::CreateObject(rq, &localPlayer, "player", g_Game->GetPlayerID());
- Script::SetProperty(rq, playerAssignments, "local", localPlayer);
- }
-
- JS::RootedValue sessionInitData(rq.cx);
-
- Script::CreateObject(
- rq,
- &sessionInitData,
- "attribs", attrs,
- "playerAssignments", playerAssignments);
-
- InitPs(true, L"page_loading.xml", &scriptInterface, sessionInitData);
-}
-
-
void InitInput()
{
g_Joystick.Initialise();
@@ -807,8 +779,8 @@
* -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-civ=PLAYER:CIV sets PLAYER's civilisation to CIV (skirmish and random maps only).
+ * Use random for a random civ.
* -autostart-team=PLAYER:TEAM sets the team for PLAYER (e.g. 2:2).
* -autostart-ceasefire=NUM sets a ceasefire duration NUM
* (default 0 minutes)
@@ -839,9 +811,9 @@
*
* 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"
+ * -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"
+ * -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:
@@ -852,16 +824,41 @@
*/
bool Autostart(const CmdLineArgs& args)
{
+ // Get optional playername.
+ CStrW userName = L"anonymous";
+ if (args.Has("autostart-playername"))
+ userName = args.Get("autostart-playername").FromUTF8();
+
+ // Create some scriptinterface to store the js values for the settings.
+ ScriptInterface scriptInterface("Engine", "Game Setup", g_ScriptContext);
+
+ ScriptRequest rq(scriptInterface);
+ JS::RootedValue sessionInitData(rq.cx);
+
+ if (args.Has("autostart-client"))
+ {
+ CStr ip = args.Get("autostart-client");
+ if (ip.empty())
+ ip = "127.0.0.1";
+
+ Script::CreateObject(
+ rq,
+ &sessionInitData,
+ "playerName", userName,
+ "ip", ip,
+ "port", PS_DEFAULT_PORT,
+ "storeReplay", !args.Has("autostart-disable-replay"));
+
+ InitPs(true, L"page_autostart_client.xml", &scriptInterface, sessionInitData);
+
+ return true;
+ }
+
CStr autoStartName = args.Get("autostart");
if (autoStartName.empty())
return false;
- g_Game = new CGame(!args.Has("autostart-disable-replay"));
-
- ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface();
- ScriptRequest rq(scriptInterface);
-
JS::RootedValue attrs(rq.cx);
JS::RootedValue settings(rq.cx);
JS::RootedValue playerData(rq.cx);
@@ -881,28 +878,6 @@
if (mapDirectory == L"random")
{
- // Random map definition will be loaded from JSON file, so we need to parse it
- std::wstring scriptPath = L"maps/" + autoStartName.FromUTF8() + L".json";
- JS::RootedValue scriptData(rq.cx);
- Script::ReadJSONFile(rq, scriptPath, &scriptData);
- if (!scriptData.isUndefined() && Script::GetProperty(rq, scriptData, "settings", &settings))
- {
- // JSON loaded ok - copy script name over to game attributes
- std::wstring scriptFile;
- if (!Script::GetProperty(rq, settings, "Script", scriptFile))
- {
- LOGERROR("Autostart: random map '%s' data has no 'Script' property.", utf8_from_wstring(scriptPath));
- throw PSERROR_Game_World_MapLoadFailed("Error reading random map script.\nCheck application log for details.");
- }
- Script::SetProperty(rq, attrs, "script", scriptFile); // RMS filename
- }
- else
- {
- // Problem with JSON file
- LOGERROR("Autostart: Error reading random map script '%s'", utf8_from_wstring(scriptPath));
- throw PSERROR_Game_World_MapLoadFailed("Error reading random map script.\nCheck application log for details.");
- }
-
// Get optional map size argument (default 192)
uint mapSize = 192;
if (args.Has("autostart-size"))
@@ -934,23 +909,10 @@
}
mapType = "random";
}
- else if (mapDirectory == L"scenarios" || mapDirectory == L"skirmishes")
- {
- // Initialize general settings from the map data so some values
- // (e.g. name of map) are always present, even when autostart is
- // partially configured
- CStr8 mapSettingsJSON = LoadSettingsOfScenarioMap("maps/" + autoStartName + ".xml");
- Script::ParseJSON(rq, mapSettingsJSON, &settings);
-
- // Initialize the playerData array being modified by autostart
- // with the real map data, so sensible values are present:
- Script::GetProperty(rq, settings, "PlayerData", &playerData);
-
- if (mapDirectory == L"scenarios")
- mapType = "scenario";
- else
- mapType = "skirmish";
- }
+ else if (mapDirectory == L"scenarios")
+ mapType = "scenario";
+ else if (mapDirectory == L"skirmishes")
+ mapType = "skirmish";
else
{
LOGERROR("Autostart: Unrecognized map type '%s'", utf8_from_wstring(mapDirectory));
@@ -1005,15 +967,7 @@
// Instead of overwriting existing player data, modify the array
JS::RootedValue currentPlayer(rq.cx);
if (!Script::GetPropertyInt(rq, playerData, playerID-offset, ¤tPlayer) || currentPlayer.isUndefined())
- {
- if (mapDirectory == L"skirmishes")
- {
- // playerID is certainly bigger than this map player number
- LOGWARNING("Autostart: Invalid player %d in autostart-team option", playerID);
- continue;
- }
Script::CreateObject(rq, ¤tPlayer);
- }
int teamID = civArgs[i].AfterFirst(":").ToInt() - 1;
Script::SetProperty(rq, currentPlayer, "Team", teamID);
@@ -1036,15 +990,7 @@
// Instead of overwriting existing player data, modify the array
JS::RootedValue currentPlayer(rq.cx);
if (!Script::GetPropertyInt(rq, playerData, playerID-offset, ¤tPlayer) || currentPlayer.isUndefined())
- {
- if (mapDirectory == L"scenarios" || mapDirectory == L"skirmishes")
- {
- // playerID is certainly bigger than this map player number
- LOGWARNING("Autostart: Invalid player %d in autostart-ai option", playerID);
- continue;
- }
Script::CreateObject(rq, ¤tPlayer);
- }
Script::SetProperty(rq, currentPlayer, "AI", aiArgs[i].AfterFirst(":"));
Script::SetProperty(rq, currentPlayer, "AIDiff", 3);
@@ -1063,15 +1009,7 @@
// Instead of overwriting existing player data, modify the array
JS::RootedValue currentPlayer(rq.cx);
if (!Script::GetPropertyInt(rq, playerData, playerID-offset, ¤tPlayer) || currentPlayer.isUndefined())
- {
- if (mapDirectory == L"scenarios" || mapDirectory == L"skirmishes")
- {
- // playerID is certainly bigger than this map player number
- LOGWARNING("Autostart: Invalid player %d in autostart-aidiff option", playerID);
- continue;
- }
Script::CreateObject(rq, ¤tPlayer);
- }
Script::SetProperty(rq, currentPlayer, "AIDiff", civArgs[i].AfterFirst(":").ToInt());
Script::SetPropertyInt(rq, playerData, playerID-offset, currentPlayer);
@@ -1090,15 +1028,7 @@
// Instead of overwriting existing player data, modify the array
JS::RootedValue currentPlayer(rq.cx);
if (!Script::GetPropertyInt(rq, playerData, playerID-offset, ¤tPlayer) || currentPlayer.isUndefined())
- {
- if (mapDirectory == L"skirmishes")
- {
- // playerID is certainly bigger than this map player number
- LOGWARNING("Autostart: Invalid player %d in autostart-civ option", playerID);
- continue;
- }
Script::CreateObject(rq, ¤tPlayer);
- }
Script::SetProperty(rq, currentPlayer, "Civ", civArgs[i].AfterFirst(":"));
Script::SetPropertyInt(rq, playerData, playerID-offset, currentPlayer);
@@ -1108,17 +1038,6 @@
LOGWARNING("Autostart: Option 'autostart-civ' is invalid for scenarios");
}
- // Add player data to map settings
- Script::SetProperty(rq, settings, "PlayerData", playerData);
-
- // Add map settings to game attributes
- Script::SetProperty(rq, attrs, "settings", settings);
-
- // Get optional playername
- CStrW userName = L"anonymous";
- if (args.Has("autostart-playername"))
- userName = args.Get("autostart-playername").FromUTF8();
-
// Add additional scripts to the TriggerScripts property
std::vector triggerScriptsVector;
JS::RootedValue triggerScripts(rq.cx);
@@ -1135,6 +1054,9 @@
triggerScriptsVector.push_back(nonVisualScript.FromUTF8());
}
+ Script::ToJSVal(rq, &triggerScripts, triggerScriptsVector);
+ Script::SetProperty(rq, settings, "TriggerScripts", triggerScripts);
+
std::vector victoryConditions(1, "conquest");
if (args.Has("autostart-victory"))
victoryConditions = args.GetMultiple("autostart-victory");
@@ -1144,31 +1066,6 @@
Script::SetProperty(rq, settings, "VictoryConditions", victoryConditions);
- for (const CStr& victory : victoryConditions)
- {
- JS::RootedValue scriptData(rq.cx);
- JS::RootedValue data(rq.cx);
- JS::RootedValue victoryScripts(rq.cx);
-
- CStrW scriptPath = L"simulation/data/settings/victory_conditions/" + victory.FromUTF8() + L".json";
- Script::ReadJSONFile(rq, scriptPath, &scriptData);
- if (!scriptData.isUndefined() && Script::GetProperty(rq, scriptData, "Data", &data) && !data.isUndefined()
- && Script::GetProperty(rq, data, "Scripts", &victoryScripts) && !victoryScripts.isUndefined())
- {
- std::vector victoryScriptsVector;
- Script::FromJSVal(rq, victoryScripts, victoryScriptsVector);
- triggerScriptsVector.insert(triggerScriptsVector.end(), victoryScriptsVector.begin(), victoryScriptsVector.end());
- }
- else
- {
- LOGERROR("Autostart: Error reading victory script '%s'", utf8_from_wstring(scriptPath));
- throw PSERROR_Game_World_MapLoadFailed("Error reading victory script.\nCheck application log for details.");
- }
- }
-
- Script::ToJSVal(rq, &triggerScripts, triggerScriptsVector);
- Script::SetProperty(rq, settings, "TriggerScripts", triggerScripts);
-
int wonderDuration = 10;
if (args.Has("autostart-wonderduration"))
wonderDuration = args.Get("autostart-wonderduration").ToInt();
@@ -1184,60 +1081,50 @@
relicCount = args.Get("autostart-reliccount").ToInt();
Script::SetProperty(rq, settings, "RelicCount", relicCount);
+ // Add player data to map settings.
+ Script::SetProperty(rq, settings, "PlayerData", playerData);
+
+ // Add map settings to game attributes.
+ Script::SetProperty(rq, attrs, "settings", settings);
+
if (args.Has("autostart-host"))
{
- InitPsAutostart(true, attrs);
-
- size_t maxPlayers = 2;
+ int maxPlayers = 2;
if (args.Has("autostart-host-players"))
maxPlayers = args.Get("autostart-host-players").ToUInt();
- // Generate a secret to identify the host client.
- std::string secret = ps_generate_guid();
+ Script::CreateObject(
+ rq,
+ &sessionInitData,
+ "attribs", attrs,
+ "playerName", userName,
+ "port", PS_DEFAULT_PORT,
+ "maxPlayers", maxPlayers,
+ "storeReplay", !args.Has("autostart-disable-replay"));
- g_NetServer = new CNetServer(false, maxPlayers);
- g_NetServer->SetControllerSecret(secret);
- g_NetServer->UpdateInitAttributes(&attrs, scriptInterface);
-
- bool ok = g_NetServer->SetupConnection(PS_DEFAULT_PORT);
- ENSURE(ok);
-
- g_NetClient = new CNetClient(g_Game);
- g_NetClient->SetUserName(userName);
- g_NetClient->SetupServerData("127.0.0.1", PS_DEFAULT_PORT, false);
- g_NetClient->SetControllerSecret(secret);
- g_NetClient->SetupConnection(nullptr);
- }
- else if (args.Has("autostart-client"))
- {
- InitPsAutostart(true, attrs);
-
- g_NetClient = new CNetClient(g_Game);
- g_NetClient->SetUserName(userName);
-
- CStr ip = args.Get("autostart-client");
- if (ip.empty())
- ip = "127.0.0.1";
-
- g_NetClient->SetupServerData(ip, PS_DEFAULT_PORT, false);
- ENSURE(g_NetClient->SetupConnection(nullptr));
+ InitPs(true, L"page_autostart_host.xml", &scriptInterface, sessionInitData);
}
else
{
- g_Game->SetPlayerID(args.Has("autostart-player") ? args.Get("autostart-player").ToInt() : 1);
+ JS::RootedValue localPlayer(rq.cx);
+ Script::CreateObject(
+ rq,
+ &localPlayer,
+ "player", args.Has("autostart-player") ? args.Get("autostart-player").ToInt() : 1,
+ "name", userName);
- g_Game->StartGame(&attrs, "");
+ JS::RootedValue playerAssignments(rq.cx);
+ Script::CreateObject(rq, &playerAssignments);
+ Script::SetProperty(rq, playerAssignments, "local", localPlayer);
- if (CRenderer::IsInitialised())
- {
- InitPsAutostart(false, attrs);
- }
- else
- {
- // TODO: Non progressive load can fail - need a decent way to handle this
- LDR_NonprogressiveLoad();
- ENSURE(g_Game->ReallyStartGame() == PSRETURN_OK);
- }
+ Script::CreateObject(
+ rq,
+ &sessionInitData,
+ "attribs", attrs,
+ "playerAssignments", playerAssignments,
+ "storeReplay", !args.Has("autostart-disable-replay"));
+
+ InitPs(true, L"page_autostart.xml", &scriptInterface, sessionInitData);
}
return true;
@@ -1256,7 +1143,21 @@
ScriptRequest rq(scriptInterface);
JS::RootedValue attrs(rq.cx, g_Game->GetSimulation2()->GetInitAttributes());
- InitPsAutostart(false, attrs);
+ JS::RootedValue playerAssignments(rq.cx);
+ Script::CreateObject(rq, &playerAssignments);
+ JS::RootedValue localPlayer(rq.cx);
+ Script::CreateObject(rq, &localPlayer, "player", g_Game->GetPlayerID());
+ Script::SetProperty(rq, playerAssignments, "local", localPlayer);
+
+ JS::RootedValue sessionInitData(rq.cx);
+
+ Script::CreateObject(
+ rq,
+ &sessionInitData,
+ "attribs", attrs,
+ "playerAssignments", playerAssignments);
+
+ InitPs(true, L"page_loading.xml", &scriptInterface, sessionInitData);
return true;
}
Index: ps/trunk/source/ps/scripting/JSInterface_Game.cpp
===================================================================
--- ps/trunk/source/ps/scripting/JSInterface_Game.cpp
+++ ps/trunk/source/ps/scripting/JSInterface_Game.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2021 Wildfire Games.
+/* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -41,13 +41,13 @@
return g_Game;
}
-void StartGame(const ScriptInterface& guiInterface, JS::HandleValue attribs, int playerID)
+void StartGame(const ScriptInterface& guiInterface, JS::HandleValue attribs, int playerID, bool storeReplay)
{
ENSURE(!g_NetServer);
ENSURE(!g_NetClient);
ENSURE(!g_Game);
- g_Game = new CGame(true);
+ g_Game = new CGame(storeReplay);
// Convert from GUI script context to sim script context/
CSimulation2* sim = g_Game->GetSimulation2();