Change indexes into tile arrays to be stored as bytes to save memory.
The index value needs only be big enough to handle all defined terrain types. This is a low number so we can save memory by defining it as a byte. This particularly saves memory for the CustomTerrain field in the Map class, which defines a cell layer for the map using tile indexes, so we can reduce the size of that layer 4x as a result.
This commit is contained in:
@@ -115,7 +115,7 @@ namespace OpenRA.Graphics
|
||||
var mapX = x + b.Left;
|
||||
var mapY = y + b.Top;
|
||||
var custom = map.CustomTerrain[mapX, mapY];
|
||||
if (custom == -1)
|
||||
if (custom == byte.MaxValue)
|
||||
continue;
|
||||
colors[y * stride + x] = world.TileSet[custom].Color.ToArgb();
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace OpenRA
|
||||
|
||||
[FieldLoader.Ignore] public Lazy<CellLayer<TerrainTile>> MapTiles;
|
||||
[FieldLoader.Ignore] public Lazy<CellLayer<ResourceTile>> MapResources;
|
||||
[FieldLoader.Ignore] public CellLayer<int> CustomTerrain;
|
||||
[FieldLoader.Ignore] public CellLayer<byte> CustomTerrain;
|
||||
|
||||
[FieldLoader.Ignore] Lazy<TileSet> cachedTileSet;
|
||||
[FieldLoader.Ignore] Lazy<Ruleset> rules;
|
||||
@@ -280,9 +280,9 @@ namespace OpenRA
|
||||
var br = Map.MapToCell(TileShape, new CPos(Bounds.Right - 1, Bounds.Bottom - 1));
|
||||
Cells = new CellRegion(TileShape, tl, br);
|
||||
|
||||
CustomTerrain = new CellLayer<int>(this);
|
||||
CustomTerrain = new CellLayer<byte>(this);
|
||||
foreach (var cell in Cells)
|
||||
CustomTerrain[cell] = -1;
|
||||
CustomTerrain[cell] = byte.MaxValue;
|
||||
}
|
||||
|
||||
public Ruleset PreloadRules()
|
||||
@@ -672,10 +672,10 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
public int GetTerrainIndex(CPos cell)
|
||||
public byte GetTerrainIndex(CPos cell)
|
||||
{
|
||||
var custom = CustomTerrain[cell];
|
||||
return custom != -1 ? custom : cachedTileSet.Value.GetTerrainIndex(MapTiles.Value[cell]);
|
||||
return custom != byte.MaxValue ? custom : cachedTileSet.Value.GetTerrainIndex(MapTiles.Value[cell]);
|
||||
}
|
||||
|
||||
public TerrainTypeInfo GetTerrainInfo(CPos cell)
|
||||
|
||||
@@ -39,9 +39,9 @@ namespace OpenRA
|
||||
public readonly bool PickAny;
|
||||
public readonly string Category;
|
||||
|
||||
int[] tiles;
|
||||
byte[] tiles;
|
||||
|
||||
public TileTemplate(ushort id, string image, int2 size, int[] tiles)
|
||||
public TileTemplate(ushort id, string image, int2 size, byte[] tiles)
|
||||
{
|
||||
this.Id = id;
|
||||
this.Image = image;
|
||||
@@ -56,16 +56,16 @@ namespace OpenRA
|
||||
tiles = LoadTiles(tileSet, my);
|
||||
}
|
||||
|
||||
int[] LoadTiles(TileSet tileSet, MiniYaml y)
|
||||
byte[] LoadTiles(TileSet tileSet, MiniYaml y)
|
||||
{
|
||||
var nodes = y.ToDictionary()["Tiles"].Nodes;
|
||||
|
||||
if (!PickAny)
|
||||
{
|
||||
var tiles = new int[Size.X * Size.Y];
|
||||
var tiles = new byte[Size.X * Size.Y];
|
||||
|
||||
for (var i = 0; i < tiles.Length; i++)
|
||||
tiles[i] = -1;
|
||||
tiles[i] = byte.MaxValue;
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
@@ -80,7 +80,7 @@ namespace OpenRA
|
||||
}
|
||||
else
|
||||
{
|
||||
var tiles = new int[nodes.Count];
|
||||
var tiles = new byte[nodes.Count];
|
||||
var i = 0;
|
||||
|
||||
foreach (var node in nodes)
|
||||
@@ -98,7 +98,7 @@ namespace OpenRA
|
||||
|
||||
static readonly string[] Fields = { "Id", "Image", "Frames", "Size", "PickAny" };
|
||||
|
||||
public int this[int index]
|
||||
public byte this[int index]
|
||||
{
|
||||
get { return tiles[index]; }
|
||||
}
|
||||
@@ -145,8 +145,8 @@ namespace OpenRA
|
||||
public readonly string[] EditorTemplateOrder;
|
||||
|
||||
public readonly TerrainTypeInfo[] TerrainInfo;
|
||||
readonly Dictionary<string, int> terrainIndexByType = new Dictionary<string, int>();
|
||||
readonly int defaultWalkableTerrainIndex;
|
||||
readonly Dictionary<string, byte> terrainIndexByType = new Dictionary<string, byte>();
|
||||
readonly byte defaultWalkableTerrainIndex;
|
||||
|
||||
static readonly string[] Fields = { "Name", "Id", "SheetSize", "Palette", "Extensions" };
|
||||
|
||||
@@ -162,7 +162,9 @@ namespace OpenRA
|
||||
.Select(y => new TerrainTypeInfo(y))
|
||||
.OrderBy(tt => tt.Type)
|
||||
.ToArray();
|
||||
for (var i = 0; i < TerrainInfo.Length; i++)
|
||||
if (TerrainInfo.Length >= byte.MaxValue)
|
||||
throw new InvalidDataException("Too many terrain types.");
|
||||
for (byte i = 0; i < TerrainInfo.Length; i++)
|
||||
{
|
||||
var tt = TerrainInfo[i].Type;
|
||||
|
||||
@@ -186,8 +188,9 @@ namespace OpenRA
|
||||
this.Palette = palette;
|
||||
this.Extensions = extensions;
|
||||
this.TerrainInfo = terrainInfo;
|
||||
|
||||
for (var i = 0; i < terrainInfo.Length; i++)
|
||||
if (TerrainInfo.Length >= byte.MaxValue)
|
||||
throw new InvalidDataException("Too many terrain types.");
|
||||
for (byte i = 0; i < terrainInfo.Length; i++)
|
||||
{
|
||||
var tt = terrainInfo[i].Type;
|
||||
|
||||
@@ -199,7 +202,7 @@ namespace OpenRA
|
||||
defaultWalkableTerrainIndex = GetTerrainIndex("Clear");
|
||||
}
|
||||
|
||||
public TerrainTypeInfo this[int index]
|
||||
public TerrainTypeInfo this[byte index]
|
||||
{
|
||||
get { return TerrainInfo[index]; }
|
||||
}
|
||||
@@ -209,28 +212,28 @@ namespace OpenRA
|
||||
get { return TerrainInfo.Length; }
|
||||
}
|
||||
|
||||
public bool TryGetTerrainIndex(string type, out int index)
|
||||
public bool TryGetTerrainIndex(string type, out byte index)
|
||||
{
|
||||
return terrainIndexByType.TryGetValue(type, out index);
|
||||
}
|
||||
|
||||
public int GetTerrainIndex(string type)
|
||||
public byte GetTerrainIndex(string type)
|
||||
{
|
||||
int index;
|
||||
byte index;
|
||||
if (terrainIndexByType.TryGetValue(type, out index))
|
||||
return index;
|
||||
|
||||
throw new InvalidDataException("Tileset '{0}' lacks terrain type '{1}'".F(Id, type));
|
||||
}
|
||||
|
||||
public int GetTerrainIndex(TerrainTile r)
|
||||
public byte GetTerrainIndex(TerrainTile r)
|
||||
{
|
||||
var tpl = Templates[r.Type];
|
||||
|
||||
if (tpl.Contains(r.Index))
|
||||
{
|
||||
var ti = tpl[r.Index];
|
||||
if (ti != -1)
|
||||
if (ti != byte.MaxValue)
|
||||
return ti;
|
||||
}
|
||||
|
||||
@@ -263,7 +266,7 @@ namespace OpenRA
|
||||
|
||||
public TerrainTypeInfo GetTerrainInfo(TerrainTile r)
|
||||
{
|
||||
return TerrainInfo[GetTerrainIndex(r)];
|
||||
return this[GetTerrainIndex(r)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace OpenRA.Mods.RA.AI
|
||||
bool enabled;
|
||||
int ticks;
|
||||
|
||||
HashSet<int> resourceTypeIndices;
|
||||
HashSet<byte> resourceTypeIndices;
|
||||
|
||||
RushFuzzy rushFuzzy = new RushFuzzy();
|
||||
|
||||
@@ -208,7 +208,7 @@ namespace OpenRA.Mods.RA.AI
|
||||
|
||||
random = new MersenneTwister((int)p.PlayerActor.ActorID);
|
||||
|
||||
resourceTypeIndices = new HashSet<int>(
|
||||
resourceTypeIndices = new HashSet<byte>(
|
||||
Map.Rules.Actors["world"].Traits
|
||||
.WithInterface<ResourceTypeInfo>()
|
||||
.Select(t => world.TileSet.GetTerrainIndex(t.TerrainType)));
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace OpenRA.Mods.RA
|
||||
self.World.Map.CustomTerrain[c] = GetTerrainType(c);
|
||||
}
|
||||
|
||||
int GetTerrainType(CPos cell)
|
||||
byte GetTerrainType(CPos cell)
|
||||
{
|
||||
var dx = cell - self.Location;
|
||||
var index = dx.X + self.World.TileSet.Templates[template].Size.X * dx.Y;
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
continue;
|
||||
|
||||
// Don't place under other buildings or custom terrain
|
||||
if (bi.GetBuildingAt(c) != self || map.CustomTerrain[c] != -1)
|
||||
if (bi.GetBuildingAt(c) != self || map.CustomTerrain[c] != byte.MaxValue)
|
||||
continue;
|
||||
|
||||
var index = Game.CosmeticRandom.Next(template.TilesCount);
|
||||
@@ -77,7 +77,7 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
continue;
|
||||
|
||||
// Don't place under other buildings or custom terrain
|
||||
if (bi.GetBuildingAt(c) != self || map.CustomTerrain[c] != -1)
|
||||
if (bi.GetBuildingAt(c) != self || map.CustomTerrain[c] != byte.MaxValue)
|
||||
continue;
|
||||
|
||||
layer.AddTile(c, new TerrainTile(template.Id, (byte)i));
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace OpenRA.Mods.RA.Move
|
||||
|
||||
foreach (var kvp in TerrainSpeeds)
|
||||
{
|
||||
int index;
|
||||
byte index;
|
||||
if (tileSet.TryGetTerrainIndex(kvp.Key, out index))
|
||||
info[index] = kvp.Value;
|
||||
}
|
||||
@@ -125,7 +125,7 @@ namespace OpenRA.Mods.RA.Move
|
||||
return int.MaxValue;
|
||||
|
||||
var index = world.Map.GetTerrainIndex(cell);
|
||||
if (index == -1)
|
||||
if (index == byte.MaxValue)
|
||||
return int.MaxValue;
|
||||
|
||||
return TilesetTerrainInfo[world.TileSet][index].Cost;
|
||||
@@ -526,7 +526,7 @@ namespace OpenRA.Mods.RA.Move
|
||||
public int MovementSpeedForCell(Actor self, CPos cell)
|
||||
{
|
||||
var index = self.World.Map.GetTerrainIndex(cell);
|
||||
if (index == -1)
|
||||
if (index == byte.MaxValue)
|
||||
return 0;
|
||||
|
||||
// TODO: Convert to integers
|
||||
|
||||
@@ -203,7 +203,7 @@ namespace OpenRA.Mods.RA
|
||||
if (--c.Density < 0)
|
||||
{
|
||||
content[cell] = EmptyCell;
|
||||
world.Map.CustomTerrain[cell] = -1;
|
||||
world.Map.CustomTerrain[cell] = byte.MaxValue;
|
||||
}
|
||||
else
|
||||
content[cell] = c;
|
||||
@@ -222,7 +222,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
// Clear cell
|
||||
content[cell] = EmptyCell;
|
||||
world.Map.CustomTerrain[cell] = -1;
|
||||
world.Map.CustomTerrain[cell] = byte.MaxValue;
|
||||
|
||||
if (!dirty.Contains(cell))
|
||||
dirty.Add(cell);
|
||||
|
||||
@@ -385,7 +385,7 @@ namespace OpenRA.TilesetBuilder
|
||||
ushort cur = 0;
|
||||
foreach (var tp in surface1.Templates)
|
||||
{
|
||||
var tiles = new int[tp.Width * tp.Height];
|
||||
var tiles = new byte[tp.Width * tp.Height];
|
||||
foreach (var t in tp.Cells)
|
||||
{
|
||||
var ttype = TerrainType[surface1.TerrainTypes[t.Key.X, t.Key.Y]].Type;
|
||||
|
||||
Reference in New Issue
Block a user