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 OrbExplosionStartLevel v0.1.2
plugins/OrbExplosionStartLevel/OrbExplosionStartLevel.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("saya")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.2.0")] [assembly: AssemblyInformationalVersion("0.1.2")] [assembly: AssemblyProduct("OrbExplosionStartLevel")] [assembly: AssemblyTitle("OrbExplosionStartLevel")] [assembly: AssemblyVersion("0.1.2.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 OrbExplosionStartLevel { internal sealed class HostStartLevel { internal const string PropertyKey = "saya.OrbExplosionStartLevel.StartLevel.v2"; internal const string GenerationKey = "saya.OrbExplosionStartLevel.Generation.v2"; private object? _room; private float _nextPublishAt; private int _configuredAtLoad; internal int? Value { get; private set; } internal string? Generation { get; private set; } internal bool HasRoom => _room != null; internal bool SetRoom(object? room) { if (_room == room) { return false; } _room = room; Value = null; Generation = null; _nextPublishAt = float.NegativeInfinity; return true; } internal void BeginLoad(int configuredStartLevel) { _configuredAtLoad = configuredStartLevel; Value = null; Generation = null; _nextPublishAt = float.NegativeInfinity; } internal void ConfirmGeneration(string generation) { if (Generation == null) { string text = (Generation = generation); } } internal int? Refresh(bool isHost, object? receivedGeneration, object? receivedValue, float now) { if (_room == null || Generation == null || Value.HasValue) { return null; } if (receivedGeneration is string text && text == Generation && receivedValue is int num && num >= 1 && num <= 1000) { Value = num; return null; } if (!isHost || now < _nextPublishAt) { return null; } _nextPublishAt = now + 3f; return _configuredAtLoad; } } [BepInPlugin("saya.OrbExplosionStartLevel", "Orb Explosion Start Level", "0.1.2")] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(LevelGenerator))] private static class LevelPatch { [HarmonyPatch("Start")] [HarmonyPrefix] private static void BeforeStart(LevelGenerator __instance) { Plugin instance = _instance; if (instance != null && Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)GameManager.instance) && Object.op_Implicit((Object)(object)RunManager.instance)) { instance.BeginLevel(__instance); } } [HarmonyPatch("GenerateDone")] [HarmonyPrefix] private static void BeforeGenerateDone(LevelGenerator __instance, PhotonMessageInfo _info) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) Plugin instance = _instance; if (instance != null && Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)GameManager.instance) && Object.op_Implicit((Object)(object)RunManager.instance) && (!SemiFunc.IsMultiplayer() || (_info.Sender != null && _info.Sender == PhotonNetwork.MasterClient && Object.op_Implicit((Object)(object)_info.photonView)))) { instance.GenerationDone(__instance, _info); } } } [HarmonyPatch(typeof(EnemyValuable))] private static class OrbPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void Postfix(EnemyValuable __instance) { Plugin instance = _instance; if (instance != null && Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)RunManager.instance)) { instance.InitializeOrb(__instance); } } [HarmonyPatch("DestroyImpulse")] [HarmonyPrefix] private static void BeforeDestroyImpulse(EnemyValuable __instance) { Plugin instance = _instance; if (instance != null && Object.op_Implicit((Object)(object)instance)) { instance.BeforeDestroy(__instance); } } } public const string PluginGuid = "saya.OrbExplosionStartLevel"; public const string PluginName = "Orb Explosion Start Level"; public const string PluginVersion = "0.1.2"; private static readonly FieldRef<EnemyValuable, bool> HasExplosion = AccessTools.FieldRefAccess<EnemyValuable, bool>("hasExplosion"); private static readonly FieldRef<RunManager, int> LevelsCompleted = AccessTools.FieldRefAccess<RunManager, int>("levelsCompleted"); private readonly Harmony _harmony = new Harmony("saya.OrbExplosionStartLevel"); private static Plugin? _instance; private ConfigEntry<int> _startLevel; private int _levelStartLevel; private LevelGenerator? _levelGenerator; private readonly HostStartLevel _hostStartLevel = new HostStartLevel(); private readonly List<(EnemyValuable Orb, int Level)> _pendingOrbs = new List<(EnemyValuable, int)>(); private float _nextRefresh; private bool _loggedWaiting; private void Awake() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown ((Component)this).transform.SetParent((Transform)null); ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); _startLevel = ((BaseUnityPlugin)this).Config.Bind<int>("General", "StartLevel", 20, new ConfigDescription("First displayed level where enemy orbs explode. The host's setting is captured at each level load and shared with clients. Changes during play apply at the next level load; no restart required. All players need the same mod version. Default 20 matches vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000), Array.Empty<object>())); _instance = this; _harmony.PatchAll(typeof(OrbPatch)); _harmony.PatchAll(typeof(LevelPatch)); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Loaded. Configured StartLevel={_startLevel.Value}; applied at the next level load using the host's setting."); } private void BeginLevel(LevelGenerator generator) { if (_levelGenerator == generator) { return; } RefreshRoom(); _levelGenerator = generator; _pendingOrbs.Clear(); _loggedWaiting = false; if (!SemiFunc.IsMultiplayer() || PhotonNetwork.IsMasterClient) { try { ((BaseUnityPlugin)this).Config.Reload(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not reload configuration; using the in-memory setting: " + ex.Message)); } } _levelStartLevel = _startLevel.Value; _hostStartLevel.BeginLoad(_levelStartLevel); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Level load started: configured StartLevel={_levelStartLevel}; multiplayer clients wait for the host."); } private void GenerationDone(LevelGenerator generator, PhotonMessageInfo info) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) BeginLevel(generator); RefreshRoom(); if (SemiFunc.IsMultiplayer()) { string generation = FormattableString.Invariant($"{info.Sender.ActorNumber}:{info.photonView.ViewID}:{((PhotonMessageInfo)(ref info)).SentServerTimestamp}"); _hostStartLevel.ConfirmGeneration(generation); RefreshRoom(); } } private void Update() { if (Time.unscaledTime < _nextRefresh) { return; } _nextRefresh = Time.unscaledTime + 0.25f; RefreshRoom(); if (!TryGetStartLevel(out var level)) { _pendingOrbs.RemoveAll(((EnemyValuable Orb, int Level) entry) => !Object.op_Implicit((Object)(object)entry.Orb)); return; } foreach (var pendingOrb in _pendingOrbs) { if (Object.op_Implicit((Object)(object)pendingOrb.Orb)) { Apply(pendingOrb.Orb, pendingOrb.Level, level); } } _pendingOrbs.Clear(); } private void RefreshRoom() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Expected O, but got Unknown Room val = ((Object.op_Implicit((Object)(object)GameManager.instance) && SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom) ? PhotonNetwork.CurrentRoom : null); bool hasRoom = _hostStartLevel.HasRoom; if (_hostStartLevel.SetRoom(val)) { if (hasRoom) { _pendingOrbs.Clear(); } _loggedWaiting = false; } if (val != null) { bool hasValue = _hostStartLevel.Value.HasValue; int? num = _hostStartLevel.Refresh(PhotonNetwork.IsMasterClient, ((RoomInfo)val).CustomProperties[(object)"saya.OrbExplosionStartLevel.Generation.v2"], ((RoomInfo)val).CustomProperties[(object)"saya.OrbExplosionStartLevel.StartLevel.v2"], Time.unscaledTime); if (num.HasValue) { bool flag = val.SetCustomProperties(new Hashtable { [(object)"saya.OrbExplosionStartLevel.Generation.v2"] = _hostStartLevel.Generation, [(object)"saya.OrbExplosionStartLevel.StartLevel.v2"] = num.Value }, (Hashtable)null, (WebFlags)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Host StartLevel={num.Value}, generation={_hostStartLevel.Generation}, publication queued={flag}; waiting for room acknowledgement."); } if (!hasValue && _hostStartLevel.Value.HasValue) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Host StartLevel synchronized: {_hostStartLevel.Value.Value} (generation={_hostStartLevel.Generation}, local setting={_startLevel.Value})."); } } } private bool TryGetStartLevel(out int level) { if (Object.op_Implicit((Object)(object)_levelGenerator) && Object.op_Implicit((Object)(object)GameManager.instance) && !SemiFunc.IsMultiplayer()) { level = _levelStartLevel; return true; } level = _hostStartLevel.Value.GetValueOrDefault(); return _hostStartLevel.Value.HasValue; } private void Apply(EnemyValuable orb, int level, int startLevel) { bool flag = HasExplosion.Invoke(orb); bool flag2 = level >= startLevel; HasExplosion.Invoke(orb) = flag2; ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Orb initialized: level={level}, start={startLevel}, previous={flag}, explosion={flag2}."); } private void InitializeOrb(EnemyValuable orb) { RefreshRoom(); int num = LevelsCompleted.Invoke(RunManager.instance) + 1; if (TryGetStartLevel(out var level)) { Apply(orb, num, level); return; } _pendingOrbs.Add((orb, num)); if (!_loggedWaiting) { _loggedWaiting = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)"Waiting for this level's host StartLevel; leaving orbs unchanged until received. All players need the same mod version."); } } private void BeforeDestroy(EnemyValuable orb) { RefreshRoom(); int num = _pendingOrbs.FindIndex(((EnemyValuable Orb, int Level) entry) => (Object)(object)entry.Orb == (Object)(object)orb); if (num >= 0) { (EnemyValuable, int) tuple = _pendingOrbs[num]; if (TryGetStartLevel(out var level)) { Apply(orb, tuple.Item2, level); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Orb destroyed before host StartLevel arrived; original explosion condition retained."); } _pendingOrbs.RemoveAt(num); } } private void OnDestroy() { _harmony.UnpatchSelf(); _pendingOrbs.Clear(); _instance = null; } } }