namespace Aeshnidae.Expedition;
///
/// The island's zones (Settings.Zones) as a landblock lookup: every landblock id of every
/// box, first zone to claim it wins. Built when the settings are read.
///
public static class Zones
{
private static Dictionary _byLandblock = new();
public static IReadOnlyList All => Mod.Settings.Zones ?? new List();
public static void Build()
{
var map = new Dictionary();
foreach (var zone in All)
{
foreach (var box in zone.Boxes ?? new List())
{
if (!TryParseBox(box, out var x0, out var x1, out var y0, out var y1))
{
ModManager.Log($"[{Mod.Name}] zone '{zone.Name}': cannot read box '{box}' (want \"B3-B5,E8-EE\")", ModManager.LogLevel.Warn);
continue;
}
for (var x = x0; x <= x1; x++)
for (var y = y0; y <= y1; y++)
map.TryAdd((ushort)(x << 8 | y), zone);
}
}
_byLandblock = map;
}
public static ZoneSetting? Of(ushort landblock) =>
_byLandblock.TryGetValue(landblock, out var zone) ? zone : null;
public static ZoneSetting? Named(string name) =>
All.FirstOrDefault(z => string.Equals(z.Name, name, StringComparison.OrdinalIgnoreCase))
?? All.FirstOrDefault(z => z.Name.StartsWith(name, StringComparison.OrdinalIgnoreCase));
/// The zones whose meters are this act's goal.
public static IEnumerable OfAct(int act) =>
All.Where(z => z.Act == act && z.MeterTarget > 0);
public static IEnumerable LandblocksOf(ZoneSetting zone) =>
_byLandblock.Where(kv => ReferenceEquals(kv.Value, zone)).Select(kv => kv.Key);
private static bool TryParseBox(string box, out int x0, out int x1, out int y0, out int y1)
{
x0 = x1 = y0 = y1 = 0;
var parts = (box ?? "").Split(',', StringSplitOptions.TrimEntries);
return parts.Length == 2 && TryRange(parts[0], out x0, out x1) && TryRange(parts[1], out y0, out y1);
}
private static bool TryRange(string text, out int from, out int to)
{
from = to = 0;
var ends = text.Split('-', StringSplitOptions.TrimEntries);
if (ends.Length is < 1 or > 2)
return false;
if (!int.TryParse(ends[0], System.Globalization.NumberStyles.HexNumber, null, out from))
return false;
to = from;
return ends.Length == 1 || int.TryParse(ends[1], System.Globalization.NumberStyles.HexNumber, null, out to);
}
}