Files
h-school/src/HSchool.Content/DefCatalog.cs
T

121 lines
4.0 KiB
C#

namespace HSchool.Content;
/// <summary>
/// Frozen set of defs and locale strings for one school. Built once at create/load; the worker
/// never re-reads pack files afterwards.
/// </summary>
public sealed class DefCatalog
{
internal DefCatalog(
IReadOnlyList<string> packIds,
IReadOnlyDictionary<string, ActionDef> actions,
IReadOnlyDictionary<string, ThingDef> things,
IReadOnlyDictionary<string, PositionDef> positions,
IReadOnlyDictionary<string, WorkDef> works,
IReadOnlyDictionary<string, RoomDef> rooms,
IReadOnlyDictionary<string, BuildingDef> buildings,
IReadOnlyDictionary<string, FloorDef> floors,
IReadOnlyDictionary<string, TerritoryDef> territories,
IReadOnlyDictionary<string, string> ru,
IReadOnlyDictionary<string, string> en)
{
PackIds = packIds;
Actions = actions;
Things = things;
Positions = positions;
Works = works;
Rooms = rooms;
Buildings = buildings;
Floors = floors;
Territories = territories;
_ru = ru;
_en = en;
}
public IReadOnlyList<string> PackIds { get; }
public IReadOnlyDictionary<string, ActionDef> Actions { get; }
public IReadOnlyDictionary<string, ThingDef> Things { get; }
public IReadOnlyDictionary<string, PositionDef> Positions { get; }
public IReadOnlyDictionary<string, WorkDef> Works { get; }
public IReadOnlyDictionary<string, RoomDef> Rooms { get; }
public IReadOnlyDictionary<string, BuildingDef> Buildings { get; }
public IReadOnlyDictionary<string, FloorDef> Floors { get; }
public IReadOnlyDictionary<string, TerritoryDef> Territories { get; }
private readonly IReadOnlyDictionary<string, string> _ru;
private readonly IReadOnlyDictionary<string, string> _en;
public bool TryGet(DefKind kind, string defName, out Def def)
{
Def? found = kind switch
{
DefKind.Action => Actions.GetValueOrDefault(defName),
DefKind.Thing => Things.GetValueOrDefault(defName),
DefKind.Position => Positions.GetValueOrDefault(defName),
DefKind.Work => Works.GetValueOrDefault(defName),
DefKind.Room => Rooms.GetValueOrDefault(defName),
DefKind.Building => Buildings.GetValueOrDefault(defName),
DefKind.Floor => Floors.GetValueOrDefault(defName),
DefKind.Territory => Territories.GetValueOrDefault(defName),
_ => null,
};
if (found is null)
{
def = null!;
return false;
}
def = found;
return true;
}
/// <summary>
/// Positions the location panel should list for this node type. Only RoomDefs carry them today.
/// </summary>
public IReadOnlyList<string> PositionsFor(DefKind kind, string defName) =>
kind == DefKind.Room && Rooms.TryGetValue(defName, out var room) ? room.Positions : [];
/// <summary>Locale string for a def, walking <c>parent</c> when the key is missing. Falls back to <c>defName</c>.</summary>
public string Label(string locale, Def def)
{
var table = locale.Equals("en", StringComparison.OrdinalIgnoreCase) ? _en : _ru;
var current = def;
while (true)
{
if (table.TryGetValue(current.DefName, out var label))
{
return label;
}
if (current.Parent is null || !TryGet(KindOf(current), current.Parent, out var parent) || parent.DefName == current.DefName)
{
return def.DefName;
}
current = parent;
}
}
internal static DefKind KindOf(Def def) => def switch
{
ActionDef => DefKind.Action,
ThingDef => DefKind.Thing,
PositionDef => DefKind.Position,
WorkDef => DefKind.Work,
RoomDef => DefKind.Room,
BuildingDef => DefKind.Building,
FloorDef => DefKind.Floor,
TerritoryDef => DefKind.Territory,
_ => throw new ArgumentOutOfRangeException(nameof(def)),
};
}