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);
                }
            }
        }
Example #4
0
        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();
        }