Files
OpenRA/OpenRA.Mods.Common/Terrain/TerrainInfo.cs
2024-07-29 21:56:36 +02:00

105 lines
3.1 KiB
C#

#region Copyright & License Information
/*
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System.Collections.Generic;
namespace OpenRA.Mods.Common.Terrain
{
public interface ITemplatedTerrainInfo : ITerrainInfo
{
string[] EditorTemplateOrder { get; }
IReadOnlyDictionary<ushort, TerrainTemplateInfo> Templates { get; }
}
public interface ITerrainInfoNotifyMapCreated : ITerrainInfo
{
void MapCreated(Map map);
}
public class TerrainTemplateInfo
{
public readonly ushort Id;
public readonly int2 Size;
public readonly bool PickAny;
public readonly string[] Categories;
readonly TerrainTileInfo[] tileInfo;
public TerrainTemplateInfo(ITerrainInfo terrainInfo, MiniYaml my)
{
FieldLoader.Load(this, my);
var nodes = my.NodeWithKey("Tiles").Value.Nodes;
if (!PickAny)
{
tileInfo = new TerrainTileInfo[Size.X * Size.Y];
foreach (var node in nodes)
{
if (!int.TryParse(node.Key, out var key))
throw new YamlException(
$"Tileset `{terrainInfo.Id}` template `{Id}` defines a frame `{node.Key}` that is not a valid integer.");
if (key < 0 || key >= tileInfo.Length)
throw new YamlException(
$"Tileset `{terrainInfo.Id}` template `{Id}` references frame {key}, but only [0..{tileInfo.Length - 1}] are valid for a {Size.X}x{Size.Y} Size template.");
tileInfo[key] = LoadTileInfo(terrainInfo, node.Value);
}
}
else
{
tileInfo = new TerrainTileInfo[nodes.Length];
var i = 0;
foreach (var node in nodes)
{
if (!int.TryParse(node.Key, out var key))
throw new YamlException($"Tileset `{terrainInfo.Id}` template `{Id}` defines a frame `{node.Key}` that is not a valid integer.");
if (key != i++)
throw new YamlException($"Tileset `{terrainInfo.Id}` template `{Id}` is missing a definition for frame {i - 1}.");
tileInfo[key] = LoadTileInfo(terrainInfo, node.Value);
}
}
}
protected virtual TerrainTileInfo LoadTileInfo(ITerrainInfo terrainInfo, MiniYaml my)
{
var tile = new TerrainTileInfo();
FieldLoader.Load(tile, my);
// Terrain type must be converted from a string to an index
tile.GetType().GetField(nameof(tile.TerrainType)).SetValue(tile, terrainInfo.GetTerrainIndex(my.Value));
// Fall back to the terrain-type color if necessary
var overrideColor = terrainInfo.TerrainTypes[tile.TerrainType].Color;
if (tile.MinColor == default)
tile.GetType().GetField(nameof(tile.MinColor)).SetValue(tile, overrideColor);
if (tile.MaxColor == default)
tile.GetType().GetField(nameof(tile.MaxColor)).SetValue(tile, overrideColor);
return tile;
}
public TerrainTileInfo this[int index] => tileInfo[index];
public bool Contains(int index)
{
return index >= 0 && index < tileInfo.Length;
}
public int TilesCount => tileInfo.Length;
}
}