public void TestOptionParsing() { var itemDefinitionFile = ItemDefinitionFile.Decode( this.Fixture.JavaClientCache.GetFile(CacheIndex.ItemDefinitions, 155).Entries[104] ); Assert.Equal("Attuned crystal teleport seed", itemDefinitionFile.Name); Assert.Equal(new [] { "Activate", "Put in pocket", "null", // "Lletya" in game. Probably dynamically hacked in via this "null" value? "Use", "null", // "Temple of Light" in game. Same deal here. "Destroy", "Examine", }, itemDefinitionFile.GetInventoryOptions()); Assert.Equal(new [] { "Remove", "Activate", null, null, null, "Examine", }, itemDefinitionFile.GetEquipOptions()); }
public void TestItemDefinitionFile(CacheIndex index, int fileId, int entryId, string expectedName, int expectedPropertyCount) { var itemDefinitionFile = ItemDefinitionFile.Decode( this.Fixture.JavaClientCache.GetFile(index, fileId).Entries[entryId] ); Assert.Equal(expectedName, itemDefinitionFile.Name); Assert.Equal(expectedPropertyCount, itemDefinitionFile.Properties?.Count); }
public void TestCreateItemCsv() { var headers = new List <string>(); using (var tempWriter = new StreamWriter(System.IO.File.Open("items.csv.tmp", FileMode.Create))) { foreach (var fileId in this.Fixture.DownloaderCache.GetAvailableFileIds(CacheIndex.ItemDefinitions)) { try { var entryFile = this.Fixture.DownloaderCache.GetFile(CacheIndex.ItemDefinitions, fileId); foreach (var entry in entryFile.Entries.Values) { var itemDefinitionFile = ItemDefinitionFile.Decode(entry); var row = new Dictionary <int, string>(); foreach (var field in itemDefinitionFile.GetFields()) { if (!headers.Contains(field.Key)) { headers.Add(field.Key); } row.Add(headers.IndexOf(field.Key), field.Value); } var lastIndex = row.Keys.Max(); for (var rowIndex = 0; rowIndex < lastIndex; rowIndex++) { if (rowIndex > 0) { tempWriter.Write(","); } if (row.ContainsKey(rowIndex)) { tempWriter.Write($"\"{row[rowIndex]?.Replace("\"", "\"\"")}\""); } } tempWriter.WriteLine(); } } catch (DecodeException) { } } } // Prepend headers using (var csvWriter = new StreamWriter(System.IO.File.OpenWrite("items.csv"))) { var headerCount = headers.Count; for (var headerIndex = 0; headerIndex < headerCount; headerIndex++) { if (headerIndex > 0) { csvWriter.Write(","); } csvWriter.Write($"\"{headers[headerIndex]}\""); } csvWriter.WriteLine(); foreach (var line in System.IO.File.ReadLines("items.csv.tmp")) { csvWriter.WriteLine(line); } } }
public void ExtractItemDefinitions(ReferenceTableCache cache, string jsonFilePath, bool skipUndecodableItems = false) { // Courtesy backup. if (System.IO.File.Exists(jsonFilePath)) { Log.Information("Backing up existing items JSON file..."); var backupFilepath = jsonFilePath + ".bak"; System.IO.File.Delete(backupFilepath); System.IO.File.Move(jsonFilePath, backupFilepath); } // Write JSON to string before writing it to file to intercept partial output. using var streamWriter = new StreamWriter(System.IO.File.Open(jsonFilePath, FileMode.Create)); using var jsonWriter = new JsonTextWriter(streamWriter) { Formatting = Formatting.Indented, Indentation = 2, }; var jsonSerializer = new JsonSerializer(); Log.Information("Downloading and writing items JSON..."); var itemReferenceTable = cache.GetReferenceTable(CacheIndex.ItemDefinitions); jsonWriter.WriteStartObject(); jsonWriter.WritePropertyName("version"); jsonWriter.WriteValue(itemReferenceTable.Version.GetValueOrDefault()); jsonWriter.WritePropertyName("protocol"); jsonWriter.WriteValue(ItemDefinitionExtractor.Protocol); jsonWriter.WritePropertyName("items"); jsonWriter.WriteStartArray(); var itemCount = 0; var undecodedItemCount = 0; var serializableProperties = typeof(ItemDefinitionFile).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var fileId in cache.GetAvailableFileIds(CacheIndex.ItemDefinitions)) { var entryFile = cache.GetFile(CacheIndex.ItemDefinitions, fileId); foreach (var entry in entryFile.Entries) { try { var itemDefinitionFile = ItemDefinitionFile.Decode(entry.Value); // TODO: An abstraction could be made to turn file ID into file + entry and vice versa. itemDefinitionFile.Id = fileId * 256 + entry.Key; jsonWriter.WriteStartObject(); foreach (var property in serializableProperties) { var propertyName = Formatter.StringToLowerCamelCase(property.Name); var propertyValue = property.GetValue(itemDefinitionFile); if (propertyValue == null) { continue; } // camelCase item properties and prefix with "unknown" when undefined. if (propertyName == "properties") { propertyValue = ((Dictionary <ItemProperty, object>)propertyValue) .ToDictionary( itemProperty => Formatter.StringToLowerCamelCase(Enum.GetName(typeof(ItemProperty), itemProperty.Key) ?? $"unknown{(int)itemProperty.Key}"), itemProperty => itemProperty.Value ); } // I tried using JsonSerializer for the entire file. Overriding individual properties // requires way to much boilerplate and changes on the original model. jsonWriter.WritePropertyName(propertyName); jsonSerializer.Serialize(jsonWriter, propertyValue); } jsonWriter.WriteEndObject(); itemCount++; } catch (DecodeException exception) { if (!skipUndecodableItems) { throw; } Log.Information($"Could not decode {(int)CacheIndex.ItemDefinitions}/{fileId}/{entry.Key}: {exception.Message}"); undecodedItemCount++; } } } jsonWriter.WriteEndArray(); jsonWriter.WritePropertyName("itemCount"); jsonWriter.WriteValue(itemCount); jsonWriter.WritePropertyName("undecodedItemCount"); jsonWriter.WriteValue(undecodedItemCount); jsonWriter.WriteEndObject(); }