Please disclose if any significant portion of your mod was created 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 Clearer Weather v1.0.0
plugins/MoreClearWeather/MoreClearWeather.dll
Decompiled 7 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Clearer Weather")] [assembly: AssemblyCompany("JPValheim")] [assembly: AssemblyProduct("Clearer Weather")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: InternalsVisibleTo("MoreClearWeather.Tests")] [assembly: AssemblyVersion("1.0.0.0")] [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 MoreClearWeather { [BepInPlugin("JPValheim.MoreClearWeather", "Clearer Weather", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { public const string Id = "JPValheim.MoreClearWeather"; internal static WeatherSettings Settings; internal static ManualLogSource Log; private Harmony harmony; private void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Settings = new WeatherSettings(((BaseUnityPlugin)this).Config); harmony = new Harmony("JPValheim.MoreClearWeather"); try { harmony.PatchAll(typeof(WeatherPatch).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Clearer Weather 1.0.0 loaded."); } catch (Exception ex) { harmony.UnpatchSelf(); ((BaseUnityPlugin)this).Logger.LogError((object)("Clearer Weather could not patch this game build. Vanilla weather remains active. " + ex)); } } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } Settings = null; Weather.ClearWarnings(); } } internal sealed class SettingsBindings { internal readonly ConfigFile Config; private readonly HashSet<ConfigDefinition> existing; internal SettingsBindings(ConfigFile config) { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown Config = config; existing = new HashSet<ConfigDefinition>(config.Keys); if (!File.Exists(config.ConfigFilePath)) { return; } string text = ""; string[] array = File.ReadAllLines(config.ConfigFilePath); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length != 0 && !text2.StartsWith("#")) { if (text2.StartsWith("[") && text2.EndsWith("]")) { text = text2.Substring(1, text2.Length - 2).Trim(); } else if (text2.IndexOf('=') > 0 && text.Length > 0) { existing.Add(new ConfigDefinition(text, text2.Substring(0, text2.IndexOf('=')).Trim())); } } } } internal ConfigEntry<int> Chance(string section, string name, string oldName, int value, string description) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown ConfigEntry<int> val = WeatherSettings.Chance(Config, section, name, value, description); ConfigDefinition val2 = new ConfigDefinition(section, oldName); if (!existing.Contains(val2)) { return val; } ConfigEntry<int> val3 = Config.Bind<int>(val2, value, new ConfigDescription("", (AcceptableValueBase)null, Array.Empty<object>())); if (!existing.Contains(((ConfigEntryBase)val).Definition)) { val.Value = val3.Value; } Config.Remove(val2); return val; } internal void MigrateAppearance(string section, ConfigEntry<WeatherStyle> style, ConfigEntry<string> custom) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown ConfigDefinition val = new ConfigDefinition(section, "Clear environment"); if (existing.Contains(val)) { ConfigEntry<string> val2 = Config.Bind<string>(val, "", new ConfigDescription("", (AcceptableValueBase)null, Array.Empty<object>())); WeatherStyle weatherStyle = AppearanceSettings.FromEnvironment(val2.Value); if (!existing.Contains(((ConfigEntryBase)style).Definition)) { style.Value = weatherStyle; } if (weatherStyle == WeatherStyle.Custom && !existing.Contains(((ConfigEntryBase)custom).Definition)) { custom.Value = val2.Value; } Config.Remove(val); } } } internal static class Weather { private static readonly Dictionary<string, string> Warnings = new Dictionary<string, string>(); internal static EnvSetup Replace(EnvSetup original, EnvMan manager, long seconds, BiomeSector biome) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected I4, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) WeatherSettings settings = Plugin.Settings; if (settings == null || !settings.Enabled.Value || original == null || manager.m_environmentDuration <= 0 || ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated())) { return original; } double sourceShare = SourceShare(manager.GetAvailableEnvironments(biome), original.m_name); double roll = WeatherPolicy.Roll(seconds / manager.m_environmentDuration, (int)biome.Biome); string name = WeatherPolicy.Choose(settings, biome.Biome, original.m_name, sourceShare, roll, delegate(string message) { WarnOnce("chance/" + original.m_name, message); })?.Trim(); if (string.IsNullOrEmpty(name) || name == original.m_name) { return original; } EnvSetup val = manager.m_environments.Find((EnvSetup env) => env.m_name == name); if (val == null) { WarnOnce("missing/" + ((object)Unsafe.As<Biome, Biome>(ref biome.Biome)/*cast due to .constrained prefix*/).ToString(), "Environment '" + name + "' is unavailable in " + ((object)Unsafe.As<Biome, Biome>(ref biome.Biome)/*cast due to .constrained prefix*/).ToString() + ". Keeping original weather. Check Clear weather style or Custom environment name."); return original; } return CopyAppearance(original, val); } private static void WarnOnce(string key, string message) { if (!Warnings.TryGetValue(key, out var value) || !(value == message)) { Warnings[key] = message; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)message); } } } internal static void ClearWarnings() { Warnings.Clear(); } internal static double SourceShare(List<EnvEntry> environments, string source) { double num = 0.0; double num2 = 0.0; if (environments == null) { return 0.0; } foreach (EnvEntry environment in environments) { if (!environment.m_ashlandsOverride && !environment.m_deepnorthOverride && !(environment.m_weight <= 0f) && !float.IsNaN(environment.m_weight) && !float.IsInfinity(environment.m_weight)) { num += (double)environment.m_weight; if ((environment.m_env?.m_name ?? environment.m_environment) == source) { num2 += (double)environment.m_weight; } } } if (!(num > 0.0)) { return 0.0; } return num2 / num; } internal static EnvSetup CopyAppearance(EnvSetup original, EnvSetup appearance) { EnvSetup obj = appearance.Clone(); obj.m_name = "MoreClearWeather:" + original.m_name + ":" + appearance.m_name; obj.m_windMin = original.m_windMin; obj.m_windMax = original.m_windMax; return obj; } } [HarmonyPatch(typeof(EnvMan), "UpdateEnvironment", new Type[] { typeof(long), typeof(BiomeSector) })] internal static class WeatherPatch { internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); MethodInfo queue = typeof(EnvMan).GetMethod("QueueEnvironment", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[1] { typeof(EnvSetup) }, null); MethodInfo method = typeof(Weather).GetMethod("Replace", BindingFlags.Static | BindingFlags.NonPublic); if (queue == null || method == null) { throw new InvalidOperationException("Required weather methods are unavailable; weather patch was not applied."); } List<CodeInstruction> list2 = list.FindAll((CodeInstruction instruction) => CodeInstructionExtensions.Calls(instruction, queue)); if (list2.Count != 1 || list2[0].blocks.Count != 0) { throw new InvalidOperationException("Expected one ordinary-weather queue call; weather patch was not applied."); } int index = list.IndexOf(list2[0]); CodeInstruction val = new CodeInstruction(OpCodes.Ldarg_0, (object)null); CodeInstructionExtensions.MoveLabelsTo(list[index], val); list.InsertRange(index, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[4] { val, new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Ldarg_2, (object)null), new CodeInstruction(OpCodes.Call, (object)method) }); return list; } } internal static class WeatherPolicy { internal static double Roll(long period, int biome) { long num = period + -7046029254386353131L + (uint)biome * -3335678366873096957L; long num2 = (num ^ (num >>> 30)) * -4658895280553007687L; long num3 = (num2 ^ (num2 >>> 27)) * -7723592293110705685L; return (double)((ulong)(num3 ^ (num3 >>> 31)) >> 11) * 1.1102230246251565E-16; } internal static int Pick(double roll, double sourceShare, int first, int second = 0) { if (sourceShare <= 0.0 || first + second == 0) { return 0; } double num = Math.Max(sourceShare, (double)(first + second) / 100.0); if (roll < (double)first / 100.0 / num) { return 1; } if (!(roll < (double)(first + second) / 100.0 / num)) { return 0; } return 2; } internal static string Choose(WeatherSettings settings, Biome biome, string original, double sourceShare, double roll, Action<string> warning = null) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_0098: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Invalid comparison between Unknown and I4 //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Invalid comparison between Unknown and I4 //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Invalid comparison between Unknown and I4 //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Invalid comparison between Unknown and I4 //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Invalid comparison between Unknown and I4 if (!settings.IsEnabled(biome, original)) { return null; } bool sea = original == "Ashlands_SeaStorm"; if (sea) { sourceShare = 1.0; } if (sea) { return Select(settings.SeaStorm.Value, null, settings.SeaClear.Value, settings.SeaEnvironment, "Ashlands_ashrain"); } Biome val = biome; if ((int)val <= 4) { if ((int)val != 2) { if ((int)val == 4 && original == "Snow") { return Select(settings.MountainClear.Value, settings.MountainWeather.Environment); } } else if (original == "SwampRain") { return Select(settings.SwampClear.Value, settings.SwampWeather.Environment, settings.SwampFog.Value, "Misty"); } } else if ((int)val != 16) { if ((int)val != 32) { if ((int)val == 512 && original == "Mistlands_clear") { return Select(settings.MistlandsClear.Value, settings.MistlandsWeather.Environment); } } else if (original == "Ashlands_ashrain") { return Select(settings.AshlandsClear.Value, settings.AshlandsWeather.Environment); } } else if (original == "Heath clear") { return Select(settings.PlainsRain.Value, "Rain", settings.PlainsStorm.Value, "ThunderStorm"); } return null; unsafe string Select(int first, string firstWeather, int second = 0, string secondWeather = null, string remainder = null) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Invalid comparison between Unknown and I4 if ((double)(first + second) > sourceShare * 100.0 && warning != null) { double num = sourceShare * 100.0 / (double)(first + second); string text = (sea ? "storm" : (((int)biome == 16) ? "added rain" : "clear")); string text2 = (sea ? "clear" : (((int)biome == 16) ? "thunderstorm" : "fog")); string text3 = ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString() + ": effective " + text + " chance = " + ((double)first * num).ToString("0.##", CultureInfo.InvariantCulture) + "%"; if (second > 0) { text3 = text3 + ", " + text2 + " chance = " + ((double)second * num).ToString("0.##", CultureInfo.InvariantCulture) + "%"; } warning(text3 + ". Requested chances exceed the weather available to replace."); } return Pick(roll, sourceShare, first, second) switch { 2 => secondWeather, 1 => firstWeather, _ => remainder, }; } } } public enum WeatherStyle { Sunny, Forest, Golden, Northern, Custom } public enum OceanWeatherStyle { UseAshlands = -1, Sunny, Forest, Golden, Northern, Custom } internal sealed class WeatherSettings { internal readonly ConfigEntry<bool> Enabled; internal readonly ConfigEntry<bool> SwampEnabled; internal readonly ConfigEntry<bool> MountainEnabled; internal readonly ConfigEntry<bool> AshlandsEnabled; internal readonly ConfigEntry<bool> SeaEnabled; internal readonly ConfigEntry<bool> PlainsEnabled; internal readonly ConfigEntry<bool> MistlandsEnabled; internal readonly ConfigEntry<int> SwampClear; internal readonly ConfigEntry<int> SwampFog; internal readonly ConfigEntry<int> MountainClear; internal readonly ConfigEntry<int> AshlandsClear; internal readonly ConfigEntry<int> SeaStorm; internal readonly ConfigEntry<int> SeaClear; internal readonly ConfigEntry<int> PlainsRain; internal readonly ConfigEntry<int> PlainsStorm; internal readonly ConfigEntry<int> MistlandsClear; internal readonly AppearanceSettings SwampWeather; internal readonly AppearanceSettings MountainWeather; internal readonly AppearanceSettings AshlandsWeather; internal readonly AppearanceSettings MistlandsWeather; internal readonly ConfigEntry<OceanWeatherStyle> SeaStyle; internal readonly ConfigEntry<string> SeaCustom; internal string SeaEnvironment { get { if (SeaStyle.Value != OceanWeatherStyle.UseAshlands) { return AppearanceSettings.Resolve((WeatherStyle)SeaStyle.Value, SeaCustom.Value); } return AshlandsWeather.Environment; } } internal WeatherSettings(ConfigFile config) { SettingsBindings settingsBindings = new SettingsBindings(config); bool saveOnConfigSet = config.SaveOnConfigSet; config.SaveOnConfigSet = false; try { Enabled = config.Bind<bool>("General", "Enabled", true, "Enable weather changes. Restart after editing this file. Configuration-manager changes apply at the next normal weather selection. The original weather's wind range is kept."); SwampEnabled = Enable(config, "Swamp"); SwampClear = Chance(config, "Swamp", "Clear chance (%)", 30, "Clear weather as a percentage of all normal weather selections. Replaces swamp rain; 0 disables added clear weather."); SwampFog = Chance(config, "Swamp", "Fog chance (%)", 5, "Fog as a percentage of normal weather selections. Also replaces swamp rain. If clear and fog exceed the rain available, both scale down; see LogOutput.log."); SwampWeather = new AppearanceSettings(settingsBindings, "Swamp", WeatherStyle.Sunny); MountainEnabled = Enable(config, "Mountains"); MountainClear = Chance(config, "Mountains", "Clear chance (%)", 30, "Clear weather as a percentage of all normal weather selections. Replaces ordinary snow; blizzards stay unchanged. A high value uses all available ordinary snow."); MountainWeather = new AppearanceSettings(settingsBindings, "Mountains", WeatherStyle.Northern); AshlandsEnabled = Enable(config, "Ashlands"); AshlandsClear = Chance(config, "Ashlands", "Clear chance (%)", 30, "Clear weather as a percentage of all normal weather selections. Replaces ordinary ash rain; other weather stays unchanged."); AshlandsWeather = new AppearanceSettings(settingsBindings, "Ashlands", WeatherStyle.Golden); SeaEnabled = Enable(config, "Ashlands Ocean"); SeaStorm = Chance(config, "Ashlands Ocean", "Storm chance (%)", 50, "Sea-storm weather chance. Ash rain fills the chance left after storm and clear weather: 50 storm + 10 clear leaves 40 ash rain."); SeaClear = Chance(config, "Ashlands Ocean", "Clear chance (%)", 10, "Clear-weather chance. Storm and clear totals above 100 scale down together; see LogOutput.log. All three options keep the original sea-storm wind range."); SeaStyle = config.Bind<OceanWeatherStyle>("Ashlands Ocean", "Clear weather style", OceanWeatherStyle.UseAshlands, "UseAshlands follows the land's style. Sunny = bright; Forest = subdued; Golden = warm and hazy; Northern = freezing. Custom uses Custom environment name."); SeaCustom = AppearanceSettings.CustomName(config, "Ashlands Ocean"); PlainsEnabled = Enable(config, "Plains"); PlainsRain = settingsBindings.Chance("Plains", "Added rain chance (%)", "Rain chance (%)", 5, "Additional ordinary rain as a percentage of all weather selections. Replaces fair weather; existing light rain and fog stay unchanged."); PlainsStorm = Chance(config, "Plains", "Thunderstorm chance (%)", 2, "Additional thunderstorms as a percentage of normal weather selections. Also replaces fair weather. If added rain and thunderstorms exceed available fair weather, both scale down; see LogOutput.log."); MistlandsEnabled = Enable(config, "Mistlands"); MistlandsClear = settingsBindings.Chance("Mistlands", "Alternative weather chance (%)", "Alternative clear chance (%)", 30, "Chance of the selected style across all weather selections. Replaces normal Mistlands fair weather; rain, thunderstorms and local mist stay unchanged."); MistlandsWeather = new AppearanceSettings(settingsBindings, "Mistlands", WeatherStyle.Forest); } finally { config.SaveOnConfigSet = saveOnConfigSet; } if (saveOnConfigSet) { config.Save(); } } internal bool IsEnabled(Biome biome, string original) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 if (!Enabled.Value) { return false; } if (original == "Ashlands_SeaStorm") { return SeaEnabled.Value; } if ((int)biome <= 4) { if ((int)biome == 2) { return SwampEnabled.Value; } if ((int)biome == 4) { return MountainEnabled.Value; } } else { if ((int)biome == 16) { return PlainsEnabled.Value; } if ((int)biome == 32) { return AshlandsEnabled.Value; } if ((int)biome == 512) { return MistlandsEnabled.Value; } } return false; } private static ConfigEntry<bool> Enable(ConfigFile config, string section) { return config.Bind<bool>(section, "Enabled", true, "Enable this biome's weather changes. False restores its normal weather without changing your other settings."); } internal static ConfigEntry<int> Chance(ConfigFile config, string section, string name, int value, string description) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown return config.Bind<int>(section, name, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); } } internal sealed class AppearanceSettings { internal readonly ConfigEntry<WeatherStyle> Style; internal readonly ConfigEntry<string> Custom; internal string Environment => Resolve(Style.Value, Custom.Value); internal AppearanceSettings(SettingsBindings bindings, string section, WeatherStyle defaultStyle) { Style = bindings.Config.Bind<WeatherStyle>(section, "Clear weather style", defaultStyle, "Sunny = bright sunlight; Forest = subdued woodland light; Golden = warm, hazy sunlight; Northern = clear and freezing. Custom uses Custom environment name. The original wind range is kept."); Custom = CustomName(bindings.Config, section); bindings.MigrateAppearance(section, Style, Custom); } internal static ConfigEntry<string> CustomName(ConfigFile config, string section) { return config.Bind<string>(section, "Custom environment name", "", "Used only when the style is Custom. Enter an exact Valheim or modded environment name. A blank or unknown name keeps the original weather."); } internal static string Resolve(WeatherStyle style, string custom) { return style switch { WeatherStyle.Sunny => "Clear", WeatherStyle.Forest => "DeepForest Mist", WeatherStyle.Golden => "Heath clear", WeatherStyle.Northern => "Twilight_Clear", _ => custom, }; } internal static WeatherStyle FromEnvironment(string name) { WeatherStyle[] array = new WeatherStyle[4] { WeatherStyle.Sunny, WeatherStyle.Forest, WeatherStyle.Golden, WeatherStyle.Northern }; foreach (WeatherStyle weatherStyle in array) { if (Resolve(weatherStyle, "") == name?.Trim()) { return weatherStyle; } } return WeatherStyle.Custom; } } }