using 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? RemoveSpawnLimit; private static readonly Dictionary> itemMaxAmountConfigs = new Dictionary>(); private static ConfigEntry? 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("General", "RemoveSpawnLimit", true, "Remove item spawn limit"); LogLevel = config.Bind("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 item in StatsManager.instance.itemDictionary) { if (!itemMaxAmountConfigs.ContainsKey(item.Key)) { int maxAmount = item.Value.maxAmount; string text = SanitizeString(item.Key); ConfigEntry value = _config.Bind("ItemLimits", text, maxAmount, new ConfigDescription("Max amount for item '" + item.Key + "'", (AcceptableValueBase)(object)new AcceptableValueRange(0, 10000), Array.Empty())); 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> 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 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 itemVolumes = __instance.itemManager.itemVolumes; List 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 list = Object.FindObjectsOfType().ToList(); ListExtension.Shuffle((IList)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(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); } } } }