Snowflake/RPG.GameCore/Excel/ExcelTables.cs

75 lines
2.7 KiB
C#

using System.Collections.Immutable;
using System.Reflection;
using System.Text.Json;
using Microsoft.Extensions.Logging;
using RPG.GameCore.Excel.Attributes;
using RPG.GameCore.Resources;
namespace RPG.GameCore.Excel;
public class ExcelTables
{
private readonly IResourceProvider _resourceProvider;
private readonly ILogger _logger;
private ImmutableDictionary<ExcelType, ImmutableArray<ExcelRow>>? _tables;
public ExcelTables(IResourceProvider resourceProvider, ILogger<ExcelTables> logger)
{
_resourceProvider = resourceProvider;
_logger = logger;
}
public TExcelRow? GetExcelRow<TExcelRow>(ExcelType type, uint id) where TExcelRow : ExcelRow
{
if (_tables == null) throw new InvalidOperationException("GetExcelRow called when ExcelTables not loaded.");
if (_tables.TryGetValue(type, out ImmutableArray<ExcelRow> rows))
{
return rows.SingleOrDefault(row => row.Id == id) as TExcelRow;
}
throw new ArgumentException($"GetExcelRow: table for excel type not found {type}");
}
public IEnumerable<ExcelRow> GetAllRows(ExcelType type)
{
if (_tables == null) throw new InvalidOperationException("GetAllRows called when ExcelTables not loaded.");
if (_tables.TryGetValue(type, out ImmutableArray<ExcelRow> rows))
{
return rows;
}
throw new ArgumentException($"GetAllRows: table for excel type not found {type}");
}
public void Load()
{
ImmutableDictionary<ExcelType, ImmutableArray<ExcelRow>>.Builder tables = ImmutableDictionary.CreateBuilder<ExcelType, ImmutableArray<ExcelRow>>();
IEnumerable<Type> types = Assembly.GetExecutingAssembly().GetTypes()
.Where(type => type.GetCustomAttribute<ExcelTableAttribute>() != null);
foreach (Type type in types)
{
ExcelTableAttribute attribute = type.GetCustomAttribute<ExcelTableAttribute>()!;
JsonDocument tableJson = _resourceProvider.GetExcelTableJson(attribute.Path);
var rows = ImmutableArray.CreateBuilder<ExcelRow>();
foreach (JsonProperty property in tableJson.RootElement.EnumerateObject())
{
if (property.Value.ValueKind != JsonValueKind.Object)
throw new ArgumentException($"Failed to load excel: expected an object, got {property.Value.ValueKind}");
ExcelRow row = (property.Value.Deserialize(type) as ExcelRow)!;
rows.Add(row);
}
tables.Add(attribute.Type, rows.ToImmutable());
}
_tables = tables.ToImmutable();
_logger.LogInformation("Loaded {count} excel tables", _tables.Count);
}
}