Index: binaries/data/mods/public/simulation/components/ProductionQueue.js =================================================================== --- binaries/data/mods/public/simulation/components/ProductionQueue.js +++ binaries/data/mods/public/simulation/components/ProductionQueue.js @@ -397,72 +397,69 @@ } }; -/* - * Removes an existing batch of units from the production queue. +/** + * Removes an item from the queue. * Refunds resource costs and population reservations. */ -ProductionQueue.prototype.RemoveBatch = function(id) +ProductionQueue.prototype.RemoveItem = function(id) { - // Destroy any cached entities (those which didn't spawn for some reason) - for (let ent of this.entityCache) - Engine.DestroyEntity(ent); + let itemIndex = this.queue.findIndex(item => item.id == id); + if (itemIndex == -1) + return; - this.entityCache = []; - - for (var i = 0; i < this.queue.length; ++i) + // Destroy any cached entities (those which didn't spawn for some reason). + if (itemIndex == 0 && this.entityCache.length > 0) { - var item = this.queue[i]; - if (item.id != id) - continue; + for (let ent of this.entityCache) + Engine.DestroyEntity(ent); - // Now we've found the item to remove + this.entityCache = []; + } - var cmpPlayer = QueryPlayerIDInterface(item.player); + let item = this.queue[itemIndex]; - // Update entity count in the EntityLimits component - if (item.unitTemplate) - { - var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); - var template = cmpTemplateManager.GetTemplate(item.unitTemplate); - if (template.TrainingRestrictions) - { - var unitCategory = template.TrainingRestrictions.Category; - var cmpPlayerEntityLimits = QueryPlayerIDInterface(item.player, IID_EntityLimits); - cmpPlayerEntityLimits.ChangeCount(unitCategory, -item.count); - } - } + // Take the player who paid because the entity's owner may be invalid (deletion, etc.) + let funder = item.player; + let cmpPlayer = QueryPlayerIDInterface(funder); - // Refund the resource cost for this batch - var totalCosts = {}; - var cmpStatisticsTracker = QueryPlayerIDInterface(item.player, IID_StatisticsTracker); - for (let r in item.resources) + if (item.unitTemplate) + { + if (item.productionStarted) + cmpPlayer.UnReservePopulationSlots(item.population * item.count); + + let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); + let template = cmpTemplateManager.GetTemplate(item.unitTemplate); + // Update entity count in the EntityLimits component. + if (template.TrainingRestrictions) { - totalCosts[r] = Math.floor(item.count * item.resources[r]); - if (cmpStatisticsTracker) - cmpStatisticsTracker.IncreaseResourceUsedCounter(r, -totalCosts[r]); + let unitCategory = template.TrainingRestrictions.Category; + let cmpPlayerEntityLimits = QueryPlayerIDInterface(funder, IID_EntityLimits); + cmpPlayerEntityLimits.ChangeCount(unitCategory, -item.count); } + } + else if (item.technologyTemplate) + { + let cmpTechnologyManager = QueryPlayerIDInterface(funder, IID_TechnologyManager); + cmpTechnologyManager.StoppedResearch(item.technologyTemplate, true); + } - cmpPlayer.AddResources(totalCosts); + // Refund the resource cost for this item. + let totalCosts = {}; + let cmpStatisticsTracker = QueryPlayerIDInterface(funder, IID_StatisticsTracker); + for (let res in item.resources) + { + totalCosts[res] = Math.floor(item.count * item.resources[res]); + if (cmpStatisticsTracker) + cmpStatisticsTracker.IncreaseResourceUsedCounter(res, -totalCosts[res]); + } - // Remove reserved population slots if necessary - if (item.productionStarted && item.unitTemplate) - cmpPlayer.UnReservePopulationSlots(item.population * item.count); + cmpPlayer.AddResources(totalCosts); - // Mark the research as stopped if we cancel it - if (item.technologyTemplate) - { - // item.player is used as this.entity's owner may be invalid (deletion, etc.) - var cmpTechnologyManager = QueryPlayerIDInterface(item.player, IID_TechnologyManager); - cmpTechnologyManager.StoppedResearch(item.technologyTemplate, true); - } + this.queue.splice(itemIndex, 1); + // There is no need to unset timer if it's the last item of the queue, + // it will expire when it discovers the queue is empty. - // Remove from the queue - // (We don't need to remove the timer - it'll expire if it discovers the queue is empty) - this.queue.splice(i, 1); - Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { }); - - return; - } + Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { }); }; /* @@ -487,17 +484,13 @@ return out; }; -/* - * Removes all existing batches from the queue. +/** + * Removes all existing items from the queue. */ ProductionQueue.prototype.ResetQueue = function() { - // Empty the production queue and refund all the resource costs - // to the player. (This is to avoid players having to micromanage their - // buildings' queues when they're about to be destroyed or captured.) - while (this.queue.length) - this.RemoveBatch(this.queue[0].id); + this.RemoveItem(this.queue[0].id); }; /* Index: binaries/data/mods/public/simulation/helpers/Commands.js =================================================================== --- binaries/data/mods/public/simulation/helpers/Commands.js +++ binaries/data/mods/public/simulation/helpers/Commands.js @@ -381,7 +381,7 @@ var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue); if (queue) - queue.RemoveBatch(cmd.id); + queue.RemoveItem(cmd.id); }, "construct": function(player, cmd, data)