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); } }