Use CellLayers for ResourceLayer.
This commit is contained in:
@@ -22,89 +22,78 @@ namespace OpenRA.Traits
|
|||||||
static readonly CellContents EmptyCell = new CellContents();
|
static readonly CellContents EmptyCell = new CellContents();
|
||||||
|
|
||||||
World world;
|
World world;
|
||||||
protected CellContents[,] content;
|
protected CellLayer<CellContents> content;
|
||||||
protected CellContents[,] render;
|
protected CellLayer<CellContents> render;
|
||||||
List<CPos> dirty;
|
List<CPos> dirty;
|
||||||
|
|
||||||
public void Render(WorldRenderer wr)
|
public void Render(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
var clip = wr.Viewport.CellBounds;
|
foreach (var cell in wr.Viewport.VisibleCells)
|
||||||
for (var x = clip.Left; x < clip.Right; x++)
|
|
||||||
{
|
{
|
||||||
for (var y = clip.Top; y < clip.Bottom; y++)
|
if (world.ShroudObscures(cell))
|
||||||
{
|
|
||||||
var pos = new CPos(x, y);
|
|
||||||
if (world.ShroudObscures(pos))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var c = render[x, y];
|
var c = render[cell];
|
||||||
if (c.Sprite != null)
|
if (c.Sprite != null)
|
||||||
new SpriteRenderable(c.Sprite, pos.CenterPosition,
|
new SpriteRenderable(c.Sprite, cell.CenterPosition,
|
||||||
WVec.Zero, -511, c.Type.Palette, 1f, true).Render(wr);
|
WVec.Zero, -511, c.Type.Palette, 1f, true).Render(wr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int GetAdjacentCellsWith(ResourceType t, int i, int j)
|
int GetAdjacentCellsWith(ResourceType t, CPos cell)
|
||||||
{
|
{
|
||||||
var sum = 0;
|
var sum = 0;
|
||||||
for (var u = -1; u < 2; u++)
|
for (var u = -1; u < 2; u++)
|
||||||
for (var v = -1; v < 2; v++)
|
for (var v = -1; v < 2; v++)
|
||||||
if (content[i + u, j + v].Type == t)
|
if (content[cell + new CVec(u, v)].Type == t)
|
||||||
++sum;
|
++sum;
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WorldLoaded(World w, WorldRenderer wr)
|
public void WorldLoaded(World w, WorldRenderer wr)
|
||||||
{
|
{
|
||||||
this.world = w;
|
this.world = w;
|
||||||
content = new CellContents[w.Map.MapSize.X, w.Map.MapSize.Y];
|
content = new CellLayer<CellContents>(w.Map);
|
||||||
render = new CellContents[w.Map.MapSize.X, w.Map.MapSize.Y];
|
render = new CellLayer<CellContents>(w.Map);
|
||||||
dirty = new List<CPos>();
|
dirty = new List<CPos>();
|
||||||
|
|
||||||
var resources = w.WorldActor.TraitsImplementing<ResourceType>()
|
var resources = w.WorldActor.TraitsImplementing<ResourceType>()
|
||||||
.ToDictionary(r => r.Info.ResourceType, r => r);
|
.ToDictionary(r => r.Info.ResourceType, r => r);
|
||||||
|
|
||||||
var map = w.Map;
|
foreach (var cell in w.Map.Cells)
|
||||||
for (var x = map.Bounds.Left; x < map.Bounds.Right; x++)
|
|
||||||
{
|
{
|
||||||
for (var y = map.Bounds.Top; y < map.Bounds.Bottom; y++)
|
|
||||||
{
|
|
||||||
var cell = new CPos(x, y);
|
|
||||||
ResourceType t;
|
ResourceType t;
|
||||||
if (!resources.TryGetValue(w.Map.MapResources.Value[x, y].Type, out t))
|
if (!resources.TryGetValue(w.Map.MapResources.Value[cell.X, cell.Y].Type, out t))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!AllowResourceAt(t, cell))
|
if (!AllowResourceAt(t, cell))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
content[x, y] = CreateResourceCell(t, cell);
|
content[cell] = CreateResourceCell(t, cell);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set initial density based on the number of neighboring resources
|
// Set initial density based on the number of neighboring resources
|
||||||
for (var x = map.Bounds.Left; x < map.Bounds.Right; x++)
|
foreach (var cell in w.Map.Cells)
|
||||||
{
|
{
|
||||||
for (var y = map.Bounds.Top; y < map.Bounds.Bottom; y++)
|
var type = content[cell].Type;
|
||||||
{
|
|
||||||
var type = content[x, y].Type;
|
|
||||||
if (type != null)
|
if (type != null)
|
||||||
{
|
{
|
||||||
// Adjacent includes the current cell, so is always >= 1
|
// Adjacent includes the current cell, so is always >= 1
|
||||||
var adjacent = GetAdjacentCellsWith(type, x, y);
|
var adjacent = GetAdjacentCellsWith(type, cell);
|
||||||
var density = int2.Lerp(0, type.Info.MaxDensity, adjacent, 9);
|
var density = int2.Lerp(0, type.Info.MaxDensity, adjacent, 9);
|
||||||
content[x, y].Density = Math.Max(density, 1);
|
var temp = content[cell];
|
||||||
|
temp.Density = Math.Max(density, 1);
|
||||||
|
|
||||||
render[x, y] = content[x, y];
|
render[cell] = content[cell] = temp;
|
||||||
UpdateRenderedSprite(new CPos(x, y));
|
UpdateRenderedSprite(cell);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void UpdateRenderedSprite(CPos p)
|
protected virtual void UpdateRenderedSprite(CPos cell)
|
||||||
{
|
{
|
||||||
var t = render[p.X, p.Y];
|
var t = render[cell];
|
||||||
if (t.Density > 0)
|
if (t.Density > 0)
|
||||||
{
|
{
|
||||||
var sprites = t.Type.Variants[t.Variant];
|
var sprites = t.Type.Variants[t.Variant];
|
||||||
@@ -114,7 +103,7 @@ namespace OpenRA.Traits
|
|||||||
else
|
else
|
||||||
t.Sprite = null;
|
t.Sprite = null;
|
||||||
|
|
||||||
render[p.X, p.Y] = t;
|
render[cell] = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual string ChooseRandomVariant(ResourceType t)
|
protected virtual string ChooseRandomVariant(ResourceType t)
|
||||||
@@ -129,7 +118,7 @@ namespace OpenRA.Traits
|
|||||||
{
|
{
|
||||||
if (!self.World.FogObscures(c))
|
if (!self.World.FogObscures(c))
|
||||||
{
|
{
|
||||||
render[c.X, c.Y] = content[c.X, c.Y];
|
render[c] = content[c];
|
||||||
UpdateRenderedSprite(c);
|
UpdateRenderedSprite(c);
|
||||||
remove.Add(c);
|
remove.Add(c);
|
||||||
}
|
}
|
||||||
@@ -139,15 +128,15 @@ namespace OpenRA.Traits
|
|||||||
dirty.Remove(r);
|
dirty.Remove(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AllowResourceAt(ResourceType rt, CPos a)
|
public bool AllowResourceAt(ResourceType rt, CPos cell)
|
||||||
{
|
{
|
||||||
if (!world.Map.IsInMap(a.X, a.Y))
|
if (!world.Map.IsInMap(cell))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!rt.Info.AllowedTerrainTypes.Contains(world.Map.GetTerrainInfo(a).Type))
|
if (!rt.Info.AllowedTerrainTypes.Contains(world.Map.GetTerrainInfo(cell).Type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!rt.Info.AllowUnderActors && world.ActorMap.AnyUnitsAt(a))
|
if (!rt.Info.AllowUnderActors && world.ActorMap.AnyUnitsAt(cell))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -160,9 +149,10 @@ namespace OpenRA.Traits
|
|||||||
|| (currentResourceType == null && AllowResourceAt(newResourceType, cell));
|
|| (currentResourceType == null && AllowResourceAt(newResourceType, cell));
|
||||||
}
|
}
|
||||||
|
|
||||||
CellContents CreateResourceCell(ResourceType t, CPos p)
|
CellContents CreateResourceCell(ResourceType t, CPos cell)
|
||||||
{
|
{
|
||||||
world.Map.CustomTerrain[p.X, p.Y] = world.TileSet.GetTerrainIndex(t.Info.TerrainType);
|
world.Map.CustomTerrain[cell.X, cell.Y] = world.TileSet.GetTerrainIndex(t.Info.TerrainType);
|
||||||
|
|
||||||
return new CellContents
|
return new CellContents
|
||||||
{
|
{
|
||||||
Type = t,
|
Type = t,
|
||||||
@@ -172,7 +162,7 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public void AddResource(ResourceType t, CPos p, int n)
|
public void AddResource(ResourceType t, CPos p, int n)
|
||||||
{
|
{
|
||||||
var cell = content[p.X, p.Y];
|
var cell = content[p];
|
||||||
if (cell.Type == null)
|
if (cell.Type == null)
|
||||||
cell = CreateResourceCell(t, p);
|
cell = CreateResourceCell(t, p);
|
||||||
|
|
||||||
@@ -180,58 +170,60 @@ namespace OpenRA.Traits
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
cell.Density = Math.Min(cell.Type.Info.MaxDensity, cell.Density + n);
|
cell.Density = Math.Min(cell.Type.Info.MaxDensity, cell.Density + n);
|
||||||
content[p.X, p.Y] = cell;
|
content[p] = cell;
|
||||||
|
|
||||||
if (!dirty.Contains(p))
|
if (!dirty.Contains(p))
|
||||||
dirty.Add(p);
|
dirty.Add(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsFull(CPos c)
|
public bool IsFull(CPos cell)
|
||||||
{
|
{
|
||||||
return content[c.X, c.Y].Density == content[c.X, c.Y].Type.Info.MaxDensity;
|
return content[cell].Density == content[cell].Type.Info.MaxDensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceType Harvest(CPos p)
|
public ResourceType Harvest(CPos cell)
|
||||||
{
|
{
|
||||||
var type = content[p.X, p.Y].Type;
|
var c = content[cell];
|
||||||
if (type == null)
|
if (c.Type == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (--content[p.X, p.Y].Density < 0)
|
if (--c.Density < 0)
|
||||||
{
|
{
|
||||||
content[p.X, p.Y] = EmptyCell;
|
content[cell] = EmptyCell;
|
||||||
world.Map.CustomTerrain[p.X, p.Y] = -1;
|
world.Map.CustomTerrain[cell.X, cell.Y] = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
content[cell] = c;
|
||||||
|
|
||||||
|
if (!dirty.Contains(cell))
|
||||||
|
dirty.Add(cell);
|
||||||
|
|
||||||
|
return c.Type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dirty.Contains(p))
|
public void Destroy(CPos cell)
|
||||||
dirty.Add(p);
|
|
||||||
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Destroy(CPos p)
|
|
||||||
{
|
{
|
||||||
// Don't break other users of CustomTerrain if there are no resources
|
// Don't break other users of CustomTerrain if there are no resources
|
||||||
if (content[p.X, p.Y].Type == null)
|
if (content[cell].Type == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Clear cell
|
// Clear cell
|
||||||
content[p.X, p.Y] = EmptyCell;
|
content[cell] = EmptyCell;
|
||||||
world.Map.CustomTerrain[p.X, p.Y] = -1;
|
world.Map.CustomTerrain[cell.X, cell.Y] = -1;
|
||||||
|
|
||||||
if (!dirty.Contains(p))
|
if (!dirty.Contains(cell))
|
||||||
dirty.Add(p);
|
dirty.Add(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceType GetResource(CPos p) { return content[p.X, p.Y].Type; }
|
public ResourceType GetResource(CPos cell) { return content[cell].Type; }
|
||||||
public ResourceType GetRenderedResource(CPos p) { return render[p.X, p.Y].Type; }
|
public ResourceType GetRenderedResource(CPos cell) { return render[cell].Type; }
|
||||||
public int GetResourceDensity(CPos p) { return content[p.X, p.Y].Density; }
|
public int GetResourceDensity(CPos cell) { return content[cell].Density; }
|
||||||
public int GetMaxResourceDensity(CPos p)
|
public int GetMaxResourceDensity(CPos cell)
|
||||||
{
|
{
|
||||||
if (content[p.X, p.Y].Type == null)
|
if (content[cell].Type == null)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return content[p.X, p.Y].Type.Info.MaxDensity;
|
return content[cell].Type.Info.MaxDensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct CellContents
|
public struct CellContents
|
||||||
|
|||||||
@@ -97,28 +97,28 @@ namespace OpenRA.Traits
|
|||||||
ClearSides FindClearSides(ResourceType t, CPos p)
|
ClearSides FindClearSides(ResourceType t, CPos p)
|
||||||
{
|
{
|
||||||
var ret = ClearSides.None;
|
var ret = ClearSides.None;
|
||||||
if (render[p.X, p.Y - 1].Type != t)
|
if (render[p + new CVec(0, -1)].Type != t)
|
||||||
ret |= ClearSides.Top | ClearSides.TopLeft | ClearSides.TopRight;
|
ret |= ClearSides.Top | ClearSides.TopLeft | ClearSides.TopRight;
|
||||||
|
|
||||||
if (render[p.X - 1, p.Y].Type != t)
|
if (render[p + new CVec(-1, 0)].Type != t)
|
||||||
ret |= ClearSides.Left | ClearSides.TopLeft | ClearSides.BottomLeft;
|
ret |= ClearSides.Left | ClearSides.TopLeft | ClearSides.BottomLeft;
|
||||||
|
|
||||||
if (render[p.X + 1, p.Y].Type != t)
|
if (render[p + new CVec(1, 0)].Type != t)
|
||||||
ret |= ClearSides.Right | ClearSides.TopRight | ClearSides.BottomRight;
|
ret |= ClearSides.Right | ClearSides.TopRight | ClearSides.BottomRight;
|
||||||
|
|
||||||
if (render[p.X, p.Y + 1].Type != t)
|
if (render[p + new CVec(0, 1)].Type != t)
|
||||||
ret |= ClearSides.Bottom | ClearSides.BottomLeft | ClearSides.BottomRight;
|
ret |= ClearSides.Bottom | ClearSides.BottomLeft | ClearSides.BottomRight;
|
||||||
|
|
||||||
if (render[p.X - 1, p.Y - 1].Type != t)
|
if (render[p + new CVec(-1, -1)].Type != t)
|
||||||
ret |= ClearSides.TopLeft;
|
ret |= ClearSides.TopLeft;
|
||||||
|
|
||||||
if (render[p.X + 1, p.Y - 1].Type != t)
|
if (render[p + new CVec(1, -1)].Type != t)
|
||||||
ret |= ClearSides.TopRight;
|
ret |= ClearSides.TopRight;
|
||||||
|
|
||||||
if (render[p.X - 1, p.Y + 1].Type != t)
|
if (render[p + new CVec(-1, 1)].Type != t)
|
||||||
ret |= ClearSides.BottomLeft;
|
ret |= ClearSides.BottomLeft;
|
||||||
|
|
||||||
if (render[p.X + 1, p.Y + 1].Type != t)
|
if (render[p + new CVec(1, 1)].Type != t)
|
||||||
ret |= ClearSides.BottomRight;
|
ret |= ClearSides.BottomRight;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -126,7 +126,7 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
void UpdateRenderedTileInner(CPos p)
|
void UpdateRenderedTileInner(CPos p)
|
||||||
{
|
{
|
||||||
var t = render[p.X, p.Y];
|
var t = render[p];
|
||||||
if (t.Density > 0)
|
if (t.Density > 0)
|
||||||
{
|
{
|
||||||
var clear = FindClearSides(t.Type, p);
|
var clear = FindClearSides(t.Type, p);
|
||||||
@@ -146,7 +146,7 @@ namespace OpenRA.Traits
|
|||||||
else
|
else
|
||||||
t.Sprite = null;
|
t.Sprite = null;
|
||||||
|
|
||||||
render[p.X, p.Y] = t;
|
render[p] = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateRenderedSprite(CPos p)
|
protected override void UpdateRenderedSprite(CPos p)
|
||||||
|
|||||||
Reference in New Issue
Block a user