using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using MegingjordReforged.Source.Config; using MegingjordReforged.Source.Definitions; using MegingjordReforged.Source.Items; using MegingjordReforged.Source.Managers; using MegingjordReforged.Source.Registry; using MegingjordReforged.Source.StatusEffects; using MegingjordReforged.Source.Utilities; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.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] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 MegingjordReforged { [BepInPlugin("NoxiousVex.MegingjordReforged", "Megingjord Reforged: Enhanced Belt Variants", "1.0.0")] public class Plugin : BaseUnityPlugin { private const string ModGUID = "NoxiousVex.MegingjordReforged"; private const string ModName = "Megingjord Reforged: Enhanced Belt Variants"; public const string ModVersion = "1.0.0"; private void Awake() { try { ModLogger.LogStart("================================="); ModLogger.LogStart("Megingjord Reforged: Enhanced Belt Variants : v1.0.0 loading..."); ConfigManager.Load(((BaseUnityPlugin)this).Config); VersionManager.Verify(ConfigManager.ConfigPath); if (!ConfigManager.Current.General.EnableMod) { ModLogger.LogWarning("Megingjord Reforged is disabled in configuration."); return; } BeltRegistry.RegisterBelts(); ServerSyncRegistry.RegisterSyncDefinitions(); ServerSyncManager.Initialize(); PrefabManager.OnVanillaPrefabsAvailable += InitializeAfterPrefabs; ModLogger.LogDebug("Waiting for vanilla prefab availability..."); } catch (Exception arg) { ModLogger.LogError(string.Format("{0} failed during initialization: {1}", "Megingjord Reforged: Enhanced Belt Variants", arg)); ModLogger.LogStart("================================="); } } private static void InitializeAfterPrefabs() { try { ModLogger.LogDebug("Vanilla prefabs available. Initializing content..."); StatusEffectRegistry.RegisterStatusEffects(); BeltPrefabManager.RegisterBelts(); BeltItemManager.RegisterRecipes(); ModLogger.LogStart("Megingjord Reforged: Enhanced Belt Variants : v1.0.0 loaded successfully."); ModLogger.LogStart("================================="); } catch (Exception arg) { ModLogger.LogError($"Prefab initialization failed: {arg}"); } } } } namespace MegingjordReforged.Source.Utilities { public static class ConfigFormatter { private static readonly string[] PreferredSectionOrder = new string[13] { "General", "Logging", "Belts - Aedigjord", "Belts - Aedigjord - Effects", "Belts - Seidgjord", "Belts - Seidgjord - Effects", "Belts - Skadigjord", "Belts - Skadigjord - Effects", "Belts - Alagjord", "Belts - Alagjord - Effects", "Belts - Fornmegingjord", "Belts - Fornmegingjord - Effects", "Advanced" }; private const string FormatVersionKey = "# MegingjordReforged Config Format Version:"; public static int GetStoredFormatVersion(string configPath) { if (string.IsNullOrWhiteSpace(configPath) || !File.Exists(configPath)) { return 0; } try { string[] array = File.ReadAllLines(configPath, Encoding.UTF8); foreach (string text in array) { if (text.StartsWith("# MegingjordReforged Config Format Version:", StringComparison.OrdinalIgnoreCase) && int.TryParse(text.Replace("# MegingjordReforged Config Format Version:", string.Empty).Trim(), out var result)) { return result; } } } catch (Exception ex) { ModLogger.LogWarning("Unable to read configuration format version: " + ex.Message); } return 0; } public static void Format(string configPath, int formatVersion) { if (string.IsNullOrWhiteSpace(configPath)) { ModLogger.LogWarning("ConfigFormatter received an invalid path."); return; } if (!File.Exists(configPath)) { ModLogger.LogWarning("Configuration file does not exist: " + configPath); return; } try { string[] lines = File.ReadAllLines(configPath, Encoding.UTF8); List list = new List(); List list2 = BuildFormattedConfiguration(ParseSections(lines, list)); list2.InsertRange(0, list); AddFormatVersion(list2, formatVersion); WriteFormattedFile(configPath, list2); ModLogger.LogInfo($"Configuration formatted to version {formatVersion}."); } catch (Exception arg) { ModLogger.LogError($"Config formatting failed: {arg}"); } } private static Dictionary> ParseSections(string[] lines, List header) { Dictionary> dictionary = new Dictionary>(StringComparer.OrdinalIgnoreCase); string text = null; foreach (string text2 in lines) { string text3 = text2.Trim(); if (text3.StartsWith("[") && text3.EndsWith("]")) { text = text3.Substring(1, text3.Length - 2).Trim(); if (!dictionary.ContainsKey(text)) { dictionary[text] = new List(); } } else if (text == null) { header.Add(text2); } else { dictionary[text].Add(text2); } } return dictionary; } private static List BuildFormattedConfiguration(Dictionary> sections) { List list = new List(); HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); string[] preferredSectionOrder = PreferredSectionOrder; foreach (string text in preferredSectionOrder) { if (sections.TryGetValue(text, out List value)) { WriteSection(list, text, value); hashSet.Add(text); } } foreach (KeyValuePair> section in sections) { if (!hashSet.Contains(section.Key)) { WriteSection(list, section.Key, section.Value); } } return list; } private static void WriteSection(List output, string name, List contents) { if (output.Count > 0) { output.Add(string.Empty); } output.Add("[" + name + "]"); output.AddRange(contents); } private static void AddFormatVersion(List lines, int version) { lines.RemoveAll((string line) => line.StartsWith("# MegingjordReforged Config Format Version:", StringComparison.OrdinalIgnoreCase)); lines.Insert(0, string.Format("{0} {1}", "# MegingjordReforged Config Format Version:", version)); lines.Insert(1, string.Empty); } private static void WriteFormattedFile(string path, List lines) { string text = path + ".tmp"; try { File.WriteAllLines(text, NormalizeSpacing(lines), Encoding.UTF8); File.Copy(text, path, overwrite: true); File.Delete(text); } catch { if (File.Exists(text)) { File.Delete(text); } throw; } } private static List NormalizeSpacing(List lines) { List list = new List(); bool flag = false; foreach (string line in lines) { bool flag2 = string.IsNullOrWhiteSpace(line); if (!(flag2 && flag)) { list.Add(line); flag = flag2; } } return list; } } public static class ConfigValueConverter { public static float RegenMultiplier(float percentage) { return 1f + percentage / 100f; } public static float RegenMultiplier(float percentage, float minimum, float maximum) { return RegenMultiplier(Mathf.Clamp(percentage, minimum, maximum)); } public static float PercentageToMultiplier(float percentage) { return percentage / 100f; } public static float Multiplier(float percentage) { return PercentageToMultiplier(percentage); } public static float Multiplier(float percentage, float minimum, float maximum) { return PercentageToMultiplier(Mathf.Clamp(percentage, minimum, maximum)); } public static float Flat(float value, float minimum, float maximum) { return Mathf.Clamp(value, minimum, maximum); } } public static class ModLogger { public static void LogStart(string message) { WriteInfo("[Startup] " + message); } public static void LogDebug(string message) { if (IsDebugEnabled()) { WriteInfo("[Debug] " + message); } } public static void LogInfo(string message) { if (IsInfoEnabled()) { WriteInfo("[Info] " + message); } } public static void LogWarning(string message) { if (IsWarningEnabled()) { WriteWarning("[Warning] " + message); } } public static void LogError(string message) { WriteError("[Error] " + message); } private static bool IsDebugEnabled() { if (ConfigManager.Current == null) { return false; } return ConfigManager.Current.Logging == ConfigLoggingMode.Debug; } private static bool IsInfoEnabled() { if (ConfigManager.Current == null) { return false; } if (ConfigManager.Current.Logging != ConfigLoggingMode.Standard) { return ConfigManager.Current.Logging == ConfigLoggingMode.Debug; } return true; } private static bool IsWarningEnabled() { if (ConfigManager.Current == null) { return true; } return ConfigManager.Current.Logging != ConfigLoggingMode.Minimal; } private static void WriteInfo(string message) { Logger.LogInfo((object)message); } private static void WriteWarning(string message) { Logger.LogWarning((object)message); } private static void WriteError(string message) { Logger.LogError((object)message); } } public static class ServerSyncSerializer { public static ZPackage Serialize(ServerSyncPackage package) { //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(package.Version); val.Write(package.SchemaVersion); val.Write(package.Values.Count); foreach (KeyValuePair value in package.Values) { val.Write(value.Key); val.Write(value.Value); } return val; } public static ServerSyncPackage Deserialize(ZPackage package) { ServerSyncPackage serverSyncPackage = new ServerSyncPackage(); serverSyncPackage.Version = package.ReadString(); serverSyncPackage.SchemaVersion = package.ReadInt(); int num = package.ReadInt(); for (int i = 0; i < num; i++) { string key = package.ReadString(); string value = package.ReadString(); serverSyncPackage.Values[key] = value; } return serverSyncPackage; } } } namespace MegingjordReforged.Source.StatusEffects { public class SE_Aedigjord : SE_Stats { public SE_Aedigjord() { ((Object)this).name = "SE_Aedigjord"; ((StatusEffect)this).m_name = "Aedigjord"; ((StatusEffect)this).m_tooltip = "Fueled by fury and the strength of forgotten heroes."; ApplyConfiguration(); } public void ApplyConfiguration() { //IL_00b6: 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) BeltEffectOptions effects = ConfigResolveManager.GetBeltOptions("Aedigjord").Effects; base.m_addMaxCarryWeight = 0f; base.m_addArmor = 0f; base.m_healthRegenMultiplier = 1f; base.m_attackStaminaUseModifier = 0f; base.m_addMaxCarryWeight = ConfigValueConverter.Flat(effects.CarryWeight, 0f, 500f); base.m_addArmor = ConfigValueConverter.Flat(effects.Armor, 0f, 25f); base.m_healthRegenMultiplier = ConfigValueConverter.RegenMultiplier(effects.HealthRegenModifier); base.m_attackStaminaUseModifier = ConfigValueConverter.PercentageToMultiplier(effects.AttackStaminaUseModifier); base.m_percentigeDamageModifiers.m_slash = 0.2f; base.m_percentigeDamageModifiers.m_blunt = 0.3f; base.m_skillLevel = (SkillType)3; base.m_skillLevelModifier = 30f; base.m_skillLevel2 = (SkillType)1; base.m_skillLevelModifier2 = 20f; base.m_adrenalineModifier = 1f; } } public class SE_Alagjord : SE_Stats { public SE_Alagjord() { ((Object)this).name = "SE_Alagjord"; ((StatusEffect)this).m_name = "Alagjord"; ((StatusEffect)this).m_tooltip = "Its wearer moves as freely as the waves themselves."; ApplyConfiguration(); } public void ApplyConfiguration() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) BeltEffectOptions effects = ConfigResolveManager.GetBeltOptions("Alagjord").Effects; base.m_addMaxCarryWeight = 0f; base.m_staminaRegenMultiplier = 1f; base.m_swimStaminaUseModifier = 0f; base.m_addMaxCarryWeight = ConfigValueConverter.Flat(effects.CarryWeight, 0f, 500f); base.m_staminaRegenMultiplier = ConfigValueConverter.RegenMultiplier(effects.StaminaRegenModifier); base.m_swimStaminaUseModifier = ConfigValueConverter.Multiplier(effects.SwimStaminaUseModifier); base.m_swimSpeedModifier = 0.3f; base.m_skillLevel = (SkillType)103; base.m_skillLevelModifier = 35f; base.m_skillLevel2 = (SkillType)104; base.m_skillLevelModifier2 = 20f; } } public class SE_Fornmegingjord : SE_Stats { public SE_Fornmegingjord() { ((Object)this).name = "SE_Fornmegingjord"; ((StatusEffect)this).m_name = "Fornmegingjord"; ((StatusEffect)this).m_tooltip = "A treasure worthy of heroes and kings."; ApplyConfiguration(); } public void ApplyConfiguration() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) BeltEffectOptions effects = ConfigResolveManager.GetBeltOptions("Fornmegingjord").Effects; base.m_addMaxCarryWeight = 0f; base.m_addMaxCarryWeight = ConfigValueConverter.Flat(effects.CarryWeight, 0f, 1000f); base.m_percentigeDamageModifiers.m_spirit = 0.4f; base.m_percentigeDamageModifiers.m_lightning = 0.3f; base.m_skillLevel = (SkillType)13; base.m_skillLevelModifier = 25f; base.m_skillLevel2 = (SkillType)12; base.m_skillLevelModifier2 = 25f; } } public class SE_Seidgjord : SE_Stats { public SE_Seidgjord() { ((Object)this).name = "SE_Seidgjord"; ((StatusEffect)this).m_name = "Seidgjord"; ((StatusEffect)this).m_tooltip = "Carrying the whispers of forgotten runes and arcane power."; ApplyConfiguration(); } public void ApplyConfiguration() { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) BeltEffectOptions effects = ConfigResolveManager.GetBeltOptions("Seidgjord").Effects; base.m_addMaxCarryWeight = 0f; base.m_healthRegenMultiplier = 1f; base.m_staminaRegenMultiplier = 1f; base.m_eitrRegenMultiplier = 1f; base.m_addMaxCarryWeight = ConfigValueConverter.Flat(effects.CarryWeight, 0f, 500f); base.m_healthRegenMultiplier = ConfigValueConverter.RegenMultiplier(effects.HealthRegenModifier); base.m_staminaRegenMultiplier = ConfigValueConverter.RegenMultiplier(effects.StaminaRegenModifier); base.m_eitrRegenMultiplier = ConfigValueConverter.RegenMultiplier(effects.EitrRegenModifier); base.m_skillLevel = (SkillType)9; base.m_skillLevelModifier = 30f; base.m_skillLevel2 = (SkillType)10; base.m_skillLevelModifier2 = 20f; } } public class SE_Skadigjord : SE_Stats { public SE_Skadigjord() { ((Object)this).name = "SE_Skadigjord"; ((StatusEffect)this).m_name = "Skadigjord"; ((StatusEffect)this).m_tooltip = "Light as the wind, granting unmatched speed and agility."; ApplyConfiguration(); } public void ApplyConfiguration() { //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) BeltEffectOptions effects = ConfigResolveManager.GetBeltOptions("Skadigjord").Effects; base.m_addMaxCarryWeight = 0f; base.m_staminaRegenMultiplier = 1f; base.m_runStaminaUseModifier = 0f; base.m_jumpStaminaUseModifier = 0f; base.m_dodgeStaminaUseModifier = 0f; base.m_sneakStaminaUseModifier = 0f; base.m_addMaxCarryWeight = ConfigValueConverter.Flat(effects.CarryWeight, 0f, 500f); base.m_staminaRegenMultiplier = ConfigValueConverter.RegenMultiplier(effects.StaminaRegenModifier); base.m_runStaminaUseModifier = ConfigValueConverter.PercentageToMultiplier(effects.RunStaminaUseModifier); base.m_jumpStaminaUseModifier = ConfigValueConverter.PercentageToMultiplier(effects.JumpStaminaUseModifier); base.m_dodgeStaminaUseModifier = ConfigValueConverter.PercentageToMultiplier(effects.DodgeStaminaUseModifier); base.m_sneakStaminaUseModifier = ConfigValueConverter.PercentageToMultiplier(effects.SneakStaminaUseModifier); base.m_percentigeDamageModifiers.m_pierce = 0.3f; base.m_skillLevel = (SkillType)8; base.m_skillLevelModifier = 20f; base.m_skillLevel2 = (SkillType)14; base.m_skillLevelModifier2 = 35f; } } } namespace MegingjordReforged.Source.Registry { public static class BeltEffectRegistry { private static readonly Dictionary> Effects = new Dictionary>(); public static void RegisterEffects() { Effects.Clear(); RegisterAedigjordEffects(); RegisterAlagjordEffects(); RegisterFornmegingjordEffects(); RegisterSeidgjordEffects(); RegisterSkadigjordEffects(); } public static IReadOnlyList GetEffects(string beltName) { if (Effects.TryGetValue(beltName, out List value)) { return value; } return new List(); } private static void RegisterAedigjordEffects() { Effects["Aedigjord"] = new List { new BeltEffectDefinition { EffectName = "addMaxCarryWeight", DefaultValue = 250f, MinimumValue = 0f, MaximumValue = 500f, AllowZero = true, Description = "Additional maximum carry weight." }, new BeltEffectDefinition { EffectName = "addArmor", DefaultValue = 25f, MinimumValue = 0f, MaximumValue = 25f, AllowZero = true, Description = "Additional armor granted by the belt." }, new BeltEffectDefinition { EffectName = "healthRegenMultiplier", DefaultValue = -0.25f, MinimumValue = -1f, MaximumValue = 3f, AllowZero = true, Description = "Health regeneration modifier." }, new BeltEffectDefinition { EffectName = "attackStaminaUseModifier", DefaultValue = -0.5f, MinimumValue = -0.01f, MaximumValue = 1f, AllowZero = true, Description = "Attack stamina consumption modifier." } }; } private static void RegisterAlagjordEffects() { Effects["Alagjord"] = new List(); } private static void RegisterFornmegingjordEffects() { Effects["Fornmegingjord"] = new List(); } private static void RegisterSeidgjordEffects() { Effects["Seidgjord"] = new List(); } private static void RegisterSkadigjordEffects() { Effects["Skadigjord"] = new List(); } } public static class BeltRegistry { public static readonly Dictionary Belts = new Dictionary(); public static void RegisterBelts() { //IL_006c: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_0086: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Expected O, but got Unknown //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Expected O, but got Unknown //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Expected O, but got Unknown //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Expected O, but got Unknown //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Expected O, but got Unknown //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Expected O, but got Unknown //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Expected O, but got Unknown //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Expected O, but got Unknown //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Expected O, but got Unknown ModLogger.LogDebug("Registering belt definitions..."); Belts.Clear(); BeltDefinition beltDefinition = new BeltDefinition(); beltDefinition.ConfigKey = "Aedigjord"; beltDefinition.PrefabName = "MR_Aedigjord"; beltDefinition.DisplayName = "Aedigjord"; beltDefinition.Description = "A reforged warrior's girdle infused with the fury of battle rage."; beltDefinition.IconName = "Aedigjord.png"; beltDefinition.TextureName = "Aedigjord_d.png"; beltDefinition.Type = BeltType.BeltAedigjord; beltDefinition.Requirements = (RequirementConfig[])(object)new RequirementConfig[2] { new RequirementConfig { Item = "BeltStrength", Amount = 1 }, new RequirementConfig { Item = "GemstoneRed", Amount = 3 } }; AddBelt(beltDefinition); beltDefinition = new BeltDefinition(); beltDefinition.ConfigKey = "Seidgjord"; beltDefinition.PrefabName = "MR_Seidgjord"; beltDefinition.DisplayName = "Seidgjord"; beltDefinition.Description = "A mystical girdle empowered by ancient seiưr magic."; beltDefinition.IconName = "Seidgjord.png"; beltDefinition.TextureName = "Seidgjord_d.png"; beltDefinition.Type = BeltType.BeltSeidgjord; beltDefinition.Requirements = (RequirementConfig[])(object)new RequirementConfig[4] { new RequirementConfig { Item = "BeltStrength", Amount = 1 }, new RequirementConfig { Item = "GemstoneRed", Amount = 1 }, new RequirementConfig { Item = "GemstoneBlue", Amount = 1 }, new RequirementConfig { Item = "Eitr", Amount = 20 } }; AddBelt(beltDefinition); beltDefinition = new BeltDefinition(); beltDefinition.ConfigKey = "Skadigjord"; beltDefinition.PrefabName = "MR_Skadigjord"; beltDefinition.DisplayName = "Skadigjord"; beltDefinition.Description = "A hunter's girdle blessed with the swiftness of the wild."; beltDefinition.IconName = "Skadigjord.png"; beltDefinition.TextureName = "Skadigjord_d.png"; beltDefinition.Type = BeltType.BeltSkadigjord; beltDefinition.Requirements = (RequirementConfig[])(object)new RequirementConfig[2] { new RequirementConfig { Item = "BeltStrength", Amount = 1 }, new RequirementConfig { Item = "GemstoneGreen", Amount = 3 } }; AddBelt(beltDefinition); beltDefinition = new BeltDefinition(); beltDefinition.ConfigKey = "Alagjord"; beltDefinition.PrefabName = "MR_Alagjord"; beltDefinition.DisplayName = "Alagjord"; beltDefinition.Description = "A sea-forged girdle granting mastery over the waves."; beltDefinition.IconName = "Alagjord.png"; beltDefinition.TextureName = "Alagjord_d.png"; beltDefinition.Type = BeltType.BeltAlagjord; beltDefinition.Requirements = (RequirementConfig[])(object)new RequirementConfig[2] { new RequirementConfig { Item = "BeltStrength", Amount = 1 }, new RequirementConfig { Item = "GemstoneBlue", Amount = 3 } }; AddBelt(beltDefinition); beltDefinition = new BeltDefinition(); beltDefinition.ConfigKey = "Fornmegingjord"; beltDefinition.PrefabName = "MR_Fornmegingjord"; beltDefinition.DisplayName = "Fornmegingjord"; beltDefinition.Description = "An ancient relic containing the forgotten strength of Thor's Megingjord."; beltDefinition.IconName = "Fornmegingjord.png"; beltDefinition.TextureName = "Fornmegingjord_d.png"; beltDefinition.Type = BeltType.BeltFornmegingjord; beltDefinition.Requirements = (RequirementConfig[])(object)new RequirementConfig[4] { new RequirementConfig { Item = "BeltStrength", Amount = 1 }, new RequirementConfig { Item = "GemstoneRed", Amount = 3 }, new RequirementConfig { Item = "GemstoneBlue", Amount = 3 }, new RequirementConfig { Item = "GemstoneGreen", Amount = 3 } }; AddBelt(beltDefinition); ModLogger.LogDebug($"Registered {Belts.Count} belt definitions."); } private static void AddBelt(BeltDefinition belt) { Belts[belt.PrefabName] = belt; ModLogger.LogDebug("Added belt definition: " + belt.PrefabName); } public static bool IsBelt(string prefabName) { return Belts.ContainsKey(prefabName); } public static BeltDefinition? GetBelt(string prefabName) { if (Belts.TryGetValue(prefabName, out BeltDefinition value)) { return value; } return null; } } public static class ServerSyncRegistry { private static readonly List Definitions = new List(); public static IReadOnlyList SyncDefinitions => Definitions; public static IReadOnlyCollection GetSyncedKeys() { List list = new List(); foreach (ServerSyncDefinition definition in Definitions) { if (definition.Enabled) { list.Add(definition.Identifier); } } return list; } public static void RegisterSyncDefinitions() { Definitions.Clear(); RegisterGeneral(); RegisterBelts(); RegisterBeltEffects(); RegisterAdvanced(); } private static void RegisterGeneral() { Register("General", "Enable Mod", "General.EnableMod"); Register("General", "Enable Server Sync", "General.EnableServerSync"); } private static void RegisterBelts() { string[] array = new string[5] { "Aedigjord", "Seidgjord", "Skadigjord", "Alagjord", "Fornmegingjord" }; foreach (string text in array) { Register("Belts - " + text, "Recipe", "Belts." + text + ".Recipe"); Register("Belts - " + text, "Crafting Station", "Belts." + text + ".CraftingStation"); Register("Belts - " + text, "Crafting Station Level", "Belts." + text + ".CraftingStationLevel"); } } private static void RegisterBeltEffects() { string[] array = new string[5] { "Aedigjord", "Seidgjord", "Skadigjord", "Alagjord", "Fornmegingjord" }; foreach (string belt in array) { RegisterEffect(belt, "Carry Weight", "CarryWeight"); RegisterEffect(belt, "Armor", "Armor"); RegisterEffect(belt, "Health Regen Modifier", "HealthRegenModifier"); RegisterEffect(belt, "Stamina Regen Modifier", "StaminaRegenModifier"); RegisterEffect(belt, "Eitr Regen Modifier", "EitrRegenModifier"); RegisterEffect(belt, "Attack Stamina Use Modifier", "AttackStaminaUseModifier"); RegisterEffect(belt, "Swim Stamina Use Modifier", "SwimStaminaUseModifier"); RegisterEffect(belt, "Run Stamina Use Modifier", "RunStaminaUseModifier"); RegisterEffect(belt, "Jump Stamina Use Modifier", "JumpStaminaUseModifier"); RegisterEffect(belt, "Dodge Stamina Use Modifier", "DodgeStaminaUseModifier"); RegisterEffect(belt, "Sneak Stamina Use Modifier", "SneakStaminaUseModifier"); } } private static void RegisterEffect(string belt, string displayName, string effectKey) { Register("Belts - " + belt + " - Effects", displayName, "Belts." + belt + ".Effects." + effectKey); } private static void RegisterAdvanced() { Register("Advanced", "Experimental Features", "Advanced.ExperimentalFeatures"); } private static void Register(string section, string key, string identifier) { Definitions.Add(new ServerSyncDefinition { Section = section, Key = key, Identifier = identifier, Enabled = true }); } } public static class StatusEffectRegistry { private static bool _registered; public static SE_Aedigjord? Aedigjord { get; private set; } public static SE_Seidgjord? Seidgjord { get; private set; } public static SE_Skadigjord? Skadigjord { get; private set; } public static SE_Alagjord? Alagjord { get; private set; } public static SE_Fornmegingjord? Fornmegingjord { get; private set; } public static void RegisterStatusEffects() { if (_registered) { ModLogger.LogDebug("Status effects have already been registered."); return; } ModLogger.LogDebug("Registering Megingjord Reforged status effects..."); Aedigjord = CreateEffect("Aedigjord"); Seidgjord = CreateEffect("Seidgjord"); Skadigjord = CreateEffect("Skadigjord"); Alagjord = CreateEffect("Alagjord"); Fornmegingjord = CreateEffect("Fornmegingjord"); _registered = true; ModLogger.LogDebug("Completed status effect registration."); } public static void RefreshStatusEffects() { if (!_registered) { ModLogger.LogWarning("Cannot refresh status effects before registration."); return; } ModLogger.LogDebug("Refreshing Megingjord Reforged status effects..."); Aedigjord?.ApplyConfiguration(); Seidgjord?.ApplyConfiguration(); Skadigjord?.ApplyConfiguration(); Alagjord?.ApplyConfiguration(); Fornmegingjord?.ApplyConfiguration(); ModLogger.LogDebug("Finished refreshing status effects."); } private static T? CreateEffect(string configKey) where T : StatusEffect { if (!IsEnabled(configKey)) { ModLogger.LogDebug("Status effect disabled: " + configKey); return default(T); } T val = ScriptableObject.CreateInstance(); ApplyEffectIcon((StatusEffect)(object)val, configKey); RegisterEffect((StatusEffect)(object)val); return val; } private static void ApplyEffectIcon(StatusEffect effect, string configKey) { BeltDefinition belt = BeltRegistry.GetBelt("MR_" + configKey); if (belt == null) { ModLogger.LogWarning("Could not locate belt definition for status effect: " + ((Object)effect).name); return; } Sprite val = BeltIconManager.LoadIcon(belt.IconName); if ((Object)(object)val == (Object)null) { ModLogger.LogWarning("Could not load icon for status effect: " + ((Object)effect).name); return; } effect.m_icon = val; ModLogger.LogDebug("Assigned status effect icon: " + ((Object)effect).name); } private static void RegisterEffect(StatusEffect effect) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if ((Object)(object)effect == (Object)null) { ModLogger.LogWarning("Attempted to register null status effect."); return; } if ((Object)(object)effect.m_icon == (Object)null) { ModLogger.LogWarning("Status effect " + ((Object)effect).name + " registered without an icon."); } ItemManager.Instance.AddStatusEffect(new CustomStatusEffect(effect, true)); ModLogger.LogInfo("Registered status effect: " + ((Object)effect).name); } private static bool IsEnabled(string configKey) { ConfigManager.Current.Belts.GetBeltOptions(configKey); return true; } } } namespace MegingjordReforged.Source.Items { public static class BeltItemManager { private static readonly Dictionary RegisteredRecipes = new Dictionary(); private static bool _registered; public static void RegisterRecipes() { if (_registered) { ModLogger.LogDebug("Recipes have already been registered."); return; } _registered = true; ModLogger.LogDebug("Registering Megingjord Reforged recipes..."); foreach (BeltDefinition value in BeltRegistry.Belts.Values) { RegisterRecipe(value); } ModLogger.LogDebug("Finished registering belt recipes."); } public static void RefreshRecipes() { ModLogger.LogDebug("Refreshing belt recipes..."); ClearRecipes(); RegisterRecipes(); ModLogger.LogDebug("Finished refreshing belt recipes."); } private static void ClearRecipes() { foreach (CustomRecipe value in RegisteredRecipes.Values) { ItemManager.Instance.RemoveRecipe(value); } RegisteredRecipes.Clear(); _registered = false; ModLogger.LogDebug("Cleared Megingjord Reforged recipes."); } private static void RegisterRecipe(BeltDefinition belt) { //IL_0043: 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_004f: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown IndividualBeltOptions beltOptions = ConfigResolveManager.GetBeltOptions(belt.ConfigKey); if (beltOptions.CraftingStation == CraftingStationType.Disabled) { ModLogger.LogDebug("Recipe disabled: " + belt.PrefabName); return; } string text = "Recipe_" + belt.PrefabName; RequirementConfig[] requirements = GetRequirements(belt, beltOptions); CustomRecipe val = new CustomRecipe(new RecipeConfig { Name = text, Item = belt.PrefabName, Amount = belt.Amount, CraftingStation = GetCraftingStation(beltOptions), MinStationLevel = GetStationLevel(beltOptions), Requirements = requirements }); if (!ItemManager.Instance.AddRecipe(val)) { ModLogger.LogWarning("Failed adding recipe: " + text); return; } RegisteredRecipes.Add(text, val); ModLogger.LogInfo("Registered recipe: " + text); } private static RequirementConfig[] GetRequirements(BeltDefinition belt, IndividualBeltOptions options) { if (string.IsNullOrWhiteSpace(options.Recipe)) { return belt.Requirements; } RequirementConfig[] array = ConfigRecipeParser.ParseRecipe(options.Recipe); if (array != null && array.Length != 0) { ModLogger.LogDebug("Using custom recipe for " + belt.PrefabName); return array; } ModLogger.LogWarning("Invalid recipe override for " + belt.PrefabName + ". Using default."); return belt.Requirements; } private static string GetCraftingStation(IndividualBeltOptions options) { return options.CraftingStation switch { CraftingStationType.None => "", CraftingStationType.Workbench => "piece_workbench", CraftingStationType.Forge => "forge", CraftingStationType.Stonecutter => "piece_stonecutter", CraftingStationType.ArtisanTable => "piece_artisanstation", CraftingStationType.BlackForge => "blackforge", CraftingStationType.GaldrTable => "piece_magetable", _ => "piece_magetable", }; } private static int GetStationLevel(IndividualBeltOptions options) { if (options.CraftingStationLevel <= 0) { return 4; } return options.CraftingStationLevel; } } } namespace MegingjordReforged.Source.Managers { public static class BeltIconManager { public static Sprite? LoadIcon(string iconName) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_00b0: 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) if (string.IsNullOrEmpty(iconName)) { ModLogger.LogWarning("Attempted to load an icon with an empty name."); return null; } try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = "MegingjordReforged.Assets.Icons." + iconName; ModLogger.LogDebug("Searching embedded icon resource: " + text); using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { ModLogger.LogError("Icon resource was not found: " + text); return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, array)) { ModLogger.LogError("Failed converting icon resource into texture: " + iconName); return null; } Sprite result = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f)); ModLogger.LogDebug("Created sprite instance for icon: " + iconName); return result; } catch (Exception arg) { ModLogger.LogError($"Exception while loading icon '{iconName}': {arg}"); return null; } } } public static class BeltModelManager { public static void ApplyTexture(GameObject beltObject, string textureName) { if ((Object)(object)beltObject == (Object)null) { ModLogger.LogError("Cannot apply belt texture. Belt object is null."); return; } Texture2D val = LoadTexture(textureName); if ((Object)(object)val == (Object)null) { ModLogger.LogError("Could not load belt texture: " + textureName); return; } Renderer[] componentsInChildren = beltObject.GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { ModLogger.LogError("No renderers found on " + ((Object)beltObject).name); return; } ModLogger.LogDebug($"Applying texture {textureName} to {((Object)beltObject).name} using {componentsInChildren.Length} renderer(s)."); Renderer[] array = componentsInChildren; for (int i = 0; i < array.Length; i++) { Material[] materials = array[i].materials; foreach (Material val2 in materials) { bool flag = false; if (val2.HasProperty("_MainTex")) { val2.SetTexture("_MainTex", (Texture)(object)val); flag = true; } if (val2.HasProperty("_BaseMap")) { val2.SetTexture("_BaseMap", (Texture)(object)val); flag = true; } if (flag) { ModLogger.LogDebug("Applied texture " + textureName + " to material " + ((Object)val2).name + "."); } } } } private static Texture2D? LoadTexture(string textureName) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = "MegingjordReforged.Assets.Textures." + textureName; ModLogger.LogDebug("Loading texture resource: " + text); using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { ModLogger.LogError("Could not find texture resource: " + text); return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, array)) { ModLogger.LogError("Failed loading texture: " + textureName); return null; } ((Object)val).name = textureName; ((Texture)val).wrapMode = (TextureWrapMode)0; ((Texture)val).filterMode = (FilterMode)1; ModLogger.LogDebug("Successfully loaded texture: " + textureName); return val; } } public static class BeltPrefabManager { private const string BasePrefab = "BeltStrength"; private static bool _registered; public static void RegisterBelts() { if (_registered) { ModLogger.LogDebug("Belts have already been registered."); return; } _registered = true; ModLogger.LogDebug("Registering Megingjord Reforged belt prefabs..."); foreach (BeltDefinition value in BeltRegistry.Belts.Values) { CreateBeltPrefab(value); } ModLogger.LogDebug("Finished registering belt prefabs."); } private static void CreateBeltPrefab(BeltDefinition belt) { //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown GameObject prefab = PrefabManager.Instance.GetPrefab("BeltStrength"); if ((Object)(object)prefab == (Object)null) { ModLogger.LogError("Unable to locate vanilla prefab: BeltStrength"); return; } GameObject val = PrefabManager.Instance.CreateClonedPrefab(belt.PrefabName, prefab); ModLogger.LogDebug("Created belt clone: " + belt.PrefabName); ItemDrop component = val.GetComponent(); if ((Object)(object)component == (Object)null) { ModLogger.LogError("Missing ItemDrop component on " + belt.PrefabName); return; } component.m_itemData.m_shared.m_name = belt.DisplayName; component.m_itemData.m_shared.m_description = belt.Description; Sprite val2 = BeltIconManager.LoadIcon(belt.IconName); if ((Object)(object)val2 != (Object)null) { component.m_itemData.m_shared.m_icons[0] = val2; ModLogger.LogDebug("Applied icon: " + belt.IconName); } ApplyBeltTextures(val, belt.TextureName); FixEquipAttach(val, belt.TextureName); StatusEffect statusEffect = GetStatusEffect(belt); if ((Object)(object)statusEffect == (Object)null) { ModLogger.LogWarning("No status effect assigned to " + belt.PrefabName); } else { component.m_itemData.m_shared.m_equipStatusEffect = statusEffect; ModLogger.LogDebug("Assigned status effect to " + belt.PrefabName); } ItemManager.Instance.AddItem(new CustomItem(val, true)); ModLogger.LogInfo("Registered belt prefab: " + belt.PrefabName); } private static StatusEffect? GetStatusEffect(BeltDefinition belt) { return (StatusEffect?)(belt.Type switch { BeltType.BeltAedigjord => StatusEffectRegistry.Aedigjord, BeltType.BeltSeidgjord => StatusEffectRegistry.Seidgjord, BeltType.BeltSkadigjord => StatusEffectRegistry.Skadigjord, BeltType.BeltAlagjord => StatusEffectRegistry.Alagjord, BeltType.BeltFornmegingjord => StatusEffectRegistry.Fornmegingjord, _ => null, }); } private static void ApplyBeltTextures(GameObject beltObject, string textureName) { string[] array = new string[2] { "attach/belt1", "attach_skin/belt1" }; foreach (string text in array) { Transform val = beltObject.transform.Find(text); if (!((Object)(object)val == (Object)null)) { BeltModelManager.ApplyTexture(((Component)val).gameObject, textureName); } } } private static void FixEquipAttach(GameObject beltObject, string textureName) { Transform val = beltObject.transform.Find("attach"); if ((Object)(object)val == (Object)null) { ModLogger.LogWarning("No attach object found for " + ((Object)beltObject).name); return; } Transform val2 = val.Find("belt1"); if ((Object)(object)val2 == (Object)null) { ModLogger.LogWarning("No belt visual found for " + ((Object)beltObject).name); } else { BeltModelManager.ApplyTexture(((Component)val2).gameObject, textureName); } } } public static class ConfigManager { public static MegingjordConfig Current { get; private set; } = new MegingjordConfig(); public static string ConfigPath { get; private set; } = string.Empty; public static void Load(ConfigFile configFile) { try { ConfigPath = configFile.ConfigFilePath; configFile.Bind("General", "Enable Mod", true, (ConfigDescription)null); configFile.Bind("Logging", "Logging Mode", ConfigLoggingMode.Standard, (ConfigDescription)null); string[] array = new string[5] { "Aedigjord", "Seidgjord", "Skadigjord", "Alagjord", "Fornmegingjord" }; foreach (string text in array) { configFile.Bind("Belts - " + text, "Crafting Station", CraftingStationType.GaldrTable, (ConfigDescription)null); } configFile.Bind("Advanced", "Experimental Features", false, (ConfigDescription)null); Current = new MegingjordConfig { General = LoadGeneral(configFile), Logging = LoadLogging(configFile), Belts = LoadBelts(configFile), Advanced = LoadAdvanced(configFile) }; ModLogger.LogDebug("Configuration loaded successfully."); } catch (Exception ex) { ModLogger.LogWarning("Configuration failed to load. " + ex.Message); Current = new MegingjordConfig(); } } private static ConfigGeneralOptions LoadGeneral(ConfigFile configFile) { return new ConfigGeneralOptions { EnableMod = configFile.Bind("General", "Enable Mod", true, (ConfigDescription)null).Value, EnableServerSync = configFile.Bind("General", "Enable Server Sync", true, (ConfigDescription)null).Value }; } private static ConfigLoggingMode LoadLogging(ConfigFile configFile) { return configFile.Bind("Logging", "Logging Mode", ConfigLoggingMode.Standard, (ConfigDescription)null).Value; } private static ConfigBeltOptions LoadBelts(ConfigFile configFile) { return new ConfigBeltOptions { Aedigjord = LoadIndividualBelt(configFile, "Aedigjord"), Seidgjord = LoadIndividualBelt(configFile, "Seidgjord"), Skadigjord = LoadIndividualBelt(configFile, "Skadigjord"), Alagjord = LoadIndividualBelt(configFile, "Alagjord"), Fornmegingjord = LoadIndividualBelt(configFile, "Fornmegingjord") }; } private static IndividualBeltOptions LoadIndividualBelt(ConfigFile configFile, string beltName) { return new IndividualBeltOptions { CraftingStation = configFile.Bind("Belts - " + beltName, "Crafting Station", CraftingStationType.GaldrTable, (ConfigDescription)null).Value, CraftingStationLevel = configFile.Bind("Belts - " + beltName, "Crafting Station Level", 4, (ConfigDescription)null).Value, Recipe = configFile.Bind("Belts - " + beltName, "Recipe", string.Empty, (ConfigDescription)null).Value, Effects = LoadBeltEffects(configFile, beltName) }; } private static BeltEffectOptions LoadBeltEffects(ConfigFile configFile, string beltName) { return beltName switch { "Aedigjord" => LoadAedigjordEffects(configFile), "Seidgjord" => LoadSeidgjordEffects(configFile), "Skadigjord" => LoadSkadigjordEffects(configFile), "Alagjord" => LoadAlagjordEffects(configFile), "Fornmegingjord" => LoadFornmegingjordEffects(configFile), _ => LoadDefaultEffects(), }; } private static BeltEffectOptions LoadFornmegingjordEffects(ConfigFile configFile) { return new BeltEffectOptions { CarryWeight = configFile.Bind("Belts - Fornmegingjord - Effects", "Carry Weight", 450f, (ConfigDescription)null).Value }; } private static BeltEffectOptions LoadAedigjordEffects(ConfigFile configFile) { string section = "Belts - Aedigjord - Effects"; return new BeltEffectOptions { CarryWeight = LoadCarryWeight(configFile, section), Armor = LoadArmor(configFile, section), HealthRegenModifier = LoadPercentage(configFile, section, "Health Regen Modifier", 50f), AttackStaminaUseModifier = LoadPercentage(configFile, section, "Attack Stamina Use Modifier", -30f) }; } private static BeltEffectOptions LoadSeidgjordEffects(ConfigFile configFile) { string section = "Belts - Seidgjord - Effects"; return new BeltEffectOptions { CarryWeight = LoadCarryWeight(configFile, section), HealthRegenModifier = LoadPercentage(configFile, section, "Health Regen Modifier", 25f), StaminaRegenModifier = LoadPercentage(configFile, section, "Stamina Regen Modifier", 25f), EitrRegenModifier = LoadPercentage(configFile, section, "Eitr Regen Modifier", 100f) }; } private static BeltEffectOptions LoadSkadigjordEffects(ConfigFile configFile) { string section = "Belts - Skadigjord - Effects"; return new BeltEffectOptions { CarryWeight = LoadCarryWeight(configFile, section), StaminaRegenModifier = LoadPercentage(configFile, section, "Stamina Regen Modifier", 100f), RunStaminaUseModifier = LoadPercentage(configFile, section, "Run Stamina Use Modifier", -20f), JumpStaminaUseModifier = LoadPercentage(configFile, section, "Jump Stamina Use Modifier", -10f) }; } private static BeltEffectOptions LoadAlagjordEffects(ConfigFile configFile) { return new BeltEffectOptions(); } private static BeltEffectOptions LoadDefaultEffects() { return new BeltEffectOptions(); } private static float LoadCarryWeight(ConfigFile configFile, string section) { return configFile.Bind(section, "Carry Weight", 150f, (ConfigDescription)null).Value; } private static float LoadArmor(ConfigFile configFile, string section) { return configFile.Bind(section, "Armor", 25f, (ConfigDescription)null).Value; } private static float LoadPercentage(ConfigFile configFile, string section, string key, float defaultValue) { return configFile.Bind(section, key, defaultValue, (ConfigDescription)null).Value; } private static ConfigAdvancedOptions LoadAdvanced(ConfigFile configFile) { return new ConfigAdvancedOptions { ExperimentalFeatures = configFile.Bind("Advanced", "Experimental Features", false, (ConfigDescription)null).Value }; } } public static class ConfigResolveManager { public static bool HasServerOverrides => RuntimeConfigOverride.Contains("General.EnableMod"); public static T Get(string key, T localValue) { return ServerSyncManager.GetValue(key, localValue); } public static IndividualBeltOptions GetBeltOptions(string beltName) { IndividualBeltOptions beltOptions = ConfigManager.Current.Belts.GetBeltOptions(beltName); return new IndividualBeltOptions { CraftingStation = Get("Belts." + beltName + ".CraftingStation", beltOptions.CraftingStation), CraftingStationLevel = Get("Belts." + beltName + ".CraftingStationLevel", beltOptions.CraftingStationLevel), Recipe = Get("Belts." + beltName + ".Recipe", beltOptions.Recipe), Effects = GetEffects(beltName, beltOptions.Effects) }; } private static BeltEffectOptions GetEffects(string beltName, BeltEffectOptions localEffects) { return new BeltEffectOptions { CarryWeight = Get("Belts." + beltName + ".Effects.CarryWeight", localEffects.CarryWeight), Armor = Get("Belts." + beltName + ".Effects.Armor", localEffects.Armor), HealthRegenModifier = Get("Belts." + beltName + ".Effects.HealthRegenModifier", localEffects.HealthRegenModifier), StaminaRegenModifier = Get("Belts." + beltName + ".Effects.StaminaRegenModifier", localEffects.StaminaRegenModifier), EitrRegenModifier = Get("Belts." + beltName + ".Effects.EitrRegenModifier", localEffects.EitrRegenModifier), AttackStaminaUseModifier = Get("Belts." + beltName + ".Effects.AttackStaminaUseModifier", localEffects.AttackStaminaUseModifier), SwimStaminaUseModifier = Get("Belts." + beltName + ".Effects.SwimStaminaUseModifier", localEffects.SwimStaminaUseModifier), RunStaminaUseModifier = Get("Belts." + beltName + ".Effects.RunStaminaUseModifier", localEffects.RunStaminaUseModifier), JumpStaminaUseModifier = Get("Belts." + beltName + ".Effects.JumpStaminaUseModifier", localEffects.JumpStaminaUseModifier), DodgeStaminaUseModifier = Get("Belts." + beltName + ".Effects.DodgeStaminaUseModifier", localEffects.DodgeStaminaUseModifier), SneakStaminaUseModifier = Get("Belts." + beltName + ".Effects.SneakStaminaUseModifier", localEffects.SneakStaminaUseModifier) }; } } public static class RuntimeConfigOverride { private static readonly Dictionary Overrides = new Dictionary(); public static bool Contains(string key) { return Overrides.ContainsKey(key); } public static void Set(string key, object value) { Overrides[key] = value.ToString() ?? string.Empty; } public static bool TryGet(string key, out T value) { value = default(T); if (!Overrides.TryGetValue(key, out string value2)) { return false; } try { Type typeFromHandle = typeof(T); if (typeFromHandle == typeof(string)) { value = (T)(object)value2; return true; } if (typeFromHandle.IsEnum) { value = (T)Enum.Parse(typeFromHandle, value2); return true; } value = (T)Convert.ChangeType(value2, typeFromHandle, CultureInfo.InvariantCulture); return true; } catch { return false; } } public static void Remove(string key) { Overrides.Remove(key); } public static void Clear() { Overrides.Clear(); } } public static class ServerSyncDataProvider { private static readonly string[] BeltNames = new string[5] { "Aedigjord", "Seidgjord", "Skadigjord", "Alagjord", "Fornmegingjord" }; public static ServerSyncPackage CreatePackage() { ServerSyncPackage serverSyncPackage = new ServerSyncPackage { Version = "1.0.0", SchemaVersion = VersionManager.SchemaVersion }; foreach (KeyValuePair serverValue in GetServerValues()) { serverSyncPackage.Values[serverValue.Key] = serverValue.Value; } return serverSyncPackage; } private static Dictionary GetServerValues() { Dictionary dictionary = new Dictionary(); foreach (ServerSyncDefinition syncDefinition in ServerSyncRegistry.SyncDefinitions) { if (!syncDefinition.Enabled) { continue; } if (TryGetValue(syncDefinition.Identifier, out string value)) { dictionary[syncDefinition.Identifier] = value; continue; } ModLogger.LogWarning("Unable to resolve synchronized key '" + syncDefinition.Identifier + "'."); if (TryGetDefaultValue(syncDefinition.Identifier, out string value2)) { dictionary[syncDefinition.Identifier] = value2; } } return dictionary; } private static bool TryGetValue(string key, out string value) { value = string.Empty; switch (key) { case "General.EnableMod": value = ConfigManager.Current.General.EnableMod.ToString(); return true; case "General.EnableServerSync": value = ConfigManager.Current.General.EnableServerSync.ToString(); return true; case "Advanced.ExperimentalFeatures": value = ConfigManager.Current.Advanced.ExperimentalFeatures.ToString(); return true; default: { string[] beltNames = BeltNames; foreach (string text in beltNames) { IndividualBeltOptions beltOptions = ConfigManager.Current.Belts.GetBeltOptions(text); if (beltOptions == null) { continue; } if (key == "Belts." + text + ".Recipe") { value = beltOptions.Recipe; return true; } if (key == "Belts." + text + ".CraftingStation") { value = beltOptions.CraftingStation.ToString(); return true; } if (key == "Belts." + text + ".CraftingStationLevel") { value = beltOptions.CraftingStationLevel.ToString(); return true; } foreach (KeyValuePair effectValue in GetEffectValues(text, beltOptions)) { if (key == effectValue.Key) { value = effectValue.Value; return true; } } } return false; } } } private static Dictionary GetEffectValues(string belt, IndividualBeltOptions options) { Dictionary dictionary = new Dictionary(); BeltEffectOptions effects = options.Effects; if (effects == null) { return dictionary; } string text = "Belts." + belt + ".Effects."; dictionary[text + "CarryWeight"] = effects.CarryWeight.ToString(); dictionary[text + "Armor"] = effects.Armor.ToString(); dictionary[text + "HealthRegenModifier"] = effects.HealthRegenModifier.ToString(); dictionary[text + "StaminaRegenModifier"] = effects.StaminaRegenModifier.ToString(); dictionary[text + "EitrRegenModifier"] = effects.EitrRegenModifier.ToString(); dictionary[text + "AttackStaminaUseModifier"] = effects.AttackStaminaUseModifier.ToString(); dictionary[text + "RunStaminaUseModifier"] = effects.RunStaminaUseModifier.ToString(); dictionary[text + "JumpStaminaUseModifier"] = effects.JumpStaminaUseModifier.ToString(); dictionary[text + "DodgeStaminaUseModifier"] = effects.DodgeStaminaUseModifier.ToString(); dictionary[text + "SneakStaminaUseModifier"] = effects.SneakStaminaUseModifier.ToString(); dictionary[text + "SwimStaminaUseModifier"] = effects.SwimStaminaUseModifier.ToString(); return dictionary; } private static bool TryGetDefaultValue(string key, out string value) { value = string.Empty; if (key.Contains("CraftingStationLevel")) { value = "4"; return true; } if (key.Contains("CraftingStation")) { value = CraftingStationType.GaldrTable.ToString(); return true; } if (key.Contains("ExperimentalFeatures")) { value = "false"; return true; } return false; } } public static class ServerSyncManager { [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] private static class RPC_PeerInfoPatch { private static void Postfix(ZNet __instance, ZRpc rpc) { if (!__instance.IsServer()) { return; } foreach (ZNetPeer peer in __instance.GetPeers()) { if (peer.m_rpc == rpc) { SendSynchronizationData(peer); break; } } } } [CompilerGenerated] private static class <>O { public static CoroutineHandler <0>__ServerReceive; public static CoroutineHandler <1>__ClientReceive; } private static bool Initialized; private static CustomRPC? SyncRPC; public static void Initialize() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0083: 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_0074: Expected O, but got Unknown if (Initialized) { return; } Initialized = true; if (!ConfigManager.Current.General.EnableServerSync) { ModLogger.LogDebug("Server synchronization disabled through configuration."); return; } ModLogger.LogDebug("Initializing ServerSync Manager."); NetworkManager instance = NetworkManager.Instance; object obj = <>O.<0>__ServerReceive; if (obj == null) { CoroutineHandler val = ServerReceive; <>O.<0>__ServerReceive = val; obj = (object)val; } object obj2 = <>O.<1>__ClientReceive; if (obj2 == null) { CoroutineHandler val2 = ClientReceive; <>O.<1>__ClientReceive = val2; obj2 = (object)val2; } SyncRPC = instance.AddRPC("MegingjordServerSync", (CoroutineHandler)obj, (CoroutineHandler)obj2); new Harmony("NoxiousVex.MegingjordReforged.ServerSync").PatchAll(typeof(ServerSyncManager)); ModLogger.LogDebug("ServerSync RPC registered."); } private static void SendSynchronizationData(ZNetPeer peer) { if (SyncRPC != null) { ZPackage val = ServerSyncSerializer.Serialize(ServerSyncDataProvider.CreatePackage()); SyncRPC.SendPackage(peer.m_uid, val); ModLogger.LogDebug($"ServerSync data sent to peer {peer.m_uid}."); } } private static IEnumerator ServerReceive(long sender, ZPackage package) { ModLogger.LogWarning($"Rejected ServerSync request from client {sender}."); yield break; } private static IEnumerator ClientReceive(long sender, ZPackage package) { ServerSyncPackage package2 = ServerSyncSerializer.Deserialize(package); if (!ValidatePackage(package2)) { ModLogger.LogWarning("Rejected incompatible ServerSync package."); yield break; } ApplyServerOverrides(package2); StatusEffectRegistry.RefreshStatusEffects(); BeltItemManager.RefreshRecipes(); ModLogger.LogDebug("Server synchronization data applied."); } private static bool ValidatePackage(ServerSyncPackage package) { if (package.SchemaVersion != VersionManager.SchemaVersion) { ModLogger.LogWarning("Rejected ServerSync package. " + $"Received schema {package.SchemaVersion}, " + $"expected schema {VersionManager.SchemaVersion}."); return false; } if (package.Version != "1.0.0") { ModLogger.LogWarning("ServerSync package version mismatch. Received " + package.Version + ", local version 1.0.0."); return false; } return true; } private static void ApplyServerOverrides(ServerSyncPackage package) { RuntimeConfigOverride.Clear(); foreach (KeyValuePair value in package.Values) { if (!IsKnownSyncKey(value.Key)) { ModLogger.LogWarning("Ignoring unknown ServerSync key '" + value.Key + "'."); } else { RuntimeConfigOverride.Set(value.Key, value.Value); } } } private static bool IsKnownSyncKey(string key) { foreach (ServerSyncDefinition syncDefinition in ServerSyncRegistry.SyncDefinitions) { if (syncDefinition.Identifier == key) { return true; } } return false; } public static T GetValue(string key, T localValue) { if (RuntimeConfigOverride.TryGet(key, out var value)) { return value; } return localValue; } public static void Shutdown() { Initialized = false; RuntimeConfigOverride.Clear(); StatusEffectRegistry.RefreshStatusEffects(); BeltItemManager.RefreshRecipes(); ModLogger.LogDebug("ServerSync Manager shutdown."); } } public static class VersionManager { private const int CurrentSchemaVersion = 1; private const int CurrentFormatVersion = 1; private const string FormatVersionKey = "# MegingjordReforged Config Format Version:"; private static bool Verified; public static int SchemaVersion => 1; public static int FormatVersion => 1; public static void Verify(string configPath) { if (Verified) { return; } try { ModLogger.LogDebug("Beginning version verification..."); CheckModVersion(); CheckSchemaVersion(); CheckConfigFormatVersion(configPath); Verified = true; ModLogger.LogDebug("Version verification completed."); } catch (Exception arg) { ModLogger.LogError($"Version verification failed: {arg}"); } } private static void CheckModVersion() { } private static void CheckSchemaVersion() { ModLogger.LogDebug($"ServerSync schema version verified: {1}."); } private static void CheckConfigFormatVersion(string configPath) { if (string.IsNullOrWhiteSpace(configPath)) { ModLogger.LogWarning("Unable to verify config format version. Invalid path."); } else if (File.Exists(configPath)) { int num = ReadStoredFormatVersion(configPath); if (num < 1) { ModLogger.LogInfo($"Updating configuration format from version {num} to {1}."); ConfigFormatter.Format(configPath, 1); } } } private static int ReadStoredFormatVersion(string configPath) { try { string[] array = File.ReadAllLines(configPath, Encoding.UTF8); foreach (string text in array) { if (text.StartsWith("# MegingjordReforged Config Format Version:", StringComparison.OrdinalIgnoreCase) && int.TryParse(text.Replace("# MegingjordReforged Config Format Version:", string.Empty).Trim(), out var result)) { return result; } } } catch (Exception ex) { ModLogger.LogWarning("Unable to read configuration format version: " + ex.Message); } return 0; } } } namespace MegingjordReforged.Source.Definitions { public class MegingjordConfig { public string ConfigPath { get; set; } = string.Empty; public ConfigGeneralOptions General { get; set; } = new ConfigGeneralOptions(); public ConfigLoggingMode Logging { get; set; } = ConfigLoggingMode.Standard; public ConfigBeltOptions Belts { get; set; } = new ConfigBeltOptions(); public ConfigAdvancedOptions Advanced { get; set; } = new ConfigAdvancedOptions(); } public class BeltDefinition { public string ConfigKey { get; set; } = string.Empty; public string PrefabName { get; set; } = string.Empty; public string DisplayName { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; public string IconName { get; set; } = string.Empty; public string TextureName { get; set; } = string.Empty; public BeltType Type { get; set; } public RequirementConfig[] Requirements { get; set; } = Array.Empty(); public int Amount { get; set; } = 1; } public enum BeltType { BeltAedigjord, BeltAlagjord, BeltFornmegingjord, BeltSeidgjord, BeltSkadigjord } public class BeltEffectDefinition { public string EffectName { get; set; } = string.Empty; public bool Configurable { get; set; } = true; public float DefaultValue { get; set; } public float MinimumValue { get; set; } public float MaximumValue { get; set; } public bool AllowZero { get; set; } = true; public string Description { get; set; } = string.Empty; public float Validate(float value) { if (!AllowZero && value == 0f) { return DefaultValue; } if (value < MinimumValue) { return MinimumValue; } if (value > MaximumValue) { return MaximumValue; } return value; } } public enum CraftingStationType { Disabled, None, Workbench, Forge, Stonecutter, ArtisanTable, BlackForge, GaldrTable } public class ServerSyncDefinition { public string Section { get; set; } = string.Empty; public string Key { get; set; } = string.Empty; public string Identifier { get; set; } = string.Empty; public bool Enabled { get; set; } = true; } public class ServerSyncPackage { public string Version { get; set; } = string.Empty; public int SchemaVersion { get; set; } public Dictionary Values { get; set; } = new Dictionary(); } } namespace MegingjordReforged.Source.Config { public class BeltEffectOptions { public float CarryWeight { get; set; } public float Armor { get; set; } public float HealthRegenModifier { get; set; } public float StaminaRegenModifier { get; set; } public float EitrRegenModifier { get; set; } public float AttackStaminaUseModifier { get; set; } public float SwimStaminaUseModifier { get; set; } public float RunStaminaUseModifier { get; set; } public float JumpStaminaUseModifier { get; set; } public float DodgeStaminaUseModifier { get; set; } public float SneakStaminaUseModifier { get; set; } } public class ConfigAdvancedOptions { public bool ExperimentalFeatures { get; set; } } public class ConfigBeltOptions { public IndividualBeltOptions Aedigjord { get; set; } = new IndividualBeltOptions(); public IndividualBeltOptions Alagjord { get; set; } = new IndividualBeltOptions(); public IndividualBeltOptions Fornmegingjord { get; set; } = new IndividualBeltOptions(); public IndividualBeltOptions Seidgjord { get; set; } = new IndividualBeltOptions(); public IndividualBeltOptions Skadigjord { get; set; } = new IndividualBeltOptions(); public IndividualBeltOptions GetBeltOptions(string configKey) { return configKey switch { "Aedigjord" => Aedigjord, "Alagjord" => Alagjord, "Fornmegingjord" => Fornmegingjord, "Seidgjord" => Seidgjord, "Skadigjord" => Skadigjord, _ => new IndividualBeltOptions(), }; } } public class ConfigGeneralOptions { public bool EnableMod { get; set; } = true; public bool EnableServerSync { get; set; } = true; } public enum ConfigLoggingMode { Minimal, Warnings, Standard, Debug } public static class ConfigRecipeParser { public static RequirementConfig[]? ParseRecipe(string recipeString) { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown if (string.IsNullOrWhiteSpace(recipeString)) { return null; } List list = new List(); string[] array = recipeString.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); string[] array2 = text.Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries); if (array2.Length != 2) { ModLogger.LogWarning("Invalid recipe entry '" + text + "'. Expected ItemPrefab:Amount."); continue; } string text2 = array2[0].Trim(); string s = array2[1].Trim(); if (string.IsNullOrWhiteSpace(text2)) { ModLogger.LogWarning("Invalid recipe entry '" + text + "'. Item name cannot be empty."); continue; } if (!int.TryParse(s, out var result)) { ModLogger.LogWarning("Invalid recipe entry '" + text + "'. Amount must be numeric."); continue; } if (result <= 0) { ModLogger.LogWarning("Invalid recipe entry '" + text + "'. Amount must be greater than zero."); continue; } list.Add(new RequirementConfig { Item = text2, Amount = result }); } if (list.Count == 0) { ModLogger.LogWarning("Recipe override contained no valid ingredients. Default recipe will be used."); return null; } ModLogger.LogDebug($"Parsed custom recipe with {list.Count} ingredient(s)."); return list.ToArray(); } } public class IndividualBeltOptions { public CraftingStationType CraftingStation { get; set; } = CraftingStationType.GaldrTable; public int CraftingStationLevel { get; set; } public string Recipe { get; set; } = string.Empty; public BeltEffectOptions Effects { get; set; } = new BeltEffectOptions(); } }