From a89cbc2c82937ba00a7f0e05b151399d87102146 Mon Sep 17 00:00:00 2001 From: JoshuaNavarro Date: Mon, 9 Sep 2019 13:31:55 -0700 Subject: [PATCH] Started work on energy graph searching. Hoping the performance is decent. --- .../Revitalize/Framework/Enums/Enums.cs | 3 +- .../Framework/Objects/CustomObject.cs | 99 --------- .../Framework/Objects/MultiTiledComponent.cs | 206 ++++++++++++++++++ 3 files changed, 208 insertions(+), 100 deletions(-) diff --git a/GeneralMods/Revitalize/Framework/Enums/Enums.cs b/GeneralMods/Revitalize/Framework/Enums/Enums.cs index a2bee1b0..dcc95fcb 100644 --- a/GeneralMods/Revitalize/Framework/Enums/Enums.cs +++ b/GeneralMods/Revitalize/Framework/Enums/Enums.cs @@ -30,7 +30,8 @@ namespace Revitalize.Framework None, Produces, Consumes, - Transfers + Transfers, + Storage } /// diff --git a/GeneralMods/Revitalize/Framework/Objects/CustomObject.cs b/GeneralMods/Revitalize/Framework/Objects/CustomObject.cs index b1e06ece..1937149c 100644 --- a/GeneralMods/Revitalize/Framework/Objects/CustomObject.cs +++ b/GeneralMods/Revitalize/Framework/Objects/CustomObject.cs @@ -740,104 +740,5 @@ namespace Revitalize.Framework.Objects } base.updateWhenCurrentLocation(time, environment); } - - /// - /// Gets a list of neighboring tiled objects that produce or transfer energy. This should be used for machines/objects that consume or transfer energy - /// - /// - public List GetNeighboringEnergyTransferProducers() - { - Vector2 tileLocation = this.TileLocation; - List customObjects = new List(); - if (this.location != null) - { - for(int i = -1; i <= 1; i++) - { - for(int j = -1; j <= 1; j++) - { - if (i == j || i== (-j)) continue; - - Vector2 neighborTile = tileLocation + new Vector2(i, j); - if (this.location.isObjectAtTile((int)neighborTile.X, (int)neighborTile.Y)) - { - StardewValley.Object obj=this.location.getObjectAtTile((int)neighborTile.X, (int)neighborTile.Y); - if (obj is CustomObject) - { - if((obj as CustomObject).EnergyManager.energyInteractionType== Enums.EnergyInteractionType.Produces || (obj as CustomObject).EnergyManager.energyInteractionType == Enums.EnergyInteractionType.Transfers) - { - customObjects.Add((CustomObject)obj); - } - } - else continue; - } - } - } - } - - - return customObjects; - - } - - /// - /// Gets a list of neighboring tiled objects that consume or transfer energy. This should be used for machines/objects that produce or transfer energy - /// - /// - public List GetNeighboringEnergyTransferConsumers() - { - Vector2 tileLocation = this.TileLocation; - List customObjects = new List(); - if (this.location != null) - { - for (int i = -1; i <= 1; i++) - { - for (int j = -1; j <= 1; j++) - { - if (i == j || i == (-j)) continue; - - Vector2 neighborTile = tileLocation + new Vector2(i, j); - if (this.location.isObjectAtTile((int)neighborTile.X, (int)neighborTile.Y)) - { - StardewValley.Object obj = this.location.getObjectAtTile((int)neighborTile.X, (int)neighborTile.Y); - if (obj is CustomObject) - { - if ((obj as CustomObject).EnergyManager.energyInteractionType == Enums.EnergyInteractionType.Consumes || (obj as CustomObject).EnergyManager.energyInteractionType == Enums.EnergyInteractionType.Transfers) - { - customObjects.Add((CustomObject)obj); - } - } - else continue; - } - } - } - } - - - return customObjects; - } - - /// - /// Gets the appropriate energy neighbors to move energy around from/to. - /// - /// - public List getAppropriateEnergyNeighbors() - { - if (this.EnergyManager.consumesEnergy) - { - return this.GetNeighboringEnergyTransferProducers(); - } - else if(this.EnergyManager.producesEnergy) - { - return this.GetNeighboringEnergyTransferConsumers(); - } - else if (this.EnergyManager.transfersEnergy) - { - List objs = new List(); - objs.AddRange(this.GetNeighboringEnergyTransferConsumers()); - objs.AddRange(this.GetNeighboringEnergyTransferProducers()); - return objs; - } - return new List(); - } } } diff --git a/GeneralMods/Revitalize/Framework/Objects/MultiTiledComponent.cs b/GeneralMods/Revitalize/Framework/Objects/MultiTiledComponent.cs index 8caed2fe..8548401f 100644 --- a/GeneralMods/Revitalize/Framework/Objects/MultiTiledComponent.cs +++ b/GeneralMods/Revitalize/Framework/Objects/MultiTiledComponent.cs @@ -371,5 +371,211 @@ namespace Revitalize.Framework.Objects MultiplayerUtilities.RequestUpdateSync(this.guid); } } + + + + + /// + /// Gets a list of neighboring tiled objects that produce or transfer energy. This should be used for machines/objects that consume or transfer energy + /// + /// + protected virtual List GetNeighboringOutputEnergySources() + { + Vector2 tileLocation = this.TileLocation; + List customObjects = new List(); + if (this.location != null) + { + for (int i = -1; i <= 1; i++) + { + for (int j = -1; j <= 1; j++) + { + if (i == j || i == (-j)) continue; + + Vector2 neighborTile = tileLocation + new Vector2(i, j); + if (this.location.isObjectAtTile((int)neighborTile.X, (int)neighborTile.Y)) + { + StardewValley.Object obj = this.location.getObjectAtTile((int)neighborTile.X, (int)neighborTile.Y); + if (obj is MultiTiledComponent) + { + if ((obj as MultiTiledComponent).EnergyManager.energyInteractionType == Enums.EnergyInteractionType.Produces || (obj as MultiTiledComponent).EnergyManager.energyInteractionType == Enums.EnergyInteractionType.Transfers || (obj as MultiTiledComponent).EnergyManager.energyInteractionType == Enums.EnergyInteractionType.Storage) + { + customObjects.Add((MultiTiledComponent)obj); + } + } + else continue; + } + } + } + } + + + return customObjects; + + } + + /// + /// Gets a list of neighboring tiled objects that consume or transfer energy. This should be used for machines/objects that produce or transfer energy + /// + /// + protected virtual List GetNeighboringInputEnergySources() + { + Vector2 tileLocation = this.TileLocation; + List customObjects = new List(); + if (this.location != null) + { + for (int i = -1; i <= 1; i++) + { + for (int j = -1; j <= 1; j++) + { + if (i == j || i == (-j)) continue; + + Vector2 neighborTile = tileLocation + new Vector2(i, j); + if (this.location.isObjectAtTile((int)neighborTile.X, (int)neighborTile.Y)) + { + StardewValley.Object obj = this.location.getObjectAtTile((int)neighborTile.X, (int)neighborTile.Y); + if (obj is MultiTiledComponent) + { + if ((obj as MultiTiledComponent).EnergyManager.energyInteractionType == Enums.EnergyInteractionType.Consumes || (obj as MultiTiledComponent).EnergyManager.energyInteractionType == Enums.EnergyInteractionType.Transfers || (obj as MultiTiledComponent).EnergyManager.energyInteractionType == Enums.EnergyInteractionType.Storage) + { + customObjects.Add((MultiTiledComponent)obj); + } + } + else continue; + } + } + } + } + + + return customObjects; + } + + /// + /// Gets the appropriate energy neighbors to move energy around from/to. + /// + /// + protected virtual List getAppropriateEnergyNeighbors() + { + if (this.EnergyManager.consumesEnergy) + { + return this.GetNeighboringOutputEnergySources(); + } + else if (this.EnergyManager.producesEnergy) + { + return this.GetNeighboringInputEnergySources(); + } + else if (this.EnergyManager.transfersEnergy) + { + List objs = new List(); + objs.AddRange(this.GetNeighboringInputEnergySources()); + objs.AddRange(this.GetNeighboringOutputEnergySources()); + return objs; + } + return new List(); + } + + /// + /// Gets all of the energy nodes in a network that are either producers or is storage. + /// + /// + protected virtual List EnergyGraphSearchSources() + { + List energySources = new List(); + List searchedComponents = new List(); + List entitiesToSearch = new List(); + entitiesToSearch.AddRange(this.getAppropriateEnergyNeighbors()); + searchedComponents.Add(this); + while (entitiesToSearch.Count > 0) + { + MultiTiledComponent searchComponent = entitiesToSearch[0]; + entitiesToSearch.Remove(searchComponent); + if (searchedComponents.Contains(searchComponent)) + { + continue; + } + else + { + searchedComponents.Add(searchComponent); + entitiesToSearch.AddRange(searchComponent.getAppropriateEnergyNeighbors()); + + if (searchComponent.containerObject.info.EnergyManager.energyInteractionType == Enums.EnergyInteractionType.Produces || searchComponent.containerObject.info.EnergyManager.energyInteractionType == Enums.EnergyInteractionType.Storage) + { + energySources.Add(searchComponent.containerObject); + } + } + + } + return energySources; + } + + /// + /// Gets all of the energy nodes in a network that are either consumers or storage. This should ALWAYS be ran after EnergyGraphSearchSources + /// + /// + protected virtual List EnergyGraphSearchConsumers() + { + List energySources = new List(); + List searchedComponents = new List(); + List entitiesToSearch = new List(); + entitiesToSearch.AddRange(this.getAppropriateEnergyNeighbors()); + searchedComponents.Add(this); + while (entitiesToSearch.Count > 0) + { + MultiTiledComponent searchComponent = entitiesToSearch[0]; + entitiesToSearch.Remove(searchComponent); + if (searchedComponents.Contains(searchComponent)) + { + continue; + } + else + { + searchedComponents.Add(searchComponent); + entitiesToSearch.AddRange(searchComponent.getAppropriateEnergyNeighbors()); + + if (searchComponent.containerObject.info.EnergyManager.energyInteractionType == Enums.EnergyInteractionType.Consumes || searchComponent.containerObject.info.EnergyManager.energyInteractionType == Enums.EnergyInteractionType.Storage) + { + energySources.Add(searchComponent.containerObject); + } + } + + } + return energySources; + } + + /// + /// Gets all nodes in a connected energy network and tries to drain the necessary amount of energy from the network. + /// + public void drainEnergyFromNetwork() + { + //Machines that consume should ALWAYS try to drain energy from a network first. + //Then producers should always try to store energy to a network. + //Storage should never try to push or pull energy from a network as consumers will pull from storage and producers will push to storage. + //Transfer nodes are used just to connect the network. + List energySources = this.EnergyGraphSearchSources(); + + int index = 0; + + for(int i = 0; i < energySources.Count; i++) + { + this.EnergyManager.transferEnergyFromAnother(energySources[i].EnergyManager, this.EnergyManager.capacityRemaining); + if (this.EnergyManager.hasMaxEnergy) break; + } + } + + /// + /// Gets all of the nodes in a connected energy network and tries to store the necessary amount of energy from the network. + /// + public void storeEnergyToNetwork() + { + List energySources = this.EnergyGraphSearchConsumers(); + + int index = 0; + + for (int i = 0; i < energySources.Count; i++) + { + this.EnergyManager.transferEnergyToAnother(energySources[i].EnergyManager, this.EnergyManager.capacityRemaining); + if (this.EnergyManager.hasEnergy) break; + } + } } }