using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using ACE.Database.Models.World; namespace ACE.Adapter.GDLE { public static class GDLELoader { public static bool TryLoadLandblock(string file, out Models.Landblock result) { try { var fileText = File.ReadAllText(file); result = JsonSerializer.Deserialize(fileText); return true; } catch { result = null; return false; } } public static bool TryLoadLandblocksInParallel(string folder, out List results) { try { var files = Directory.GetFiles(folder, "*.json", SearchOption.AllDirectories); var landblocks = new ConcurrentBag(); Parallel.ForEach(files, file => { if (TryLoadLandblock(file, out var result)) landblocks.Add(result); }); results = new List(landblocks); return true; } catch { results = null; return false; } } public static bool TryLoadWorldSpawns(string file, out Models.WorldSpawns result) { try { var fileText = File.ReadAllText(file); result = JsonSerializer.Deserialize(fileText); return true; } catch { result = null; return false; } } /// /// This will sanitize the Guids for ACE use to the following format: 0x7LBID### where ### starts from [startingIdOffset] /// public static bool TryLoadLandblocksConverted(string folder, out List results, out List links, ushort startingIdOffset = 0) { try { TryLoadLandblocksInParallel(folder, out var landblocks); if (landblocks == null) { results = null; links = null; return false; } ReGuidAndConvertLandblocks(out results, out links, startingIdOffset, landblocks); return true; } catch { results = null; links = null; return false; } } private static void ReGuidAndConvertLandblocks(out List results, out List links, ushort startingIdOffset, List landblocks) { var idChanges = new Dictionary>(); // First we convert all weenies foreach (var landblock in landblocks) { var currentOffset = startingIdOffset; if (!idChanges.ContainsKey(landblock.key)) idChanges.Add(landblock.key, new Dictionary()); foreach (var weenie in landblock.value.weenies) { var newGuid = (0x70000000 | ((weenie.pos.LandCellId & 0xFFFF0000) >> 4) | currentOffset); currentOffset++; if (!idChanges[landblock.key].ContainsKey(weenie.id)) { idChanges[landblock.key].Add(weenie.id, newGuid); weenie.id = newGuid; } } } // Then we update all the links foreach (var landblock in landblocks) { if (landblock.value.links == null) continue; foreach (var link in landblock.value.links) { if (idChanges[landblock.key].TryGetValue(link.source, out var source)) link.source = source; else link.source = 0; if (idChanges[landblock.key].TryGetValue(link.target, out var target)) link.target = target; else link.target = 0; } } TryConvertLandblocks(out results, out links, landblocks); } private static void TryConvertLandblocks(out List results, out List links, List landblocks) { results = new List(); links = new List(); foreach (var value in landblocks) { if (GDLEConverter.TryConvert(value, out var part1, out var part2)) { foreach (var instance in part1) { foreach (var link in part2) { if (link.ParentGuid == instance.Guid) instance.LandblockInstanceLink.Add(link); } results.Add(instance); } foreach (var part in part2) { links.Add(part); var child = results.FirstOrDefault(x => x.Guid == part.ChildGuid); if (child != null) child.IsLinkChild = true; } } } } /// /// This will sanitize the Guids for ACE use to the following format: 0x7LBID### where ### starts from [startingIdOffset] /// public static bool TryLoadWorldSpawnsConverted(string file, out List results, out List links, ushort startingIdOffset = 0) { try { var fileText = File.ReadAllText(file); var gdleModel = JsonSerializer.Deserialize(fileText); if (gdleModel.Landblocks == null) { results = null; links = null; return false; } ReGuidAndConvertLandblocks(out results, out links, startingIdOffset, gdleModel.Landblocks); return true; } catch { results = null; links = null; return false; } } public static bool TryLoadEvents(string file, out List results) { try { var fileText = File.ReadAllText(file); results = JsonSerializer.Deserialize>(fileText); return true; } catch { results = null; return false; } } public static bool TryLoadEventsConverted(string file, out List results) { try { var fileText = File.ReadAllText(file); var gdleModel = JsonSerializer.Deserialize>(fileText); results = new List(); foreach (var value in gdleModel) { if (GDLEConverter.TryConvert(value, out var result)) results.Add(result); } return true; } catch { results = null; return false; } } public static bool TryLoadQuest(string file, out Models.Quest result) { try { var fileText = File.ReadAllText(file); result = JsonSerializer.Deserialize(fileText); return true; } catch { result = null; return false; } } public static bool TryLoadQuests(string file, out List results) { try { var fileText = File.ReadAllText(file); results = JsonSerializer.Deserialize>(fileText); return true; } catch { results = null; return false; } } public static bool TryLoadQuestsConverted(string file, out List results) { try { var fileText = File.ReadAllText(file); var gdleModel = JsonSerializer.Deserialize>(fileText); results = new List(); foreach (var value in gdleModel) { if (GDLEConverter.TryConvert(value, out var result)) results.Add(result); } return true; } catch { results = null; return false; } } public static bool TryLoadSpells(string file, out Models.Spells result) { try { var fileText = File.ReadAllText(file); result = JsonSerializer.Deserialize(fileText); return true; } catch { result = null; return false; } } public static bool TryLoadSpellsConverted(string file, out List results) { try { var fileText = File.ReadAllText(file); var gdleModel = JsonSerializer.Deserialize(fileText); results = new List(); foreach (var value in gdleModel.Table.SpellBaseHash) { if (GDLEConverter.TryConvert(value.Key, value.Value, out var result)) results.Add(result); } return true; } catch { results = null; return false; } } public static bool TryLoadRecipe(string file, out Models.Recipe result) { try { var fileText = File.ReadAllText(file); result = JsonSerializer.Deserialize(fileText); return true; } catch { result = null; return false; } } public static bool TryLoadRecipeCombined(string file, out Models.RecipeCombined result) { try { var fileText = File.ReadAllText(file); result = JsonSerializer.Deserialize(fileText); return true; } catch { result = null; return false; } } public static bool TryLoadRecipeCombinedInParallel(string folder, out List results) { try { var files = Directory.GetFiles(folder, "*.json", SearchOption.AllDirectories); var recipes = new ConcurrentBag(); Parallel.ForEach(files, file => { if (TryLoadRecipeCombined(file, out var result)) recipes.Add(result); }); results = new List(recipes); return true; } catch { results = null; return false; } } public static bool TryLoadRecipeCombinedConverted(string folder, out List recipes, out List cookBooks) { try { TryLoadRecipeCombinedInParallel(folder, out var gdleModel); if (gdleModel == null) { recipes = null; cookBooks = null; return false; } recipes = new List(); cookBooks = new List(); foreach (var value in gdleModel) { if (GDLEConverter.TryConvert(value.recipe, out var result)) { foreach (var precursor in value.precursors) { if (GDLEConverter.TryConvert(precursor, out var result2)) { result2.RecipeId = value.key; cookBooks.Add(result2); } } recipes.Add(result); } } return true; } catch { recipes = null; cookBooks = null; return false; } } public static bool TryLoadRecipesConverted(string file, out List results) { try { var fileText = File.ReadAllText(file); var gdleModel = JsonSerializer.Deserialize>(fileText); results = new List(); foreach (var value in gdleModel) { if (GDLEConverter.TryConvert(value, out var result)) results.Add(result); } return true; } catch { results = null; return false; } } public static bool TryLoadRecipePrecursors(string file, out List results) { try { var fileText = File.ReadAllText(file); results = JsonSerializer.Deserialize>(fileText); return true; } catch { results = null; return false; } } public static bool TryLoadRecipePrecursorsConverted(string file, out List results) { try { var fileText = File.ReadAllText(file); var gdleModel = JsonSerializer.Deserialize>(fileText); results = new List(); foreach (var value in gdleModel) { if (GDLEConverter.TryConvert(value, out var result)) results.Add(result); } return true; } catch { results = null; return false; } } public static bool TryLoadRegion(string file, out Models.Region result) { try { var fileText = File.ReadAllText(file); result = JsonSerializer.Deserialize(fileText); return true; } catch { result = null; return false; } } public static bool TryLoadTerrainData(string file, out List results) { try { var fileText = File.ReadAllText(file); results = JsonSerializer.Deserialize>(fileText); return true; } catch { results = null; return false; } } public static bool TryLoadWieldedTreasureTable(string file, out List results) { try { var fileText = File.ReadAllText(file); results = JsonSerializer.Deserialize>(fileText); return true; } catch { results = null; return false; } } public static bool TryLoadWieldedTreasureTableConverted(string file, out List results) { try { var fileText = File.ReadAllText(file); var gdleModel = JsonSerializer.Deserialize>(fileText); results = new List(); foreach (var value in gdleModel) { if (GDLEConverter.TryConvert(value, out var result)) results.AddRange(result); } return true; } catch { results = null; return false; } } } }