Clean up LoadPlayerSettings.

Include gaia to make iteration easier.
Add TemplateExists() to the TemplateLoader. Refs #2877.

This was SVN commit r16099.
This commit is contained in:
leper 2015-01-01 23:10:24 +00:00
parent 8e30410109
commit a472944689
9 changed files with 113 additions and 110 deletions

View File

@ -31,8 +31,7 @@ PlayerManager.prototype.AddPlayer = function(ent)
/**
* To avoid possible problems with cached quantities (as in TechnologyManager),
* we first remove all entities from this player, and add them back after the replacement.
* Futhermore, because of the Engine.FlushDestroyedComponents, it should only be called during setup/init
* and not during the game
* Note: This should only be called during setup/init and not during the game
*/
PlayerManager.prototype.ReplacePlayer = function(id, ent)
{

View File

@ -24,21 +24,21 @@ function InitGame(settings)
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
if (settings.ExploreMap)
for (var i = 0; i < settings.PlayerData.length; i++)
cmpRangeManager.ExploreAllTiles(i+1);
for (let i = 1; i < settings.PlayerData.length; ++i)
cmpRangeManager.ExploreAllTiles(i);
else
// Explore the map only inside the players' territory borders
cmpRangeManager.ExploreTerritories();
let cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
let cmpAIManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_AIManager);
for (let i = 0; i < settings.PlayerData.length; ++i)
for (let i = 1; i < settings.PlayerData.length; ++i)
{
let cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(i+1), IID_Player);
let cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(i), IID_Player);
cmpPlayer.SetCheatsEnabled(!!settings.CheatsEnabled);
if (settings.PlayerData[i] && settings.PlayerData[i].AI && settings.PlayerData[i].AI != "")
{
cmpAIManager.AddPlayer(settings.PlayerData[i].AI, i+1, +settings.PlayerData[i].AIDiff);
cmpAIManager.AddPlayer(settings.PlayerData[i].AI, i, +settings.PlayerData[i].AIDiff);
cmpPlayer.SetAI(true);
// Sandbox: 50%, very easy: 50%, easy: 66%, Medium: 100%, hard: 133%, very hard: 166%
cmpPlayer.SetGatherRateMultiplier(Math.max(0.5,(+settings.PlayerData[i].AIDiff)/3.0));

View File

@ -19,43 +19,35 @@ function LoadPlayerSettings(settings, newPlayers)
if (!(rawData && rawData.PlayerData))
throw("Player.js: Error reading player_defaults.json");
// Add gaia to simplify iteration
if (settings.PlayerData)
settings.PlayerData.unshift({});
var playerDefaults = rawData.PlayerData;
var playerData = settings.PlayerData;
// Get player manager
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
var numPlayers = cmpPlayerManager.GetNumPlayers();
var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
var templatesList = cmpTemplateManager.FindAllTemplates(false);
var previousPlayers = numPlayers;
// Remove existing players or add new ones
if (newPlayers)
{
var settingsNumPlayers = 9; // default 8 players + gaia
if (settings.PlayerData)
settingsNumPlayers = settings.PlayerData.length + 1; // including gaia
if (playerData)
settingsNumPlayers = playerData.length; // includes gaia (see above)
else
warn("Player.js: Setup has no player data - using defaults");
previousPlayers = Math.min(numPlayers, settingsNumPlayers);
while (settingsNumPlayers > numPlayers)
{
// Add player entity to engine
var playerTemplate = "special/player";
if (numPlayers > 0)
{
var pDefs = playerDefaults ? playerDefaults[numPlayers] : {};
var pData = settings.PlayerData ? settings.PlayerData[numPlayers-1] : {};
var civ = getSetting(pData, pDefs, "Civ");
}
else
var civ = "gaia";
if (templatesList.indexOf("special/"+civ+"_player") !== -1)
playerTemplate = "special/"+civ+"_player";
var entID = Engine.AddEntity(playerTemplate);
var civ = getSetting(playerData, playerDefaults, i, "Civ");
var template = cmpTemplateManager.TemplateExists("special/"+civ+"_player") ? "special/"+civ+"_player" : "special/player";
var entID = Engine.AddEntity(template);
var cmpPlayer = Engine.QueryInterface(entID, IID_Player);
if (!cmpPlayer)
throw("Player.js: Error creating player entity " + numPlayers);
@ -72,19 +64,15 @@ function LoadPlayerSettings(settings, newPlayers)
}
// Even when no new player, we must check the template compatibility as player template may be civ dependent
for (var i = 1; i < previousPlayers; ++i)
for (var i = 0; i < numPlayers; ++i)
{
var pDefs = playerDefaults ? playerDefaults[i] : {};
var pData = settings.PlayerData ? settings.PlayerData[i-1] : {};
var civ = getSetting(pData, pDefs, "Civ");
var neededTemplate = "special/player";
if (templatesList.indexOf("special/"+civ+"_player") !== -1)
neededTemplate = "special/"+civ+"_player";
var civ = getSetting(playerData, playerDefaults, i, "Civ");
var template = cmpTemplateManager.TemplateExists("special/"+civ+"_player") ? "special/"+civ+"_player" : "special/player";
var entID = cmpPlayerManager.GetPlayerByID(i);
if (cmpTemplateManager.GetCurrentTemplateName(entID) === neededTemplate)
if (cmpTemplateManager.GetCurrentTemplateName(entID) === template)
continue;
// We need to recreate this player to have the right template
entID = Engine.AddEntity(neededTemplate);
entID = Engine.AddEntity(template);
cmpPlayerManager.ReplacePlayer(i, entID);
}
@ -92,79 +80,70 @@ function LoadPlayerSettings(settings, newPlayers)
for (var i = 0; i < numPlayers; ++i)
{
var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(i), IID_Player);
var pDefs = playerDefaults ? playerDefaults[i] : {};
cmpPlayer.SetName(getSetting(playerData, playerDefaults, i, "Name"));
cmpPlayer.SetCiv(getSetting(playerData, playerDefaults, i, "Civ"));
var colour = getSetting(playerData, playerDefaults, i, "Colour");
cmpPlayer.SetColour(colour.r, colour.g, colour.b);
// Skip gaia
if (i > 0)
// Special case for gaia
if (i == 0)
{
var pData = settings.PlayerData ? settings.PlayerData[i-1] : {};
cmpPlayer.SetName(getSetting(pData, pDefs, "Name"));
cmpPlayer.SetCiv(getSetting(pData, pDefs, "Civ"));
var colour = getSetting(pData, pDefs, "Colour");
cmpPlayer.SetColour(colour.r, colour.g, colour.b);
// Note: this is not yet implemented but I leave it commented to highlight it's easy
// If anyone ever adds handicap.
//if (getSetting(pData, pDefs, "GatherRateMultiplier") !== undefined)
// cmpPlayer.SetGatherRateMultiplier(getSetting(pData, pDefs, "GatherRateMultiplier"));
if (getSetting(pData, pDefs, "PopulationLimit") !== undefined)
cmpPlayer.SetMaxPopulation(getSetting(pData, pDefs, "PopulationLimit"));
if (getSetting(pData, pDefs, "Resources") !== undefined)
cmpPlayer.SetResourceCounts(getSetting(pData, pDefs, "Resources"));
// If diplomacy explicitly defined, use that; otherwise use teams
if (getSetting(pData, pDefs, "Diplomacy") !== undefined)
cmpPlayer.SetDiplomacy(getSetting(pData, pDefs, "Diplomacy"));
else
{
// Init diplomacy
var myTeam = getSetting(pData, pDefs, "Team");
// Set all but self as enemies as SetTeam takes care of allies
for (var j = 0; j < numPlayers; ++j)
{
if (i == j)
cmpPlayer.SetAlly(j);
else
cmpPlayer.SetEnemy(j);
}
cmpPlayer.SetTeam((myTeam !== undefined) ? myTeam : -1);
}
// If formations explicitly defined, use that; otherwise use civ defaults
var formations = getSetting(pData, pDefs, "Formations");
if (formations !== undefined)
cmpPlayer.SetFormations(formations);
else
{
var rawFormations = Engine.ReadCivJSONFile(cmpPlayer.GetCiv()+".json");
if (!(rawFormations && rawFormations.Formations))
throw("Player.js: Error reading "+cmpPlayer.GetCiv()+".json");
cmpPlayer.SetFormations(rawFormations.Formations);
}
var startCam = getSetting(pData, pDefs, "StartingCamera");
if (startCam !== undefined)
cmpPlayer.SetStartingCamera(startCam.Position, startCam.Rotation);
}
else
{
// Copy gaia data from defaults
cmpPlayer.SetName(pDefs.Name);
cmpPlayer.SetCiv(pDefs.Civ);
cmpPlayer.SetColour(pDefs.Colour.r, pDefs.Colour.g, pDefs.Colour.b);
// Gaia should be its own ally.
cmpPlayer.SetAlly(0);
// Gaia is everyone's enemy
for (var j = 1; j < numPlayers; ++j)
cmpPlayer.SetEnemy(j);
continue;
}
// Note: this is not yet implemented but I leave it commented to highlight it's easy
// If anyone ever adds handicap.
//if (getSetting(playerData, playerDefaults, i, "GatherRateMultiplier") !== undefined)
// cmpPlayer.SetGatherRateMultiplier(getSetting(playerData, playerDefaults, i, "GatherRateMultiplier"));
if (getSetting(playerData, playerDefaults, i, "PopulationLimit") !== undefined)
cmpPlayer.SetMaxPopulation(getSetting(playerData, playerDefaults, i, "PopulationLimit"));
if (getSetting(playerData, playerDefaults, i, "Resources") !== undefined)
cmpPlayer.SetResourceCounts(getSetting(playerData, playerDefaults, i, "Resources"));
// If diplomacy explicitly defined, use that; otherwise use teams
if (getSetting(playerData, playerDefaults, i, "Diplomacy") !== undefined)
cmpPlayer.SetDiplomacy(getSetting(playerData, playerDefaults, i, "Diplomacy"));
else
{
// Init diplomacy
var myTeam = getSetting(playerData, playerDefaults, i, "Team");
// Set all but self as enemies as SetTeam takes care of allies
for (var j = 0; j < numPlayers; ++j)
{
if (i == j)
cmpPlayer.SetAlly(j);
else
cmpPlayer.SetEnemy(j);
}
cmpPlayer.SetTeam((myTeam !== undefined) ? myTeam : -1);
}
// If formations explicitly defined, use that; otherwise use civ defaults
var formations = getSetting(playerData, playerDefaults, i, "Formations");
if (formations !== undefined)
cmpPlayer.SetFormations(formations);
else
{
var rawFormations = Engine.ReadCivJSONFile(cmpPlayer.GetCiv()+".json");
if (!(rawFormations && rawFormations.Formations))
throw("Player.js: Error reading "+cmpPlayer.GetCiv()+".json");
cmpPlayer.SetFormations(rawFormations.Formations);
}
var startCam = getSetting(playerData, playerDefaults, i, "StartingCamera");
if (startCam !== undefined)
cmpPlayer.SetStartingCamera(startCam.Position, startCam.Rotation);
}
// NOTE: We need to do the team locking here, as otherwise
@ -178,14 +157,14 @@ function LoadPlayerSettings(settings, newPlayers)
}
// Get a setting if it exists or return default
function getSetting(settings, defaults, property)
function getSetting(settings, defaults, idx, property)
{
if (settings && (property in settings))
return settings[property];
if (settings && settings[idx] && (property in settings[idx]))
return settings[idx][property];
// Use defaults
if (defaults && (property in defaults))
return defaults[property];
if (defaults && defaults[idx] && (property in defaults[idx]))
return defaults[idx][property];
return undefined;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2014 Wildfire Games.
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -206,6 +206,13 @@ static Status AddActorToTemplates(const VfsPath& pathname, const CFileInfo& UNUS
return INFO::OK;
}
bool CTemplateLoader::TemplateExists(const std::string& templateName)
{
size_t pos = templateName.rfind('|');
std::string baseName(pos != std::string::npos ? templateName.substr(pos+1) : templateName);
return VfsFileExists(VfsPath(TEMPLATE_ROOT) / wstring_from_utf8(baseName + ".xml"));
}
std::vector<std::string> CTemplateLoader::FindPlaceableTemplates(const std::string& path, bool includeSubdirectories, ETemplatesType templatesType, ScriptInterface& scriptInterface)
{
JSContext* cx = scriptInterface.GetContext();

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2014 Wildfire Games.
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -54,6 +54,11 @@ public:
*/
const CParamNode& GetTemplateFileData(const std::string& templateName);
/**
* Check if the template XML file exits, without trying to load it.
*/
bool TemplateExists(const std::string& templateName);
/**
* Returns a list of strings that could be validly passed as @c templateName to LoadTemplateFile.
* (This includes "actor|foo" etc names).

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2014 Wildfire Games.
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -124,6 +124,8 @@ public:
virtual const CParamNode* GetTemplateWithoutValidation(std::string templateName);
virtual bool TemplateExists(std::string templateName);
virtual const CParamNode* LoadLatestTemplate(entity_id_t ent);
virtual std::string GetCurrentTemplateName(entity_id_t ent);
@ -212,6 +214,11 @@ const CParamNode* CCmpTemplateManager::GetTemplateWithoutValidation(std::string
return &templateRoot;
}
bool CCmpTemplateManager::TemplateExists(std::string templateName)
{
return m_templateLoader.TemplateExists(templateName);
}
const CParamNode* CCmpTemplateManager::LoadLatestTemplate(entity_id_t ent)
{
std::map<entity_id_t, std::string>::const_iterator it = m_LatestTemplates.find(ent);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010 Wildfire Games.
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -24,6 +24,7 @@
BEGIN_INTERFACE_WRAPPER(TemplateManager)
DEFINE_INTERFACE_METHOD_1("GetTemplate", const CParamNode*, ICmpTemplateManager, GetTemplate, std::string)
DEFINE_INTERFACE_METHOD_1("GetTemplateWithoutValidation", const CParamNode*, ICmpTemplateManager, GetTemplateWithoutValidation, std::string)
DEFINE_INTERFACE_METHOD_1("TemplateExists", bool, ICmpTemplateManager, TemplateExists, std::string)
DEFINE_INTERFACE_METHOD_1("GetCurrentTemplateName", std::string, ICmpTemplateManager, GetCurrentTemplateName, entity_id_t)
DEFINE_INTERFACE_METHOD_1("FindAllTemplates", std::vector<std::string>, ICmpTemplateManager, FindAllTemplates, bool)
DEFINE_INTERFACE_METHOD_1("GetEntitiesUsingTemplate", std::vector<entity_id_t>, ICmpTemplateManager, GetEntitiesUsingTemplate, std::string)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2014 Wildfire Games.
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -73,6 +73,11 @@ public:
*/
virtual const CParamNode* GetTemplateWithoutValidation(std::string templateName) = 0;
/**
* Check if the template XML file exists, without trying to load it.
*/
virtual bool TemplateExists(std::string templateName) = 0;
/**
* Returns the template most recently specified for the entity 'ent'.
* Used during deserialization.

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2014 Wildfire Games.
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -668,7 +668,7 @@ void PlayerSettingsControl::ReadFromEngine()
m_NumPlayers = MAX_NUM_PLAYERS;
}
else
m_NumPlayers = player.count();
m_NumPlayers = player.count() - 1; // skip gaia
wxASSERT(m_NumPlayers <= MAX_NUM_PLAYERS && m_NumPlayers != 0);