Index: binaries/data/mods/public/simulation/components/ResourceSupply.js =================================================================== --- binaries/data/mods/public/simulation/components/ResourceSupply.js +++ binaries/data/mods/public/simulation/components/ResourceSupply.js @@ -81,13 +81,20 @@ }; /** - * @param {number} gathererID The gatherer's entity id. - * @param {number} player The gatherer's id. - * @return {boolean} Whether the ResourceSupply can have additional gatherers. + * @param {number} gathererID - The gatherer's entity id. + * @return {boolean} - Whether the ResourceSupply can have this additional gatherer or it is already gathering. + */ +ResourceSupply.prototype.IsAvailableTo = function(gathererID) +{ + return this.IsAvailable() || this.IsGatheringUs(gathererID); +}; + +/** + * @return {boolean} - Whether the ResourceSupply can have an additional gatherer. */ -ResourceSupply.prototype.IsAvailable = function(player, gathererID) +ResourceSupply.prototype.IsAvailable = function() { - return this.GetCurrentAmount() > 0 && (this.GetNumGatherers() < this.GetMaxGatherers() || this.gatherers[player].indexOf(gathererID) != -1); + return this.GetCurrentAmount() > 0 && this.GetNumGatherers() < this.GetMaxGatherers(); }; /** @@ -138,21 +145,29 @@ }; /** - * @param {number} player The gatherer's id. - * @param {number} gathererID The gatherer's player id. - * @returns {boolean} Whether the gatherer was successfully added to the entity's gatherers list. + * @param {number} gathererID - The gatherer to add. + * @return {boolean} - Whether the gatherer was successfully added to the entity's gatherers list. */ -ResourceSupply.prototype.AddGatherer = function(player, gathererID) +ResourceSupply.prototype.AddGatherer = function(gathererID) { - if (!this.IsAvailable(player, gathererID)) + if (!this.IsAvailable()) return false; - if (this.gatherers[player].indexOf(gathererID) == -1) - { - this.gatherers[player].push(gathererID); - // broadcast message, mainly useful for the AIs. - Engine.PostMessage(this.entity, MT_ResourceSupplyNumGatherersChanged, { "to": this.GetNumGatherers() }); - } + if (this.IsGatheringUs(gathererID)) + return true; + + let cmpOwnership = Engine.QueryInterface(gathererID, IID_Ownership); + if (!cmpOwnership) + return false; + + let gathererOwner = cmpOwnership.GetOwner(); + if (gathererOwner == INVALID_ENTITY) + return false; + + this.gatherers[gathererOwner].push(gathererID); + + // Broadcast message, mainly useful for the AIs. + Engine.PostMessage(this.entity, MT_ResourceSupplyNumGatherersChanged, { "to": this.GetNumGatherers() }); return true; }; @@ -182,4 +197,17 @@ Engine.PostMessage(this.entity, MT_ResourceSupplyNumGatherersChanged, { "to": this.GetNumGatherers() }); }; +/** + * @param {number} entity - The entity ID to check for. + * @return {boolean} - Whether the given entity is already gathering at us. + */ +ResourceSupply.prototype.IsGatheringUs = function(entity) +{ + for (let gatherers of this.gatherers) + if (gatherers.indexOf(entity) != -1) + return true; + + return false; +}; + Engine.RegisterComponentType(IID_ResourceSupply, "ResourceSupply", ResourceSupply); Index: binaries/data/mods/public/simulation/components/UnitAI.js =================================================================== --- binaries/data/mods/public/simulation/components/UnitAI.js +++ binaries/data/mods/public/simulation/components/UnitAI.js @@ -2246,11 +2246,10 @@ this.gatheringTarget = this.order.data.target; // temporary, deleted in "leave". // Check that we can gather from the resource we're supposed to gather from. - let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); let cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); let cmpMirage = Engine.QueryInterface(this.gatheringTarget, IID_Mirage); if ((!cmpMirage || !cmpMirage.Mirages(IID_ResourceSupply)) && - (!cmpSupply || !cmpSupply.AddGatherer(cmpOwnership.GetOwner(), this.entity)) || + (!cmpSupply || !cmpSupply.AddGatherer(this.entity)) || !this.MoveTo(this.order.data, IID_ResourceGatherer)) { // If the target's last known position is in FOW, try going there @@ -2324,11 +2323,8 @@ // Check if the resource is full. // Will only be added if we're not already in. - let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); - let cmpSupply; - if (cmpOwnership) - cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); - if (!cmpSupply || !cmpSupply.AddGatherer(cmpOwnership.GetOwner(), this.entity)) + let cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); + if (!cmpSupply || !cmpSupply.AddGatherer(this.entity)) { this.SetNextState("FINDINGNEWTARGET"); return true; @@ -2395,10 +2391,6 @@ let resourceTemplate = this.order.data.template; let resourceType = this.order.data.type; - let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); - if (!cmpOwnership) - return; - // TODO: we are leaking information here - if the target died in FOW, we'll know it's dead // straight away. // Seems one would have to listen to ownership changed messages to make it work correctly @@ -2406,7 +2398,7 @@ let cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); // If we can't gather from the target, find a new one. - if (!cmpSupply || !cmpSupply.IsAvailable(cmpOwnership.GetOwner(), this.entity) || + if (!cmpSupply || !cmpSupply.IsAvailableTo(this.entity) || !this.CanGather(this.gatheringTarget)) { this.SetNextState("FINDINGNEWTARGET"); @@ -4339,11 +4331,6 @@ if (!position) return undefined; - let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); - if (!cmpOwnership || cmpOwnership.GetOwner() == INVALID_PLAYER) - return undefined; - let owner = cmpOwnership.GetOwner(); - // We accept resources owned by Gaia or any player let players = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetAllPlayers(); @@ -4364,7 +4351,7 @@ if (template.indexOf("resource|") != -1) template = template.slice(9); - return amount > 0 && cmpResourceSupply.IsAvailable(owner, this.entity) && filter(ent, type, template); + return amount > 0 && cmpResourceSupply.IsAvailableTo(this.entity) && filter(ent, type, template); }); }; Index: binaries/data/mods/public/simulation/components/tests/test_ResourceSupply.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_ResourceSupply.js +++ binaries/data/mods/public/simulation/components/tests/test_ResourceSupply.js @@ -24,6 +24,22 @@ "Activate": () => {} }); +AddMock(70, IID_Ownership, { + "GetOwner": () => 1 +}); + +AddMock(71, IID_Ownership, { + "GetOwner": () => 1 +}); + +AddMock(72, IID_Ownership, { + "GetOwner": () => 2 +}); + +AddMock(73, IID_Ownership, { + "GetOwner": () => 1 +}); + let template = { "Amount": 1000, "Type": "food.meat", @@ -45,19 +61,19 @@ TS_ASSERT_EQUALS(cmpResourceSupply.GetNumGatherers(), 0); -TS_ASSERT(cmpResourceSupply.IsAvailable(1, 70)); -TS_ASSERT(cmpResourceSupply.AddGatherer(1, 70)); +TS_ASSERT(cmpResourceSupply.IsAvailableTo(70)); +TS_ASSERT(cmpResourceSupply.AddGatherer(70)); TS_ASSERT_EQUALS(cmpResourceSupply.GetNumGatherers(), 1); -TS_ASSERT(cmpResourceSupply.AddGatherer(1, 71)); +TS_ASSERT(cmpResourceSupply.AddGatherer(71)); TS_ASSERT_EQUALS(cmpResourceSupply.GetNumGatherers(), 2); -TS_ASSERT(!cmpResourceSupply.AddGatherer(2, 72)); +TS_ASSERT(!cmpResourceSupply.AddGatherer(72)); TS_ASSERT_EQUALS(cmpResourceSupply.GetNumGatherers(), 2); -TS_ASSERT(cmpResourceSupply.IsAvailable(1, 70)); -TS_ASSERT(!cmpResourceSupply.IsAvailable(1, 73)); -TS_ASSERT(!cmpResourceSupply.AddGatherer(1, 73)); +TS_ASSERT(cmpResourceSupply.IsAvailableTo(70)); +TS_ASSERT(!cmpResourceSupply.IsAvailableTo(73)); +TS_ASSERT(!cmpResourceSupply.AddGatherer(73)); TS_ASSERT_EQUALS(cmpResourceSupply.GetNumGatherers(), 2); cmpResourceSupply.RemoveGatherer(70, 1); @@ -66,9 +82,9 @@ TS_ASSERT_UNEVAL_EQUALS(cmpResourceSupply.GetCurrentAmount(), 1000); TS_ASSERT_UNEVAL_EQUALS(cmpResourceSupply.TakeResources(300), { "amount": 300, "exhausted": false }); TS_ASSERT_EQUALS(cmpResourceSupply.GetCurrentAmount(), 700); -TS_ASSERT(cmpResourceSupply.IsAvailable(1, 70)); +TS_ASSERT(cmpResourceSupply.IsAvailableTo(70)); TS_ASSERT_UNEVAL_EQUALS(cmpResourceSupply.TakeResources(800), { "amount": 700, "exhausted": true }); TS_ASSERT_EQUALS(cmpResourceSupply.GetCurrentAmount(), 0); // The resource is not available when exhausted -TS_ASSERT(!cmpResourceSupply.IsAvailable(1, 70)); +TS_ASSERT(!cmpResourceSupply.IsAvailableTo(70));