Let the Gamesetup.cpp Autostart (starting from cl) use the gamesettings via the autostart gui page.
Comments and testing By: Langbart Fixes #6433 Differential Revision: D4492 Includes/Obsoletes D4287 This was SVN commit r26584.
This commit is contained in:
parent
2af020bab1
commit
8eecc39e71
@ -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
|
||||
});
|
||||
}
|
||||
|
@ -4,5 +4,5 @@
|
||||
<script directory="gui/common/"/>
|
||||
<script directory="gui/gamesettings/"/>
|
||||
<script directory="gui/gamesettings/attributes/"/>
|
||||
<script directory="gui/autostart/"/>
|
||||
<script file="gui/autostart/autostart.js"/>
|
||||
</objects>
|
||||
|
54
binaries/data/mods/public/gui/autostart/autostart_client.js
Normal file
54
binaries/data/mods/public/gui/autostart/autostart_client.js
Normal file
@ -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);
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<objects>
|
||||
<script directory="gui/common/"/>
|
||||
<script file="gui/autostart/autostart_client.js"/>
|
||||
|
||||
<object name="ticker"/>
|
||||
</objects>
|
61
binaries/data/mods/public/gui/autostart/autostart_host.js
Normal file
61
binaries/data/mods/public/gui/autostart/autostart_host.js
Normal file
@ -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);
|
||||
}
|
10
binaries/data/mods/public/gui/autostart/autostart_host.xml
Normal file
10
binaries/data/mods/public/gui/autostart/autostart_host.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<objects>
|
||||
<script file="gui/maps/MapCache.js"/>
|
||||
<script directory="gui/common/"/>
|
||||
<script directory="gui/gamesettings/"/>
|
||||
<script directory="gui/gamesettings/attributes/"/>
|
||||
<script file="gui/autostart/autostart_host.js"/>
|
||||
|
||||
<object name="ticker"/>
|
||||
</objects>
|
@ -95,7 +95,7 @@ class CampaignMenu extends AutoWatcher
|
||||
return;
|
||||
}
|
||||
|
||||
gameSettings.launchGame(assignments);
|
||||
gameSettings.launchGame(assignments, true);
|
||||
Engine.SwitchGuiPage("page_loading.xml", {
|
||||
"attribs": gameSettings.finalizedAttributes,
|
||||
"playerAssignments": assignments
|
||||
|
@ -125,7 +125,7 @@ class GameSettings
|
||||
* 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 @@ class GameSettings
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,8 @@ GameSettings.prototype.Attributes.CircularMap = class CircularMap extends GameSe
|
||||
|
||||
fromInitAttributes(attribs)
|
||||
{
|
||||
this.value = !!this.getLegacySetting(attribs, "CircularMap");
|
||||
if (this.getLegacySetting(attribs, "CircularMap") !== undefined)
|
||||
this.value = !!this.getLegacySetting(attribs, "CircularMap");
|
||||
}
|
||||
|
||||
onMapChange()
|
||||
|
@ -270,7 +270,7 @@ class GameSettingsController
|
||||
|
||||
// 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.
|
||||
|
@ -366,7 +366,7 @@ function startHost(playername, servername, port, password)
|
||||
|
||||
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 @@ function startJoin(playername, ip, port)
|
||||
{
|
||||
try
|
||||
{
|
||||
Engine.StartNetworkJoin(playername, ip, port);
|
||||
Engine.StartNetworkJoin(playername, ip, port, true);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
<page>
|
||||
<!--
|
||||
This is simply a convenience forwarder to avoid loading
|
||||
the gameSettings from the main menu.
|
||||
the gameSettings from the main menu or command line.
|
||||
-->
|
||||
<include>autostart/autostart.xml</include>
|
||||
</page>
|
||||
|
10
binaries/data/mods/public/gui/page_autostart_client.xml
Normal file
10
binaries/data/mods/public/gui/page_autostart_client.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<page>
|
||||
<!--
|
||||
This is simply a convenience forwarder to avoid loading
|
||||
the gamesetup_mp when autostarting from command line.
|
||||
-->
|
||||
<include>common/modern/styles.xml</include>
|
||||
|
||||
<include>autostart/autostart_client.xml</include>
|
||||
</page>
|
10
binaries/data/mods/public/gui/page_autostart_host.xml
Normal file
10
binaries/data/mods/public/gui/page_autostart_host.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<page>
|
||||
<!--
|
||||
This is simply a convenience forwarder to avoid loading
|
||||
the gamesetup_mp when autostarting from command line.
|
||||
-->
|
||||
<include>common/modern/styles.xml</include>
|
||||
|
||||
<include>autostart/autostart_host.xml</include>
|
||||
</page>
|
@ -15,11 +15,20 @@ var g_MainMenuItems = [
|
||||
"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
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -13,7 +13,7 @@ Autostart:
|
||||
-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 @@ 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"
|
||||
-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
|
||||
|
@ -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 @@ private:
|
||||
* 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 @@ void CNetServerWorker::Run()
|
||||
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 @@ void CNetServerWorker::SendHolePunchingMessage(const CStr& ipStr, u16 port)
|
||||
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
@ -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 @@ class CNetServer
|
||||
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 @@ private:
|
||||
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 @@ private:
|
||||
*/
|
||||
JS::PersistentRootedValue m_InitAttributes;
|
||||
|
||||
int m_AutostartPlayers;
|
||||
|
||||
/**
|
||||
* Whether this match requires lobby authentication.
|
||||
*/
|
||||
|
@ -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 @@ bool HasNetClient()
|
||||
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 @@ void StartNetworkHost(const ScriptRequest& rq, const CStrW& playerName, const u1
|
||||
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 StartNetworkHost(const ScriptRequest& rq, const CStrW& playerName, const u1
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -219,34 +219,6 @@ 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();
|
||||
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 @@ CStr8 LoadSettingsOfScenarioMap(const VfsPath &mapPath)
|
||||
* -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 @@ 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"
|
||||
* -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 @@ CStr8 LoadSettingsOfScenarioMap(const VfsPath &mapPath)
|
||||
*/
|
||||
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 @@ bool Autostart(const CmdLineArgs& args)
|
||||
|
||||
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 @@ bool Autostart(const CmdLineArgs& args)
|
||||
}
|
||||
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 @@ bool Autostart(const CmdLineArgs& args)
|
||||
// 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 @@ bool Autostart(const CmdLineArgs& args)
|
||||
// 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 @@ bool Autostart(const CmdLineArgs& args)
|
||||
// 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 @@ bool Autostart(const CmdLineArgs& args)
|
||||
// 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 @@ bool Autostart(const CmdLineArgs& args)
|
||||
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<CStrW> triggerScriptsVector;
|
||||
JS::RootedValue triggerScripts(rq.cx);
|
||||
@ -1135,6 +1054,9 @@ bool Autostart(const CmdLineArgs& args)
|
||||
triggerScriptsVector.push_back(nonVisualScript.FromUTF8());
|
||||
}
|
||||
|
||||
Script::ToJSVal(rq, &triggerScripts, triggerScriptsVector);
|
||||
Script::SetProperty(rq, settings, "TriggerScripts", triggerScripts);
|
||||
|
||||
std::vector<CStr> victoryConditions(1, "conquest");
|
||||
if (args.Has("autostart-victory"))
|
||||
victoryConditions = args.GetMultiple("autostart-victory");
|
||||
@ -1144,31 +1066,6 @@ bool Autostart(const CmdLineArgs& args)
|
||||
|
||||
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<CStrW> 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 @@ bool Autostart(const CmdLineArgs& args)
|
||||
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 @@ bool AutostartVisualReplay(const std::string& replayFile)
|
||||
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;
|
||||
}
|
||||
|
@ -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 @@ bool IsGameStarted()
|
||||
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();
|
||||
|
Loading…
Reference in New Issue
Block a user