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 SailRange v0.5.0
SailRange.dll
Decompiled a month agousing System; 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 BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JG224.ModCore.API; using Microsoft.CodeAnalysis; using SailRange.Core; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("SailRange")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.5.0.0")] [assembly: AssemblyInformationalVersion("0.5.0+e7226e273c5e1399ea5d29d9165606bea5783ccf")] [assembly: AssemblyProduct("SailRange")] [assembly: AssemblyTitle("SailRange")] [assembly: AssemblyVersion("0.5.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 SailRange { [BepInPlugin("jg224.BoatRadiusGuard", "SailRange", "0.5.0")] [BepInProcess("valheim.exe")] [BepInDependency("com.jg224.modcore", "0.5.0")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "jg224.BoatRadiusGuard"; public const string PluginName = "SailRange"; public const string PluginVersion = "0.5.0"; public const string ModCoreGuid = "com.jg224.modcore"; public const string ConfigFileName = "jg224.BoatRadiusGuard.cfg"; public const int ProtocolVersion = 1; public const float MinimumRadius = 10f; public const float MaximumRadius = 10000f; internal const ModuleSide DeclaredSide = (ModuleSide)1; internal const ModuleRequirement DeclaredRequirement = (ModuleRequirement)1; public static readonly ModuleId ModuleId = new ModuleId("sailrange"); private readonly List<IDisposable> _registrations = new List<IDisposable>(); private Harmony _harmony; private bool _moduleRegistered; private bool _shutDown; internal static ManualLogSource Log { get; private set; } internal static ConfigEntry<float> BoatExploreRadius { get; private set; } internal static ConfigEntry<bool> Enabled { get; private set; } internal static ConfigEntry<string> ShipRadii { get; private set; } internal static ConfigEntry<float> MinimumTravelDistance { get; private set; } internal static ConfigEntry<int> WorkBudget { get; private set; } internal static ICoreServices Core { get; private set; } private void Awake() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_005d: 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) Log = ((BaseUnityPlugin)this).Logger; try { if (!ModCoreApi.IsAvailable) { throw new InvalidOperationException("ModCore did not initialize before SailRange."); } Core = ModCoreApi.Services; AttachAndBindConfiguration(); RegisterWithCore(); _harmony = new Harmony("jg224.BoatRadiusGuard"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); Core.Modules.SetState(ModuleId, (ModuleRuntimeState)2, "Client-local sailing exploration radius ready."); Game.isModded = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("SailRange 0.5.0 loaded; local boat exploration radius: " + BoatExploreRadius.Value.ToString("0.##", CultureInfo.InvariantCulture) + "m.")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("SailRange failed to initialize safely: " + ex)); if (Core != null && _moduleRegistered) { Core.Modules.SetState(ModuleId, (ModuleRuntimeState)5, ex.Message); } Shutdown(); throw; } } private void AttachAndBindConfiguration() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown if (!Directory.Exists(Paths.ConfigPath)) { Directory.CreateDirectory(Paths.ConfigPath); } string text = Path.Combine(Paths.ConfigPath, "jg224.BoatRadiusGuard.cfg"); ConfigFile obj = PluginConfigFiles.Attach((BaseUnityPlugin)(object)this, new ConfigFile(text, true, ((BaseUnityPlugin)this).Info.Metadata)); BoatExploreRadius = obj.Bind<float>("General", "BoatExploreRadius", 150f, new ConfigDescription("Map exploration radius in meters while the local player is aboard a boat.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 10000f), Array.Empty<object>())); Enabled = obj.Bind<bool>("General", "Enabled", true, "Enable local sailing exploration changes."); ShipRadii = obj.Bind<string>("General", "ShipRadii", "", "Optional prefab=radius overrides in metres, separated by semicolons; e.g. Karve=200;VikingShip=250. Range 10-10000."); MinimumTravelDistance = obj.Bind<float>("General", "MinimumTravelDistance", 2f, new ConfigDescription("Skip completed-radius rescans until the boat has moved this many metres. Zero always rescans.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); WorkBudget = obj.Bind<int>("General", "WorkBudget", 16384, new ConfigDescription("Maximum candidate map pixels per frame. Large radii reveal progressively until complete; no radius is discarded.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1024, 262144), Array.Empty<object>())); } private void RegisterWithCore() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) SemanticVersion val = default(SemanticVersion); if (!SemanticVersion.TryParse("0.5.0", ref val)) { throw new InvalidOperationException("Invalid plugin version."); } _registrations.Add(Core.Modules.Register(new ModuleDescriptor(ModuleId, "jg224.BoatRadiusGuard", "SailRange", val, 1, (ModuleSide)1, (ModuleRequirement)1, 0uL, 1, 1))); _moduleRegistered = true; _registrations.Add(Core.Configuration.Register(new ConfigSettingDescriptor(ModuleId, ((ConfigEntryBase)BoatExploreRadius).Definition.Section, ((ConfigEntryBase)BoatExploreRadius).Definition.Key, (ConfigScope)1, (Func<string>)(() => Convert.ToString(((ConfigEntryBase)BoatExploreRadius).BoxedValue, CultureInfo.InvariantCulture)), 1))); ConfigEntryBase[] array = (ConfigEntryBase[])(object)new ConfigEntryBase[4] { (ConfigEntryBase)Enabled, (ConfigEntryBase)ShipRadii, (ConfigEntryBase)MinimumTravelDistance, (ConfigEntryBase)WorkBudget }; foreach (ConfigEntryBase entry in array) { _registrations.Add(Core.Configuration.Register(new ConfigSettingDescriptor(ModuleId, entry.Definition.Section, entry.Definition.Key, (ConfigScope)1, (Func<string>)(() => Convert.ToString(entry.BoxedValue, CultureInfo.InvariantCulture)), 1))); } _registrations.Add(Core.Lifecycle.Subscribe(ModuleId, (LifecycleEventKind)9, (Action<LifecycleEvent>)delegate { MinimapUpdateExplorePatch.Reset(); }, 0)); _registrations.Add(Core.Lifecycle.Subscribe(ModuleId, (LifecycleEventKind)3, (Action<LifecycleEvent>)delegate { MinimapUpdateExplorePatch.Reset(); }, 0)); } private void OnDestroy() { Shutdown(); } private void Shutdown() { //IL_009b: Unknown result type (might be due to invalid IL or missing references) if (_shutDown) { return; } _shutDown = true; Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _harmony = null; for (int num = _registrations.Count - 1; num >= 0; num--) { try { _registrations[num].Dispose(); } catch (Exception ex) { ManualLogSource logger = ((BaseUnityPlugin)this).Logger; if (logger != null) { logger.LogWarning((object)("Registration cleanup failed: " + ex.Message)); } } } _registrations.Clear(); _moduleRegistered = false; if (Core != null) { Core.Metrics.RemoveOwner(ModuleId); } Core = null; BoatExploreRadius = null; Enabled = null; ShipRadii = null; MinimumTravelDistance = null; WorkBudget = null; MinimapUpdateExplorePatch.Reset(); Log = null; } } [HarmonyPatch(typeof(Minimap), "UpdateExplore")] internal static class MinimapUpdateExplorePatch { internal sealed class Scope { internal RadiusLease Lease; internal Vector3 Origin; internal float Radius; } private static readonly FieldRef<Minimap, Texture2D> FogTexture = AccessTools.FieldRefAccess<Minimap, Texture2D>("m_fogTexture"); private static Func<Minimap, int, int, bool> _explorePixel; private static Minimap _map; private static Ship _ship; private static DiskScan _pending; private static Vector3 _origin; private static Vector3 _completedOrigin; private static float _radius; private static float _completedRadius; private static bool _completed; private static string _raw; private static Dictionary<string, float> _radii = ExplorationRules.ParseOverrides(""); internal static void Reset() { _pending = null; _map = null; _ship = null; _completed = false; } [HarmonyPrefix] private static bool Prefix(Minimap __instance, Player player, ref float ___m_exploreTimer, out Scope __state) { //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011f: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: 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) __state = null; Ship localShip = Ship.GetLocalShip(); if (Object.op_Implicit((Object)(object)localShip) && Object.op_Implicit((Object)(object)player)) { ConfigEntry<bool> enabled = Plugin.Enabled; if (enabled != null && enabled.Value) { if ((Object)(object)_map != (Object)(object)__instance || (Object)(object)_ship != (Object)(object)localShip) { Reset(); _map = __instance; _ship = localShip; } string value = Plugin.ShipRadii.Value; if (_raw != value) { _raw = value; _radii = ExplorationRules.ParseOverrides(value); } string key = ((Object)localShip).name.Replace("(Clone)", "").Trim(); float value2; float num = (_radii.TryGetValue(key, out value2) ? value2 : Plugin.BoatExploreRadius.Value); if (!ExplorationRules.ValidRadius(num) || !(__instance.m_pixelSize > 0f)) { return true; } if (_pending != null && _radius != num) { _pending = null; } if (_pending != null) { Process(__instance); return false; } if (___m_exploreTimer + Time.deltaTime <= __instance.m_exploreInterval) { return true; } Vector3 position = ((Component)player).transform.position; Vector3 val = position - _completedOrigin; val.y = 0f; if (!ExplorationRules.NeedsExplore(_completed, ((Vector3)(ref val)).sqrMagnitude, Plugin.MinimumTravelDistance.Value, _completedRadius, num)) { ___m_exploreTimer = 0f; return false; } int num2 = Mathf.CeilToInt(num / __instance.m_pixelSize); if (ExplorationRules.FitsBudget(num2, Plugin.WorkBudget.Value)) { __state = new Scope { Lease = new RadiusLease(__instance.m_exploreRadius, num), Origin = position, Radius = num }; __instance.m_exploreRadius = num; return true; } if (!Object.op_Implicit((Object)(object)FogTexture.Invoke(__instance))) { return true; } _origin = position; _radius = num; int x = Mathf.RoundToInt(position.x / __instance.m_pixelSize + (float)(__instance.m_textureSize / 2)); int y = Mathf.RoundToInt(position.z / __instance.m_pixelSize + (float)(__instance.m_textureSize / 2)); _pending = new DiskScan(x, y, num2, __instance.m_textureSize); ___m_exploreTimer = 0f; Process(__instance); return false; } } Reset(); return true; } [HarmonyPostfix] private static void Postfix(Minimap __instance, Scope __state, bool __runOriginal) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (__state != null) { Restore(__instance, __state); if (__runOriginal) { _completed = true; _completedOrigin = __state.Origin; _completedRadius = __state.Radius; } } } [HarmonyFinalizer] private static void Finalizer(Minimap __instance, Scope __state) { Restore(__instance, __state); } private static void Restore(Minimap map, Scope scope) { if (scope != null && scope.Lease.TryRestore(map.m_exploreRadius, out var value)) { map.m_exploreRadius = value; } } private static void Process(Minimap map) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) if (_explorePixel == null) { _explorePixel = AccessTools.MethodDelegate<Func<Minimap, int, int, bool>>(AccessTools.Method(typeof(Minimap), "Explore", new Type[2] { typeof(int), typeof(int) }, (Type[])null), (object)null, true); } bool flag = false; for (int i = 0; i < Plugin.WorkBudget.Value; i++) { if (!_pending.Next(out var x, out var y, out var inside)) { break; } if (inside && _explorePixel(map, x, y)) { flag = true; } } if (flag) { FogTexture.Invoke(map).Apply(); } if (_pending.Complete) { _pending = null; _completed = true; _completedOrigin = _origin; _completedRadius = _radius; } } } } namespace SailRange.Core { internal static class ExplorationRules { internal static bool ValidRadius(float radius) { if (!float.IsNaN(radius) && !float.IsInfinity(radius) && radius >= 10f) { return radius <= 10000f; } return false; } internal static Dictionary<string, float> ParseOverrides(string raw) { Dictionary<string, float> dictionary = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase); string[] array = (raw ?? "").Split(new char[1] { ';' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { '=' }); if (array2.Length == 2 && array2[0].Trim().Length > 0 && float.TryParse(array2[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && ValidRadius(result)) { dictionary[array2[0].Trim()] = result; } } return dictionary; } internal static bool NeedsExplore(bool completed, float movedSquared, float threshold, float previousRadius, float radius) { if (completed && previousRadius == radius && !(threshold <= 0f)) { return movedSquared >= threshold * threshold; } return true; } internal static bool FitsBudget(int radiusPixels, int budget) { if (radiusPixels >= 0) { return (2L * (long)radiusPixels + 1) * (2L * (long)radiusPixels + 1) <= budget; } return false; } } internal sealed class DiskScan { private readonly int _centerX; private readonly int _centerY; private readonly int _radius; private readonly int _minX; private readonly int _maxX; private readonly int _maxY; private int _x; private int _y; internal bool Complete { get { if (_y <= _maxY) { return _minX > _maxX; } return true; } } internal DiskScan(int x, int y, int radius, int textureSize) { _centerX = x; _centerY = y; _radius = Math.Max(0, radius); _minX = Math.Max(0, x - _radius); _maxX = Math.Min(textureSize - 1, x + _radius); _x = _minX; _y = Math.Max(0, y - _radius); _maxY = Math.Min(textureSize - 1, y + _radius); } internal bool Next(out int x, out int y, out bool inside) { x = _x; y = _y; inside = false; if (Complete) { return false; } long num = (long)x - (long)_centerX; long num2 = (long)y - (long)_centerY; inside = num * num + num2 * num2 <= (long)_radius * (long)_radius; if (++_x > _maxX) { _x = _minX; _y++; } return true; } } internal sealed class RadiusLease { private bool _restored; internal float Original { get; } internal float Applied { get; } internal RadiusLease(float original, float applied) { Original = original; Applied = applied; } internal bool TryRestore(float current, out float value) { value = current; if (_restored) { return false; } _restored = true; if (current != Applied) { return false; } value = Original; return true; } } }