Add safeguards for all queryOwnerInterface calls

Comments By: Angen, wraitii
Reviewed By: Freagarach
Differential Revision: D2973
This was SVN commit r24050.
This commit is contained in:
bb
2020-09-19 17:55:34 +00:00
parent ff9a5fe8f9
commit 31df44673a
11 changed files with 67 additions and 30 deletions
@@ -211,7 +211,11 @@ Trigger.prototype.StartAnEnemyWave = function()
} }
// Don't spawn attackers for defeated players and players that lost their cc after win // Don't spawn attackers for defeated players and players that lost their cc after win
let playerID = QueryOwnerInterface(point, IID_Player).GetPlayerID(); let cmpPlayer = QueryOwnerInterface(point, IID_Player);
if (!cmpPlayer)
continue;
let playerID = cmpPlayer.GetPlayerID();
let civicCentre = this.playerCivicCenter[playerID]; let civicCentre = this.playerCivicCenter[playerID];
if (!civicCentre) if (!civicCentre)
continue; continue;
@@ -38,7 +38,7 @@ Trigger.prototype.CheckCaptureTheRelicVictory = function(data)
if (data.to == -1) if (data.to == -1)
{ {
warn("Relic entity " + data.entity + " has been destroyed"); warn("Relic entity " + data.entity + " has been destroyed.");
this.relics.splice(this.relics.indexOf(data.entity), 1); this.relics.splice(this.relics.indexOf(data.entity), 1);
} }
else else
@@ -130,6 +130,14 @@ Trigger.prototype.StartCaptureTheRelicCountdown = function(winningPlayers)
} }
let cmpPlayer = QueryOwnerInterface(this.relics[0], IID_Player); let cmpPlayer = QueryOwnerInterface(this.relics[0], IID_Player);
if (!cmpPlayer)
{
warn("Relic entity " + this.relics[0] + " has no owner.");
this.relics.splice(0, 1);
this.CheckCaptureTheRelicCountdown();
return;
}
let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager); let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
let captureTheRelicDuration = cmpEndGameManager.GetGameSettings().relicDuration; let captureTheRelicDuration = cmpEndGameManager.GetGameSettings().relicDuration;
@@ -92,8 +92,11 @@ BuildRestrictions.prototype.CheckPlacement = function()
"translateParameters": ["name"], "translateParameters": ["name"],
}; };
// TODO: AI has no visibility info
var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
if (!cmpPlayer)
return result; // Fail
// TODO: AI has no visibility info
if (!cmpPlayer.IsAI()) if (!cmpPlayer.IsAI())
{ {
// Check whether it's in a visible or fogged region // Check whether it's in a visible or fogged region
@@ -164,9 +167,8 @@ BuildRestrictions.prototype.CheckPlacement = function()
// Check territory restrictions // Check territory restrictions
var cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager); var cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager);
var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
if (!(cmpTerritoryManager && cmpPlayer && cmpPosition && cmpPosition.IsInWorld())) if (!cmpTerritoryManager || !cmpPosition || !cmpPosition.IsInWorld())
return result; // Fail return result; // Fail
var pos = cmpPosition.GetPosition2D(); var pos = cmpPosition.GetPosition2D();
@@ -239,7 +241,6 @@ BuildRestrictions.prototype.CheckPlacement = function()
if (this.template.Distance) if (this.template.Distance)
{ {
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
var cat = this.template.Distance.FromClass; var cat = this.template.Distance.FromClass;
var filter = function(id) var filter = function(id)
@@ -34,7 +34,8 @@ Looter.prototype.Collect = function(targetEntity)
// Transfer resources // Transfer resources
var cmpPlayer = QueryOwnerInterface(this.entity); var cmpPlayer = QueryOwnerInterface(this.entity);
cmpPlayer.AddResources(resources); if (cmpPlayer)
cmpPlayer.AddResources(resources);
// Update statistics // Update statistics
var cmpStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker); var cmpStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
@@ -303,6 +303,8 @@ ProductionQueue.prototype.IsTechnologyResearchedOrInProgress = function(tech)
return false; return false;
let cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager); let cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager);
if (!cmpTechnologyManager)
return false;
let template = TechnologyTemplates.Get(tech); let template = TechnologyTemplates.Get(tech);
if (template.top) if (template.top)
@@ -323,6 +325,8 @@ ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat
// TODO: there should be a way for the GUI to determine whether it's going // TODO: there should be a way for the GUI to determine whether it's going
// to be possible to add a batch (based on resource costs and length limits). // to be possible to add a batch (based on resource costs and length limits).
let cmpPlayer = QueryOwnerInterface(this.entity); let cmpPlayer = QueryOwnerInterface(this.entity);
if (!cmpPlayer)
return;
if (this.queue.length < this.MaxQueueSize) if (this.queue.length < this.MaxQueueSize)
{ {
@@ -376,7 +380,8 @@ ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat
{ {
let unitCategory = template.TrainingRestrictions.Category; let unitCategory = template.TrainingRestrictions.Category;
let cmpPlayerEntityLimits = QueryOwnerInterface(this.entity, IID_EntityLimits); let cmpPlayerEntityLimits = QueryOwnerInterface(this.entity, IID_EntityLimits);
cmpPlayerEntityLimits.ChangeCount(unitCategory, count); if (cmpPlayerEntityLimits)
cmpPlayerEntityLimits.ChangeCount(unitCategory, count);
} }
let buildTime = ApplyValueModificationsToTemplate( let buildTime = ApplyValueModificationsToTemplate(
@@ -718,13 +723,12 @@ ProductionQueue.prototype.SpawnUnits = function(templateName, count, metadata)
// since it will be increased by EntityLimits.OnGlobalOwnershipChanged function, // since it will be increased by EntityLimits.OnGlobalOwnershipChanged function,
// i.e. we replace a 'trained' entity by 'alive' one. // i.e. we replace a 'trained' entity by 'alive' one.
// Must be done after spawn check so EntityLimits decrements only if unit spawns. // Must be done after spawn check so EntityLimits decrements only if unit spawns.
let cmpTrainingRestrictions = Engine.QueryInterface(ent, IID_TrainingRestrictions); if (cmpPlayerEntityLimits)
if (cmpTrainingRestrictions)
{ {
let unitCategory = cmpTrainingRestrictions.GetCategory(); let cmpTrainingRestrictions = Engine.QueryInterface(ent, IID_TrainingRestrictions);
cmpPlayerEntityLimits.ChangeCount(unitCategory, -1); if (cmpTrainingRestrictions)
cmpPlayerEntityLimits.ChangeCount(cmpTrainingRestrictions.GetCategory(), -1);
} }
cmpNewOwnership.SetOwner(cmpOwnership.GetOwner()); cmpNewOwnership.SetOwner(cmpOwnership.GetOwner());
if (cmpPlayerStatisticsTracker) if (cmpPlayerStatisticsTracker)
@@ -773,11 +777,15 @@ ProductionQueue.prototype.ProgressTimeout = function(data)
// Check if the production is paused (eg the entity is garrisoned) // Check if the production is paused (eg the entity is garrisoned)
if (this.paused) if (this.paused)
return; return;
let cmpPlayer = QueryOwnerInterface(this.entity);
if (!cmpPlayer)
return;
// Allocate available time to as many queue items as it takes // Allocate available time to as many queue items as it takes
// until we've used up all the time (so that we work accurately // until we've used up all the time (so that we work accurately
// with items that take fractions of a second). // with items that take fractions of a second).
let time = this.ProgressInterval; let time = this.ProgressInterval;
let cmpPlayer = QueryOwnerInterface(this.entity);
let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
while (time > 0 && this.queue.length) while (time > 0 && this.queue.length)
@@ -815,7 +823,11 @@ ProductionQueue.prototype.ProgressTimeout = function(data)
{ {
// Mark the research as started. // Mark the research as started.
let cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager); let cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager);
cmpTechnologyManager.StartedResearch(item.technologyTemplate, true); if (cmpTechnologyManager)
cmpTechnologyManager.StartedResearch(item.technologyTemplate, true);
else
warn("Failed to start researching " + item.technologyTemplate + ": No TechnologyManager available.");
this.SetAnimation("researching"); this.SetAnimation("researching");
} }
@@ -877,13 +889,16 @@ ProductionQueue.prototype.ProgressTimeout = function(data)
else if (item.technologyTemplate) else if (item.technologyTemplate)
{ {
let cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager); let cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager);
cmpTechnologyManager.ResearchTechnology(item.technologyTemplate); if (cmpTechnologyManager)
cmpTechnologyManager.ResearchTechnology(item.technologyTemplate);
else
warn("Failed to stop researching " + item.technologyTemplate + ": No TechnologyManager available.");
this.SetAnimation("idle"); this.SetAnimation("idle");
let template = TechnologyTemplates.Get(item.technologyTemplate); let template = TechnologyTemplates.Get(item.technologyTemplate);
if (template && template.soundComplete) if (template && template.soundComplete)
{ {
let cmpSoundManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_SoundManager); let cmpSoundManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_SoundManager);
if (cmpSoundManager) if (cmpSoundManager)
cmpSoundManager.PlaySoundGroup(template.soundComplete, this.entity); cmpSoundManager.PlaySoundGroup(template.soundComplete, this.entity);
} }
@@ -60,19 +60,23 @@ Promotion.prototype.IncreaseXp = function(amount)
return; return;
} }
this.currentXp += +(amount); this.currentXp += +amount;
var requiredXp = this.GetRequiredXp(); let requiredXp = this.GetRequiredXp();
if (this.currentXp >= requiredXp) if (this.currentXp >= requiredXp)
{ {
var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
var playerID = QueryOwnerInterface(this.entity, IID_Player).GetPlayerID(); let cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
if (!cmpPlayer)
return;
let playerID = cmpPlayer.GetPlayerID();
this.currentXp -= requiredXp; this.currentXp -= requiredXp;
var promotedTemplateName = this.GetPromotedTemplateName(); let promotedTemplateName = this.GetPromotedTemplateName();
// check if we can upgrade a second time (or even more) // check if we can upgrade a second time (or even more)
while (true) while (true)
{ {
var template = cmpTemplateManager.GetTemplate(promotedTemplateName); let template = cmpTemplateManager.GetTemplate(promotedTemplateName);
if (!template.Promotion) if (!template.Promotion)
break; break;
requiredXp = ApplyValueModificationsToTemplate("Promotion/RequiredXp", +template.Promotion.RequiredXp, playerID, template); requiredXp = ApplyValueModificationsToTemplate("Promotion/RequiredXp", +template.Promotion.RequiredXp, playerID, template);
@@ -358,7 +358,8 @@ ResourceGatherer.prototype.OnGlobalInitGame = function(msg)
ResourceGatherer.prototype.OnMultiplierChanged = function(msg) ResourceGatherer.prototype.OnMultiplierChanged = function(msg)
{ {
if (msg.player == QueryOwnerInterface(this.entity, IID_Player).GetPlayerID()) let cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
if (cmpPlayer && msg.player == cmpPlayer.GetPlayerID())
this.RecalculateGatherRatesAndCapacities(); this.RecalculateGatherRatesAndCapacities();
}; };
@@ -29,6 +29,9 @@ SkirmishReplacer.prototype.OnOwnershipChanged = function(msg)
SkirmishReplacer.prototype.ReplaceEntities = function() SkirmishReplacer.prototype.ReplaceEntities = function()
{ {
var cmpPlayer = QueryOwnerInterface(this.entity); var cmpPlayer = QueryOwnerInterface(this.entity);
if (!cmpPlayer)
return;
var civ = cmpPlayer.GetCiv(); var civ = cmpPlayer.GetCiv();
var replacementEntities = getReplacementEntities(civ); var replacementEntities = getReplacementEntities(civ);
@@ -81,7 +81,7 @@ Trader.prototype.RemoveTargetMarket = function(target)
this.index = -1; this.index = -1;
this.markets = []; this.markets = [];
return true; return true;
} };
// Set target as target market. // Set target as target market.
// Return true if at least one of markets was changed. // Return true if at least one of markets was changed.
@@ -184,7 +184,7 @@ Trader.prototype.CanTrade = function(target)
let cmpTraderPlayer = QueryOwnerInterface(this.entity, IID_Player); let cmpTraderPlayer = QueryOwnerInterface(this.entity, IID_Player);
let cmpTargetPlayer = QueryOwnerInterface(target, IID_Player); let cmpTargetPlayer = QueryOwnerInterface(target, IID_Player);
return !cmpTraderPlayer.IsEnemy(cmpTargetPlayer.GetPlayerID()); return cmpTraderPlayer && cmpTargetPlayer && !cmpTraderPlayer.IsEnemy(cmpTargetPlayer.GetPlayerID());
}; };
Trader.prototype.AddResources = function(ent, gain) Trader.prototype.AddResources = function(ent, gain)
@@ -230,7 +230,7 @@ Upgrade.prototype.Upgrade = function(template)
let cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); let cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
this.expendedResources = this.GetResourceCosts(template); this.expendedResources = this.GetResourceCosts(template);
if (!cmpPlayer.TrySubtractResources(this.expendedResources)) if (!cmpPlayer || !cmpPlayer.TrySubtractResources(this.expendedResources))
{ {
this.expendedResources = {}; this.expendedResources = {};
return false; return false;
@@ -296,7 +296,7 @@ var g_Commands = {
if (unitCategory) if (unitCategory)
{ {
var cmpPlayerEntityLimits = QueryOwnerInterface(ent, IID_EntityLimits); var cmpPlayerEntityLimits = QueryOwnerInterface(ent, IID_EntityLimits);
if (!cmpPlayerEntityLimits.AllowedToTrain(unitCategory, cmd.count)) if (cmpPlayerEntityLimits && !cmpPlayerEntityLimits.AllowedToTrain(unitCategory, cmd.count))
{ {
if (g_DebugCommands) if (g_DebugCommands)
warn(unitCategory + " train limit is reached: " + uneval(cmd)); warn(unitCategory + " train limit is reached: " + uneval(cmd));
@@ -305,7 +305,7 @@ var g_Commands = {
} }
var cmpTechnologyManager = QueryOwnerInterface(ent, IID_TechnologyManager); var cmpTechnologyManager = QueryOwnerInterface(ent, IID_TechnologyManager);
if (!cmpTechnologyManager.CanProduce(cmd.template)) if (cmpTechnologyManager && !cmpTechnologyManager.CanProduce(cmd.template))
{ {
if (g_DebugCommands) if (g_DebugCommands)
warn("Invalid command: training requires unresearched technology: " + uneval(cmd)); warn("Invalid command: training requires unresearched technology: " + uneval(cmd));
@@ -348,7 +348,7 @@ var g_Commands = {
} }
var cmpTechnologyManager = QueryOwnerInterface(cmd.entity, IID_TechnologyManager); var cmpTechnologyManager = QueryOwnerInterface(cmd.entity, IID_TechnologyManager);
if (!cmpTechnologyManager.CanResearch(cmd.template)) if (cmpTechnologyManager && !cmpTechnologyManager.CanResearch(cmd.template))
{ {
if (g_DebugCommands) if (g_DebugCommands)
warn("Invalid command: Requirements to research technology are not met: " + uneval(cmd)); warn("Invalid command: Requirements to research technology are not met: " + uneval(cmd));