Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ChestCategories v1.2.0
despr0grammer.ChestCategories.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace despr0grammer.ChestCategories { internal static class Actions { internal static Container HoveredStorage(Player player) { GameObject hoverObject = ((Humanoid)player).GetHoverObject(); Container val = (((Object)(object)hoverObject != (Object)null) ? hoverObject.GetComponentInParent<Container>() : null); if (!((Object)(object)val != (Object)null) || !ChestRegistry.IsStorage(val)) { return null; } return val; } internal static void OpenHud() { Categories.ReloadIfChanged(); CategoryHud.Open(HoveredStorage(Player.m_localPlayer)); } internal static string AssignChest(Container chest, Category category) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)chest == (Object)null || (Object)(object)localPlayer == (Object)null || !ChestRegistry.IsStorage(chest)) { return Text.ChestGone; } if (!ChestRegistry.CanUse(chest, localPlayer.GetPlayerID())) { return Text.NoAccess; } if (ChestTag.InUse(chest)) { return Text.ChestInUse; } if (!ChestTag.Set(chest, (category != null) ? category.Id : string.Empty)) { return Text.NoAccess; } if (category == null) { return Text.ChestCleared; } return Text.ChestSet(category.DisplayName(Text.Spanish)); } internal static void CycleHoveredChest(bool backwards) { Container val = HoveredStorage(Player.m_localPlayer); if ((Object)(object)val == (Object)null) { Notify(Text.LookAtChest); return; } Categories.ReloadIfChanged(); IReadOnlyList<Category> all = Categories.All; if (all.Count == 0) { Notify(Text.NoCategoriesDefined); return; } int num = IndexOf(ChestTag.Get(val)); int num2 = (backwards ? (num - 1) : (num + 1)); if (num2 >= all.Count) { num2 = -1; } else if (num2 < -1) { num2 = all.Count - 1; } Notify(AssignChest(val, (num2 >= 0) ? all[num2] : null)); } internal static void SortNearby() { Player localPlayer = Player.m_localPlayer; Stopwatch stopwatch = Stopwatch.StartNew(); Sorter.Report report = Sorter.Run(localPlayer); stopwatch.Stop(); if (!report.HadTargets) { Notify(Text.NoTaggedChests(Plugin.MenuKeyLabel), center: true); } else if (report.Moved == 0 && report.Stuck == 0) { Notify(Text.NothingToSort, center: true); } else { Notify(Text.Sorted(report.Moved, report.Stuck), center: true); } Plugin.Log.LogInfo((object)$"Sort: moved {report.Moved}, did not fit {report.Stuck}, took {stopwatch.ElapsedMilliseconds} ms"); } internal static string OrderNearby() { Player localPlayer = Player.m_localPlayer; Stopwatch stopwatch = Stopwatch.StartNew(); Orderer.Report report = Orderer.Run(localPlayer); stopwatch.Stop(); string text = ((report.Skipped > 0) ? Text.OrderSkipped : ((report.Moved == 0) ? Text.AlreadyOrdered : Text.Ordered(report.Moved, report.Inventories))); Notify(text, center: true); Plugin.Log.LogInfo((object)$"Order: moved {report.Moved} in {report.Inventories} places, skipped {report.Skipped}, took {stopwatch.ElapsedMilliseconds} ms"); return text; } internal static void Notify(string message, bool center = false) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)((!center) ? 1 : 2), message, 0, (Sprite)null, false); } } private static int IndexOf(string id) { IReadOnlyList<Category> all = Categories.All; for (int i = 0; i < all.Count; i++) { if (string.Equals(all[i].Id, id, StringComparison.OrdinalIgnoreCase)) { return i; } } return -1; } } internal static class Categories { private static readonly List<Category> Loaded = new List<Category>(); private static readonly Dictionary<string, Category> ByIdMap = new Dictionary<string, Category>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<SharedData, Category> Cache = new Dictionary<SharedData, Category>(); private static Dictionary<string, string> _prefabBySharedName; private static string _path; private static DateTime _stamp; private static string _diskText; private static bool _readFailed; private static string _sharedMine; private static bool _sharedPending; private static float _sharedPublishedAt; private static bool _sharedSynced; private static bool _sharedFirst = true; private static bool _sharedWarned; private static bool _backedUpBeforeShared; private static long _sharedWorld; private static bool _sharedDirty; private static float _sharedDirtySince; private static int _sharedTooBigVersion = -1; private static int _lastLoadProblems; private const float MaxUnpublishedSeconds = 60f; internal static int Version { get; private set; } internal static IReadOnlyList<Category> All => Loaded; internal static string FilePath => _path; internal static bool SharedActive { get; private set; } internal static int SharedRevision => SharedCodec.RevisionOf(_sharedMine); internal static void Initialize() { _path = Path.Combine(Paths.ConfigPath, "despr0grammer.ChestCategories.categories.txt"); if (!File.Exists(_path)) { try { WriteFile("# ChestCategories - categorías de cofres / chest categories\n#\n# Puedes editar este archivo a mano o desde el HUD del juego (tecla F7). Cuando guardas desde el HUD, el mod\n# reescribe el archivo entero: tus categorías se conservan y estos comentarios se vuelven a generar.\n# Edit this file by hand or from the in-game HUD (F7 key). Saving from the HUD rewrites the whole file:\n# your categories are kept and these comments are regenerated.\n#\n# Cada bloque [id] es una categoría. Si lo editas a mano, el mod recarga el archivo al abrir el HUD o pulsar F8.\n#\n# Claves / keys:\n# es / en = nombre en español / name in English\n# color = color en el HUD, #RRGGBB\n# item = nombre interno del objeto (el de la consola: spawn Wood), separados por comas.\n# Admite un * al principio o al final: Mead* *Uncooked\n# También acepta el nombre traducible del juego: $item_wood\n# type = tipo de objeto del juego: Material, Consumable, OneHandedWeapon, TwoHandedWeapon, TwoHandedWeaponLeft,\n# Bow, Shield, Helmet, Chest, Legs, Shoulder, Hands, Ammo, AmmoNonEquipable, Trophy, Torch, Tool, Utility,\n# Trinket, Fish, Misc, Customization ... y dos tipos derivados:\n# Food = consumible que da vida, aguante o eitr\n# Potion = consumible que no es comida (pociones, hidromieles)\n#\n# Prioridad, de más a menos específica: 1) nombre exacto (Wood, $item_wood), 2) nombre con * (Mead*), 3) type.\n# Dentro de cada nivel gana la primera categoría del archivo. Por eso un objeto que asignas a mano desde el HUD\n# (nombre exacto) siempre gana a las reglas por tipo de cualquier categoría.\n# Un cambio de id (lo que va entre corchetes) desvincula los cofres que ya lo tenían asignado.\n\n[wood]\nes = Madera\nen = Wood\ncolor = #C8864A\nitem = Wood, FineWood, RoundLog, ElderBark, YggdrasilWood, Blackwood, Frostwood\n\n[metals]\nes = Metales\nen = Metals\ncolor = #8DB4CC\nitem = Copper, Tin, Bronze, Iron, Silver, BlackMetal, Gold, Flametal*\nitem = CopperOre, TinOre, IronOre, IronScrap, SilverOre, BlackMetalScrap, GoldOre\nitem = BronzeNails, IronNails, Chain\n\n[stone]\nes = Piedras\nen = Stone\ncolor = #A5A9B8\nitem = Stone, Flint, Obsidian, Blackmarble, Grausten, Crystal\n\n[valuables]\nes = Tesoros\nen = Valuables\ncolor = #E0BE4A\nitem = Coins, Amber, AmberPearl, Ruby, SilverNecklace, GemstoneRed, GemstoneBlue, GemstoneGreen\n\n[hides]\nes = Pieles y cuero\nen = Hides and leather\ncolor = #B8895C\nitem = LeatherScraps, DeerHide, TrollHide, WolfPelt, LoxPelt, ScaleHide, MooseHide, SealHide, Leatherstraps\n\n[farming]\nes = Cultivo y semillas\nen = Farming and seeds\ncolor = #8FB24F\nitem = *Seeds, Acorn, FirCone, PineCone, Barley, Flax\n\n[vegetables]\nes = Vegetales y bayas\nen = Vegetables and berries\ncolor = #5FAE6E\nitem = Carrot, Turnip, Onion, Kale, Fiddleheadfern\nitem = Cloudberry, Raspberry, Blueberries, Pukeberries, Lingonberry, Vineberry\nitem = Mushroom, MushroomBlue, MushroomYellow, MushroomJotunPuffs, MushroomMagecap, MushroomSmokePuff\n\n[meats]\nes = Carnes\nen = Meats\ncolor = #C0524E\ntype = Fish\nitem = RawMeat, DeerMeat, WolfMeat, LoxMeat, SerpentMeat, BugMeat, MooseMeat, ChickenMeat, HareMeat\nitem = BjornMeat, BoneMawSerpentMeat, VoltureMeat, AsksvinMeat, NeckTail, FishRaw, RottenMeat\nitem = Cooked*, *MeatCooked, FishCooked, NeckTailGrilled\n\n[meals]\nes = Comidas preparadas\nen = Prepared meals\ncolor = #D99A3A\ntype = Food\nitem = Feast*, KaleChipsUncooked\n\n[cooking]\nes = Materiales para comida\nen = Cooking ingredients\ncolor = #C97BA6\nitem = BarleyFlour, BreadDough, Honey, RoyalJelly, ChickenEgg, Oat, Entrails, Bloodbag\nitem = sap, Dandelion, Thistle, SpiceDeepNorth, SealBlubber, GlowWorm\n\n[tools]\nes = Herramientas\nen = Tools\ncolor = #52AFA0\ntype = Tool, Torch\nitem = Pickaxe*, FishingRod*, FishingBait\n\n[potions]\nes = Pociones e hidromieles\nen = Potions and meads\ncolor = #9879C4\ntype = Potion\nitem = Mead*, BarleyWine*\n\n[weapons]\nes = Armas y escudos\nen = Weapons and shields\ncolor = #B83F4A\ntype = OneHandedWeapon, TwoHandedWeapon, TwoHandedWeaponLeft, Bow, Attach_Atgeir, Shield\n\n[armor]\nes = Armaduras\nen = Armor\ncolor = #5C86C4\ntype = Helmet, Chest, Legs, Shoulder, Hands\n\n[trinkets]\nes = Accesorios\nen = Accessories\ncolor = #D6B04A\ntype = Utility, Trinket\n\n[ammo]\nes = Munición\nen = Ammunition\ncolor = #C98A4E\ntype = Ammo, AmmoNonEquipable\n\n[trophies]\nes = Trofeos\nen = Trophies\ncolor = #CFCBE0\ntype = Trophy\n\n[drops]\nes = Botín de criaturas\nen = Creature drops\ncolor = #98A844\nitem = Bilebag, Ooze, OozeMork, Guck, BoneFragments, WolfFang, WolfClaw, WolfHairBundle\nitem = Mandible, Chitin, Carapace, Needle, Softtissue, HardAntler, Feathers, GreydwarfEye, FreezeGland\nitem = GiantBloodSack, SerpentScale, DragonTear, Root, MoleClaws, MooseSinew, ElakingHairBundle, WrithanRoots\n\n[other]\nes = Materiales varios\nen = Other materials\ncolor = #8E8A80\ntype = Material, Misc, Customization\n"); Plugin.Log.LogInfo((object)("Created the default categories file: " + _path)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not create " + _path + "; using the built-in categories. " + ex.Message)); } } else { UpgradeUntouchedDefaults(); } Load(); } private static void UpgradeUntouchedDefaults() { try { if (CategoryDefaults.IsUntouchedPreviousDefault(File.ReadAllText(_path, Encoding.UTF8))) { File.Copy(_path, _path + ".old-defaults.bak", overwrite: true); WriteFile("# ChestCategories - categorías de cofres / chest categories\n#\n# Puedes editar este archivo a mano o desde el HUD del juego (tecla F7). Cuando guardas desde el HUD, el mod\n# reescribe el archivo entero: tus categorías se conservan y estos comentarios se vuelven a generar.\n# Edit this file by hand or from the in-game HUD (F7 key). Saving from the HUD rewrites the whole file:\n# your categories are kept and these comments are regenerated.\n#\n# Cada bloque [id] es una categoría. Si lo editas a mano, el mod recarga el archivo al abrir el HUD o pulsar F8.\n#\n# Claves / keys:\n# es / en = nombre en español / name in English\n# color = color en el HUD, #RRGGBB\n# item = nombre interno del objeto (el de la consola: spawn Wood), separados por comas.\n# Admite un * al principio o al final: Mead* *Uncooked\n# También acepta el nombre traducible del juego: $item_wood\n# type = tipo de objeto del juego: Material, Consumable, OneHandedWeapon, TwoHandedWeapon, TwoHandedWeaponLeft,\n# Bow, Shield, Helmet, Chest, Legs, Shoulder, Hands, Ammo, AmmoNonEquipable, Trophy, Torch, Tool, Utility,\n# Trinket, Fish, Misc, Customization ... y dos tipos derivados:\n# Food = consumible que da vida, aguante o eitr\n# Potion = consumible que no es comida (pociones, hidromieles)\n#\n# Prioridad, de más a menos específica: 1) nombre exacto (Wood, $item_wood), 2) nombre con * (Mead*), 3) type.\n# Dentro de cada nivel gana la primera categoría del archivo. Por eso un objeto que asignas a mano desde el HUD\n# (nombre exacto) siempre gana a las reglas por tipo de cualquier categoría.\n# Un cambio de id (lo que va entre corchetes) desvincula los cofres que ya lo tenían asignado.\n\n[wood]\nes = Madera\nen = Wood\ncolor = #C8864A\nitem = Wood, FineWood, RoundLog, ElderBark, YggdrasilWood, Blackwood, Frostwood\n\n[metals]\nes = Metales\nen = Metals\ncolor = #8DB4CC\nitem = Copper, Tin, Bronze, Iron, Silver, BlackMetal, Gold, Flametal*\nitem = CopperOre, TinOre, IronOre, IronScrap, SilverOre, BlackMetalScrap, GoldOre\nitem = BronzeNails, IronNails, Chain\n\n[stone]\nes = Piedras\nen = Stone\ncolor = #A5A9B8\nitem = Stone, Flint, Obsidian, Blackmarble, Grausten, Crystal\n\n[valuables]\nes = Tesoros\nen = Valuables\ncolor = #E0BE4A\nitem = Coins, Amber, AmberPearl, Ruby, SilverNecklace, GemstoneRed, GemstoneBlue, GemstoneGreen\n\n[hides]\nes = Pieles y cuero\nen = Hides and leather\ncolor = #B8895C\nitem = LeatherScraps, DeerHide, TrollHide, WolfPelt, LoxPelt, ScaleHide, MooseHide, SealHide, Leatherstraps\n\n[farming]\nes = Cultivo y semillas\nen = Farming and seeds\ncolor = #8FB24F\nitem = *Seeds, Acorn, FirCone, PineCone, Barley, Flax\n\n[vegetables]\nes = Vegetales y bayas\nen = Vegetables and berries\ncolor = #5FAE6E\nitem = Carrot, Turnip, Onion, Kale, Fiddleheadfern\nitem = Cloudberry, Raspberry, Blueberries, Pukeberries, Lingonberry, Vineberry\nitem = Mushroom, MushroomBlue, MushroomYellow, MushroomJotunPuffs, MushroomMagecap, MushroomSmokePuff\n\n[meats]\nes = Carnes\nen = Meats\ncolor = #C0524E\ntype = Fish\nitem = RawMeat, DeerMeat, WolfMeat, LoxMeat, SerpentMeat, BugMeat, MooseMeat, ChickenMeat, HareMeat\nitem = BjornMeat, BoneMawSerpentMeat, VoltureMeat, AsksvinMeat, NeckTail, FishRaw, RottenMeat\nitem = Cooked*, *MeatCooked, FishCooked, NeckTailGrilled\n\n[meals]\nes = Comidas preparadas\nen = Prepared meals\ncolor = #D99A3A\ntype = Food\nitem = Feast*, KaleChipsUncooked\n\n[cooking]\nes = Materiales para comida\nen = Cooking ingredients\ncolor = #C97BA6\nitem = BarleyFlour, BreadDough, Honey, RoyalJelly, ChickenEgg, Oat, Entrails, Bloodbag\nitem = sap, Dandelion, Thistle, SpiceDeepNorth, SealBlubber, GlowWorm\n\n[tools]\nes = Herramientas\nen = Tools\ncolor = #52AFA0\ntype = Tool, Torch\nitem = Pickaxe*, FishingRod*, FishingBait\n\n[potions]\nes = Pociones e hidromieles\nen = Potions and meads\ncolor = #9879C4\ntype = Potion\nitem = Mead*, BarleyWine*\n\n[weapons]\nes = Armas y escudos\nen = Weapons and shields\ncolor = #B83F4A\ntype = OneHandedWeapon, TwoHandedWeapon, TwoHandedWeaponLeft, Bow, Attach_Atgeir, Shield\n\n[armor]\nes = Armaduras\nen = Armor\ncolor = #5C86C4\ntype = Helmet, Chest, Legs, Shoulder, Hands\n\n[trinkets]\nes = Accesorios\nen = Accessories\ncolor = #D6B04A\ntype = Utility, Trinket\n\n[ammo]\nes = Munición\nen = Ammunition\ncolor = #C98A4E\ntype = Ammo, AmmoNonEquipable\n\n[trophies]\nes = Trofeos\nen = Trophies\ncolor = #CFCBE0\ntype = Trophy\n\n[drops]\nes = Botín de criaturas\nen = Creature drops\ncolor = #98A844\nitem = Bilebag, Ooze, OozeMork, Guck, BoneFragments, WolfFang, WolfClaw, WolfHairBundle\nitem = Mandible, Chitin, Carapace, Needle, Softtissue, HardAntler, Feathers, GreydwarfEye, FreezeGland\nitem = GiantBloodSack, SerpentScale, DragonTear, Root, MoleClaws, MooseSinew, ElakingHairBundle, WrithanRoots\n\n[other]\nes = Materiales varios\nen = Other materials\ncolor = #8E8A80\ntype = Material, Misc, Customization\n"); Plugin.Log.LogInfo((object)("The categories file was never edited, so it was updated to the new default categories (the old one is kept as " + Path.GetFileName(_path) + ".old-defaults.bak)")); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not update the default categories file: " + ex.Message)); } } internal static void ReloadIfChanged() { try { if (!File.Exists(_path) || !(File.GetLastWriteTimeUtc(_path) != _stamp)) { return; } Load(); if (SharedActive) { if (Loaded.Count > 0 && _lastLoadProblems == 0) { MarkSharedDirty(); } else { Plugin.Log.LogWarning((object)"The categories file has problems or no categories, so this change is not shared with the world until it is fixed."); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not check the categories file: " + ex.Message)); } } internal static Category Get(string id) { if (string.IsNullOrEmpty(id) || !ByIdMap.TryGetValue(id, out var value)) { return null; } return value; } internal static Color ColorOf(Category category, Color fallback) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) Color color = default(Color); if (category == null || category.Color == null || !ColorUtility.TryParseHtmlString(category.Color, ref color)) { return fallback; } return Tame(color); } internal static Color Tame(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) float num = default(float); float num2 = default(float); float num3 = default(float); Color.RGBToHSV(color, ref num, ref num2, ref num3); if (num2 > 0.55f) { num2 = 0.55f + (num2 - 0.55f) * 0.3f; } return Color.HSVToRGB(num, num2, Mathf.Clamp(num3, 0.55f, 0.9f)); } internal static Category Of(ItemData item) { SharedData val = item?.m_shared; if (val == null) { return null; } if (!Cache.TryGetValue(val, out var value)) { value = Resolve(PrefabName(item), val); Cache[val] = value; } return value; } internal static Category Resolve(string prefab, SharedData shared) { string text = ((object)Unsafe.As<ItemType, ItemType>(ref shared.m_itemType)/*cast due to .constrained prefix*/).ToString(); bool flag = text == "Consumable"; bool flag2 = flag && (shared.m_food > 0f || shared.m_foodStamina > 0f || shared.m_foodEitr > 0f); return CategoryFile.Classify(Loaded, prefab, shared.m_name, text, flag2, flag && !flag2); } internal static void SyncShared(bool hudOpen) { ZoneSystem instance = ZoneSystem.instance; if (!Plugin.ShareCategories.Value || (Object)(object)instance == (Object)null || ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null) { return; } long worldUID = ZNet.instance.GetWorldUID(); if (worldUID != _sharedWorld) { ResetShared(); _sharedWorld = worldUID; } string store = StoreValue(instance); _sharedSynced = true; if (_sharedDirty) { if (!hudOpen || Time.unscaledTime - _sharedDirtySince >= 60f) { PublishShared(); } } else { AdoptOrSeed(store); } } private static void AdoptOrSeed(string store) { if (store == _sharedMine) { _sharedPending = false; } SyncAction syncAction = SharedCodec.Decide(store, _sharedMine, _sharedPending, Time.unscaledTime - _sharedPublishedAt); switch (syncAction) { case SyncAction.Adopt: AdoptShared(store); return; case SyncAction.Seed: if (Loaded.Count > 0 && _sharedTooBigVersion != Version) { PublishShared(); return; } break; } if (syncAction == SyncAction.None && store != null && SharedCodec.RevisionOf(store) < 0 && !_sharedWarned) { _sharedWarned = true; Plugin.Log.LogWarning((object)"The world has a value under the shared categories key that this version cannot read (a newer version of the mod?); it is left alone and the categories are not shared."); } } private static void BeforeEdit() { ZoneSystem instance = ZoneSystem.instance; if (Plugin.ShareCategories.Value && _sharedSynced && !_sharedDirty && (Object)(object)instance != (Object)null && ZRoutedRpc.instance != null) { AdoptOrSeed(StoreValue(instance)); } } private static Category Fresh(Category category) { object obj; if (category != null) { obj = Get(category.Id); if (obj == null) { return category; } } else { obj = null; } return (Category)obj; } private static void MarkSharedDirty() { if (Plugin.ShareCategories.Value && _sharedSynced && !_sharedDirty) { _sharedDirty = true; _sharedDirtySince = Time.unscaledTime; } } private static void ResetShared() { _sharedMine = null; _sharedPending = false; _sharedSynced = false; _sharedFirst = true; _sharedWarned = false; _backedUpBeforeShared = false; _sharedDirty = false; _sharedTooBigVersion = -1; SharedActive = false; } private static string StoreValue(ZoneSystem zones) { string result = default(string); if (!zones.GetGlobalKey("despr0grammer_chestcategories", ref result)) { return null; } return result; } private static void AdoptShared(string store) { if (!SharedCodec.TryDecode(store, out var revision, out var text)) { if (!_sharedWarned) { _sharedWarned = true; Plugin.Log.LogWarning((object)"The world's shared categories could not be read (damaged?); they are left alone."); } return; } List<string> list = new List<string>(); List<Category> list2 = CategoryFile.Parse(text.Split('\n'), list); foreach (string item in list) { Plugin.Log.LogWarning((object)("Shared categories: " + item)); } ValidateTypes(list2); KeepListBeforeShared(list2); bool num = _sharedPending && _sharedMine != null; Loaded.Clear(); Loaded.AddRange(list2); Reindex(); bool flag = Save(); _sharedMine = store; _sharedPending = false; SharedActive = true; if (num) { Plugin.Log.LogWarning((object)"The last change to the shared categories did not reach the world (or another player's change replaced it); using the world's list."); } Plugin.Log.LogInfo((object)string.Format("Using the world's shared categories (revision {0}, {1} categories){2}", revision, Loaded.Count, flag ? string.Empty : "; the local file could not be updated")); Actions.Notify(_sharedFirst ? Text.SharedLoaded : Text.SharedUpdated); _sharedFirst = false; } private static void PublishShared() { ZoneSystem instance = ZoneSystem.instance; if (!Plugin.ShareCategories.Value || !_sharedSynced || (Object)(object)instance == (Object)null || ZRoutedRpc.instance == null || _readFailed) { return; } _sharedDirty = false; string text = StoreValue(instance); if (text != null && SharedCodec.RevisionOf(text) < 0) { if (!_sharedWarned) { _sharedWarned = true; Plugin.Log.LogWarning((object)"The world has a value under the shared categories key that this version cannot read; it is left alone and the categories are not shared."); } return; } int num = Math.Max(SharedCodec.RevisionOf(text), Math.Max(SharedCodec.RevisionOf(_sharedMine), 0)); if (num >= 2147483646) { Plugin.Log.LogWarning((object)"The shared categories have reached the highest revision there is; they cannot be shared any more."); return; } int num2 = num + 1; string text2 = SharedCodec.Encode(num2, CategoryFile.SerializeBody(Loaded)); if (text2.Length > 60000) { if (_sharedTooBigVersion != Version) { _sharedTooBigVersion = Version; Plugin.Log.LogWarning((object)$"The category list is too big to share ({text2.Length} characters; the limit is {60000}); it stays on this game only."); } } else { instance.SetGlobalKey("despr0grammer_chestcategories " + text2); _sharedMine = text2; _sharedPending = true; _sharedPublishedAt = Time.unscaledTime; SharedActive = true; Plugin.Log.LogInfo((object)$"Shared the categories with the world (revision {num2}, {Loaded.Count} categories)"); } } private static void KeepListBeforeShared(List<Category> adopted) { if (_backedUpBeforeShared) { return; } _backedUpBeforeShared = true; try { if (File.Exists(_path) && !(CategoryFile.SerializeBody(Loaded) == CategoryFile.SerializeBody(adopted))) { string text = $"{_path}.before-shared-{DateTime.Now:yyyyMMdd-HHmmss}"; File.Copy(_path, text, overwrite: true); Plugin.Log.LogInfo((object)("Kept the local categories as " + Path.GetFileName(text) + " before using the world's.")); string[] files = Directory.GetFiles(Path.GetDirectoryName(_path), Path.GetFileName(_path) + ".before-shared-*"); Array.Sort(files, (IComparer<string>?)StringComparer.Ordinal); for (int i = 0; i < files.Length - 5; i++) { File.Delete(files[i]); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not keep the local categories before using the world's: " + ex.Message)); } } internal static Category Create(string name, out bool saved) { BeforeEdit(); Category category = CategoryEditor.Add(Loaded, name); saved = category == null || Commit(); return category; } internal static bool Delete(Category category) { BeforeEdit(); if (!CategoryEditor.Remove(Loaded, category.Id)) { return true; } return Commit(); } internal static bool Rename(Category category, string spanish, string english) { BeforeEdit(); if (CategoryEditor.Rename(Fresh(category), spanish, english)) { return Commit(); } return true; } internal static bool SetColor(Category category, string color) { BeforeEdit(); category = Fresh(category); if (!CategoryFile.IsValidColor(color) || string.Equals(category.Color, color, StringComparison.OrdinalIgnoreCase)) { return true; } category.Color = color.ToUpperInvariant(); return Commit(); } internal static bool AssignItem(Category category, string prefab) { BeforeEdit(); CategoryEditor.Assign(Loaded, Fresh(category), prefab); return Commit(); } internal static bool UnassignItem(Category category, string prefab) { BeforeEdit(); if (CategoryEditor.Unassign(Fresh(category), prefab)) { return Commit(); } return true; } internal static bool RemovePattern(Category category, string pattern) { BeforeEdit(); if (Fresh(category).Patterns.Remove(pattern)) { return Commit(); } return true; } internal static bool RemoveType(Category category, string type) { BeforeEdit(); if (Fresh(category).Types.Remove(type)) { return Commit(); } return true; } private static bool Commit() { Reindex(); bool result = Save(); MarkSharedDirty(); return result; } private static void Reindex() { ByIdMap.Clear(); foreach (Category item in Loaded) { ByIdMap[item.Id] = item; } Cache.Clear(); Version++; } private static bool Save() { if (_readFailed) { Plugin.Log.LogError((object)("Not saving: " + _path + " could not be read earlier, and saving now would overwrite it with the built-in categories.")); return false; } try { BackUpOnce(); BackUpIfEditedElsewhere(); _diskText = WriteFile(CategoryFile.Serialize(Loaded)); _stamp = File.GetLastWriteTimeUtc(_path); return true; } catch (Exception ex) { Plugin.Log.LogError((object)("Could not save " + _path + ": " + ex.Message)); return false; } } private static void BackUpOnce() { string text = _path + ".bak"; if (File.Exists(_path) && !File.Exists(text)) { File.Copy(_path, text); } } private static void BackUpIfEditedElsewhere() { if (_diskText != null && File.Exists(_path) && !(File.ReadAllText(_path, Encoding.UTF8) == _diskText)) { string text = $"{_path}.bak-{DateTime.Now:yyyyMMdd-HHmmss}"; File.Copy(_path, text, overwrite: true); Plugin.Log.LogWarning((object)("The categories file was changed outside the game since it was loaded; its content was kept as " + Path.GetFileName(text) + " before saving.")); } } private static string WriteFile(string text) { string text2 = text.Replace("\r\n", "\n").Replace("\n", Environment.NewLine); string text3 = _path + ".tmp"; File.WriteAllText(text3, text2, new UTF8Encoding(encoderShouldEmitUTF8Identifier: true)); try { if (File.Exists(_path)) { File.Replace(text3, _path, _path + ".prev"); } else { File.Move(text3, _path); } } catch (Exception) { File.Copy(text3, _path, overwrite: true); try { File.Delete(text3); } catch (Exception) { } } return text2; } private static void Load() { List<string> list = new List<string>(); DateTime minValue = DateTime.MinValue; string text = null; bool readFailed = false; List<Category> list2; try { minValue = File.GetLastWriteTimeUtc(_path); text = File.ReadAllText(_path, Encoding.UTF8); list2 = CategoryFile.Parse(text.Split('\n'), list); } catch (Exception ex) { readFailed = true; minValue = DateTime.MinValue; text = null; Plugin.Log.LogWarning((object)("Could not read " + _path + "; using the built-in categories until it can be read. " + ex.Message)); list2 = CategoryFile.Parse("# ChestCategories - categorías de cofres / chest categories\n#\n# Puedes editar este archivo a mano o desde el HUD del juego (tecla F7). Cuando guardas desde el HUD, el mod\n# reescribe el archivo entero: tus categorías se conservan y estos comentarios se vuelven a generar.\n# Edit this file by hand or from the in-game HUD (F7 key). Saving from the HUD rewrites the whole file:\n# your categories are kept and these comments are regenerated.\n#\n# Cada bloque [id] es una categoría. Si lo editas a mano, el mod recarga el archivo al abrir el HUD o pulsar F8.\n#\n# Claves / keys:\n# es / en = nombre en español / name in English\n# color = color en el HUD, #RRGGBB\n# item = nombre interno del objeto (el de la consola: spawn Wood), separados por comas.\n# Admite un * al principio o al final: Mead* *Uncooked\n# También acepta el nombre traducible del juego: $item_wood\n# type = tipo de objeto del juego: Material, Consumable, OneHandedWeapon, TwoHandedWeapon, TwoHandedWeaponLeft,\n# Bow, Shield, Helmet, Chest, Legs, Shoulder, Hands, Ammo, AmmoNonEquipable, Trophy, Torch, Tool, Utility,\n# Trinket, Fish, Misc, Customization ... y dos tipos derivados:\n# Food = consumible que da vida, aguante o eitr\n# Potion = consumible que no es comida (pociones, hidromieles)\n#\n# Prioridad, de más a menos específica: 1) nombre exacto (Wood, $item_wood), 2) nombre con * (Mead*), 3) type.\n# Dentro de cada nivel gana la primera categoría del archivo. Por eso un objeto que asignas a mano desde el HUD\n# (nombre exacto) siempre gana a las reglas por tipo de cualquier categoría.\n# Un cambio de id (lo que va entre corchetes) desvincula los cofres que ya lo tenían asignado.\n\n[wood]\nes = Madera\nen = Wood\ncolor = #C8864A\nitem = Wood, FineWood, RoundLog, ElderBark, YggdrasilWood, Blackwood, Frostwood\n\n[metals]\nes = Metales\nen = Metals\ncolor = #8DB4CC\nitem = Copper, Tin, Bronze, Iron, Silver, BlackMetal, Gold, Flametal*\nitem = CopperOre, TinOre, IronOre, IronScrap, SilverOre, BlackMetalScrap, GoldOre\nitem = BronzeNails, IronNails, Chain\n\n[stone]\nes = Piedras\nen = Stone\ncolor = #A5A9B8\nitem = Stone, Flint, Obsidian, Blackmarble, Grausten, Crystal\n\n[valuables]\nes = Tesoros\nen = Valuables\ncolor = #E0BE4A\nitem = Coins, Amber, AmberPearl, Ruby, SilverNecklace, GemstoneRed, GemstoneBlue, GemstoneGreen\n\n[hides]\nes = Pieles y cuero\nen = Hides and leather\ncolor = #B8895C\nitem = LeatherScraps, DeerHide, TrollHide, WolfPelt, LoxPelt, ScaleHide, MooseHide, SealHide, Leatherstraps\n\n[farming]\nes = Cultivo y semillas\nen = Farming and seeds\ncolor = #8FB24F\nitem = *Seeds, Acorn, FirCone, PineCone, Barley, Flax\n\n[vegetables]\nes = Vegetales y bayas\nen = Vegetables and berries\ncolor = #5FAE6E\nitem = Carrot, Turnip, Onion, Kale, Fiddleheadfern\nitem = Cloudberry, Raspberry, Blueberries, Pukeberries, Lingonberry, Vineberry\nitem = Mushroom, MushroomBlue, MushroomYellow, MushroomJotunPuffs, MushroomMagecap, MushroomSmokePuff\n\n[meats]\nes = Carnes\nen = Meats\ncolor = #C0524E\ntype = Fish\nitem = RawMeat, DeerMeat, WolfMeat, LoxMeat, SerpentMeat, BugMeat, MooseMeat, ChickenMeat, HareMeat\nitem = BjornMeat, BoneMawSerpentMeat, VoltureMeat, AsksvinMeat, NeckTail, FishRaw, RottenMeat\nitem = Cooked*, *MeatCooked, FishCooked, NeckTailGrilled\n\n[meals]\nes = Comidas preparadas\nen = Prepared meals\ncolor = #D99A3A\ntype = Food\nitem = Feast*, KaleChipsUncooked\n\n[cooking]\nes = Materiales para comida\nen = Cooking ingredients\ncolor = #C97BA6\nitem = BarleyFlour, BreadDough, Honey, RoyalJelly, ChickenEgg, Oat, Entrails, Bloodbag\nitem = sap, Dandelion, Thistle, SpiceDeepNorth, SealBlubber, GlowWorm\n\n[tools]\nes = Herramientas\nen = Tools\ncolor = #52AFA0\ntype = Tool, Torch\nitem = Pickaxe*, FishingRod*, FishingBait\n\n[potions]\nes = Pociones e hidromieles\nen = Potions and meads\ncolor = #9879C4\ntype = Potion\nitem = Mead*, BarleyWine*\n\n[weapons]\nes = Armas y escudos\nen = Weapons and shields\ncolor = #B83F4A\ntype = OneHandedWeapon, TwoHandedWeapon, TwoHandedWeaponLeft, Bow, Attach_Atgeir, Shield\n\n[armor]\nes = Armaduras\nen = Armor\ncolor = #5C86C4\ntype = Helmet, Chest, Legs, Shoulder, Hands\n\n[trinkets]\nes = Accesorios\nen = Accessories\ncolor = #D6B04A\ntype = Utility, Trinket\n\n[ammo]\nes = Munición\nen = Ammunition\ncolor = #C98A4E\ntype = Ammo, AmmoNonEquipable\n\n[trophies]\nes = Trofeos\nen = Trophies\ncolor = #CFCBE0\ntype = Trophy\n\n[drops]\nes = Botín de criaturas\nen = Creature drops\ncolor = #98A844\nitem = Bilebag, Ooze, OozeMork, Guck, BoneFragments, WolfFang, WolfClaw, WolfHairBundle\nitem = Mandible, Chitin, Carapace, Needle, Softtissue, HardAntler, Feathers, GreydwarfEye, FreezeGland\nitem = GiantBloodSack, SerpentScale, DragonTear, Root, MoleClaws, MooseSinew, ElakingHairBundle, WrithanRoots\n\n[other]\nes = Materiales varios\nen = Other materials\ncolor = #8E8A80\ntype = Material, Misc, Customization\n".Split('\n'), list); } _readFailed = readFailed; _diskText = text; _lastLoadProblems = list.Count; foreach (string item in list) { Plugin.Log.LogWarning((object)("despr0grammer.ChestCategories.categories.txt: " + item)); } ValidateTypes(list2); Loaded.Clear(); Loaded.AddRange(list2); Reindex(); _stamp = minValue; Plugin.Log.LogInfo((object)$"Loaded {Loaded.Count} chest categories"); if (Loaded.Count == 0) { Plugin.Log.LogWarning((object)"The categories file defines no categories, so chests cannot be tagged."); } } private static void ValidateTypes(List<Category> categories) { HashSet<string> hashSet = new HashSet<string>(Enum.GetNames(typeof(ItemType)), StringComparer.OrdinalIgnoreCase) { "Food", "Potion" }; foreach (Category category in categories) { foreach (string type in category.Types) { if (!hashSet.Contains(type)) { Plugin.Log.LogWarning((object)("despr0grammer.ChestCategories.categories.txt: [" + category.Id + "] type '" + type + "' is not an item type of this game version")); } } } } private static string PrefabName(ItemData item) { GameObject dropPrefab = item.m_dropPrefab; if ((Object)(object)dropPrefab != (Object)null) { return StripClone(((Object)dropPrefab).name); } return PrefabNameFromObjectDb(item.m_shared.m_name); } private static string PrefabNameFromObjectDb(string sharedName) { if (_prefabBySharedName == null) { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || instance.m_items == null || instance.m_items.Count == 0) { return null; } Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (GameObject item in instance.m_items) { string text = ((!((Object)(object)item != (Object)null)) ? null : item.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_name); if (!string.IsNullOrEmpty(text) && !dictionary.ContainsKey(text)) { dictionary[text] = ((Object)item).name; } } _prefabBySharedName = dictionary; } if (!_prefabBySharedName.TryGetValue(sharedName, out var value)) { return null; } return value; } private static string StripClone(string name) { if (!name.EndsWith("(Clone)", StringComparison.Ordinal)) { return name; } return name.Substring(0, name.Length - "(Clone)".Length); } } internal static class CategoryHud { private static int _blockUntilFrame = -1; internal static bool Available { get; set; } internal static bool IsOpen { get; private set; } internal static Container Chest { get; private set; } internal static CategoryHudWindow Window { get; set; } internal static bool Blocking { get { if (!IsOpen) { return Time.frameCount <= _blockUntilFrame; } return true; } } internal static void Open(Container chest) { if (!Available || (Object)(object)Window == (Object)null || IsOpen) { return; } Chest = chest; IsOpen = true; try { Window.OnOpened(chest); ((Behaviour)Window).enabled = true; } catch (Exception arg) { Plugin.Log.LogError((object)$"The category HUD could not open: {arg}"); Close(); } } internal static void Close() { if (IsOpen) { IsOpen = false; Chest = null; _blockUntilFrame = Time.frameCount + 1; if ((Object)(object)Window != (Object)null) { ((Behaviour)Window).enabled = false; } } } } internal sealed class CategoryHudWindow : MonoBehaviour { private struct RuleRow { internal string Title; internal string Sub; internal Sprite Icon; internal int Kind; internal string Key; } private const float PanelMaxWidth = 920f; private const float PanelMaxHeight = 660f; private const float RuleRowHeight = 44f; private const float ItemRowHeight = 46f; private const float ContentTop = 138f; private const float ContentBottom = 44f; private int _tab; private string _selectedId; private bool _picking; private bool _creating; private bool _focusNewName; private bool _focusSearch; private bool _confirmDelete; private string _newName = string.Empty; private string _search = string.Empty; private int _filter; private Vector2 _scrollGrid; private Vector2 _scrollCategories; private Vector2 _scrollRules; private Vector2 _scrollItems; private string _nameEs = string.Empty; private string _nameEn = string.Empty; private string _buffersFor; private string _status; private float _statusUntil; private readonly List<RuleRow> _rules = new List<RuleRow>(); private string _rulesFor; private int _rulesVersion = -1; private string _rulesLanguage; private int _rulesGeneration = -1; private readonly List<CatalogEntry> _filtered = new List<CatalogEntry>(700); private string _filteredSearch; private int _filteredFilter = -1; private int _filteredVersion = -1; private string _filteredFor; private int _filteredInventory = -1; private int _filteredGeneration = -1; private readonly HashSet<string> _inventory = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private int _inventoryStamp; private float _inventoryRead = -10f; private void Awake() { ((Behaviour)this).enabled = false; } internal void OnOpened(Container chest) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) _tab = ((!((Object)(object)chest != (Object)null)) ? 1 : 0); _picking = false; _creating = false; _confirmDelete = false; _status = null; _search = string.Empty; _filter = 0; _buffersFor = null; _scrollGrid = Vector2.zero; _scrollCategories = Vector2.zero; _scrollRules = Vector2.zero; _scrollItems = Vector2.zero; Category category = (((Object)(object)chest != (Object)null) ? Categories.Get(ChestTag.Get(chest)) : null); if (category != null) { _selectedId = category.Id; } else if (Categories.Get(_selectedId) == null) { _selectedId = ((Categories.All.Count > 0) ? Categories.All[0].Id : null); } } private void Update() { if (CategoryHud.IsOpen) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting() || Menu.IsVisible() || InventoryGui.IsVisible() || Console.IsVisible() || Input.GetKeyDown((KeyCode)27)) { CategoryHud.Close(); } } } private void OnGUI() { if (!CategoryHud.IsOpen) { return; } try { Draw(); } catch (ExitGUIException) { throw; } catch (Exception arg) { Plugin.Log.LogError((object)$"The category HUD failed and was closed: {arg}"); CategoryHud.Close(); } } private void Draw() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) HudStyle.Ensure(); GUI.depth = -100; GUISkin skin = GUI.skin; GUI.skin = HudStyle.Skin; float num = Mathf.Clamp((float)Screen.height / 1080f, 0.75f, 3f) * Plugin.HudScale.Value; GUI.matrix = Matrix4x4.Scale(new Vector3(num, num, 1f)); float num2 = (float)Screen.width / num; float num3 = (float)Screen.height / num; float num4 = Mathf.Min(920f, num2 - 40f); float num5 = Mathf.Min(660f, num3 - 40f); GUI.BeginGroup(new Rect((num2 - num4) / 2f, (num3 - num5) / 2f, num4, num5)); try { DrawFrame(num4, num5); DrawTabs(num4); Rect val = default(Rect); ((Rect)(ref val))..ctor(28f, 138f, num4 - 56f, num5 - 138f - 44f); GUI.BeginGroup(val); try { if (_tab == 0) { DrawChestTab(((Rect)(ref val)).width, ((Rect)(ref val)).height); } else { DrawCategoriesTab(((Rect)(ref val)).width, ((Rect)(ref val)).height); } } finally { GUI.EndGroup(); } DrawFooter(num4, num5); } finally { GUI.EndGroup(); GUI.matrix = Matrix4x4.identity; GUI.skin = skin; } } private void DrawFrame(float width, float height) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) HudStyle.Frame(new Rect(0f, 0f, width, height)); HudStyle.DrawTitle(new Rect(70f, 18f, width - 140f, 50f), Text.HudTitle); HudStyle.Divider(60f, width - 60f, 74f); if (GUI.Button(new Rect(width - 66f, 24f, 38f, 34f), "X", HudStyle.Button)) { CategoryHud.Close(); } } private void DrawTabs(float width) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) string[] array = new string[2] { Text.TabChest, Text.TabCategories }; for (int i = 0; i < array.Length; i++) { if (GUI.Button(new Rect(28f + (float)i * 178f, 90f, 170f, 36f), array[i], (_tab == i) ? HudStyle.TabOn : HudStyle.Button)) { _tab = i; _picking = false; } } if (GUI.Button(new Rect(width - 28f - 220f, 90f, 220f, 36f), Text.OrderChests, HudStyle.Button)) { Say(RunOrder()); } } private static string RunOrder() { try { return Actions.OrderNearby(); } catch (Exception arg) { Plugin.Log.LogError((object)$"Order failed: {arg}"); return Text.OrderSkipped; } } private void DrawFooter(float width, float height) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) HudStyle.Shadowed(new Rect(32f, height - 36f, 300f, 26f), Text.FooterHint(Plugin.MenuKeyLabel), HudStyle.Small); bool flag = Categories.SharedActive && Plugin.ShareCategories.Value; if (flag) { HudStyle.Shadowed(new Rect(width - 190f, height - 36f, 160f, 26f), Text.SharedFooter(Categories.SharedRevision), HudStyle.Small); } if (_status != null && Time.unscaledTime < _statusUntil) { HudStyle.Shadowed(new Rect(340f, height - 36f, width - (flag ? 540f : 380f), 26f), _status, HudStyle.Notice); } } private void Say(string message) { _status = message; _statusUntil = Time.unscaledTime + 4f; } private void DrawChestTab(float width, float height) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) Container chest = CategoryHud.Chest; Player localPlayer = Player.m_localPlayer; int num; int num2; if ((Object)(object)chest != (Object)null && (Object)(object)localPlayer != (Object)null) { num = (ChestRegistry.IsStorage(chest) ? 1 : 0); if (num != 0) { num2 = (ChestRegistry.CanUse(chest, localPlayer.GetPlayerID()) ? 1 : 0); goto IL_0039; } } else { num = 0; } num2 = 0; goto IL_0039; IL_0039: bool flag = (byte)num2 != 0; string text = ((num != 0) ? ChestTag.Get(chest) : string.Empty); Category category = Categories.Get(text); if (num == 0) { HudStyle.Shadowed(new Rect(0f, 0f, width, 60f), Text.NoChestTarget(Plugin.MenuKeyLabel), HudStyle.Wrap); } else { HudStyle.Shadowed(new Rect(0f, 0f, width, 28f), Text.ChestHeader(Localization.instance.Localize(chest.m_name)), HudStyle.Heading); HudStyle.Shadowed(new Rect(0f, 32f, 190f, 26f), Text.CurrentCategory + ":", HudStyle.Small); Color contentColor = GUI.contentColor; GUI.contentColor = Categories.ColorOf(category, HudStyle.Dim); HudStyle.Shadowed(text: (category != null) ? category.DisplayName(Text.Spanish) : ((text.Length > 0) ? Text.UnknownCategory(text) : Text.NoCategory), rect: new Rect(190f, 32f, width - 190f, 26f), style: HudStyle.Plain); GUI.contentColor = contentColor; if (!flag) { HudStyle.Shadowed(new Rect(width - 330f, 0f, 330f, 28f), Text.NoAccess, HudStyle.Small); } } IReadOnlyList<Category> all = Categories.All; int num3 = all.Count + 1; int num4 = Mathf.Max(1, Mathf.FloorToInt((width - 16f) / 250f)); float num5 = (width - 16f - (float)(num4 - 1) * 8f) / (float)num4; int num6 = Mathf.CeilToInt((float)num3 / (float)num4); Rect val = default(Rect); ((Rect)(ref val))..ctor(0f, 66f, width, height - 66f - 48f); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(0f, 0f, width - 16f, (float)num6 * 54f); _scrollGrid = GUI.BeginScrollView(val, _scrollGrid, val2); Rect val3 = default(Rect); for (int i = 0; i < num3; i++) { ((Rect)(ref val3))..ctor((float)(i % num4) * (num5 + 8f), (float)(i / num4) * 54f, num5, 46f); Category category2 = ((i == 0) ? null : all[i - 1]); bool selected = ((category2 == null) ? (text.Length == 0) : string.Equals(text, category2.Id, StringComparison.OrdinalIgnoreCase)); DrawCategoryCell(val3, category2, selected, flag); if (flag && GUI.Button(val3, GUIContent.none, HudStyle.Row)) { Say(Actions.AssignChest(chest, category2)); } } GUI.EndScrollView(); if (GUI.Button(new Rect(0f, height - 42f, 240f, 36f), Text.EditCategories, HudStyle.Button)) { _tab = 1; _picking = false; if (category != null) { _selectedId = category.Id; } } } private static void DrawCategoryCell(Rect rect, Category category, bool selected, bool enabled) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) Color color = GUI.color; if (!enabled) { GUI.color = new Color(1f, 1f, 1f, 0.55f); } GUI.Box(rect, GUIContent.none, selected ? HudStyle.SlotOn : HudStyle.Slot); DrawTag(new Rect(((Rect)(ref rect)).x + 14f, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height / 2f - 9f, 14f, 18f), category); Color contentColor = GUI.contentColor; GUI.contentColor = (selected ? HudStyle.GoldBright : Color.white); HudStyle.Shadowed(new Rect(((Rect)(ref rect)).x + 40f, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width - 48f, ((Rect)(ref rect)).height), (category == null) ? Text.NoCategoryOption : category.DisplayName(Text.Spanish), HudStyle.Plain); GUI.contentColor = contentColor; GUI.color = color; } private static void DrawTag(Rect rect, Category category) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) Color color = (Color)((category == null) ? new Color(0.45f, 0.4f, 0.34f, 1f) : Categories.ColorOf(category, HudStyle.Dim)); HudStyle.Fill(rect, color); HudStyle.Border(rect, new Color(0.07f, 0.045f, 0.03f, 0.95f)); HudStyle.Fill(new Rect(((Rect)(ref rect)).x + 2f, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).width - 4f, 2f), new Color(1f, 1f, 1f, 0.22f)); } private void DrawCategoriesTab(float width, float height) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) DrawCategoryList(new Rect(0f, 0f, 250f, height)); Rect val = default(Rect); ((Rect)(ref val))..ctor(266f, 0f, width - 250f - 16f, height); Category category = Categories.Get(_selectedId); if (category == null) { HudStyle.Shadowed(val, Text.SelectCategory, HudStyle.Wrap); return; } GUI.BeginGroup(val); try { if (_picking) { DrawItemPicker(category, ((Rect)(ref val)).width, ((Rect)(ref val)).height); } else { DrawCategoryDetail(category, ((Rect)(ref val)).width, ((Rect)(ref val)).height); } } finally { GUI.EndGroup(); } } private void DrawCategoryList(Rect area) { //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Invalid comparison between Unknown and I4 //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) float num; if (_creating) { Event current = Event.current; bool flag = (int)current.type == 4 && ((int)current.keyCode == 13 || (int)current.keyCode == 271) && GUI.GetNameOfFocusedControl() == "newname"; GUI.SetNextControlName("newname"); _newName = GUI.TextField(new Rect(0f, 0f, ((Rect)(ref area)).width, 34f), _newName, 40, HudStyle.Field); if (_focusNewName) { GUI.FocusControl("newname"); _focusNewName = false; } if (flag) { current.Use(); } if (GUI.Button(new Rect(0f, 38f, ((Rect)(ref area)).width / 2f - 4f, 32f), Text.Create, HudStyle.Button) || flag) { CreateCategory(); } if (GUI.Button(new Rect(((Rect)(ref area)).width / 2f + 4f, 38f, ((Rect)(ref area)).width / 2f - 4f, 32f), Text.Cancel, HudStyle.Button)) { _creating = false; } num = 78f; } else { if (GUI.Button(new Rect(0f, 0f, ((Rect)(ref area)).width, 36f), Text.NewCategory, HudStyle.Button)) { _creating = true; _newName = string.Empty; _focusNewName = true; } num = 46f; } IReadOnlyList<Category> categories = Categories.All; VirtualRows(new Rect(0f, num, ((Rect)(ref area)).width, ((Rect)(ref area)).height - num), ref _scrollCategories, categories.Count, 40f, delegate(int i, Rect rect) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) DrawCategoryRow(categories[i], rect); }); } private void DrawCategoryRow(Category category, Rect rect) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) bool flag = string.Equals(category.Id, _selectedId, StringComparison.OrdinalIgnoreCase); GUI.Box(rect, GUIContent.none, flag ? HudStyle.SlotOn : HudStyle.Slot); DrawTag(new Rect(((Rect)(ref rect)).x + 12f, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height / 2f - 9f, 14f, 18f), category); Color contentColor = GUI.contentColor; GUI.contentColor = (flag ? HudStyle.GoldBright : Color.white); HudStyle.Shadowed(new Rect(((Rect)(ref rect)).x + 38f, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width - 44f, ((Rect)(ref rect)).height), category.DisplayName(Text.Spanish), HudStyle.Plain); GUI.contentColor = contentColor; if (GUI.Button(rect, GUIContent.none, HudStyle.Row)) { _selectedId = category.Id; _picking = false; _confirmDelete = false; _scrollRules = Vector2.zero; } } private void CreateCategory() { bool saved; Category category = Categories.Create(_newName, out saved); if (category != null) { _selectedId = category.Id; _creating = false; _picking = false; _buffersFor = null; Say(saved ? Text.Created(category.DisplayName(Text.Spanish)) : Text.SaveFailed); } } private void DrawCategoryDetail(Category category, float width, float height) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) if (_buffersFor != category.Id) { _nameEs = category.NameEs ?? string.Empty; _nameEn = category.NameEn ?? string.Empty; _buffersFor = category.Id; _confirmDelete = false; } float num = (width - 12f) / 2f; HudStyle.Shadowed(new Rect(2f, 0f, num, 20f), Text.NameSpanish, HudStyle.Small); HudStyle.Shadowed(new Rect(num + 14f, 0f, num, 20f), Text.NameEnglish, HudStyle.Small); _nameEs = GUI.TextField(new Rect(0f, 22f, num, 34f), _nameEs, 40, HudStyle.Field); _nameEn = GUI.TextField(new Rect(num + 12f, 22f, num, 34f), _nameEn, 40, HudStyle.Field); if (GUI.Button(new Rect(0f, 64f, 180f, 32f), Text.SaveNames, HudStyle.Button)) { bool flag = Categories.Rename(category, _nameEs, _nameEn); _buffersFor = null; Say(flag ? Text.Saved : Text.SaveFailed); } DrawSwatches(category, width); HudStyle.Shadowed(new Rect(2f, 106f, width - 200f, 30f), Text.ItemsHeader(CountRules(category)), HudStyle.Heading); if (GUI.Button(new Rect(width - 190f, 104f, 190f, 34f), Text.AddItems, HudStyle.Button)) { _picking = true; _focusSearch = true; _scrollItems = Vector2.zero; } RefreshRules(category); Rect view = default(Rect); ((Rect)(ref view))..ctor(0f, 146f, width, height - 146f - 48f); if (_rules.Count == 0) { HudStyle.Shadowed(new Rect(((Rect)(ref view)).x + 2f, ((Rect)(ref view)).y, ((Rect)(ref view)).width, 40f), Text.EmptyCategory, HudStyle.Small); } else { VirtualRows(view, ref _scrollRules, _rules.Count, 44f, delegate(int i, Rect rect) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) DrawRuleRow(category, _rules[i], rect); }); } DrawDelete(category, height); } private void DrawSwatches(Category category, float width) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) string[] palette = CategoryEditor.Palette; float num = width - (float)palette.Length * 31f + 5f; Rect val = default(Rect); Color color = default(Color); for (int i = 0; i < palette.Length; i++) { ((Rect)(ref val))..ctor(num + (float)i * 31f, 67f, 26f, 26f); ColorUtility.TryParseHtmlString(palette[i], ref color); if (string.Equals(category.Color, palette[i], StringComparison.OrdinalIgnoreCase)) { HudStyle.Border(new Rect(((Rect)(ref val)).x - 3f, ((Rect)(ref val)).y - 3f, ((Rect)(ref val)).width + 6f, ((Rect)(ref val)).height + 6f), HudStyle.GoldBright); } HudStyle.Fill(val, Categories.Tame(color)); HudStyle.Border(val, new Color(0.07f, 0.045f, 0.03f, 0.95f)); HudStyle.Fill(new Rect(((Rect)(ref val)).x + 2f, ((Rect)(ref val)).y + 2f, ((Rect)(ref val)).width - 4f, 3f), new Color(1f, 1f, 1f, 0.2f)); if (GUI.Button(val, GUIContent.none, HudStyle.Row)) { Say(Categories.SetColor(category, palette[i]) ? Text.Saved : Text.SaveFailed); } } } private void DrawRuleRow(Category category, RuleRow row, Rect rect) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) GUI.Box(rect, GUIContent.none, HudStyle.Slot); float num = ((Rect)(ref rect)).x + 14f; if (row.Kind == 0) { HudStyle.SlotIcon(new Rect(((Rect)(ref rect)).x + 5f, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).height - 4f, ((Rect)(ref rect)).height - 4f), row.Icon); num = ((Rect)(ref rect)).x + ((Rect)(ref rect)).height + 8f; } float num2 = ((Rect)(ref rect)).width - num - 54f; if (row.Sub != null) { HudStyle.Shadowed(new Rect(num, ((Rect)(ref rect)).y + 2f, num2, 22f), row.Title, HudStyle.Label); HudStyle.Shadowed(new Rect(num, ((Rect)(ref rect)).y + 22f, num2, 18f), row.Sub, HudStyle.Small); } else { HudStyle.Shadowed(new Rect(num, ((Rect)(ref rect)).y, num2, ((Rect)(ref rect)).height), row.Title, HudStyle.Label); } if (GUI.Button(new Rect(((Rect)(ref rect)).xMax - 46f, ((Rect)(ref rect)).y + 6f, 38f, ((Rect)(ref rect)).height - 12f), "X", HudStyle.Button)) { bool flag = ((row.Kind == 0) ? Categories.UnassignItem(category, row.Key) : ((row.Kind == 1) ? Categories.RemovePattern(category, row.Key) : Categories.RemoveType(category, row.Key))); Say(flag ? Text.Removed(row.Title) : Text.SaveFailed); } } private void DrawDelete(Category category, float height) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) string text = (_confirmDelete ? Text.ConfirmDelete : Text.DeleteCategory); if (GUI.Button(new Rect(0f, height - 42f, 220f, 36f), text, HudStyle.Button)) { if (!_confirmDelete) { _confirmDelete = true; return; } string category2 = category.DisplayName(Text.Spanish); bool flag = Categories.Delete(category); _selectedId = ((Categories.All.Count > 0) ? Categories.All[0].Id : null); _confirmDelete = false; _buffersFor = null; Say(flag ? Text.Deleted(category2) : Text.SaveFailed); } } private static int CountRules(Category category) { return category.Items.Count + category.Patterns.Count + category.Types.Count; } private void RefreshRules(Category category) { string language = Text.Language; if (_rulesFor == category.Id && _rulesVersion == Categories.Version && _rulesLanguage == language && _rulesGeneration == ItemCatalog.Generation) { return; } _rules.Clear(); foreach (string item in category.Items) { CatalogEntry catalogEntry = ItemCatalog.Find(item); _rules.Add(new RuleRow { Title = ((catalogEntry != null) ? catalogEntry.Display : item), Sub = item, Icon = catalogEntry?.Icon, Kind = 0, Key = item }); } _rules.Sort((RuleRow a, RuleRow b) => string.Compare(a.Title, b.Title, StringComparison.CurrentCultureIgnoreCase)); foreach (string pattern in category.Patterns) { _rules.Add(new RuleRow { Title = Text.RuleName(pattern), Kind = 1, Key = pattern }); } foreach (string type in category.Types) { _rules.Add(new RuleRow { Title = Text.RuleType(type), Kind = 2, Key = type }); } _rulesFor = category.Id; _rulesVersion = Categories.Version; _rulesLanguage = language; _rulesGeneration = ItemCatalog.Generation; } private void DrawItemPicker(Category category, float width, float height) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) GUI.SetNextControlName("search"); _search = GUI.TextField(new Rect(0f, 0f, width - 334f, 34f), _search, 60, HudStyle.Field); if (_focusSearch) { GUI.FocusControl("search"); _focusSearch = false; } string[] array = new string[3] { Text.FilterAll, Text.FilterInventory, Text.FilterNone }; for (int i = 0; i < array.Length; i++) { if (GUI.Button(new Rect(width - 326f + (float)i * 110f, 0f, 106f, 34f), array[i], (_filter == i) ? HudStyle.TabOn : HudStyle.Button)) { _filter = i; _scrollItems = Vector2.zero; } } HudStyle.Shadowed(new Rect(2f, 38f, width, 22f), Text.SearchHint, HudStyle.Small); RefreshFiltered(category); Rect view = default(Rect); ((Rect)(ref view))..ctor(0f, 66f, width, height - 66f - 48f); if (_filtered.Count == 0) { HudStyle.Shadowed(new Rect(((Rect)(ref view)).x + 2f, ((Rect)(ref view)).y, ((Rect)(ref view)).width, 30f), Text.NoResults, HudStyle.Small); } else { VirtualRows(view, ref _scrollItems, _filtered.Count, 46f, delegate(int index, Rect rect) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) DrawItemRow(category, _filtered[index], rect); }); } if (GUI.Button(new Rect(0f, height - 42f, 160f, 36f), Text.Done, HudStyle.Button)) { _picking = false; } } private void DrawItemRow(Category category, CatalogEntry entry, Rect rect) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) bool flag = entry.Category == category; GUI.Box(rect, GUIContent.none, flag ? HudStyle.SlotOn : HudStyle.Slot); HudStyle.SlotIcon(new Rect(((Rect)(ref rect)).x + 5f, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).height - 4f, ((Rect)(ref rect)).height - 4f), entry.Icon); float num = ((Rect)(ref rect)).x + ((Rect)(ref rect)).height + 8f; float num2 = ((Rect)(ref rect)).width * 0.5f; HudStyle.Shadowed(new Rect(num, ((Rect)(ref rect)).y + 3f, num2 - num, 22f), entry.Display, HudStyle.Label); HudStyle.Shadowed(new Rect(num, ((Rect)(ref rect)).y + 24f, num2 - num, 18f), entry.Prefab, HudStyle.Small); Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(((Rect)(ref rect)).x + num2, ((Rect)(ref rect)).y, num2 - 14f, ((Rect)(ref rect)).height); Color contentColor = GUI.contentColor; if (flag) { GUI.contentColor = HudStyle.GoldBright; HudStyle.Shadowed(rect2, entry.Exact ? Text.InThisCategory : Text.InThisCategoryByRule, HudStyle.PlainRight); } else if (entry.Category != null) { GUI.contentColor = Categories.ColorOf(entry.Category, HudStyle.Dim); HudStyle.Shadowed(rect2, entry.Category.DisplayName(Text.Spanish), HudStyle.PlainRight); } GUI.contentColor = contentColor; if (GUI.Button(rect, GUIContent.none, HudStyle.Row)) { ToggleItem(category, entry); } } private void ToggleItem(Category category, CatalogEntry entry) { if (entry.Category == category && !entry.Exact) { Say(Text.ByRuleHint); return; } if (entry.Category == category) { Say(Categories.UnassignItem(category, entry.Prefab) ? Text.Removed(entry.Display) : Text.SaveFailed); return; } bool flag = Categories.AssignItem(category, entry.Prefab); Say(flag ? Text.Assigned(entry.Display, category.DisplayName(Text.Spanish)) : Text.SaveFailed); } private void RefreshFiltered(Category category) { if (_filter == 1 && Time.unscaledTime - _inventoryRead > 1f) { ReadInventory(); } if (_filteredSearch == _search && _filteredFilter == _filter && _filteredVersion == Categories.Version && _filteredFor == category.Id && _filteredInventory == _inventoryStamp && _filteredGeneration == ItemCatalog.Generation) { return; } _filtered.Clear(); string[] array = _search.ToLowerInvariant().Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (CatalogEntry item in ItemCatalog.All) { if ((_filter == 1 && !_inventory.Contains(item.Prefab)) || (_filter == 2 && item.Category != null)) { continue; } bool flag = true; string[] array2 = array; foreach (string value in array2) { if (!item.Search.Contains(value)) { flag = false; break; } } if (flag) { _filtered.Add(item); } } _filteredSearch = _search; _filteredFilter = _filter; _filteredVersion = Categories.Version; _filteredFor = category.Id; _filteredInventory = _inventoryStamp; _filteredGeneration = ItemCatalog.Generation; } private void ReadInventory() { _inventoryRead = Time.unscaledTime; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (ItemData allItem in ((Humanoid)localPlayer).GetInventory().GetAllItems()) { if ((Object)(object)allItem?.m_dropPrefab != (Object)null) { hashSet.Add(((Object)allItem.m_dropPrefab).name); } } if (!hashSet.SetEquals(_inventory)) { _inventory.Clear(); _inventory.UnionWith(hashSet); _inventoryStamp++; } } private static void VirtualRows(Rect view, ref Vector2 scroll, int count, float rowHeight, Action<int, Rect> drawRow) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) Rect val = default(Rect); ((Rect)(ref val))..ctor(0f, 0f, ((Rect)(ref view)).width - 16f, (float)count * rowHeight); scroll = GUI.BeginScrollView(view, scroll, val); int num = Mathf.Clamp(Mathf.FloorToInt(scroll.y / rowHeight), 0, Mathf.Max(0, count - 1)); int num2 = Mathf.Clamp(Mathf.CeilToInt((scroll.y + ((Rect)(ref view)).height) / rowHeight), 0, count - 1); for (int i = num; i <= num2; i++) { drawRow(i, new Rect(0f, (float)i * rowHeight, ((Rect)(ref val)).width, rowHeight - 4f)); } GUI.EndScrollView(); } } internal sealed class NameSet : IEnumerable<string>, IEnumerable { private readonly List<string> _order = new List<string>(); private readonly HashSet<string> _lookup = new HashSet<string>(StringComparer.OrdinalIgnoreCase); internal int Count => _order.Count; internal bool Add(string name) { if (!_lookup.Add(name)) { return false; } _order.Add(name); return true; } internal bool Remove(string name) { if (!_lookup.Remove(name)) { return false; } _order.RemoveAll((string existing) => string.Equals(existing, name, StringComparison.OrdinalIgnoreCase)); return true; } internal bool Contains(string name) { return _lookup.Contains(name); } public IEnumerator<string> GetEnumerator() { return _order.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal sealed class Category { internal string Id; internal string NameEn; internal string NameEs; internal string Color; internal readonly NameSet Items = new NameSet(); internal readonly NameSet Patterns = new NameSet(); internal readonly NameSet Types = new NameSet(); internal string DisplayName(bool spanish) { string text = (spanish ? (NameEs ?? NameEn) : (NameEn ?? NameEs)); if (!string.IsNullOrEmpty(text)) { return text; } return Id; } internal bool MatchesExact(string prefab, string shared) { if (!string.IsNullOrEmpty(prefab) && Items.Contains(prefab)) { return true; } if (!string.IsNullOrEmpty(shared) && shared[0] == '$') { return Items.Contains(shared); } return false; } internal bool MatchesPattern(string prefab) { if (string.IsNullOrEmpty(prefab)) { return false; } foreach (string pattern in Patterns) { if ((pattern[pattern.Length - 1] == '*') ? prefab.StartsWith(pattern.Substring(0, pattern.Length - 1), StringComparison.OrdinalIgnoreCase) : prefab.EndsWith(pattern.Substring(1), StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } internal bool MatchesType(string itemType, bool isFood, bool isPotion) { if (!string.IsNullOrEmpty(itemType) && Types.Contains(itemType)) { return true; } if (!isFood || !Types.Contains("Food")) { if (isPotion) { return Types.Contains("Potion"); } return false; } return true; } } internal static class CategoryFile { internal static List<Category> Parse(IEnumerable<string> lines, List<string> problems) { List<Category> result = new List<Category>(); HashSet<string> ids = new HashSet<string>(StringComparer.OrdinalIgnoreCase); Category category = null; int num = 0; foreach (string line in lines) { num++; string text = line.Trim(); if (text.Length == 0 || text[0] == '#' || text[0] == ';') { continue; } if (text[0] == '[') { category = StartCategory(text, num, ids, result, problems); continue; } int num2 = text.IndexOf('='); if (category == null || num2 <= 0) { problems.Add(string.Format("line {0}: ignored ({1}): {2}", num, (category == null) ? "outside a [category]" : "expected key = value", text)); continue; } string key = text.Substring(0, num2).Trim().ToLowerInvariant(); string value = text.Substring(num2 + 1).Trim(); ApplyKey(category, key, value, num, problems); } return result; } internal static Category Classify(IReadOnlyList<Category> categories, string prefab, string shared, string itemType, bool isFood, bool isPotion) { for (int i = 0; i < categories.Count; i++) { if (categories[i].MatchesExact(prefab, shared)) { return categories[i]; } } for (int j = 0; j < categories.Count; j++) { if (categories[j].MatchesPattern(prefab)) { return categories[j]; } } for (int k = 0; k < categories.Count; k++) { if (categories[k].MatchesType(itemType, isFood, isPotion)) { return categories[k]; } } return null; } internal static string Serialize(IReadOnlyList<Category> categories) { return "# ChestCategories - categorías de cofres / chest categories\n#\n# Puedes editar este archivo a mano o desde el HUD del juego (tecla F7). Cuando guardas desde el HUD, el mod\n# reescribe el archivo entero: tus categorías se conservan y estos comentarios se vuelven a generar.\n# Edit this file by hand or from the in-game HUD (F7 key). Saving from the HUD rewrites the whole file:\n# your categories are kept and these comments are regenerated.\n#\n# Cada bloque [id] es una categoría. Si lo editas a mano, el mod recarga el archivo al abrir el HUD o pulsar F8.\n#\n# Claves / keys:\n# es / en = nombre en español / name in English\n# color = color en el HUD, #RRGGBB\n# item = nombre interno del objeto (el de la consola: spawn Wood), separados por comas.\n# Admite un * al principio o al final: Mead* *Uncooked\n# También acepta el nombre traducible del juego: $item_wood\n# type = tipo de objeto del juego: Material, Consumable, OneHandedWeapon, TwoHandedWeapon, TwoHandedWeaponLeft,\n# Bow, Shield, Helmet, Chest, Legs, Shoulder, Hands, Ammo, AmmoNonEquipable, Trophy, Torch, Tool, Utility,\n# Trinket, Fish, Misc, Customization ... y dos tipos derivados:\n# Food = consumible que da vida, aguante o eitr\n# Potion = consumible que no es comida (pociones, hidromieles)\n#\n# Prioridad, de más a menos específica: 1) nombre exacto (Wood, $item_wood), 2) nombre con * (Mead*), 3) type.\n# Dentro de cada nivel gana la primera categoría del archivo. Por eso un objeto que asignas a mano desde el HUD\n# (nombre exacto) siempre gana a las reglas por tipo de cualquier categoría.\n# Un cambio de id (lo que va entre corchetes) desvincula los cofres que ya lo tenían asignado.\n\n" + SerializeBody(categories); } internal static string SerializeBody(IReadOnlyList<Category> categories) { StringBuilder stringBuilder = new StringBuilder(); foreach (Category category in categories) { stringBuilder.Append('[').Append(category.Id).Append("]\n"); AppendValue(stringBuilder, "es", category.NameEs); AppendValue(stringBuilder, "en", category.NameEn); AppendValue(stringBuilder, "color", category.Color); if (category.Types.Count > 0) { stringBuilder.Append("type = ").Append(string.Join(", ", category.Types)).Append('\n'); } List<string> list = new List<string>(category.Items); list.AddRange(category.Patterns); for (int i = 0; i < list.Count; i += 8) { int count = Math.Min(8, list.Count - i); stringBuilder.Append("item = ").Append(string.Join(", ", list.GetRange(i, count))).Append('\n'); } stringBuilder.Append('\n'); } return stringBuilder.ToString(); } internal static bool IsValidColor(string color) { if (color == null || color.Length != 7 || color[0] != '#') { return false; } for (int i = 1; i < 7; i++) { if (!Uri.IsHexDigit(color[i])) { return false; } } return true; } private static void AppendValue(StringBuilder text, string key, string value) { if (!string.IsNullOrEmpty(value)) { text.Append(key).Append(" = ").Append(value) .Append('\n'); } } private static Category StartCategory(string line, int number, HashSet<string> ids, List<Category> result, List<string> problems) { int num = line.IndexOf(']'); if (num < 0) { problems.Add($"line {number}: missing ']': {line}"); return null; } string text = line.Substring(1, num - 1).Trim().ToLowerInvariant(); if (!IsValidId(text)) { problems.Add($"line {number}: invalid category id '{text}' (use a-z, 0-9 and _, up to 32 characters)"); return null; } if (!ids.Add(text)) { problems.Add($"line {number}: category '{text}' is defined twice; the second block is ignored"); return null; } Category category = new Category { Id = text }; result.Add(category); return category; } private static void ApplyKey(Category category, string key, string value, int number, List<string> problems) { switch (key) { case "en": category.NameEn = value; break; case "es": category.NameEs = value; break; case "color": if (IsValidColor(value)) { category.Color = value.ToUpperInvariant(); } else { problems.Add($"line {number}: color '{value}' ignored (use #RRGGBB)"); } break; case "items": case "item": { foreach (string item in Split(value)) { AddItem(category, item, number, problems); } break; } case "types": case "type": { foreach (string item2 in Split(value)) { category.Types.Add(item2); } break; } default: problems.Add($"line {number}: unknown key '{key}' (use es, en, color, item, type)"); break; } } private static void AddItem(Category category, string entry, int number, List<string> problems) { int num = 0; for (int i = 0; i < entry.Length; i++) { if (entry[i] == '*') { num++; } } switch (num) { case 0: category.Items.Add(entry); return; case 1: if (entry.Length > 1 && (entry[0] == '*' || entry[entry.Length - 1] == '*')) { category.Patterns.Add(entry); return; } break; } problems.Add($"line {number}: '{entry}' ignored (a * is only allowed at the start or the end)"); } private static IEnumerable<string> Split(string value) { string[] array = value.Split(','); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { yield return text; } } } private static bool IsValidId(string id) { if (id.Length == 0 || id.Length > 32) { return false; } foreach (char c in id) { if ((c < 'a' || c > 'z') && (c < '0' || c > '9') && c != '_') { return false; } } return true; } } internal static class CategoryEditor { internal const int MaxNameLength = 40; internal static readonly string[] Palette = new string[8] { "#C8864A", "#8DB4CC", "#E0BE4A", "#5FAE6E", "#C0524E", "#9879C4", "#5C86C4", "#C97BA6" }; internal static string CleanName(string raw) { if (string.IsNullOrEmpty(raw)) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(raw.Length); bool flag = false; foreach (char c in raw) { if (char.IsControl(c) || char.IsWhiteSpace(c)) { flag = stringBuilder.Length > 0; continue; } if (flag) { stringBuilder.Append(' '); flag = false; } stringBuilder.Append(c); } string text = stringBuilder.ToString(); if (text.Length <= 40) { return text; } return text.Substring(0, 40).TrimEnd(); } internal static string MakeId(string name, IEnumerable<string> existing) { HashSet<string> hashSet = new HashSet<string>(existing, StringComparer.OrdinalIgnoreCase); StringBuilder stringBuilder = new StringBuilder(); string text = (name ?? string.Empty).Normalize(NormalizationForm.FormD); foreach (char c in text) { if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) { char c2 = char.ToLowerInvariant(c); if ((c2 >= 'a' && c2 <= 'z') || (c2 >= '0' && c2 <= '9')) { stringBuilder.Append(c2); } else if (stringBuilder.Length > 0 && stringBuilder[stringBuilder.Length - 1] != '_') { stringBuilder.Append('_'); } } } string text2 = stringBuilder.ToString().Trim('_'); if (text2.Length == 0) { text2 = "category"; } if (text2.Length > 28) { text2 = text2.Substring(0, 28).TrimEnd('_'); } string text3 = text2; int num = 2; while (hashSet.Contains(text3)) { text3 = text2 + "_" + num.ToString(CultureInfo.InvariantCulture); num++; } return text3; } internal static string NextColor(IReadOnlyList<Category> categories) { string[] palette = Palette; foreach (string text in palette) { bool flag = false; foreach (Category category in categories) { if (string.Equals(category.Color, text, StringComparison.OrdinalIgnoreCase)) { flag = true; break; } } if (!flag) { return text; } } return Palette[categories.Count % Palette.Length]; } internal static Category Add(List<Category> categories, string name) { string text = CleanName(name); if (text.Length == 0) { return null; } List<string> list = new List<string>(); foreach (Category category2 in categories) { list.Add(category2.Id); } Category category = new Category { Id = MakeId(text, list), NameEs = text, NameEn = text, Color = NextColor(categories) }; categories.Add(category); return category; } internal static bool Remove(List<Category> categories, string id) { return categories.RemoveAll((Category c) => string.Equals(c.Id, id, StringComparison.OrdinalIgnoreCase)) > 0; } internal static bool Rename(Category category, string spanish, string english) { string text = CleanName(spanish); string text2 = CleanName(english); bool result = false; if (text.Length > 0 && text != category.NameEs) { category.NameEs = text; result = true; } if (text2.Length > 0 && text2 != category.NameEn) { category.NameEn = text2; result = true; } return result; } internal static void Assign(IReadOnlyList<Category> categories, Category target, string name) { foreach (Category category in categories) { category.Items.Remove(name); } target.Items.Add(name); } internal static bool Unassign(Category category, string name) { return category.Items.Remove(name); } } internal static class CategoryDefaults { internal const string FileName = "despr0grammer.ChestCategories.categories.txt"; internal const string Header = "# ChestCategories - categorías de cofres / chest categories\n#\n# Puedes editar este archivo a mano o desde el HUD del juego (tecla F7). Cuando guardas desde el HUD, el mod\n# reescribe el archivo entero: tus categorías se conservan y estos comentarios se vuelven a generar.\n# Edit this file by hand or from the in-game HUD (F7 key). Saving from the HUD rewrites the whole file:\n# your categories are kept and these comments are regenerated.\n#\n# Cada bloque [id] es una categoría. Si lo editas a mano, el mod recarga el archivo al abrir el HUD o pulsar F8.\n#\n# Claves / keys:\n# es / en = nombre en español / name in English\n# color = color en el HUD, #RRGGBB\n# item = nombre interno del objeto (el de la consola: spawn Wood), separados por comas.\n# Admite un * al principio o al final: Mead* *Uncooked\n# También acepta el nombre traducible del juego: $item_wood\n# type = tipo de objeto del juego: Material, Consumable, OneHandedWeapon, TwoHandedWeapon, TwoHandedWeaponLeft,\n# Bow, Shield, Helmet, Chest, Legs, Shoulder, Hands, Ammo, AmmoNonEquipable, Trophy, Torch, Tool, Utility,\n# Trinket, Fish, Misc, Customization ... y dos tipos derivados:\n# Food = consumible que da vida, aguante o eitr\n# Potion = consumible que no es comida (pociones, hidromieles)\n#\n# Prioridad, de más a menos específica: 1) nombre exacto (Wood, $item_wood), 2) nombre con * (Mead*), 3) type.\n# Dentro de cada nivel gana la primera categoría del archivo. Por eso un objeto que asignas a mano desde el HUD\n# (nombre exacto) siempre gana a las reglas por tipo de cualquier categoría.\n# Un cambio de id (lo que va entre corchetes) desvincula los cofres que ya lo tenían asignado.\n\n"; internal const string Body = "[wood]\nes = Madera\nen = Wood\ncolor = #C8864A\nitem = Wood, FineWood, RoundLog, ElderBark, YggdrasilWood, Blackwood, Frostwood\n\n[metals]\nes = Metales\nen = Metals\ncolor = #8DB4CC\nitem = Copper, Tin, Bronze, Iron, Silver, BlackMetal, Gold, Flametal*\nitem = CopperOre, TinOre, IronOre, IronScrap, SilverOre, BlackMetalScrap, GoldOre\nitem = BronzeNails, IronNails, Chain\n\n[stone]\nes = Piedras\nen = Stone\ncolor = #A5A9B8\nitem = Stone, Flint, Obsidian, Blackmarble, Grausten, Crystal\n\n[valuables]\nes = Tesoros\nen = Valuables\ncolor = #E0BE4A\nitem = Coins, Amber, AmberPearl, Ruby, SilverNecklace, GemstoneRed, GemstoneBlue, GemstoneGreen\n\n[hides]\nes = Pieles y cuero\nen = Hides and leather\ncolor = #B8895C\nitem = LeatherScraps, DeerHide, TrollHide, WolfPelt, LoxPelt, ScaleHide, MooseHide, SealHide, Leatherstraps\n\n[farming]\nes = Cultivo y semillas\nen = Farming and seeds\ncolor = #8FB24F\nitem = *Seeds, Acorn, FirCone, PineCone, Barley, Flax\n\n[vegetables]\nes = Vegetales y bayas\nen = Vegetables and berries\ncolor = #5FAE6E\nitem = Carrot, Turnip, Onion, Kale, Fiddleheadfern\nitem = Cloudberry, Raspberry, Blueberries, Pukeberries, Lingonberry, Vineberry\nitem = Mushroom, MushroomBlue, MushroomYellow, MushroomJotunPuffs, MushroomMagecap, MushroomSmokePuff\n\n[meats]\nes = Carnes\nen = Meats\ncolor = #C0524E\ntype = Fish\nitem = RawMeat, DeerMeat, WolfMeat, LoxMeat, SerpentMeat, BugMeat, MooseMeat, ChickenMeat, HareMeat\nitem = BjornMeat, BoneMawSerpentMeat, VoltureMeat, AsksvinMeat, NeckTail, FishRaw, RottenMeat\nitem = Cooked*, *MeatCooked, FishCooked, NeckTailGrilled\n\n[meals]\nes = Comidas preparadas\nen = Prepared meals\ncolor = #D99A3A\ntype = Food\nitem = Feast*, KaleChipsUncooked\n\n[cooking]\nes = Materiales para comida\nen = Cooking ingredients\ncolor = #C97BA6\nitem = BarleyFlour, BreadDough, Honey, RoyalJelly, ChickenEgg, Oat, Entrails, Bloodbag\nitem = sap, Dandelion, Thistle, SpiceDeepNorth, SealBlubber, GlowWorm\n\n[tools]\nes = Herramientas\nen = Tools\ncolor = #52AFA0\ntype = Tool, Torch\nitem = Pickaxe*, FishingRod*, FishingBait\n\n[potions]\nes = Pociones e hidromieles\nen = Potions and meads\ncolor = #9879C4\ntype = Potion\nitem = Mead*, BarleyWine*\n\n[weapons]\nes = Armas y escudos\nen = Weapons and shields\ncolor = #B83F4A\ntype = OneHandedWeapon, TwoHandedWeapon, TwoHandedWeaponLeft, Bow, Attach_Atgeir, Shield\n\n[armor]\nes = Armaduras\nen = Armor\ncolor = #5C86C4\ntype = Helmet, Chest, Legs, Shoulder, Hands\n\n[trinkets]\nes = Accesorios\nen = Accessories\ncolor = #D6B04A\ntype = Utility, Trinket\n\n[ammo]\nes = Munición\nen = Ammunition\ncolor = #C98A4E\ntype = Ammo, AmmoNonEquipable\n\n[trophies]\nes = Trofeos\nen = Trophies\ncolor = #CFCBE0\ntype = Trophy\n\n[drops]\nes = Botín de criaturas\nen = Creature drops\ncolor = #98A844\nitem = Bilebag, Ooze, OozeMork, Guck, BoneFragments, WolfFang, WolfClaw, WolfHairBundle\nitem = Mandible, Chitin, Carapace, Needle, Softtissue, HardAntler, Feathers, GreydwarfEye, FreezeGland\nitem = GiantBloodSack, SerpentScale, DragonTear, Root, MoleClaws, MooseSinew, ElakingHairBundle, WrithanRoots\n\n[other]\nes = Materiales varios\nen = Other materials\ncolor = #8E8A80\ntype = Material, Misc, Customization\n"; internal const string Text = "# ChestCategories - categorías de cofres / chest categories\n#\n# Puedes editar este archivo a mano o desde el HUD del juego (tecla F7). Cuando guardas desde el HUD, el mod\n# reescribe el archivo entero: tus categorías se conservan y estos comentarios se vuelven a generar.\n# Edit this file by hand or from the in-game HUD (F7 key). Saving from the HUD rewrites the whole file:\n# your categories are kept and these comments are regenerated.\n#\n# Cada bloque [id] es una categoría. Si lo editas a mano, el mod recarga el archivo al abrir el HUD o pulsar F8.\n#\n# Claves / keys:\n# es / en = nombre en español / name in English\n# color = color en el HUD, #RRGGBB\n# item = nombre interno del objeto (el de la consola: spawn Wood), separados por comas.\n# Admite un * al principio o al final: Mead* *Uncooked\n# También acepta el nombre traducible del juego: $item_wood\n# type = tipo de objeto del juego: Material, Consumable, OneHandedWeapon, TwoHandedWeapon, TwoHandedWeaponLeft,\n# Bow, Shield, Helmet, Chest, Legs, Shoulder, Hands, Ammo, AmmoNonEquipable, Trophy, Torch, Tool, Utility,\n# Trinket, Fish, Misc, Customization ... y dos tipos derivados:\n# Food = consumible que da vida, aguante o eitr\n# Potion = consumible que no es comida (pociones, hidromieles)\n#\n# Prioridad, de más a menos específica: 1) nombre exacto (Wood, $item_wood), 2) nombre con * (Mead*), 3) type.\n# Dentro de cada nivel gana la primera categoría del archivo. Por eso un objeto que asignas a mano desde el HUD\n# (nombre exacto) siempre gana a las reglas por tipo de cualquier categoría.\n# Un cambio de id (lo que va entre corchetes) desvincula los cofres que ya lo tenían asignado.\n\n[wood]\nes = Madera\nen = Wood\ncolor = #C8864A\nitem = Wood, FineWood, RoundLog, ElderBark, YggdrasilWood, Blackwood, Frostwood\n\n[metals]\nes = Metales\nen = Metals\ncolor = #8DB4CC\nitem = Copper, Tin, Bronze, Iron, Silver, BlackMetal, Gold, Flametal*\nitem = CopperOre, TinOre, IronOre, IronScrap, SilverOre, BlackMetalScrap, GoldOre\nitem = BronzeNails, IronNails, Chain\n\n[stone]\nes = Piedras\nen = Stone\ncolor = #A5A9B8\nitem = Stone, Flint, Obsidian, Blackmarble, Grausten, Crystal\n\n[valuables]\nes = Tesoros\nen = Valuables\ncolor = #E0BE4A\nitem = Coins, Amber, AmberPearl, Ruby, SilverNecklace, GemstoneRed, GemstoneBlue, GemstoneGreen\n\n[hides]\nes = Pieles y cuero\nen = Hides and leather\ncolor = #B8895C\nitem = LeatherScraps, DeerHide, TrollHide, WolfPelt, LoxPelt, ScaleHide, MooseHide, SealHide, Leatherstraps\n\n[farming]\nes = Cultivo y semillas\nen = Farming and seeds\ncolor = #8FB24F\nitem = *Seeds, Acorn, FirCone, PineCone, Barley, Flax\n\n[vegetables]\nes = Vegetales y bayas\nen = Vegetables and berries\ncolor = #5FAE6E\nitem = Carrot, Turnip, Onion, Kale, Fiddleheadfern\nitem = Cloudberry, Raspberry, Blueberries, Pukeberries, Lingonberry, Vineberry\nitem = Mushroom, MushroomBlue, MushroomYellow, MushroomJotunPuffs, MushroomMagecap, MushroomSmokePuff\n\n[meats]\nes = Carnes\nen = Meats\ncolor = #C0524E\ntype = Fish\nitem = RawMeat, DeerMeat, WolfMeat, LoxMeat, SerpentMeat, BugMeat, MooseMeat, ChickenMeat, HareMeat\nitem = BjornMeat, BoneMawSerpentMeat, VoltureMeat, AsksvinMeat, NeckTail, FishRaw, RottenMeat\nitem = Cooked*, *MeatCooked, FishCooked, NeckTailGrilled\n\n[meals]\nes = Comidas preparadas\nen = Prepared meals\ncolor = #D99A3A\ntype = Food\nitem = Feast*, KaleChipsUncooked\n\n[cooking]\nes = Materiales para comida\nen = Cooking ingredients\ncolor = #C97BA6\nitem = BarleyFlour, BreadDough, Honey, RoyalJelly, ChickenEgg, Oat, Entrails, Bloodbag\nitem = sap, Dandelion, Thistle, SpiceDeepNorth, SealBlubber, GlowWorm\n\n[tools]\nes = Herramientas\nen = Tools\ncolor = #52AFA0\ntype = Tool, Torch\nitem = Pickaxe*, FishingRod*, FishingBait\n\n[potions]\nes = Pociones e hidromieles\nen = Potions and meads\ncolor = #9879C4\ntype = Potion\nitem = Mead*, BarleyWine*\n\n[weapons]\nes = Armas y escudos\nen = Weapons and shields\ncolor = #B83F4A\ntype = OneHandedWeapon, TwoHandedWeapon, TwoHandedWeaponLeft, Bow, Attach_Atgeir, Shield\n\n[armor]\nes = Armaduras\nen = Armor\ncolor = #5C86C4\ntype = Helmet, Chest, Legs, Shoulder, Hands\n\n[trinkets]\nes = Accesorios\nen = Accessories\ncolor = #D6B04A\ntype = Utility, Trinket\n\n[ammo]\nes = Munición\nen = Ammunition\ncolor = #C98A4E\ntype = Ammo, AmmoNonEquipable\n\n[trophies]\nes = Trofeos\nen = Trophies\ncolor = #CFCBE0\ntype = Trophy\n\n[drops]\nes = Botín de criaturas\nen = Creature drops\ncolor = #98A844\nitem = Bilebag, Ooze, OozeMork, Guck, BoneFragments, WolfFang, WolfClaw, WolfHairBundle\nitem = Mandible, Chitin, Carapace, Needle, Softtissue, HardAntler, Feathers, GreydwarfEye, FreezeGland\nitem = GiantBloodSack, SerpentScale, DragonTear, Root, MoleClaws, MooseSinew, ElakingHairBundle, WrithanRoots\n\n[other]\nes = Materiales varios\nen = Other materials\ncolor = #8E8A80\ntype = Material, Misc, Customization\n"; private static readonly string[] PreviousDefaultHashes = new string[1] { "0b90d6ba8756d4ba07116a8b3c69f95aefbe9743ce91e97c065d845a320adf0b" }; internal static bool IsUntouchedPreviousDefault(string fileText) { string text = Fingerprint(fileText); string[] previousDefaultHashes = PreviousDefaultHashes; foreach (string text2 in previousDefaultHashes) { if (text == text2) { return true; } } return false; } internal static string Fingerprint(string text) { string s = (text ?? string.Empty).TrimStart('\ufeff').Replace("\r\n", "\n"); using SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(Encoding.UTF8.GetBytes(s)); StringBuilder stringBuilder = new StringBuilder(array.Length * 2); byte[] array2 = array; foreach (byte b in array2) { stringBuilder.Append(b.ToString("x2", CultureInfo.InvariantCulture)); } return stringBuilder.ToString(); } } internal static class ChestRegistry { private sealed class Entry { internal int Id; internal Container Container; internal Inventory Inventory; internal Transform Transform; internal ZNetView NetView; internal int Storage = -1; } private struct Candidate { internal Container Container; internal float SqrDistance; } private static readonly List<Entry> Entries = new List<Entry>(64); private static readonly Dictionary<int, Entry> ById = new Dictionary<int, Entry>(); private static readonly Dictionary<Inventory, Entry> ByInventory = new Dictionary<Inventory, Entry>(); private static readonly List<Candidate> Scratch = new List<Candidate>(32); private static readonly Comparison<Candidate> ByDistance = (Candidate a, Candidate b) => a.SqrDistance.CompareTo(b.SqrDistance); internal static void Register(Contai