diff --git a/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.Chat.cs b/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.Chat.cs index 4b9d5bd..4ae561a 100644 --- a/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.Chat.cs +++ b/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.Chat.cs @@ -94,6 +94,16 @@ public partial class LightlessHub throw new HubException("Unsupported chat channel."); } + if (channel.WorldId == 0 || !WorldRegistry.IsKnownWorld(channel.WorldId)) + { + throw new HubException("Unsupported chat channel."); + } + + if (presence.TerritoryId == 0 || !definition.TerritoryIds.Contains(presence.TerritoryId)) + { + throw new HubException("Zone chat is only available in supported territories."); + } + string? hashedCid = null; var isLightfinder = false; if (IsValidHashedCid(UserCharaIdent)) @@ -110,6 +120,7 @@ public partial class LightlessHub UserUID, definition, channel.WorldId, + presence.TerritoryId, hashedCid, isLightfinder, isActive: true); diff --git a/LightlessSyncServer/LightlessSyncServer/Models/ChatModels.cs b/LightlessSyncServer/LightlessSyncServer/Models/ChatModels.cs index c85e385..39214dc 100644 --- a/LightlessSyncServer/LightlessSyncServer/Models/ChatModels.cs +++ b/LightlessSyncServer/LightlessSyncServer/Models/ChatModels.cs @@ -43,7 +43,8 @@ public readonly record struct ZoneChannelDefinition( string Key, string DisplayName, ChatChannelDescriptor Descriptor, - IReadOnlyList TerritoryNames); + IReadOnlyList TerritoryNames, + IReadOnlySet TerritoryIds); public readonly record struct ChannelKey(ChatChannelType Type, ushort WorldId, string CustomKey) { diff --git a/LightlessSyncServer/LightlessSyncServer/Models/ChatZoneDefinitions.cs b/LightlessSyncServer/LightlessSyncServer/Models/ChatZoneDefinitions.cs index ebef986..ddc12f5 100644 --- a/LightlessSyncServer/LightlessSyncServer/Models/ChatZoneDefinitions.cs +++ b/LightlessSyncServer/LightlessSyncServer/Models/ChatZoneDefinitions.cs @@ -22,7 +22,10 @@ internal static class ChatZoneDefinitions { "Limsa Lominsa Lower Decks", "Limsa Lominsa Upper Decks" - }), + }, + TerritoryIds: TerritoryRegistry.GetIds( + "Limsa Lominsa Lower Decks", + "Limsa Lominsa Upper Decks")), new ZoneChannelDefinition( Key: "gridania", DisplayName: "Gridania", @@ -37,7 +40,10 @@ internal static class ChatZoneDefinitions { "New Gridania", "Old Gridania" - }), + }, + TerritoryIds: TerritoryRegistry.GetIds( + "New Gridania", + "Old Gridania")), new ZoneChannelDefinition( Key: "uldah", DisplayName: "Ul'dah", @@ -52,6 +58,10 @@ internal static class ChatZoneDefinitions { "Ul'dah - Steps of Nald", "Ul'dah - Steps of Thal" - }) + }, + TerritoryIds: TerritoryRegistry.GetIds( + "Ul'dah - Steps of Nald", + "Ul'dah - Steps of Thal")) }; + } diff --git a/LightlessSyncServer/LightlessSyncServer/Models/TerritoryDefinition.cs b/LightlessSyncServer/LightlessSyncServer/Models/TerritoryDefinition.cs new file mode 100644 index 0000000..cdba485 --- /dev/null +++ b/LightlessSyncServer/LightlessSyncServer/Models/TerritoryDefinition.cs @@ -0,0 +1,5 @@ +namespace LightlessSyncServer.Models; + +internal readonly record struct TerritoryDefinition( + ushort TerritoryId, + string Name); diff --git a/LightlessSyncServer/LightlessSyncServer/Models/TerritoryRegistry.generated.cs b/LightlessSyncServer/LightlessSyncServer/Models/TerritoryRegistry.generated.cs new file mode 100644 index 0000000..c12844c --- /dev/null +++ b/LightlessSyncServer/LightlessSyncServer/Models/TerritoryRegistry.generated.cs @@ -0,0 +1,1121 @@ +// +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace LightlessSyncServer.Models; + +internal static class TerritoryRegistry +{ + private static readonly TerritoryDefinition[] TerritoryArray = new[] + { + new TerritoryDefinition(1238, "A Future Rewritten"), + new TerritoryDefinition(560, "Aetherochemical Research Facility"), + new TerritoryDefinition(702, "Aetherochemical Research Facility"), + new TerritoryDefinition(1110, "Aetherochemical Research Facility"), + new TerritoryDefinition(1054, "Aglaia"), + new TerritoryDefinition(841, "Akadaemia Anyder"), + new TerritoryDefinition(377, "Akh Afah Amphitheatre"), + new TerritoryDefinition(378, "Akh Afah Amphitheatre"), + new TerritoryDefinition(457, "Akh Afah Amphitheatre"), + new TerritoryDefinition(403, "Ala Mhigo"), + new TerritoryDefinition(1146, "Ala Mhigo"), + new TerritoryDefinition(1217, "Ala Mhigo"), + new TerritoryDefinition(505, "Alexander"), + new TerritoryDefinition(553, "Alexander"), + new TerritoryDefinition(1199, "Alexandria"), + new TerritoryDefinition(1176, "Aloalo Island"), + new TerritoryDefinition(1050, "Alzadaal's Legacy"), + new TerritoryDefinition(1056, "Alzadaal's Legacy"), + new TerritoryDefinition(838, "Amaurot"), + new TerritoryDefinition(167, "Amdapor Keep"), + new TerritoryDefinition(189, "Amdapor Keep"), + new TerritoryDefinition(396, "Amdapor Keep"), + new TerritoryDefinition(721, "Amdapor Keep"), + new TerritoryDefinition(815, "Amh Araeng"), + new TerritoryDefinition(860, "Amh Araeng"), + new TerritoryDefinition(872, "Amh Araeng"), + new TerritoryDefinition(898, "Anamnesis Anyder"), + new TerritoryDefinition(918, "Anamnesis Anyder"), + new TerritoryDefinition(990, "Andron"), + new TerritoryDefinition(1179, "Another Aloalo Island"), + new TerritoryDefinition(1180, "Another Aloalo Island"), + new TerritoryDefinition(1155, "Another Mount Rokkon"), + new TerritoryDefinition(1156, "Another Mount Rokkon"), + new TerritoryDefinition(1075, "Another Sil'dihn Subterrane"), + new TerritoryDefinition(1076, "Another Sil'dihn Subterrane"), + new TerritoryDefinition(1153, "Ascension"), + new TerritoryDefinition(1154, "Ascension"), + new TerritoryDefinition(903, "Ashfall"), + new TerritoryDefinition(907, "Ashfall"), + new TerritoryDefinition(729, "Astragalos"), + new TerritoryDefinition(852, "Atlas Peak"), + new TerritoryDefinition(856, "Atlas Peak"), + new TerritoryDefinition(172, "Aurum Vale"), + new TerritoryDefinition(402, "Azys Lla"), + new TerritoryDefinition(459, "Azys Lla"), + new TerritoryDefinition(1114, "Baelsar's Wall"), + new TerritoryDefinition(714, "Bardam's Mettle"), + new TerritoryDefinition(1143, "Bardam's Mettle"), + new TerritoryDefinition(1216, "Bardam's Mettle"), + new TerritoryDefinition(1013, "Beyond the Stars"), + new TerritoryDefinition(1026, "Beyond the Stars"), + new TerritoryDefinition(1229, "Blasting Ring"), + new TerritoryDefinition(1230, "Blasting Ring"), + new TerritoryDefinition(796, "Blue Sky"), + new TerritoryDefinition(1165, "Blunderville"), + new TerritoryDefinition(1197, "Blunderville Square"), + new TerritoryDefinition(629, "Bokairo Inn"), + new TerritoryDefinition(292, "Bowl of Embers"), + new TerritoryDefinition(295, "Bowl of Embers"), + new TerritoryDefinition(592, "Bowl of Embers"), + new TerritoryDefinition(1045, "Bowl of Embers"), + new TerritoryDefinition(920, "Bozjan Southern Front"), + new TerritoryDefinition(362, "Brayflox's Longstop"), + new TerritoryDefinition(1041, "Brayflox's Longstop"), + new TerritoryDefinition(1215, "Brayflox's Longstop"), + new TerritoryDefinition(1268, "Break Room"), + new TerritoryDefinition(581, "Breath of the Creator"), + new TerritoryDefinition(585, "Breath of the Creator"), + new TerritoryDefinition(944, "Bygone Gaol"), + new TerritoryDefinition(948, "Bygone Gaol"), + new TerritoryDefinition(376, "Carteneau Flats: Borderland Ruins"), + new TerritoryDefinition(502, "Carteneau Flats: Borderland Ruins"), + new TerritoryDefinition(633, "Carteneau Flats: Borderland Ruins"), + new TerritoryDefinition(977, "Carteneau Flats: Borderland Ruins"), + new TerritoryDefinition(1273, "Carteneau Flats: Borderland Ruins"), + new TerritoryDefinition(1145, "Castrum Abania"), + new TerritoryDefinition(778, "Castrum Fluminis"), + new TerritoryDefinition(779, "Castrum Fluminis"), + new TerritoryDefinition(786, "Castrum Fluminis"), + new TerritoryDefinition(934, "Castrum Marinum Drydocks"), + new TerritoryDefinition(935, "Castrum Marinum Drydocks"), + new TerritoryDefinition(967, "Castrum Marinum Drydocks"), + new TerritoryDefinition(1043, "Castrum Meridianum"), + new TerritoryDefinition(1209, "Cenote Ja Ja Gural"), + new TerritoryDefinition(507, "Central Azys Lla"), + new TerritoryDefinition(357, "Central Decks"), + new TerritoryDefinition(382, "Central Decks"), + new TerritoryDefinition(148, "Central Shroud"), + new TerritoryDefinition(190, "Central Shroud"), + new TerritoryDefinition(219, "Central Shroud"), + new TerritoryDefinition(225, "Central Shroud"), + new TerritoryDefinition(226, "Central Shroud"), + new TerritoryDefinition(227, "Central Shroud"), + new TerritoryDefinition(230, "Central Shroud"), + new TerritoryDefinition(233, "Central Shroud"), + new TerritoryDefinition(237, "Central Shroud"), + new TerritoryDefinition(239, "Central Shroud"), + new TerritoryDefinition(319, "Central Shroud"), + new TerritoryDefinition(320, "Central Shroud"), + new TerritoryDefinition(1015, "Central Shroud"), + new TerritoryDefinition(141, "Central Thanalan"), + new TerritoryDefinition(216, "Central Thanalan"), + new TerritoryDefinition(248, "Central Thanalan"), + new TerritoryDefinition(253, "Central Thanalan"), + new TerritoryDefinition(258, "Central Thanalan"), + new TerritoryDefinition(270, "Central Thanalan"), + new TerritoryDefinition(271, "Central Thanalan"), + new TerritoryDefinition(314, "Central Thanalan"), + new TerritoryDefinition(1235, "Central Thanalan"), + new TerritoryDefinition(388, "Chocobo Square"), + new TerritoryDefinition(389, "Chocobo Square"), + new TerritoryDefinition(390, "Chocobo Square"), + new TerritoryDefinition(391, "Chocobo Square"), + new TerritoryDefinition(417, "Chocobo Square"), + new TerritoryDefinition(506, "Chocobo Square"), + new TerritoryDefinition(589, "Chocobo Square"), + new TerritoryDefinition(590, "Chocobo Square"), + new TerritoryDefinition(591, "Chocobo Square"), + new TerritoryDefinition(911, "Cid's Memory"), + new TerritoryDefinition(897, "Cinder Drift"), + new TerritoryDefinition(912, "Cinder Drift"), + new TerritoryDefinition(429, "Cloud Nine"), + new TerritoryDefinition(1034, "Cloud Nine"), + new TerritoryDefinition(1060, "Cloud Nine"), + new TerritoryDefinition(155, "Coerthas Central Highlands"), + new TerritoryDefinition(223, "Coerthas Central Highlands"), + new TerritoryDefinition(298, "Coerthas Central Highlands"), + new TerritoryDefinition(301, "Coerthas Central Highlands"), + new TerritoryDefinition(302, "Coerthas Central Highlands"), + new TerritoryDefinition(304, "Coerthas Central Highlands"), + new TerritoryDefinition(313, "Coerthas Central Highlands"), + new TerritoryDefinition(316, "Coerthas Central Highlands"), + new TerritoryDefinition(322, "Coerthas Central Highlands"), + new TerritoryDefinition(468, "Coerthas Central Highlands"), + new TerritoryDefinition(469, "Coerthas Central Highlands"), + new TerritoryDefinition(475, "Coerthas Central Highlands"), + new TerritoryDefinition(487, "Coerthas Central Highlands"), + new TerritoryDefinition(488, "Coerthas Central Highlands"), + new TerritoryDefinition(496, "Coerthas Central Highlands"), + new TerritoryDefinition(500, "Coerthas Central Highlands"), + new TerritoryDefinition(533, "Coerthas Central Highlands"), + new TerritoryDefinition(699, "Coerthas Central Highlands"), + new TerritoryDefinition(397, "Coerthas Western Highlands"), + new TerritoryDefinition(467, "Coerthas Western Highlands"), + new TerritoryDefinition(470, "Coerthas Western Highlands"), + new TerritoryDefinition(472, "Coerthas Western Highlands"), + new TerritoryDefinition(477, "Coerthas Western Highlands"), + new TerritoryDefinition(479, "Coerthas Western Highlands"), + new TerritoryDefinition(489, "Coerthas Western Highlands"), + new TerritoryDefinition(493, "Coerthas Western Highlands"), + new TerritoryDefinition(497, "Coerthas Western Highlands"), + new TerritoryDefinition(498, "Coerthas Western Highlands"), + new TerritoryDefinition(709, "Coerthas Western Highlands"), + new TerritoryDefinition(866, "Coerthas Western Highlands"), + new TerritoryDefinition(198, "Command Room"), + new TerritoryDefinition(984, "Company Workshop - Empyreum"), + new TerritoryDefinition(423, "Company Workshop - Mist"), + new TerritoryDefinition(653, "Company Workshop - Shirogane"), + new TerritoryDefinition(424, "Company Workshop - The Goblet"), + new TerritoryDefinition(425, "Company Workshop - The Lavender Beds"), + new TerritoryDefinition(576, "Containment Bay P1T6"), + new TerritoryDefinition(577, "Containment Bay P1T6"), + new TerritoryDefinition(517, "Containment Bay S1T7"), + new TerritoryDefinition(524, "Containment Bay S1T7"), + new TerritoryDefinition(637, "Containment Bay Z1T9"), + new TerritoryDefinition(638, "Containment Bay Z1T9"), + new TerritoryDefinition(1299, "Containment Complex 10-29"), + new TerritoryDefinition(349, "Copperbell Mines"), + new TerritoryDefinition(1038, "Copperbell Mines"), + new TerritoryDefinition(1020, "Cutter's Cry"), + new TerritoryDefinition(1303, "Cutter's Cry"), + new TerritoryDefinition(355, "Dalamud's Shadow"), + new TerritoryDefinition(380, "Dalamud's Shadow"), + new TerritoryDefinition(704, "Dalamud's Shadow"), + new TerritoryDefinition(691, "Deltascape V1.0"), + new TerritoryDefinition(695, "Deltascape V1.0"), + new TerritoryDefinition(692, "Deltascape V2.0"), + new TerritoryDefinition(696, "Deltascape V2.0"), + new TerritoryDefinition(693, "Deltascape V3.0"), + new TerritoryDefinition(697, "Deltascape V3.0"), + new TerritoryDefinition(694, "Deltascape V4.0"), + new TerritoryDefinition(698, "Deltascape V4.0"), + new TerritoryDefinition(936, "Delubrum Reginae"), + new TerritoryDefinition(937, "Delubrum Reginae"), + new TerritoryDefinition(1260, "Demolition Site"), + new TerritoryDefinition(1261, "Demolition Site"), + new TerritoryDefinition(1276, "Demolition Site"), + new TerritoryDefinition(821, "Dohn Mheg"), + new TerritoryDefinition(1144, "Doma Castle"), + new TerritoryDefinition(1234, "Dreamlike Palace"), + new TerritoryDefinition(627, "Dun Scaith"), + new TerritoryDefinition(434, "Dusk Vigil"), + new TerritoryDefinition(1021, "Dusk Vigil"), + new TerritoryDefinition(171, "Dzemael Darkhold"), + new TerritoryDefinition(1171, "Earthen Sky Hideout"), + new TerritoryDefinition(152, "East Shroud"), + new TerritoryDefinition(191, "East Shroud"), + new TerritoryDefinition(234, "East Shroud"), + new TerritoryDefinition(277, "East Shroud"), + new TerritoryDefinition(289, "East Shroud"), + new TerritoryDefinition(290, "East Shroud"), + new TerritoryDefinition(303, "East Shroud"), + new TerritoryDefinition(839, "East Shroud"), + new TerritoryDefinition(137, "Eastern La Noscea"), + new TerritoryDefinition(310, "Eastern La Noscea"), + new TerritoryDefinition(311, "Eastern La Noscea"), + new TerritoryDefinition(327, "Eastern La Noscea"), + new TerritoryDefinition(408, "Eastern La Noscea"), + new TerritoryDefinition(411, "Eastern La Noscea"), + new TerritoryDefinition(414, "Eastern La Noscea"), + new TerritoryDefinition(471, "Eastern La Noscea"), + new TerritoryDefinition(867, "Eastern La Noscea"), + new TerritoryDefinition(145, "Eastern Thanalan"), + new TerritoryDefinition(256, "Eastern Thanalan"), + new TerritoryDefinition(257, "Eastern Thanalan"), + new TerritoryDefinition(266, "Eastern Thanalan"), + new TerritoryDefinition(268, "Eastern Thanalan"), + new TerritoryDefinition(275, "Eastern Thanalan"), + new TerritoryDefinition(465, "Eastern Thanalan"), + new TerritoryDefinition(494, "Eastern Thanalan"), + new TerritoryDefinition(668, "Eastern Thanalan"), + new TerritoryDefinition(961, "Elpis"), + new TerritoryDefinition(1014, "Elpis"), + new TerritoryDefinition(1073, "Elysion"), + new TerritoryDefinition(719, "Emanation"), + new TerritoryDefinition(720, "Emanation"), + new TerritoryDefinition(979, "Empyreum"), + new TerritoryDefinition(829, "Eorzean Alliance Headquarters"), + new TerritoryDefinition(338, "Eorzean Subterrane"), + new TerritoryDefinition(1161, "Estinien's Chambers"), + new TerritoryDefinition(820, "Eulmore"), + new TerritoryDefinition(863, "Eulmore"), + new TerritoryDefinition(1118, "Euphrosyne"), + new TerritoryDefinition(732, "Eureka Anemos"), + new TerritoryDefinition(827, "Eureka Hydatos"), + new TerritoryDefinition(1099, "Eureka Orthos"), + new TerritoryDefinition(1100, "Eureka Orthos"), + new TerritoryDefinition(1101, "Eureka Orthos"), + new TerritoryDefinition(1102, "Eureka Orthos"), + new TerritoryDefinition(1103, "Eureka Orthos"), + new TerritoryDefinition(1104, "Eureka Orthos"), + new TerritoryDefinition(1105, "Eureka Orthos"), + new TerritoryDefinition(1106, "Eureka Orthos"), + new TerritoryDefinition(1107, "Eureka Orthos"), + new TerritoryDefinition(1108, "Eureka Orthos"), + new TerritoryDefinition(1124, "Eureka Orthos"), + new TerritoryDefinition(763, "Eureka Pagos"), + new TerritoryDefinition(795, "Eureka Pyros"), + new TerritoryDefinition(895, "Excavation Tunnels"), + new TerritoryDefinition(580, "Eyes of the Creator"), + new TerritoryDefinition(584, "Eyes of the Creator"), + new TerritoryDefinition(535, "Flame Barracks"), + new TerritoryDefinition(433, "Fortemps Manor"), + new TerritoryDefinition(418, "Foundation"), + new TerritoryDefinition(458, "Foundation"), + new TerritoryDefinition(700, "Foundation"), + new TerritoryDefinition(611, "Frondale's Home for Friendless Foundlings"), + new TerritoryDefinition(921, "Frondale's Home for Friendless Foundlings"), + new TerritoryDefinition(950, "G-Savior Deck"), + new TerritoryDefinition(951, "G-Savior Deck"), + new TerritoryDefinition(991, "G-Savior Deck"), + new TerritoryDefinition(915, "Gangos"), + new TerritoryDefinition(958, "Garlemald"), + new TerritoryDefinition(1011, "Garlemald"), + new TerritoryDefinition(1120, "Garlemald"), + new TerritoryDefinition(905, "Great Glacier"), + new TerritoryDefinition(909, "Great Glacier"), + new TerritoryDefinition(1224, "Greenroom"), + new TerritoryDefinition(366, "Griffin Crossing"), + new TerritoryDefinition(1256, "Groovy Ring"), + new TerritoryDefinition(1257, "Groovy Ring"), + new TerritoryDefinition(142, "Halatali"), + new TerritoryDefinition(360, "Halatali"), + new TerritoryDefinition(460, "Halatali"), + new TerritoryDefinition(1245, "Halatali"), + new TerritoryDefinition(276, "Hall of Summoning"), + new TerritoryDefinition(369, "Hall of the Bestiarii"), + new TerritoryDefinition(1255, "Hall of the Unbound"), + new TerritoryDefinition(350, "Haukke Manor"), + new TerritoryDefinition(1040, "Haukke Manor"), + new TerritoryDefinition(571, "Haunted Manor"), + new TerritoryDefinition(809, "Haunted Manor"), + new TerritoryDefinition(1305, "Haunted Manor"), + new TerritoryDefinition(582, "Heart of the Creator"), + new TerritoryDefinition(586, "Heart of the Creator"), + new TerritoryDefinition(588, "Heart of the Creator"), + new TerritoryDefinition(210, "Heart of the Sworn"), + new TerritoryDefinition(770, "Heaven-on-High"), + new TerritoryDefinition(771, "Heaven-on-High"), + new TerritoryDefinition(772, "Heaven-on-High"), + new TerritoryDefinition(773, "Heaven-on-High"), + new TerritoryDefinition(774, "Heaven-on-High"), + new TerritoryDefinition(775, "Heaven-on-High"), + new TerritoryDefinition(780, "Heaven-on-High"), + new TerritoryDefinition(782, "Heaven-on-High"), + new TerritoryDefinition(783, "Heaven-on-High"), + new TerritoryDefinition(784, "Heaven-on-High"), + new TerritoryDefinition(785, "Heaven-on-High"), + new TerritoryDefinition(810, "Hells' Kier"), + new TerritoryDefinition(811, "Hells' Kier"), + new TerritoryDefinition(742, "Hells' Lid"), + new TerritoryDefinition(1191, "Heritage Found"), + new TerritoryDefinition(791, "Hidden Gorge"), + new TerritoryDefinition(837, "Holminster Switch"), + new TerritoryDefinition(361, "Hullbreaker Isle"), + new TerritoryDefinition(490, "Hullbreaker Isle"), + new TerritoryDefinition(557, "Hullbreaker Isle"), + new TerritoryDefinition(1262, "Hunter's Ring"), + new TerritoryDefinition(1263, "Hunter's Ring"), + new TerritoryDefinition(246, "IC-04 Main Bridge"), + new TerritoryDefinition(193, "IC-06 Central Decks"), + new TerritoryDefinition(195, "IC-06 Main Bridge"), + new TerritoryDefinition(194, "IC-06 Regeneration Grid"), + new TerritoryDefinition(478, "Idyllshire"), + new TerritoryDefinition(1167, "Ihuykatumu"), + new TerritoryDefinition(816, "Il Mheg"), + new TerritoryDefinition(869, "Il Mheg"), + new TerritoryDefinition(999, "Ingleside Apartment"), + new TerritoryDefinition(985, "Ingleside Apartment Lobby"), + new TerritoryDefinition(395, "Intercessory"), + new TerritoryDefinition(1202, "Interphos"), + new TerritoryDefinition(1221, "Interphos"), + new TerritoryDefinition(1243, "Interphos"), + new TerritoryDefinition(1248, "Jeuno: The First Walk"), + new TerritoryDefinition(1125, "Khadga"), + new TerritoryDefinition(1218, "Khadga"), + new TerritoryDefinition(814, "Kholusia"), + new TerritoryDefinition(864, "Kholusia"), + new TerritoryDefinition(870, "Kholusia"), + new TerritoryDefinition(744, "Kienkan"), + new TerritoryDefinition(655, "Kobai Goten Apartment"), + new TerritoryDefinition(654, "Kobai Goten Apartment Lobby"), + new TerritoryDefinition(1188, "Kozama'uka"), + new TerritoryDefinition(974, "Ktisis Hyperboreia"), + new TerritoryDefinition(628, "Kugane"), + new TerritoryDefinition(664, "Kugane"), + new TerritoryDefinition(665, "Kugane"), + new TerritoryDefinition(667, "Kugane"), + new TerritoryDefinition(710, "Kugane"), + new TerritoryDefinition(662, "Kugane Castle"), + new TerritoryDefinition(353, "Kugane Ohashi"), + new TerritoryDefinition(806, "Kugane Ohashi"), + new TerritoryDefinition(174, "Labyrinth of the Ancients"), + new TerritoryDefinition(956, "Labyrinthos"), + new TerritoryDefinition(813, "Lakeland"), + new TerritoryDefinition(861, "Lakeland"), + new TerritoryDefinition(862, "Lakeland"), + new TerritoryDefinition(877, "Lakeland"), + new TerritoryDefinition(1097, "Lapis Manalis"), + new TerritoryDefinition(1119, "Lapis Manalis"), + new TerritoryDefinition(943, "Laxan Loft"), + new TerritoryDefinition(947, "Laxan Loft"), + new TerritoryDefinition(971, "Lemures Headquarters"), + new TerritoryDefinition(568, "Leofard's Chambers"), + new TerritoryDefinition(609, "Lily Hills Apartment"), + new TerritoryDefinition(574, "Lily Hills Apartment Lobby"), + new TerritoryDefinition(887, "Liminal Space"), + new TerritoryDefinition(181, "Limsa Lominsa"), + new TerritoryDefinition(129, "Limsa Lominsa Lower Decks"), + new TerritoryDefinition(404, "Limsa Lominsa Lower Decks"), + new TerritoryDefinition(128, "Limsa Lominsa Upper Decks"), + new TerritoryDefinition(409, "Limsa Lominsa Upper Decks"), + new TerritoryDefinition(474, "Limsa Lominsa Upper Decks"), + new TerritoryDefinition(1192, "Living Memory"), + new TerritoryDefinition(205, "Lotus Stand"), + new TerritoryDefinition(1227, "Lovely Lovering"), + new TerritoryDefinition(1228, "Lovely Lovering"), + new TerritoryDefinition(242, "Lower Aetheroacoustic Exploratory Site"), + new TerritoryDefinition(1264, "Lower Jeuno"), + new TerritoryDefinition(1265, "Lower Jeuno"), + new TerritoryDefinition(135, "Lower La Noscea"), + new TerritoryDefinition(222, "Lower La Noscea"), + new TerritoryDefinition(249, "Lower La Noscea"), + new TerritoryDefinition(262, "Lower La Noscea"), + new TerritoryDefinition(264, "Lower La Noscea"), + new TerritoryDefinition(265, "Lower La Noscea"), + new TerritoryDefinition(279, "Lower La Noscea"), + new TerritoryDefinition(287, "Lower La Noscea"), + new TerritoryDefinition(307, "Lower La Noscea"), + new TerritoryDefinition(415, "Lower La Noscea"), + new TerritoryDefinition(484, "Lower La Noscea"), + new TerritoryDefinition(495, "Lower La Noscea"), + new TerritoryDefinition(889, "Lyhe Mheg"), + new TerritoryDefinition(890, "Lyhe Mheg"), + new TerritoryDefinition(891, "Lyhe Mheg"), + new TerritoryDefinition(892, "Lyhe Mheg"), + new TerritoryDefinition(894, "Lyhe Mheg"), + new TerritoryDefinition(536, "Maelstrom Barracks"), + new TerritoryDefinition(1010, "Magna Glacies"), + new TerritoryDefinition(1012, "Magna Glacies"), + new TerritoryDefinition(370, "Main Bridge"), + new TerritoryDefinition(1206, "Main Deck"), + new TerritoryDefinition(1277, "Main Deck"), + new TerritoryDefinition(987, "Main Hall"), + new TerritoryDefinition(836, "Malikah's Well"), + new TerritoryDefinition(1233, "Manor Basement"), + new TerritoryDefinition(959, "Mare Lamentorum"), + new TerritoryDefinition(463, "Matoya's Cave"), + new TerritoryDefinition(933, "Matoya's Relict"), + new TerritoryDefinition(968, "Medias Res"), + new TerritoryDefinition(1078, "Meghaduta Guest Chambers"), + new TerritoryDefinition(134, "Middle La Noscea"), + new TerritoryDefinition(214, "Middle La Noscea"), + new TerritoryDefinition(252, "Middle La Noscea"), + new TerritoryDefinition(272, "Middle La Noscea"), + new TerritoryDefinition(285, "Middle La Noscea"), + new TerritoryDefinition(136, "Mist"), + new TerritoryDefinition(339, "Mist"), + new TerritoryDefinition(177, "Mizzenmast Inn"), + new TerritoryDefinition(156, "Mor Dhona"), + new TerritoryDefinition(299, "Mor Dhona"), + new TerritoryDefinition(300, "Mor Dhona"), + new TerritoryDefinition(305, "Mor Dhona"), + new TerritoryDefinition(308, "Mor Dhona"), + new TerritoryDefinition(309, "Mor Dhona"), + new TerritoryDefinition(315, "Mor Dhona"), + new TerritoryDefinition(326, "Mor Dhona"), + new TerritoryDefinition(335, "Mor Dhona"), + new TerritoryDefinition(379, "Mor Dhona"), + new TerritoryDefinition(480, "Mor Dhona"), + new TerritoryDefinition(672, "Mor Dhona"), + new TerritoryDefinition(176, "Mordion Gaol"), + new TerritoryDefinition(728, "Mordion Gaol"), + new TerritoryDefinition(1095, "Mount Ordeals"), + new TerritoryDefinition(1096, "Mount Ordeals"), + new TerritoryDefinition(1137, "Mount Rokkon"), + new TerritoryDefinition(822, "Mt. Gulg"), + new TerritoryDefinition(420, "Neverreap"), + new TerritoryDefinition(132, "New Gridania"), + new TerritoryDefinition(183, "New Gridania"), + new TerritoryDefinition(154, "North Shroud"), + new TerritoryDefinition(228, "North Shroud"), + new TerritoryDefinition(240, "North Shroud"), + new TerritoryDefinition(321, "North Shroud"), + new TerritoryDefinition(324, "North Shroud"), + new TerritoryDefinition(147, "Northern Thanalan"), + new TerritoryDefinition(410, "Northern Thanalan"), + new TerritoryDefinition(483, "Northern Thanalan"), + new TerritoryDefinition(133, "Old Gridania"), + new TerritoryDefinition(238, "Old Gridania"), + new TerritoryDefinition(865, "Old Gridania"), + new TerritoryDefinition(962, "Old Sharlayan"), + new TerritoryDefinition(636, "Omega Control"), + new TerritoryDefinition(888, "Onsal Hakair"), + new TerritoryDefinition(1208, "Origenics"), + new TerritoryDefinition(180, "Outer La Noscea"), + new TerritoryDefinition(325, "Outer La Noscea"), + new TerritoryDefinition(486, "Outer La Noscea"), + new TerritoryDefinition(938, "Paglth'an"), + new TerritoryDefinition(1291, "Phaenna"), + new TerritoryDefinition(1269, "Phantom Village"), + new TerritoryDefinition(1278, "Phantom Village"), + new TerritoryDefinition(160, "Pharos Sirius"), + new TerritoryDefinition(510, "Pharos Sirius"), + new TerritoryDefinition(1280, "Pilgrim's Traverse"), + new TerritoryDefinition(1281, "Pilgrim's Traverse"), + new TerritoryDefinition(1282, "Pilgrim's Traverse"), + new TerritoryDefinition(1283, "Pilgrim's Traverse"), + new TerritoryDefinition(1284, "Pilgrim's Traverse"), + new TerritoryDefinition(1285, "Pilgrim's Traverse"), + new TerritoryDefinition(1286, "Pilgrim's Traverse"), + new TerritoryDefinition(1287, "Pilgrim's Traverse"), + new TerritoryDefinition(1288, "Pilgrim's Traverse"), + new TerritoryDefinition(1289, "Pilgrim's Traverse"), + new TerritoryDefinition(1290, "Pilgrim's Traverse"), + new TerritoryDefinition(1311, "Pilgrim's Traverse"), + new TerritoryDefinition(1333, "Pilgrim's Traverse"), + new TerritoryDefinition(348, "Porta Decumana"), + new TerritoryDefinition(1048, "Porta Decumana"), + new TerritoryDefinition(983, "Private Chambers - Empyreum"), + new TerritoryDefinition(384, "Private Chambers - Mist"), + new TerritoryDefinition(652, "Private Chambers - Shirogane"), + new TerritoryDefinition(386, "Private Chambers - The Goblet"), + new TerritoryDefinition(385, "Private Chambers - The Lavender Beds"), + new TerritoryDefinition(980, "Private Cottage - Empyreum"), + new TerritoryDefinition(282, "Private Cottage - Mist"), + new TerritoryDefinition(649, "Private Cottage - Shirogane"), + new TerritoryDefinition(345, "Private Cottage - The Goblet"), + new TerritoryDefinition(342, "Private Cottage - The Lavender Beds"), + new TerritoryDefinition(981, "Private House - Empyreum"), + new TerritoryDefinition(283, "Private House - Mist"), + new TerritoryDefinition(650, "Private House - Shirogane"), + new TerritoryDefinition(346, "Private House - The Goblet"), + new TerritoryDefinition(343, "Private House - The Lavender Beds"), + new TerritoryDefinition(982, "Private Mansion - Empyreum"), + new TerritoryDefinition(284, "Private Mansion - Mist"), + new TerritoryDefinition(651, "Private Mansion - Shirogane"), + new TerritoryDefinition(347, "Private Mansion - The Goblet"), + new TerritoryDefinition(344, "Private Mansion - The Lavender Beds"), + new TerritoryDefinition(1031, "Propylaion"), + new TerritoryDefinition(798, "Psiscape V1.0"), + new TerritoryDefinition(802, "Psiscape V1.0"), + new TerritoryDefinition(799, "Psiscape V2.0"), + new TerritoryDefinition(803, "Psiscape V2.0"), + new TerritoryDefinition(963, "Radz-at-Han"), + new TerritoryDefinition(245, "Ragnarok Central Core"), + new TerritoryDefinition(244, "Ragnarok Drive Cylinder"), + new TerritoryDefinition(247, "Ragnarok Main Bridge"), + new TerritoryDefinition(1258, "Rebel Ring"), + new TerritoryDefinition(1259, "Rebel Ring"), + new TerritoryDefinition(1270, "Recollection"), + new TerritoryDefinition(1271, "Recollection"), + new TerritoryDefinition(1275, "Recollection"), + new TerritoryDefinition(764, "Reisen Temple"), + new TerritoryDefinition(781, "Reisen Temple Road"), + new TerritoryDefinition(1057, "Restricted Archives"), + new TerritoryDefinition(635, "Rhalgr's Reach"), + new TerritoryDefinition(659, "Rhalgr's Reach"), + new TerritoryDefinition(286, "Rhotano Sea"), + new TerritoryDefinition(288, "Rhotano Sea"), + new TerritoryDefinition(407, "Rhotano Sea"), + new TerritoryDefinition(708, "Rhotano Sea"), + new TerritoryDefinition(737, "Royal Palace"), + new TerritoryDefinition(639, "Ruby Bazaar Offices"), + new TerritoryDefinition(440, "Ruling Chamber"), + new TerritoryDefinition(456, "Ruling Chamber"), + new TerritoryDefinition(462, "Sacrificial Chamber"), + new TerritoryDefinition(427, "Saint Endalim's Scholasticate"), + new TerritoryDefinition(511, "Saint Mocianne's Arboretum"), + new TerritoryDefinition(788, "Saint Mocianne's Arboretum"), + new TerritoryDefinition(1022, "Saint Mocianne's Arboretum"), + new TerritoryDefinition(1304, "San d'Oria: The Second Walk"), + new TerritoryDefinition(392, "Sanctum of the Twelve"), + new TerritoryDefinition(393, "Sanctum of the Twelve"), + new TerritoryDefinition(741, "Sanctum of the Twelve"), + new TerritoryDefinition(387, "Sastasha"), + new TerritoryDefinition(1016, "Sastasha"), + new TerritoryDefinition(1036, "Sastasha"), + new TerritoryDefinition(1225, "Scratching Ring"), + new TerritoryDefinition(1226, "Scratching Ring"), + new TerritoryDefinition(431, "Seal Rock"), + new TerritoryDefinition(701, "Seal Rock"), + new TerritoryDefinition(204, "Seat of the First Bow"), + new TerritoryDefinition(428, "Seat of the Lord Commander"), + new TerritoryDefinition(1160, "Senatus"), + new TerritoryDefinition(1190, "Shaaloani"), + new TerritoryDefinition(1244, "Shaaloani"), + new TerritoryDefinition(641, "Shirogane"), + new TerritoryDefinition(616, "Shisui of the Violet Tides"), + new TerritoryDefinition(748, "Sigmascape V1.0"), + new TerritoryDefinition(752, "Sigmascape V1.0"), + new TerritoryDefinition(749, "Sigmascape V2.0"), + new TerritoryDefinition(753, "Sigmascape V2.0"), + new TerritoryDefinition(750, "Sigmascape V3.0"), + new TerritoryDefinition(754, "Sigmascape V3.0"), + new TerritoryDefinition(751, "Sigmascape V4.0"), + new TerritoryDefinition(755, "Sigmascape V4.0"), + new TerritoryDefinition(437, "Singularity Reactor"), + new TerritoryDefinition(448, "Singularity Reactor"), + new TerritoryDefinition(1237, "Sinus Ardorum"), + new TerritoryDefinition(1222, "Skydeep Cenote Inner Chamber"), + new TerritoryDefinition(976, "Smileton"), + new TerritoryDefinition(1094, "Sneaky Hollow"), + new TerritoryDefinition(1062, "Snowcloak"), + new TerritoryDefinition(617, "Sohm Al"), + new TerritoryDefinition(673, "Sohm Al"), + new TerritoryDefinition(1064, "Sohm Al"), + new TerritoryDefinition(1112, "Sohr Khai"), + new TerritoryDefinition(1186, "Solution Nine"), + new TerritoryDefinition(1213, "Solution Nine"), + new TerritoryDefinition(583, "Soul of the Creator"), + new TerritoryDefinition(587, "Soul of the Creator"), + new TerritoryDefinition(1252, "South Horn"), + new TerritoryDefinition(153, "South Shroud"), + new TerritoryDefinition(192, "South Shroud"), + new TerritoryDefinition(220, "South Shroud"), + new TerritoryDefinition(229, "South Shroud"), + new TerritoryDefinition(231, "South Shroud"), + new TerritoryDefinition(232, "South Shroud"), + new TerritoryDefinition(235, "South Shroud"), + new TerritoryDefinition(236, "South Shroud"), + new TerritoryDefinition(291, "South Shroud"), + new TerritoryDefinition(317, "South Shroud"), + new TerritoryDefinition(394, "South Shroud"), + new TerritoryDefinition(473, "South Shroud"), + new TerritoryDefinition(146, "Southern Thanalan"), + new TerritoryDefinition(260, "Southern Thanalan"), + new TerritoryDefinition(261, "Southern Thanalan"), + new TerritoryDefinition(306, "Southern Thanalan"), + new TerritoryDefinition(312, "Southern Thanalan"), + new TerritoryDefinition(318, "Southern Thanalan"), + new TerritoryDefinition(323, "Southern Thanalan"), + new TerritoryDefinition(491, "Southern Thanalan"), + new TerritoryDefinition(669, "Southern Thanalan"), + new TerritoryDefinition(1236, "Southern Thanalan"), + new TerritoryDefinition(942, "Sphere of Naught"), + new TerritoryDefinition(946, "Sphere of Naught"), + new TerritoryDefinition(1241, "Sphere of Naught"), + new TerritoryDefinition(1247, "Starlight Stalls"), + new TerritoryDefinition(1253, "Starlight Stalls"), + new TerritoryDefinition(1309, "Starlight Stalls"), + new TerritoryDefinition(559, "Steps of Faith"), + new TerritoryDefinition(566, "Steps of Faith"), + new TerritoryDefinition(569, "Steps of Faith"), + new TerritoryDefinition(1068, "Steps of Faith"), + new TerritoryDefinition(365, "Stone Vigil"), + new TerritoryDefinition(1042, "Stone Vigil"), + new TerritoryDefinition(1071, "Storm's Crown"), + new TerritoryDefinition(1072, "Storm's Crown"), + new TerritoryDefinition(1092, "Storm's Crown"), + new TerritoryDefinition(1001, "Strategy Room"), + new TerritoryDefinition(1204, "Strayborough"), + new TerritoryDefinition(1087, "Stygian Insenescence Cells"), + new TerritoryDefinition(1088, "Stygian Insenescence Cells"), + new TerritoryDefinition(1093, "Stygian Insenescence Cells"), + new TerritoryDefinition(610, "Sultana's Breath Apartment"), + new TerritoryDefinition(575, "Sultana's Breath Apartment Lobby"), + new TerritoryDefinition(1200, "Summit of Everkeep"), + new TerritoryDefinition(1201, "Summit of Everkeep"), + new TerritoryDefinition(1220, "Summit of Everkeep"), + new TerritoryDefinition(1170, "Sunperch"), + new TerritoryDefinition(1210, "Sunperch"), + new TerritoryDefinition(1098, "Sylphstep"), + new TerritoryDefinition(372, "Syrcus Tower"), + new TerritoryDefinition(1203, "Tender Valley"), + new TerritoryDefinition(919, "Terncliff"), + new TerritoryDefinition(925, "Terncliff Bay"), + new TerritoryDefinition(926, "Terncliff Bay"), + new TerritoryDefinition(1178, "Thaleia"), + new TerritoryDefinition(1182, "Thaleia"), + new TerritoryDefinition(957, "Thavnair"), + new TerritoryDefinition(900, "The Endeavor"), + new TerritoryDefinition(1163, "The Endeavor"), + new TerritoryDefinition(680, "The Misery"), + new TerritoryDefinition(736, "The Prima Vista Bridge"), + new TerritoryDefinition(735, "The Prima Vista Tiring Room"), + new TerritoryDefinition(828, "The Prima Vista Tiring Room"), + new TerritoryDefinition(1168, "The Abyssal Fracture"), + new TerritoryDefinition(1169, "The Abyssal Fracture"), + new TerritoryDefinition(1181, "The Abyssal Fracture"), + new TerritoryDefinition(1065, "The Aery"), + new TerritoryDefinition(1126, "The Aetherfont"), + new TerritoryDefinition(1177, "The Aetherfont"), + new TerritoryDefinition(1147, "The Aetherial Slough"), + new TerritoryDefinition(1148, "The Aetherial Slough"), + new TerritoryDefinition(1295, "The Ageless Necropolis"), + new TerritoryDefinition(1296, "The Ageless Necropolis"), + new TerritoryDefinition(1312, "The Ageless Necropolis"), + new TerritoryDefinition(978, "The Aitiascope"), + new TerritoryDefinition(1079, "The Aitiascope"), + new TerritoryDefinition(1111, "The Antitower"), + new TerritoryDefinition(558, "The Aquapolis"), + new TerritoryDefinition(444, "The Arm of the Father"), + new TerritoryDefinition(451, "The Arm of the Father"), + new TerritoryDefinition(522, "The Arm of the Son"), + new TerritoryDefinition(531, "The Arm of the Son"), + new TerritoryDefinition(622, "The Azim Steppe"), + new TerritoryDefinition(688, "The Azim Steppe"), + new TerritoryDefinition(713, "The Azim Steppe"), + new TerritoryDefinition(718, "The Azim Steppe"), + new TerritoryDefinition(723, "The Azim Steppe"), + new TerritoryDefinition(797, "The Azim Steppe"), + new TerritoryDefinition(1207, "The Backroom"), + new TerritoryDefinition(579, "The Battlehall"), + new TerritoryDefinition(940, "The Battlehall"), + new TerritoryDefinition(941, "The Battlehall"), + new TerritoryDefinition(1293, "The Bayside Battleground"), + new TerritoryDefinition(1294, "The Bayside Battleground"), + new TerritoryDefinition(733, "The Binding Coil of Bahamut"), + new TerritoryDefinition(674, "The Blessed Treasury"), + new TerritoryDefinition(677, "The Blessed Treasury"), + new TerritoryDefinition(445, "The Burden of the Father"), + new TerritoryDefinition(452, "The Burden of the Father"), + new TerritoryDefinition(523, "The Burden of the Son"), + new TerritoryDefinition(532, "The Burden of the Son"), + new TerritoryDefinition(769, "The Burn"), + new TerritoryDefinition(1173, "The Burn"), + new TerritoryDefinition(196, "The Burning Heart"), + new TerritoryDefinition(1081, "The Caustic Purgatory"), + new TerritoryDefinition(1082, "The Caustic Purgatory"), + new TerritoryDefinition(1151, "The Chamber of Fourteen"), + new TerritoryDefinition(1152, "The Chamber of Fourteen"), + new TerritoryDefinition(426, "The Chrysalis"), + new TerritoryDefinition(400, "The Churning Mists"), + new TerritoryDefinition(501, "The Churning Mists"), + new TerritoryDefinition(715, "The Churning Mists"), + new TerritoryDefinition(1116, "The Clockwork Castletown"), + new TerritoryDefinition(1117, "The Clockwork Castletown"), + new TerritoryDefinition(859, "The Confessional of Toupasa the Elder"), + new TerritoryDefinition(882, "The Copied Factory"), + new TerritoryDefinition(896, "The Copied Factory"), + new TerritoryDefinition(849, "The Core"), + new TerritoryDefinition(853, "The Core"), + new TerritoryDefinition(857, "The Core"), + new TerritoryDefinition(846, "The Crown of the Immaculate"), + new TerritoryDefinition(848, "The Crown of the Immaculate"), + new TerritoryDefinition(880, "The Crown of the Immaculate"), + new TerritoryDefinition(819, "The Crystarium"), + new TerritoryDefinition(443, "The Cuff of the Father"), + new TerritoryDefinition(450, "The Cuff of the Father"), + new TerritoryDefinition(521, "The Cuff of the Son"), + new TerritoryDefinition(530, "The Cuff of the Son"), + new TerritoryDefinition(354, "The Dancing Plague"), + new TerritoryDefinition(845, "The Dancing Plague"), + new TerritoryDefinition(858, "The Dancing Plague"), + new TerritoryDefinition(873, "The Dancing Plague"), + new TerritoryDefinition(992, "The Dark Inside"), + new TerritoryDefinition(993, "The Dark Inside"), + new TerritoryDefinition(1028, "The Dark Inside"), + new TerritoryDefinition(973, "The Dead Ends"), + new TerritoryDefinition(512, "The Diadem"), + new TerritoryDefinition(514, "The Diadem"), + new TerritoryDefinition(515, "The Diadem"), + new TerritoryDefinition(624, "The Diadem"), + new TerritoryDefinition(625, "The Diadem"), + new TerritoryDefinition(656, "The Diadem"), + new TerritoryDefinition(901, "The Diadem"), + new TerritoryDefinition(929, "The Diadem"), + new TerritoryDefinition(939, "The Diadem"), + new TerritoryDefinition(682, "The Doman Enclave"), + new TerritoryDefinition(739, "The Doman Enclave"), + new TerritoryDefinition(759, "The Doman Enclave"), + new TerritoryDefinition(398, "The Dravanian Forelands"), + new TerritoryDefinition(464, "The Dravanian Forelands"), + new TerritoryDefinition(481, "The Dravanian Forelands"), + new TerritoryDefinition(482, "The Dravanian Forelands"), + new TerritoryDefinition(1023, "The Dravanian Forelands"), + new TerritoryDefinition(399, "The Dravanian Hinterlands"), + new TerritoryDefinition(476, "The Dravanian Hinterlands"), + new TerritoryDefinition(485, "The Dravanian Hinterlands"), + new TerritoryDefinition(503, "The Dravanian Hinterlands"), + new TerritoryDefinition(1172, "The Drowned City of Skalla"), + new TerritoryDefinition(879, "The Dungeons of Lyhe Ghiah"), + new TerritoryDefinition(847, "The Dying Gasp"), + new TerritoryDefinition(881, "The Dying Gasp"), + new TerritoryDefinition(885, "The Dying Gasp"), + new TerritoryDefinition(1149, "The Dæmons' Nest"), + new TerritoryDefinition(1150, "The Dæmons' Nest"), + new TerritoryDefinition(1158, "The Dæmons' Nest"), + new TerritoryDefinition(504, "The Eighteenth Floor"), + new TerritoryDefinition(878, "The Empty"), + new TerritoryDefinition(965, "The Empty"), + new TerritoryDefinition(1000, "The Excitatron 6000"), + new TerritoryDefinition(792, "The Fall of Belah'dia"), + new TerritoryDefinition(899, "The Falling City of Nym"), + new TerritoryDefinition(149, "The Feasting Grounds"), + new TerritoryDefinition(1070, "The Fell Court of Troia"), + new TerritoryDefinition(1089, "The Fell Court of Troia"), + new TerritoryDefinition(1091, "The Fell Court of Troia"), + new TerritoryDefinition(1006, "The Fervid Limbo"), + new TerritoryDefinition(1007, "The Fervid Limbo"), + new TerritoryDefinition(554, "The Fields of Glory"), + new TerritoryDefinition(997, "The Final Day"), + new TerritoryDefinition(998, "The Final Day"), + new TerritoryDefinition(1029, "The Final Day"), + new TerritoryDefinition(886, "The Firmament"), + new TerritoryDefinition(683, "The First Altar of Djanan Qhat"), + new TerritoryDefinition(442, "The Fist of the Father"), + new TerritoryDefinition(449, "The Fist of the Father"), + new TerritoryDefinition(520, "The Fist of the Son"), + new TerritoryDefinition(529, "The Fist of the Son"), + new TerritoryDefinition(537, "The Fold"), + new TerritoryDefinition(538, "The Fold"), + new TerritoryDefinition(539, "The Fold"), + new TerritoryDefinition(540, "The Fold"), + new TerritoryDefinition(541, "The Fold"), + new TerritoryDefinition(542, "The Fold"), + new TerritoryDefinition(543, "The Fold"), + new TerritoryDefinition(544, "The Fold"), + new TerritoryDefinition(545, "The Fold"), + new TerritoryDefinition(546, "The Fold"), + new TerritoryDefinition(547, "The Fold"), + new TerritoryDefinition(548, "The Fold"), + new TerritoryDefinition(549, "The Fold"), + new TerritoryDefinition(550, "The Fold"), + new TerritoryDefinition(551, "The Fold"), + new TerritoryDefinition(1127, "The Fold"), + new TerritoryDefinition(1128, "The Fold"), + new TerritoryDefinition(1129, "The Fold"), + new TerritoryDefinition(1205, "The For'ard Cabins"), + new TerritoryDefinition(430, "The Fractal Continuum"), + new TerritoryDefinition(743, "The Fractal Continuum"), + new TerritoryDefinition(612, "The Fringes"), + new TerritoryDefinition(640, "The Fringes"), + new TerritoryDefinition(647, "The Fringes"), + new TerritoryDefinition(648, "The Fringes"), + new TerritoryDefinition(670, "The Fringes"), + new TerritoryDefinition(671, "The Fringes"), + new TerritoryDefinition(678, "The Fringes"), + new TerritoryDefinition(703, "The Fringes"), + new TerritoryDefinition(760, "The Fringes"), + new TerritoryDefinition(902, "The Gandof Thunder Plains"), + new TerritoryDefinition(906, "The Gandof Thunder Plains"), + new TerritoryDefinition(945, "The Garden of Nowhere"), + new TerritoryDefinition(949, "The Garden of Nowhere"), + new TerritoryDefinition(1002, "The Gates of Pandæmonium"), + new TerritoryDefinition(1003, "The Gates of Pandæmonium"), + new TerritoryDefinition(1025, "The Gates of Pandæmonium"), + new TerritoryDefinition(830, "The Ghimlyt Dark"), + new TerritoryDefinition(1174, "The Ghimlyt Dark"), + new TerritoryDefinition(509, "The Gilded Araya"), + new TerritoryDefinition(1136, "The Gilded Araya"), + new TerritoryDefinition(1183, "The Gilded Araya"), + new TerritoryDefinition(341, "The Goblet"), + new TerritoryDefinition(144, "The Gold Saucer"), + new TerritoryDefinition(832, "The Gold Saucer"), + new TerritoryDefinition(884, "The Grand Cosmos"), + new TerritoryDefinition(578, "The Great Gubal Library"), + new TerritoryDefinition(676, "The Great Gubal Library"), + new TerritoryDefinition(1109, "The Great Gubal Library"), + new TerritoryDefinition(761, "The Great Hunt"), + new TerritoryDefinition(762, "The Great Hunt"), + new TerritoryDefinition(850, "The Halo"), + new TerritoryDefinition(854, "The Halo"), + new TerritoryDefinition(904, "The Halo"), + new TerritoryDefinition(908, "The Halo"), + new TerritoryDefinition(916, "The Heroes' Gauntlet"), + new TerritoryDefinition(1085, "The Hollow Purgatory"), + new TerritoryDefinition(1086, "The Hollow Purgatory"), + new TerritoryDefinition(358, "The Holocharts"), + new TerritoryDefinition(383, "The Holocharts"), + new TerritoryDefinition(178, "The Hourglass"), + new TerritoryDefinition(681, "The House of the Fierce"), + new TerritoryDefinition(294, "The Howling Eye"), + new TerritoryDefinition(297, "The Howling Eye"), + new TerritoryDefinition(331, "The Howling Eye"), + new TerritoryDefinition(833, "The Howling Eye"), + new TerritoryDefinition(834, "The Howling Eye"), + new TerritoryDefinition(1047, "The Howling Eye"), + new TerritoryDefinition(893, "The Imperial Palace"), + new TerritoryDefinition(658, "The Interdimensional Rift"), + new TerritoryDefinition(690, "The Interdimensional Rift"), + new TerritoryDefinition(724, "The Interdimensional Rift"), + new TerritoryDefinition(756, "The Interdimensional Rift"), + new TerritoryDefinition(800, "The Interdimensional Rift"), + new TerritoryDefinition(801, "The Interdimensional Rift"), + new TerritoryDefinition(804, "The Interdimensional Rift"), + new TerritoryDefinition(805, "The Interdimensional Rift"), + new TerritoryDefinition(807, "The Interdimensional Rift"), + new TerritoryDefinition(808, "The Interdimensional Rift"), + new TerritoryDefinition(812, "The Interdimensional Rift"), + new TerritoryDefinition(1122, "The Interdimensional Rift"), + new TerritoryDefinition(746, "The Jade Stoa"), + new TerritoryDefinition(758, "The Jade Stoa"), + new TerritoryDefinition(1063, "The Keeper of the Lake"), + new TerritoryDefinition(955, "The Last Trace"), + new TerritoryDefinition(964, "The Last Trace"), + new TerritoryDefinition(340, "The Lavender Beds"), + new TerritoryDefinition(439, "The Lightfeather Proving Grounds"), + new TerritoryDefinition(436, "The Limitless Blue"), + new TerritoryDefinition(447, "The Limitless Blue"), + new TerritoryDefinition(621, "The Lochs"), + new TerritoryDefinition(684, "The Lochs"), + new TerritoryDefinition(686, "The Lochs"), + new TerritoryDefinition(687, "The Lochs"), + new TerritoryDefinition(712, "The Lost Canals of Uznair"), + new TerritoryDefinition(725, "The Lost Canals of Uznair"), + new TerritoryDefinition(363, "The Lost City of Amdapor"), + new TerritoryDefinition(519, "The Lost City of Amdapor"), + new TerritoryDefinition(722, "The Lost City of Amdapor"), + new TerritoryDefinition(1164, "The Lunar Subterrane"), + new TerritoryDefinition(1184, "The Lunar Subterrane"), + new TerritoryDefinition(831, "The Manderville Tables"), + new TerritoryDefinition(1166, "The Memory of Embers"), + new TerritoryDefinition(1292, "The Meso Terminal"), + new TerritoryDefinition(995, "The Mothercrystal"), + new TerritoryDefinition(996, "The Mothercrystal"), + new TerritoryDefinition(1030, "The Mothercrystal"), + new TerritoryDefinition(876, "The Nabaath Mines"), + new TerritoryDefinition(293, "The Navel"), + new TerritoryDefinition(296, "The Navel"), + new TerritoryDefinition(954, "The Navel"), + new TerritoryDefinition(1046, "The Navel"), + new TerritoryDefinition(851, "The Nereus Trench"), + new TerritoryDefinition(855, "The Nereus Trench"), + new TerritoryDefinition(1024, "The Nethergate"), + new TerritoryDefinition(844, "The Ocular"), + new TerritoryDefinition(1061, "The Omphalos"), + new TerritoryDefinition(826, "The Orbonne Monastery"), + new TerritoryDefinition(356, "The Outer Coil"), + new TerritoryDefinition(381, "The Outer Coil"), + new TerritoryDefinition(561, "The Palace of the Dead"), + new TerritoryDefinition(562, "The Palace of the Dead"), + new TerritoryDefinition(563, "The Palace of the Dead"), + new TerritoryDefinition(564, "The Palace of the Dead"), + new TerritoryDefinition(565, "The Palace of the Dead"), + new TerritoryDefinition(570, "The Palace of the Dead"), + new TerritoryDefinition(593, "The Palace of the Dead"), + new TerritoryDefinition(594, "The Palace of the Dead"), + new TerritoryDefinition(595, "The Palace of the Dead"), + new TerritoryDefinition(596, "The Palace of the Dead"), + new TerritoryDefinition(597, "The Palace of the Dead"), + new TerritoryDefinition(598, "The Palace of the Dead"), + new TerritoryDefinition(599, "The Palace of the Dead"), + new TerritoryDefinition(600, "The Palace of the Dead"), + new TerritoryDefinition(601, "The Palace of the Dead"), + new TerritoryDefinition(602, "The Palace of the Dead"), + new TerritoryDefinition(603, "The Palace of the Dead"), + new TerritoryDefinition(604, "The Palace of the Dead"), + new TerritoryDefinition(605, "The Palace of the Dead"), + new TerritoryDefinition(606, "The Palace of the Dead"), + new TerritoryDefinition(607, "The Palace of the Dead"), + new TerritoryDefinition(1032, "The Palaistra"), + new TerritoryDefinition(1058, "The Palaistra"), + new TerritoryDefinition(567, "The Parrock"), + new TerritoryDefinition(620, "The Peaks"), + new TerritoryDefinition(716, "The Peaks"), + new TerritoryDefinition(868, "The Peaks"), + new TerritoryDefinition(1019, "The Peaks"), + new TerritoryDefinition(843, "The Pendants Personal Suite"), + new TerritoryDefinition(1083, "The Pestilent Purgatory"), + new TerritoryDefinition(1084, "The Pestilent Purgatory"), + new TerritoryDefinition(994, "The Phantoms' Feast"), + new TerritoryDefinition(419, "The Pillars"), + new TerritoryDefinition(499, "The Pillars"), + new TerritoryDefinition(1052, "The Porta Decumana"), + new TerritoryDefinition(1053, "The Porta Decumana"), + new TerritoryDefinition(1044, "The Praetorium"), + new TerritoryDefinition(917, "The Puppets' Bunker"), + new TerritoryDefinition(928, "The Puppets' Bunker"), + new TerritoryDefinition(823, "The Qitana Ravel"), + new TerritoryDefinition(243, "The Ragnarok"), + new TerritoryDefinition(817, "The Rak'tika Greatwood"), + new TerritoryDefinition(871, "The Rak'tika Greatwood"), + new TerritoryDefinition(874, "The Rak'tika Greatwood"), + new TerritoryDefinition(875, "The Rak'tika Greatwood"), + new TerritoryDefinition(1162, "The Red Moon"), + new TerritoryDefinition(1138, "The Red Sands"), + new TerritoryDefinition(1139, "The Red Sands"), + new TerritoryDefinition(738, "The Resonatorium"), + new TerritoryDefinition(787, "The Ridorana Cataract"), + new TerritoryDefinition(776, "The Ridorana Lighthouse"), + new TerritoryDefinition(351, "The Rising Stones"), + new TerritoryDefinition(179, "The Roost"), + new TerritoryDefinition(679, "The Royal Airship Landing"), + new TerritoryDefinition(734, "The Royal City of Rabanastre"), + new TerritoryDefinition(727, "The Royal Menagerie"), + new TerritoryDefinition(740, "The Royal Menagerie"), + new TerritoryDefinition(613, "The Ruby Sea"), + new TerritoryDefinition(657, "The Ruby Sea"), + new TerritoryDefinition(711, "The Ruby Sea"), + new TerritoryDefinition(726, "The Ruby Sea"), + new TerritoryDefinition(757, "The Ruby Sea"), + new TerritoryDefinition(1008, "The Sanguine Limbo"), + new TerritoryDefinition(1009, "The Sanguine Limbo"), + new TerritoryDefinition(401, "The Sea of Clouds"), + new TerritoryDefinition(455, "The Sea of Clouds"), + new TerritoryDefinition(461, "The Sea of Clouds"), + new TerritoryDefinition(492, "The Sea of Clouds"), + new TerritoryDefinition(1214, "The Sea of Clouds"), + new TerritoryDefinition(922, "The Seat of Sacrifice"), + new TerritoryDefinition(923, "The Seat of Sacrifice"), + new TerritoryDefinition(931, "The Seat of Sacrifice"), + new TerritoryDefinition(794, "The Shifting Altars of Uznair"), + new TerritoryDefinition(1123, "The Shifting Gymnasion Agonon"), + new TerritoryDefinition(924, "The Shifting Oubliettes of Lyhe Ghiah"), + new TerritoryDefinition(1069, "The Sil'dihn Subterrane"), + new TerritoryDefinition(1142, "The Sirensong Sea"), + new TerritoryDefinition(1194, "The Skydeep Cenote"), + new TerritoryDefinition(1004, "The Stagnant Limbo"), + new TerritoryDefinition(1005, "The Stagnant Limbo"), + new TerritoryDefinition(986, "The Stigma Dreamscape"), + new TerritoryDefinition(374, "The Striking Tree"), + new TerritoryDefinition(375, "The Striking Tree"), + new TerritoryDefinition(367, "The Sunken Temple of Qarn"), + new TerritoryDefinition(1267, "The Sunken Temple of Qarn"), + new TerritoryDefinition(768, "The Swallow's Compass"), + new TerritoryDefinition(1017, "The Swallow's Compass"), + new TerritoryDefinition(842, "The Syrcus Trench"), + new TerritoryDefinition(373, "The Tam-Tara Deepcroft"), + new TerritoryDefinition(1037, "The Tam-Tara Deepcroft"), + new TerritoryDefinition(818, "The Tempest"), + new TerritoryDefinition(932, "The Tempest"), + new TerritoryDefinition(663, "The Temple of the Fist"), + new TerritoryDefinition(1039, "The Thousand Maws of Toto-Rak"), + new TerritoryDefinition(1231, "The Thundering"), + new TerritoryDefinition(1232, "The Thundering"), + new TerritoryDefinition(966, "The Tower at Paradigm's Breach"), + new TerritoryDefinition(969, "The Tower of Babil"), + new TerritoryDefinition(1051, "The Tower of Babil"), + new TerritoryDefinition(1115, "The Tower of Babil"), + new TerritoryDefinition(952, "The Tower of Zot"), + new TerritoryDefinition(840, "The Twinning"), + new TerritoryDefinition(1266, "The Underkeep"), + new TerritoryDefinition(513, "The Vault"), + new TerritoryDefinition(1018, "The Vault"), + new TerritoryDefinition(1066, "The Vault"), + new TerritoryDefinition(1140, "The Voidcast Dais"), + new TerritoryDefinition(1141, "The Voidcast Dais"), + new TerritoryDefinition(1159, "The Voidcast Dais"), + new TerritoryDefinition(1033, "The Volcanic Heart"), + new TerritoryDefinition(1059, "The Volcanic Heart"), + new TerritoryDefinition(212, "The Waking Sands"), + new TerritoryDefinition(159, "The Wanderer's Palace"), + new TerritoryDefinition(188, "The Wanderer's Palace"), + new TerritoryDefinition(329, "The Wanderer's Palace"), + new TerritoryDefinition(556, "The Weeping City of Mhach"), + new TerritoryDefinition(707, "The Weeping City of Mhach"), + new TerritoryDefinition(368, "The Weeping Saint"), + new TerritoryDefinition(281, "The Whorleater"), + new TerritoryDefinition(359, "The Whorleater"), + new TerritoryDefinition(1300, "The Windward Wilds"), + new TerritoryDefinition(1301, "The Windward Wilds"), + new TerritoryDefinition(1306, "The Windward Wilds"), + new TerritoryDefinition(151, "The World of Darkness"), + new TerritoryDefinition(824, "The Wreath of Snakes"), + new TerritoryDefinition(825, "The Wreath of Snakes"), + new TerritoryDefinition(1302, "The Wreath of Snakes"), + new TerritoryDefinition(432, "Thok ast Thok"), + new TerritoryDefinition(446, "Thok ast Thok"), + new TerritoryDefinition(364, "Thornmarch"), + new TerritoryDefinition(1067, "Thornmarch"), + new TerritoryDefinition(1274, "Throne Room"), + new TerritoryDefinition(608, "Topmast Apartment"), + new TerritoryDefinition(573, "Topmast Apartment Lobby"), + new TerritoryDefinition(913, "Transmission Control"), + new TerritoryDefinition(730, "Transparency"), + new TerritoryDefinition(914, "Trial's Threshold"), + new TerritoryDefinition(1223, "Tritails Training"), + new TerritoryDefinition(1185, "Tuliyollal"), + new TerritoryDefinition(534, "Twin Adder Barracks"), + new TerritoryDefinition(130, "Ul'dah - Steps of Nald"), + new TerritoryDefinition(182, "Ul'dah - Steps of Nald"), + new TerritoryDefinition(251, "Ul'dah - Steps of Nald"), + new TerritoryDefinition(254, "Ul'dah - Steps of Nald"), + new TerritoryDefinition(259, "Ul'dah - Steps of Nald"), + new TerritoryDefinition(274, "Ul'dah - Steps of Nald"), + new TerritoryDefinition(790, "Ul'dah - Steps of Nald"), + new TerritoryDefinition(131, "Ul'dah - Steps of Thal"), + new TerritoryDefinition(666, "Ul'dah - Steps of Thal"), + new TerritoryDefinition(705, "Ul'dah - Steps of Thal"), + new TerritoryDefinition(706, "Ul'dah - Steps of Thal"), + new TerritoryDefinition(960, "Ultima Thule"), + new TerritoryDefinition(1027, "Ultima Thule"), + new TerritoryDefinition(777, "Ultimacy"), + new TerritoryDefinition(1055, "Unnamed Island"), + new TerritoryDefinition(241, "Upper Aetheroacoustic Exploratory Site"), + new TerritoryDefinition(139, "Upper La Noscea"), + new TerritoryDefinition(221, "Upper La Noscea"), + new TerritoryDefinition(328, "Upper La Noscea"), + new TerritoryDefinition(412, "Upper La Noscea"), + new TerritoryDefinition(454, "Upper La Noscea"), + new TerritoryDefinition(466, "Upper La Noscea"), + new TerritoryDefinition(1187, "Urqopacha"), + new TerritoryDefinition(970, "Vanaspati"), + new TerritoryDefinition(1198, "Vanguard"), + new TerritoryDefinition(1219, "Vanguard"), + new TerritoryDefinition(1279, "Vault Oneiron"), + new TerritoryDefinition(508, "Void Ark"), + new TerritoryDefinition(138, "Western La Noscea"), + new TerritoryDefinition(263, "Western La Noscea"), + new TerritoryDefinition(280, "Western La Noscea"), + new TerritoryDefinition(330, "Western La Noscea"), + new TerritoryDefinition(405, "Western La Noscea"), + new TerritoryDefinition(406, "Western La Noscea"), + new TerritoryDefinition(413, "Western La Noscea"), + new TerritoryDefinition(453, "Western La Noscea"), + new TerritoryDefinition(552, "Western La Noscea"), + new TerritoryDefinition(675, "Western La Noscea"), + new TerritoryDefinition(140, "Western Thanalan"), + new TerritoryDefinition(215, "Western Thanalan"), + new TerritoryDefinition(255, "Western Thanalan"), + new TerritoryDefinition(267, "Western Thanalan"), + new TerritoryDefinition(269, "Western Thanalan"), + new TerritoryDefinition(273, "Western Thanalan"), + new TerritoryDefinition(278, "Western Thanalan"), + new TerritoryDefinition(1049, "Western Thanalan"), + new TerritoryDefinition(250, "Wolves' Den Pier"), + new TerritoryDefinition(717, "Wolves' Den Pier"), + new TerritoryDefinition(1195, "Worqor Lar Dor"), + new TerritoryDefinition(1196, "Worqor Lar Dor"), + new TerritoryDefinition(1193, "Worqor Zormor"), + new TerritoryDefinition(1113, "Xelphatol"), + new TerritoryDefinition(1189, "Yak T'el"), + new TerritoryDefinition(1211, "Yak T'el"), + new TerritoryDefinition(1212, "Yak T'el"), + new TerritoryDefinition(614, "Yanxia"), + new TerritoryDefinition(634, "Yanxia"), + new TerritoryDefinition(685, "Yanxia"), + new TerritoryDefinition(1242, "Yuweyawata"), + new TerritoryDefinition(1254, "Yuweyawata"), + new TerritoryDefinition(975, "Zadnor"), + new TerritoryDefinition(1077, "Zero's Domain"), + new TerritoryDefinition(1297, "Zirgorteh the Open-armed"), + new TerritoryDefinition(1246, "Zorgor the Boundless"), + }; + + public static IReadOnlyList All { get; } = Array.AsReadOnly(TerritoryArray); + public static IReadOnlyDictionary ById { get; } = new ReadOnlyDictionary(TerritoryArray.ToDictionary(t => t.TerritoryId)); + public static IReadOnlyDictionary> IdsByName { get; } = new ReadOnlyDictionary>(TerritoryArray + .GroupBy(t => t.Name, StringComparer.OrdinalIgnoreCase) + .ToDictionary( + g => g.Key, + g => (IReadOnlySet)new HashSet(g.Select(t => t.TerritoryId)), + StringComparer.OrdinalIgnoreCase)); + + public static bool TryGetIds(string name, out IReadOnlySet ids) + => IdsByName.TryGetValue(name, out ids); + + public static IReadOnlySet GetIds(IEnumerable names) + { + var set = new HashSet(); + foreach (var name in names) + { + if (string.IsNullOrWhiteSpace(name)) + continue; + + if (IdsByName.TryGetValue(name, out var ids)) + { + set.UnionWith(ids); + } + } + + return set; + } + + public static IReadOnlySet GetIds(params string[] names) + => GetIds((IEnumerable)names); +} diff --git a/LightlessSyncServer/LightlessSyncServer/Models/WorldDefinition.cs b/LightlessSyncServer/LightlessSyncServer/Models/WorldDefinition.cs new file mode 100644 index 0000000..919b6e8 --- /dev/null +++ b/LightlessSyncServer/LightlessSyncServer/Models/WorldDefinition.cs @@ -0,0 +1,7 @@ +namespace LightlessSyncServer.Models; + +internal readonly record struct WorldDefinition( + ushort WorldId, + string Name, + string Region, + string DataCenter); diff --git a/LightlessSyncServer/LightlessSyncServer/Models/WorldRegistry.generated.cs b/LightlessSyncServer/LightlessSyncServer/Models/WorldRegistry.generated.cs new file mode 100644 index 0000000..9fbcc75 --- /dev/null +++ b/LightlessSyncServer/LightlessSyncServer/Models/WorldRegistry.generated.cs @@ -0,0 +1,117 @@ +// +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace LightlessSyncServer.Models; + +internal static class WorldRegistry +{ + private static readonly WorldDefinition[] WorldArray = new[] + { + new WorldDefinition(80, "Cerberus", "Europe", "Chaos"), + new WorldDefinition(83, "Louisoix", "Europe", "Chaos"), + new WorldDefinition(71, "Moogle", "Europe", "Chaos"), + new WorldDefinition(39, "Omega", "Europe", "Chaos"), + new WorldDefinition(401, "Phantom", "Europe", "Chaos"), + new WorldDefinition(97, "Ragnarok", "Europe", "Chaos"), + new WorldDefinition(400, "Sagittarius", "Europe", "Chaos"), + new WorldDefinition(85, "Spriggan", "Europe", "Chaos"), + new WorldDefinition(402, "Alpha", "Europe", "Light"), + new WorldDefinition(36, "Lich", "Europe", "Light"), + new WorldDefinition(66, "Odin", "Europe", "Light"), + new WorldDefinition(56, "Phoenix", "Europe", "Light"), + new WorldDefinition(403, "Raiden", "Europe", "Light"), + new WorldDefinition(67, "Shiva", "Europe", "Light"), + new WorldDefinition(33, "Twintania", "Europe", "Light"), + new WorldDefinition(42, "Zodiark", "Europe", "Light"), + new WorldDefinition(90, "Aegis", "Japan", "Elemental"), + new WorldDefinition(68, "Atomos", "Japan", "Elemental"), + new WorldDefinition(45, "Carbuncle", "Japan", "Elemental"), + new WorldDefinition(58, "Garuda", "Japan", "Elemental"), + new WorldDefinition(94, "Gungnir", "Japan", "Elemental"), + new WorldDefinition(49, "Kujata", "Japan", "Elemental"), + new WorldDefinition(72, "Tonberry", "Japan", "Elemental"), + new WorldDefinition(50, "Typhon", "Japan", "Elemental"), + new WorldDefinition(43, "Alexander", "Japan", "Gaia"), + new WorldDefinition(69, "Bahamut", "Japan", "Gaia"), + new WorldDefinition(92, "Durandal", "Japan", "Gaia"), + new WorldDefinition(46, "Fenrir", "Japan", "Gaia"), + new WorldDefinition(59, "Ifrit", "Japan", "Gaia"), + new WorldDefinition(98, "Ridill", "Japan", "Gaia"), + new WorldDefinition(76, "Tiamat", "Japan", "Gaia"), + new WorldDefinition(51, "Ultima", "Japan", "Gaia"), + new WorldDefinition(44, "Anima", "Japan", "Mana"), + new WorldDefinition(23, "Asura", "Japan", "Mana"), + new WorldDefinition(70, "Chocobo", "Japan", "Mana"), + new WorldDefinition(47, "Hades", "Japan", "Mana"), + new WorldDefinition(48, "Ixion", "Japan", "Mana"), + new WorldDefinition(96, "Masamune", "Japan", "Mana"), + new WorldDefinition(28, "Pandaemonium", "Japan", "Mana"), + new WorldDefinition(61, "Titan", "Japan", "Mana"), + new WorldDefinition(24, "Belias", "Japan", "Meteor"), + new WorldDefinition(82, "Mandragora", "Japan", "Meteor"), + new WorldDefinition(60, "Ramuh", "Japan", "Meteor"), + new WorldDefinition(29, "Shinryu", "Japan", "Meteor"), + new WorldDefinition(30, "Unicorn", "Japan", "Meteor"), + new WorldDefinition(52, "Valefor", "Japan", "Meteor"), + new WorldDefinition(31, "Yojimbo", "Japan", "Meteor"), + new WorldDefinition(32, "Zeromus", "Japan", "Meteor"), + new WorldDefinition(73, "Adamantoise", "North America", "Aether"), + new WorldDefinition(79, "Cactuar", "North America", "Aether"), + new WorldDefinition(54, "Faerie", "North America", "Aether"), + new WorldDefinition(63, "Gilgamesh", "North America", "Aether"), + new WorldDefinition(40, "Jenova", "North America", "Aether"), + new WorldDefinition(65, "Midgardsormr", "North America", "Aether"), + new WorldDefinition(99, "Sargatanas", "North America", "Aether"), + new WorldDefinition(57, "Siren", "North America", "Aether"), + new WorldDefinition(91, "Balmung", "North America", "Crystal"), + new WorldDefinition(34, "Brynhildr", "North America", "Crystal"), + new WorldDefinition(74, "Coeurl", "North America", "Crystal"), + new WorldDefinition(62, "Diabolos", "North America", "Crystal"), + new WorldDefinition(81, "Goblin", "North America", "Crystal"), + new WorldDefinition(75, "Malboro", "North America", "Crystal"), + new WorldDefinition(37, "Mateus", "North America", "Crystal"), + new WorldDefinition(41, "Zalera", "North America", "Crystal"), + new WorldDefinition(408, "Cuchulainn", "North America", "Dynamis"), + new WorldDefinition(411, "Golem", "North America", "Dynamis"), + new WorldDefinition(406, "Halicarnassus", "North America", "Dynamis"), + new WorldDefinition(409, "Kraken", "North America", "Dynamis"), + new WorldDefinition(407, "Maduin", "North America", "Dynamis"), + new WorldDefinition(404, "Marilith", "North America", "Dynamis"), + new WorldDefinition(410, "Rafflesia", "North America", "Dynamis"), + new WorldDefinition(405, "Seraph", "North America", "Dynamis"), + new WorldDefinition(78, "Behemoth", "North America", "Primal"), + new WorldDefinition(93, "Excalibur", "North America", "Primal"), + new WorldDefinition(53, "Exodus", "North America", "Primal"), + new WorldDefinition(35, "Famfrit", "North America", "Primal"), + new WorldDefinition(95, "Hyperion", "North America", "Primal"), + new WorldDefinition(55, "Lamia", "North America", "Primal"), + new WorldDefinition(64, "Leviathan", "North America", "Primal"), + new WorldDefinition(77, "Ultros", "North America", "Primal"), + new WorldDefinition(22, "Bismarck", "Oceania", "Materia"), + new WorldDefinition(21, "Ravana", "Oceania", "Materia"), + new WorldDefinition(86, "Sephirot", "Oceania", "Materia"), + new WorldDefinition(87, "Sophia", "Oceania", "Materia"), + new WorldDefinition(88, "Zurvan", "Oceania", "Materia"), + }; + + public static IReadOnlyList All { get; } = Array.AsReadOnly(WorldArray); + public static IReadOnlyDictionary ById { get; } = new ReadOnlyDictionary(WorldArray.ToDictionary(w => w.WorldId)); + public static IReadOnlyDictionary> ByDataCenter { get; } = new ReadOnlyDictionary>(WorldArray + .GroupBy(w => w.DataCenter, StringComparer.OrdinalIgnoreCase) + .ToDictionary( + g => g.Key, + g => (IReadOnlyList)g.OrderBy(w => w.Name, StringComparer.Ordinal).ToArray(), + StringComparer.OrdinalIgnoreCase)); + public static IReadOnlyDictionary> ByRegion { get; } = new ReadOnlyDictionary>(WorldArray + .GroupBy(w => w.Region, StringComparer.OrdinalIgnoreCase) + .ToDictionary( + g => g.Key, + g => (IReadOnlyList)g.OrderBy(w => w.Name, StringComparer.Ordinal).ToArray(), + StringComparer.OrdinalIgnoreCase)); + + public static bool TryGet(ushort worldId, out WorldDefinition definition) => ById.TryGetValue(worldId, out definition); + public static bool IsKnownWorld(ushort worldId) => ById.ContainsKey(worldId); +} diff --git a/LightlessSyncServer/LightlessSyncServer/Services/ChatChannelService.cs b/LightlessSyncServer/LightlessSyncServer/Services/ChatChannelService.cs index 0a411d1..9c47097 100644 --- a/LightlessSyncServer/LightlessSyncServer/Services/ChatChannelService.cs +++ b/LightlessSyncServer/LightlessSyncServer/Services/ChatChannelService.cs @@ -49,11 +49,24 @@ public sealed class ChatChannelService string userUid, ZoneChannelDefinition definition, ushort worldId, + ushort territoryId, string? hashedCid, bool isLightfinder, bool isActive) { - var descriptor = definition.Descriptor with { WorldId = worldId }; + if (worldId == 0 || !WorldRegistry.IsKnownWorld(worldId)) + { + _logger.LogWarning("Rejected zone chat presence for {User} in {Zone}: unknown world {WorldId}", userUid, definition.Key, worldId); + return null; + } + + if (!definition.TerritoryIds.Contains(territoryId)) + { + _logger.LogWarning("Rejected zone chat presence for {User} in {Zone}: invalid territory {TerritoryId}", userUid, definition.Key, territoryId); + return null; + } + + var descriptor = definition.Descriptor with { WorldId = worldId, ZoneId = territoryId }; var participant = new ChatParticipantInfo( Token: string.Empty, UserUid: userUid,