diff --git a/OpenRA.Mods.Cnc/Traits/ResourcePurifier.cs b/OpenRA.Mods.Cnc/Traits/ResourcePurifier.cs index d69f8f1be0..da9d8e30d6 100644 --- a/OpenRA.Mods.Cnc/Traits/ResourcePurifier.cs +++ b/OpenRA.Mods.Cnc/Traits/ResourcePurifier.cs @@ -56,7 +56,7 @@ namespace OpenRA.Mods.Cnc.Traits base.Created(self); } - void INotifyResourceAccepted.OnResourceAccepted(Actor self, Actor refinery, ResourceTypeInfo resourceType, int count, int value) + void INotifyResourceAccepted.OnResourceAccepted(Actor self, Actor refinery, string resourceType, int count, int value) { if (IsTraitDisabled) return; diff --git a/OpenRA.Mods.Cnc/Traits/TransformsNearResources.cs b/OpenRA.Mods.Cnc/Traits/TransformsNearResources.cs index 3ff95aa8c6..5d4e9ec1ff 100644 --- a/OpenRA.Mods.Cnc/Traits/TransformsNearResources.cs +++ b/OpenRA.Mods.Cnc/Traits/TransformsNearResources.cs @@ -67,7 +67,7 @@ namespace OpenRA.Mods.Cnc.Traits var location = self.Location + direction; var resource = resourceLayer.GetResource(location); - if (resource.Type == null || resource.Type.Info.Type != info.Type) + if (resource.Type == null || resource.Type != info.Type) continue; if (resource.Density < info.Density) diff --git a/OpenRA.Mods.Common/EditorBrushes/EditorDefaultBrush.cs b/OpenRA.Mods.Common/EditorBrushes/EditorDefaultBrush.cs index 8c282d2659..00d9b80601 100644 --- a/OpenRA.Mods.Common/EditorBrushes/EditorDefaultBrush.cs +++ b/OpenRA.Mods.Common/EditorBrushes/EditorDefaultBrush.cs @@ -78,7 +78,7 @@ namespace OpenRA.Mods.Common.Widgets if (underCursor != null) editorWidget.SetTooltip(underCursor.Tooltip); else if (resourceUnderCursor != null) - editorWidget.SetTooltip(resourceUnderCursor.Info.Type); + editorWidget.SetTooltip(resourceUnderCursor); else editorWidget.SetTooltip(null); @@ -150,12 +150,12 @@ namespace OpenRA.Mods.Common.Widgets ResourceLayerContents resourceContents; - public RemoveResourceAction(IResourceLayer resourceLayer, CPos cell, ResourceType type) + public RemoveResourceAction(IResourceLayer resourceLayer, CPos cell, string resourceType) { this.resourceLayer = resourceLayer; this.cell = cell; - Text = "Removed {0}".F(type.Info.TerrainType); + Text = "Removed {0}".F(resourceType); } public void Execute() diff --git a/OpenRA.Mods.Common/EditorBrushes/EditorResourceBrush.cs b/OpenRA.Mods.Common/EditorBrushes/EditorResourceBrush.cs index a3a394ff5f..7b48608b9e 100644 --- a/OpenRA.Mods.Common/EditorBrushes/EditorResourceBrush.cs +++ b/OpenRA.Mods.Common/EditorBrushes/EditorResourceBrush.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Widgets { public sealed class EditorResourceBrush : IEditorBrush { - public readonly ResourceType ResourceType; + public readonly string ResourceType; readonly WorldRenderer worldRenderer; readonly World world; @@ -30,18 +30,18 @@ namespace OpenRA.Mods.Common.Widgets AddResourcesEditorAction action; bool resourceAdded; - public EditorResourceBrush(EditorViewportControllerWidget editorWidget, ResourceType resource, WorldRenderer wr) + public EditorResourceBrush(EditorViewportControllerWidget editorWidget, string resourceType, WorldRenderer wr) { this.editorWidget = editorWidget; - ResourceType = resource; + ResourceType = resourceType; worldRenderer = wr; world = wr.World; editorActionManager = world.WorldActor.Trait(); editorCursor = world.WorldActor.Trait(); resourceLayer = world.WorldActor.Trait(); - action = new AddResourcesEditorAction(world.Map, resourceLayer, resource); + action = new AddResourcesEditorAction(world.Map, resourceType, resourceLayer); - cursorToken = editorCursor.SetResource(wr, resource); + cursorToken = editorCursor.SetResource(wr, resourceType); } public bool HandleMouseInput(MouseInput mi) @@ -74,7 +74,7 @@ namespace OpenRA.Mods.Common.Widgets else if (resourceAdded && mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Up) { editorActionManager.Add(action); - action = new AddResourcesEditorAction(world.Map, resourceLayer, ResourceType); + action = new AddResourcesEditorAction(world.Map, ResourceType, resourceLayer); resourceAdded = false; } @@ -93,9 +93,9 @@ namespace OpenRA.Mods.Common.Widgets { public readonly CPos Cell; public readonly ResourceLayerContents OldResourceTile; - public readonly ResourceType NewResourceType; + public readonly string NewResourceType; - public CellResource(CPos cell, ResourceLayerContents oldResourceTile, ResourceType newResourceType) + public CellResource(CPos cell, ResourceLayerContents oldResourceTile, string newResourceType) { Cell = cell; OldResourceTile = oldResourceTile; @@ -109,14 +109,14 @@ namespace OpenRA.Mods.Common.Widgets readonly Map map; readonly IResourceLayer resourceLayer; - readonly ResourceType resourceType; + readonly string resourceType; readonly List cellResources = new List(); - public AddResourcesEditorAction(Map map, IResourceLayer resourceLayer, ResourceType resourceType) + public AddResourcesEditorAction(Map map, string resourceType, IResourceLayer resourceLayer) { this.map = map; - this.resourceLayer = resourceLayer; this.resourceType = resourceType; + this.resourceLayer = resourceLayer; } public void Execute() @@ -128,7 +128,7 @@ namespace OpenRA.Mods.Common.Widgets foreach (var resourceCell in cellResources) { resourceLayer.ClearResources(resourceCell.Cell); - resourceLayer.AddResource(resourceCell.NewResourceType, resourceCell.Cell, resourceCell.NewResourceType.Info.MaxDensity); + resourceLayer.AddResource(resourceCell.NewResourceType, resourceCell.Cell, resourceLayer.GetMaxDensity(resourceCell.NewResourceType)); } } @@ -145,11 +145,11 @@ namespace OpenRA.Mods.Common.Widgets public void Add(CellResource resourceCell) { resourceLayer.ClearResources(resourceCell.Cell); - resourceLayer.AddResource(resourceCell.NewResourceType, resourceCell.Cell, resourceCell.NewResourceType.Info.MaxDensity); + resourceLayer.AddResource(resourceCell.NewResourceType, resourceCell.Cell, resourceLayer.GetMaxDensity(resourceCell.NewResourceType)); cellResources.Add(resourceCell); var cellText = cellResources.Count != 1 ? "cells" : "cell"; - Text = "Added {0} {1} of {2}".F(cellResources.Count, cellText, resourceType.Info.TerrainType); + Text = "Added {0} {1} of {2}".F(cellResources.Count, cellText, resourceType); } } } diff --git a/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs b/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs index 8a63d4eea2..39026a9a60 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs @@ -57,6 +57,7 @@ namespace OpenRA.Mods.Common.Traits { readonly Actor self; readonly RefineryInfo info; + readonly Dictionary resourceValues; PlayerResources playerResources; IEnumerable resourceValueModifiers; @@ -82,6 +83,8 @@ namespace OpenRA.Mods.Common.Traits this.info = info; playerResources = self.Owner.PlayerActor.Trait(); currentDisplayTick = info.TickRate; + resourceValues = self.World.WorldActor.TraitsImplementing() + .ToDictionary(r => r.Info.Type, r => r.Info.ValuePerUnit); } void INotifyCreated.Created(Actor self) @@ -100,9 +103,12 @@ namespace OpenRA.Mods.Common.Traits .Where(a => a.Trait.LinkedProc == self); } - int IAcceptResources.AcceptResources(ResourceTypeInfo resourceType, int count) + int IAcceptResources.AcceptResources(string resourceType, int count) { - var value = Util.ApplyPercentageModifiers(count * resourceType.ValuePerUnit, resourceValueModifiers); + if (!resourceValues.TryGetValue(resourceType, out var resourceValue)) + return 0; + + var value = Util.ApplyPercentageModifiers(count * resourceValue, resourceValueModifiers); if (info.UseStorage) { @@ -111,7 +117,7 @@ namespace OpenRA.Mods.Common.Traits { // Reduce amount if needed until it will fit the available storage while (value > storageLimit) - value = Util.ApplyPercentageModifiers(--count * resourceType.ValuePerUnit, resourceValueModifiers); + value = Util.ApplyPercentageModifiers(--count * resourceValue, resourceValueModifiers); } else value = Math.Min(value, playerResources.ResourceCapacity - playerResources.Resources); diff --git a/OpenRA.Mods.Common/Traits/CarryableHarvester.cs b/OpenRA.Mods.Common/Traits/CarryableHarvester.cs index 0fa1880f7a..a1d60a54aa 100644 --- a/OpenRA.Mods.Common/Traits/CarryableHarvester.cs +++ b/OpenRA.Mods.Common/Traits/CarryableHarvester.cs @@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.Traits t.MovementCancelled(self); } - void INotifyHarvesterAction.Harvested(Actor self, ResourceType resource) { } + void INotifyHarvesterAction.Harvested(Actor self, string resourceType) { } void INotifyHarvesterAction.Docked() { } void INotifyHarvesterAction.Undocked() { } } diff --git a/OpenRA.Mods.Common/Traits/Cloak.cs b/OpenRA.Mods.Common/Traits/Cloak.cs index 310dec35bd..4dad57431e 100644 --- a/OpenRA.Mods.Common/Traits/Cloak.cs +++ b/OpenRA.Mods.Common/Traits/Cloak.cs @@ -214,7 +214,7 @@ namespace OpenRA.Mods.Common.Traits void INotifyHarvesterAction.MovementCancelled(Actor self) { } - void INotifyHarvesterAction.Harvested(Actor self, ResourceType resource) { } + void INotifyHarvesterAction.Harvested(Actor self, string resourceType) { } void INotifyHarvesterAction.Docked() { diff --git a/OpenRA.Mods.Common/Traits/Harvester.cs b/OpenRA.Mods.Common/Traits/Harvester.cs index 508c550458..e6134a53bb 100644 --- a/OpenRA.Mods.Common/Traits/Harvester.cs +++ b/OpenRA.Mods.Common/Traits/Harvester.cs @@ -103,12 +103,12 @@ namespace OpenRA.Mods.Common.Traits ISpeedModifier, ISync, INotifyCreated { public readonly HarvesterInfo Info; - public readonly IReadOnlyDictionary Contents; + public readonly IReadOnlyDictionary Contents; readonly Mobile mobile; readonly IResourceLayer resourceLayer; readonly ResourceClaimLayer claimLayer; - readonly Dictionary contents = new Dictionary(); + readonly Dictionary contents = new Dictionary(); int conditionToken = Actor.InvalidConditionToken; [Sync] @@ -121,13 +121,13 @@ namespace OpenRA.Mods.Common.Traits int currentUnloadTicks; [Sync] - public int ContentValue + public int ContentHash { get { var value = 0; foreach (var c in contents) - value += c.Key.ValuePerUnit * c.Value; + value += c.Value << c.Key.Length; return value; } } @@ -135,8 +135,7 @@ namespace OpenRA.Mods.Common.Traits public Harvester(Actor self, HarvesterInfo info) { Info = info; - Contents = new ReadOnlyDictionary(contents); - + Contents = new ReadOnlyDictionary(contents); mobile = self.Trait(); resourceLayer = self.World.WorldActor.Trait(); claimLayer = self.World.WorldActor.Trait(); @@ -229,12 +228,12 @@ namespace OpenRA.Mods.Common.Traits conditionToken = self.RevokeCondition(conditionToken); } - public void AcceptResource(Actor self, ResourceType type) + public void AcceptResource(Actor self, string resourceType) { - if (!contents.ContainsKey(type.Info)) - contents[type.Info] = 1; + if (!contents.ContainsKey(resourceType)) + contents[resourceType] = 1; else - contents[type.Info]++; + contents[resourceType]++; UpdateCondition(self); } @@ -281,7 +280,7 @@ namespace OpenRA.Mods.Common.Traits return false; // Can the harvester collect this kind of resource? - return Info.Resources.Contains(resourceType.Info.Type); + return Info.Resources.Contains(resourceType); } IEnumerable IIssueOrder.Orders @@ -388,7 +387,7 @@ namespace OpenRA.Mods.Common.Traits var info = self.Info.TraitInfo(); var res = self.World.WorldActor.TraitsImplementing() .Select(r => r.GetRenderedResourceType(location)) - .FirstOrDefault(r => r != null && info.Resources.Contains(r.Info.Type)); + .FirstOrDefault(r => r != null && info.Resources.Contains(r)); if (res == null) return false; diff --git a/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs index c37a52aeb6..8fd40d5f88 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs @@ -37,7 +37,7 @@ namespace OpenRA.Mods.Common.Traits.Render wsb = init.Self.TraitsImplementing().Single(w => w.Info.Name == Info.Body); } - void INotifyHarvesterAction.Harvested(Actor self, ResourceType resource) + void INotifyHarvesterAction.Harvested(Actor self, string resourceType) { var sequence = wsb.NormalizeSequence(self, Info.HarvestSequence); if (wsb.DefaultAnimation.HasSequence(sequence) && wsb.DefaultAnimation.CurrentSequence.Name != sequence) diff --git a/OpenRA.Mods.Common/Traits/Render/WithHarvestOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithHarvestOverlay.cs index eedacb2deb..3d5b0f8148 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithHarvestOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithHarvestOverlay.cs @@ -51,7 +51,7 @@ namespace OpenRA.Mods.Common.Traits.Render p => ZOffsetFromCenter(self, p, 0)), info.Palette); } - void INotifyHarvesterAction.Harvested(Actor self, ResourceType resource) + void INotifyHarvesterAction.Harvested(Actor self, string resourceType) { if (visible) return; diff --git a/OpenRA.Mods.Common/Traits/Render/WithHarvesterPipsDecoration.cs b/OpenRA.Mods.Common/Traits/Render/WithHarvesterPipsDecoration.cs index 8e4d1d7c20..315b902836 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithHarvesterPipsDecoration.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithHarvesterPipsDecoration.cs @@ -65,7 +65,7 @@ namespace OpenRA.Mods.Common.Traits.Render { if (n < rt.Value) { - if (!Info.ResourceSequences.TryGetValue(rt.Key.Type, out var sequence)) + if (!Info.ResourceSequences.TryGetValue(rt.Key, out var sequence)) sequence = Info.FullSequence; return sequence; diff --git a/OpenRA.Mods.Common/Traits/SeedsResource.cs b/OpenRA.Mods.Common/Traits/SeedsResource.cs index 42bbd786b4..920ededc64 100644 --- a/OpenRA.Mods.Common/Traits/SeedsResource.cs +++ b/OpenRA.Mods.Common/Traits/SeedsResource.cs @@ -28,21 +28,12 @@ namespace OpenRA.Mods.Common.Traits class SeedsResource : ConditionalTrait, ITick, ISeedableResource { readonly SeedsResourceInfo info; - - readonly ResourceType resourceType; readonly IResourceLayer resourceLayer; public SeedsResource(Actor self, SeedsResourceInfo info) : base(info) { this.info = info; - - resourceType = self.World.WorldActor.TraitsImplementing() - .FirstOrDefault(t => t.Info.Type == info.ResourceType); - - if (resourceType == null) - throw new InvalidOperationException("No such resource type `{0}`".F(info.ResourceType)); - resourceLayer = self.World.WorldActor.Trait(); } @@ -64,11 +55,11 @@ namespace OpenRA.Mods.Common.Traits { var cell = Util.RandomWalk(self.Location, self.World.SharedRandom) .Take(info.MaxRange) - .SkipWhile(p => resourceLayer.GetResource(p).Type == resourceType && !resourceLayer.CanAddResource(resourceType, p)) + .SkipWhile(p => resourceLayer.GetResource(p).Type == info.ResourceType && !resourceLayer.CanAddResource(info.ResourceType, p)) .Cast().FirstOrDefault(); - if (cell != null && resourceLayer.CanAddResource(resourceType, cell.Value)) - resourceLayer.AddResource(resourceType, cell.Value); + if (cell != null && resourceLayer.CanAddResource(info.ResourceType, cell.Value)) + resourceLayer.AddResource(info.ResourceType, cell.Value); } } } diff --git a/OpenRA.Mods.Common/Traits/World/EditorCursorLayer.cs b/OpenRA.Mods.Common/Traits/World/EditorCursorLayer.cs index d585102c85..7b7f36579d 100644 --- a/OpenRA.Mods.Common/Traits/World/EditorCursorLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/EditorCursorLayer.cs @@ -44,7 +44,7 @@ namespace OpenRA.Mods.Common.Traits bool actorSharesCell; public TerrainTemplateInfo TerrainTemplate { get; private set; } - public ResourceType Resource { get; private set; } + public string ResourceType { get; private set; } CPos terrainOrResourceCell; bool terrainOrResourceDirty; readonly List terrainOrResourcePreview = new List(); @@ -82,7 +82,7 @@ namespace OpenRA.Mods.Common.Traits if (Type == EditorCursorType.TerrainTemplate) terrainOrResourcePreview.AddRange(terrainRenderer.RenderPreview(wr, TerrainTemplate, pos)); else - terrainOrResourcePreview.AddRange(resourceRenderers.SelectMany(r => r.RenderPreview(wr, Resource, pos))); + terrainOrResourcePreview.AddRange(resourceRenderers.SelectMany(r => r.RenderPreview(wr, ResourceType, pos))); } } else if (Type == EditorCursorType.Actor) @@ -181,7 +181,7 @@ namespace OpenRA.Mods.Common.Traits Type = EditorCursorType.Actor; Actor = new EditorActorPreview(wr, null, reference, owner); TerrainTemplate = null; - Resource = null; + ResourceType = null; return ++CurrentToken; } @@ -193,18 +193,18 @@ namespace OpenRA.Mods.Common.Traits Type = EditorCursorType.TerrainTemplate; TerrainTemplate = template; Actor = null; - Resource = null; + ResourceType = null; terrainOrResourceDirty = true; return ++CurrentToken; } - public int SetResource(WorldRenderer wr, ResourceType resource) + public int SetResource(WorldRenderer wr, string resourceType) { terrainOrResourceCell = wr.Viewport.ViewToWorld(wr.Viewport.WorldToViewPx(Viewport.LastMousePos)); Type = EditorCursorType.Resource; - Resource = resource; + ResourceType = resourceType; Actor = null; TerrainTemplate = null; terrainOrResourceDirty = true; @@ -220,7 +220,7 @@ namespace OpenRA.Mods.Common.Traits Type = EditorCursorType.None; Actor = null; TerrainTemplate = null; - Resource = null; + ResourceType = null; } } } diff --git a/OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs b/OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs index 4c3dc3732c..9887a4fcaf 100644 --- a/OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs @@ -26,19 +26,28 @@ namespace OpenRA.Mods.Common.Traits public class EditorResourceLayer : IResourceLayer, IWorldLoaded, INotifyActorDisposing { protected readonly Map Map; - protected readonly Dictionary Resources; + protected readonly Dictionary ResourceInfo; + protected readonly Dictionary Resources; protected readonly CellLayer Tiles; public int NetWorth { get; protected set; } bool disposed; - public event Action CellChanged; + public event Action CellChanged; ResourceLayerContents IResourceLayer.GetResource(CPos cell) { return Tiles.Contains(cell) ? Tiles[cell] : default; } - bool IResourceLayer.CanAddResource(ResourceType resourceType, CPos cell, int amount) { return CanAddResource(resourceType, cell, amount); } - int IResourceLayer.AddResource(ResourceType resourceType, CPos cell, int amount) { return AddResource(resourceType, cell, amount); } - int IResourceLayer.RemoveResource(ResourceType resourceType, CPos cell, int amount) { return RemoveResource(resourceType, cell, amount); } + int IResourceLayer.GetMaxDensity(string resourceType) + { + if (!ResourceInfo.TryGetValue(resourceType, out var resourceInfo)) + return 0; + + return resourceInfo.MaxDensity; + } + + bool IResourceLayer.CanAddResource(string resourceType, CPos cell, int amount) { return CanAddResource(resourceType, cell, amount); } + int IResourceLayer.AddResource(string resourceType, CPos cell, int amount) { return AddResource(resourceType, cell, amount); } + int IResourceLayer.RemoveResource(string resourceType, CPos cell, int amount) { return RemoveResource(resourceType, cell, amount); } void IResourceLayer.ClearResources(CPos cell) { ClearResources(cell); } bool IResourceLayer.IsVisible(CPos cell) { return Map.Contains(cell); } bool IResourceLayer.IsEmpty => false; @@ -50,8 +59,10 @@ namespace OpenRA.Mods.Common.Traits Map = self.World.Map; Tiles = new CellLayer(Map); - Resources = self.TraitsImplementing() - .ToDictionary(r => r.Info.ResourceType, r => r); + ResourceInfo = self.TraitsImplementing() + .ToDictionary(r => r.Info.Type, r => r.Info); + Resources = ResourceInfo.Values + .ToDictionary(r => r.ResourceType, r => r.Type); Map.Resources.CellEntryChanged += UpdateCell; } @@ -76,10 +87,10 @@ namespace OpenRA.Mods.Common.Traits var newTile = ResourceLayerContents.Empty; var newTerrain = byte.MaxValue; - if (Resources.TryGetValue(tile.Type, out var type)) + if (Resources.TryGetValue(tile.Type, out var resourceType) && ResourceInfo.TryGetValue(resourceType, out var resourceInfo)) { - newTile = new ResourceLayerContents(type, CalculateCellDensity(type, cell)); - newTerrain = Map.Rules.TerrainInfo.GetTerrainIndex(type.Info.TerrainType); + newTile = new ResourceLayerContents(resourceType, CalculateCellDensity(resourceType, cell)); + newTerrain = Map.Rules.TerrainInfo.GetTerrainIndex(resourceInfo.TerrainType); } // Nothing has changed @@ -89,7 +100,7 @@ namespace OpenRA.Mods.Common.Traits UpdateNetWorth(t.Type, t.Density, newTile.Type, newTile.Density); Tiles[uv] = newTile; Map.CustomTerrain[uv] = newTerrain; - CellChanged?.Invoke(cell, type); + CellChanged?.Invoke(cell, newTile.Type); // Neighbouring cell density depends on this cell foreach (var d in CVec.Directions) @@ -106,24 +117,24 @@ namespace OpenRA.Mods.Common.Traits UpdateNetWorth(neighbouringTile.Type, neighbouringTile.Density, neighbouringTile.Type, density); Tiles[neighbouringCell] = new ResourceLayerContents(neighbouringTile.Type, density); - CellChanged?.Invoke(neighbouringCell, type); + CellChanged?.Invoke(neighbouringCell, neighbouringTile.Type); } } - void UpdateNetWorth(ResourceType oldType, int oldDensity, ResourceType newType, int newDensity) + void UpdateNetWorth(string oldResourceType, int oldDensity, string newResourceType, int newDensity) { // Density + 1 as workaround for fixing ResourceLayer.Harvest as it would be very disruptive to balancing - if (oldType != null && oldDensity > 0) - NetWorth -= (oldDensity + 1) * oldType.Info.ValuePerUnit; + if (oldResourceType != null && oldDensity > 0 && ResourceInfo.TryGetValue(oldResourceType, out var oldResourceInfo)) + NetWorth -= (oldDensity + 1) * oldResourceInfo.ValuePerUnit; - if (newType != null && newDensity > 0) - NetWorth += (newDensity + 1) * newType.Info.ValuePerUnit; + if (newResourceType != null && newDensity > 0 && ResourceInfo.TryGetValue(newResourceType, out var newResourceInfo)) + NetWorth += (newDensity + 1) * newResourceInfo.ValuePerUnit; } - public int CalculateCellDensity(ResourceType type, CPos c) + public int CalculateCellDensity(string resourceType, CPos c) { var resources = Map.Resources; - if (type == null || resources[c].Type != type.Info.ResourceType) + if (resourceType == null || !ResourceInfo.TryGetValue(resourceType, out var resourceInfo) || resources[c].Type != resourceInfo.ResourceType) return 0; // Set density based on the number of neighboring resources @@ -133,73 +144,85 @@ namespace OpenRA.Mods.Common.Traits for (var v = -1; v < 2; v++) { var cell = c + new CVec(u, v); - if (resources.Contains(cell) && resources[cell].Type == type.Info.ResourceType) + if (resources.Contains(cell) && resources[cell].Type == resourceInfo.ResourceType) adjacent++; } } - return Math.Max(int2.Lerp(0, type.Info.MaxDensity, adjacent, 9), 1); + return Math.Max(int2.Lerp(0, resourceInfo.MaxDensity, adjacent, 9), 1); } - bool AllowResourceAt(ResourceType rt, CPos cell) + bool AllowResourceAt(string resourceType, CPos cell) { var mapResources = Map.Resources; if (!mapResources.Contains(cell)) return false; + if (!ResourceInfo.TryGetValue(resourceType, out var resourceInfo)) + return false; + // Ignore custom terrain types when spawning resources in the editor var terrainInfo = Map.Rules.TerrainInfo; var terrainType = terrainInfo.TerrainTypes[terrainInfo.GetTerrainInfo(Map.Tiles[cell]).TerrainType].Type; - if (!rt.Info.AllowedTerrainTypes.Contains(terrainType)) + if (!resourceInfo.AllowedTerrainTypes.Contains(terrainType)) return false; // TODO: Check against actors in the EditorActorLayer - return rt.Info.AllowOnRamps || Map.Ramp[cell] == 0; + return resourceInfo.AllowOnRamps || Map.Ramp[cell] == 0; } - bool CanAddResource(ResourceType resourceType, CPos cell, int amount = 1) + bool CanAddResource(string resourceType, CPos cell, int amount = 1) { var resources = Map.Resources; if (!resources.Contains(cell)) return false; + if (!ResourceInfo.TryGetValue(resourceType, out var resourceInfo)) + return false; + // The editor allows the user to replace one resource type with another, so treat mismatching resource type as an empty cell var content = resources[cell]; - if (content.Type != resourceType.Info.ResourceType) - return amount <= resourceType.Info.MaxDensity && AllowResourceAt(resourceType, cell); + if (content.Type != resourceInfo.ResourceType) + return amount <= resourceInfo.MaxDensity && AllowResourceAt(resourceType, cell); - var oldDensity = content.Type == resourceType.Info.ResourceType ? content.Index : 0; - return oldDensity + amount <= resourceType.Info.MaxDensity; + var oldDensity = content.Type == resourceInfo.ResourceType ? content.Index : 0; + return oldDensity + amount <= resourceInfo.MaxDensity; } - int AddResource(ResourceType resourceType, CPos cell, int amount = 1) + int AddResource(string resourceType, CPos cell, int amount = 1) { var resources = Map.Resources; if (!resources.Contains(cell)) return 0; + if (!ResourceInfo.TryGetValue(resourceType, out var resourceInfo)) + return 0; + // The editor allows the user to replace one resource type with another, so treat mismatching resource type as an empty cell var content = resources[cell]; - var oldDensity = content.Type == resourceType.Info.ResourceType ? content.Index : 0; - var density = (byte)Math.Min(resourceType.Info.MaxDensity, oldDensity + amount); - Map.Resources[cell] = new ResourceTile((byte)resourceType.Info.ResourceType, density); + var oldDensity = content.Type == resourceInfo.ResourceType ? content.Index : 0; + var density = (byte)Math.Min(resourceInfo.MaxDensity, oldDensity + amount); + Map.Resources[cell] = new ResourceTile((byte)resourceInfo.ResourceType, density); return density - oldDensity; } - int RemoveResource(ResourceType resourceType, CPos cell, int amount = 1) + int RemoveResource(string resourceType, CPos cell, int amount = 1) { var resources = Map.Resources; if (!resources.Contains(cell)) return 0; + if (!ResourceInfo.TryGetValue(resourceType, out var resourceInfo)) + return 0; + var content = resources[cell]; - if (content.Type == 0 || content.Type != resourceType.Info.ResourceType) + if (content.Type == 0 || content.Type != resourceInfo.ResourceType) return 0; var oldDensity = content.Index; var density = (byte)Math.Max(0, oldDensity - amount); - resources[cell] = density > 0 ? new ResourceTile((byte)resourceType.Info.ResourceType, density) : default; + resources[cell] = density > 0 ? new ResourceTile((byte)resourceInfo.ResourceType, density) : default; return oldDensity - density; } diff --git a/OpenRA.Mods.Common/Traits/World/ResourceLayer.cs b/OpenRA.Mods.Common/Traits/World/ResourceLayer.cs index 0e8c2a6b93..961e60ffac 100644 --- a/OpenRA.Mods.Common/Traits/World/ResourceLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/ResourceLayer.cs @@ -10,6 +10,7 @@ #endregion using System; +using System.Collections.Generic; using System.Linq; using OpenRA.Graphics; using OpenRA.Traits; @@ -19,10 +20,10 @@ namespace OpenRA.Mods.Common.Traits public struct ResourceLayerContents { public static readonly ResourceLayerContents Empty = default; - public readonly ResourceType Type; + public readonly string Type; public readonly int Density; - public ResourceLayerContents(ResourceType type, int density) + public ResourceLayerContents(string type, int density) { Type = type; Density = density; @@ -39,29 +40,31 @@ namespace OpenRA.Mods.Common.Traits { readonly World world; readonly BuildingInfluence buildingInfluence; - + protected readonly Dictionary ResourceInfo; protected readonly CellLayer Content; int resCells; - public event Action CellChanged; + public event Action CellChanged; public ResourceLayer(Actor self) { world = self.World; buildingInfluence = self.Trait(); + ResourceInfo = self.TraitsImplementing() + .ToDictionary(r => r.Info.Type, r => r.Info); Content = new CellLayer(world.Map); } - int GetAdjacentCellsWith(ResourceType t, CPos cell) + int GetAdjacentCellsWith(string resourceType, CPos cell) { var sum = 0; var directions = CVec.Directions; for (var i = 0; i < directions.Length; i++) { var c = cell + directions[i]; - if (Content.Contains(c) && Content[c].Type == t) + if (Content.Contains(c) && Content[c].Type == resourceType) ++sum; } @@ -71,78 +74,93 @@ namespace OpenRA.Mods.Common.Traits public void WorldLoaded(World w, WorldRenderer wr) { var resources = w.WorldActor.TraitsImplementing() - .ToDictionary(r => r.Info.ResourceType, r => r); + .ToDictionary(r => r.Info.ResourceType, r => r.Info.Type); foreach (var cell in w.Map.AllCells) { - if (!resources.TryGetValue(w.Map.Resources[cell].Type, out var t)) + if (!resources.TryGetValue(w.Map.Resources[cell].Type, out var resourceType)) continue; - if (!AllowResourceAt(t, cell)) + if (!AllowResourceAt(resourceType, cell)) continue; - Content[cell] = CreateResourceCell(t, cell); + Content[cell] = CreateResourceCell(resourceType, cell); } foreach (var cell in w.Map.AllCells) { - var type = Content[cell].Type; - if (type != null) + var resourceType = Content[cell].Type; + if (resourceType != null && ResourceInfo.TryGetValue(resourceType, out var resourceInfo)) { // Set initial density based on the number of neighboring resources // Adjacent includes the current cell, so is always >= 1 - var adjacent = GetAdjacentCellsWith(type, cell); - var density = int2.Lerp(0, type.Info.MaxDensity, adjacent, 9); + var adjacent = GetAdjacentCellsWith(resourceType, cell); + var density = int2.Lerp(0, resourceInfo.MaxDensity, adjacent, 9); Content[cell] = new ResourceLayerContents(Content[cell].Type, Math.Max(density, 1)); } } } - public bool AllowResourceAt(ResourceType rt, CPos cell) + public bool AllowResourceAt(string resourceType, CPos cell) { + if (!ResourceInfo.TryGetValue(resourceType, out var resourceInfo)) + return false; + if (!world.Map.Contains(cell)) return false; - if (!rt.Info.AllowedTerrainTypes.Contains(world.Map.GetTerrainInfo(cell).Type)) + if (!resourceInfo.AllowedTerrainTypes.Contains(world.Map.GetTerrainInfo(cell).Type)) return false; - if (!rt.Info.AllowUnderActors && world.ActorMap.AnyActorsAt(cell)) + if (!resourceInfo.AllowUnderActors && world.ActorMap.AnyActorsAt(cell)) return false; - if (!rt.Info.AllowUnderBuildings && buildingInfluence.GetBuildingAt(cell) != null) + if (!resourceInfo.AllowUnderBuildings && buildingInfluence.GetBuildingAt(cell) != null) return false; - return rt.Info.AllowOnRamps || world.Map.Ramp[cell] == 0; + return resourceInfo.AllowOnRamps || world.Map.Ramp[cell] == 0; } - ResourceLayerContents CreateResourceCell(ResourceType t, CPos cell) + ResourceLayerContents CreateResourceCell(string resourceType, CPos cell) { - world.Map.CustomTerrain[cell] = world.Map.Rules.TerrainInfo.GetTerrainIndex(t.Info.TerrainType); + if (!ResourceInfo.TryGetValue(resourceType, out var resourceInfo)) + { + world.Map.CustomTerrain[cell] = byte.MaxValue; + return ResourceLayerContents.Empty; + } + + world.Map.CustomTerrain[cell] = world.Map.Rules.TerrainInfo.GetTerrainIndex(resourceInfo.TerrainType); ++resCells; - return new ResourceLayerContents(t, 0); + return new ResourceLayerContents(resourceType, 0); } - bool CanAddResource(ResourceType resourceType, CPos cell, int amount = 1) + bool CanAddResource(string resourceType, CPos cell, int amount = 1) { if (!world.Map.Contains(cell)) return false; + if (!ResourceInfo.TryGetValue(resourceType, out var resourceInfo)) + return false; + var content = Content[cell]; if (content.Type == null) - return amount <= resourceType.Info.MaxDensity && AllowResourceAt(resourceType, cell); + return amount <= resourceInfo.MaxDensity && AllowResourceAt(resourceType, cell); if (content.Type != resourceType) return false; - return content.Density + amount <= resourceType.Info.MaxDensity; + return content.Density + amount <= resourceInfo.MaxDensity; } - int AddResource(ResourceType resourceType, CPos cell, int amount = 1) + int AddResource(string resourceType, CPos cell, int amount = 1) { if (!Content.Contains(cell)) return 0; + if (!ResourceInfo.TryGetValue(resourceType, out var resourceInfo)) + return 0; + var content = Content[cell]; if (content.Type == null) content = CreateResourceCell(resourceType, cell); @@ -151,7 +169,7 @@ namespace OpenRA.Mods.Common.Traits return 0; var oldDensity = content.Density; - var density = Math.Min(content.Type.Info.MaxDensity, oldDensity + amount); + var density = Math.Min(resourceInfo.MaxDensity, oldDensity + amount); Content[cell] = new ResourceLayerContents(content.Type, density); CellChanged?.Invoke(cell, content.Type); @@ -159,7 +177,7 @@ namespace OpenRA.Mods.Common.Traits return density - oldDensity; } - int RemoveResource(ResourceType resourceType, CPos cell, int amount = 1) + int RemoveResource(string resourceType, CPos cell, int amount = 1) { if (!Content.Contains(cell)) return 0; @@ -206,9 +224,17 @@ namespace OpenRA.Mods.Common.Traits } ResourceLayerContents IResourceLayer.GetResource(CPos cell) { return Content.Contains(cell) ? Content[cell] : default; } - bool IResourceLayer.CanAddResource(ResourceType resourceType, CPos cell, int amount) { return CanAddResource(resourceType, cell, amount); } - int IResourceLayer.AddResource(ResourceType resourceType, CPos cell, int amount) { return AddResource(resourceType, cell, amount); } - int IResourceLayer.RemoveResource(ResourceType resourceType, CPos cell, int amount) { return RemoveResource(resourceType, cell, amount); } + int IResourceLayer.GetMaxDensity(string resourceType) + { + if (!ResourceInfo.TryGetValue(resourceType, out var resourceInfo)) + return 0; + + return resourceInfo.MaxDensity; + } + + bool IResourceLayer.CanAddResource(string resourceType, CPos cell, int amount) { return CanAddResource(resourceType, cell, amount); } + int IResourceLayer.AddResource(string resourceType, CPos cell, int amount) { return AddResource(resourceType, cell, amount); } + int IResourceLayer.RemoveResource(string resourceType, CPos cell, int amount) { return RemoveResource(resourceType, cell, amount); } void IResourceLayer.ClearResources(CPos cell) { ClearResources(cell); } bool IResourceLayer.IsVisible(CPos cell) { return !world.FogObscures(cell); } bool IResourceLayer.IsEmpty => resCells < 1; diff --git a/OpenRA.Mods.Common/Traits/World/ResourceRenderer.cs b/OpenRA.Mods.Common/Traits/World/ResourceRenderer.cs index 009e6c98d9..8183d6e647 100644 --- a/OpenRA.Mods.Common/Traits/World/ResourceRenderer.cs +++ b/OpenRA.Mods.Common/Traits/World/ResourceRenderer.cs @@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.Traits protected readonly IResourceLayer ResourceLayer; protected readonly CellLayer RenderContent; protected readonly ResourceRendererInfo Info; - protected readonly World World; + protected readonly Dictionary ResourceInfo; readonly HashSet dirty = new HashSet(); readonly Queue cleanDirty = new Queue(); @@ -43,36 +43,34 @@ namespace OpenRA.Mods.Common.Traits public ResourceRenderer(Actor self, ResourceRendererInfo info) { Info = info; - World = self.World; ResourceLayer = self.Trait(); ResourceLayer.CellChanged += AddDirtyCell; + ResourceInfo = self.TraitsImplementing() + .ToDictionary(r => r.Info.Type, r => r); RenderContent = new CellLayer(self.World.Map); } - void AddDirtyCell(CPos cell, ResourceType resType) + void AddDirtyCell(CPos cell, string resourceType) { - if (resType == null || Info.RenderTypes.Contains(resType.Info.Type)) + if (resourceType == null || Info.RenderTypes.Contains(resourceType)) dirty.Add(cell); } void IWorldLoaded.WorldLoaded(World w, WorldRenderer wr) { - var resources = w.WorldActor.TraitsImplementing() - .ToDictionary(r => r.Info.ResourceType, r => r); - - foreach (var r in resources) + foreach (var resourceType in ResourceInfo.Values) { if (spriteLayer == null) { - var first = r.Value.Variants.First().Value.GetSprite(0); + var first = resourceType.Variants.First().Value.GetSprite(0); var emptySprite = new Sprite(first.Sheet, Rectangle.Empty, TextureChannel.Alpha); spriteLayer = new TerrainSpriteLayer(w, wr, emptySprite, first.BlendMode, wr.World.Type != WorldType.Editor); } if (shadowLayer == null) { - var firstWithShadow = r.Value.Variants.Values.FirstOrDefault(v => v.ShadowStart > 0); + var firstWithShadow = resourceType.Variants.Values.FirstOrDefault(v => v.ShadowStart > 0); if (firstWithShadow != null) { var first = firstWithShadow.GetShadow(0, WAngle.Zero); @@ -82,7 +80,7 @@ namespace OpenRA.Mods.Common.Traits } // All resources must share a blend mode - var sprites = r.Value.Variants.Values.SelectMany(v => Exts.MakeArray(v.Length, x => v.GetSprite(x))); + var sprites = resourceType.Variants.Values.SelectMany(v => Exts.MakeArray(v.Length, x => v.GetSprite(x))); if (sprites.Any(s => s.BlendMode != spriteLayer.BlendMode)) throw new InvalidDataException("Resource sprites specify different blend modes. " + "Try using different ResourceRenderer traits for resource types that use different blend modes."); @@ -93,10 +91,13 @@ namespace OpenRA.Mods.Common.Traits foreach (var cell in w.Map.AllCells) { var type = ResourceLayer.GetResource(cell).Type; - if (type != null && Info.RenderTypes.Contains(type.Info.Type)) + if (type != null && Info.RenderTypes.Contains(type)) { var resourceContent = ResourceLayer.GetResource(cell); - var rendererCellContents = new RendererCellContents(ChooseRandomVariant(resourceContent.Type), resourceContent.Type, resourceContent.Density); + if (!ResourceInfo.TryGetValue(resourceContent.Type, out var resourceType)) + continue; + + var rendererCellContents = new RendererCellContents(ChooseRandomVariant(resourceType), resourceType, resourceContent.Density); RenderContent[cell] = rendererCellContents; UpdateRenderedSprite(cell, rendererCellContents); } @@ -135,11 +136,12 @@ namespace OpenRA.Mods.Common.Traits if (resourceContent.Density > 0) { var cellContents = RenderContent[cell]; + var resourceData = ResourceInfo[resourceContent.Type]; var variant = cellContents.Variant; - if (cellContents.Variant == null || cellContents.Type != resourceContent.Type) - variant = ChooseRandomVariant(resourceContent.Type); + if (cellContents.Variant == null || cellContents.Type.Info.Type != resourceContent.Type) + variant = ChooseRandomVariant(resourceData); - var rendererCellContents = new RendererCellContents(variant, resourceContent.Type, resourceContent.Density); + var rendererCellContents = new RendererCellContents(variant, resourceData, resourceContent.Density); RenderContent[cell] = rendererCellContents; UpdateRenderedSprite(cell, rendererCellContents); @@ -199,22 +201,25 @@ namespace OpenRA.Mods.Common.Traits return t.Variants.Keys.Random(Game.CosmeticRandom); } - protected virtual ResourceType GetRenderedResourceType(CPos cell) { return RenderContent[cell].Type; } + protected virtual string GetRenderedResourceType(CPos cell) { return RenderContent[cell].Type.Info.Type; } protected virtual string GetRenderedResourceTooltip(CPos cell) { return RenderContent[cell].Type?.Info.Name; } - IEnumerable IResourceRenderer.ResourceTypes => World.WorldActor.TraitsImplementing(); + IEnumerable IResourceRenderer.ResourceTypes => ResourceInfo.Keys; - ResourceType IResourceRenderer.GetRenderedResourceType(CPos cell) { return GetRenderedResourceType(cell); } + string IResourceRenderer.GetRenderedResourceType(CPos cell) { return GetRenderedResourceType(cell); } string IResourceRenderer.GetRenderedResourceTooltip(CPos cell) { return GetRenderedResourceTooltip(cell); } - IEnumerable IResourceRenderer.RenderUIPreview(WorldRenderer wr, ResourceType resourceType, int2 origin, float scale) + IEnumerable IResourceRenderer.RenderUIPreview(WorldRenderer wr, string resourceType, int2 origin, float scale) { - var sequence = resourceType.Variants.First().Value; + if (!ResourceInfo.TryGetValue(resourceType, out var resourceInfo)) + yield break; + + var sequence = resourceInfo.Variants.First().Value; var sprite = sequence.GetSprite(sequence.Length - 1); var shadow = sequence.GetShadow(sequence.Length - 1, WAngle.Zero); - var palette = resourceType.Palette; + var palette = resourceInfo.Palette; if (shadow != null) yield return new UISpriteRenderable(shadow, WPos.Zero, origin, 0, palette, scale); @@ -222,13 +227,16 @@ namespace OpenRA.Mods.Common.Traits yield return new UISpriteRenderable(sprite, WPos.Zero, origin, 0, palette, scale); } - IEnumerable IResourceRenderer.RenderPreview(WorldRenderer wr, ResourceType resourceType, WPos origin) + IEnumerable IResourceRenderer.RenderPreview(WorldRenderer wr, string resourceType, WPos origin) { - var sequence = resourceType.Variants.First().Value; + if (!ResourceInfo.TryGetValue(resourceType, out var resourceInfo)) + yield break; + + var sequence = resourceInfo.Variants.First().Value; var sprite = sequence.GetSprite(sequence.Length - 1); var shadow = sequence.GetShadow(sequence.Length - 1, WAngle.Zero); var alpha = sequence.GetAlpha(sequence.Length - 1); - var palette = resourceType.Palette; + var palette = resourceInfo.Palette; var tintModifiers = sequence.IgnoreWorldTint ? TintModifiers.IgnoreWorldTint : TintModifiers.None; if (shadow != null) @@ -243,7 +251,7 @@ namespace OpenRA.Mods.Common.Traits public readonly ResourceType Type; public readonly int Density; - public static readonly RendererCellContents Empty = default(RendererCellContents); + public static readonly RendererCellContents Empty = default; public RendererCellContents(string variant, ResourceType type, int density) { diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs index 2f509ad984..644f70f9c6 100644 --- a/OpenRA.Mods.Common/TraitsInterfaces.cs +++ b/OpenRA.Mods.Common/TraitsInterfaces.cs @@ -152,7 +152,7 @@ namespace OpenRA.Mods.Common.Traits public interface INotifyDocking { void Docked(Actor self, Actor harvester); void Undocked(Actor self, Actor harvester); } [RequireExplicitImplementation] - public interface INotifyResourceAccepted { void OnResourceAccepted(Actor self, Actor refinery, ResourceTypeInfo resourceType, int count, int value); } + public interface INotifyResourceAccepted { void OnResourceAccepted(Actor self, Actor refinery, string resourceType, int count, int value); } public interface INotifyParachute { void OnParachute(Actor self); void OnLanded(Actor self); } [RequireExplicitImplementation] @@ -188,7 +188,7 @@ namespace OpenRA.Mods.Common.Traits void MovingToResources(Actor self, CPos targetCell); void MovingToRefinery(Actor self, Actor refineryActor); void MovementCancelled(Actor self); - void Harvested(Actor self, ResourceType resource); + void Harvested(Actor self, string resourceType); void Docked(); void Undocked(); } @@ -260,7 +260,7 @@ namespace OpenRA.Mods.Common.Traits public interface IAcceptResources { void OnDock(Actor harv, DeliverResources dockOrder); - int AcceptResources(ResourceTypeInfo resourceType, int count = 1); + int AcceptResources(string resourceType, int count = 1); CVec DeliveryOffset { get; } bool AllowDocking { get; } } @@ -668,11 +668,12 @@ namespace OpenRA.Mods.Common.Traits [RequireExplicitImplementation] public interface IResourceLayer { - event Action CellChanged; + event Action CellChanged; ResourceLayerContents GetResource(CPos cell); - bool CanAddResource(ResourceType resourceType, CPos cell, int amount = 1); - int AddResource(ResourceType resourceType, CPos cell, int amount = 1); - int RemoveResource(ResourceType resourceType, CPos cell, int amount = 1); + int GetMaxDensity(string resourceType); + bool CanAddResource(string resourceType, CPos cell, int amount = 1); + int AddResource(string resourceType, CPos cell, int amount = 1); + int RemoveResource(string resourceType, CPos cell, int amount = 1); void ClearResources(CPos cell); bool IsVisible(CPos cell); @@ -682,10 +683,10 @@ namespace OpenRA.Mods.Common.Traits [RequireExplicitImplementation] public interface IResourceRenderer { - IEnumerable ResourceTypes { get; } - ResourceType GetRenderedResourceType(CPos cell); + IEnumerable ResourceTypes { get; } + string GetRenderedResourceType(CPos cell); string GetRenderedResourceTooltip(CPos cell); - IEnumerable RenderUIPreview(WorldRenderer wr, ResourceType resourceType, int2 origin, float scale); - IEnumerable RenderPreview(WorldRenderer wr, ResourceType resourceType, WPos origin); + IEnumerable RenderUIPreview(WorldRenderer wr, string resourceType, int2 origin, float scale); + IEnumerable RenderPreview(WorldRenderer wr, string resourceType, WPos origin); } } diff --git a/OpenRA.Mods.Common/Warheads/CreateResourceWarhead.cs b/OpenRA.Mods.Common/Warheads/CreateResourceWarhead.cs index 44b33aa4e5..68639645b4 100644 --- a/OpenRA.Mods.Common/Warheads/CreateResourceWarhead.cs +++ b/OpenRA.Mods.Common/Warheads/CreateResourceWarhead.cs @@ -16,7 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Warheads { - public class CreateResourceWarhead : Warhead, IRulesetLoaded + public class CreateResourceWarhead : Warhead { [Desc("Size of the area. The resources are seeded within this area.", "Provide 2 values for a ring effect (outer/inner).")] public readonly int[] Size = { 0, 0 }; @@ -25,16 +25,6 @@ namespace OpenRA.Mods.Common.Warheads [FieldLoader.Require] public readonly string AddsResourceType = null; - void IRulesetLoaded.RulesetLoaded(Ruleset rules, WeaponInfo info) - { - var world = rules.Actors["world"]; - var resourceType = world.TraitInfos() - .FirstOrDefault(t => t.Type == AddsResourceType); - - if (resourceType == null) - throw new YamlException("CreateResourceWarhead defines an invalid resource type '{0}'".F(AddsResourceType)); - } - // TODO: Allow maximum resource splatter to be defined. (Per tile, and in total). public override void DoImpact(in Target target, WarheadArgs args) { @@ -53,17 +43,15 @@ namespace OpenRA.Mods.Common.Warheads var minRange = (Size.Length > 1 && Size[1] > 0) ? Size[1] : 0; var allCells = world.Map.FindTilesInAnnulus(targetTile, minRange, Size[0]); - var resourceType = world.WorldActor.TraitsImplementing() - .First(t => t.Info.Type == AddsResourceType); - var resourceLayer = world.WorldActor.Trait(); + var maxDensity = resourceLayer.GetMaxDensity(AddsResourceType); foreach (var cell in allCells) { - if (!resourceLayer.CanAddResource(resourceType, cell)) + if (!resourceLayer.CanAddResource(AddsResourceType, cell)) continue; - var splash = world.SharedRandom.Next(1, resourceType.Info.MaxDensity - resourceLayer.GetResource(cell).Density); - resourceLayer.AddResource(resourceType, cell, splash); + var splash = world.SharedRandom.Next(1, maxDensity - resourceLayer.GetResource(cell).Density); + resourceLayer.AddResource(AddsResourceType, cell, splash); } } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/LayerSelectorLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/LayerSelectorLogic.cs index 7936890e80..88eb635882 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/LayerSelectorLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/LayerSelectorLogic.cs @@ -49,7 +49,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic foreach (var resourceType in resourceRenderer.ResourceTypes) { var newResourcePreviewTemplate = ScrollItemWidget.Setup(layerPreviewTemplate, - () => editorCursor.Type == EditorCursorType.Resource && editorCursor.Resource == resourceType, + () => editorCursor.Type == EditorCursorType.Resource && editorCursor.ResourceType == resourceType, () => editor.SetBrush(new EditorResourceBrush(editor, resourceType, worldRenderer))); newResourcePreviewTemplate.Bounds.X = 0; @@ -63,7 +63,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic newResourcePreviewTemplate.Bounds.Width = tileSize.Width + (layerPreview.Bounds.X * 2); newResourcePreviewTemplate.Bounds.Height = tileSize.Height + (layerPreview.Bounds.Y * 2); newResourcePreviewTemplate.IsVisible = () => true; - newResourcePreviewTemplate.GetTooltipText = () => resourceType.Info.Type; + newResourcePreviewTemplate.GetTooltipText = () => resourceType; layerTemplateList.AddChild(newResourcePreviewTemplate); } diff --git a/OpenRA.Mods.Common/Widgets/ResourcePreviewWidget.cs b/OpenRA.Mods.Common/Widgets/ResourcePreviewWidget.cs index 4fb0e7ae74..ccc87fc533 100644 --- a/OpenRA.Mods.Common/Widgets/ResourcePreviewWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ResourcePreviewWidget.cs @@ -28,10 +28,10 @@ namespace OpenRA.Mods.Common.Widgets readonly IResourceRenderer[] resourceRenderers; readonly Size tileSize; - ResourceType resourceType; + string resourceType; IResourceRenderer resourceRenderer; - public ResourceType ResourceType + public string ResourceType { get => resourceType; diff --git a/OpenRA.Mods.D2k/Traits/SpiceBloom.cs b/OpenRA.Mods.D2k/Traits/SpiceBloom.cs index eaec5da59c..b25ad16e29 100644 --- a/OpenRA.Mods.D2k/Traits/SpiceBloom.cs +++ b/OpenRA.Mods.D2k/Traits/SpiceBloom.cs @@ -61,7 +61,6 @@ namespace OpenRA.Mods.D2k.Traits public class SpiceBloom : ITick, INotifyKilled { readonly SpiceBloomInfo info; - readonly ResourceType resourceType; readonly IResourceLayer resourceLayer; readonly Animation body; readonly Animation spurt; @@ -76,7 +75,6 @@ namespace OpenRA.Mods.D2k.Traits this.info = info; resourceLayer = self.World.WorldActor.Trait(); - resourceType = self.World.WorldActor.TraitsImplementing().First(t => t.Info.Type == info.ResourceType); var rs = self.Trait(); body = new Animation(self.World, rs.GetImage(self)); @@ -127,7 +125,7 @@ namespace OpenRA.Mods.D2k.Traits for (var i = 0; i < pieces; i++) { var cell = cells - .SkipWhile(p => resourceLayer.GetResource(p).Type == resourceType && !resourceLayer.CanAddResource(resourceType, p)) + .SkipWhile(p => resourceLayer.GetResource(p).Type == info.ResourceType && !resourceLayer.CanAddResource(info.ResourceType, p)) .Cast() .RandomOrDefault(self.World.SharedRandom);