From 6dad0eecee9c012f1ae45134269e8d8582076e8f Mon Sep 17 00:00:00 2001 From: neru Date: Thu, 18 Jun 2026 17:20:40 -0300 Subject: [PATCH] feat: add item dumper --- src/dumper/dumper.cs | 60 +++++++++++++++++++++++++++++++++++++++++++- src/dumper/main.cs | 14 +++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/dumper/dumper.cs b/src/dumper/dumper.cs index 91ccb8b..6adc179 100644 --- a/src/dumper/dumper.cs +++ b/src/dumper/dumper.cs @@ -21,15 +21,24 @@ struct CharacterInfo public string iconFilePath; } +struct ItemInfo +{ + public string id; + public string name; + public string iconFilePath; +} + class Dumper { private DefaultFileProvider? _provider; private IAesVfsReader? _dataPak; - private readonly Dictionary _characterMap = new(); private Logger _log; private string _outDir; + private readonly Dictionary _characterMap = new(); + private readonly Dictionary _itemMap = new(); + public Dumper(string outDir) { _log = new Logger("Dumper"); @@ -160,6 +169,55 @@ class Dumper return; } + public void DumpItems() + { + if (_dataPak == null || _provider == null) + throw new InvalidOperationException("Attempted to call dump function without dumper initialization"); + + _log.Info("Dumping character icons"); + + List itemDBPaths = _dataPak.Files.Keys.Where(x => x.Contains("/ItemDB.uasset", StringComparison.OrdinalIgnoreCase)).ToList(); + + foreach (string path in itemDBPaths) + { + string cleanPath = path.Contains('.') ? path[..path.LastIndexOf('.')] : path; + + if (_provider.TryLoadPackageObject(cleanPath, out UDataTable? dataTable)) + { + foreach (KeyValuePair row in dataTable.RowMap) + { + List props = row.Value.Properties; + + string itemId = row.Key.Text; + + if (!TryGetProp(props, "Type", out EInventoryItemType itemType) || !TryGetProp(props, "UIData", out FStructFallback uiDataFb)) + throw new KeyNotFoundException("Type or UIData was not found."); + + UIDataStruct uiData = uiDataFb.MapToStruct(); + + if (itemType != EInventoryItemType.Item) + { + _log.Verbose("Ignoring invalid item type ({0})", itemType.ToString()); + continue; + } + + if (uiData.IconAssetList.Length == 0) + throw new InvalidDataException("Item's UIData had no icons"); + + _itemMap[itemId] = new ItemInfo + { + id = itemId, + name = uiData.DisplayName.ToString(), + iconFilePath = uiData.IconAssetList[0].ToString() + }; + } + } + } + + WriteJson("items", _itemMap.Values); + _log.Info("Dumped all items"); + } + /* * internal helper functions */ diff --git a/src/dumper/main.cs b/src/dumper/main.cs index aa4fc88..19ef2de 100644 --- a/src/dumper/main.cs +++ b/src/dumper/main.cs @@ -24,6 +24,20 @@ catch (Exception er) return 1; } +log.Info("Getting item data and icons"); +try +{ + dumper.DumpItems(); +} +catch (Exception er) +{ + log.Error("Error while dumping items"); + log.Error("Exception: {0}", er.ToString()); + Console.ReadKey(); + return 1; + +} + log.Info("Dump finished"); return 0; \ No newline at end of file