Index: binaries/data/mods/public/simulation/components/Capturable.js =================================================================== --- binaries/data/mods/public/simulation/components/Capturable.js +++ binaries/data/mods/public/simulation/components/Capturable.js @@ -369,4 +369,24 @@ this.CheckTimer(); }; +function CapturableMirage() {} +CapturableMirage.prototype.Init = function(cmpCapturable) +{ + this.capturePoints = clone(cmpCapturable.GetCapturePoints()); + this.maxCapturePoints = cmpCapturable.GetMaxCapturePoints(); +}; + +CapturableMirage.prototype.GetCapturePoints = function() { return this.capturePoints; }; +CapturableMirage.prototype.GetMaxCapturePoints = function() { return this.maxCapturePoints; }; +CapturableMirage.prototype.CanCapture = Capturable.prototype.CanCapture; + +Engine.RegisterGlobal("CapturableMirage", CapturableMirage); + +Capturable.prototype.Mirage = function() +{ + let mirage = new CapturableMirage(); + mirage.Init(this); + return mirage; +}; + Engine.RegisterComponentType(IID_Capturable, "Capturable", Capturable); Index: binaries/data/mods/public/simulation/components/Fogging.js =================================================================== --- binaries/data/mods/public/simulation/components/Fogging.js +++ binaries/data/mods/public/simulation/components/Fogging.js @@ -8,6 +8,19 @@ "Allows this entity to be replaced by mirage entities in the fog-of-war." + ""; +/** + * The components that we want to mirage when present. + */ +Fogging.prototype.componentsToMirage = [ + IID_Capturable, + IID_Foundation, + IID_Health, + IID_Identity, + IID_Market, + IID_Repairable, + IID_ResourceSupply +]; + Fogging.prototype.Init = function() { this.activated = false; @@ -106,33 +119,8 @@ cmpMirageVisualActor.SetActorSeed(cmpParentVisualActor.GetActorSeed()); // Store valuable information into the mirage component (especially for the GUI). - let cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity); - if (cmpIdentity) - cmpMirage.CopyIdentity(cmpIdentity); - - let cmpFoundation = Engine.QueryInterface(this.entity, IID_Foundation); - if (cmpFoundation) - cmpMirage.CopyFoundation(cmpFoundation); - - let cmpRepairable = Engine.QueryInterface(this.entity, IID_Repairable); - if (cmpRepairable && !cmpFoundation) - cmpMirage.CopyRepairable(cmpRepairable); - - let cmpHealth = Engine.QueryInterface(this.entity, IID_Health); - if (cmpHealth) - cmpMirage.CopyHealth(cmpHealth); - - let cmpCapturable = Engine.QueryInterface(this.entity, IID_Capturable); - if (cmpCapturable) - cmpMirage.CopyCapturable(cmpCapturable); - - let cmpResourceSupply = Engine.QueryInterface(this.entity, IID_ResourceSupply); - if (cmpResourceSupply) - cmpMirage.CopyResourceSupply(cmpResourceSupply); - - let cmpMarket = Engine.QueryInterface(this.entity, IID_Market); - if (cmpMarket) - cmpMirage.CopyMarket(cmpMarket); + for (let component of this.componentsToMirage) + cmpMirage.CopyComponent(component); // Notify the GUI the entity has been replaced by a mirage, in case it is selected at this moment. Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface).AddMiragedEntity(player, this.entity, this.mirages[player]); Index: binaries/data/mods/public/simulation/components/Foundation.js =================================================================== --- binaries/data/mods/public/simulation/components/Foundation.js +++ binaries/data/mods/public/simulation/components/Foundation.js @@ -531,5 +531,23 @@ } }; -Engine.RegisterComponentType(IID_Foundation, "Foundation", Foundation); +function FoundationMirage() {} +FoundationMirage.prototype.Init = function(cmpFoundation) +{ + this.numBuilders = cmpFoundation.GetNumBuilders(); + this.buildTime = cmpFoundation.GetBuildTime(); +}; + +FoundationMirage.prototype.GetNumBuilders = function() { return this.numBuilders; }; +FoundationMirage.prototype.GetBuildTime = function() { return this.buildTime; }; + +Engine.RegisterGlobal("FoundationMirage", FoundationMirage); +Foundation.prototype.Mirage = function() +{ + let mirage = new FoundationMirage(); + mirage.Init(this); + return mirage; +}; + +Engine.RegisterComponentType(IID_Foundation, "Foundation", Foundation); Index: binaries/data/mods/public/simulation/components/Health.js =================================================================== --- binaries/data/mods/public/simulation/components/Health.js +++ binaries/data/mods/public/simulation/components/Health.js @@ -483,4 +483,28 @@ Engine.PostMessage(this.entity, MT_HealthChanged, { "from": from, "to": this.hitpoints }); }; +function HealthMirage() {} +HealthMirage.prototype.Init = function(cmpHealth) +{ + this.maxHitpoints = cmpHealth.GetMaxHitpoints(); + this.hitpoints = cmpHealth.GetHitpoints(); + this.repairable = cmpHealth.IsRepairable(); + this.injured = cmpHealth.IsInjured(); + this.unhealable = cmpHealth.IsUnhealable(); +}; +HealthMirage.prototype.GetMaxHitpoints = function() { return this.maxHitpoints; }; +HealthMirage.prototype.GetHitpoints = function() { return this.hitpoints; }; +HealthMirage.prototype.IsRepairable = function() { return this.repairable; }; +HealthMirage.prototype.IsInjured = function() { return this.injured; }; +HealthMirage.prototype.IsUnhealable = function() { return this.unhealable; }; + +Engine.RegisterGlobal("HealthMirage", HealthMirage); + +Health.prototype.Mirage = function() +{ + let mirage = new HealthMirage(); + mirage.Init(this); + return mirage; +}; + Engine.RegisterComponentType(IID_Health, "Health", Health); Index: binaries/data/mods/public/simulation/components/Identity.js =================================================================== --- binaries/data/mods/public/simulation/components/Identity.js +++ binaries/data/mods/public/simulation/components/Identity.js @@ -201,4 +201,24 @@ this.controllable = controllability; }; +function IdentityMirage() {} +IdentityMirage.prototype.Init = function(cmpIdentity) +{ + // Mirages don't get identity classes via the template-filter, so that code can query + // identity components via Engine.QueryInterface without having to explicitly check for mirages. + // This is cloned as otherwise we get a reference to Identity's property, + // and that array is deleted when serializing (as it's not seralized), which ends in OOS. + this.classes = clone(cmpIdentity.GetClassesList()); +}; +IdentityMirage.prototype.GetClassesList = function() { return this.classes; }; + +Engine.RegisterGlobal("IdentityMirage", IdentityMirage); + +Identity.prototype.Mirage = function() +{ + let mirage = new IdentityMirage(); + mirage.Init(this); + return mirage; +}; + Engine.RegisterComponentType(IID_Identity, "Identity", Identity); Index: binaries/data/mods/public/simulation/components/Market.js =================================================================== --- binaries/data/mods/public/simulation/components/Market.js +++ binaries/data/mods/public/simulation/components/Market.js @@ -84,4 +84,71 @@ this.UpdateTraders(msg.to == INVALID_PLAYER); }; +function MarketMirage() {} +MarketMirage.prototype.Init = function(cmpMarket, entity, parent, player) +{ + this.entity = entity; + this.parent = parent; + this.player = player; + + this.traders = new Set(); + for (let trader of cmpMarket.GetTraders()) + { + let cmpTrader = Engine.QueryInterface(trader, IID_Trader); + let cmpOwnership = Engine.QueryInterface(trader, IID_Ownership); + if (!cmpTrader || !cmpOwnership) + { + cmpMarket.RemoveTrader(trader); + continue; + } + if (this.player != cmpOwnership.GetOwner()) + continue; + cmpTrader.SwitchMarket(cmpMarket.entity, this.entity); + cmpMarket.RemoveTrader(trader); + this.AddTrader(trader); + } + this.marketType = cmpMarket.GetType(); + this.internationalBonus = cmpMarket.GetInternationalBonus(); +}; + +MarketMirage.prototype.HasType = function(type) { return this.marketType.has(type); }; +MarketMirage.prototype.GetInternationalBonus = function() { return this.internationalBonus; }; +MarketMirage.prototype.AddTrader = function(trader) { this.traders.add(trader); }; +MarketMirage.prototype.RemoveTrader = function(trader) { this.traders.delete(trader); }; + +MarketMirage.prototype.UpdateTraders = function(msg) +{ + let cmpMarket = Engine.QueryInterface(this.parent, IID_Market); + if (!cmpMarket) // The parent market does not exist anymore + { + for (let trader of this.traders) + { + let cmpTrader = Engine.QueryInterface(trader, IID_Trader); + if (cmpTrader) + cmpTrader.RemoveMarket(this.entity); + } + return; + } + + // The market becomes visible, switch all traders from the mirage to the market + for (let trader of this.traders) + { + let cmpTrader = Engine.QueryInterface(trader, IID_Trader); + if (!cmpTrader) + continue; + cmpTrader.SwitchMarket(this.entity, cmpMarket.entity); + this.RemoveTrader(trader); + cmpMarket.AddTrader(trader); + } +}; + +Engine.RegisterGlobal("MarketMirage", MarketMirage); + +Market.prototype.Mirage = function(mirageID, miragePlayer) +{ + let mirage = new MarketMirage(); + mirage.Init(this, mirageID, this.entity, miragePlayer); + return mirage; +}; + Engine.RegisterComponentType(IID_Market, "Market", Market); Index: binaries/data/mods/public/simulation/components/Mirage.js =================================================================== --- binaries/data/mods/public/simulation/components/Mirage.js +++ binaries/data/mods/public/simulation/components/Mirage.js @@ -49,212 +49,14 @@ // ============================ // Parent entity data -function MiragedIdentity() {} -MiragedIdentity.prototype.Init = function(cmpIdentity) -{ - // Mirages don't get identity classes via the template-filter, so that code can query - // identity components via Engine.QueryInterface without having to explicitly check for mirages. - // This is cloned as otherwise we get a reference to Identity's property, - // and that array is deleted when serializing (as it's not seralized), which ends in OOS. - this.classes = clone(cmpIdentity.GetClassesList()); -}; - -MiragedIdentity.prototype.GetClassesList = function() { return this.classes; }; -Engine.RegisterGlobal("MiragedIdentity", MiragedIdentity); - -Mirage.prototype.CopyIdentity = function(cmpIdentity) -{ - let mirage = new MiragedIdentity(); - mirage.Init(cmpIdentity); - this.miragedIids.set(IID_Identity, mirage); -}; - -// Foundation data - -function MiragedFoundation() {} -MiragedFoundation.prototype.Init = function(cmpFoundation) -{ - this.numBuilders = cmpFoundation.GetNumBuilders(); - this.buildTime = cmpFoundation.GetBuildTime(); -}; - -MiragedFoundation.prototype.GetNumBuilders = function() { return this.numBuilders; }; -MiragedFoundation.prototype.GetBuildTime = function() { return this.buildTime; }; -Engine.RegisterGlobal("MiragedFoundation", MiragedFoundation); - -Mirage.prototype.CopyFoundation = function(cmpFoundation) -{ - let mirage = new MiragedFoundation(); - mirage.Init(cmpFoundation); - this.miragedIids.set(IID_Foundation, mirage); -}; - -// Repairable data - -function MiragedRepairable() {} -MiragedRepairable.prototype.Init = function(cmpRepairable) -{ - this.numBuilders = cmpRepairable.GetNumBuilders(); - this.buildTime = cmpRepairable.GetBuildTime(); -}; - -MiragedRepairable.prototype.GetNumBuilders = function() { return this.numBuilders; }; -MiragedRepairable.prototype.GetBuildTime = function() { return this.buildTime; }; -Engine.RegisterGlobal("MiragedRepairable", MiragedRepairable); - -Mirage.prototype.CopyRepairable = function(cmpRepairable) -{ - let mirage = new MiragedRepairable(); - mirage.Init(cmpRepairable); - this.miragedIids.set(IID_Repairable, mirage); -}; - -// Health data - -function MiragedHealth() {} -MiragedHealth.prototype.Init = function(cmpHealth) -{ - this.maxHitpoints = cmpHealth.GetMaxHitpoints(); - this.hitpoints = cmpHealth.GetHitpoints(); - this.repairable = cmpHealth.IsRepairable(); - this.injured = cmpHealth.IsInjured(); - this.unhealable = cmpHealth.IsUnhealable(); -}; - -MiragedHealth.prototype.GetMaxHitpoints = function() { return this.maxHitpoints; }; -MiragedHealth.prototype.GetHitpoints = function() { return this.hitpoints; }; -MiragedHealth.prototype.IsRepairable = function() { return this.repairable; }; -MiragedHealth.prototype.IsInjured = function() { return this.injured; }; -MiragedHealth.prototype.IsUnhealable = function() { return this.unhealable; }; -Engine.RegisterGlobal("MiragedHealth", MiragedHealth); - -Mirage.prototype.CopyHealth = function(cmpHealth) -{ - let mirage = new MiragedHealth(); - mirage.Init(cmpHealth); - this.miragedIids.set(IID_Health, mirage); -}; - -// Capture data - -function MiragedCapturable() {} -MiragedCapturable.prototype.Init = function(cmpCapturable) -{ - this.capturePoints = clone(cmpCapturable.GetCapturePoints()); - this.maxCapturePoints = cmpCapturable.GetMaxCapturePoints(); -}; - -MiragedCapturable.prototype.GetCapturePoints = function() { return this.capturePoints; }; -MiragedCapturable.prototype.GetMaxCapturePoints = function() { return this.maxCapturePoints; }; -MiragedCapturable.prototype.CanCapture = Capturable.prototype.CanCapture; -Engine.RegisterGlobal("MiragedCapturable", MiragedCapturable); - -Mirage.prototype.CopyCapturable = function(cmpCapturable) -{ - let mirage = new MiragedCapturable(); - mirage.Init(cmpCapturable); - this.miragedIids.set(IID_Capturable, mirage); -}; - -// ResourceSupply data -function MiragedResourceSupply() {} -MiragedResourceSupply.prototype.Init = function(cmpResourceSupply) -{ - this.maxAmount = cmpResourceSupply.GetMaxAmount(); - this.amount = cmpResourceSupply.GetCurrentAmount(); - this.type = cmpResourceSupply.GetType(); - this.isInfinite = cmpResourceSupply.IsInfinite(); - this.killBeforeGather = cmpResourceSupply.GetKillBeforeGather(); - this.maxGatherers = cmpResourceSupply.GetMaxGatherers(); - this.numGatherers = cmpResourceSupply.GetNumGatherers(); -}; - -MiragedResourceSupply.prototype.GetMaxAmount = function() { return this.maxAmount; }; -MiragedResourceSupply.prototype.GetCurrentAmount = function() { return this.amount; }; -MiragedResourceSupply.prototype.GetType = function() { return this.type; }; -MiragedResourceSupply.prototype.IsInfinite = function() { return this.isInfinite; }; -MiragedResourceSupply.prototype.GetKillBeforeGather = function() { return this.killBeforeGather; }; -MiragedResourceSupply.prototype.GetMaxGatherers = function() { return this.maxGatherers; }; -MiragedResourceSupply.prototype.GetNumGatherers = function() { return this.numGatherers; }; - -// Apply diminishing returns with more gatherers, for e.g. infinite farms. For most resources this has no effect -// (GetDiminishingReturns will return null). We can assume that for resources that are miraged this is the case. -MiragedResourceSupply.prototype.GetDiminishingReturns = function() { return null; }; - -Engine.RegisterGlobal("MiragedResourceSupply", MiragedResourceSupply); - -Mirage.prototype.CopyResourceSupply = function(cmpResourceSupply) -{ - let mirage = new MiragedResourceSupply(); - mirage.Init(cmpResourceSupply); - this.miragedIids.set(IID_ResourceSupply, mirage); -}; - -// Market data -function MiragedMarket() {} -MiragedMarket.prototype.Init = function(cmpMarket, entity, parent, player) -{ - this.entity = entity; - this.parent = parent; - this.player = player; - - this.traders = new Set(); - for (let trader of cmpMarket.GetTraders()) - { - let cmpTrader = Engine.QueryInterface(trader, IID_Trader); - let cmpOwnership = Engine.QueryInterface(trader, IID_Ownership); - if (!cmpTrader || !cmpOwnership) - { - cmpMarket.RemoveTrader(trader); - continue; - } - if (this.player != cmpOwnership.GetOwner()) - continue; - cmpTrader.SwitchMarket(cmpMarket.entity, this.entity); - cmpMarket.RemoveTrader(trader); - this.AddTrader(trader); - } - this.marketType = cmpMarket.GetType(); - this.internationalBonus = cmpMarket.GetInternationalBonus(); -}; - -MiragedMarket.prototype.HasType = function(type) { return this.marketType.has(type); }; -MiragedMarket.prototype.GetInternationalBonus = function() { return this.internationalBonus; }; -MiragedMarket.prototype.AddTrader = function(trader) { this.traders.add(trader); }; -MiragedMarket.prototype.RemoveTrader = function(trader) { this.traders.delete(trader); }; - -MiragedMarket.prototype.UpdateTraders = function(msg) -{ - let cmpMarket = Engine.QueryInterface(this.parent, IID_Market); - if (!cmpMarket) // The parent market does not exist anymore - { - for (let trader of this.traders) - { - let cmpTrader = Engine.QueryInterface(trader, IID_Trader); - if (cmpTrader) - cmpTrader.RemoveMarket(this.entity); - } - return; - } - - // The market becomes visible, switch all traders from the mirage to the market - for (let trader of this.traders) - { - let cmpTrader = Engine.QueryInterface(trader, IID_Trader); - if (!cmpTrader) - continue; - cmpTrader.SwitchMarket(this.entity, cmpMarket.entity); - this.RemoveTrader(trader); - cmpMarket.AddTrader(trader); - } -}; -Engine.RegisterGlobal("MiragedMarket", MiragedMarket); - -Mirage.prototype.CopyMarket = function(cmpMarket) -{ - let mirage = new MiragedMarket(); - mirage.Init(cmpMarket, this.entity, this.parent, this.player); - this.miragedIids.set(IID_Market, mirage); +/** + * @param {number} iid - The component to mirage. + */ +Mirage.prototype.CopyComponent = function(iid) +{ + let cmp = Engine.QueryInterface(this.parent, iid); + if (cmp) + this.miragedIids.set(iid, cmp.Mirage(this.entity, this.player)); }; // ============================ Index: binaries/data/mods/public/simulation/components/Repairable.js =================================================================== --- binaries/data/mods/public/simulation/components/Repairable.js +++ binaries/data/mods/public/simulation/components/Repairable.js @@ -151,4 +151,23 @@ return repairTime ? cmpHealth.GetMaxHitpoints() / repairTime : 1; }; +function RepairableMirage() {} +RepairableMirage.prototype.Init = function(cmpRepairable) +{ + this.numBuilders = cmpRepairable.GetNumBuilders(); + this.buildTime = cmpRepairable.GetBuildTime(); +}; + +RepairableMirage.prototype.GetNumBuilders = function() { return this.numBuilders; }; +RepairableMirage.prototype.GetBuildTime = function() { return this.buildTime; }; + +Engine.RegisterGlobal("RepairableMirage", RepairableMirage); + +Repairable.prototype.Mirage = function() +{ + let mirage = new RepairableMirage(); + mirage.Init(this); + return mirage; +}; + Engine.RegisterComponentType(IID_Repairable, "Repairable", Repairable); 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 @@ -468,4 +468,37 @@ cmpResourceSupplyNew.SetAmount(this.GetCurrentAmount()); }; +function ResourceSupplyMirage() {} +ResourceSupplyMirage.prototype.Init = function(cmpResourceSupply) +{ + this.maxAmount = cmpResourceSupply.GetMaxAmount(); + this.amount = cmpResourceSupply.GetCurrentAmount(); + this.type = cmpResourceSupply.GetType(); + this.isInfinite = cmpResourceSupply.IsInfinite(); + this.killBeforeGather = cmpResourceSupply.GetKillBeforeGather(); + this.maxGatherers = cmpResourceSupply.GetMaxGatherers(); + this.numGatherers = cmpResourceSupply.GetNumGatherers(); +}; + +ResourceSupplyMirage.prototype.GetMaxAmount = function() { return this.maxAmount; }; +ResourceSupplyMirage.prototype.GetCurrentAmount = function() { return this.amount; }; +ResourceSupplyMirage.prototype.GetType = function() { return this.type; }; +ResourceSupplyMirage.prototype.IsInfinite = function() { return this.isInfinite; }; +ResourceSupplyMirage.prototype.GetKillBeforeGather = function() { return this.killBeforeGather; }; +ResourceSupplyMirage.prototype.GetMaxGatherers = function() { return this.maxGatherers; }; +ResourceSupplyMirage.prototype.GetNumGatherers = function() { return this.numGatherers; }; + +// Apply diminishing returns with more gatherers, for e.g. infinite farms. For most resources this has no effect +// (GetDiminishingReturns will return null). We can assume that for resources that are miraged this is the case. +ResourceSupplyMirage.prototype.GetDiminishingReturns = function() { return null; }; + +Engine.RegisterGlobal("ResourceSupplyMirage", ResourceSupplyMirage); + +ResourceSupply.prototype.Mirage = function() +{ + let mirage = new ResourceSupplyMirage(); + mirage.Init(this); + return mirage; +}; + Engine.RegisterComponentType(IID_ResourceSupply, "ResourceSupply", ResourceSupply);