using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using SimpleJSON;
using Splatform;
using SullysAutoPinner;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SullysAutoPinner")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SullysAutoPinner")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("53eb7460-cf9b-4412-b6f9-0c7191329f58")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.2.0.0")]
public class LocalizationManager
{
private readonly Dictionary<string, string> _translations = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
private readonly HashSet<string> _missingKeys = new HashSet<string>();
private readonly ManualLogSource _logger;
private readonly string _langCode;
private readonly string _translationsFolder;
private const string FallbackLang = "en";
private string _currentLanguage = "";
public LocalizationManager(ManualLogSource logger, string langCode)
{
_logger = logger;
_langCode = (string.IsNullOrWhiteSpace(langCode) ? "en" : langCode.ToLowerInvariant());
_translationsFolder = Path.Combine(Paths.ConfigPath, "SullysAutoPinnerFiles", "Translations");
LoadTranslations("en");
if (_langCode != "en")
{
LoadTranslations(_langCode);
}
}
public void Reload(string newLanguageCode)
{
if (!_currentLanguage.Equals(newLanguageCode, StringComparison.OrdinalIgnoreCase))
{
_currentLanguage = newLanguageCode;
LoadTranslations(newLanguageCode);
}
}
private void LoadTranslations(string lang)
{
try
{
string text = Path.Combine(_translationsFolder, lang + ".json");
if (!File.Exists(text))
{
_logger.LogWarning((object)("[LocalizationManager] Translation file not found: " + text));
return;
}
JSONNode jSONNode = JSON.Parse(File.ReadAllText(text));
if (jSONNode == null || !jSONNode.IsObject)
{
_logger.LogWarning((object)("[LocalizationManager] Failed to parse " + text));
return;
}
JSONNode.Enumerator enumerator = jSONNode.AsObject.GetEnumerator();
while (enumerator.MoveNext())
{
KeyValuePair<string, JSONNode> current = enumerator.Current;
_translations[current.Key.ToUpperInvariant()] = current.Value.Value;
}
_logger.LogWarning((object)$"[LocalizationManager] Loaded {jSONNode.Count} entries from {lang}.json");
}
catch (Exception ex)
{
_logger.LogWarning((object)("[LocalizationManager] Error loading " + lang + ".json: " + ex.Message));
}
}
public string GetLabel(string key)
{
if (string.IsNullOrWhiteSpace(key))
{
return key;
}
if (_translations.TryGetValue(key.ToUpperInvariant(), out var value))
{
return value;
}
if (_missingKeys.Add(key))
{
_logger.LogWarning((object)("[LocalizationManager] Missing translation for label: " + key));
}
return key;
}
public static void EnsureBaseLanguageFiles(ManualLogSource logger)
{
string text = Path.Combine(Paths.ConfigPath, "SullysAutoPinnerFiles", "Translations");
Directory.CreateDirectory(text);
foreach (KeyValuePair<string, Dictionary<string, string>> defaultTranslation in GetDefaultTranslations())
{
string key = defaultTranslation.Key;
string path = Path.Combine(text, key + ".json");
if (File.Exists(path))
{
continue;
}
try
{
JSONObject jSONObject = new JSONObject();
foreach (KeyValuePair<string, string> item in defaultTranslation.Value)
{
jSONObject[item.Key] = item.Value;
}
File.WriteAllText(path, jSONObject.ToString(2));
logger.LogWarning((object)("[LocalizationManager] Created default translation file: " + key + ".json"));
}
catch (Exception ex)
{
logger.LogWarning((object)("[LocalizationManager] Failed to write " + key + ".json: " + ex.Message));
}
}
}
private static Dictionary<string, Dictionary<string, string>> GetDefaultTranslations()
{
return new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase)
{
["en"] = LocalizationTranslations.EN,
["ru"] = LocalizationTranslations.RU,
["fr"] = LocalizationTranslations.FR,
["de"] = LocalizationTranslations.DE,
["es"] = LocalizationTranslations.ES,
["pl"] = LocalizationTranslations.PL,
["zh"] = LocalizationTranslations.ZH,
["pt"] = LocalizationTranslations.PT
};
}
}
public static class LocalizationTranslations
{
public static readonly Dictionary<string, string> EN = new Dictionary<string, string>
{
["ABOMINATION"] = "Abomination",
["CRYPT"] = "Crypt",
["DRAUGRSPAWNER"] = "Draugr Spawner",
["DVERGERTHINGS"] = "Dvergr Remains",
["DWARFSPAWNER"] = "Greydwarf Nest",
["FIRE"] = "Campfire",
["FLAX"] = "Flax",
["IRON"] = "Iron",
["MUDPILE"] = "Mudpile",
["METEORITE"] = "Meteorite",
["MAGECAPS"] = "Magecaps",
["MARKER"] = "Marker",
["MUSHROOMS"] = "Mushrooms",
["OBSIDIAN"] = "Obsidian",
["SEEDS"] = "Seeds",
["SILVER"] = "Silver",
["SKELETON"] = "Skeleton",
["SMOKEPUFFS"] = "Smoke Puffs",
["TAR"] = "Tar Pit",
["THISTLE"] = "Thistle",
["TOTEM"] = "Fuling Totem",
["TROLLCAVE"] = "Troll Cave",
["TREASURE"] = "Buried Treasure",
["VOLTUREEGG"] = "Vulture Egg",
["YPCONES"] = "Yggdrasil Pine Cones",
["JOTUNNPUFFS"] = "Jotunn Puffs",
["RASPBERRIES"] = "Raspberries",
["BLUEBERRIES"] = "Blueberries",
["CLOUDBERRIES"] = "Cloudberries",
["BARLEY"] = "Barley",
["CLOTH"] = "Cloth",
["SHIPWRECKCHEST"] = "Shipwreck Chest",
["GIANTSWORD"] = "Giant Sword",
["GIANTRIBS"] = "Giant Ribs",
["GIANTSKULL"] = "Giant Skull",
["GIANTBRAIN"] = "Giant Brain",
["EXCAVATION"] = "Excavation Site",
["LANTERN"] = "Lantern",
["ASHLANDPOTGREEN"] = "Ashland Pot (Green)",
["ASHLANDPOTRED"] = "Ashland Pot (Red)",
["SEEKERBRUTE"] = "Seeker Brute",
["BONEMAWSERPENT"] = "Bonemaw Serpent",
["COPPER"] = "Copper",
["DRAGONEGG"] = "Dragon Egg"
};
public static readonly Dictionary<string, string> RU = new Dictionary<string, string>
{
["ABOMINATION"] = "Мерзость",
["CRYPT"] = "Крипта",
["DRAUGRSPAWNER"] = "Портал драугров",
["DVERGERTHINGS"] = "Останки двергров",
["DWARFSPAWNER"] = "Гнездо серого карлика",
["FIRE"] = "Костер",
["FLAX"] = "Лён",
["IRON"] = "Железо",
["MUDPILE"] = "Грязевая куча",
["METEORITE"] = "Метеорит",
["MAGECAPS"] = "Волшебные шляпки",
["MARKER"] = "Маркер",
["MUSHROOMS"] = "Грибы",
["OBSIDIAN"] = "Обсидиан",
["SEEDS"] = "Семена",
["SILVER"] = "Серебро",
["SKELETON"] = "Скелет",
["SMOKEPUFFS"] = "Клубы дыма",
["TAR"] = "Смоляная яма",
["THISTLE"] = "Чертополох",
["TOTEM"] = "Тотем фулингов",
["TROLLCAVE"] = "Пещера тролля",
["TREASURE"] = "Сокровище",
["VOLTUREEGG"] = "Яйцо стервятника",
["YPCONES"] = "Шишки Иггдрасиля",
["JOTUNNPUFFS"] = "Пух Йотуна",
["RASPBERRIES"] = "Малина",
["BLUEBERRIES"] = "Черника",
["CLOUDBERRIES"] = "Морошка",
["BARLEY"] = "Ячмень",
["CLOTH"] = "Ткань",
["SHIPWRECKCHEST"] = "Сундук кораблекрушения",
["GIANTSWORD"] = "Меч великана",
["GIANTRIBS"] = "Рёбра великана",
["GIANTSKULL"] = "Череп великана",
["GIANTBRAIN"] = "Мозг великана",
["EXCAVATION"] = "Место раскопок",
["LANTERN"] = "Фонарь",
["ASHLANDPOTGREEN"] = "Пот Зелёный",
["ASHLANDPOTRED"] = "Пот Красный",
["SEEKERBRUTE"] = "Ищущий Враг",
["BONEMAWSERPENT"] = "Костеглот",
["COPPER"] = "Медь",
["DRAGONEGG"] = "Яйцо дракона"
};
public static readonly Dictionary<string, string> FR = new Dictionary<string, string>
{
["ABOMINATION"] = "Abomination",
["CRYPT"] = "Crypte",
["DRAUGRSPAWNER"] = "Portail Draugr",
["DVERGERTHINGS"] = "Restes de Dvergr",
["DWARFSPAWNER"] = "Nid de nain gris",
["FIRE"] = "Feu de camp",
["FLAX"] = "Lin",
["IRON"] = "Fer",
["MUDPILE"] = "Tas de boue",
["METEORITE"] = "Météorite",
["MAGECAPS"] = "Chapeaux de mage",
["MARKER"] = "Marqueur",
["MUSHROOMS"] = "Champignons",
["OBSIDIAN"] = "Obsidienne",
["SEEDS"] = "Graines",
["SILVER"] = "Argent",
["SKELETON"] = "Squelette",
["SMOKEPUFFS"] = "Nuages de fumée",
["TAR"] = "Fosse à goudron",
["THISTLE"] = "Chardon",
["TOTEM"] = "Totem de Fuling",
["TROLLCAVE"] = "Grotte du troll",
["TREASURE"] = "Trésor",
["VOLTUREEGG"] = "Œuf de vautour",
["YPCONES"] = "Cônes d’Yggdrasil",
["JOTUNNPUFFS"] = "Poussières de Jotunn",
["RASPBERRIES"] = "Framboises",
["BLUEBERRIES"] = "Myrtilles",
["CLOUDBERRIES"] = "Plaquebières",
["BARLEY"] = "Orge",
["CLOTH"] = "Tissu",
["SHIPWRECKCHEST"] = "Coffre d'épave",
["GIANTSWORD"] = "Épée de géant",
["GIANTRIBS"] = "Côtes de géant",
["GIANTSKULL"] = "Crâne de géant",
["GIANTBRAIN"] = "Cerveau de géant",
["EXCAVATION"] = "Site d’excavation",
["LANTERN"] = "Lanterne",
["ASHLANDPOTGREEN"] = "Pot des cendres (vert)",
["ASHLANDPOTRED"] = "Pot des cendres (rouge)",
["SEEKERBRUTE"] = "Brute Chercheuse",
["BONEMAWSERPENT"] = "Serpent Mâchoires d’Os",
["COPPER"] = "Cuivre",
["DRAGONEGG"] = "Œuf de dragon"
};
public static readonly Dictionary<string, string> DE = new Dictionary<string, string>
{
["ABOMINATION"] = "Abscheulichkeit",
["CRYPT"] = "Gruft",
["DRAUGRSPAWNER"] = "Draugr-Portal",
["DVERGERTHINGS"] = "Dvergr-Überreste",
["DWARFSPAWNER"] = "Grauzwergen-Nest",
["FIRE"] = "Lagerfeuer",
["FLAX"] = "Flachs",
["IRON"] = "Eisen",
["MUDPILE"] = "Schlammhaufen",
["METEORITE"] = "Meteorit",
["MAGECAPS"] = "Magierkappen",
["MARKER"] = "Markierung",
["MUSHROOMS"] = "Pilze",
["OBSIDIAN"] = "Obsidian",
["SEEDS"] = "Samen",
["SILVER"] = "Silber",
["SKELETON"] = "Skelett",
["SMOKEPUFFS"] = "Rauchwolken",
["TAR"] = "Teergrube",
["THISTLE"] = "Distel",
["TOTEM"] = "Fuling-Totem",
["TROLLCAVE"] = "Trollhöhle",
["TREASURE"] = "Schatz",
["VOLTUREEGG"] = "Geier-Ei",
["YPCONES"] = "Yggdrasil-Zapfen",
["JOTUNNPUFFS"] = "Jotunnflusen",
["RASPBERRIES"] = "Himbeeren",
["BLUEBERRIES"] = "Blaubeeren",
["CLOUDBERRIES"] = "Moltebeeren",
["BARLEY"] = "Gerste",
["CLOTH"] = "Stoff",
["SHIPWRECKCHEST"] = "Schiffswracktruhe",
["GIANTSWORD"] = "Schwert des Riesen",
["GIANTRIBS"] = "Rippen des Riesen",
["GIANTSKULL"] = "Schädel des Riesen",
["GIANTBRAIN"] = "Gehirn des Riesen",
["EXCAVATION"] = "Ausgrabungsstätte",
["LANTERN"] = "Laterne",
["ASHLANDPOTGREEN"] = "Aschenkrug (Grün)",
["ASHLANDPOTRED"] = "Aschenkrug (Rot)",
["SEEKERBRUTE"] = "Sucher-Brutalo",
["BONEMAWSERPENT"] = "Knochenrachen-Schlange",
["COPPER"] = "Kupfer",
["DRAGONEGG"] = "Drachenei"
};
public static readonly Dictionary<string, string> ES = new Dictionary<string, string>
{
["ABOMINATION"] = "Abominación",
["CRYPT"] = "Cripta",
["DRAUGRSPAWNER"] = "Generador de Draugr",
["DVERGERTHINGS"] = "Restos de Dvergr",
["DWARFSPAWNER"] = "Nido de enano gris",
["FIRE"] = "Hoguera",
["FLAX"] = "Lino",
["IRON"] = "Hierro",
["MUDPILE"] = "Montón de barro",
["METEORITE"] = "Meteorito",
["MAGECAPS"] = "Sombreros de mago",
["MARKER"] = "Marcador",
["MUSHROOMS"] = "Hongos",
["OBSIDIAN"] = "Obsidiana",
["SEEDS"] = "Semillas",
["SILVER"] = "Plata",
["SKELETON"] = "Esqueleto",
["SMOKEPUFFS"] = "Nubes de humo",
["TAR"] = "Pozo de alquitrán",
["THISTLE"] = "Cardo",
["TOTEM"] = "Tótem de Fuling",
["TROLLCAVE"] = "Cueva del troll",
["TREASURE"] = "Tesoro enterrado",
["VOLTUREEGG"] = "Huevo de buitre",
["YPCONES"] = "Conos de Yggdrasil",
["JOTUNNPUFFS"] = "Pelusas de Jotunn",
["RASPBERRIES"] = "Frambuesas",
["BLUEBERRIES"] = "Arándanos",
["CLOUDBERRIES"] = "Moras árticas",
["BARLEY"] = "Cebada",
["CLOTH"] = "Tela",
["SHIPWRECKCHEST"] = "Cofre del naufragio",
["GIANTSWORD"] = "Espada gigante",
["GIANTRIBS"] = "Costillas de gigante",
["GIANTSKULL"] = "Cráneo de gigante",
["GIANTBRAIN"] = "Cerebro de gigante",
["EXCAVATION"] = "Sitio de excavación",
["LANTERN"] = "Linterna",
["ASHLANDPOTGREEN"] = "Tintero de ceniza (verde)",
["ASHLANDPOTRED"] = "Tintero de ceniza (rojo)",
["SEEKERBRUTE"] = "Bruto Buscador",
["BONEMAWSERPENT"] = "Serpiente Mandíbulas de Hueso",
["COPPER"] = "Cobre",
["DRAGONEGG"] = "Huevo de dragón"
};
public static readonly Dictionary<string, string> PL = new Dictionary<string, string>
{
["ABOMINATION"] = "Abominacja",
["CRYPT"] = "Krypta",
["DRAUGRSPAWNER"] = "Pojawiacz Draugrów",
["DVERGERTHINGS"] = "Szczątki Dvergrów",
["DWARFSPAWNER"] = "Gniazdo szarego krasnoluda",
["FIRE"] = "Ognisko",
["FLAX"] = "Len",
["IRON"] = "Żelazo",
["MUDPILE"] = "Stos błota",
["METEORITE"] = "Meteoryt",
["MAGECAPS"] = "Kapelusze maga",
["MARKER"] = "Znacznik",
["MUSHROOMS"] = "Grzyby",
["OBSIDIAN"] = "Obsydian",
["SEEDS"] = "Nasiona",
["SILVER"] = "Srebro",
["SKELETON"] = "Szkielet",
["SMOKEPUFFS"] = "Kłęby dymu",
["TAR"] = "Dół smoły",
["THISTLE"] = "Oset",
["TOTEM"] = "Totem Fulingów",
["TROLLCAVE"] = "Jaskinia trolla",
["TREASURE"] = "Zakopany skarb",
["VOLTUREEGG"] = "Jajo sępa",
["YPCONES"] = "Szyszki Yggdrasila",
["JOTUNNPUFFS"] = "Puch Jotunna",
["RASPBERRIES"] = "Maliny",
["BLUEBERRIES"] = "Jagody",
["CLOUDBERRIES"] = "Maliny moroszki",
["BARLEY"] = "Jęczmień",
["CLOTH"] = "Tkanina",
["SHIPWRECKCHEST"] = "Skrzynia z wraku statku",
["GIANTSWORD"] = "Miecz olbrzyma",
["GIANTRIBS"] = "Żebra olbrzyma",
["GIANTSKULL"] = "Czaszka olbrzyma",
["GIANTBRAIN"] = "Mózg olbrzyma",
["EXCAVATION"] = "Miejsce wykopalisk",
["LANTERN"] = "Latarnia",
["ASHLANDPOTGREEN"] = "Popielniczka (zielona)",
["ASHLANDPOTRED"] = "Popielniczka (czerwona)",
["SEEKERBRUTE"] = "Brutalny Poszukiwacz",
["BONEMAWSERPENT"] = "Wąż Kościany",
["COPPER"] = "Miedź",
["DRAGONEGG"] = "Jajo smoka"
};
public static readonly Dictionary<string, string> ZH = new Dictionary<string, string>
{
["ABOMINATION"] = "憎恶",
["CRYPT"] = "地穴",
["DRAUGRSPAWNER"] = "尸鬼刷怪点",
["DVERGERTHINGS"] = "矮人遗骸",
["DWARFSPAWNER"] = "灰矮人巢穴",
["FIRE"] = "篝火",
["FLAX"] = "亚麻",
["IRON"] = "铁",
["MUDPILE"] = "泥堆",
["METEORITE"] = "陨石",
["MAGECAPS"] = "法师帽",
["MARKER"] = "标记",
["MUSHROOMS"] = "蘑菇",
["OBSIDIAN"] = "黑曜石",
["SEEDS"] = "种子",
["SILVER"] = "银",
["SKELETON"] = "骷髅",
["SMOKEPUFFS"] = "烟雾",
["TAR"] = "焦油坑",
["THISTLE"] = "蓟",
["TOTEM"] = "伏林图腾",
["TROLLCAVE"] = "巨魔洞穴",
["TREASURE"] = "埋藏宝藏",
["VOLTUREEGG"] = "秃鹫蛋",
["YPCONES"] = "世界树松果",
["JOTUNNPUFFS"] = "尤顿之绒",
["RASPBERRIES"] = "覆盆子",
["BLUEBERRIES"] = "蓝莓",
["CLOUDBERRIES"] = "云莓",
["BARLEY"] = "大麦",
["CLOTH"] = "布料",
["SHIPWRECKCHEST"] = "沉船宝箱",
["GIANTSWORD"] = "巨人之剑",
["GIANTRIBS"] = "巨人肋骨",
["GIANTSKULL"] = "巨人头骨",
["GIANTBRAIN"] = "巨人脑",
["EXCAVATION"] = "挖掘现场",
["LANTERN"] = "灯笼",
["ASHLANDPOTGREEN"] = "灰烬罐(绿色)",
["ASHLANDPOTRED"] = "灰烬罐(红色)",
["SEEKERBRUTE"] = "搜寻者蛮兵",
["BONEMAWSERPENT"] = "骨颚巨蛇",
["COPPER"] = "铜",
["DRAGONEGG"] = "龙蛋"
};
public static readonly Dictionary<string, string> PT = new Dictionary<string, string>
{
["ABOMINATION"] = "Abominação",
["CRYPT"] = "Cripta",
["DRAUGRSPAWNER"] = "Gerador de Draugr",
["DVERGERTHINGS"] = "Restos de Dvergr",
["DWARFSPAWNER"] = "Ninho de Anão Cinzento",
["FIRE"] = "Fogueira",
["FLAX"] = "Linho",
["IRON"] = "Ferro",
["MUDPILE"] = "Monturo de lama",
["METEORITE"] = "Meteorito",
["MAGECAPS"] = "Chapéus de mago",
["MARKER"] = "Marcador",
["MUSHROOMS"] = "Cogumelos",
["OBSIDIAN"] = "Obsidiana",
["SEEDS"] = "Sementes",
["SILVER"] = "Prata",
["SKELETON"] = "Esqueleto",
["SMOKEPUFFS"] = "Fumaça",
["TAR"] = "Poça de piche",
["THISTLE"] = "Cardo",
["TOTEM"] = "Totem de Fuling",
["TROLLCAVE"] = "Caverna do troll",
["TREASURE"] = "Tesouro enterrado",
["VOLTUREEGG"] = "Ovo de abutre",
["YPCONES"] = "Pinhas de Yggdrasil",
["JOTUNNPUFFS"] = "Pufs de Jotunn",
["RASPBERRIES"] = "Framboesas",
["BLUEBERRIES"] = "Mirtilos",
["CLOUDBERRIES"] = "Amoras árticas",
["BARLEY"] = "Cevada",
["CLOTH"] = "Tecido",
["SHIPWRECKCHEST"] = "Baú de naufrágio",
["GIANTSWORD"] = "Espada gigante",
["GIANTRIBS"] = "Costelas gigantes",
["GIANTSKULL"] = "Crânio gigante",
["GIANTBRAIN"] = "Cérebro gigante",
["EXCAVATION"] = "Local de escavação",
["LANTERN"] = "Lanterna",
["ASHLANDPOTGREEN"] = "Pote das Cinzas (Verde)",
["ASHLANDPOTRED"] = "Pote das Cinzas (Vermelho)",
["SEEKERBRUTE"] = "Bruto Buscador",
["BONEMAWSERPENT"] = "Serpente Mandíbula Óssea",
["COPPER"] = "Cobre",
["DRAGONEGG"] = "Ovo de dragão"
};
}
public class PinManager
{
private const int PinFlushThreshold = 50;
private readonly HashSet<string> _pinHashes = new HashSet<string>();
private readonly ModConfig _config;
private readonly ManualLogSource _logger;
private readonly LocalizationManager _localizationManager;
private readonly List<Tuple<Vector3, string>> _currentPins = new List<Tuple<Vector3, string>>();
private readonly List<Tuple<Vector3, string>> _newPins = new List<Tuple<Vector3, string>>();
private float _lastSaveTime;
private static readonly string SaveFolder = Path.Combine(Paths.ConfigPath, "SullysAutoPinnerFiles");
private static readonly string PinsFilePath = Path.Combine(SaveFolder, "Pins.txt");
public PinManager(ModConfig config, ManualLogSource logger, LocalizationManager localizationManager)
{
_config = config;
_logger = logger;
_localizationManager = localizationManager;
Directory.CreateDirectory(Path.GetDirectoryName(PinsFilePath));
LoadPinsFromFile();
}
public void ReloadConfig()
{
}
public void TryAddPin(Vector3 pos, string label, PinType icon)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: 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_0054: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Minimap.instance == (Object)null)
{
return;
}
Vector3 val = RoundTo0_1(pos);
string text = label.ToUpperInvariant();
string pinHash = GetPinHash(val, text);
if (_pinHashes.Contains(pinHash))
{
return;
}
foreach (Tuple<Vector3, string> currentPin in _currentPins)
{
if (Vector3.Distance(currentPin.Item1, val) < _config.PinMergeDistance.Value && string.Equals(currentPin.Item2, text, StringComparison.OrdinalIgnoreCase))
{
return;
}
}
string label2 = _localizationManager.GetLabel(text);
Minimap.instance.AddPin(val, icon, label2, true, false, 0L, default(PlatformUserID));
_newPins.Add(new Tuple<Vector3, string>(val, text));
_currentPins.Add(new Tuple<Vector3, string>(val, text));
_pinHashes.Add(pinHash);
if (_config.EnablePinSaving.Value && _newPins.Count >= 50)
{
SavePinsToFile();
}
}
public void TryPeriodicSave()
{
if (_config.EnablePinSaving.Value && _newPins.Count != 0 && (_newPins.Count >= 50 || Time.time - _lastSaveTime > _config.SaveInterval.Value))
{
SavePinsToFile();
}
}
public void SaveImmediate()
{
if (_config.EnablePinSaving.Value)
{
SavePinsToFile();
}
}
public void RemoveAllPins()
{
if ((Object)(object)Minimap.instance == (Object)null)
{
return;
}
_pinHashes.Clear();
try
{
File.WriteAllText(PinsFilePath, string.Empty);
_logger.LogWarning((object)"SullysAutoPinner >>> All Map Pins Removed - Pin history file emptied.");
}
catch (Exception ex)
{
_logger.LogWarning((object)("SullysAutoPinner >>> Failed to clear Pins.txt: " + ex.Message));
return;
}
if (!(AccessTools.Field(typeof(Minimap), "m_pins").GetValue(Minimap.instance) is List<PinData> list))
{
return;
}
foreach (PinData item in list.ToList())
{
Minimap.instance.RemovePin(item);
}
_currentPins.Clear();
_newPins.Clear();
_pinHashes.Clear();
_logger.LogWarning((object)$"SullysAutoPinner >>> All Map Pins Removed: {list.Count} pins removed from the map.");
}
public void RemoveUnwantedPins(ModConfig config)
{
if ((Object)(object)Minimap.instance == (Object)null || !(AccessTools.Field(typeof(Minimap), "m_pins").GetValue(Minimap.instance) is List<PinData> list))
{
return;
}
HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (KeyValuePair<string, (string, PinType)> item2 in PinScanner.PinLabelMap.LabelToSettingInfo)
{
string item = item2.Value.Item1;
FieldInfo field = typeof(ModConfig).GetField(item);
if (!(field == null) && !(field.FieldType != typeof(ConfigEntry<bool>)))
{
ConfigEntry<bool> val = (ConfigEntry<bool>)field.GetValue(config);
if (val != null && val.Value)
{
string label = _localizationManager.GetLabel(item.ToUpperInvariant());
hashSet.Add(label);
}
}
}
List<PinData> list2 = new List<PinData>();
foreach (PinData item3 in list)
{
if (!hashSet.Contains(item3.m_name))
{
list2.Add(item3);
}
}
foreach (PinData item4 in list2)
{
Minimap.instance.RemovePin(item4);
}
_logger.LogWarning((object)$"Removed {list2.Count} unwanted pins from the map.");
}
private bool IsLabelEnabled(string label, ModConfig config)
{
if (!PinScanner.PinLabelMap.LabelToSettingInfo.TryGetValue(label, out (string, PinType) value))
{
return true;
}
FieldInfo field = typeof(ModConfig).GetField(value.Item1);
if (field == null || field.FieldType != typeof(ConfigEntry<bool>))
{
return true;
}
return ((ConfigEntry<bool>)field.GetValue(config)).Value;
}
private void SavePinsToFile()
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
try
{
using StreamWriter streamWriter = File.AppendText(PinsFilePath);
foreach (Tuple<Vector3, string> newPin in _newPins)
{
streamWriter.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0:F1}|{1:F1}|{2:F1}|{3}", newPin.Item1.x, newPin.Item1.y, newPin.Item1.z, newPin.Item2));
}
}
catch (Exception ex)
{
_logger.LogWarning((object)("SullyAutoPinner >>> Error saving pins: " + ex.Message));
}
_newPins.Clear();
_lastSaveTime = Time.time;
}
private void LoadPinsFromFile()
{
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
try
{
if (!File.Exists(PinsFilePath))
{
return;
}
string[] array = File.ReadAllLines(PinsFilePath);
for (int i = 0; i < array.Length; i++)
{
string[] array2 = array[i].Split(new char[1] { '|' });
if (array2.Length == 4 && float.TryParse(array2[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array2[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && float.TryParse(array2[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
{
string text = array2[3].Trim().ToUpperInvariant();
Vector3 val = RoundTo0_1(new Vector3(result, result2, result3));
string pinHash = GetPinHash(val, text);
_pinHashes.Add(pinHash);
_currentPins.Add(new Tuple<Vector3, string>(val, text));
}
}
}
catch (Exception ex)
{
_logger.LogWarning((object)("SullyAutoPinner >>> Error loading pins: " + ex.Message));
}
}
private string GetPinHash(Vector3 pos, string label)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: 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_003f: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = RoundTo0_1(pos);
return string.Format(CultureInfo.InvariantCulture, "{0}:{1:F1},{2:F1},{3:F1}", label.ToUpperInvariant(), val.x, val.y, val.z);
}
private Vector3 RoundTo0_1(Vector3 v)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
return new Vector3(Mathf.Round(v.x * 10f) / 10f, Mathf.Round(v.y * 10f) / 10f, Mathf.Round(v.z * 10f) / 10f);
}
public void RemoveNearbyFallbackPins(Vector3 center, float radius)
{
//IL_004d: 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)
if ((Object)(object)Minimap.instance == (Object)null || !(AccessTools.Field(typeof(Minimap), "m_pins").GetValue(Minimap.instance) is List<PinData> list))
{
return;
}
List<PinData> list2 = new List<PinData>();
foreach (PinData item in list)
{
if (!(Vector3.Distance(center, item.m_pos) > radius))
{
string name = item.m_name;
if (!PinScanner.PinLabelMap.LabelToSettingInfo.ContainsKey(name))
{
list2.Add(item);
}
}
}
foreach (PinData item2 in list2)
{
Minimap.instance.RemovePin(item2);
}
_logger.LogWarning((object)$"Removed {list2.Count} fallback pins within {radius}m.");
}
}
namespace SimpleJSON
{
public enum JSONNodeType
{
Array = 1,
Object = 2,
String = 3,
Number = 4,
NullValue = 5,
Boolean = 6,
None = 7,
Custom = 255
}
public enum JSONTextMode
{
Compact,
Indent
}
public abstract class JSONNode
{
public struct Enumerator
{
private enum Type
{
None,
Array,
Object
}
private Type type;
private Dictionary<string, JSONNode>.Enumerator m_Object;
private List<JSONNode>.Enumerator m_Array;
public bool IsValid => type != Type.None;
public KeyValuePair<string, JSONNode> Current
{
get
{
if (type == Type.Array)
{
return new KeyValuePair<string, JSONNode>(string.Empty, m_Array.Current);
}
if (type == Type.Object)
{
return m_Object.Current;
}
return new KeyValuePair<string, JSONNode>(string.Empty, null);
}
}
public Enumerator(List<JSONNode>.Enumerator aArrayEnum)
{
type = Type.Array;
m_Object = default(Dictionary<string, JSONNode>.Enumerator);
m_Array = aArrayEnum;
}
public Enumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
{
type = Type.Object;
m_Object = aDictEnum;
m_Array = default(List<JSONNode>.Enumerator);
}
public bool MoveNext()
{
if (type == Type.Array)
{
return m_Array.MoveNext();
}
if (type == Type.Object)
{
return m_Object.MoveNext();
}
return false;
}
}
public struct ValueEnumerator
{
private Enumerator m_Enumerator;
public JSONNode Current => m_Enumerator.Current.Value;
public ValueEnumerator(List<JSONNode>.Enumerator aArrayEnum)
: this(new Enumerator(aArrayEnum))
{
}
public ValueEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
: this(new Enumerator(aDictEnum))
{
}
public ValueEnumerator(Enumerator aEnumerator)
{
m_Enumerator = aEnumerator;
}
public bool MoveNext()
{
return m_Enumerator.MoveNext();
}
public ValueEnumerator GetEnumerator()
{
return this;
}
}
public struct KeyEnumerator
{
private Enumerator m_Enumerator;
public string Current => m_Enumerator.Current.Key;
public KeyEnumerator(List<JSONNode>.Enumerator aArrayEnum)
: this(new Enumerator(aArrayEnum))
{
}
public KeyEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
: this(new Enumerator(aDictEnum))
{
}
public KeyEnumerator(Enumerator aEnumerator)
{
m_Enumerator = aEnumerator;
}
public bool MoveNext()
{
return m_Enumerator.MoveNext();
}
public KeyEnumerator GetEnumerator()
{
return this;
}
}
public class LinqEnumerator : IEnumerator<KeyValuePair<string, JSONNode>>, IDisposable, IEnumerator, IEnumerable<KeyValuePair<string, JSONNode>>, IEnumerable
{
private JSONNode m_Node;
private Enumerator m_Enumerator;
public KeyValuePair<string, JSONNode> Current => m_Enumerator.Current;
object IEnumerator.Current => m_Enumerator.Current;
internal LinqEnumerator(JSONNode aNode)
{
m_Node = aNode;
if (m_Node != null)
{
m_Enumerator = m_Node.GetEnumerator();
}
}
public bool MoveNext()
{
return m_Enumerator.MoveNext();
}
public void Dispose()
{
m_Node = null;
m_Enumerator = default(Enumerator);
}
public IEnumerator<KeyValuePair<string, JSONNode>> GetEnumerator()
{
return new LinqEnumerator(m_Node);
}
public void Reset()
{
if (m_Node != null)
{
m_Enumerator = m_Node.GetEnumerator();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return new LinqEnumerator(m_Node);
}
}
[CompilerGenerated]
private sealed class <get_Children>d__43 : IEnumerable<JSONNode>, IEnumerable, IEnumerator<JSONNode>, IDisposable, IEnumerator
{
private int <>1__state;
private JSONNode <>2__current;
private int <>l__initialThreadId;
JSONNode IEnumerator<JSONNode>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <get_Children>d__43(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
if (<>1__state != 0)
{
return false;
}
<>1__state = -1;
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<JSONNode> IEnumerable<JSONNode>.GetEnumerator()
{
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
return this;
}
return new <get_Children>d__43(0);
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<JSONNode>)this).GetEnumerator();
}
}
[CompilerGenerated]
private sealed class <get_DeepChildren>d__45 : IEnumerable<JSONNode>, IEnumerable, IEnumerator<JSONNode>, IDisposable, IEnumerator
{
private int <>1__state;
private JSONNode <>2__current;
private int <>l__initialThreadId;
public JSONNode <>4__this;
private IEnumerator<JSONNode> <>7__wrap1;
private IEnumerator<JSONNode> <>7__wrap2;
JSONNode IEnumerator<JSONNode>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <get_DeepChildren>d__45(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if ((uint)(num - -4) <= 1u || num == 1)
{
try
{
if (num == -4 || num == 1)
{
try
{
}
finally
{
<>m__Finally2();
}
}
}
finally
{
<>m__Finally1();
}
}
<>7__wrap1 = null;
<>7__wrap2 = null;
<>1__state = -2;
}
private bool MoveNext()
{
try
{
int num = <>1__state;
JSONNode jSONNode = <>4__this;
if (num != 0)
{
if (num != 1)
{
return false;
}
<>1__state = -4;
goto IL_008d;
}
<>1__state = -1;
<>7__wrap1 = jSONNode.Children.GetEnumerator();
<>1__state = -3;
goto IL_00a7;
IL_008d:
if (<>7__wrap2.MoveNext())
{
JSONNode current = <>7__wrap2.Current;
<>2__current = current;
<>1__state = 1;
return true;
}
<>m__Finally2();
<>7__wrap2 = null;
goto IL_00a7;
IL_00a7:
if (<>7__wrap1.MoveNext())
{
JSONNode current2 = <>7__wrap1.Current;
<>7__wrap2 = current2.DeepChildren.GetEnumerator();
<>1__state = -4;
goto IL_008d;
}
<>m__Finally1();
<>7__wrap1 = null;
return false;
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
if (<>7__wrap1 != null)
{
<>7__wrap1.Dispose();
}
}
private void <>m__Finally2()
{
<>1__state = -3;
if (<>7__wrap2 != null)
{
<>7__wrap2.Dispose();
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<JSONNode> IEnumerable<JSONNode>.GetEnumerator()
{
<get_DeepChildren>d__45 result;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
result = this;
}
else
{
result = new <get_DeepChildren>d__45(0)
{
<>4__this = <>4__this
};
}
return result;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<JSONNode>)this).GetEnumerator();
}
}
public static bool forceASCII = false;
public static bool longAsString = false;
public static bool allowLineComments = true;
[ThreadStatic]
private static StringBuilder m_EscapeBuilder;
public abstract JSONNodeType Tag { get; }
public virtual JSONNode this[int aIndex]
{
get
{
return null;
}
set
{
}
}
public virtual JSONNode this[string aKey]
{
get
{
return null;
}
set
{
}
}
public virtual string Value
{
get
{
return "";
}
set
{
}
}
public virtual int Count => 0;
public virtual bool IsNumber => false;
public virtual bool IsString => false;
public virtual bool IsBoolean => false;
public virtual bool IsNull => false;
public virtual bool IsArray => false;
public virtual bool IsObject => false;
public virtual bool Inline
{
get
{
return false;
}
set
{
}
}
public virtual IEnumerable<JSONNode> Children
{
[IteratorStateMachine(typeof(<get_Children>d__43))]
get
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <get_Children>d__43(-2);
}
}
public IEnumerable<JSONNode> DeepChildren
{
[IteratorStateMachine(typeof(<get_DeepChildren>d__45))]
get
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <get_DeepChildren>d__45(-2)
{
<>4__this = this
};
}
}
public IEnumerable<KeyValuePair<string, JSONNode>> Linq => new LinqEnumerator(this);
public KeyEnumerator Keys => new KeyEnumerator(GetEnumerator());
public ValueEnumerator Values => new ValueEnumerator(GetEnumerator());
public virtual double AsDouble
{
get
{
double result = 0.0;
if (double.TryParse(Value, NumberStyles.Float, CultureInfo.InvariantCulture, out result))
{
return result;
}
return 0.0;
}
set
{
Value = value.ToString(CultureInfo.InvariantCulture);
}
}
public virtual int AsInt
{
get
{
return (int)AsDouble;
}
set
{
AsDouble = value;
}
}
public virtual float AsFloat
{
get
{
return (float)AsDouble;
}
set
{
AsDouble = value;
}
}
public virtual bool AsBool
{
get
{
bool result = false;
if (bool.TryParse(Value, out result))
{
return result;
}
return !string.IsNullOrEmpty(Value);
}
set
{
Value = (value ? "true" : "false");
}
}
public virtual long AsLong
{
get
{
long result = 0L;
if (long.TryParse(Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result))
{
return result;
}
return 0L;
}
set
{
Value = value.ToString(CultureInfo.InvariantCulture);
}
}
public virtual ulong AsULong
{
get
{
ulong result = 0uL;
if (ulong.TryParse(Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result))
{
return result;
}
return 0uL;
}
set
{
Value = value.ToString(CultureInfo.InvariantCulture);
}
}
public virtual JSONArray AsArray => this as JSONArray;
public virtual JSONObject AsObject => this as JSONObject;
internal static StringBuilder EscapeBuilder
{
get
{
if (m_EscapeBuilder == null)
{
m_EscapeBuilder = new StringBuilder();
}
return m_EscapeBuilder;
}
}
public virtual void Add(string aKey, JSONNode aItem)
{
}
public virtual void Add(JSONNode aItem)
{
Add("", aItem);
}
public virtual JSONNode Remove(string aKey)
{
return null;
}
public virtual JSONNode Remove(int aIndex)
{
return null;
}
public virtual JSONNode Remove(JSONNode aNode)
{
return aNode;
}
public virtual void Clear()
{
}
public virtual JSONNode Clone()
{
return null;
}
public virtual bool HasKey(string aKey)
{
return false;
}
public virtual JSONNode GetValueOrDefault(string aKey, JSONNode aDefault)
{
return aDefault;
}
public override string ToString()
{
StringBuilder stringBuilder = new StringBuilder();
WriteToStringBuilder(stringBuilder, 0, 0, JSONTextMode.Compact);
return stringBuilder.ToString();
}
public virtual string ToString(int aIndent)
{
StringBuilder stringBuilder = new StringBuilder();
WriteToStringBuilder(stringBuilder, 0, aIndent, JSONTextMode.Indent);
return stringBuilder.ToString();
}
internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode);
public abstract Enumerator GetEnumerator();
public static implicit operator JSONNode(string s)
{
if (s != null)
{
return new JSONString(s);
}
return JSONNull.CreateOrGet();
}
public static implicit operator string(JSONNode d)
{
if (!(d == null))
{
return d.Value;
}
return null;
}
public static implicit operator JSONNode(double n)
{
return new JSONNumber(n);
}
public static implicit operator double(JSONNode d)
{
if (!(d == null))
{
return d.AsDouble;
}
return 0.0;
}
public static implicit operator JSONNode(float n)
{
return new JSONNumber(n);
}
public static implicit operator float(JSONNode d)
{
if (!(d == null))
{
return d.AsFloat;
}
return 0f;
}
public static implicit operator JSONNode(int n)
{
return new JSONNumber(n);
}
public static implicit operator int(JSONNode d)
{
if (!(d == null))
{
return d.AsInt;
}
return 0;
}
public static implicit operator JSONNode(long n)
{
if (longAsString)
{
return new JSONString(n.ToString(CultureInfo.InvariantCulture));
}
return new JSONNumber(n);
}
public static implicit operator long(JSONNode d)
{
if (!(d == null))
{
return d.AsLong;
}
return 0L;
}
public static implicit operator JSONNode(ulong n)
{
if (longAsString)
{
return new JSONString(n.ToString(CultureInfo.InvariantCulture));
}
return new JSONNumber(n);
}
public static implicit operator ulong(JSONNode d)
{
if (!(d == null))
{
return d.AsULong;
}
return 0uL;
}
public static implicit operator JSONNode(bool b)
{
return new JSONBool(b);
}
public static implicit operator bool(JSONNode d)
{
if (!(d == null))
{
return d.AsBool;
}
return false;
}
public static implicit operator JSONNode(KeyValuePair<string, JSONNode> aKeyValue)
{
return aKeyValue.Value;
}
public static bool operator ==(JSONNode a, object b)
{
if ((object)a == b)
{
return true;
}
bool flag = a is JSONNull || (object)a == null || a is JSONLazyCreator;
bool flag2 = b is JSONNull || b == null || b is JSONLazyCreator;
if (flag && flag2)
{
return true;
}
if (!flag)
{
return a.Equals(b);
}
return false;
}
public static bool operator !=(JSONNode a, object b)
{
return !(a == b);
}
public override bool Equals(object obj)
{
return (object)this == obj;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
internal static string Escape(string aText)
{
StringBuilder escapeBuilder = EscapeBuilder;
escapeBuilder.Length = 0;
if (escapeBuilder.Capacity < aText.Length + aText.Length / 10)
{
escapeBuilder.Capacity = aText.Length + aText.Length / 10;
}
foreach (char c in aText)
{
switch (c)
{
case '\\':
escapeBuilder.Append("\\\\");
continue;
case '"':
escapeBuilder.Append("\\\"");
continue;
case '\n':
escapeBuilder.Append("\\n");
continue;
case '\r':
escapeBuilder.Append("\\r");
continue;
case '\t':
escapeBuilder.Append("\\t");
continue;
case '\b':
escapeBuilder.Append("\\b");
continue;
case '\f':
escapeBuilder.Append("\\f");
continue;
}
if (c < ' ' || (forceASCII && c > '\u007f'))
{
ushort num = c;
escapeBuilder.Append("\\u").Append(num.ToString("X4"));
}
else
{
escapeBuilder.Append(c);
}
}
string result = escapeBuilder.ToString();
escapeBuilder.Length = 0;
return result;
}
private static JSONNode ParseElement(string token, bool quoted)
{
if (quoted)
{
return token;
}
if (token.Length <= 5)
{
string text = token.ToLower();
switch (text)
{
case "false":
case "true":
return text == "true";
case "null":
return JSONNull.CreateOrGet();
}
}
if (double.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
{
return result;
}
return token;
}
public static JSONNode Parse(string aJSON)
{
Stack<JSONNode> stack = new Stack<JSONNode>();
JSONNode jSONNode = null;
int i = 0;
StringBuilder stringBuilder = new StringBuilder();
string aKey = "";
bool flag = false;
bool flag2 = false;
bool flag3 = false;
for (; i < aJSON.Length; i++)
{
switch (aJSON[i])
{
case '{':
if (flag)
{
stringBuilder.Append(aJSON[i]);
break;
}
stack.Push(new JSONObject());
if (jSONNode != null)
{
jSONNode.Add(aKey, stack.Peek());
}
aKey = "";
stringBuilder.Length = 0;
jSONNode = stack.Peek();
flag3 = false;
break;
case '[':
if (flag)
{
stringBuilder.Append(aJSON[i]);
break;
}
stack.Push(new JSONArray());
if (jSONNode != null)
{
jSONNode.Add(aKey, stack.Peek());
}
aKey = "";
stringBuilder.Length = 0;
jSONNode = stack.Peek();
flag3 = false;
break;
case ']':
case '}':
if (flag)
{
stringBuilder.Append(aJSON[i]);
break;
}
if (stack.Count == 0)
{
throw new Exception("JSON Parse: Too many closing brackets");
}
stack.Pop();
if (stringBuilder.Length > 0 || flag2)
{
jSONNode.Add(aKey, ParseElement(stringBuilder.ToString(), flag2));
}
if (jSONNode != null)
{
jSONNode.Inline = !flag3;
}
flag2 = false;
aKey = "";
stringBuilder.Length = 0;
if (stack.Count > 0)
{
jSONNode = stack.Peek();
}
break;
case ':':
if (flag)
{
stringBuilder.Append(aJSON[i]);
break;
}
aKey = stringBuilder.ToString();
stringBuilder.Length = 0;
flag2 = false;
break;
case '"':
flag = !flag;
flag2 = flag2 || flag;
break;
case ',':
if (flag)
{
stringBuilder.Append(aJSON[i]);
break;
}
if (stringBuilder.Length > 0 || flag2)
{
jSONNode.Add(aKey, ParseElement(stringBuilder.ToString(), flag2));
}
flag2 = false;
aKey = "";
stringBuilder.Length = 0;
flag2 = false;
break;
case '\n':
case '\r':
flag3 = true;
break;
case '\t':
case ' ':
if (flag)
{
stringBuilder.Append(aJSON[i]);
}
break;
case '\\':
i++;
if (flag)
{
char c = aJSON[i];
switch (c)
{
case 't':
stringBuilder.Append('\t');
break;
case 'r':
stringBuilder.Append('\r');
break;
case 'n':
stringBuilder.Append('\n');
break;
case 'b':
stringBuilder.Append('\b');
break;
case 'f':
stringBuilder.Append('\f');
break;
case 'u':
{
string s = aJSON.Substring(i + 1, 4);
stringBuilder.Append((char)int.Parse(s, NumberStyles.AllowHexSpecifier));
i += 4;
break;
}
default:
stringBuilder.Append(c);
break;
}
}
break;
case '/':
if (allowLineComments && !flag && i + 1 < aJSON.Length && aJSON[i + 1] == '/')
{
while (++i < aJSON.Length && aJSON[i] != '\n' && aJSON[i] != '\r')
{
}
}
else
{
stringBuilder.Append(aJSON[i]);
}
break;
default:
stringBuilder.Append(aJSON[i]);
break;
case '\ufeff':
break;
}
}
if (flag)
{
throw new Exception("JSON Parse: Quotation marks seems to be messed up.");
}
if (jSONNode == null)
{
return ParseElement(stringBuilder.ToString(), flag2);
}
return jSONNode;
}
}
public class JSONArray : JSONNode
{
[CompilerGenerated]
private sealed class <get_Children>d__24 : IEnumerable<JSONNode>, IEnumerable, IEnumerator<JSONNode>, IDisposable, IEnumerator
{
private int <>1__state;
private JSONNode <>2__current;
private int <>l__initialThreadId;
public JSONArray <>4__this;
private List<JSONNode>.Enumerator <>7__wrap1;
JSONNode IEnumerator<JSONNode>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <get_Children>d__24(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if (num == -3 || num == 1)
{
try
{
}
finally
{
<>m__Finally1();
}
}
<>7__wrap1 = default(List<JSONNode>.Enumerator);
<>1__state = -2;
}
private bool MoveNext()
{
try
{
int num = <>1__state;
JSONArray jSONArray = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<>7__wrap1 = jSONArray.m_List.GetEnumerator();
<>1__state = -3;
break;
case 1:
<>1__state = -3;
break;
}
if (<>7__wrap1.MoveNext())
{
JSONNode current = <>7__wrap1.Current;
<>2__current = current;
<>1__state = 1;
return true;
}
<>m__Finally1();
<>7__wrap1 = default(List<JSONNode>.Enumerator);
return false;
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
((IDisposable)<>7__wrap1).Dispose();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<JSONNode> IEnumerable<JSONNode>.GetEnumerator()
{
<get_Children>d__24 result;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
result = this;
}
else
{
result = new <get_Children>d__24(0)
{
<>4__this = <>4__this
};
}
return result;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<JSONNode>)this).GetEnumerator();
}
}
private List<JSONNode> m_List = new List<JSONNode>();
private bool inline;
public override bool Inline
{
get
{
return inline;
}
set
{
inline = value;
}
}
public override JSONNodeType Tag => JSONNodeType.Array;
public override bool IsArray => true;
public override JSONNode this[int aIndex]
{
get
{
if (aIndex < 0 || aIndex >= m_List.Count)
{
return new JSONLazyCreator(this);
}
return m_List[aIndex];
}
set
{
if (value == null)
{
value = JSONNull.CreateOrGet();
}
if (aIndex < 0 || aIndex >= m_List.Count)
{
m_List.Add(value);
}
else
{
m_List[aIndex] = value;
}
}
}
public override JSONNode this[string aKey]
{
get
{
return new JSONLazyCreator(this);
}
set
{
if (value == null)
{
value = JSONNull.CreateOrGet();
}
m_List.Add(value);
}
}
public override int Count => m_List.Count;
public override IEnumerable<JSONNode> Children
{
[IteratorStateMachine(typeof(<get_Children>d__24))]
get
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <get_Children>d__24(-2)
{
<>4__this = this
};
}
}
public override Enumerator GetEnumerator()
{
return new Enumerator(m_List.GetEnumerator());
}
public override void Add(string aKey, JSONNode aItem)
{
if (aItem == null)
{
aItem = JSONNull.CreateOrGet();
}
m_List.Add(aItem);
}
public override JSONNode Remove(int aIndex)
{
if (aIndex < 0 || aIndex >= m_List.Count)
{
return null;
}
JSONNode result = m_List[aIndex];
m_List.RemoveAt(aIndex);
return result;
}
public override JSONNode Remove(JSONNode aNode)
{
m_List.Remove(aNode);
return aNode;
}
public override void Clear()
{
m_List.Clear();
}
public override JSONNode Clone()
{
JSONArray jSONArray = new JSONArray();
jSONArray.m_List.Capacity = m_List.Capacity;
foreach (JSONNode item in m_List)
{
if (item != null)
{
jSONArray.Add(item.Clone());
}
else
{
jSONArray.Add(null);
}
}
return jSONArray;
}
internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
{
aSB.Append('[');
int count = m_List.Count;
if (inline)
{
aMode = JSONTextMode.Compact;
}
for (int i = 0; i < count; i++)
{
if (i > 0)
{
aSB.Append(',');
}
if (aMode == JSONTextMode.Indent)
{
aSB.AppendLine();
}
if (aMode == JSONTextMode.Indent)
{
aSB.Append(' ', aIndent + aIndentInc);
}
m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
}
if (aMode == JSONTextMode.Indent)
{
aSB.AppendLine().Append(' ', aIndent);
}
aSB.Append(']');
}
}
public class JSONObject : JSONNode
{
[CompilerGenerated]
private sealed class <get_Children>d__27 : IEnumerable<JSONNode>, IEnumerable, IEnumerator<JSONNode>, IDisposable, IEnumerator
{
private int <>1__state;
private JSONNode <>2__current;
private int <>l__initialThreadId;
public JSONObject <>4__this;
private Dictionary<string, JSONNode>.Enumerator <>7__wrap1;
JSONNode IEnumerator<JSONNode>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <get_Children>d__27(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if (num == -3 || num == 1)
{
try
{
}
finally
{
<>m__Finally1();
}
}
<>7__wrap1 = default(Dictionary<string, JSONNode>.Enumerator);
<>1__state = -2;
}
private bool MoveNext()
{
try
{
int num = <>1__state;
JSONObject jSONObject = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<>7__wrap1 = jSONObject.m_Dict.GetEnumerator();
<>1__state = -3;
break;
case 1:
<>1__state = -3;
break;
}
if (<>7__wrap1.MoveNext())
{
<>2__current = <>7__wrap1.Current.Value;
<>1__state = 1;
return true;
}
<>m__Finally1();
<>7__wrap1 = default(Dictionary<string, JSONNode>.Enumerator);
return false;
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
((IDisposable)<>7__wrap1).Dispose();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<JSONNode> IEnumerable<JSONNode>.GetEnumerator()
{
<get_Children>d__27 result;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
result = this;
}
else
{
result = new <get_Children>d__27(0)
{
<>4__this = <>4__this
};
}
return result;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<JSONNode>)this).GetEnumerator();
}
}
private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>();
private bool inline;
public override bool Inline
{
get
{
return inline;
}
set
{
inline = value;
}
}
public override JSONNodeType Tag => JSONNodeType.Object;
public override bool IsObject => true;
public override JSONNode this[string aKey]
{
get
{
if (m_Dict.TryGetValue(aKey, out var value))
{
return value;
}
return new JSONLazyCreator(this, aKey);
}
set
{
if (value == null)
{
value = JSONNull.CreateOrGet();
}
if (m_Dict.ContainsKey(aKey))
{
m_Dict[aKey] = value;
}
else
{
m_Dict.Add(aKey, value);
}
}
}
public override JSONNode this[int aIndex]
{
get
{
if (aIndex < 0 || aIndex >= m_Dict.Count)
{
return null;
}
return m_Dict.ElementAt(aIndex).Value;
}
set
{
if (value == null)
{
value = JSONNull.CreateOrGet();
}
if (aIndex >= 0 && aIndex < m_Dict.Count)
{
string key = m_Dict.ElementAt(aIndex).Key;
m_Dict[key] = value;
}
}
}
public override int Count => m_Dict.Count;
public override IEnumerable<JSONNode> Children
{
[IteratorStateMachine(typeof(<get_Children>d__27))]
get
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <get_Children>d__27(-2)
{
<>4__this = this
};
}
}
public override Enumerator GetEnumerator()
{
return new Enumerator(m_Dict.GetEnumerator());
}
public override void Add(string aKey, JSONNode aItem)
{
if (aItem == null)
{
aItem = JSONNull.CreateOrGet();
}
if (aKey != null)
{
if (m_Dict.ContainsKey(aKey))
{
m_Dict[aKey] = aItem;
}
else
{
m_Dict.Add(aKey, aItem);
}
}
else
{
m_Dict.Add(Guid.NewGuid().ToString(), aItem);
}
}
public override JSONNode Remove(string aKey)
{
if (!m_Dict.ContainsKey(aKey))
{
return null;
}
JSONNode result = m_Dict[aKey];
m_Dict.Remove(aKey);
return result;
}
public override JSONNode Remove(int aIndex)
{
if (aIndex < 0 || aIndex >= m_Dict.Count)
{
return null;
}
KeyValuePair<string, JSONNode> keyValuePair = m_Dict.ElementAt(aIndex);
m_Dict.Remove(keyValuePair.Key);
return keyValuePair.Value;
}
public override JSONNode Remove(JSONNode aNode)
{
try
{
KeyValuePair<string, JSONNode> keyValuePair = m_Dict.Where((KeyValuePair<string, JSONNode> k) => k.Value == aNode).First();
m_Dict.Remove(keyValuePair.Key);
return aNode;
}
catch
{
return null;
}
}
public override void Clear()
{
m_Dict.Clear();
}
public override JSONNode Clone()
{
JSONObject jSONObject = new JSONObject();
foreach (KeyValuePair<string, JSONNode> item in m_Dict)
{
jSONObject.Add(item.Key, item.Value.Clone());
}
return jSONObject;
}
public override bool HasKey(string aKey)
{
return m_Dict.ContainsKey(aKey);
}
public override JSONNode GetValueOrDefault(string aKey, JSONNode aDefault)
{
if (m_Dict.TryGetValue(aKey, out var value))
{
return value;
}
return aDefault;
}
internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
{
aSB.Append('{');
bool flag = true;
if (inline)
{
aMode = JSONTextMode.Compact;
}
foreach (KeyValuePair<string, JSONNode> item in m_Dict)
{
if (!flag)
{
aSB.Append(',');
}
flag = false;
if (aMode == JSONTextMode.Indent)
{
aSB.AppendLine();
}
if (aMode == JSONTextMode.Indent)
{
aSB.Append(' ', aIndent + aIndentInc);
}
aSB.Append('"').Append(JSONNode.Escape(item.Key)).Append('"');
if (aMode == JSONTextMode.Compact)
{
aSB.Append(':');
}
else
{
aSB.Append(" : ");
}
item.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
}
if (aMode == JSONTextMode.Indent)
{
aSB.AppendLine().Append(' ', aIndent);
}
aSB.Append('}');
}
}
public class JSONString : JSONNode
{
private string m_Data;
public override JSONNodeType Tag => JSONNodeType.String;
public override bool IsString => true;
public override string Value
{
get
{
return m_Data;
}
set
{
m_Data = value;
}
}
public override Enumerator GetEnumerator()
{
return default(Enumerator);
}
public JSONString(string aData)
{
m_Data = aData;
}
public override JSONNode Clone()
{
return new JSONString(m_Data);
}
internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
{
aSB.Append('"').Append(JSONNode.Escape(m_Data)).Append('"');
}
public override bool Equals(object obj)
{
if (base.Equals(obj))
{
return true;
}
if (obj is string text)
{
return m_Data == text;
}
JSONString jSONString = obj as JSONString;
if (jSONString != null)
{
return m_Data == jSONString.m_Data;
}
return false;
}
public override int GetHashCode()
{
return m_Data.GetHashCode();
}
public override void Clear()
{
m_Data = "";
}
}
public class JSONNumber : JSONNode
{
private double m_Data;
public override JSONNodeType Tag => JSONNodeType.Number;
public override bool IsNumber => true;
public override string Value
{
get
{
return m_Data.ToString(CultureInfo.InvariantCulture);
}
set
{
if (double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
{
m_Data = result;
}
}
}
public override double AsDouble
{
get
{
return m_Data;
}
set
{
m_Data = value;
}
}
public override long AsLong
{
get
{
return (long)m_Data;
}
set
{
m_Data = value;
}
}
public override ulong AsULong
{
get
{
return (ulong)m_Data;
}
set
{
m_Data = value;
}
}
public override Enumerator GetEnumerator()
{
return default(Enumerator);
}
public JSONNumber(double aData)
{
m_Data = aData;
}
public JSONNumber(string aData)
{
Value = aData;
}
public override JSONNode Clone()
{
return new JSONNumber(m_Data);
}
internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
{
aSB.Append(Value.ToString(CultureInfo.InvariantCulture));
}
private static bool IsNumeric(object value)
{
if (!(value is int) && !(value is uint) && !(value is float) && !(value is double) && !(value is decimal) && !(value is long) && !(value is ulong) && !(value is short) && !(value is ushort) && !(value is sbyte))
{
return value is byte;
}
return true;
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (base.Equals(obj))
{
return true;
}
JSONNumber jSONNumber = obj as JSONNumber;
if (jSONNumber != null)
{
return m_Data == jSONNumber.m_Data;
}
if (IsNumeric(obj))
{
return Convert.ToDouble(obj) == m_Data;
}
return false;
}
public override int GetHashCode()
{
return m_Data.GetHashCode();
}
public override void Clear()
{
m_Data = 0.0;
}
}
public class JSONBool : JSONNode
{
private bool m_Data;
public override JSONNodeType Tag => JSONNodeType.Boolean;
public override bool IsBoolean => true;
public override string Value
{
get
{
return m_Data.ToString();
}
set
{
if (bool.TryParse(value, out var result))
{
m_Data = result;
}
}
}
public override bool AsBool
{
get
{
return m_Data;
}
set
{
m_Data = value;
}
}
public override Enumerator GetEnumerator()
{
return default(Enumerator);
}
public JSONBool(bool aData)
{
m_Data = aData;
}
public JSONBool(string aData)
{
Value = aData;
}
public override JSONNode Clone()
{
return new JSONBool(m_Data);
}
internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
{
aSB.Append(m_Data ? "true" : "false");
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (obj is bool)
{
return m_Data == (bool)obj;
}
return false;
}
public override int GetHashCode()
{
return m_Data.GetHashCode();
}
public override void Clear()
{
m_Data = false;
}
}
public class JSONNull : JSONNode
{
private static JSONNull m_StaticInstance = new JSONNull();
public static bool reuseSameInstance = true;
public override JSONNodeType Tag => JSONNodeType.NullValue;
public override bool IsNull => true;
public override string Value
{
get
{
return "null";
}
set
{
}
}
public override bool AsBool
{
get
{
return false;
}
set
{
}
}
public static JSONNull CreateOrGet()
{
if (reuseSameInstance)
{
return m_StaticInstance;
}
return new JSONNull();
}
private JSONNull()
{
}
public override Enumerator GetEnumerator()
{
return default(Enumerator);
}
public override JSONNode Clone()
{
return CreateOrGet();
}
public override bool Equals(object obj)
{
if ((object)this == obj)
{
return true;
}
return obj is JSONNull;
}
public override int GetHashCode()
{
return 0;
}
internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
{
aSB.Append("null");
}
}
internal class JSONLazyCreator : JSONNode
{
private JSONNode m_Node;
private string m_Key;
public override JSONNodeType Tag => JSONNodeType.None;
public override JSONNode this[int aIndex]
{
get
{
return new JSONLazyCreator(this);
}
set
{
Set(new JSONArray()).Add(value);
}
}
public override JSONNode this[string aKey]
{
get
{
return new JSONLazyCreator(this, aKey);
}
set
{
Set(new JSONObject()).Add(aKey, value);
}
}
public override int AsInt
{
get
{
Set(new JSONNumber(0.0));
return 0;
}
set
{
Set(new JSONNumber(value));
}
}
public override float AsFloat
{
get
{
Set(new JSONNumber(0.0));
return 0f;
}
set
{
Set(new JSONNumber(value));
}
}
public override double AsDouble
{
get
{
Set(new JSONNumber(0.0));
return 0.0;
}
set
{
Set(new JSONNumber(value));
}
}
public override long AsLong
{
get
{
if (JSONNode.longAsString)
{
Set(new JSONString("0"));
}
else
{
Set(new JSONNumber(0.0));
}
return 0L;
}
set
{
if (JSONNode.longAsString)
{
Set(new JSONString(value.ToString(CultureInfo.InvariantCulture)));
}
else
{
Set(new JSONNumber(value));
}
}
}
public override ulong AsULong
{
get
{
if (JSONNode.longAsString)
{
Set(new JSONString("0"));
}
else
{
Set(new JSONNumber(0.0));
}
return 0uL;
}
set
{
if (JSONNode.longAsString)
{
Set(new JSONString(value.ToString(CultureInfo.InvariantCulture)));
}
else
{
Set(new JSONNumber(value));
}
}
}
public override bool AsBool
{
get
{
Set(new JSONBool(aData: false));
return false;
}
set
{
Set(new JSONBool(value));
}
}
public override JSONArray AsArray => Set(new JSONArray());
public override JSONObject AsObject => Set(new JSONObject());
public override Enumerator GetEnumerator()
{
return default(Enumerator);
}
public JSONLazyCreator(JSONNode aNode)
{
m_Node = aNode;
m_Key = null;
}
public JSONLazyCreator(JSONNode aNode, string aKey)
{
m_Node = aNode;
m_Key = aKey;
}
private T Set<T>(T aVal) where T : JSONNode
{
if (m_Key == null)
{
m_Node.Add(aVal);
}
else
{
m_Node.Add(m_Key, aVal);
}
m_Node = null;
return aVal;
}
public override void Add(JSONNode aItem)
{
Set(new JSONArray()).Add(aItem);
}
public override void Add(string aKey, JSONNode aItem)
{
Set(new JSONObject()).Add(aKey, aItem);
}
public static bool operator ==(JSONLazyCreator a, object b)
{
if (b == null)
{
return true;
}
return (object)a == b;
}
public static bool operator !=(JSONLazyCreator a, object b)
{
return !(a == b);
}
public override bool Equals(object obj)
{
if (obj == null)
{
return true;
}
return (object)this == obj;
}
public override int GetHashCode()
{
return 0;
}
internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
{
aSB.Append("null");
}
}
public static class JSON
{
public static JSONNode Parse(string aJSON)
{
return JSONNode.Parse(aJSON);
}
}
}
namespace SullysAutoPinner
{
public class ConfigWatcher : IDisposable
{
private readonly string _filePath;
private readonly ManualLogSource _logger;
private readonly Action _onConfigChanged;
private FileSystemWatcher _watcher;
private Timer _debounceTimer;
public ConfigWatcher(string filePath, Action onConfigChanged, ManualLogSource logger)
{
_filePath = filePath;
_onConfigChanged = onConfigChanged;
_logger = logger;
if (!File.Exists(filePath))
{
_logger.LogWarning((object)("[ConfigWatcher] File does not exist yet: " + filePath));
return;
}
string directoryName = Path.GetDirectoryName(filePath);
string fileName = Path.GetFileName(filePath);
_watcher = new FileSystemWatcher(directoryName, fileName)
{
NotifyFilter = (NotifyFilters.Size | NotifyFilters.LastWrite),
EnableRaisingEvents = true
};
_watcher.Changed += OnChanged;
_watcher.Renamed += OnChanged;
_logger.LogInfo((object)("[ConfigWatcher] Watching for changes: " + filePath));
}
private void OnChanged(object sender, FileSystemEventArgs e)
{
_debounceTimer?.Dispose();
_debounceTimer = new Timer(delegate
{
try
{
_logger.LogInfo((object)("[ConfigWatcher] Detected config change: " + _filePath));
_onConfigChanged?.Invoke();
}
catch (Exception ex)
{
_logger.LogWarning((object)("[ConfigWatcher] Reload failed: " + ex.Message));
}
}, null, 300, -1);
}
public void Dispose()
{
_watcher?.Dispose();
_debounceTimer?.Dispose();
}
}
[BepInPlugin("sullys.autopinner", "Sullys Auto Pinner", "1.4.0")]
public class SullysAutoPinner : BaseUnityPlugin
{
private PinManager _pinManager;
private ModConfig _config;
private PinScanner _scanner;
private PrefabTracker _prefabTracker;
private float _lastScanTime;
private LocalizationManager _localizationManager;
private ConfigWatcher _configWatcher;
private void Awake()
{
_config = new ModConfig(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
string filePath = Path.Combine(Paths.ConfigPath, "sullys.autopinner.cfg");
_configWatcher = new ConfigWatcher(filePath, OnConfigReloaded, ((BaseUnityPlugin)this).Logger);
LocalizationManager.EnsureBaseLanguageFiles(((BaseUnityPlugin)this).Logger);
_localizationManager = new LocalizationManager(((BaseUnityPlugin)this).Logger, _config.PreferredLanguage.Value);
_pinManager = new PinManager(_config, ((BaseUnityPlugin)this).Logger, _localizationManager);
_prefabTracker = new PrefabTracker(((BaseUnityPlugin)this).Logger, _config);
_scanner = new PinScanner(_config, _pinManager, _prefabTracker);
((BaseUnityPlugin)this).Logger.LogWarning((object)"SullysAutoPinner Initialized");
}
private void OnConfigReloaded()
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"[SullysAutoPinner] Reloading config from file...");
((BaseUnityPlugin)this).Config.Reload();
_localizationManager.Reload(_config.PreferredLanguage.Value);
_pinManager.ReloadConfig();
if (_config.ClearAllUnwantedPins.Value)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"[SullysAutoPinner] Remove Unwanted Pins Triggered");
_pinManager.RemoveUnwantedPins(_config);
_config.ClearAllUnwantedPins.Value = false;
}
if (_config.ClearAllMapPinsAndHistory.Value)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"[SullysAutoPinner] Remove All Pins and History Triggered");
_pinManager.RemoveAllPins();
_config.ClearAllMapPinsAndHistory.Value = false;
}
}
private void Update()
{
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)Player.m_localPlayer == (Object)null))
{
if (Time.time - _lastScanTime > _config.ScanInterval.Value)
{
_lastScanTime = Time.time;
_scanner.RunScan(((Component)Player.m_localPlayer).transform.position);
}
_pinManager.TryPeriodicSave();
_prefabTracker.TryPeriodicSave();
}
}
private void OnApplicationQuit()
{
_pinManager.SaveImmediate();
_prefabTracker.SaveImmediate();
}
}
public class PrefabTracker
{
private readonly HashSet<string> _seenPrefabs = new HashSet<string>();
private readonly ManualLogSource _logger;
private readonly ModConfig _config;
private float _lastPrefabDumpTime;
private const float DumpInterval = 300f;
private const int PrefabFlushThreshold = 1000;
private const string PrefabsFilePath = "BepInEx/config/SullysAutoPinnerFiles/SeenPrefabs.txt";
private static readonly HashSet<string> IgnoredPrefabs = new HashSet<string> { "tree", "bush", "log", "stone", "branch" };
public PrefabTracker(ManualLogSource logger, ModConfig config)
{
_logger = logger;
_config = config;
Directory.CreateDirectory(Path.GetDirectoryName("BepInEx/config/SullysAutoPinnerFiles/SeenPrefabs.txt"));
}
public void LogPrefabHierarchy(GameObject rootGO)
{
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Expected O, but got Unknown
if (!_config.EnablePrefabLogging.Value || (Object)(object)rootGO == (Object)null)
{
return;
}
string text = ((Object)rootGO).name.ToLowerInvariant();
foreach (string ignoredPrefab in IgnoredPrefabs)
{
if (text.Contains(ignoredPrefab))
{
return;
}
}
List<string> list = new List<string>();
foreach (Transform item2 in rootGO.transform)
{
Transform val = item2;
if ((Object)(object)val != (Object)null)
{
list.Add(((Object)val).name);
}
}
list.Sort();
string item = ((Object)rootGO).name + " | " + string.Join(",", list);
if (_seenPrefabs.Add(item) && _seenPrefabs.Count >= 1000)
{
SaveImmediate();
}
}
public void TryPeriodicSave()
{
if (_config.EnablePrefabLogging.Value && Time.time - _lastPrefabDumpTime > 300f)
{
SaveImmediate();
}
}
public void SaveImmediate()
{
_lastPrefabDumpTime = Time.time;
try
{
HashSet<string> hashSet = new HashSet<string>();
if (File.Exists("BepInEx/config/SullysAutoPinnerFiles/SeenPrefabs.txt"))
{
string[] array = File.ReadAllLines("BepInEx/config/SullysAutoPinnerFiles/SeenPrefabs.txt");
foreach (string item in array)
{
hashSet.Add(item);
}
}
using StreamWriter streamWriter = File.AppendText("BepInEx/config/SullysAutoPinnerFiles/SeenPrefabs.txt");
foreach (string seenPrefab in _seenPrefabs)
{
if (!hashSet.Contains(seenPrefab))
{
streamWriter.WriteLine(seenPrefab);
}
}
}
catch (Exception ex)
{
_logger.LogWarning((object)("SullyAutoPinner >>> Error saving prefab list: " + ex.Message));
}
}
}
public class PinScanner
{
public static class PinLabelMap
{
public static readonly Dictionary<string, (string SettingKey, PinType Icon)> LabelToSettingInfo = new Dictionary<string, (string, PinType)>(StringComparer.OrdinalIgnoreCase)
{
{
"abomination",
("Abomination", (PinType)3)
},
{
"crypt2",
("Crypt", (PinType)3)
},
{
"crypt3",
("Crypt", (PinType)3)
},
{
"crypt4",
("Crypt", (PinType)3)
},
{
"trollcave",
("TrollCave", (PinType)3)
},
{
"dwarfspawner",
("DwarfSpawner", (PinType)2)
},
{
"draugrspawner",
("DraugrSpawner", (PinType)2)
},
{
"totem",
("Totem", (PinType)2)
},
{
"skel",
("Skeleton", (PinType)3)
},
{
"seekerbrute",
("SeekerBrute", (PinType)3)
},
{
"bonemawserpent",
("BonemawSerpent", (PinType)3)
},
{
"rock4_copper",
("Copper", (PinType)3)
},
{
"iron_deposit",
("Iron", (PinType)3)
},
{
"mudpile",
("Mudpile", (PinType)3)
},
{
"obsidian",
("Obsidian", (PinType)3)
},
{
"rock3_silver",
("Silver", (PinType)3)
},
{
"silvervein",
("Silver", (PinType)3)
},
{
"meteor",
("Meteorite", (PinType)3)
},
{
"pickable_tar",
("Tar", (PinType)2)
},
{
"pickable_flax_wild",
("Flax", (PinType)3)
},
{
"flax",
("Flax", (PinType)3)
},
{
"barley",
("Barley", (PinType)3)
},
{
"blueberry",
("BlueBerries", (PinType)3)
},
{
"raspberry",
("RaspBerries", (PinType)3)
},
{
"shroom",
("Mushrooms", (PinType)3)
},
{
"cloud",
("CloudBerries", (PinType)3)
},
{
"thistle",
("Thistle", (PinType)3)
},
{
"carrot",
("Seeds", (PinType)3)
},
{
"onion",
("Seeds", (PinType)3)
},
{
"turnip",
("Seeds", (PinType)3)
},
{
"magecap",
("MageCaps", (PinType)3)
},
{
"y-pcone",
("YPCones", (PinType)3)
},
{
"j-puff",
("JotunPuffs", (PinType)3)
},
{
"v-egg",
("VoltureEgg", (PinType)3)
},
{
"dragonegg",
("DragonEgg", (PinType)3)
},
{
"pickable_smokepuff",
("SmokePuffs", (PinType)3)
},
{
"thing",
("DvergerThings", (PinType)3)
},
{
"giant_sword1",
("GiantSword", (PinType)3)
},
{
"giant_ribs",
("GiantRibs", (PinType)3)
},
{
"giant_skull",
("GiantSkull", (PinType)3)
},
{
"giant_brain",
("GiantBrain", (PinType)3)
},
{
"marker",
("Marker", (PinType)2)
},
{
"campfire",
("Fire", (PinType)0)
},
{
"firepit",
("Fire", (PinType)0)
},
{
"treasurechest",
("Treasure", (PinType)3)
},
{
"shipwreck_karve_chest",
("ShipwreckChest", (PinType)3)
},
{
"pickable_dvergrlantern",
("Lantern", (PinType)3)
},
{
"mistlands_excavation2",
("Excavation", (PinType)3)
},
{
"ashland_pot1_green",
("AshlandPotGreen", (PinType)3)
},
{
"ashland_pot2_red",
("AshlandPotRed", (PinType)3)
},
{
"ashland_pot3_red",
("AshlandPotRed", (PinType)3)
}
};
}
private readonly ModConfig _config;
private readonly PinManager _pinManager;
private readonly PrefabTracker _prefabTracker;
public PinScanner(ModConfig config, PinManager pinManager, PrefabTracker prefabTracker)
{
_config = config;
_pinManager = pinManager;
_prefabTracker = prefabTracker;
}
public void RunScan(Vector3 playerPosition)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_024b: Unknown result type (might be due to invalid IL or missing references)
//IL_0250: Unknown result type (might be due to invalid IL or missing references)
//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
//IL_026f: Unknown result type (might be due to invalid IL or missing references)
//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
if (_config.ClearNearbyFallbackPinsOnNextScan.Value)
{
_pinManager.RemoveNearbyFallbackPins(playerPosition, _config.ScanRadius.Value);
_config.ClearNearbyFallbackPinsOnNextScan.Value = false;
}
if (playerPosition.y > 1000f)
{
return;
}
Collider[] array = Physics.OverlapSphere(playerPosition, _config.ScanRadius.Value, -1, (QueryTriggerInteraction)2);
List<Vector3> list = new List<Vector3>();
List<(Vector3, Transform)> list2 = new List<(Vector3, Transform)>();
Collider[] array2 = array;
foreach (Collider obj in array2)
{
GameObject gameObject = ((Component)((Component)obj).transform.root).gameObject;
if ((Object)(object)gameObject == (Object)null)
{
continue;
}
_prefabTracker.LogPrefabHierarchy(gameObject);
string text = ((Object)gameObject).name.ToLowerInvariant();
Vector3 pinPos2 = gameObject.transform.position;
string matchedLabel;
PinType icon;
if (text.Contains("locationproxy"))
{
list2.Add((pinPos2, gameObject.transform));
}
else if (TryMatchPrefab(text, out matchedLabel, out icon))
{
if (matchedLabel == "TROLLCAVE")
{
list.Add(pinPos2);
}
if (!(matchedLabel == "CRYPT") || !list.Any((Vector3 tc) => Vector3.Distance(tc, pinPos2) < 40f))
{
_pinManager.TryAddPin(pinPos2, matchedLabel, icon);
}
}
}
foreach (var item in list2)
{
var (val, _) = item;
foreach (Transform item2 in item.Item2)
{
string text2 = ((Object)item2).name.ToLowerInvariant();
if (!text2.Contains("runestone") && TryMatchPrefab(text2, out var matchedLabel2, out var icon2))
{
if (matchedLabel2 == "TROLLCAVE")
{
list.Add(val);
_pinManager.TryAddPin(val, matchedLabel2, icon2);
}
break;
}
}
}
foreach (var item3 in list2)
{
var (pinPos, _) = item3;
foreach (Transform item4 in item3.Item2)
{
string text3 = ((Object)item4).name.ToLowerInvariant();
if (!text3.Contains("runestone") && TryMatchPrefab(text3, out var matchedLabel3, out var icon3))
{
if (!(matchedLabel3 == "TROLLCAVE") && (!(matchedLabel3 == "CRYPT") || !list.Any((Vector3 tc) => Vector3.Distance(tc, pinPos) < 40f)))
{
_pinManager.TryAddPin(pinPos, matchedLabel3, icon3);
}
break;
}
}
}
}
private string CleanLabel(string rawName)
{
return Regex.Replace(rawName.Replace("(Clone)", ""), "\\d", "").ToUpperInvariant();
}
private bool TryMatchPrefab(string prefabName, out string matchedLabel, out PinType icon)
{
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Expected I4, but got Unknown
matchedLabel = null;
icon = (PinType)3;
foreach (KeyValuePair<string, (string, PinType)> item2 in PinLabelMap.LabelToSettingInfo)
{
if (prefabName.IndexOf(item2.Key, StringComparison.OrdinalIgnoreCase) < 0)
{
continue;
}
string item = item2.Value.Item1;
FieldInfo field = typeof(ModConfig).GetField(item, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);
if (!(field == null) && !(field.FieldType != typeof(ConfigEntry<bool>)))
{
ConfigEntry<bool> val = (ConfigEntry<bool>)field.GetValue(_config);
if (val != null && val.Value)
{
matchedLabel = item.ToUpperInvariant();
icon = (PinType)(int)item2.Value.Item2;
return true;
}
}
}
if (_config.ShowUnmappedPrefabs.Value)
{
string[] array = new string[85]
{
"beech", "berry", "birch", "boar", "branch", "bush", "dandelion", "deer", "feathers", "fish",
"firtree", "fur", "goblin", "goblin_archer", "goblin_banner", "goblin_bed", "goblin_fence", "goblin_pole", "goblin_roof", "goblin_roof_cap",
"goblin_shaman", "goblin_stepladder", "greyling", "greydwarf", "mushroom", "neck", "oak1", "pickable_dolmentreasure", "pickable_forestcryptremains", "pickable_flint",
"pickable_stone", "player", "pine", "piece_sharpstakes", "piece_workbench", "berries", "resin", "seagal", "shrub", "stone",
"stone_wall", "stubbe", "vines", "wood", "zone", "pillar", "carrot", "turnip", "onion", "thistle",
"minerock_tin", "crow", "odin", "pickable_tar", "tarliquid", "skeleton", "deathsquito", "forestcrypt", "swamptree", "wraith",
"statue", "leech", "table", "draugr", "blob", "oak", "leather", "log", "meat", "seed",
"bonefragments", "honey", "forge", "entrails", "bonepile", "castlekit", "trophy", "sunken", "root", "guck",
"swamp", "grave", "piece", "rock_3", "rock_4"
};
foreach (string value in array)
{
if (prefabName.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
{
return false;
}
}
matchedLabel = prefabName.Replace("(clone)", "");
icon = (PinType)2;
return true;
}
return false;
}
}
public class ModConfig
{
private readonly ManualLogSource _logger;
public ConfigEntry<string> PreferredLanguage;
public ConfigEntry<float> ScanRadius;
public ConfigEntry<float> ScanInterval;
public ConfigEntry<float> SaveInterval;
public ConfigEntry<float> PinMergeDistance;
public ConfigEntry<bool> EnablePinSaving;
public ConfigEntry<bool> EnablePrefabLogging;
public ConfigEntry<bool> ClearAllMapPinsAndHistory;
public ConfigEntry<bool> ClearAllUnwantedPins;
public ConfigEntry<bool> ClearNearbyFallbackPinsOnNextScan;
public ConfigEntry<bool> ShowUnmappedPrefabs;
public ConfigEntry<bool> Abomination;
public ConfigEntry<bool> AshlandPotGreen;
public ConfigEntry<bool> AshlandPotRed;
public ConfigEntry<bool> Barley;
public ConfigEntry<bool> BlueBerries;
public ConfigEntry<bool> BonemawSerpent;
public ConfigEntry<bool> CloudBerries;
public ConfigEntry<bool> Copper;
public ConfigEntry<bool> Crypt;
public ConfigEntry<bool> DragonEgg;
public ConfigEntry<bool> DraugrSpawner;
public ConfigEntry<bool> DvergerThings;
public ConfigEntry<bool> DwarfSpawner;
public ConfigEntry<bool> Excavation;
public ConfigEntry<bool> Fire;
public ConfigEntry<bool> Flax;
public ConfigEntry<bool> GiantBrain;
public ConfigEntry<bool> GiantRibs;
public ConfigEntry<bool> GiantSkull;
public ConfigEntry<bool> GiantSword;
public ConfigEntry<bool> Iron;
public ConfigEntry<bool> JotunPuffs;
public ConfigEntry<bool> Lantern;
public ConfigEntry<bool> MageCaps;
public ConfigEntry<bool> Marker;
public ConfigEntry<bool> Meteorite;
public ConfigEntry<bool> MistlandsGiants;
public ConfigEntry<bool> MistlandsSwords;
public ConfigEntry<bool> Mudpile;
public ConfigEntry<bool> Mushrooms;
public ConfigEntry<bool> Obsidian;
public ConfigEntry<bool> Onion;
public ConfigEntry<bool> PickableSmokePuff;
public ConfigEntry<bool> RaspBerries;
public ConfigEntry<bool> Seeds;
public ConfigEntry<bool> SeekerBrute;
public ConfigEntry<bool> ShipwreckChest;
public ConfigEntry<bool> Silver;
public ConfigEntry<bool> Skeleton;
public ConfigEntry<bool> SmokePuffs;
public ConfigEntry<bool> Tar;
public ConfigEntry<bool> Thistle;
public ConfigEntry<bool> Tin;
public ConfigEntry<bool> Totem;
public ConfigEntry<bool> Treasure;
public ConfigEntry<bool> TrollCave;
public ConfigEntry<bool> Turnip;
public ConfigEntry<bool> VoltureEgg;
public ConfigEntry<bool> YPCones;
public ModConfig(ConfigFile config, ManualLogSource logger)
{
_logger = logger;
PreferredLanguage = config.Bind<string>("Localization", "LanguageCode", "en", "Language code for localization (en, fr, ru, etc).");
ScanRadius = config.Bind<float>("Scanning", "ScanRadius", 300f, "Radius (in meters) to scan for prefabs.");
ScanInterval = config.Bind<float>("Scanning", "ScanInterval", 12f, "Time (in seconds) between environment scans.");
SaveInterval = config.Bind<float>("Persistence", "SaveInterval", 120f, "How often to save pins to disk (in seconds).");
PinMergeDistance = config.Bind<float>("Pins", "PinMergeDistance", 50f, "Distance (in meters) at which duplicate pins are merged.");
EnablePinSaving = config.Bind<bool>("Persistence", "EnablePinSaving", true, "Enable saving of detected pins.");
EnablePrefabLogging = config.Bind<bool>("Debug", "EnablePrefabLogging", false, "Enable logging of prefab names and hierarchy for debugging.");
ClearAllMapPinsAndHistory = config.Bind<bool>("Admin", "ClearAllMapPinsAndHistory", false, "Clear all pins and reset history file on next run.");
ClearAllUnwantedPins = config.Bind<bool>("Admin", "ClearAllUnwantedPins", false, "Clear only pins that do not match active settings.");
ClearNearbyFallbackPinsOnNextScan = config.Bind<bool>("Admin", "ClearNearbyFallbackPinsOnNextScan", false, "Remove fallback pins near the player on next scan.");
ShowUnmappedPrefabs = config.Bind<bool>("Fallback", "ShowUnmappedPrefabs", false, "Create pins for unknown prefabs using prefab name.");
Mushrooms = config.Bind<bool>("Pins", "Mushrooms", false, "");
RaspBerries = config.Bind<bool>("Pins", "RaspBerries", false, "");
BlueBerries = config.Bind<bool>("Pins", "BlueBerries", false, "");
Seeds = config.Bind<bool>("Pins", "Seeds", false, "");
Thistle = config.Bind<bool>("Pins", "Thistle", false, "");
CloudBerries = config.Bind<bool>("Pins", "CloudBerries", false, "");
Copper = config.Bind<bool>("Pins", "Copper", true, "");
Tin = config.Bind<bool>("Pins", "Tin", false, "");
Skeleton = config.Bind<bool>("Pins", "Skeleton", false, "");
DwarfSpawner = config.Bind<bool>("Pins", "DwarfSpawner", true, "");
TrollCave = config.Bind<bool>("Pins", "TrollCave", true, "");
Crypt = config.Bind<bool>("Pins", "Crypt", true, "");
Totem = config.Bind<bool>("Pins", "Totem", true, "");
Fire = config.Bind<bool>("Pins", "Fire", true, "");
DraugrSpawner = config.Bind<bool>("Pins", "DraugrSpawner", false, "");
Treasure = config.Bind<bool>("Pins", "Treasure", false, "");
Barley = config.Bind<bool>("Pins", "Barley", false, "");
Flax = config.Bind<bool>("Pins", "Flax", false, "");
Tar = config.Bind<bool>("Pins", "Tar", true, "");
DragonEgg = config.Bind<bool>("Pins", "DragonEgg", true, "");
VoltureEgg = config.Bind<bool>("Pins", "VoltureEgg", true, "");
SmokePuffs = config.Bind<bool>("Pins", "SmokePuffs", false, "");
MageCaps = config.Bind<bool>("Pins", "MageCaps", true, "");
YPCones = config.Bind<bool>("Pins", "YPCones", true, "");
JotunPuffs = config.Bind<bool>("Pins", "JotunPuffs", true, "");
Iron = config.Bind<bool>("Pins", "Iron", true, "");
Mudpile = config.Bind<bool>("Pins", "Mudpile", true, "");
Abomination = config.Bind<bool>("Pins", "Abomination", true, "");
Meteorite = config.Bind<bool>("Pins", "Meteorite", true, "");
Obsidian = config.Bind<bool>("Pins", "Obsidian", true, "");
Silver = config.Bind<bool>("Pins", "Silver", true, "");
MistlandsGiants = config.Bind<bool>("Pins", "MistlandsGiants", true, "");
MistlandsSwords = config.Bind<bool>("Pins", "MistlandsSwords", true, "");
DvergerThings = config.Bind<bool>("Pins", "DvergerThings", true, "");
BonemawSerpent = config.Bind<bool>("Pins", "BonemawSerpent", true, "");
GiantSword = config.Bind<bool>("Pins", "GiantSword", true, "");
GiantRibs = config.Bind<bool>("Pins", "GiantRibs", true, "");
GiantSkull = config.Bind<bool>("Pins", "GiantSkull", true, "");
GiantBrain = config.Bind<bool>("Pins", "GiantBrain", true, "");
Lantern = config.Bind<bool>("Pins", "Lantern", true, "");
Excavation = config.Bind<bool>("Pins", "Excavation", true, "");
AshlandPotGreen = config.Bind<bool>("Pins", "AshlandPotGreen", true, "");
AshlandPotRed = config.Bind<bool>("Pins", "AshlandPotRed", true, "");
ShipwreckChest = config.Bind<bool>("Pins", "ShipwreckChest", true, "");
SeekerBrute = config.Bind<bool>("Pins", "SeekerBrute", true, "");
Marker = config.Bind<bool>("Pins", "Marker", true, "");
}
}
}