Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/ps/GameSetup/GameSetup.cpp
Show First 20 Lines • Show All 213 Lines • ▼ Show 20 Lines | if (!setup_gui) | ||||
g_GUI->SwitchPage(L"page_atlas.xml", srcScriptInterface, initData); | g_GUI->SwitchPage(L"page_atlas.xml", srcScriptInterface, initData); | ||||
return; | return; | ||||
} | } | ||||
// GUI uses VFS, so this must come after VFS init. | // GUI uses VFS, so this must come after VFS init. | ||||
g_GUI->SwitchPage(gui_page, srcScriptInterface, initData); | 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() | void InitInput() | ||||
{ | { | ||||
g_Joystick.Initialise(); | g_Joystick.Initialise(); | ||||
// register input handlers | // register input handlers | ||||
// This stack is constructed so the first added, will be the last | // This stack is constructed so the first added, will be the last | ||||
// one called. This is important, because each of the handlers | // one called. This is important, because each of the handlers | ||||
// has the potential to block events to go further down | // has the potential to block events to go further down | ||||
▲ Show 20 Lines • Show All 544 Lines • ▼ Show 20 Lines | |||||
* TYPEDIR is skirmishes, scenarios, or random | * TYPEDIR is skirmishes, scenarios, or random | ||||
* -autostart-seed=SEED sets randomization seed value (default 0, use -1 for random) | * -autostart-seed=SEED sets randomization seed value (default 0, use -1 for random) | ||||
* -autostart-ai=PLAYER:AI sets the AI for PLAYER (e.g. 2:petra) | * -autostart-ai=PLAYER:AI sets the AI for PLAYER (e.g. 2:petra) | ||||
* -autostart-aidiff=PLAYER:DIFF sets the DIFFiculty of PLAYER's AI | * -autostart-aidiff=PLAYER:DIFF sets the DIFFiculty of PLAYER's AI | ||||
* (0: sandbox, 5: very hard) | * (0: sandbox, 5: very hard) | ||||
* -autostart-aiseed=AISEED sets the seed used for the AI random | * -autostart-aiseed=AISEED sets the seed used for the AI random | ||||
* generator (default 0, use -1 for 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-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 | * -autostart-civ=PLAYER:CIV sets PLAYER's civilisation to CIV (skirmish and random maps only). | ||||
* (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-team=PLAYER:TEAM sets the team for PLAYER (e.g. 2:2). | ||||
* -autostart-ceasefire=NUM sets a ceasefire duration NUM | * -autostart-ceasefire=NUM sets a ceasefire duration NUM | ||||
* (default 0 minutes) | * (default 0 minutes) | ||||
* -autostart-nonvisual disable any graphics and sounds | * -autostart-nonvisual disable any graphics and sounds | ||||
* -autostart-victory=SCRIPTNAME sets the victory conditions with SCRIPTNAME | * -autostart-victory=SCRIPTNAME sets the victory conditions with SCRIPTNAME | ||||
* located in simulation/data/settings/victory_conditions/ | * located in simulation/data/settings/victory_conditions/ | ||||
* (default conquest). When the first given SCRIPTNAME is | * (default conquest). When the first given SCRIPTNAME is | ||||
* "endless", no victory conditions will apply. | * "endless", no victory conditions will apply. | ||||
Show All 14 Lines | |||||
* given IP address | * given IP address | ||||
* Random maps only: | * Random maps only: | ||||
* -autostart-size=TILES sets random map size in TILES (default 192) | * -autostart-size=TILES sets random map size in TILES (default 192) | ||||
* -autostart-players=NUMBER sets NUMBER of players on random map | * -autostart-players=NUMBER sets NUMBER of players on random map | ||||
* (default 2) | * (default 2) | ||||
* | * | ||||
* Examples: | * Examples: | ||||
* 1) "Bob" will host a 2 player game on the Arcadia map: | * 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: | * "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. | * 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: | * 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 | * -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: | * 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 | * -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) | 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"); | CStr autoStartName = args.Get("autostart"); | ||||
if (autoStartName.empty()) | if (autoStartName.empty()) | ||||
return false; | 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 attrs(rq.cx); | ||||
JS::RootedValue settings(rq.cx); | JS::RootedValue settings(rq.cx); | ||||
JS::RootedValue playerData(rq.cx); | JS::RootedValue playerData(rq.cx); | ||||
Script::CreateObject(rq, &attrs); | Script::CreateObject(rq, &attrs); | ||||
Script::CreateObject(rq, &settings); | Script::CreateObject(rq, &settings); | ||||
Script::CreateArray(rq, &playerData); | Script::CreateArray(rq, &playerData); | ||||
// The directory in front of the actual map name indicates which type | // The directory in front of the actual map name indicates which type | ||||
// of map is being loaded. Drawback of this approach is the association | // of map is being loaded. Drawback of this approach is the association | ||||
// of map types and folders is hard-coded, but benefits are: | // of map types and folders is hard-coded, but benefits are: | ||||
// - No need to pass the map type via command line separately | // - No need to pass the map type via command line separately | ||||
// - Prevents mixing up of scenarios and skirmish maps to some degree | // - Prevents mixing up of scenarios and skirmish maps to some degree | ||||
Path mapPath = Path(autoStartName); | Path mapPath = Path(autoStartName); | ||||
std::wstring mapDirectory = mapPath.Parent().Filename().string(); | std::wstring mapDirectory = mapPath.Parent().Filename().string(); | ||||
std::string mapType; | std::string mapType; | ||||
if (mapDirectory == L"random") | 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) | // Get optional map size argument (default 192) | ||||
uint mapSize = 192; | uint mapSize = 192; | ||||
if (args.Has("autostart-size")) | if (args.Has("autostart-size")) | ||||
{ | { | ||||
CStr size = args.Get("autostart-size"); | CStr size = args.Get("autostart-size"); | ||||
mapSize = size.ToUInt(); | mapSize = size.ToUInt(); | ||||
} | } | ||||
Show All 15 Lines | for (size_t i = 0; i < numPlayers; ++i) | ||||
// We could load player_defaults.json here, but that would complicate the logic | // We could load player_defaults.json here, but that would complicate the logic | ||||
// even more and autostart is only intended for developers anyway | // even more and autostart is only intended for developers anyway | ||||
Script::CreateObject(rq, &player, "Civ", "athen"); | Script::CreateObject(rq, &player, "Civ", "athen"); | ||||
Script::SetPropertyInt(rq, playerData, i, player); | Script::SetPropertyInt(rq, playerData, i, player); | ||||
} | } | ||||
mapType = "random"; | mapType = "random"; | ||||
} | } | ||||
else if (mapDirectory == L"scenarios" || mapDirectory == L"skirmishes") | else if (mapDirectory == L"scenarios") | ||||
{ | |||||
// 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"; | mapType = "scenario"; | ||||
else | else if (mapDirectory == L"skirmishes") | ||||
mapType = "skirmish"; | mapType = "skirmish"; | ||||
} | |||||
else | else | ||||
{ | { | ||||
LOGERROR("Autostart: Unrecognized map type '%s'", utf8_from_wstring(mapDirectory)); | LOGERROR("Autostart: Unrecognized map type '%s'", utf8_from_wstring(mapDirectory)); | ||||
throw PSERROR_Game_World_MapLoadFailed("Unrecognized map type.\nConsult readme.txt for the currently supported types."); | throw PSERROR_Game_World_MapLoadFailed("Unrecognized map type.\nConsult readme.txt for the currently supported types."); | ||||
} | } | ||||
Script::SetProperty(rq, attrs, "mapType", mapType); | Script::SetProperty(rq, attrs, "mapType", mapType); | ||||
Script::SetProperty(rq, attrs, "map", "maps/" + autoStartName); | Script::SetProperty(rq, attrs, "map", "maps/" + autoStartName); | ||||
Show All 38 Lines | if (args.Has("autostart-team")) | ||||
std::vector<CStr> civArgs = args.GetMultiple("autostart-team"); | std::vector<CStr> civArgs = args.GetMultiple("autostart-team"); | ||||
for (size_t i = 0; i < civArgs.size(); ++i) | for (size_t i = 0; i < civArgs.size(); ++i) | ||||
{ | { | ||||
int playerID = civArgs[i].BeforeFirst(":").ToInt(); | int playerID = civArgs[i].BeforeFirst(":").ToInt(); | ||||
// Instead of overwriting existing player data, modify the array | // Instead of overwriting existing player data, modify the array | ||||
JS::RootedValue currentPlayer(rq.cx); | JS::RootedValue currentPlayer(rq.cx); | ||||
if (!Script::GetPropertyInt(rq, playerData, playerID-offset, ¤tPlayer) || currentPlayer.isUndefined()) | 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); | Script::CreateObject(rq, ¤tPlayer); | ||||
} | |||||
int teamID = civArgs[i].AfterFirst(":").ToInt() - 1; | int teamID = civArgs[i].AfterFirst(":").ToInt() - 1; | ||||
Script::SetProperty(rq, currentPlayer, "Team", teamID); | Script::SetProperty(rq, currentPlayer, "Team", teamID); | ||||
Script::SetPropertyInt(rq, playerData, playerID-offset, currentPlayer); | Script::SetPropertyInt(rq, playerData, playerID-offset, currentPlayer); | ||||
} | } | ||||
} | } | ||||
int ceasefire = 0; | int ceasefire = 0; | ||||
if (args.Has("autostart-ceasefire")) | if (args.Has("autostart-ceasefire")) | ||||
ceasefire = args.Get("autostart-ceasefire").ToInt(); | ceasefire = args.Get("autostart-ceasefire").ToInt(); | ||||
Script::SetProperty(rq, settings, "Ceasefire", ceasefire); | Script::SetProperty(rq, settings, "Ceasefire", ceasefire); | ||||
if (args.Has("autostart-ai")) | if (args.Has("autostart-ai")) | ||||
{ | { | ||||
std::vector<CStr> aiArgs = args.GetMultiple("autostart-ai"); | std::vector<CStr> aiArgs = args.GetMultiple("autostart-ai"); | ||||
for (size_t i = 0; i < aiArgs.size(); ++i) | for (size_t i = 0; i < aiArgs.size(); ++i) | ||||
{ | { | ||||
int playerID = aiArgs[i].BeforeFirst(":").ToInt(); | int playerID = aiArgs[i].BeforeFirst(":").ToInt(); | ||||
// Instead of overwriting existing player data, modify the array | // Instead of overwriting existing player data, modify the array | ||||
JS::RootedValue currentPlayer(rq.cx); | JS::RootedValue currentPlayer(rq.cx); | ||||
if (!Script::GetPropertyInt(rq, playerData, playerID-offset, ¤tPlayer) || currentPlayer.isUndefined()) | 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::CreateObject(rq, ¤tPlayer); | ||||
} | |||||
Script::SetProperty(rq, currentPlayer, "AI", aiArgs[i].AfterFirst(":")); | Script::SetProperty(rq, currentPlayer, "AI", aiArgs[i].AfterFirst(":")); | ||||
Script::SetProperty(rq, currentPlayer, "AIDiff", 3); | Script::SetProperty(rq, currentPlayer, "AIDiff", 3); | ||||
Script::SetProperty(rq, currentPlayer, "AIBehavior", "balanced"); | Script::SetProperty(rq, currentPlayer, "AIBehavior", "balanced"); | ||||
Script::SetPropertyInt(rq, playerData, playerID-offset, currentPlayer); | Script::SetPropertyInt(rq, playerData, playerID-offset, currentPlayer); | ||||
} | } | ||||
} | } | ||||
// Set AI difficulty | // Set AI difficulty | ||||
if (args.Has("autostart-aidiff")) | if (args.Has("autostart-aidiff")) | ||||
{ | { | ||||
std::vector<CStr> civArgs = args.GetMultiple("autostart-aidiff"); | std::vector<CStr> civArgs = args.GetMultiple("autostart-aidiff"); | ||||
for (size_t i = 0; i < civArgs.size(); ++i) | for (size_t i = 0; i < civArgs.size(); ++i) | ||||
{ | { | ||||
int playerID = civArgs[i].BeforeFirst(":").ToInt(); | int playerID = civArgs[i].BeforeFirst(":").ToInt(); | ||||
// Instead of overwriting existing player data, modify the array | // Instead of overwriting existing player data, modify the array | ||||
JS::RootedValue currentPlayer(rq.cx); | JS::RootedValue currentPlayer(rq.cx); | ||||
if (!Script::GetPropertyInt(rq, playerData, playerID-offset, ¤tPlayer) || currentPlayer.isUndefined()) | 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::CreateObject(rq, ¤tPlayer); | ||||
} | |||||
Script::SetProperty(rq, currentPlayer, "AIDiff", civArgs[i].AfterFirst(":").ToInt()); | Script::SetProperty(rq, currentPlayer, "AIDiff", civArgs[i].AfterFirst(":").ToInt()); | ||||
Script::SetPropertyInt(rq, playerData, playerID-offset, currentPlayer); | Script::SetPropertyInt(rq, playerData, playerID-offset, currentPlayer); | ||||
} | } | ||||
} | } | ||||
// Set player data for Civs | // Set player data for Civs | ||||
if (args.Has("autostart-civ")) | if (args.Has("autostart-civ")) | ||||
{ | { | ||||
if (mapDirectory != L"scenarios") | if (mapDirectory != L"scenarios") | ||||
{ | { | ||||
std::vector<CStr> civArgs = args.GetMultiple("autostart-civ"); | std::vector<CStr> civArgs = args.GetMultiple("autostart-civ"); | ||||
for (size_t i = 0; i < civArgs.size(); ++i) | for (size_t i = 0; i < civArgs.size(); ++i) | ||||
{ | { | ||||
int playerID = civArgs[i].BeforeFirst(":").ToInt(); | int playerID = civArgs[i].BeforeFirst(":").ToInt(); | ||||
// Instead of overwriting existing player data, modify the array | // Instead of overwriting existing player data, modify the array | ||||
JS::RootedValue currentPlayer(rq.cx); | JS::RootedValue currentPlayer(rq.cx); | ||||
if (!Script::GetPropertyInt(rq, playerData, playerID-offset, ¤tPlayer) || currentPlayer.isUndefined()) | 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::CreateObject(rq, ¤tPlayer); | ||||
} | |||||
Script::SetProperty(rq, currentPlayer, "Civ", civArgs[i].AfterFirst(":")); | Script::SetProperty(rq, currentPlayer, "Civ", civArgs[i].AfterFirst(":")); | ||||
Script::SetPropertyInt(rq, playerData, playerID-offset, currentPlayer); | Script::SetPropertyInt(rq, playerData, playerID-offset, currentPlayer); | ||||
} | } | ||||
} | } | ||||
else | else | ||||
LOGWARNING("Autostart: Option 'autostart-civ' is invalid for scenarios"); | 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 | // Add additional scripts to the TriggerScripts property | ||||
std::vector<CStrW> triggerScriptsVector; | std::vector<CStrW> triggerScriptsVector; | ||||
JS::RootedValue triggerScripts(rq.cx); | JS::RootedValue triggerScripts(rq.cx); | ||||
if (Script::HasProperty(rq, settings, "TriggerScripts")) | if (Script::HasProperty(rq, settings, "TriggerScripts")) | ||||
{ | { | ||||
Script::GetProperty(rq, settings, "TriggerScripts", &triggerScripts); | Script::GetProperty(rq, settings, "TriggerScripts", &triggerScripts); | ||||
Script::FromJSVal(rq, triggerScripts, triggerScriptsVector); | Script::FromJSVal(rq, triggerScripts, triggerScriptsVector); | ||||
} | } | ||||
if (!CRenderer::IsInitialised()) | if (!CRenderer::IsInitialised()) | ||||
{ | { | ||||
CStr nonVisualScript = "scripts/NonVisualTrigger.js"; | CStr nonVisualScript = "scripts/NonVisualTrigger.js"; | ||||
triggerScriptsVector.push_back(nonVisualScript.FromUTF8()); | triggerScriptsVector.push_back(nonVisualScript.FromUTF8()); | ||||
} | } | ||||
Script::ToJSVal(rq, &triggerScripts, triggerScriptsVector); | |||||
Script::SetProperty(rq, settings, "TriggerScripts", triggerScripts); | |||||
std::vector<CStr> victoryConditions(1, "conquest"); | std::vector<CStr> victoryConditions(1, "conquest"); | ||||
if (args.Has("autostart-victory")) | if (args.Has("autostart-victory")) | ||||
victoryConditions = args.GetMultiple("autostart-victory"); | victoryConditions = args.GetMultiple("autostart-victory"); | ||||
if (victoryConditions.size() == 1 && victoryConditions[0] == "endless") | if (victoryConditions.size() == 1 && victoryConditions[0] == "endless") | ||||
victoryConditions.clear(); | victoryConditions.clear(); | ||||
Script::SetProperty(rq, settings, "VictoryConditions", victoryConditions); | 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; | int wonderDuration = 10; | ||||
if (args.Has("autostart-wonderduration")) | if (args.Has("autostart-wonderduration")) | ||||
wonderDuration = args.Get("autostart-wonderduration").ToInt(); | wonderDuration = args.Get("autostart-wonderduration").ToInt(); | ||||
Script::SetProperty(rq, settings, "WonderDuration", wonderDuration); | Script::SetProperty(rq, settings, "WonderDuration", wonderDuration); | ||||
int relicDuration = 10; | int relicDuration = 10; | ||||
if (args.Has("autostart-relicduration")) | if (args.Has("autostart-relicduration")) | ||||
relicDuration = args.Get("autostart-relicduration").ToInt(); | relicDuration = args.Get("autostart-relicduration").ToInt(); | ||||
Script::SetProperty(rq, settings, "RelicDuration", relicDuration); | Script::SetProperty(rq, settings, "RelicDuration", relicDuration); | ||||
int relicCount = 2; | int relicCount = 2; | ||||
if (args.Has("autostart-reliccount")) | if (args.Has("autostart-reliccount")) | ||||
relicCount = args.Get("autostart-reliccount").ToInt(); | relicCount = args.Get("autostart-reliccount").ToInt(); | ||||
Script::SetProperty(rq, settings, "RelicCount", relicCount); | 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")) | if (args.Has("autostart-host")) | ||||
{ | { | ||||
InitPsAutostart(true, attrs); | int maxPlayers = 2; | ||||
size_t maxPlayers = 2; | |||||
if (args.Has("autostart-host-players")) | if (args.Has("autostart-host-players")) | ||||
maxPlayers = args.Get("autostart-host-players").ToUInt(); | maxPlayers = args.Get("autostart-host-players").ToUInt(); | ||||
// Generate a secret to identify the host client. | Script::CreateObject( | ||||
std::string secret = ps_generate_guid(); | rq, | ||||
&sessionInitData, | |||||
g_NetServer = new CNetServer(false, maxPlayers); | "attribs", attrs, | ||||
g_NetServer->SetControllerSecret(secret); | "playerName", userName, | ||||
g_NetServer->UpdateInitAttributes(&attrs, scriptInterface); | "port", PS_DEFAULT_PORT, | ||||
"maxPlayers", maxPlayers, | |||||
bool ok = g_NetServer->SetupConnection(PS_DEFAULT_PORT); | "storeReplay", !args.Has("autostart-disable-replay")); | ||||
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); | InitPs(true, L"page_autostart_host.xml", &scriptInterface, sessionInitData); | ||||
ENSURE(g_NetClient->SetupConnection(nullptr)); | |||||
} | } | ||||
else | 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()) | Script::CreateObject( | ||||
{ | rq, | ||||
InitPsAutostart(false, attrs); | &sessionInitData, | ||||
} | "attribs", attrs, | ||||
else | "playerAssignments", playerAssignments, | ||||
{ | "storeReplay", !args.Has("autostart-disable-replay")); | ||||
// TODO: Non progressive load can fail - need a decent way to handle this | |||||
LDR_NonprogressiveLoad(); | InitPs(true, L"page_autostart.xml", &scriptInterface, sessionInitData); | ||||
ENSURE(g_Game->ReallyStartGame() == PSRETURN_OK); | |||||
} | |||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool AutostartVisualReplay(const std::string& replayFile) | bool AutostartVisualReplay(const std::string& replayFile) | ||||
{ | { | ||||
if (!FileExists(OsPath(replayFile))) | if (!FileExists(OsPath(replayFile))) | ||||
return false; | return false; | ||||
g_Game = new CGame(false); | g_Game = new CGame(false); | ||||
g_Game->SetPlayerID(-1); | g_Game->SetPlayerID(-1); | ||||
g_Game->StartVisualReplay(replayFile); | g_Game->StartVisualReplay(replayFile); | ||||
ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface(); | ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface(); | ||||
ScriptRequest rq(scriptInterface); | ScriptRequest rq(scriptInterface); | ||||
JS::RootedValue attrs(rq.cx, g_Game->GetSimulation2()->GetInitAttributes()); | 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; | return true; | ||||
} | } | ||||
void CancelLoad(const CStrW& message) | void CancelLoad(const CStrW& message) | ||||
{ | { | ||||
std::shared_ptr<ScriptInterface> pScriptInterface = g_GUI->GetActiveGUI()->GetScriptInterface(); | std::shared_ptr<ScriptInterface> pScriptInterface = g_GUI->GetActiveGUI()->GetScriptInterface(); | ||||
ScriptRequest rq(pScriptInterface); | ScriptRequest rq(pScriptInterface); | ||||
Show All 20 Lines |
Wildfire Games · Phabricator