From 8eca9edae6fb9435c7f1c0ef14c2977e783b0511 Mon Sep 17 00:00:00 2001 From: Anna Date: Tue, 17 Oct 2023 03:49:24 -0400 Subject: [PATCH] feat(extractor): generate source for server --- game-data-extractor/Maps.cs | 23 ++++++++--- game-data-extractor/Program.cs | 2 + game-data-extractor/ServerInfo.cs | 61 +++++++++++++++++++++++++++++ game-data-extractor/TerritoryExt.cs | 42 ++++++++++++++++++++ 4 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 game-data-extractor/ServerInfo.cs create mode 100644 game-data-extractor/TerritoryExt.cs diff --git a/game-data-extractor/Maps.cs b/game-data-extractor/Maps.cs index 454a878..5e5f5d5 100644 --- a/game-data-extractor/Maps.cs +++ b/game-data-extractor/Maps.cs @@ -10,7 +10,7 @@ internal class Maps { this.Data = data; } - internal Dictionary Extract() { + internal List Extract() { var dict = new Dictionary(); var fromMaps = this.Data.GetExcelSheet()! .Where(map => map.RowId != 0 && map.TerritoryType.Row != 0) @@ -20,17 +20,24 @@ internal class Maps { .Where(terri => terri.RowId != 0 && terri.Map.Row != 0) .Select(terri => (Map: terri.Map.Value!, Territory: terri, Name: terri.PlaceName.Value?.Name.RawString)) .Where(tuple => !string.IsNullOrWhiteSpace(tuple.Name)); + var quests = this.Data.GetExcelSheet()!; foreach (var (map, territory, name) in fromMaps.Concat(fromTerris)) { if (!dict.ContainsKey(territory.RowId)) { + var (subtitle, category) = territory.GetSubtitleAndCategory(quests); + dict[territory.RowId] = new TerritoryInfo { + Id = territory.RowId, + Name = name!, + Subtitle = subtitle, + Category = category, Battle = territory.ContentFinderCondition.Row != 0, Maps = new List(), }; } var id = map.Id.RawString; - if (string.IsNullOrWhiteSpace(id) || string.IsNullOrWhiteSpace(name)) { + if (string.IsNullOrWhiteSpace(id)) { continue; } @@ -40,7 +47,6 @@ internal class Maps { dict[territory.RowId].Maps.Add(new MapInfo { Id = id, - Name = name, OffsetX = map.OffsetX, OffsetY = map.OffsetY, Scale = map.SizeFactor, @@ -51,12 +57,20 @@ internal class Maps { info.Maps.Sort((a, b) => string.Compare(a.Id, b.Id, StringComparison.Ordinal)); } - return dict; + return dict + .OrderBy(entry => entry.Value.Battle) + .ThenBy(entry => entry.Key) + .Select(entry => entry.Value) + .ToList(); } } [Serializable] public class TerritoryInfo { + public uint Id { get; set; } + public string Name { get; set; } + public string? Subtitle { get; set; } + public string? Category { get; set; } public bool Battle { get; init; } public List Maps { get; init; } } @@ -64,7 +78,6 @@ public class TerritoryInfo { [Serializable] public class MapInfo { public string Id { get; init; } - public string Name { get; init; } public short OffsetX { get; init; } public short OffsetY { get; init; } public ushort Scale { get; init; } diff --git a/game-data-extractor/Program.cs b/game-data-extractor/Program.cs index 82e5df1..5614b7b 100644 --- a/game-data-extractor/Program.cs +++ b/game-data-extractor/Program.cs @@ -6,9 +6,11 @@ var data = new GameData("/home/anna/.xlcore/ffxiv/game/sqpack"); var maps = new Maps(data).Extract(); var worlds = new Worlds(data).Extract(); +var serverInfo = new ServerInfo(data).Extract(); await WriteToFile("territories.json", maps); await WriteToFile("worlds.json", worlds); +await File.WriteAllTextAsync("game_info.rs", serverInfo); Console.WriteLine("Done"); return; diff --git a/game-data-extractor/ServerInfo.cs b/game-data-extractor/ServerInfo.cs new file mode 100644 index 0000000..7f9a843 --- /dev/null +++ b/game-data-extractor/ServerInfo.cs @@ -0,0 +1,61 @@ +using System.Text; +using Lumina; +using Lumina.Excel.GeneratedSheets; + +namespace GameDataExtractor; + +internal class ServerInfo { + private GameData Data { get; } + + internal ServerInfo(GameData data) { + this.Data = data; + } + + internal string Extract() { + var sb = new StringBuilder(); + + var questSheet = this.Data.GetExcelSheet()!; + var ttSheet = this.Data.GetExcelSheet()!; + var territories = ttSheet.OrderBy(tt => tt.RowId).ToList(); + var max = territories.Select(tt => tt.RowId).Max(); + sb.Append("#[derive(Clone, Copy)]\npub struct TerritoryInfo {\n pub parties_visible: bool,\n pub map_visible: bool,\n}\n\n"); + sb.Append($"pub const TERRITORY_INFO: [TerritoryInfo; {max + 1}] = [\n TerritoryInfo {{ parties_visible: false, map_visible: false }}, // 0 - none\n"); + var last = 0u; + foreach (var territory in ttSheet.OrderBy(tt => tt.RowId)) { + var diff = territory.RowId - last; + for (var i = 1; i < diff; i++) { + sb.Append($" TerritoryInfo {{ parties_visible: false, map_visible: false }}, // {last + i} - missing\n"); + } + + last = territory.RowId; + + var name = territory.PlaceName.Value?.Name.RawString; + var (subtitle, category) = territory.GetSubtitleAndCategory(questSheet); + var comment = $"// {territory.RowId}"; + if (!string.IsNullOrWhiteSpace(name)) { + comment += $" - {name}"; + } + + var hasSubtitle = !string.IsNullOrWhiteSpace(subtitle); + var hasCategory = !string.IsNullOrWhiteSpace(category); + if (hasSubtitle && hasCategory) { + comment += $" ({category}: {subtitle})"; + } else if (hasSubtitle) { + comment += $" ({subtitle})"; + } else if (hasCategory) { + comment += $" ({category})"; + } + + var pvp = territory.IsPvpZone && territory.RowId != 250; + var battle = territory.ContentFinderCondition.Row != 0 && !pvp; + var battleString = battle ? "true" : "false"; + var allowedString = pvp ? "false" : "true"; + sb.Append($" TerritoryInfo {{ parties_visible: {battleString}, map_visible: {allowedString} }}, {comment}\n"); + } + + // sb.Append(" };\n}\n"); + sb.Append("];\n"); + + return sb.ToString(); + } +} diff --git a/game-data-extractor/TerritoryExt.cs b/game-data-extractor/TerritoryExt.cs new file mode 100644 index 0000000..5709652 --- /dev/null +++ b/game-data-extractor/TerritoryExt.cs @@ -0,0 +1,42 @@ +using Lumina.Excel; +using Lumina.Excel.GeneratedSheets; + +namespace GameDataExtractor; + +internal static class TerritoryExt { + internal static (string? Subtitle, string? Category) GetSubtitleAndCategory(this TerritoryType territory, ExcelSheet quests) { + string? subtitle = null; + string? category = null; + if (territory.QuestBattle.Row != 0) { + var questId = territory.QuestBattle.Value!.Quest; + var quest = quests.GetRow((uint) questId); + if (quest != null) { + category = "Quest Battles"; + subtitle = quest.Name.RawString; + } + } else if (territory.ContentFinderCondition.Row != 0) { + var cfc = territory.ContentFinderCondition.Value!; + + var ctName = cfc.ContentType.Value?.Name.RawString; + if (!string.IsNullOrWhiteSpace(ctName)) { + category = ctName; + } + + var cfcName = cfc.Name.RawString; + subtitle = Prettify(cfcName); + } + + return (subtitle, category); + + string Prettify(string input) { + if (string.IsNullOrWhiteSpace(input)) { + return "Instance"; + } + + var name = input[..1].ToUpperInvariant() + input[1..]; + return name + .Replace("TamTara", "Tam-Tara") + .Replace("TotoRak", "Toto-Rak"); + } + } +}