using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using Common; using Jotunn; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Plugin; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("CustomizedBronze")] [assembly: AssemblyDescription("Allows the user to customize the bronze recipe.")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCompany("Nitrinax")] [assembly: AssemblyProduct("CustomizedBronze")] [assembly: AssemblyCopyright("GNU GPL V3")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: AssemblyFileVersion("0.1.5")] [assembly: NeutralResourcesLanguage("English")] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.5.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Plugin { internal class Data { public const string Namespace = "CustomizedBronze"; public const string ModName = "CustomizedBronze"; public const string Company = "Nitrinax"; public const string Version = "0.1.5"; public const string ModGuid = "Nitrinax.CustomizedBronze"; public const string Description = "Allows the user to customize the bronze recipe."; public const string Configuration = "Release"; public const string Copyright = "GNU GPL V3"; public const string Trademark = ""; public const string Culture = ""; public const string Language = "English"; public const string PluginDefaultLanguage = "English"; public const string ConfigCategoryGeneral = "General"; public const string ConfigEntryEnabled = "Enabled"; public const string ConfigEntryEnabledDescription = "Enable this mod"; public const bool ConfigEntryEnabledDefaultState = true; public const string ConfigEntryNexusID = "NexusID"; public const string ConfigEntryNexusIDDescription = "Nexus mod ID for updates"; public const int ConfigEntryNexusIDID = 1898; public const string ConfigCategoryPlugin = "Plugin"; public const string ConfigEntryShowChangesAtStartup = "ShowChangesAtStartup"; public const bool ConfigEntryShowChangesAtStartupDefaultState = true; public const string ConfigEntryShowChangesAtStartupDescription = "If this option is set, the changes made by this mod are displayed in the console log."; } internal class Dependencies { public const string GameName = "Valheim"; public const string GameVersion = "0.221.12"; public const string BepInExName = "BepInExPack Valheim"; public const string BepInExVersion = "5.4.23.3"; public const bool IsJotunnRequired = true; public const string JotunnName = "Jotunn, the Valheim Library"; public const string JotunnVersion = "2.29.1"; public static string[] RequiredPlugins = Array.Empty(); public static string[] RequiredFiles = Array.Empty(); public static string[,] RecommendedPlugins = new string[1, 2] { { "ConfigurationManager.dll", "This is required to change the mod’s settings within the game. Without this plugin, settings can only be adjusted by editing the configuration file." } }; } } namespace CustomizedBronze { [BepInPlugin("Nitrinax.CustomizedBronze", "CustomizedBronze", "0.1.5")] [BepInProcess("valheim.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class CustomizedBronze : BaseUnityPlugin { public enum BronzeAlloy { [Description("Default")] Default, [Description("WoWlike")] WoWlike, [Description("Realistic")] Realistic, [Description("Custom")] Custom } private const string ConfigCategoryRecipeAlloy = "Recipe Alloy"; private const string ConfigCategoryRecipeCustom = "Recipe Custom"; private static readonly string ConfigEntryAttention = "Please note: Changes to the recipe are applied immediately (no relog required)."; private static readonly string ConfigEntryRecipeAlloyDescription = "Alloy composition:" + Environment.NewLine + "(" + ConfigEntryAttention + ")" + Environment.NewLine + Environment.NewLine + "Default = the standard alloy from Valheim (2 Copper + 1 Tin = 1 Bronze)[If you select this preset, your custom settings will be ignored.]" + Environment.NewLine + Environment.NewLine + "WoWlike = an alloy like in World of Warcraft (1 Copper + 1 Tin = 2 Bronze)[If you select this preset, your custom settings will be ignored.]" + Environment.NewLine + Environment.NewLine + "Realistic = a more realistic alloy (2 Copper + 1 Tin = 3 Bronze)[If you select this preset, your custom settings will be ignored.]" + Environment.NewLine + Environment.NewLine + "Custom = a custom alloy with the mixing ratio you set[If you select this, your custom settings will be used.]"; private static readonly string ConfigEntryRecipeCustomCopperDescription = "Sets amount of needed Copper."; private static readonly string ConfigEntryRecipeCustomTinDescription = "Sets amount of needed Tin."; private static readonly string ConfigEntryRecipeCustomBronzeDescription = "Sets the amount of Bronze produced."; private static readonly int[] DefaultAlloy = new int[3] { 2, 1, 1 }; private static readonly int[] WoWlikeAlloy = new int[3] { 1, 1, 2 }; private static readonly int[] RealisticAlloy = new int[3] { 2, 1, 3 }; public static ConfigEntry configModEnabled; public static ConfigEntry configNexusID; public static ConfigEntry configShowChangesAtStartup; public static ConfigEntry configBronzeAlloy; public static ConfigEntry configRecipeNeededCopper; public static ConfigEntry configRecipeNeededTin; public static ConfigEntry configRecipeProducedBronze; private int usedRequirementCopper; private int usedRequirementTin; private int usedQuantityBronze; private ItemDrop copperPrefab; private ItemDrop tinPrefab; private Dictionary originalRecipes = new Dictionary(); private static bool firstUpdate = true; private static bool showChanges = true; private List bronzeRecipes = new List(); private void Awake() { if (!DependencyOperations.CheckForDependencyErrors("Nitrinax.CustomizedBronze")) { CreateConfigValues(); SubscribeToConfigChanges(); ItemManager.OnItemsRegistered += OnItemsRegistered; if (!configModEnabled.Value) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Nitrinax CustomizedBronze v0.1.5 is loaded but disabled by config."); } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Nitrinax CustomizedBronze v0.1.5 loaded."); } } } private void OnDestroy() { configModEnabled.SettingChanged -= OnConfigChanged; configBronzeAlloy.SettingChanged -= OnConfigChanged; configRecipeNeededCopper.SettingChanged -= OnConfigChanged; configRecipeNeededTin.SettingChanged -= OnConfigChanged; configRecipeProducedBronze.SettingChanged -= OnConfigChanged; ItemManager.OnItemsRegistered -= OnItemsRegistered; SynchronizationManager.OnConfigurationSynchronized -= OnConfigurationSynchronized; } private void OnItemsRegistered() { try { InitializeRecipeCache(); if (configModEnabled.Value) { UpdateBronzeRecipe(); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Error in OnItemsRegistered: " + ex.Message)); } finally { ItemManager.OnItemsRegistered -= OnItemsRegistered; } } private void OnConfigurationSynchronized(object sender, ConfigurationSynchronizationEventArgs args) { ((BaseUnityPlugin)this).Logger.LogMessage((object)(args.InitialSynchronization ? "Initial Config sync event received" : "Config sync event received")); } private void OnConfigChanged(object sender, EventArgs e) { if (!configModEnabled.Value) { RestoreOriginalRecipes(); return; } if (bronzeRecipes.Count == 0) { InitializeRecipeCache(); } UpdateBronzeRecipe(); } private void InitializeRecipeCache() { if (!((Object)(object)ObjectDB.instance != (Object)null) || ObjectDB.instance.m_recipes == null) { return; } bronzeRecipes = ObjectDB.instance.m_recipes.Where(delegate(Recipe r) { ItemDrop item = r.m_item; return ((item != null) ? ((Object)item).name : null) == "Bronze"; }).ToList(); foreach (Recipe bronzeRecipe in bronzeRecipes) { SaveOriginalRecipe(bronzeRecipe); } } private void CreateConfigValues() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_006f: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Expected O, but got Unknown //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Expected O, but got Unknown //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Expected O, but got Unknown //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Expected O, but got Unknown //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Expected O, but got Unknown ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; configModEnabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, new ConfigDescription("Enable this mod", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 0 } })); configNexusID = ((BaseUnityPlugin)this).Config.Bind("General", "NexusID", 1898, new ConfigDescription("Nexus mod ID for updates", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Browsable = false, Order = 1, ReadOnly = true } })); configShowChangesAtStartup = ((BaseUnityPlugin)this).Config.Bind("Plugin", "ShowChangesAtStartup", true, new ConfigDescription("If this option is set, the changes made by this mod are displayed in the console log.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 0 } })); configBronzeAlloy = ((BaseUnityPlugin)this).Config.Bind("Recipe Alloy", "Alloy Type", BronzeAlloy.Default, new ConfigDescription(ConfigEntryRecipeAlloyDescription, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { DefaultValue = BronzeAlloy.Default, Order = 1, DispName = "Alloy Type" + Environment.NewLine + Environment.NewLine + ConfigEntryAttention } })); configRecipeNeededCopper = ((BaseUnityPlugin)this).Config.Bind("Recipe Custom", "Required Copper", DefaultAlloy[0], new ConfigDescription(ConfigEntryRecipeCustomCopperDescription, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 0 } })); configRecipeNeededTin = ((BaseUnityPlugin)this).Config.Bind("Recipe Custom", "Required Tin", DefaultAlloy[1], new ConfigDescription(ConfigEntryRecipeCustomTinDescription, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 1 } })); configRecipeProducedBronze = ((BaseUnityPlugin)this).Config.Bind("Recipe Custom", "Produced Bronze", DefaultAlloy[2], new ConfigDescription(ConfigEntryRecipeCustomBronzeDescription, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 2 } })); SynchronizationManager.OnConfigurationSynchronized += OnConfigurationSynchronized; } private void SubscribeToConfigChanges() { configModEnabled.SettingChanged += OnConfigChanged; configBronzeAlloy.SettingChanged += OnConfigChanged; configRecipeNeededCopper.SettingChanged += OnConfigChanged; configRecipeNeededTin.SettingChanged += OnConfigChanged; configRecipeProducedBronze.SettingChanged += OnConfigChanged; } private void ReadConfigValues() { showChanges = configShowChangesAtStartup.Value && firstUpdate; if (showChanges) { firstUpdate = false; } BronzeAlloy value = configBronzeAlloy.Value; switch (value) { case BronzeAlloy.Default: if (showChanges) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Default option selected"); } usedRequirementCopper = DefaultAlloy[0]; usedRequirementTin = DefaultAlloy[1]; usedQuantityBronze = DefaultAlloy[2]; break; case BronzeAlloy.WoWlike: if (showChanges) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"WoWlike option selected"); } usedRequirementCopper = WoWlikeAlloy[0]; usedRequirementTin = WoWlikeAlloy[1]; usedQuantityBronze = WoWlikeAlloy[2]; break; case BronzeAlloy.Realistic: if (showChanges) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Realistic option selected"); } usedRequirementCopper = RealisticAlloy[0]; usedRequirementTin = RealisticAlloy[1]; usedQuantityBronze = RealisticAlloy[2]; break; case BronzeAlloy.Custom: if (showChanges) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Custom option selected"); } usedRequirementCopper = Math.Max(1, configRecipeNeededCopper.Value); usedRequirementTin = Math.Max(1, configRecipeNeededTin.Value); usedQuantityBronze = Math.Max(1, configRecipeProducedBronze.Value); break; default: if (showChanges) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Unknown alloy preset '{value}', falling back to Default."); } usedRequirementCopper = DefaultAlloy[0]; usedRequirementTin = DefaultAlloy[1]; usedQuantityBronze = DefaultAlloy[2]; break; } } private void UpdateBronzeRecipe() { ReadConfigValues(); ChangeBronzeRecipe(); } private void ChangeBronzeRecipe() { //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"ObjectDB not ready, skipping recipe update."); return; } if ((Object)(object)copperPrefab == (Object)null) { copperPrefab = Cache.GetPrefab("Copper"); } if ((Object)(object)tinPrefab == (Object)null) { tinPrefab = Cache.GetPrefab("Tin"); } if ((Object)(object)copperPrefab == (Object)null || (Object)(object)tinPrefab == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Failed to get Copper or Tin prefab."); return; } if (bronzeRecipes.Count > 0) { foreach (Recipe bronzeRecipe in bronzeRecipes) { try { int num = ((((Object)bronzeRecipe).name == "Recipe_Bronze") ? 1 : 5); int num2 = usedRequirementCopper * num; int num3 = usedRequirementTin * num; int num4 = usedQuantityBronze * num; bronzeRecipe.m_resources = (Requirement[])(object)new Requirement[2] { new Requirement { m_resItem = copperPrefab, m_amount = num2 }, new Requirement { m_resItem = tinPrefab, m_amount = num3 } }; bronzeRecipe.m_amount = num4; if (showChanges) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Changed {((Object)bronzeRecipe).name}: Copper = {num2}, Tin = {num3}, Bronze = {num4}"); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Error updating recipe " + ((Object)bronzeRecipe).name + ": " + ex.Message)); } } return; } ((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not find any Bronze recipes."); } private void SaveOriginalRecipe(Recipe recipe) { //IL_0056: 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) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown if ((Object)(object)recipe == (Object)null || string.IsNullOrEmpty(((Object)recipe).name) || originalRecipes.ContainsKey(((Object)recipe).name)) { return; } Requirement[] resources = recipe.m_resources; Requirement[] array = (Requirement[])(object)new Requirement[(resources != null) ? resources.Length : 0]; if (recipe.m_resources != null) { for (int i = 0; i < recipe.m_resources.Length; i++) { Requirement val = recipe.m_resources[i]; array[i] = new Requirement { m_resItem = val.m_resItem, m_amount = val.m_amount }; } } originalRecipes[((Object)recipe).name] = (array, recipe.m_amount); } private void RestoreOriginalRecipes() { if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null) { return; } foreach (Recipe bronzeRecipe in bronzeRecipes) { if (originalRecipes.TryGetValue(((Object)bronzeRecipe).name, out (Requirement[], int) value)) { (bronzeRecipe.m_resources, bronzeRecipe.m_amount) = value; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Restored original recipe: " + ((Object)bronzeRecipe).name)); } } } } public static class PluginInfo { public const string PLUGIN_GUID = "CustomizedBronze"; public const string PLUGIN_NAME = "CustomizedBronze"; public const string PLUGIN_VERSION = "0.0.1.1"; } } namespace Common { public class DependencyOperations { public static bool CheckForDependencyErrors(string pluginName) { bool result = false; if (!VersionOperations.CheckVersionWithOutput(pluginName, "Valheim", VersionOperations.GetGameVersion(), "0.221.12")) { result = true; } if (!VersionOperations.CheckVersionWithOutput(pluginName, "BepInExPack Valheim", VersionOperations.GetBepinExVersion(), "5.4.23.3")) { result = true; } if (!VersionOperations.CheckVersionWithOutput(pluginName, "Jotunn, the Valheim Library", VersionOperations.GetJotunnVersion(), "2.29.1")) { result = true; } if (Dependencies.RequiredPlugins.Length != 0 && !FileOperations.CheckRequiredPluginDependencies(Dependencies.RequiredPlugins)) { result = true; } if (Dependencies.RequiredFiles.Length != 0 && !FileOperations.CheckFileDependencies(Dependencies.RequiredFiles)) { result = true; } if (Dependencies.RecommendedPlugins.Length > 0 && FileOperations.CheckRecommendedPluginDependencies(Dependencies.RecommendedPlugins) > 0) { Logger.LogInfo((object)"Some recommended plugins could not be found. The mod's functionality may be limited."); } return result; } } public class FileOperations { public static bool CheckRequiredPluginDependencies(string[] plugins) { bool result = true; foreach (string text in plugins) { if (Directory.GetFiles(Paths.PluginPath, text, SearchOption.AllDirectories).Length == 0) { Logger.LogInfo((object)("Needed plugin " + text + " not installed.")); result = false; } } return result; } public static bool CheckFileDependencies(string[] files) { bool result = true; foreach (string path in files) { string text = Path.Combine(Paths.PluginPath, "CustomizedBronze", path); if (!File.Exists(text)) { Logger.LogError((object)("File " + text + " not exists.")); result = false; } } return result; } public static int CheckRecommendedPluginDependencies(string[,] plugins) { int num = 0; for (int i = 0; i < plugins.GetLength(0); i++) { string text = plugins[i, 0]; string text2 = plugins[i, 1]; if (Directory.GetFiles(Paths.PluginPath, text, SearchOption.AllDirectories).Length == 0) { num++; Logger.LogInfo((object)("Recommended plugin " + text + " (" + text2 + ") not installed.")); } } return num; } } public class VersionOperations { internal static string BepInExVersion => typeof(BaseUnityPlugin).Assembly.GetName().Version.ToString(); public static bool CheckVersionWithOutput(string pluginName, string dependencyName, string dependencyInstalledVersion, string dependencyNeededMinVersion) { if (!CheckVersion(dependencyInstalledVersion, dependencyNeededMinVersion)) { Logger.LogError((object)(pluginName + " need " + dependencyName + " version " + dependencyNeededMinVersion + " or higher, installed version is " + dependencyInstalledVersion + ", pls update")); return false; } return true; } private static bool CheckVersion(string v1, string v2) { int num = 0; int num2 = 0; int i = 0; for (int j = 0; i < v1.Length || j < v2.Length; j++) { for (; i < v1.Length && v1[i] != '.'; i++) { num = num * 10 + (v1[i] - 48); } for (; j < v2.Length && v2[j] != '.'; j++) { num2 = num2 * 10 + (v2[j] - 48); } if (num > num2) { return true; } if (num2 > num) { return false; } num = (num2 = 0); i++; } return true; } public static string GetGameVersion() { return GameVersions.ValheimVersion.ToString(); } private static string GetCompatiblePlayerVersions() { return string.Join(", ", 27); } private static string GetCompatibleWorldVersion() { return string.Join(", ", 9); } public static string GetBepinExVersion() { return BepInExVersion; } public static string GetJotunnVersion() { return "2.29.1"; } } }