Please disclose if your mod was created primarily 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 Rune Tablet v1.1.0
RuneTablet/RuneTablet.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Splatform; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("RuneTablet")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+5c5184f8fb1729c07283e4a8f38a1ad7df2c259a")] [assembly: AssemblyProduct("Make a rune tablet to locate dungeons")] [assembly: AssemblyTitle("RuneTablet")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 RuneTablet { public static class Helper { private static Dictionary<string, string> PinNames = new Dictionary<string, string> { { "Crypt2", "$location_forestcrypt" }, { "Crypt3", "$location_forestcrypt" }, { "Crypt4", "$location_forestcrypt" }, { "Mistlands_DvergrTownEntrance1", "$location_dvergrtown" }, { "Mistlands_DvergrTownEntrance2", "$location_dvergrtown" }, { "Hildir_crypt", "$hud_pin_hildir1" }, { "Hildir_cave", "$hud_pin_hildir2" }, { "Hildir_plainsfortress", "$hud_pin_hildir3" }, { "MountainCave02", "$location_mountaincave" }, { "GoblinCamp2", "$enemy_goblin" }, { "SunkenCrypt4", "$location_sunkencrypt" }, { "MorgenHole1", "$location_morgenhole" }, { "MorgenHole2", "$location_morgenhole" }, { "MorgenHole3", "$location_morgenhole" } }; public static string GetHashedName(RuneStone component) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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) Vector3 position = ((Component)component).transform.position; int num = (int)position.x * 31 + (int)position.z * 37; return ((Object)component).name + "-" + num; } public static LocationInstance? GetLocationInstance(Location location) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_0038: Unknown result type (might be due to invalid IL or missing references) Vector2i zone = ZoneSystem.GetZone(((Component)location).transform.position); if (!ZoneSystem.instance.m_locationInstances.TryGetValue(zone, out var value)) { return null; } return value; } public static string GetHashedName(Location location) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) LocationInstance? locationInstance = GetLocationInstance(location); if (locationInstance.HasValue) { return GetHashedName(locationInstance.Value); } Plugin.Logger.LogError((object)("Could not find location instance for " + ((Object)location).name)); return null; } public static string GetHashedName(LocationInstance instance) { //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_000c: 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_0029: 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) Vector2i zone = ZoneSystem.GetZone(instance.m_position); string name = ZNet.World.m_name; string name2 = instance.m_location.m_prefab.Name; int num = zone.x * 31 + zone.y * 37; return $"{name}-{name2}-{num}"; } public static string GetPinName(string locationName) { string value; return PinNames.TryGetValue(locationName, out value) ? value : locationName; } } [HarmonyPatch(typeof(Player))] public class PlayerPatches { [HarmonyPostfix] [HarmonyPatch("Save")] public static void SavePostfix() { if (!((Object)(object)Player.m_localPlayer == (Object)null)) { Plugin.SaveToDisk(); } } [HarmonyPostfix] [HarmonyPatch("Load")] public static void LoadPostfix() { if (!((Object)(object)Player.m_localPlayer == (Object)null)) { Plugin.LoadFromDisk(); } } [HarmonyPrefix] [HarmonyPatch("ConsumeItem")] public static bool ConsumeItemPrefix(Inventory inventory, ItemData item, ref Player __instance, ref bool __result) { if (item.m_shared.m_name != "$item_runetablet") { return true; } Plugin.Logger.LogInfo((object)"Player.ConsumeItem: Called on Rune Tablet"); __result = RuneTablet.Consume(__instance); if (__result) { InventoryGui.instance.Hide(); inventory.RemoveItem(item); } return false; } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("org.bepinex.plugins.rune_tablet", "Rune Tablet", "1.1.0")] public class Plugin : BaseUnityPlugin { public const string RuneTabletGuid = "org.bepinex.plugins.rune_tablet"; public const string RuneTabletName = "Rune Tablet"; public const string NumericVersion = "1.1.0"; private static readonly GameVersion MinSupportedGameVersion = new GameVersion(0, 219, 10); public static List<string> FoundRuneStones = new List<string>(); public static List<string> FoundDungeons = new List<string>(); private CustomLocalization Localization; private static readonly Harmony Harmony = new Harmony("mod.rune_tablet"); public static string SaveFile { get { Player localPlayer = Player.m_localPlayer; string text = ((localPlayer != null) ? localPlayer.GetPlayerName() : null); if (string.IsNullOrEmpty(text) || text == "...") { return null; } text += "_runetablet.fch"; return Path.Combine(Utils.GetSaveDataPath((FileSource)3), text); } } public static ManualLogSource Logger { get; private set; } private static bool IsGameVersionTooOld() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) return Version.CurrentVersion < MinSupportedGameVersion; } private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)("Valheim game version: " + Version.GetVersionString(false))); if (IsGameVersionTooOld()) { LogTooOld(); Logger.LogFatal((object)"Aborting loading of Rune Tablet due to incompatible version."); return; } LoadAssets(); AddLocalization(); PrefabManager.OnVanillaPrefabsAvailable += AddClonedItems; Harmony.PatchAll(); Logger.LogInfo((object)"Rune Tablet done loading."); } private void AddLocalization() { Localization = LocalizationManager.Instance.GetLocalization(); CustomLocalization localization = Localization; string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "item_runecrystal", "Rune Crystal" }, { "item_runecrystal_desc", "A potent source of energy from a runestone" }, { "item_runetablet", "Rune Tablet" }, { "item_runetablet_desc", "A mysterious tablet inscribed with runes glowing with energy." } }); } private void LoadAssets() { //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_007c: 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) string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); Texture2D val = AssetUtils.LoadTexture(Path.Combine(directoryName, "Assets/rune_crystal.png"), true); Texture2D val2 = AssetUtils.LoadTexture(Path.Combine(directoryName, "Assets/rune_tablet.png"), true); RuneCrystal.IconSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), Vector2.zero); RuneTablet.IconSprite = Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), Vector2.zero); } private void AddClonedItems() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) RuneCrystal runeCrystal = new RuneCrystal(); RuneTablet runeTablet = new RuneTablet(); ItemManager.Instance.AddItem((CustomItem)(object)runeCrystal); ItemManager.Instance.AddItem((CustomItem)(object)runeTablet); ((CustomItem)runeTablet).ItemDrop.m_itemData.m_shared.m_itemType = (ItemType)2; PrefabManager.OnVanillaPrefabsAvailable -= AddClonedItems; } public static void SaveLocation(LocationInstance instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) string hashedName = Helper.GetHashedName(instance); if (!FoundDungeons.Contains(hashedName)) { FoundDungeons.Add(hashedName); Logger.LogInfo((object)("Saved location " + hashedName)); } } public static void RecoverPins() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_0096: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<Vector2i, LocationInstance> locationInstance in ZoneSystem.instance.m_locationInstances) { string hashedName = Helper.GetHashedName(locationInstance.Value); if (FoundDungeons.Contains(hashedName) && !Minimap.instance.HavePinInRange(locationInstance.Value.m_position, 14f)) { Minimap.instance.AddPin(locationInstance.Value.m_position, (PinType)14, Helper.GetPinName(locationInstance.Value.m_location.m_prefabName), true, false, 0L, default(PlatformUserID)); } } } private static void LogTooOld() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) Logger.LogError((object)("This version of Rune Tablet (1.1.0) expects a minimum game version of " + $"\"{MinSupportedGameVersion}\", but this game version is older at \"{Version.CurrentVersion}\". " + "Please either update the Valheim game, or use an older version of Rune Tablet.")); } public static void SaveToDisk() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown if (SaveFile == null) { Logger.LogError((object)"Something went wrong when trying to save to disk"); return; } ZPackage val = new ZPackage(); ZPackage val2 = new ZPackage(); foreach (string foundRuneStone in FoundRuneStones) { val2.Write(foundRuneStone); } ZPackage val3 = new ZPackage(); foreach (string foundDungeon in FoundDungeons) { val3.Write(foundDungeon); } val.Write(FoundRuneStones.Count); val.Write(val2); val.Write(FoundDungeons.Count); val.Write(val3); byte[] array = val.GetArray(); try { FileWriter val4 = new FileWriter(SaveFile, (FileHelperType)0, (FileSource)1); val4.m_binary.Write(array.Length); val4.m_binary.Write(array); val4.Finish(); } catch (Exception ex) { Logger.LogWarning((object)("Error saving CoinPurse data: Path: " + SaveFile + ", Error: " + ex.Message)); } } public static void LoadFromDisk() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown if (SaveFile == null) { Logger.LogError((object)"Something went wrong when trying to load from disk"); return; } if (!File.Exists(SaveFile)) { File.Create(SaveFile).Close(); return; } FoundRuneStones.Clear(); FoundDungeons.Clear(); FileReader val; try { val = new FileReader(SaveFile, (FileSource)1, (FileHelperType)0); } catch (Exception ex) { Logger.LogWarning((object)("Error loading RuneTablet data: Path: " + SaveFile + ", Error: " + ex.Message)); return; } try { BinaryReader binary = val.m_binary; byte[] array = binary.ReadBytes(binary.ReadInt32()); ZPackage val2 = new ZPackage(array); int num = val2.ReadInt(); ZPackage val3 = val2.ReadPackage(); int num2 = val2.ReadInt(); ZPackage val4 = val2.ReadPackage(); for (int i = 0; i < num; i++) { FoundRuneStones.Add(val3.ReadString()); } for (int j = 0; j < num2; j++) { FoundDungeons.Add(val4.ReadString()); } } catch (Exception ex2) { Logger.LogWarning((object)("Error loading RuneTablet data: Path: " + SaveFile + ", Error: " + ex2.Message)); } finally { if (val != null) { val.Dispose(); } } } } public class RuneCrystal : CustomItem { internal static Sprite IconSprite; public RuneCrystal() : base("RuneCrystal", true, new ItemConfig { Name = "$item_runecrystal", Description = "$item_runecrystal_desc", StackSize = 10, Weight = 1f, Icon = IconSprite }) { }//IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0024: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown } [HarmonyPatch(typeof(RuneStone), "Interact")] public class RuneStoneInteractPatch { public static void Postfix(Humanoid character, bool hold, bool alt, RuneStone __instance) { Plugin.Logger.LogInfo((object)"RuneStone.Interact: Called"); string hashedName = Helper.GetHashedName(__instance); Plugin.Logger.LogInfo((object)("RuneStone.Interact: Found runestone " + hashedName)); if (!Plugin.FoundRuneStones.Contains(hashedName)) { GameObject prefab = PrefabManager.Instance.GetPrefab("RuneCrystal"); if (character.m_inventory.CanAddItem(prefab, -1)) { ((Humanoid)Player.m_localPlayer).m_inventory.AddItem(prefab, 1); ((Character)Player.m_localPlayer).Message((MessageType)1, "A mysterious crystal falls into your hand.", 0, (Sprite)null); Plugin.FoundRuneStones.Add(hashedName); } } } } public class RuneTablet : CustomItem { internal static Sprite IconSprite; private static Dictionary<Biome, string[]> BiomeDungeons = new Dictionary<Biome, string[]> { { (Biome)32, Array.Empty<string>() }, { (Biome)8, new string[4] { "Hildir_crypt", "Crypt2", "Crypt3", "Crypt4" } }, { (Biome)512, new string[2] { "Mistlands_DvergrTownEntrance1", "Mistlands_DvergrTownEntrance2" } }, { (Biome)64, new string[2] { "Hildir_cave", "MountainCave02" } }, { (Biome)4, new string[2] { "Hildir_cave", "MountainCave02" } }, { (Biome)16, new string[4] { "GoblinCamp2", "StoneTower1", "StoneTower3", "Hildir_plainsfortress" } }, { (Biome)2, new string[1] { "SunkenCrypt4" } } }; public RuneTablet() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown ItemConfig val = new ItemConfig(); val.Name = "$item_runetablet"; val.Description = "$item_runetablet_desc"; val.CraftingStation = CraftingStations.Workbench; val.Icon = IconSprite; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2] { new RequirementConfig { Item = "Stone", Amount = 10 }, new RequirementConfig { Item = "RuneCrystal", Amount = 4 } }; val.Weight = 10f; ((CustomItem)this)..ctor("RuneTablet", true, val); } public static bool Consume(Player player) { //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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: 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) //IL_00ca: Invalid comparison between Unknown and I4 //IL_00d7: 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) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { Plugin.Logger.LogWarning((object)"Player.ConsumeItem: Called with null player"); return false; } Biome currentBiome = player.GetCurrentBiome(); Plugin.Logger.LogInfo((object)("Player.ConsumeItem: Called in biome " + ((object)(Biome)(ref currentBiome)).ToString())); if (((Enum)currentBiome).HasFlag((Enum)(object)(Biome)256) || ((Enum)currentBiome).HasFlag((Enum)(object)(Biome)1)) { ((Character)player).Message((MessageType)2, "Cannot use that in this biome.", 0, (Sprite)null); return false; } foreach (object value in Enum.GetValues(typeof(Biome))) { Biome val = (Biome)value; if ((int)val == 0 || (int)val == 895 || !((Enum)currentBiome).HasFlag((Enum)(object)val) || !player.IsBiomeKnown(val)) { continue; } return DiscoverNearestDungeon(player, val); } return false; } private static Tuple<string, Vector3> FindClosestLocationFromTypes(string[] types, Vector3 point) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) string text = null; Vector3 item = Vector3.zero; float num = float.PositiveInfinity; List<LocationInstance> list = new List<LocationInstance>(); foreach (string text2 in types) { List<LocationInstance> collection = new List<LocationInstance>(); if (ZoneSystem.instance.FindLocations(text2, ref collection)) { list.AddRange(collection); } } foreach (LocationInstance item2 in list) { string name = item2.m_location.m_prefab.Name; if (Minimap.instance.HavePinInRange(item2.m_position, 14f)) { Plugin.SaveLocation(item2); continue; } string hashedName = Helper.GetHashedName(item2); if (!Plugin.FoundDungeons.Contains(hashedName)) { float num2 = Vector3.Distance(point, item2.m_position); if (num2 < num) { text = name; item = item2.m_position; num = num2; } } } if (string.IsNullOrEmpty(text)) { return null; } return new Tuple<string, Vector3>(text, item); } public static bool DiscoverNearestDungeon(Player player, Biome biome) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_00a2: Unknown result type (might be due to invalid IL or missing references) if (!BiomeDungeons.TryGetValue(biome, out var value)) { Plugin.Logger.LogWarning((object)$"DiscoverNearestDungeon: Invalid biome {biome}"); return false; } Vector3 position = ((Component)player).transform.position; Tuple<string, Vector3> tuple = FindClosestLocationFromTypes(value, position); if (tuple == null) { ((Character)Player.m_localPlayer).Message((MessageType)2, "<color=red>No locations found</color>", 0, (Sprite)null); Plugin.Logger.LogWarning((object)"DiscoverNearestDungeon: No locations found"); return false; } Vector3 item = tuple.Item2; string text = Localization.instance.Localize(Helper.GetPinName(tuple.Item1)); return Minimap.instance.DiscoverLocation(item, (PinType)14, text, true); } } [HarmonyPatch(typeof(Teleport), "Interact")] public class Teleport_Interact_Patch { private static void Postfix(Humanoid character, Teleport __instance, ref bool __result) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (!__result || !((Character)character).InInterior()) { return; } Teleport targetPoint = __instance.m_targetPoint; Location componentInParent = ((Component)targetPoint).GetComponentInParent<Location>(); if (!((Object)(object)componentInParent == (Object)null)) { LocationInstance? locationInstance = Helper.GetLocationInstance(componentInParent); if (locationInstance.HasValue) { Plugin.SaveLocation(locationInstance.Value); } else { Plugin.Logger.LogError((object)("Could not find location instance for " + ((Object)componentInParent).name)); } } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "RuneTablet"; public const string PLUGIN_NAME = "Make a rune tablet to locate dungeons"; public const string PLUGIN_VERSION = "1.0.0"; } }