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 CraftedBossDrops v1.0.9
plugins\CraftedBossDrops.dll
Decompiled a year agousing 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.Serialization; using System.Runtime.Versioning; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Common; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("CraftedBossDrops")] [assembly: AssemblyDescription("https://thunderstore.io/c/valheim/p/probablykory/CraftedBossDrops/")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("probablykory")] [assembly: AssemblyCopyright("Copyright probablykory © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("1.0.9")] [assembly: AssemblyProduct("CraftedBossDrops")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.9.0")] [module: <2bbef6a2-ec2f-455d-af37-047412e59296>RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<d8c74559-f18f-47c0-ad96-ff69778ec96d>Embedded] internal sealed class <d8c74559-f18f-47c0-ad96-ff69778ec96d>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [<d8c74559-f18f-47c0-ad96-ff69778ec96d>Embedded] [CompilerGenerated] internal sealed class <2bbef6a2-ec2f-455d-af37-047412e59296>RefSafetyRulesAttribute : Attribute { public readonly int Version; public <2bbef6a2-ec2f-455d-af37-047412e59296>RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CraftedBossDrops { public class Entries { private Action<object, EventArgs> _action; public string Name { get; set; } = string.Empty; public ConfigEntry<string> Table { get; set; } public ConfigEntry<int> MinTableLevel { get; set; } public ConfigEntry<int> Amount { get; set; } public ConfigEntry<string> Requirements { get; set; } public static Entries GetFromProps(IPlugin instance, string name, string table, int minTableLevel, int amount, string requirements) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Expected O, but got Unknown //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown Entries entries = new Entries(); entries.Name = name; entries.Table = instance.Config(entries.Name, "Table", table, new ConfigDescription("Crafting station needed to craft " + entries.Name + ".", (AcceptableValueBase)(object)CraftingStations.GetAcceptableValueList(), new object[1] { ConfigHelper.GetAdminOnlyFlag() })); entries.MinTableLevel = instance.Config(entries.Name, "Table Level", minTableLevel, new ConfigDescription("Level of crafting station required to craft " + entries.Name + ".", (AcceptableValueBase)null, new object[1] { ConfigHelper.GetAdminOnlyFlag() })); entries.Amount = instance.Config(entries.Name, "Amount", amount, new ConfigDescription("The amount of " + entries.Name + " created.", (AcceptableValueBase)null, new object[1] { ConfigHelper.GetAdminOnlyFlag() })); entries.Requirements = instance.Config(entries.Name, "Requirements", requirements, new ConfigDescription("The required items to craft " + entries.Name + ".", (AcceptableValueBase)(object)new AcceptableValueConfigNote("You must use valid spawn item codes."), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, CustomDrawer = SharedDrawers.DrawReqConfigTable() } })); return entries; } private void OnSettingChanged(object sender, EventArgs e) { if (_action != null) { _action(sender, e); } } public void AddSettingsChangedHandler(Action<object, EventArgs> action) { _action = action; Table.SettingChanged += OnSettingChanged; MinTableLevel.SettingChanged += OnSettingChanged; Amount.SettingChanged += OnSettingChanged; Requirements.SettingChanged += OnSettingChanged; } public void RemoveSettingsChangedHandler() { Table.SettingChanged -= OnSettingChanged; MinTableLevel.SettingChanged -= OnSettingChanged; Amount.SettingChanged -= OnSettingChanged; Requirements.SettingChanged -= OnSettingChanged; _action = null; } } [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("probablykory.CraftedBossDrops", "CraftedBossDrops", "1.0.9")] internal class CraftedBossDrops : BaseUnityPlugin, IPlugin { public const string PluginAuthor = "probablykory"; public const string PluginName = "CraftedBossDrops"; public const string PluginVersion = "1.0.9"; public const string PluginGUID = "probablykory.CraftedBossDrops"; private bool settingsUpdated; private Harmony harmony; internal static CraftedBossDrops Instance; private static ConfigEntry<bool> isDebugEnabled; private CustomRecipe hardAntlerRecipe; private CustomRecipe cryptKeyRecipe; private CustomRecipe wishboneRecipe; private CustomRecipe dragonTearRecipe; private CustomRecipe yagluthDropRecipe; private CustomRecipe queenDropRecipe; private CustomRecipe faderDropRecipe; public ManualLogSource Logger { get; private set; } = Logger.CreateLogSource("CraftedBossDrops"); public bool Debug { get { if (isDebugEnabled == null) { return true; } return isDebugEnabled.Value; } } public Entries HardAntlerEntry { get; protected set; } public Entries CryptKeyEntry { get; protected set; } public Entries WishboneEntry { get; protected set; } public Entries DragonTearEntry { get; protected set; } public Entries YagluthDropEntry { get; protected set; } public Entries QueenDropEntry { get; protected set; } public Entries FaderDropEntry { get; protected set; } private void Awake() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown harmony = new Harmony("probablykory.CraftedBossDrops"); harmony.PatchAll(); isDebugEnabled = this.Config("1 - General", "Debugging Enabled", value: false, "If on, mod will output alot more information in the debug log level."); Instance = this; InitializeFeatures(); PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable; SynchronizationManager.OnConfigurationSynchronized += OnConfigurationSynchronized; ((BaseUnityPlugin)this).Config.ConfigReloaded += OnConfigReloaded; new ConfigWatcher(this); } private void InitializeFeatures() { HardAntlerEntry = Entries.GetFromProps(Instance, "HardAntler", "Workbench", 3, 1, "TrophyDeer:10,Resin:20"); CryptKeyEntry = Entries.GetFromProps(Instance, "CryptKey", "Forge", 3, 1, "AncientSeed:6,Bronze:20"); WishboneEntry = Entries.GetFromProps(Instance, "Wishbone", "Forge", 7, 1, "WitheredBone:15,Iron:10,TrophyDraugr:3"); DragonTearEntry = Entries.GetFromProps(Instance, "DragonTear", "Workbench", 5, 2, "DragonEgg:4,Crystal:16"); YagluthDropEntry = Entries.GetFromProps(Instance, "YagluthDrop", "ArtisanTable", 1, 2, "GoblinTotem:10,TrophyGoblin:3,TrophyGoblinShaman:1,TrophyGoblinBrute:1"); QueenDropEntry = Entries.GetFromProps(Instance, "QueenDrop", "BlackForge", 2, 1, "DvergrKeyFragment:10,Mandible:5,TrophySeeker:3,TrophySeekerBrute:1"); FaderDropEntry = Entries.GetFromProps(Instance, "FaderDrop", "ArtisanTable", 2, 1, "BellFragment:10,MorgenHeart:5,TrophyCharredMelee:4,TrophyCharredMage:1"); HardAntlerEntry.AddSettingsChangedHandler(OnSettingsChanged); CryptKeyEntry.AddSettingsChangedHandler(OnSettingsChanged); WishboneEntry.AddSettingsChangedHandler(OnSettingsChanged); DragonTearEntry.AddSettingsChangedHandler(OnSettingsChanged); YagluthDropEntry.AddSettingsChangedHandler(OnSettingsChanged); QueenDropEntry.AddSettingsChangedHandler(OnSettingsChanged); FaderDropEntry.AddSettingsChangedHandler(OnSettingsChanged); } private void UpdateFeatures() { settingsUpdated = false; hardAntlerRecipe.Update(getRecipeFromEntry(HardAntlerEntry)); cryptKeyRecipe.Update(getRecipeFromEntry(CryptKeyEntry)); wishboneRecipe.Update(getRecipeFromEntry(WishboneEntry)); dragonTearRecipe.Update(getRecipeFromEntry(DragonTearEntry)); yagluthDropRecipe.Update(getRecipeFromEntry(YagluthDropEntry)); queenDropRecipe.Update(getRecipeFromEntry(QueenDropEntry)); faderDropRecipe.Update(getRecipeFromEntry(FaderDropEntry)); } private void OnVanillaPrefabsAvailable() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown this.LogDebugOnly("Vanilla Prefabs Available received."); hardAntlerRecipe = new CustomRecipe(getRecipeFromEntry(HardAntlerEntry)); cryptKeyRecipe = new CustomRecipe(getRecipeFromEntry(CryptKeyEntry)); wishboneRecipe = new CustomRecipe(getRecipeFromEntry(WishboneEntry)); dragonTearRecipe = new CustomRecipe(getRecipeFromEntry(DragonTearEntry)); yagluthDropRecipe = new CustomRecipe(getRecipeFromEntry(YagluthDropEntry)); queenDropRecipe = new CustomRecipe(getRecipeFromEntry(QueenDropEntry)); faderDropRecipe = new CustomRecipe(getRecipeFromEntry(FaderDropEntry)); ItemManager.Instance.AddRecipe(hardAntlerRecipe); ItemManager.Instance.AddRecipe(cryptKeyRecipe); ItemManager.Instance.AddRecipe(wishboneRecipe); ItemManager.Instance.AddRecipe(dragonTearRecipe); ItemManager.Instance.AddRecipe(yagluthDropRecipe); ItemManager.Instance.AddRecipe(queenDropRecipe); ItemManager.Instance.AddRecipe(faderDropRecipe); PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; } private void OnSettingsChanged(object sender, EventArgs e) { settingsUpdated = true; } private void OnConfigReloaded(object sender, EventArgs e) { if (settingsUpdated) { UpdateFeatures(); } } private void OnConfigurationSynchronized(object sender, ConfigurationSynchronizationEventArgs e) { UpdateFeatures(); } private RecipeConfig getRecipeFromEntry(Entries entry) { //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) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown return new RecipeConfig { Item = entry.Name, CraftingStation = CraftingStations.GetInternalName(entry.Table.Value), RepairStation = CraftingStations.GetInternalName(entry.Table.Value), MinStationLevel = entry.MinTableLevel.Value, Amount = entry.Amount.Value, Requirements = RequirementsEntry.Deserialize(entry.Requirements.Value) }; } ConfigFile IPlugin.get_Config() { return ((BaseUnityPlugin)this).Config; } } public static class Extensions { private static HashSet<CustomRecipe> hashsetRecipes; public static Recipe GetRecipe(this List<Recipe> list, Recipe recipe) { int num = ObjectDB.instance.m_recipes.IndexOf(recipe); if (num > -1) { return list[num]; } string name = ((object)recipe).ToString(); return ((IEnumerable<Recipe>)ObjectDB.instance.m_recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => name.Equals(((object)r).ToString()))); } public static bool Update(this CustomRecipe recipe, RecipeConfig newRecipe) { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Expected O, but got Unknown if (hashsetRecipes == null) { FieldInfo fieldInfo = ((object)ItemManager.Instance).GetType().GetMembers(BindingFlags.Instance | BindingFlags.NonPublic).FirstOrDefault((MemberInfo m) => m.Name == "Recipes") as FieldInfo; if (fieldInfo != null && fieldInfo.GetValue(ItemManager.Instance) is HashSet<CustomRecipe> hashSet) { hashsetRecipes = hashSet; } } Recipe recipe2 = ObjectDB.instance.m_recipes.GetRecipe(recipe.Recipe); if ((Object)(object)recipe2 == (Object)null) { if (hashsetRecipes != null && hashsetRecipes.Contains(recipe)) { IPlugin plugin = Get.Plugin; object obj; if (recipe == null) { obj = null; } else { Recipe recipe3 = recipe.Recipe; obj = ((recipe3 != null) ? ((Object)recipe3).name : null); } plugin.LogDebugOnly("Removing and re-adding recipe " + (string?)obj + " in ItemManager."); ItemManager.Instance.RemoveRecipe(recipe); ItemManager.Instance.AddRecipe(new CustomRecipe(newRecipe)); return true; } object obj2; if (recipe == null) { obj2 = null; } else { Recipe recipe4 = recipe.Recipe; obj2 = ((recipe4 != null) ? ((Object)recipe4).name : null); } Logger.LogError((object)("Error updating recipe " + (string?)obj2 + ", did not find existing recipe in ObjectDB or ItemManager")); return false; } IPlugin plugin2 = Get.Plugin; object obj3; if (recipe == null) { obj3 = null; } else { Recipe recipe5 = recipe.Recipe; obj3 = ((recipe5 != null) ? ((Object)recipe5).name : null); } plugin2.LogDebugOnly("Updating recipe " + (string?)obj3 + " in place."); recipe2.m_amount = newRecipe.Amount; recipe2.m_minStationLevel = newRecipe.MinStationLevel; GameObject prefab = PrefabManager.Instance.GetPrefab(newRecipe.CraftingStation); recipe2.m_craftingStation = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null); recipe2.m_resources = newRecipe.GetRequirements(); Requirement[] resources = recipe2.m_resources; foreach (Requirement val in resources) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(((Object)val.m_resItem).name.Replace("JVLmock_", "")); if ((Object)(object)itemPrefab != (Object)null) { val.m_resItem = itemPrefab.GetComponent<ItemDrop>(); } } if (hashsetRecipes != null) { hashsetRecipes.Remove(recipe); hashsetRecipes.Add(new CustomRecipe(recipe2, false, false)); } return true; } } [HarmonyPatch] public static class TraderPatch { private static Dictionary<string, string> GlobalKeyTokenMap = new Dictionary<string, string> { { "defeated_eikthyr", "$item_hardantler" }, { "defeated_gdking", "$item_cryptkey" }, { "defeated_bonemass", "$item_wishbone" }, { "defeated_dragon", "$item_dragontear" }, { "defeated_goblinking", "$item_yagluththing" }, { "defeated_queen", "$item_queen_drop" }, { "defeated_fader", "$item_fader_drop" } }; [HarmonyPatch(typeof(Trader), "GetAvailableItems")] [HarmonyPostfix] public static List<TradeItem> TraderGetAvailableItems(List<TradeItem> values, Trader __instance) { if ((Object)(object)__instance == (Object)null) { return values; } if (((__instance == null) ? null : ((Object)__instance).name?.Contains("Haldor")).Value || ((__instance == null) ? null : ((Object)__instance).name?.Contains("BogWitch")).Value) { List<TradeItem> list = new List<TradeItem>(); { foreach (TradeItem item in __instance.m_items) { if (string.IsNullOrEmpty(item.m_requiredGlobalKey) || ZoneSystem.instance.GetGlobalKey(item.m_requiredGlobalKey) || (GlobalKeyTokenMap.ContainsKey(item.m_requiredGlobalKey) && Player.m_localPlayer.IsKnownMaterial(GlobalKeyTokenMap[item.m_requiredGlobalKey]))) { list.Add(item); } } return list; } } return values; } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "AddKnownItem")] public static void PlayerAddKnownItem(ItemData item, Player __instance) { object obj; if (item == null) { obj = null; } else { GameObject dropPrefab = item.m_dropPrefab; obj = ((dropPrefab != null) ? ((Object)dropPrefab).name : null); } string text = (string)obj; if (!string.IsNullOrEmpty(text) && string.Equals(text, "HardAntler") && !__instance.m_knownMaterial.Contains(item.m_shared.m_name)) { __instance.SetSeenTutorial("blackforest"); } } } } namespace Microsoft.CodeAnalysis { [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [Microsoft.CodeAnalysis.Embedded] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Common { internal class AcceptableValueConfigNote : AcceptableValueBase { public virtual string Note { get; } public AcceptableValueConfigNote(string note) : base(typeof(string)) { if (string.IsNullOrEmpty(note)) { throw new ArgumentException("A string with atleast 1 character is needed", "Note"); } Note = note; } public override object Clamp(object value) { return value; } public override bool IsValid(object value) { return !string.IsNullOrEmpty(value as string); } public override string ToDescriptionString() { return "# Note: " + Note; } } internal static class ConfigHelper { public static ConfigurationManagerAttributes GetAdminOnlyFlag() { //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) //IL_000d: Expected O, but got Unknown return new ConfigurationManagerAttributes { IsAdminOnly = true }; } public static ConfigurationManagerAttributes GetTags(Action<ConfigEntryBase> action) { //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) //IL_000d: Expected O, but got Unknown return new ConfigurationManagerAttributes { CustomDrawer = action }; } public static ConfigurationManagerAttributes GetTags() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new ConfigurationManagerAttributes(); } public static ConfigEntry<T> Config<T>(this IPlugin instance, string group, string name, T value, ConfigDescription description) { return instance.Config.Bind<T>(group, name, value, description); } public static ConfigEntry<T> Config<T>(this IPlugin instance, string group, string name, T value, string description) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown return instance.Config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { GetAdminOnlyFlag() })); } } internal static class RequirementsEntry { public static RequirementConfig[] Deserialize(string reqs) { return ((IEnumerable<string>)reqs.Split(new char[1] { ',' })).Select((Func<string, RequirementConfig>)delegate(string r) { //IL_0012: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown string[] array = r.Split(new char[1] { ':' }); int result; int result2; return new RequirementConfig { Item = array[0], Amount = ((array.Length <= 1 || !int.TryParse(array[1], out result)) ? 1 : result), AmountPerLevel = ((array.Length > 2 && int.TryParse(array[2], out result2)) ? result2 : 0), Recover = true }; }).ToArray(); } public static string Serialize(RequirementConfig[] reqs) { return string.Join(",", reqs.Select((RequirementConfig r) => (r.AmountPerLevel <= 0) ? $"{r.Item}:{r.Amount}" : $"{r.Item}:{r.Amount}:{r.AmountPerLevel}")); } } internal static class SharedDrawers { private static BaseUnityPlugin configManager; private static BaseUnityPlugin GetConfigManager() { if ((Object)(object)configManager == (Object)null && Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value) && Object.op_Implicit((Object)(object)value.Instance)) { configManager = value.Instance; } return configManager; } public static int GetRightColumnWidth() { int result = 130; BaseUnityPlugin val = GetConfigManager(); if ((Object)(object)val != (Object)null) { PropertyInfo propertyInfo = ((object)val)?.GetType().GetProperty("RightColumnWidth", BindingFlags.Instance | BindingFlags.NonPublic); if (propertyInfo != null) { result = (int)propertyInfo.GetValue(val); } } return result; } public static void ReloadConfigDisplay() { BaseUnityPlugin val = GetConfigManager(); if ((Object)(object)val != (Object)null) { object obj = ((object)val).GetType()?.GetProperty("DisplayingWindow")?.GetValue(val); if (obj is bool && (bool)obj) { ((object)val).GetType().GetMethod("BuildSettingList").Invoke(val, Array.Empty<object>()); } } } public static Action<ConfigEntryBase> DrawReqConfigTable(bool hasUpgrades = false) { return delegate(ConfigEntryBase cfg) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Expected O, but got Unknown //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Expected O, but got Unknown //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Expected O, but got Unknown List<RequirementConfig> list = new List<RequirementConfig>(); bool flag = false; int rightColumnWidth = GetRightColumnWidth(); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); foreach (RequirementConfig item in RequirementsEntry.Deserialize((string)cfg.BoxedValue).ToList()) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); string text = GUILayout.TextField(item.Item, new GUIStyle(GUI.skin.textField) { fixedWidth = rightColumnWidth - 33 - (hasUpgrades ? 37 : 0) - 21 - 21 - 12 }, Array.Empty<GUILayoutOption>()); string text2 = (string.IsNullOrEmpty(text) ? item.Item : text); flag = flag || text2 != item.Item; int num = item.Amount; if (int.TryParse(GUILayout.TextField(num.ToString(), new GUIStyle(GUI.skin.textField) { fixedWidth = 33f }, Array.Empty<GUILayoutOption>()), out var result) && result != num) { num = result; flag = true; } int num2 = item.AmountPerLevel; if (hasUpgrades && int.TryParse(GUILayout.TextField(num2.ToString(), new GUIStyle(GUI.skin.textField) { fixedWidth = 33f }, Array.Empty<GUILayoutOption>()), out var result2) && result2 != num2) { num2 = result2; flag = true; } if (GUILayout.Button("x", new GUIStyle(GUI.skin.button) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>())) { flag = true; } else { list.Add(new RequirementConfig { Item = text2, Amount = num, AmountPerLevel = num2 }); } if (GUILayout.Button("+", new GUIStyle(GUI.skin.button) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>())) { flag = true; list.Add(new RequirementConfig { Item = "<Prefab Name>", Amount = 1 }); } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); if (flag) { cfg.BoxedValue = RequirementsEntry.Serialize(list.ToArray()); } }; } } internal class ConfigWatcher { private BaseUnityPlugin configurationManager; private IPlugin plugin; public ConfigWatcher(IPlugin plugin) { if (plugin == null) { throw new ArgumentNullException("plugin"); } this.plugin = plugin; CheckForConfigManager(); } private void InitializeWatcher() { string fileName = Path.GetFileName(plugin.Config.ConfigFilePath); new Watcher(Path.GetDirectoryName(plugin.Config.ConfigFilePath), fileName).FileChanged += OnFileChanged; Get.Plugin.LogDebugOnly("File system watcher initialized."); } private void CheckForConfigManager() { PluginInfo value; if (GUIManager.IsHeadless()) { InitializeWatcher(); } else if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out value) && Object.op_Implicit((Object)(object)value.Instance)) { configurationManager = value.Instance; Get.Plugin.LogDebugOnly("Configuration manager found, hooking DisplayingWindowChanged"); EventInfo @event = ((object)configurationManager).GetType().GetEvent("DisplayingWindowChanged"); if (@event != null) { Action<object, object> action = OnConfigManagerDisplayingWindowChanged; Delegate handler = Delegate.CreateDelegate(@event.EventHandlerType, action.Target, action.Method); @event.AddEventHandler(configurationManager, handler); } } else { InitializeWatcher(); } } private void OnFileChanged(object sender, FileSystemEventArgs e) { string configFilePath = plugin.Config.ConfigFilePath; if (!File.Exists(configFilePath)) { return; } try { plugin.Config.SaveOnConfigSet = false; plugin.Config.Reload(); plugin.Config.SaveOnConfigSet = true; } catch { Get.Plugin.LogError("There was an issue with your " + Path.GetFileName(configFilePath) + " file."); Get.Plugin.LogError("Please check the format and spelling."); } } private void OnConfigManagerDisplayingWindowChanged(object sender, object e) { if (!(bool)((object)configurationManager).GetType().GetProperty("DisplayingWindow").GetValue(configurationManager, null)) { plugin.Config.SaveOnConfigSet = false; plugin.Config.Reload(); plugin.Config.SaveOnConfigSet = true; } } } internal class CustomSyncedValueBase { private class Patches { [HarmonyPatch(typeof(ZNet), "Shutdown")] [HarmonyPostfix] private static void ZNet_Shutdown() { if (ZNetExtension.IsClientInstance(ZNet.instance)) { foreach (CustomSyncedValueBase syncedValue in SyncedValues) { syncedValue.OnResetFromServer(); } return; } foreach (CustomSyncedValueBase syncedValue2 in SyncedValues) { syncedValue2.OnServerShutdown(); } } } public readonly string Name; public readonly Type Type; private object? boxedValue; public object? LocalBaseValue; private CustomRPC customRPC; private static readonly HashSet<CustomSyncedValueBase> SyncedValues = new HashSet<CustomSyncedValueBase>(); private static Harmony harmony = null; public bool IsSourceOfTruth { get; private set; } = true; public object? BoxedValue { get { return boxedValue; } set { boxedValue = value; this.ValueChanged?.Invoke(this, value); } } public event Action<object, object>? ValueChanged; protected CustomSyncedValueBase(string name, Type type, object? initialValue) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_00af: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown Name = name; Type = type; SyncedValues.Add(this); if (harmony == null) { harmony = (Harmony)AccessTools.Field(typeof(Main), "Harmony").GetValue(null); harmony.PatchAll(typeof(Patches)); Get.Plugin.LogDebugOnly("Jotunn's harmony instance obtained, CustomSyncedValueBase+Patches applied."); } boxedValue = initialValue; customRPC = NetworkManager.Instance.AddRPC(Name + "_CustomSyncedValue_RPC", new CoroutineHandler(OnServerReceive), new CoroutineHandler(OnClientReceive)); SynchronizationManager.Instance.AddInitialSynchronization(customRPC, (Func<ZPackage>)GetPackage); } public void SendPackage() { if ((Object)(object)ZNet.instance == (Object)null) { Get.Plugin.LogDebugOnly("SendPackage called but am not connected."); } if (!SynchronizationManager.Instance.PlayerIsAdmin) { Get.Plugin.LogDebugOnly("SendPackage called but Player is not admin."); } if ((Object)(object)ZNet.instance != (Object)null && SynchronizationManager.Instance.PlayerIsAdmin) { ZPackage package = GetPackage(); if (ZNetExtension.IsClientInstance(ZNet.instance)) { customRPC.SendPackage(ZRoutedRpc.instance.GetServerPeerID(), package); } else { customRPC.SendPackage(ZNet.instance.m_peers, package); } } } private ZPackage GetPackage() { return new PackageEntry { key = Name, type = Type, value = boxedValue }.ToPackage(); } private IEnumerator OnServerReceive(long sender, ZPackage package) { Get.Plugin.LogDebugOnly($"Server received RPC: {sender} {package}"); yield return null; ParsedEntries parsedEntries = package.ReadEntries(); if (parsedEntries.Count > 0 && parsedEntries.TryGetValue(Name, out var value)) { BoxedValue = (LocalBaseValue = value.value); Get.Plugin.LogDebugOnly($"Set local and boxed: {value.value}"); customRPC.SendPackage(ZNet.instance.m_peers.Where((ZNetPeer x) => x.m_uid != sender).ToList(), package); } else { OnReceiveError(parsedEntries); } } private IEnumerator OnClientReceive(long sender, ZPackage package) { Get.Plugin.LogDebugOnly($"Client received RPC: {sender} {package}"); yield return null; ParsedEntries parsedEntries = package.ReadEntries(); if (parsedEntries.Count > 0 && parsedEntries.TryGetValue(Name, out var value)) { IsSourceOfTruth = false; if (LocalBaseValue == null) { LocalBaseValue = BoxedValue; } BoxedValue = value.value; Get.Plugin.LogDebugOnly($"Set source of truth: {IsSourceOfTruth}, {Environment.NewLine}local: {LocalBaseValue} {Environment.NewLine}boxed: {BoxedValue}"); } else { OnReceiveError(parsedEntries); } } private void OnReceiveError(ParsedEntries entries) { Get.Plugin.LogWarning(Name + "_CustomSyncedValue_RPC recieved package without expected key: " + Name); string text = ""; foreach (KeyValuePair<string, PackageEntry> entry in entries) { text += $"{entry.Key} - {entry.Value.type} - {entry.Value.value?.ToString()} {Environment.NewLine}"; } Get.Plugin.LogWarning("Result: " + Environment.NewLine + text); } private void OnResetFromServer() { BoxedValue = LocalBaseValue; IsSourceOfTruth = true; LocalBaseValue = null; } private void OnServerShutdown() { } } internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase { public T Value { get { return (T)base.BoxedValue; } set { base.BoxedValue = value; if (base.BoxedValue != null) { SendPackage(); } } } public CustomSyncedValue(string name, T value = default(T)) : base(name, typeof(T), value) { } public void AssignLocalValue(T value) { if (base.IsSourceOfTruth && SynchronizationManager.Instance.PlayerIsAdmin) { Value = value; } else { LocalBaseValue = value; } } } internal class ParsedEntries : Dictionary<string, PackageEntry> { } internal class PackageEntry { public string key; public Type type; public object? value; } internal class InvalidDeserializationTypeException : Exception { public string expected; public string received; public string field = ""; } internal static class PackageUtils { public static string GetPackageTypeString(Type type) { return type.AssemblyQualifiedName; } public static void AddValue(this ZPackage package, object? value) { Type type = value?.GetType(); if (value is Enum) { value = ((IConvertible)value).ToType(Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture); } else { if (value is ICollection collection) { package.Write(collection.Count); { foreach (object item in collection) { package.AddValue(item); } return; } } if ((object)type != null && type.IsValueType && !type.IsPrimitive) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); package.Write(fields.Length); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { package.Write(GetPackageTypeString(fieldInfo.FieldType)); package.AddValue(fieldInfo.GetValue(value)); } return; } } ZRpc.Serialize(new object[1] { value }, ref package); } public static void AddEntry(this ZPackage package, PackageEntry entry) { package.Write(entry.key); package.Write((entry.value == null) ? "" : GetPackageTypeString(entry.type)); package.AddValue(entry.value); } public static ZPackage ToPackage(this PackageEntry packageEntry) { return new List<PackageEntry> { packageEntry }.ToPackage(); } public static ZPackage ToPackage(this IEnumerable<PackageEntry> packageEntries) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(packageEntries?.Count() ?? 0); foreach (PackageEntry item in packageEntries ?? Array.Empty<PackageEntry>()) { val.AddEntry(item); } return val; } public static object ReadValueWithType(this ZPackage package, Type type) { if ((object)type != null && type.IsValueType && !type.IsPrimitive && !type.IsEnum) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); int num = package.ReadInt(); if (num != fields.Length) { throw new InvalidDeserializationTypeException { received = $"(field count: {num})", expected = $"(field count: {fields.Length})" }; } object uninitializedObject = FormatterServices.GetUninitializedObject(type); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { string text = package.ReadString(); if (text != GetPackageTypeString(fieldInfo.FieldType)) { throw new InvalidDeserializationTypeException { received = text, expected = GetPackageTypeString(fieldInfo.FieldType), field = fieldInfo.Name }; } fieldInfo.SetValue(uninitializedObject, package.ReadValueWithType(fieldInfo.FieldType)); } return uninitializedObject; } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >)) { int num2 = package.ReadInt(); IDictionary dictionary = (IDictionary)Activator.CreateInstance(type); Type type2 = typeof(KeyValuePair<, >).MakeGenericType(type.GenericTypeArguments); FieldInfo field = type2.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = type2.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic); for (int j = 0; j < num2; j++) { object obj = package.ReadValueWithType(type2); dictionary.Add(field.GetValue(obj), field2.GetValue(obj)); } return dictionary; } if (type != typeof(List<string>) && type.IsGenericType) { Type type3 = typeof(ICollection<>).MakeGenericType(type.GenericTypeArguments[0]); if ((object)type3 != null && type3.IsAssignableFrom(type)) { int num3 = package.ReadInt(); object obj2 = Activator.CreateInstance(type); MethodInfo method = type3.GetMethod("Add"); for (int k = 0; k < num3; k++) { method.Invoke(obj2, new object[1] { package.ReadValueWithType(type.GenericTypeArguments[0]) }); } return obj2; } } ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo)); AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl").SetValue(parameterInfo, type); List<object> source = new List<object>(); ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, package, ref source); return source.FirstOrDefault(); } public static ParsedEntries ReadEntries(this ZPackage package) { ParsedEntries parsedEntries = new ParsedEntries(); int num = package.ReadInt(); for (int i = 0; i < num; i++) { string key = package.ReadString(); string text = package.ReadString(); Type type = Type.GetType(text); if (text == "" || type != null) { object obj; try { obj = ((text == "") ? null : package.ReadValueWithType(type)); } catch (InvalidDeserializationTypeException ex) { Get.Plugin.LogWarning("Got unexpected struct internal type " + ex.received + " for field " + ex.field + " struct " + text); continue; } if (obj != null) { parsedEntries[key] = new PackageEntry { key = key, type = type, value = obj }; } continue; } Get.Plugin.LogWarning("Got invalid type " + text + ", abort reading of received configs"); return new ParsedEntries(); } return parsedEntries; } public static void Test() { } } internal interface IPlugin { ConfigFile Config { get; } bool Debug { get; } ManualLogSource Logger { get; } } internal static class LoggingExtensions { private static readonly Dictionary<string, ManualLogSource> logSources = new Dictionary<string, ManualLogSource>(); internal static ManualLogSource GetLogger(this IPlugin mod) { if (mod.Debug) { Type declaringType = new StackFrame(2).GetMethod().DeclaringType; if (!logSources.TryGetValue(declaringType.FullName, out var value)) { value = Logger.CreateLogSource(declaringType.FullName); logSources.Add(declaringType.FullName, value); } return value; } return mod.Logger; } public static void LogDebugOnly(this IPlugin mod, object data) { if (mod.Debug) { mod.GetLogger().LogDebug(data); } } public static void LogDebug(this IPlugin mod, object data) { if (mod.Debug) { mod.GetLogger().LogDebug(data); } else { mod.Logger.LogDebug(data); } } public static void LogInfo(this IPlugin mod, object data) { if (mod.Debug) { mod.GetLogger().LogInfo(data); } else { mod.Logger.LogInfo(data); } } public static void LogMessage(this IPlugin mod, object data) { if (mod.Debug) { mod.GetLogger().LogMessage(data); } else { mod.Logger.LogMessage(data); } } public static void LogWarning(this IPlugin mod, object data) { if (mod.Debug) { mod.GetLogger().LogWarning(data); } else { mod.Logger.LogWarning(data); } } public static void LogError(this IPlugin mod, object data) { if (mod.Debug) { mod.GetLogger().LogError(data); } else { mod.Logger.LogError(data); } } public static void LogFatal(this IPlugin mod, object data) { if (mod.Debug) { mod.GetLogger().LogFatal(data); } else { mod.Logger.LogFatal(data); } } } internal static class Get { private static IPlugin cachedModRef; public static IPlugin Plugin { get { if (cachedModRef == null) { cachedModRef = AccessTools.Field((from p in new StackFrame(0).GetMethod().DeclaringType.Assembly.GetTypes() where typeof(IPlugin).IsAssignableFrom(p) select p).FirstOrDefault(), "Instance").GetValue(null) as IPlugin; cachedModRef.LogDebugOnly("Caching static mod reference"); } return cachedModRef; } } } internal class Watcher { private FileSystemWatcher fileSystemWatcher; public bool EnableRaisingEvents { get { if (fileSystemWatcher != null) { return fileSystemWatcher.EnableRaisingEvents; } return false; } set { if (fileSystemWatcher != null) { fileSystemWatcher.EnableRaisingEvents = value; } } } public event Action<object, FileSystemEventArgs>? FileChanged; public Watcher(string path, string filter) { if (path == null) { throw new ArgumentNullException("path"); } if (filter == null) { throw new ArgumentNullException("filter"); } Get.Plugin.LogDebugOnly("Watcher created for " + path + ", " + filter); fileSystemWatcher = new FileSystemWatcher(path, filter); fileSystemWatcher.Changed += OnCreatedChangedOrRenamed; fileSystemWatcher.Created += OnCreatedChangedOrRenamed; fileSystemWatcher.Renamed += OnCreatedChangedOrRenamed; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private void OnCreatedChangedOrRenamed(object sender, FileSystemEventArgs args) { Get.Plugin.LogDebugOnly($"OnCreatedChangedOrRenamed triggered {args.Name}, {args.ChangeType}"); this.FileChanged?.Invoke(sender, args); } } }