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 NoItemSpawnLimit v1.0.8
NoItemSpawnLimit.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using NoItemSpawnLimit.Logging; using NoItemSpawnLimit.Patches; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("HeroHanex")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.8.0")] [assembly: AssemblyInformationalVersion("1.0.8+9dd5a50fc6508d43cddc4f74b95360fe1c75b796")] [assembly: AssemblyProduct("NoItemSpawnLimit")] [assembly: AssemblyTitle("NoItemSpawnLimit")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.8.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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 NoItemSpawnLimit { [BepInPlugin("HeroHanex.NoItemSpawnLimit", "NoItemSpawnLimit", "1.0.8")] public class NoItemSpawnLimit : BaseUnityPlugin { internal static NoItemSpawnLimit Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; ConfigManager.Init(((BaseUnityPlugin)this).Config); Patch(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } internal void Patch() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0026: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); Harmony.PatchAll(typeof(LevelGeneratorPatch)); Harmony.PatchAll(typeof(PunManagerPatch)); } internal void Unpatch() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { } } } namespace NoItemSpawnLimit.Patches { public class ConfigManager { private static ConfigFile? _config; private static ConfigEntry<bool>? RemoveSpawnLimit; private static readonly Dictionary<string, ConfigEntry<int>> itemMaxAmountConfigs = new Dictionary<string, ConfigEntry<int>>(); private static ConfigEntry<ModLogLevel>? LogLevel; private const int DefaultMaxAmount = 10000; private static readonly char[] invalidChars = new char[7] { '=', '\n', '\t', '"', '\'', '[', ']' }; public static ModLogLevel CurrentLogLevel => LogLevel?.Value ?? ModLogLevel.Info; public static void Init(ConfigFile config) { _config = config; RemoveSpawnLimit = config.Bind<bool>("General", "RemoveSpawnLimit", true, "Remove item spawn limit"); LogLevel = config.Bind<ModLogLevel>("General", "LogLevel", ModLogLevel.Info, "Logging level"); ModLogger.LogDebug("ConfigManager initialized."); config.Save(); } public static void LoadMaxItemConfig() { //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown if (_config == null) { throw new InvalidOperationException("ConfigManager not initialized. Call Init() before loading config."); } if ((Object)(object)StatsManager.instance == (Object)null || StatsManager.instance.itemDictionary.Count == 0) { ModLogger.LogDebug("StatsManager or itemDictionary is not ready. It should be ready once loaded into a level."); return; } foreach (KeyValuePair<string, Item> item in StatsManager.instance.itemDictionary) { if (!itemMaxAmountConfigs.ContainsKey(item.Key)) { int maxAmount = item.Value.maxAmount; string text = SanitizeString(item.Key); ConfigEntry<int> value = _config.Bind<int>("ItemLimits", text, maxAmount, new ConfigDescription("Max amount for item '" + item.Key + "'", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10000), Array.Empty<object>())); itemMaxAmountConfigs[item.Key] = value; } } if (RemoveSpawnLimit == null) { throw new InvalidOperationException("RemoveSpawnLimit config entry is null. This should not happen if Init() was called correctly."); } _config.Save(); if (RemoveSpawnLimit.Value) { ModLogger.LogInfo($"RemoveSpawnLimit is enabled. Applying predefined config of {10000} to all items..."); ApplyPredefinedConfig(); } else { ModLogger.LogInfo("RemoveSpawnLimit is disabled. Applying per-item config..."); ApplyItemConfig(); } } private static void ApplyItemConfig() { foreach (KeyValuePair<string, ConfigEntry<int>> itemMaxAmountConfig in itemMaxAmountConfigs) { if (!StatsManager.instance.itemDictionary.TryGetValue(itemMaxAmountConfig.Key, out var value)) { ModLogger.LogWarning("Item '" + itemMaxAmountConfig.Key + "' not found in itemDictionary."); } else { value.maxAmount = itemMaxAmountConfig.Value.Value; } } } private static void ApplyPredefinedConfig() { foreach (KeyValuePair<string, Item> item in StatsManager.instance.itemDictionary) { item.Value.maxAmount = 10000; } } private static string SanitizeString(string input) { char[] array = invalidChars; foreach (char oldChar in array) { input = input.Replace(oldChar, '_'); } return input; } } [HarmonyPatch(typeof(LevelGenerator))] public class LevelGeneratorPatch { [HarmonyPostfix] [HarmonyPatch("GenerateDone")] private static void GenerateDonePatch(LevelGenerator __instance) { if (StatsManager.instance.itemDictionary != null && StatsManager.instance.itemDictionary.Count != 0 && !SemiFunc.IsNotMasterClient()) { ModLogger.LogDebug("LevelGeneratorPatch: Level generation done. Loading item config..."); ConfigManager.LoadMaxItemConfig(); } } } [HarmonyPatch(typeof(PunManager))] public class PunManagerPatch { private const float SpawnOffsetFacing = 7f; private const float SpawnOffsetHeight = 2f; private static readonly Vector3 SpawnOffset = new Vector3(0f, 2f, 7f); private static readonly Vector3 SpawnOffsetLobby = new Vector3(7f, 2f, 0f); [HarmonyPrefix] [HarmonyPatch("TruckPopulateItemVolumes")] private static void TruckPopulateItemVolumesPatch(PunManager __instance) { //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Invalid comparison between Unknown and I4 //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) ItemManager.instance.spawnedItems.Clear(); if (SemiFunc.IsNotMasterClient()) { return; } List<ItemVolume> itemVolumes = __instance.itemManager.itemVolumes; List<Item> purchasedItems = __instance.itemManager.purchasedItems; ModLogger.LogDebug($"Initial shelfVolumes: {itemVolumes.Count}, purchasedItems: {purchasedItems.Count}"); while (itemVolumes.Count > 0 && purchasedItems.Count > 0) { bool flag = false; for (int i = 0; i < purchasedItems.Count; i++) { Item item = purchasedItems[i]; ItemVolume val = itemVolumes.Find((ItemVolume v) => v.itemVolume == item.itemVolume); if ((Object)(object)val != (Object)null) { __instance.SpawnItem(item, val); itemVolumes.Remove(val); purchasedItems.RemoveAt(i); flag = true; break; } } if (!flag) { break; } } ModLogger.LogDebug($"After shelf fill: shelfVolumes: {itemVolumes.Count}, purchasedItems: {purchasedItems.Count}"); if (purchasedItems.Count > 0) { List<SpawnPoint> list = Object.FindObjectsOfType<SpawnPoint>().ToList(); ListExtension.Shuffle<SpawnPoint>((IList<SpawnPoint>)list); int num = 0; foreach (Item item2 in purchasedItems.ToList()) { if ((int)item2.itemType == 5) { ModLogger.LogInfo("Ignoring item: " + item2.itemName); continue; } if (list.Count == 0) { ModLogger.LogError("No spawn points found."); return; } Vector3 position = ((Component)list[num % list.Count]).transform.position; Vector3 val2 = (((Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelLobby) ? SpawnOffsetLobby : SpawnOffset); Vector3 position2 = position + val2; SpawnItemAtPosition(item2, position2); purchasedItems.Remove(item2); num++; } } foreach (ItemVolume itemVolume in __instance.itemManager.itemVolumes) { Object.Destroy((Object)(object)((Component)itemVolume).gameObject); } } private static void SpawnItemAtPosition(Item item, Vector3 position) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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) ((Component)ShopManager.instance.itemRotateHelper).transform.parent = ((Component)ShopManager.instance).transform; ((Component)ShopManager.instance.itemRotateHelper).transform.localRotation = item.spawnRotationOffset; Quaternion rotation = ((Component)ShopManager.instance.itemRotateHelper).transform.rotation; if (SemiFunc.IsMasterClient()) { PhotonNetwork.InstantiateRoomObject(item.prefab.ResourcePath, position, rotation, (byte)0, (object[])null); } else if (!SemiFunc.IsMultiplayer()) { Object.Instantiate<GameObject>(item.prefab.Prefab, position, rotation); } } } } namespace NoItemSpawnLimit.Logging { public enum ModLogLevel { Error, Warning, Info, Debug } public static class ModLogger { private static readonly ManualLogSource Logger = Logger.CreateLogSource("NoItemSpawnLimit"); private static bool CanLog(ModLogLevel level) { return level <= ConfigManager.CurrentLogLevel; } public static void LogFatal(object data) { if (CanLog(ModLogLevel.Error)) { Logger.LogFatal(data); } } public static void LogError(object data) { if (CanLog(ModLogLevel.Error)) { Logger.LogError(data); } } public static void LogWarning(object data) { if (CanLog(ModLogLevel.Warning)) { Logger.LogWarning(data); } } public static void LogInfo(object data) { if (CanLog(ModLogLevel.Info)) { Logger.LogInfo(data); } } public static void LogDebug(object data) { if (CanLog(ModLogLevel.Debug)) { Logger.LogDebug(data); } } } }