Replace ResourceType with strings in interfaces/public methods.
This commit is contained in:
@@ -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<IRenderable> terrainOrResourcePreview = new List<IRenderable>();
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,19 +26,28 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public class EditorResourceLayer : IResourceLayer, IWorldLoaded, INotifyActorDisposing
|
||||
{
|
||||
protected readonly Map Map;
|
||||
protected readonly Dictionary<int, ResourceType> Resources;
|
||||
protected readonly Dictionary<string, ResourceTypeInfo> ResourceInfo;
|
||||
protected readonly Dictionary<int, string> Resources;
|
||||
protected readonly CellLayer<ResourceLayerContents> Tiles;
|
||||
|
||||
public int NetWorth { get; protected set; }
|
||||
|
||||
bool disposed;
|
||||
|
||||
public event Action<CPos, ResourceType> CellChanged;
|
||||
public event Action<CPos, string> 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<ResourceLayerContents>(Map);
|
||||
Resources = self.TraitsImplementing<ResourceType>()
|
||||
.ToDictionary(r => r.Info.ResourceType, r => r);
|
||||
ResourceInfo = self.TraitsImplementing<ResourceType>()
|
||||
.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;
|
||||
}
|
||||
|
||||
@@ -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<string, ResourceTypeInfo> ResourceInfo;
|
||||
protected readonly CellLayer<ResourceLayerContents> Content;
|
||||
|
||||
int resCells;
|
||||
|
||||
public event Action<CPos, ResourceType> CellChanged;
|
||||
public event Action<CPos, string> CellChanged;
|
||||
|
||||
public ResourceLayer(Actor self)
|
||||
{
|
||||
world = self.World;
|
||||
buildingInfluence = self.Trait<BuildingInfluence>();
|
||||
ResourceInfo = self.TraitsImplementing<ResourceType>()
|
||||
.ToDictionary(r => r.Info.Type, r => r.Info);
|
||||
|
||||
Content = new CellLayer<ResourceLayerContents>(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<ResourceType>()
|
||||
.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;
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
protected readonly IResourceLayer ResourceLayer;
|
||||
protected readonly CellLayer<RendererCellContents> RenderContent;
|
||||
protected readonly ResourceRendererInfo Info;
|
||||
protected readonly World World;
|
||||
protected readonly Dictionary<string, ResourceType> ResourceInfo;
|
||||
|
||||
readonly HashSet<CPos> dirty = new HashSet<CPos>();
|
||||
readonly Queue<CPos> cleanDirty = new Queue<CPos>();
|
||||
@@ -43,36 +43,34 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public ResourceRenderer(Actor self, ResourceRendererInfo info)
|
||||
{
|
||||
Info = info;
|
||||
World = self.World;
|
||||
ResourceLayer = self.Trait<IResourceLayer>();
|
||||
ResourceLayer.CellChanged += AddDirtyCell;
|
||||
ResourceInfo = self.TraitsImplementing<ResourceType>()
|
||||
.ToDictionary(r => r.Info.Type, r => r);
|
||||
|
||||
RenderContent = new CellLayer<RendererCellContents>(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<ResourceType>()
|
||||
.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<ResourceType> IResourceRenderer.ResourceTypes => World.WorldActor.TraitsImplementing<ResourceType>();
|
||||
IEnumerable<string> 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<IRenderable> IResourceRenderer.RenderUIPreview(WorldRenderer wr, ResourceType resourceType, int2 origin, float scale)
|
||||
IEnumerable<IRenderable> 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<IRenderable> IResourceRenderer.RenderPreview(WorldRenderer wr, ResourceType resourceType, WPos origin)
|
||||
IEnumerable<IRenderable> 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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user