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 MoreStandsForShops v1.3.2
plugins/MoreStandsForShops/MoreStandsForShops.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using MoreStandsForShops.Network; using MoreStandsForShops.Patches; using MoreStandsForShops.Rewriters; using MoreStandsForShops.Shop; using MoreStandsForShops.Spawners; using MoreStandsForShops.Stands.Upgrade; using MoreStandsForShops.Truck; using MoreStandsForShops.Utilities; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.Localization; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("MoreStandsForShops")] [assembly: AssemblyDescription("More shop stands for R.E.P.O.")] [assembly: AssemblyCompany("DarkSpider90")] [assembly: AssemblyProduct("MoreStandsForShops")] [assembly: AssemblyCopyright("Copyright (c) 2026 DarkSpider90")] [assembly: ComVisible(false)] [assembly: Guid("2BE30F9F-3160-41F9-BC85-989F4333B8B2")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [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 MoreStandsForShops { public static class CleanPresetDatabase { private const string LevelPrefix = "Level Generator/Level/"; public static List<SpawnPointData> GetSpawnPoints() { List<SpawnPointData> list = new List<SpawnPointData>(); list.Add(Point("center_extract_right_rear", "Module - Shop - N - Center Extract(Clone)", 7.04f, 0.03f, -5.075f, 270f, 34, new string[1] { "Main/Level Generator/Level/Module - Shop - N - Center Extract(Clone)/WALLS/RIGHT/Not Connected/shop sign lynx" })); list.Add(Point("center_extract_right_mid", "Module - Shop - N - Center Extract(Clone)", 7.04f, 0.03f, -1.635f, 270f, 1, Array.Empty<string>())); list.Add(Point("center_extract_top_mid", "Module - Shop - N - Center Extract(Clone)", 0.471f, 0.03f, 7.04f, 180f, 1, new string[2] { "Main/Level Generator/Level/Module - Shop - N - Center Extract(Clone)/WALLS/TOP/Not Connected/Candy Shelf 2", "Main/Level Generator/Level/Module - Shop - N - Center Extract(Clone)/WALLS/TOP/Not Connected/Shop prop fridge" })); list.Add(Point("corner_stands_bottom_left", "Module - Shop - N - Corner Stands(Clone)", -1.72f, 0.03f, -7.04f, 0f, 1, new string[3] { "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/BOT/Not Connected/Shop Ice Cream Freezer", "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/BOT/Not Connected/shop sign tyre (1)", "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/BOT/Not Connected/shop sign tyre (2)" })); list.Add(Point("corner_stands_bottom_mid", "Module - Shop - N - Corner Stands(Clone)", 0.637f, 0.03f, -7.04f, 0f, 8, new string[3] { "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/BOT/Not Connected/Candy Shelf 2", "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/BOT/Not Connected/Shop Ice Cream Freezer", "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/BOT/Not Connected/shop sign tyre (1)" })); list.Add(Point("corner_stands_left_mid", "Module - Shop - N - Corner Stands(Clone)", -7.04f, 0.03f, -1.868f, 90f, 5, new string[1] { "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/LEFT/Not Connected/Shop Ice Cream Freezer (1)" })); list.Add(Point("corner_stands_right_secret", "Module - Shop - N - Corner Stands(Clone)", 7.04f, 0.03f, -1.349f, 270f, 1, new string[2] { "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/RIGHT/Not Connected/Shop Magazine Holder", "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/RIGHT/Not Connected/shop sign lynx" })); list.Add(Point("corner_stands_right_mid", "Module - Shop - N - Corner Stands(Clone)", 7.04f, 0.03f, -0.682f, 270f, 5, new string[1] { "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/RIGHT/Not Connected/Shop Magazine Holder" })); list.Add(Point("corner_stands_top_mid", "Module - Shop - N - Corner Stands(Clone)", 0.054f, 0.03f, 7.04f, 180f, 9, Array.Empty<string>())); list.Add(Point("middle_stands_left_secret", "Module - Shop - N - Middle Stands(Clone)", -7.04f, 0.03f, -1.385f, 90f, 1, new string[1] { "Main/Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/WALLS/LEFT/Not Connected/shop sign ai" })); list.Add(Point("middle_stands_left_mid", "Module - Shop - N - Middle Stands(Clone)", -7.04f, 0.03f, -0.481f, 90f, 1, new string[2] { "Main/Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/WALLS/LEFT/Not Connected/shop sign ai", "Main/Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/WALLS/LEFT/Not Connected/shop sign hotdog" })); list.Add(Point("middle_stands_right_mid", "Module - Shop - N - Middle Stands(Clone)", 7.04f, 0.03f, -0.639f, 270f, 5, new string[1] { "Main/Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/WALLS/RIGHT/Not Connected/Shop Magazine Holder" })); list.Add(Point("middle_stands_top_left", "Module - Shop - N - Middle Stands(Clone)", -5.504f, 0.03f, 7.04f, 180f, 13, new string[2] { "Main/Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/WALLS/RIGHT/Not Connected/Shop Magazine Holder", "Main/Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/WALLS/TOP/Not Connected/Shop Magazine Stand (1)" })); list.Add(Point("middle_stands_top_car_service", "Module - Shop - N - Middle Stands(Clone)", -4.184f, 0.03f, 7.04f, 180f, 1, new string[1] { "Main/Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/WALLS/TOP/Connected/Soda Machine (1)" })); list.Add(Point("middle_stands_top_mid", "Module - Shop - N - Middle Stands(Clone)", 0.051f, 0.03f, 7.04f, 180f, 13, Array.Empty<string>())); return list; } private static SpawnPointData Point(string id, string mainModule, float x, float y, float z, float yaw, int sourceCount, string[] disablePaths) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) return new SpawnPointData { VariantId = id, MainModule = "Level Generator/Level/" + mainModule, LocalPosition = new Vector3(x, y, z), LocalYaw = yaw, SourceCount = sourceCount, DisablePaths = disablePaths, RejectIfPresentPaths = Array.Empty<string>() }; } } public class SpawnPointData { public string VariantId { get; set; } public string MainModule { get; set; } public Vector3 LocalPosition { get; set; } public float LocalYaw { get; set; } public int SourceCount { get; set; } public string[] DisablePaths { get; set; } = Array.Empty<string>(); public string[] RejectIfPresentPaths { get; set; } = Array.Empty<string>(); } public static class MyPluginInfo { public const string PLUGIN_GUID = "DarkSpider90.MoreStandsForShops"; public const string PLUGIN_NAME = "MoreStandsForShops"; public const string PLUGIN_VERSION = "1.3.2"; } [BepInPlugin("DarkSpider90.MoreStandsForShops", "MoreStandsForShops", "1.3.2")] public class Plugin : BaseUnityPlugin { internal static ConfigEntry<bool> EnableMod; internal static ConfigEntry<bool> EnableAdditionalUpgradeStand; internal static ConfigEntry<bool> EnableVanillaShelfTableRewrite; internal static ConfigEntry<bool> DisableShopPoolLimit; internal static ConfigEntry<bool> KeepItemDictionaryIntact; internal static ConfigEntry<bool> DeliverEveryPurchasedCopy; internal static ConfigEntry<bool> DeliverEveryPurchasedItem; internal static ConfigEntry<bool> DebugLogs; internal static Dictionary<string, ConfigEntry<int>> ItemCounts = new Dictionary<string, ConfigEntry<int>>(); internal static Dictionary<string, ConfigEntry<int>> SameItemCopies = new Dictionary<string, ConfigEntry<int>>(); internal static Dictionary<string, ConfigEntry<int>> ItemSpawnChances = new Dictionary<string, ConfigEntry<int>>(); private static readonly string[] VanillaItemSpawnChanceNames = new string[70] { "Duct Taped Grenades", "Feather Drone", "Grenade", "Human Grenade", "Indestructible Drone", "Recharge Drone", "Roll Drone", "Rubber Duck", "Shockwave Grenade", "Stun Grenade", "Zero Gravity Drone", "Zero Gravity Orb", "Boltzap", "Explosive Mine", "Gun", "Pulse Pistol", "Shockwave Mine", "Shotgun", "Tranq Gun", "Trapzap", "Defibro", "Duck Bucket", "Frying Pan", "Phase Bridge", "Photon Blaster", "C.A.R.T.", "Energy Crystal", "Baseball Bat", "C.A.R.T. Cannon", "C.A.R.T. Laser", "Extraction Tracker", "Inflatable Hammer", "Leaf Blower", "Prodzap", "Roll Staff", "Semibot Walkies", "Sledge Hammer", "Sword", "Valuable Tracker", "Void Staff", "Zero Gravity Staff", "Autoscan Upgrade", "Crouch Rest Upgrade", "Death Head Battery Upgrade", "Extra Jump Upgrade", "Extra Life Upgrade", "Health Upgrade", "Item Resist Upgrade", "Item Value Upgrade", "Mana Regeneration Upgrade", "Map Enemy Tracker Upgrade", "Map Player Count Upgrade", "Map Player Tracker Upgrade", "Map Zoom Upgrade", "Range Upgrade", "Scout Cooldown Upgrade", "Sprint Speed Upgrade", "Sprint Usage Upgrade", "Stamina Upgrade", "Strength Upgrade", "Tumble Climb Upgrade", "Tumble Launch Upgrade", "Tumble Wings Upgrade", "Valuable Count Upgrade", "Large Health Pack (100)", "Medium Health Pack (50)", "Small Health Pack (25)", "POCKET C.A.R.T.", "Hauler", "Scout" }; private Harmony _harmony; internal static ManualLogSource Log { get; private set; } internal static Plugin Instance { get; private set; } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; LoadConfig(); VanillaShopApi.LogResolvedMembers(); ApplyPatches(); Log.LogInfo((object)"MoreStandsForShops v1.3.2 loaded."); } private void ApplyPatches() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown _harmony = new Harmony("DarkSpider90.MoreStandsForShops"); Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly()); foreach (Type type in typesFromAssembly) { try { List<MethodInfo> list = _harmony.CreateClassProcessor(type).Patch(); if ((list == null || list.Count <= 0) && DeclaresHarmonyPatchMethods(type)) { Log.LogError((object)("[Plugin] " + type.FullName + " declares Harmony patch methods but carries no [HarmonyPatch] attribute on the class itself, so none of them were applied.")); } } catch (Exception arg) { Log.LogError((object)$"[Plugin] Failed to apply patches from {type.FullName}; continuing. {arg}"); } } } private static bool DeclaresHarmonyPatchMethods(Type type) { foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type)) { if (((MemberInfo)declaredMethod).GetCustomAttribute<HarmonyPrefix>() != null || ((MemberInfo)declaredMethod).GetCustomAttribute<HarmonyPostfix>() != null || ((MemberInfo)declaredMethod).GetCustomAttribute<HarmonyTranspiler>() != null || ((MemberInfo)declaredMethod).GetCustomAttribute<HarmonyFinalizer>() != null) { return true; } } return false; } private void LoadConfig() { //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Expected O, but got Unknown //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Expected O, but got Unknown //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Expected O, but got Unknown //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Expected O, but got Unknown //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Expected O, but got Unknown //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Expected O, but got Unknown //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Expected O, but got Unknown //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Expected O, but got Unknown //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Expected O, but got Unknown //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Expected O, but got Unknown //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Expected O, but got Unknown //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Expected O, but got Unknown //IL_03c6: Unknown result type (might be due to invalid IL or missing references) //IL_03d0: Expected O, but got Unknown //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_0407: Expected O, but got Unknown //IL_0434: Unknown result type (might be due to invalid IL or missing references) //IL_043e: Expected O, but got Unknown //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_0475: Expected O, but got Unknown //IL_04a8: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Expected O, but got Unknown //IL_04df: Unknown result type (might be due to invalid IL or missing references) //IL_04e9: Expected O, but got Unknown //IL_0516: Unknown result type (might be due to invalid IL or missing references) //IL_0520: Expected O, but got Unknown //IL_054d: Unknown result type (might be due to invalid IL or missing references) //IL_0557: Expected O, but got Unknown //IL_0584: Unknown result type (might be due to invalid IL or missing references) //IL_058e: Expected O, but got Unknown //IL_05bb: Unknown result type (might be due to invalid IL or missing references) //IL_05c5: Expected O, but got Unknown //IL_05f2: Unknown result type (might be due to invalid IL or missing references) //IL_05fc: Expected O, but got Unknown //IL_0629: Unknown result type (might be due to invalid IL or missing references) //IL_0633: Expected O, but got Unknown //IL_0660: Unknown result type (might be due to invalid IL or missing references) //IL_066a: Expected O, but got Unknown EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable Mod", true, "Enable or disable the entire mod."); EnableAdditionalUpgradeStand = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable Additional Upgrade Stand", true, "Spawn a second upgrade stand in the shop."); EnableVanillaShelfTableRewrite = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable Vanilla Shelf Table Rewrite", true, "Move grenades to the lower health shelf and give vanilla table places safe adaptive item-size slots."); DisableShopPoolLimit = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Disable Shop Pool Limit", true, "Attempt the complete configured current-shop pool instead of applying vanilla's accumulated purchase-based pool limit."); KeepItemDictionaryIntact = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Keep Item Catalogue Intact", true, "Refuse requests from other mods to rebuild the game's item catalogue in the middle of a run. Such a rebuild drops every modded item, which is why modded shop purchases stop arriving in the truck."); DeliverEveryPurchasedCopy = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Deliver Every Purchased Copy", true, "Hand over every copy of an item that was paid for. The game otherwise caps a delivery at the number of copies it expects you to be able to buy - one gun, three grenades - and drops the rest without refunding them."); DeliverEveryPurchasedItem = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Deliver Every Purchased Item", true, "Use the free space inside the truck when the group buys more items of one size than the truck has places for, so nothing is left behind on the way to the level."); DebugLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Debug Logs", false, "Enable detailed debug logging for troubleshooting."); string text = "Item Counts"; ItemCounts["Upgrades Per Stand"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Upgrades Per Stand", 14, new ConfigDescription("Upgrade items per stand (0-14).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 14), Array.Empty<object>())); ItemCounts["Total Upgrades"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Total Upgrades", 28, new ConfigDescription("Total upgrade items across the vanilla stand and passive second stand (0-28).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 28), Array.Empty<object>())); ItemCounts["Drones"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Drones", 4, new ConfigDescription("Drone items to spawn (0-8).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 8), Array.Empty<object>())); ItemCounts["Power Crystals"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Power Crystals", 3, new ConfigDescription("Power crystals (0-5).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 5), Array.Empty<object>())); ItemCounts["Orbs"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Orbs", 1, new ConfigDescription("Orbs (0-3).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3), Array.Empty<object>())); ItemCounts["Grenades"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Grenades", 4, new ConfigDescription("Grenades (0-6).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 6), Array.Empty<object>())); ItemCounts["Mines"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Mines", 2, new ConfigDescription("Mines (0-3).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3), Array.Empty<object>())); ItemCounts["Melee"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Melee", 4, new ConfigDescription("Melee weapons (0-6).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 6), Array.Empty<object>())); ItemCounts["Guns"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Guns", 4, new ConfigDescription("Guns (0-6).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 6), Array.Empty<object>())); ItemCounts["Launchers"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Launchers (Staff)", 2, new ConfigDescription("Launchers/staffs (0-6).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 6), Array.Empty<object>())); ItemCounts["Tools"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Tools", 2, new ConfigDescription("Tools (0-4).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 4), Array.Empty<object>())); ItemCounts["Health Packs"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Health Packs", 3, new ConfigDescription("Health packs (0-5).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 5), Array.Empty<object>())); ItemCounts["Carts"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Carts", 2, new ConfigDescription("Carts (0-4).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 4), Array.Empty<object>())); ItemCounts["Pocket Carts"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Pocket Carts", 1, new ConfigDescription("Pocket carts (0-4).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 4), Array.Empty<object>())); ItemCounts["Vehicles"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "Vehicles", 1, new ConfigDescription("Vehicles (0-4).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 4), Array.Empty<object>())); ItemCounts["C.A.R.T. Weapons"] = ((BaseUnityPlugin)this).Config.Bind<int>(text, "C.A.R.T. Weapons", 1, new ConfigDescription("Total C.A.R.T. Cannon and C.A.R.T. Laser items (0-4).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 4), Array.Empty<object>())); string text2 = "Same Item Copies"; SameItemCopies["Upgrades"] = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "Upgrades", 3, new ConfigDescription("Max copies of the same upgrade item (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 6), Array.Empty<object>())); SameItemCopies["Drones"] = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "Drones", 2, new ConfigDescription("Max copies of the same drone (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 6), Array.Empty<object>())); SameItemCopies["Guns"] = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "Guns", 2, new ConfigDescription("Max copies of the same gun (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 6), Array.Empty<object>())); SameItemCopies["Melee"] = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "Melee", 2, new ConfigDescription("Max copies of the same melee weapon (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 6), Array.Empty<object>())); SameItemCopies["Launchers"] = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "Launchers (Staff)", 2, new ConfigDescription("Max copies of the same launcher (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 6), Array.Empty<object>())); SameItemCopies["Grenades"] = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "Grenades", 3, new ConfigDescription("Max copies of the same grenade (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 6), Array.Empty<object>())); SameItemCopies["Mines"] = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "Mines", 2, new ConfigDescription("Max copies of the same mine (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 6), Array.Empty<object>())); SameItemCopies["Health Packs"] = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "Health Packs", 2, new ConfigDescription("Max copies of the same health pack (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 6), Array.Empty<object>())); SameItemCopies["C.A.R.T. Weapons"] = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "C.A.R.T. Weapons", 1, new ConfigDescription("Max copies of the same C.A.R.T. Cannon or C.A.R.T. Laser item (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 6), Array.Empty<object>())); BindVanillaItemSpawnChanceConfigs(); } private static void BindVanillaItemSpawnChanceConfigs() { bool createdAny = false; string[] vanillaItemSpawnChanceNames = VanillaItemSpawnChanceNames; for (int i = 0; i < vanillaItemSpawnChanceNames.Length; i++) { BindItemSpawnChanceConfig(vanillaItemSpawnChanceNames[i], ref createdAny); } SaveItemSpawnChanceConfigs(createdAny, $"Created vanilla item spawn chance config entries for {ItemSpawnChances.Count} items."); } internal static void EnsureItemSpawnChanceConfigs(IEnumerable<Item> items) { if ((Object)(object)Instance == (Object)null || items == null) { return; } bool createdAny = false; foreach (Item item in items) { if (!((Object)(object)item == (Object)null)) { BindItemSpawnChanceConfig(ItemConfigName(item), ref createdAny); } } SaveItemSpawnChanceConfigs(createdAny, $"Created/updated item spawn chance config entries for {ItemSpawnChances.Count} items."); } internal static int GetItemSpawnChance(Item item) { if ((Object)(object)item == (Object)null) { return 0; } string key = ItemConfigName(item); if (!ItemSpawnChances.TryGetValue(key, out var value)) { return 100; } return value.Value; } private static void BindItemSpawnChanceConfig(string itemName, ref bool createdAny) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown if (string.IsNullOrWhiteSpace(itemName) || ItemSpawnChances.ContainsKey(itemName)) { return; } string text = BuildItemSpawnChanceConfigKey(itemName); try { ConfigEntry<int> value = ((BaseUnityPlugin)Instance).Config.Bind<int>("Item Spawn Chances", text, 100, new ConfigDescription("Relative spawn chance/weight for '" + PrintableItemName(itemName) + "'. 0 disables it in this mod's shop pools; 100 is default.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); ItemSpawnChances[itemName] = value; createdAny = true; ConfigEntry<bool> debugLogs = DebugLogs; if (debugLogs != null && debugLogs.Value && !string.Equals(text, itemName, StringComparison.Ordinal)) { Log.LogInfo((object)("[Config] Unsafe item name mapped to config key '" + text + "'.")); } } catch (Exception ex) { Log.LogWarning((object)("[Config] Could not create spawn chance setting for '" + PrintableItemName(itemName) + "'. Using default weight 100. " + ex.GetType().Name + ": " + ex.Message)); } } private static string BuildItemSpawnChanceConfigKey(string itemName) { string text = itemName.Trim(); bool flag = !string.Equals(text, itemName, StringComparison.Ordinal); string text2 = text; for (int i = 0; i < text2.Length; i++) { if (IsInvalidConfigKeyCharacter(text2[i])) { flag = true; break; } } if (!flag) { return itemName; } StringBuilder stringBuilder = new StringBuilder(text.Length); text2 = text; foreach (char c in text2) { stringBuilder.Append(IsInvalidConfigKeyCharacter(c) ? ' ' : c); } string text3 = stringBuilder.ToString().Trim(); if (string.IsNullOrWhiteSpace(text3)) { text3 = "Unnamed Item"; } return $"{text3} (MSFS-{StableConfigHash(itemName):X8})"; } private static bool IsInvalidConfigKeyCharacter(char character) { bool flag; switch (character) { case '\t': case '\n': case '"': case '\'': case '=': case '[': case '\\': case ']': flag = true; break; default: flag = false; break; } if (!flag) { return char.IsControl(character); } return true; } private static uint StableConfigHash(string value) { uint num = 2166136261u; foreach (char c in value) { num ^= c; num *= 16777619; } return num; } private static string PrintableItemName(string itemName) { StringBuilder stringBuilder = new StringBuilder(itemName.Length); foreach (char c in itemName) { stringBuilder.Append(char.IsControl(c) ? ' ' : c); } return stringBuilder.ToString().Trim(); } private static void SaveItemSpawnChanceConfigs(bool createdAny, string successMessage) { if (!createdAny) { return; } try { ((BaseUnityPlugin)Instance).Config.Save(); Log.LogInfo((object)successMessage); } catch (Exception ex) { Log.LogWarning((object)("[Config] Spawn chance settings were created in memory but could not be saved. Shop initialization will continue. " + ex.GetType().Name + ": " + ex.Message)); } } private static string ItemConfigName(Item item) { if ((Object)(object)item == (Object)null) { return "<null>"; } if (!string.IsNullOrWhiteSpace(item.itemName)) { return item.itemName; } return ((Object)item).name; } } } namespace MoreStandsForShops.Utilities { internal static class ItemDictionaryGuard { private const string VanillaCallerType = "StatsManager"; private const string VanillaCallerMethod = "RunStartStats"; private static readonly string[] PlumbingAssemblies = new string[5] { "0Harmony", "mscorlib", "System", "System.Core", "netstandard" }; private static readonly string[] DispatcherAssemblyPrefixes = new string[2] { "UnityEngine", "Unity." }; private static readonly HashSet<string> ReportedRequesters = new HashSet<string>(StringComparer.Ordinal); internal static bool IsVanillaRunStartRebuild() { StackTrace stackTrace = new StackTrace(1, fNeedFileInfo: false); for (int i = 0; i < stackTrace.FrameCount; i++) { MethodBase methodBase = stackTrace.GetFrame(i)?.GetMethod(); if (!(methodBase?.DeclaringType == null) && methodBase.DeclaringType.Name == "StatsManager" && methodBase.Name == "RunStartStats") { return true; } } return false; } internal static string DescribeRequester() { StackTrace stackTrace = new StackTrace(1, fNeedFileInfo: false); for (int i = 0; i < stackTrace.FrameCount; i++) { MethodBase methodBase = stackTrace.GetFrame(i)?.GetMethod(); Type type = methodBase?.DeclaringType; if (type == null) { continue; } Assembly assembly = type.Assembly; if (!(assembly == typeof(ItemDictionaryGuard).Assembly)) { string name = assembly.GetName().Name; if (!(name == "Assembly-CSharp") && !IsPlumbing(name)) { return name + " (" + type.Name + "." + methodBase.Name + ")"; } } } return null; } internal static bool ShouldReport(string requester) { return ReportedRequesters.Add(requester ?? "<unknown>"); } private static bool IsPlumbing(string assemblyName) { string[] plumbingAssemblies = PlumbingAssemblies; foreach (string b in plumbingAssemblies) { if (string.Equals(assemblyName, b, StringComparison.Ordinal)) { return true; } } plumbingAssemblies = DispatcherAssemblyPrefixes; foreach (string value in plumbingAssemblies) { if (assemblyName.StartsWith(value, StringComparison.Ordinal)) { return true; } } return false; } } public static class ItemVolumeHelper { private static readonly Vector3[] CrystalSlotPositions = (Vector3[])(object)new Vector3[5] { new Vector3(-0.72f, 1.68f, 0.5f), new Vector3(-0.36f, 1.68f, 0.5f), new Vector3(0f, 1.68f, 0.5f), new Vector3(0.36f, 1.68f, 0.5f), new Vector3(0.72f, 1.68f, 0.5f) }; private static readonly Vector3[] DroneSlotPositions = (Vector3[])(object)new Vector3[8] { new Vector3(-0.77f, 1.18f, 0.5f), new Vector3(-0.55f, 1.18f, 0.5f), new Vector3(-0.33f, 1.18f, 0.5f), new Vector3(-0.11f, 1.18f, 0.5f), new Vector3(0.11f, 1.18f, 0.5f), new Vector3(0.33f, 1.18f, 0.5f), new Vector3(0.55f, 1.18f, 0.5f), new Vector3(0.77f, 1.18f, 0.5f) }; public static void AssignVolumesForDroneCrystalStand(GameObject stand) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) ItemVolume[] componentsInChildren = stand.GetComponentsInChildren<ItemVolume>(true); if (componentsInChildren.Length == 0) { CreateDroneCrystalVolumes(stand); return; } Array.Sort(componentsInChildren, (ItemVolume a, ItemVolume b) => ((Component)a).transform.position.y.CompareTo(((Component)b).transform.position.y)); int num = componentsInChildren.Length / 2; for (int num2 = 0; num2 < componentsInChildren.Length; num2++) { bool flag = num2 < num; componentsInChildren[num2].itemVolume = (itemVolume)((!flag) ? 4 : 0); componentsInChildren[num2].itemSecretShopType = (itemSecretShopType)0; MoreStandsShelfVolume obj = ((Component)componentsInChildren[num2]).gameObject.GetComponent<MoreStandsShelfVolume>() ?? ((Component)componentsInChildren[num2]).gameObject.AddComponent<MoreStandsShelfVolume>(); obj.Zone = ((!flag) ? MoreStandsShelfZone.Crystal : MoreStandsShelfZone.Drone); obj.Handled = false; if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)string.Format("[ItemVolumeHelper] Volume {0} (Y={1:F3}) -> {2}", ((Object)componentsInChildren[num2]).name, ((Component)componentsInChildren[num2]).transform.position.y, (num2 < num) ? "small" : "power_crystal")); } } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ItemVolumeHelper] Assigned {num} lower volume(s) to 'small' (drones) and {componentsInChildren.Length - num} upper volume(s) to 'power_crystal'."); } } private static void CreateDroneCrystalVolumes(GameObject stand) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)stand == (Object)null)) { for (int i = 0; i < CrystalSlotPositions.Length; i++) { CreateVolumeSlot(stand.transform, $"MoreStandsForShops Crystal Slot {i + 1:00}", (itemVolume)4, MoreStandsShelfZone.Crystal, CrystalSlotPositions[i]); } for (int j = 0; j < DroneSlotPositions.Length; j++) { CreateVolumeSlot(stand.transform, $"MoreStandsForShops Drone Slot {j + 1:00}", (itemVolume)0, MoreStandsShelfZone.Drone, DroneSlotPositions[j]); } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ItemVolumeHelper] Created {CrystalSlotPositions.Length} crystal ItemVolume(s) and {DroneSlotPositions.Length} drone ItemVolume(s) on drone/crystal stand."); } } } private static ItemVolume CreateVolumeSlot(Transform parent, string name, itemVolume itemVolume, MoreStandsShelfZone zone, Vector3 localPosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0039: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); val.transform.localPosition = localPosition; val.transform.localRotation = Quaternion.identity; ItemVolume val2 = val.AddComponent<ItemVolume>(); val2.itemVolume = itemVolume; val2.itemSecretShopType = (itemSecretShopType)0; MoreStandsShelfVolume moreStandsShelfVolume = val.AddComponent<MoreStandsShelfVolume>(); moreStandsShelfVolume.Zone = zone; moreStandsShelfVolume.Handled = false; if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ItemVolumeHelper] Created {name} zone={itemVolume} local={localPosition}."); } return val2; } } public sealed class MoreStandsMultiSizeVolume : MonoBehaviour { public string GroupId; } public enum MoreStandsShelfZone { Drone, Crystal, Grenade, Health } public sealed class MoreStandsShelfVolume : MonoBehaviour { public MoreStandsShelfZone Zone; public bool Handled; } public sealed class MoreStandsUpgradeVolume : MonoBehaviour { } internal static class RepoLibCatalog { private const string ItemsTypeName = "REPOLib.Modules.Items"; private const string ExtensionsTypeName = "REPOLib.Extensions.StatsManagerExtensions"; private static bool resolved; private static PropertyInfo registeredItemsProperty; private static MethodInfo addItemMethod; private static bool reportedResolveFailure; private static readonly HashSet<string> reportedRestores = new HashSet<string>(StringComparer.Ordinal); internal static bool IsAvailable { get { Resolve(); if (registeredItemsProperty != null) { return addItemMethod != null; } return false; } } internal static int RestoreMissingItems() { Resolve(); StatsManager instance = StatsManager.instance; if (instance?.itemDictionary == null || registeredItemsProperty == null || addItemMethod == null) { return 0; } IEnumerable enumerable; try { enumerable = registeredItemsProperty.GetValue(null) as IEnumerable; } catch (Exception ex) { ReportResolveFailure("reading REPOLib.Modules.Items.RegisteredItems failed. " + ex.GetType().Name + ": " + ex.Message); return 0; } if (enumerable == null) { return 0; } List<string> list = new List<string>(); foreach (object item in enumerable) { Item val = (Item)((item is Item) ? item : null); if (val == null || (Object)(object)val == (Object)null) { continue; } string name = ((Object)val).name; if (!string.IsNullOrWhiteSpace(name) && !instance.itemDictionary.ContainsKey(name)) { try { addItemMethod.Invoke(null, new object[2] { instance, val }); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[RepoLibCatalog] Could not restore modded item '" + name + "' into StatsManager. " + ex2.GetType().Name + ": " + ex2.Message)); continue; } if (instance.itemDictionary.ContainsKey(name)) { list.Add(DescribeItem(val)); } } } if (list.Count > 0) { bool flag = false; foreach (string item2 in list) { flag |= reportedRestores.Add(item2); } string text = $"[RepoLibCatalog] Restored {list.Count} modded item(s) that REPOLib registered but that " + "were missing from StatsManager.itemDictionary: " + string.Join(", ", list) + ". Without them the shop cannot stock that content and purchased copies are lost on level load."; if (flag) { Plugin.Log.LogWarning((object)text); } else { ConfigEntry<bool> debugLogs = Plugin.DebugLogs; if (debugLogs != null && debugLogs.Value) { Plugin.Log.LogInfo((object)text); } } } else { ConfigEntry<bool> debugLogs2 = Plugin.DebugLogs; if (debugLogs2 != null && debugLogs2.Value && IsAvailable) { Plugin.Log.LogInfo((object)"[RepoLibCatalog] Every REPOLib item is present in StatsManager.itemDictionary."); } } return list.Count; } private static void Resolve() { if (resolved) { return; } resolved = true; Type type = AccessTools.TypeByName("REPOLib.Modules.Items"); Type type2 = AccessTools.TypeByName("REPOLib.Extensions.StatsManagerExtensions"); if (type == null || type2 == null) { return; } registeredItemsProperty = AccessTools.Property(type, "RegisteredItems"); addItemMethod = AccessTools.Method(type2, "AddItem", new Type[2] { typeof(StatsManager), typeof(Item) }, (Type[])null); if (registeredItemsProperty == null || addItemMethod == null) { ReportResolveFailure("RegisteredItems=" + ((registeredItemsProperty != null) ? "found" : "missing") + ", AddItem=" + ((addItemMethod != null) ? "found" : "missing")); return; } ConfigEntry<bool> debugLogs = Plugin.DebugLogs; if (debugLogs != null && debugLogs.Value) { Plugin.Log.LogInfo((object)"[RepoLibCatalog] REPOLib item registry resolved."); } } private static void ReportResolveFailure(string detail) { if (!reportedResolveFailure) { reportedResolveFailure = true; Plugin.Log.LogWarning((object)("[RepoLibCatalog] REPOLib is installed but its item registry could not be read, so modded items the game drops from StatsManager cannot be restored. " + detail)); } } private static string DescribeItem(Item item) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) string arg = (string.IsNullOrWhiteSpace(item.itemName) ? ((Object)item).name : item.itemName); return $"{arg} ({item.itemType})"; } } internal static class ScenePathUtility { public static Transform FindTransformByPath(string path) { if (string.IsNullOrWhiteSpace(path)) { return null; } return ShopSceneCache.Current.FindTransformByPath(path); } public static string GetTransformPath(Transform transform) { return ShopSceneCache.Current.GetTransformPath(transform); } public static List<string> DisableExactPaths(IEnumerable<string> paths, string logPrefix) { List<string> list = new List<string>(); HashSet<string> hashSet = new HashSet<string>(); if (paths == null) { return list; } foreach (string path in paths) { if (string.IsNullOrWhiteSpace(path) || !hashSet.Add(path)) { continue; } Transform val = FindTransformByPath(path); if ((Object)(object)val == (Object)null) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)(logPrefix + " Preset disable path not present: " + path)); } continue; } int num = DisableTree(val, list); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"{logPrefix} Disabled preset blocker: {GetTransformPath(val)} (nodes={num})"); } } return list; } private static int DisableTree(Transform root, List<string> disabled) { if ((Object)(object)root == (Object)null) { return 0; } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true); int num = 0; Transform[] array = componentsInChildren; foreach (Transform val in array) { if (!((Object)(object)val == (Object)null) && (((Component)val).gameObject.activeSelf || ((Component)val).gameObject.activeInHierarchy)) { ((Component)val).gameObject.SetActive(false); disabled.Add(GetTransformPath(val)); num++; } } return num; } public static bool HasActivePath(IEnumerable<string> paths, out string activePath) { activePath = null; if (paths == null) { return false; } foreach (string path in paths) { Transform val = FindTransformByPath(path); if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy) { activePath = GetTransformPath(val); return true; } } return false; } public static void RestoreExactPaths(IEnumerable<string> paths, string logPrefix) { if (paths == null) { return; } foreach (string item in new List<string>(paths).OrderBy(PathDepth)) { Transform val = FindTransformByPath(item); if (!((Object)(object)val == (Object)null) && !((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(true); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)(logPrefix + " Restored: " + item)); } } } } private static int PathDepth(string path) { if (string.IsNullOrEmpty(path)) { return 0; } int num = 1; for (int i = 0; i < path.Length; i++) { if (path[i] == '/') { num++; } } return num; } } internal static class ShopCatalogDiagnostics { private static readonly HashSet<string> detailedStages = new HashSet<string>(StringComparer.Ordinal); internal static void Reset() { detailedStages.Clear(); } internal static void DumpItemDictionary(string stage) { //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0112: 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_00cb: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, Item> dictionary = StatsManager.instance?.itemDictionary; if (dictionary == null) { Plugin.Log.LogWarning((object)("[ShopCatalog] " + stage + ": StatsManager.itemDictionary is null.")); return; } List<string> list = new List<string>(dictionary.Count); List<string> list2 = new List<string>(); int num = 0; int num2 = 0; foreach (KeyValuePair<string, Item> item in dictionary) { Item value = item.Value; if ((Object)(object)value == (Object)null) { num2++; list.Add(item.Key + " -> entry is null or already destroyed"); continue; } num++; string countKey; string copyKey; string text = (ShopStockCatalog.TryGetConfigKeys(value, out countKey, out copyKey) ? countKey : "<no category>"); if (text == "<no category>") { list2.Add($"{Describe(value)} [{value.itemType}]"); } list.Add($"{item.Key} | display={value.itemName} | type={value.itemType} | volume={value.itemVolume} | " + $"secretShop={value.itemSecretShopType} | disabled={value.disabled} | minPlayers={value.minPlayerCount} | " + $"maxInShop={value.maxAmountInShop} | prefab={DescribePrefab(value)} | category={text}"); } Plugin.Log.LogInfo((object)($"[ShopCatalog] {stage}: entries={dictionary.Count}, usable={num}, unusable={num2}, " + $"withoutCategory={list2.Count}.")); bool flag = detailedStages.Add(stage); if (list2.Count > 0 && flag) { Plugin.Log.LogWarning((object)($"[ShopCatalog] {stage}: {list2.Count} registered item(s) have an item type this mod has " + "no category for, so its own pools can never select them: " + string.Join(", ", list2) + ". Vanilla's placement for them is preserved instead.")); } ConfigEntry<bool> debugLogs = Plugin.DebugLogs; if (debugLogs == null || !debugLogs.Value || !flag) { return; } foreach (string item2 in list.OrderBy<string, string>((string line) => line, StringComparer.Ordinal)) { Plugin.Log.LogInfo((object)("[ShopCatalog] " + item2)); } } private static string Describe(Item item) { if (!string.IsNullOrWhiteSpace(item.itemName)) { return item.itemName; } return ((Object)item).name; } private static string DescribePrefab(Item item) { try { return ((PrefabRef<GameObject>)(object)item.prefab)?.ResourcePath ?? "<none>"; } catch (Exception ex) { return "<unreadable: " + ex.GetType().Name + ">"; } } } internal static class ShopModuleDiagnostics { internal const string LevelRootPath = "Level Generator/Level"; internal static string DescribeLevelModules() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown ShopSceneCache current = ShopSceneCache.Current; Transform val = current.FindTransformByPath("Level Generator/Level"); if ((Object)(object)val == (Object)null) { return "\"Level Generator/Level\" was not found. Loaded scenes: " + DescribeScenes() + ". Active scene roots: " + DescribeRoots(current) + "."; } List<string> list = new List<string>(); foreach (Transform item in val) { Transform val2 = item; list.Add(((Component)val2).gameObject.activeInHierarchy ? ("\"" + ((Object)val2).name + "\"") : ("\"" + ((Object)val2).name + "\" (inactive)")); } if (list.Count == 0) { return "\"Level Generator/Level\" has no child modules."; } return string.Format("{0} module(s) under \"{1}\": {2}.", list.Count, "Level Generator/Level", string.Join(", ", list)); } private static string DescribeScenes() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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) StringBuilder stringBuilder = new StringBuilder(); Scene activeScene = SceneManager.GetActiveScene(); for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); if (stringBuilder.Length > 0) { stringBuilder.Append(", "); } stringBuilder.Append($"\"{((Scene)(ref sceneAt)).name}\" (loaded={((Scene)(ref sceneAt)).isLoaded}, roots={((Scene)(ref sceneAt)).rootCount}"); stringBuilder.Append((((Scene)(ref sceneAt)).handle == ((Scene)(ref activeScene)).handle) ? ", active)" : ")"); } if (stringBuilder.Length != 0) { return stringBuilder.ToString(); } return "<none>"; } private static string DescribeRoots(ShopSceneCache cache) { string[] array = (from root in cache.Roots where (Object)(object)root != (Object)null select "\"" + ((Object)root).name + "\"").ToArray(); if (array.Length != 0) { return string.Join(", ", array); } return "<none>"; } } internal sealed class ShopSceneCache { private static ShopSceneCache _current; private readonly Dictionary<int, string> pathByInstanceId = new Dictionary<int, string>(); private readonly Dictionary<string, Transform> transformByPath = new Dictionary<string, Transform>(StringComparer.Ordinal); private readonly Dictionary<string, Transform> transformByLooseKey = new Dictionary<string, Transform>(StringComparer.OrdinalIgnoreCase); private readonly HashSet<string> reportedLooseMatches = new HashSet<string>(StringComparer.Ordinal); private readonly int sceneHandle; internal GameObject[] Roots { get; } internal Transform[] Transforms { get; } internal ItemVolume[] ItemVolumes { get; } internal Renderer[] Renderers { get; } internal static ShopSceneCache Current { get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); if (_current == null || SceneHandle.op_Implicit(_current.sceneHandle) != ((Scene)(ref activeScene)).handle) { _current = new ShopSceneCache(); } return _current; } } private ShopSceneCache() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) Scene scene = SceneManager.GetActiveScene(); sceneHandle = SceneHandle.op_Implicit(((Scene)(ref scene)).handle); Roots = ((Scene)(ref scene)).GetRootGameObjects(); Transforms = (from transform in Resources.FindObjectsOfTypeAll<Transform>() where (Object)(object)transform != (Object)null && ((Component)transform).gameObject.activeInHierarchy where ((Component)transform).gameObject.scene == scene select transform).ToArray(); ItemVolumes = (from volume in Transforms.SelectMany((Transform transform) => ((Component)transform).GetComponents<ItemVolume>()) where (Object)(object)volume != (Object)null && ((Component)volume).gameObject.activeInHierarchy select volume).ToArray(); Renderers = (from renderer in Transforms.SelectMany((Transform transform) => ((Component)transform).GetComponents<Renderer>()) where (Object)(object)renderer != (Object)null && ((Component)renderer).gameObject.activeInHierarchy select renderer).ToArray(); Dictionary<int, string> dictionary = Transforms.ToDictionary((Transform transform) => ((Object)transform).GetInstanceID(), BuildPath); Dictionary<string, int> dictionary2 = dictionary.Values.GroupBy<string, string>((string path) => path, StringComparer.Ordinal).ToDictionary<IGrouping<string, string>, string, int>((IGrouping<string, string> group) => group.Key, (IGrouping<string, string> group) => group.Count(), StringComparer.Ordinal); Transform[] transforms = Transforms; foreach (Transform val in transforms) { string text = dictionary[((Object)val).GetInstanceID()]; string text2 = ((dictionary2[text] > 1) ? BuildIndexedPath(text, val) : text); pathByInstanceId[((Object)val).GetInstanceID()] = text2; if (!transformByPath.ContainsKey(text2)) { transformByPath.Add(text2, val); } if (!transformByPath.ContainsKey(text)) { transformByPath.Add(text, val); } IndexLooseKey(text2, val); IndexLooseKey(text, val); } ConfigEntry<bool> debugLogs = Plugin.DebugLogs; if (debugLogs != null && debugLogs.Value) { Plugin.Log.LogInfo((object)($"[ShopSceneCache] Built scene cache: transforms={Transforms.Length}, " + $"itemVolumes={ItemVolumes.Length}, renderers={Renderers.Length}.")); } } internal static ShopSceneCache Rebuild() { _current = new ShopSceneCache(); return _current; } internal static void Clear() { _current = null; } internal Transform FindTransformByPath(string path) { if (string.IsNullOrWhiteSpace(path)) { return null; } string[] pathCandidates = GetPathCandidates(path); foreach (string text in pathCandidates) { if (transformByPath.TryGetValue(text, out var value) && (Object)(object)value != (Object)null) { return value; } GameObject[] roots = Roots; foreach (GameObject val in roots) { if ((Object)(object)val == (Object)null) { continue; } Transform val2 = val.transform.Find(text); if ((Object)(object)val2 != (Object)null) { return val2; } if (text.StartsWith(((Object)val).name + "/", StringComparison.Ordinal)) { string text2 = text.Substring(((Object)val).name.Length + 1); val2 = val.transform.Find(text2); if ((Object)(object)val2 != (Object)null) { return val2; } } } } pathCandidates = GetPathCandidates(path); foreach (string text3 in pathCandidates) { if (transformByLooseKey.TryGetValue(BuildLooseKey(text3), out var value2) && !((Object)(object)value2 == (Object)null)) { if (reportedLooseMatches.Add(text3)) { Plugin.Log.LogInfo((object)("[ShopSceneCache] Path \"" + text3 + "\" matched \"" + GetTransformPath(value2) + "\" by ignoring spacing and case; vanilla renamed this object.")); } return value2; } } return null; } private void IndexLooseKey(string path, Transform transform) { string key = BuildLooseKey(path); if (!transformByLooseKey.ContainsKey(key)) { transformByLooseKey.Add(key, transform); } } private static string BuildLooseKey(string path) { StringBuilder stringBuilder = new StringBuilder(path.Length); foreach (char c in path) { if (!char.IsWhiteSpace(c)) { stringBuilder.Append(c); } } return stringBuilder.ToString(); } internal string GetTransformPath(Transform transform) { if ((Object)(object)transform == (Object)null) { return "<null>"; } int instanceID = ((Object)transform).GetInstanceID(); if (pathByInstanceId.TryGetValue(instanceID, out var value)) { return value; } string text = BuildPath(transform); value = text; if (transformByPath.TryGetValue(text, out var value2) && (Object)(object)value2 != (Object)null && (Object)(object)value2 != (Object)(object)transform) { value = BuildIndexedPath(text, transform); } pathByInstanceId[instanceID] = value; if (!transformByPath.ContainsKey(value)) { transformByPath.Add(value, transform); } if (!transformByPath.ContainsKey(text)) { transformByPath.Add(text, transform); } return value; } private static string[] GetPathCandidates(string path) { string text = path.Trim().Trim('/'); if (!text.StartsWith("Main/", StringComparison.Ordinal)) { return new string[1] { text }; } return new string[2] { text, text.Substring("Main/".Length) }; } private static string BuildPath(Transform transform) { Stack<string> stack = new Stack<string>(); Transform val = transform; while ((Object)(object)val != (Object)null) { stack.Push(((Object)val).name); val = val.parent; } return string.Join("/", stack); } private static string BuildIndexedPath(string legacyPath, Transform transform) { Stack<int> stack = new Stack<int>(); Transform val = transform; while ((Object)(object)val != (Object)null) { stack.Push(val.GetSiblingIndex()); val = val.parent; } return legacyPath + "|MSFSIDX:" + string.Join(".", stack); } } internal static class StandNetworkSafety { private static readonly FieldInfo RuntimeViewIdField = typeof(PhotonView).GetField("viewIdField", BindingFlags.Instance | BindingFlags.NonPublic); internal static GameObject CloneVanillaSceneVisual(GameObject source, string context) { if ((Object)(object)source == (Object)null) { return null; } PhotonView[] componentsInChildren = source.GetComponentsInChildren<PhotonView>(true); int[] array = new int[componentsInChildren.Length]; try { for (int i = 0; i < componentsInChildren.Length; i++) { PhotonView val = componentsInChildren[i]; if (!((Object)(object)val == (Object)null)) { array[i] = val.sceneViewId; val.sceneViewId = 0; } } GameObject obj = Object.Instantiate<GameObject>(source); ClearInheritedPhotonViewIdentities(obj, context); return obj; } finally { for (int j = 0; j < componentsInChildren.Length; j++) { PhotonView val2 = componentsInChildren[j]; if ((Object)(object)val2 != (Object)null) { val2.sceneViewId = array[j]; } } } } internal static int DisableInheritedPhotonViews(GameObject standRoot, string context, bool includeChildren = true) { if ((Object)(object)standRoot == (Object)null) { return 0; } int num = 0; int num2 = 0; PhotonView[] array = (PhotonView[])(includeChildren ? ((Array)standRoot.GetComponentsInChildren<PhotonView>(true)) : ((Array)new PhotonView[1] { standRoot.GetComponent<PhotonView>() })); foreach (PhotonView val in array) { if (!((Object)(object)val == (Object)null)) { num++; ClearInheritedPhotonViewIdentity(val, context); if (((Behaviour)val).enabled) { ((Behaviour)val).enabled = false; num2++; } } } if (Plugin.DebugLogs.Value && (num > 0 || num2 > 0)) { Plugin.Log.LogInfo((object)("[" + context + "] Inherited vanilla PhotonViews made inert before stand activation: " + $"found={num}, disabled={num2}.")); } return num2; } private static void ClearInheritedPhotonViewIdentities(GameObject standRoot, string context) { if ((Object)(object)standRoot == (Object)null) { return; } PhotonView[] componentsInChildren = standRoot.GetComponentsInChildren<PhotonView>(true); foreach (PhotonView val in componentsInChildren) { if ((Object)(object)val != (Object)null) { ClearInheritedPhotonViewIdentity(val, context); } } } private static void ClearInheritedPhotonViewIdentity(PhotonView view, string context) { view.sceneViewId = 0; view.InstantiationId = 0; view.isRuntimeInstantiated = false; if (view.ViewID != 0) { if (RuntimeViewIdField == null) { throw new InvalidOperationException("[" + context + "] Cannot safely clear an inherited PhotonView identity; the PUN runtime field was not found."); } RuntimeViewIdField.SetValue(view, 0); } } internal static bool HasEnabledInheritedPhotonView(GameObject standRoot) { if ((Object)(object)standRoot == (Object)null) { return false; } PhotonView[] componentsInChildren = standRoot.GetComponentsInChildren<PhotonView>(true); foreach (PhotonView val in componentsInChildren) { if ((Object)(object)val != (Object)null && ((Behaviour)val).enabled) { return true; } } return false; } } internal static class VanillaShopApi { private const float PositionMatchSqrDistance = 0.0001f; internal static MethodInfo ShopInitialize { get; } internal static MethodInfo ShopPopulateItemVolumes { get; } internal static MethodInfo SpawnShopItem { get; } internal static MethodInfo ItemSpawnApply { get; } private static FieldInfo ItemSpawnPositionField { get; } private static int SpawnShopItemParameterCount { get; } internal static bool SpawnShopItemTakesSpawnList => SpawnShopItemParameterCount >= 5; static VanillaShopApi() { ShopInitialize = ResolveWidestOverload(typeof(ShopManager), "ShopInitialize"); ShopPopulateItemVolumes = ResolveWidestOverload(typeof(PunManager), "ShopPopulateItemVolumes"); SpawnShopItem = ResolveWidestOverload(typeof(PunManager), "SpawnShopItem"); ItemSpawnApply = ResolveWidestOverload(typeof(PunManager), "ItemSpawnApply"); MethodInfo spawnShopItem = SpawnShopItem; SpawnShopItemParameterCount = (((object)spawnShopItem != null) ? spawnShopItem.GetParameters().Length : 0); ParameterInfo[] array = ItemSpawnApply?.GetParameters(); if (array != null && array.Length == 1) { ItemSpawnPositionField = AccessTools.Field(array[0].ParameterType, "position"); } } internal static void LogResolvedMembers() { if (ShopInitialize == null) { Plugin.Log.LogError((object)"[VanillaShopApi] ShopManager.ShopInitialize was not found; shop customizations are inactive."); } if (ShopPopulateItemVolumes == null) { Plugin.Log.LogError((object)"[VanillaShopApi] PunManager.ShopPopulateItemVolumes was not found; shop stock customizations are inactive."); } if (SpawnShopItem == null) { Plugin.Log.LogError((object)"[VanillaShopApi] PunManager.SpawnShopItem was not found; controlled shelves cannot place items."); } if (ItemSpawnApply != null && ItemSpawnPositionField == null) { Plugin.Log.LogError((object)"[VanillaShopApi] PunManager.ItemSpawn has no \"position\" field; deferred table item placement is inactive."); } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[VanillaShopApi] Resolved shop API: ShopInitialize=" + Describe(ShopInitialize) + ", ShopPopulateItemVolumes=" + Describe(ShopPopulateItemVolumes) + ", SpawnShopItem=" + Describe(SpawnShopItem) + ", ItemSpawnApply=" + Describe(ItemSpawnApply) + ", " + $"deferredSpawns={SpawnShopItemTakesSpawnList}.")); } } internal static bool InvokeSpawnShopItem(PunManager punManager, ItemVolume itemVolume, List<Item> itemList, bool isSecret, object spawnList) { if (SpawnShopItem == null) { return false; } object[] parameters = ((!SpawnShopItemTakesSpawnList) ? new object[4] { itemVolume, itemList, 0, isSecret } : new object[5] { itemVolume, itemList, 0, isSecret, spawnList }); return (bool)SpawnShopItem.Invoke(punManager, parameters); } internal static bool TryGetSpawnPosition(object itemSpawn, out Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; if (itemSpawn == null || ItemSpawnPositionField == null) { return false; } if (!(ItemSpawnPositionField.GetValue(itemSpawn) is Vector3 val)) { return false; } position = val; return true; } internal static bool IsSamePosition(Vector3 left, Vector3 right) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) return Vector3.SqrMagnitude(left - right) <= 0.0001f; } private static MethodInfo ResolveWidestOverload(Type type, string name) { try { return (from method in AccessTools.GetDeclaredMethods(type) where method != null && !method.IsStatic && method.Name == name orderby method.GetParameters().Length descending select method).FirstOrDefault(); } catch (Exception arg) { Plugin.Log.LogError((object)$"[VanillaShopApi] Failed to resolve {type.Name}.{name}: {arg}"); return null; } } private static string Describe(MethodInfo method) { if (method == null) { return "<missing>"; } return method.Name + "(" + string.Join(", ", from p in method.GetParameters() select p.ParameterType.Name) + ")"; } } } namespace MoreStandsForShops.Truck { internal static class PurchaseDeliveryLimits { private static readonly Dictionary<string, int> ReportedCaps = new Dictionary<string, int>(StringComparer.Ordinal); internal static void LiftCapsForOwedCopies() { if (!Plugin.EnableMod.Value || !Plugin.DeliverEveryPurchasedCopy.Value) { return; } StatsManager instance = StatsManager.instance; if (instance?.itemsPurchased == null || instance.itemDictionary == null) { return; } foreach (KeyValuePair<string, int> item in instance.itemsPurchased) { if (item.Value > 0 && instance.itemDictionary.TryGetValue(item.Key, out var value) && !((Object)(object)value == (Object)null) && value.maxAmount < item.Value) { int maxAmount = value.maxAmount; value.maxAmount = item.Value; if (!ReportedCaps.TryGetValue(item.Key, out var value2) || value2 < item.Value) { ReportedCaps[item.Key] = item.Value; Plugin.Log.LogInfo((object)($"[PurchaseDelivery] {ItemLabel(value)}: {item.Value} copy/copies are owed but the game would " + $"only hand over {maxAmount}. Raised the delivery cap so none of them is lost.")); } } } } private static string ItemLabel(Item item) { if (!string.IsNullOrWhiteSpace(item.itemName)) { return item.itemName; } return ((Object)item).name; } } internal static class ShopCheckoutAudit { private static readonly FieldInfo ShoppingListField = AccessTools.Field(typeof(ShopManager), "shoppingList"); private static readonly FieldInfo RoomVolumeCheckField = AccessTools.Field(typeof(ItemAttributes), "roomVolumeCheck"); private static readonly FieldInfo BlockExtractionField = AccessTools.Field(typeof(ItemAttributes), "blockExtraction"); private static readonly FieldInfo InStartRoomField = AccessTools.Field(typeof(ItemAttributes), "inStartRoom"); private static readonly FieldInfo InExtractionPointField = AccessTools.Field(typeof(RoomVolumeCheck), "inExtractionPoint"); private static readonly FieldInfo InTruckField = AccessTools.Field(typeof(RoomVolumeCheck), "inTruck"); private static readonly FieldInfo MaskField = AccessTools.Field(typeof(RoomVolumeCheck), "Mask"); private static readonly List<ItemAttributes> BasketBeforeCheck = new List<ItemAttributes>(); private static readonly StringBuilder Report = new StringBuilder(); internal static void RememberBasketBeforeCheck() { BasketBeforeCheck.Clear(); if (SemiFunc.IsMasterClientOrSingleplayer() && TryGetShoppingList(out var shoppingList)) { BasketBeforeCheck.AddRange(shoppingList); } } internal static void ReportBasketPruning() { if (BasketBeforeCheck.Count == 0 || !TryGetShoppingList(out var shoppingList)) { return; } foreach (ItemAttributes item in BasketBeforeCheck) { if (!shoppingList.Contains(item)) { Plugin.Log.LogInfo((object)("[ShopCheckout] " + Describe(item) + " left the basket at the room check, so it is neither charged for nor delivered. " + DescribeRoomCheck(item))); } } Plugin.Log.LogInfo((object)($"[ShopCheckout] Basket after the room check: {shoppingList.Count} of " + $"{BasketBeforeCheck.Count} item(s) kept.")); BasketBeforeCheck.Clear(); } internal static void ReportUnregisteredItemsInTruck() { if (!Plugin.DebugLogs.Value || !SemiFunc.IsMasterClientOrSingleplayer() || !TryGetShoppingList(out var shoppingList)) { return; } ItemAttributes[] array = Object.FindObjectsByType<ItemAttributes>((FindObjectsSortMode)0); foreach (ItemAttributes val in array) { if (!((Object)(object)val == (Object)null) && !shoppingList.Contains(val)) { RoomVolumeCheck val2 = ReadRoomVolumeCheck(val); if (!((Object)(object)val2 == (Object)null) && (ReadBool(InTruckField, val2) || ReadBool(InExtractionPointField, val2))) { Plugin.Log.LogInfo((object)("[ShopCheckout] " + Describe(val) + " is standing in the truck but is not in the basket, so the checkout will not pay for it. " + DescribeRoomCheck(val))); } } } } internal static void LogShoppingList(string stage) { if (!Plugin.DebugLogs.Value || !SemiFunc.IsMasterClientOrSingleplayer()) { return; } if (!TryGetShoppingList(out var shoppingList)) { Plugin.Log.LogWarning((object)"[ShopCheckout] ShopManager.shoppingList could not be read, so the purchase audit is blank."); return; } Report.Clear(); Report.Append("[ShopCheckout] ").Append(stage).Append(": ") .Append(shoppingList.Count) .Append(" item(s) in the basket"); if (shoppingList.Count == 0) { Report.Append('.'); } else { Report.Append(" -"); for (int i = 0; i < shoppingList.Count; i++) { Report.Append((i > 0) ? ", " : " ").Append(Describe(shoppingList[i])); } Report.Append('.'); } Plugin.Log.LogInfo((object)Report.ToString()); } internal static void LogPurchaseLedger(string stage) { if (!Plugin.DebugLogs.Value || !SemiFunc.IsMasterClientOrSingleplayer()) { return; } StatsManager instance = StatsManager.instance; if (instance?.itemsPurchased == null) { return; } Report.Clear(); Report.Append("[ShopCheckout] ").Append(stage).Append(" ledger:"); bool flag = false; foreach (KeyValuePair<string, int> item in instance.itemsPurchased) { if (item.Value > 0) { flag = true; bool num = instance.itemDictionary != null && instance.itemDictionary.ContainsKey(item.Key); Report.Append(' ').Append(item.Key).Append(" x") .Append(item.Value); if (!num) { Report.Append("(MISSING FROM ITEM DICTIONARY)"); } } } if (!flag) { Report.Append(" nothing awaiting delivery."); } Plugin.Log.LogInfo((object)Report.ToString()); } private static bool TryGetShoppingList(out List<ItemAttributes> shoppingList) { shoppingList = ShoppingListField?.GetValue(ShopManager.instance) as List<ItemAttributes>; return shoppingList != null; } private static string Describe(ItemAttributes attributes) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)attributes == (Object)null) { return "<destroyed item>"; } Item item = attributes.item; if ((Object)(object)item == (Object)null) { return ((Object)attributes).name; } string text = (string.IsNullOrWhiteSpace(item.itemName) ? ((Object)item).name : item.itemName); return $"{text} (key=\"{((Object)item).name}\", {item.itemType}/{item.itemVolume})"; } private static string DescribeRoomCheck(ItemAttributes attributes) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)attributes == (Object)null) { return "The item is already destroyed."; } RoomVolumeCheck val = ReadRoomVolumeCheck(attributes); if ((Object)(object)val == (Object)null) { return "It carries no RoomVolumeCheck, so the shop can never see it in the extraction point."; } int num = val.CurrentRooms?.Count ?? (-1); string arg = ((MaskField?.GetValue(val) is LayerMask val2) ? ((LayerMask)(ref val2)).value.ToString() : "<unreadable>"); return $"rooms={num}, inExtractionPoint={ReadBool(InExtractionPointField, val)}, " + $"inTruck={ReadBool(InTruckField, val)}, mask={arg}, " + $"checkSize={val.currentSize}, checkOffset={val.CheckPosition}, " + $"scale={((Component)attributes).transform.localScale}, " + $"blockExtraction={ReadBool(BlockExtractionField, attributes)}, " + $"inStartRoom={ReadBool(InStartRoomField, attributes)}."; } private static RoomVolumeCheck ReadRoomVolumeCheck(ItemAttributes attributes) { object? obj = RoomVolumeCheckField?.GetValue(attributes); return (RoomVolumeCheck)(((obj is RoomVolumeCheck) ? obj : null) ?? ((Component)attributes).GetComponent<RoomVolumeCheck>()); } private static bool ReadBool(FieldInfo field, object target) { object obj = field?.GetValue(target); if (obj is bool) { return (bool)obj; } return false; } } internal static class TruckDeliverySlots { private const int MaxCreatedPlaces = 256; private const float GridStep = 0.45f; private const float TierStep = 0.5f; private const float PlaceSpacing = 0.34f; private static readonly Dictionary<itemVolume, int> Demand = new Dictionary<itemVolume, int>(); private static readonly Dictionary<itemVolume, int> Supply = new Dictionary<itemVolume, int>(); private static readonly List<Vector3> CandidatePlaces = new List<Vector3>(); private static readonly List<Vector3> TakenPlaces = new List<Vector3>(); private static readonly Collider[] ProbeHits = (Collider[])(object)new Collider[16]; private static readonly StringBuilder Report = new StringBuilder(); internal static void EnsureEveryPurchasedItemHasAPlace() { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.EnableMod.Value || !Plugin.DeliverEveryPurchasedItem.Value || SemiFunc.IsNotMasterClient()) { return; } ItemManager instance = ItemManager.instance; if (instance?.purchasedItems == null || instance.itemVolumes == null || instance.purchasedItems.Count == 0) { return; } MeasureDemand(instance.purchasedItems); MeasureSupply(instance.itemVolumes); if (!IsAnythingShort()) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[TruckDelivery] The truck already has a place for every purchased item."); } return; } LogBalance(instance.purchasedItems.Count); if (!TruckInterior.TryResolveUsableSpace(instance.itemVolumes, out var usableSpace, out var truck)) { Plugin.Log.LogWarning((object)"[TruckDelivery] Some purchased items have no place in the truck, and the truck's own room volume could not be measured, so no extra places were added."); return; } CollectCandidatePlaces(usableSpace); int num = 0; foreach (KeyValuePair<itemVolume, int> item in Demand) { Supply.TryGetValue(item.Key, out var value); int num2 = item.Value - value; if (num2 > 0) { int num3 = AddPlaces(instance, truck, item.Key, num2, 256 - num); num += num3; if (num3 >= num2) { Plugin.Log.LogInfo((object)($"[TruckDelivery] The truck had {value} \"{item.Key}\" place(s) for " + $"{item.Value} purchased item(s); added {num3} so none of them is left behind.")); } else { Plugin.Log.LogWarning((object)($"[TruckDelivery] {num2 - num3} purchased \"{item.Key}\" item(s) found no room in the " + "truck. They stay in the purchase list and are handed over on a later level.")); } } } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)($"[TruckDelivery] Cargo bay {((Bounds)(ref usableSpace)).center} size {((Bounds)(ref usableSpace)).size}: " + $"{CandidatePlaces.Count} candidate place(s), {num} added.")); } CandidatePlaces.Clear(); TakenPlaces.Clear(); } private static void MeasureDemand(List<Item> purchasedItems) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) Demand.Clear(); foreach (Item purchasedItem in purchasedItems) { if (!((Object)(object)purchasedItem == (Object)null) && DeservesAPlace(purchasedItem)) { Demand.TryGetValue(purchasedItem.itemVolume, out var value); Demand[purchasedItem.itemVolume] = value + 1; } } } private static bool DeservesAPlace(Item item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if ((int)item.itemVolume != 4) { return (int)item.itemType != 5; } return false; } private static void MeasureSupply(List<ItemVolume> itemVolumes) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) Supply.Clear(); TakenPlaces.Clear(); foreach (ItemVolume itemVolume in itemVolumes) { if (!((Object)(object)itemVolume == (Object)null)) { Supply.TryGetValue(itemVolume.itemVolume, out var value); Supply[itemVolume.itemVolume] = value + 1; TakenPlaces.Add(((Component)itemVolume).transform.position); } } } private static void LogBalance(int purchasedCount) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) Report.Clear(); Report.Append("[TruckDelivery] ").Append(purchasedCount).Append(" item(s) to hand over. Waiting / places in the truck:"); foreach (KeyValuePair<itemVolume, int> item in Demand) { Supply.TryGetValue(item.Key, out var value); Report.Append(' ').Append(item.Key).Append('=') .Append(item.Value) .Append('/') .Append(value); } Plugin.Log.LogInfo((object)Report.ToString()); } private static bool IsAnythingShort() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<itemVolume, int> item in Demand) { Supply.TryGetValue(item.Key, out var value); if (item.Value > value) { return true; } } return false; } private static void CollectCandidatePlaces(Bounds usableSpace) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) CandidatePlaces.Clear(); Vector3 min = ((Bounds)(ref usableSpace)).min; Vector3 max = ((Bounds)(ref usableSpace)).max; for (float num = min.y; num <= max.y; num += 0.5f) { for (float num2 = min.z; num2 <= max.z; num2 += 0.45f) { for (float num3 = min.x; num3 <= max.x; num3 += 0.45f) { CandidatePlaces.Add(new Vector3(num3, num, num2)); } } } } private static int AddPlaces(ItemManager itemManager, Transform truck, itemVolume volume, int missing, int budget) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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) //IL_003e: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) if (budget <= 0) { return 0; } float clearance = ClearanceFor(volume); int num = 0; for (int i = 0; i < CandidatePlaces.Count; i++) { if (num >= missing) { break; } if (num >= budget) { break; } Vector3 val = CandidatePlaces[i]; if (!float.IsInfinity(val.x) && !IsTooCloseToATakenPlace(val) && !IsBlockedByLevelGeometry(val, clearance)) { ItemVolume val2 = CreatePlace(val, truck, volume, num); if (!((Object)(object)val2 == (Object)null)) { itemManager.itemVolumes.Add(val2); TakenPlaces.Add(val); CandidatePlaces[i] = Vector3.positiveInfinity; num++; } } } return num; } private static ItemVolume CreatePlace(Vector3 position, Transform truck, itemVolume volume, int index) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_003a: 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) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject($"MoreStandsForShops Truck Place {volume} {index + 1:00}"); if ((Object)(object)truck != (Object)null) { val.transform.SetParent(truck, false); } val.transform.position = position; val.transform.rotation = Quaternion.identity; ItemVolume obj = val.AddComponent<ItemVolume>(); obj.itemVolume = volume; obj.itemSecretShopType = (itemSecretShopType)0; if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[TruckDelivery] Created {((Object)val).name} at {position}."); } return obj; } private static bool IsTooCloseToATakenPlace(Vector3 place) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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) //IL_0020: Unknown result type (might be due to invalid IL or missing references) float num = 0.115600005f; foreach (Vector3 takenPlace in TakenPlaces) { Vector3 val = takenPlace - place; if (((Vector3)(ref val)).sqrMagnitude < num) { return true; } } return false; } private static bool IsBlockedByLevelGeometry(Vector3 place, float clearance) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) int num = Physics.OverlapBoxNonAlloc(place + Vector3.up * clearance, Vector3.one * clearance, ProbeHits, Quaternion.identity, -1, (QueryTriggerInteraction)1); bool flag = false; for (int i = 0; i < num; i++) { Collider val = ProbeHits[i]; ProbeHits[i] = null; if (!flag && !((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).GetComponentInParent<PhysGrabObject>() != (Object)null)) { flag = true; } } return flag; } private static float ClearanceFor(itemVolume volume) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected I4, but got Unknown switch (volume - 1) { case 1: case 2: case 4: case 7: return 0.32f; case 8: return 0.45f; case 0: return 0.22f; default: return 0.15f; } } } internal static class TruckInterior { private const float SideGrowth = 0.5f; private const float GrowthBelow = 0.45f; private const float GrowthAbove = 1f; private const float WallMargin = 0.35f; private const float FloorMargin = 0.12f; private const float RoofMargin = 0.45f; private const float MinimumRoomVolume = 1.5f; internal static bool TryResolveUsableSpace(List<ItemVolume> truckPlaces, out Bounds usableSpace, out Transform truck) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) usableSpace = default(Bounds); Bounds room; bool flag = TryResolveTruckRoom(out room, out truck); if (TryResolveAreaAroundPlaces(truckPlaces, out var aroundPlaces)) { usableSpace = (flag ? Intersect(aroundPlaces, Inset(room)) : aroundPlaces); return IsUsable(usableSpace); } if (!flag) { return false; } usableSpace = Inset(room); return IsUsable(usableSpace); } private static bool TryResolveAreaAroundPlaces(List<ItemVolume> truckPlaces, out Bounds aroundPlaces) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //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) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) aroundPlaces = default(Bounds); if (truckPlaces == null) { return false; } bool flag = false; foreach (ItemVolume truckPlace in truckPlaces) { if (!((Object)(object)truckPlace == (Object)null)) { if (!flag) { aroundPlaces = new Bounds(((Component)truckPlace).transform.position, Vector3.zero); flag = true; } else { ((Bounds)(ref aroundPlaces)).Encapsulate(((Component)truckPlace).transform.position); } } } if (!flag) { return false; } Vector3 min = ((Bounds)(ref aroundPlaces)).min - new Vector3(0.5f, 0.45f, 0.5f); Vector3 max = ((Bounds)(ref aroundPlaces)).max + new Vector3(0.5f, 1f, 0.5f); aroundPlaces = FromCorners(min, max); return true; } private static bool TryResolveTruckRoom(out Bounds room, out Transform truck) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) room = default(Bounds); truck = null; float num = 0f; RoomVolume[] array = Object.FindObjectsByType<RoomVolume>((FindObjectsSortMode)0); foreach (RoomVolume val in array) { if ((Object)(object)val == (Object)null || !val.Truck) { continue; } Collider val2 = ((Component)val).GetComponent<Collider>() ?? ((Component)val).GetComponentInChildren<Collider>(true); if (!((Object)(object)val2 == (Object)null)) { Bounds bounds = val2.bounds; Vector3 size = ((Bounds)(ref bounds)).size; float num2 = size.x * size.y * size.z; if (!(num2 < 1.5f) && !(num2 <= num)) { num = num2; room = bounds; truck = ((Component)val).transform; } } } return num > 0f; } private static Bounds Inset(Bounds room) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) Vector3 min = ((Bounds)(ref room)).min + new Vector3(0.35f, 0.12f, 0.35f); Vector3 max = ((Bounds)(ref room)).max - new Vector3(0.35f, 0.45f, 0.35f); return FromCorners(min, max); } private static Bounds Intersect(Bounds left, Bounds right) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) return FromCorners(Vector3.Max(((Bounds)(ref left)).min, ((Bounds)(ref right)).min), Vector3.Min(((Bounds)(ref left)).max, ((Bounds)(ref right)).max)); } private static Bounds FromCorners(Vector3 min, Vector3 max) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) Bounds result = default(Bounds); ((Bounds)(ref result)).SetMinMax(min, max); return result; } private static bool IsUsable(Bounds space) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) Vector3 size = ((Bounds)(ref space)).size; if (size.x > 0f && size.y > 0f) { return size.z > 0f; } return false; } } } namespace MoreStandsForShops.Stands.Upgrade { internal sealed class UpgradeStandRerollController : MonoBehaviour, IOnEventCallback, IInRoomCallbacks { private enum RerollState { Idle, Holding, Rollback, PressFail, PressSucceed, CloseHatch, RollStart, Rolling, RollEnd, OpenHatch, WaitingForHost, Broken } private readonly struct CachedUpgrade { internal readonly ItemUpgrade Upgrade; internal readonly Item Item; internal readonly Vector3 Position; internal readonly Quaternion Rotation; internal CachedUpgrade(ItemUpgrade upgrade, Item item, Vector3 position, Quaternion rotation) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) Upgrade = upgrade; Item = item; Position = position; Rotation = rotation; } } private readonly struct PendingReplacement { internal readonly ItemUpgrade OriginalUpgrade; internal readonly Item Item; internal readonly Vector3 Position; internal readonly Quaternion Rotation; internal PendingReplacement(ItemUpgrade originalUpgrade, Item item, Vector3 position, Quaternion rotation) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) OriginalUpgrade = originalUpgrade; Item = item; Position = position; Rotation = rotation; } } private sealed class PreparedReplacement { private readonly GameObject _gameObject; private readonly Vector3 _position; private readonly Quaternion _rotation; private readonly Rigidbody _body; private readonly PhysGrabObject _grabObject; private readonly bool _originalIsKinematic; private readonly bool _originalDetectCollisions; private readonly RigidbodyConstraints _originalConstraints; internal GameObject GameObject => _gameObject; internal PreparedReplacement(GameObject gameObject, Vector3 position, Quaternion rotation) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: 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) _gameObject = gameObject ?? throw new ArgumentNullException("gameObject"); _position = position; _rotation = rotation; _grabObject = gameObject.GetComponent<PhysGrabObject>() ?? gameObject.GetComponentInChildren<PhysGrabObject>(true); _body = (((Object)(object)_grabObject != (Object)null && (Object)(object)_grabObject.rb != (Object)null) ? _grabObject.rb : (gameObject.GetComponent<Rigidbody>() ?? gameObject.GetComponentInChildren<Rigidbody>(true))); _originalIsKinematic = (Object)(object)_body != (Object)null && _body.isKinematic; _originalDetectCollisions = (Object)(object)_body == (Object)null || _body.detectCollisions; _originalConstraints = (RigidbodyConstraints)(((Object)(object)_body != (Object)null) ? ((int)_body.constraints) : 0); MaintainStagedPose(); } internal bool MaintainStagedPose() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_gameObject == (Object)null) { return false; } if ((Object)(object)_grabObject != (Object)null) { _grabObject.OverrideKinematic(0.25f); } else if ((Object)(object)_body != (Object)null) { _body.isKinematic = true; } if ((Object)(object)_body != (Object)null) { _body.detectCollisions = false; } Vector3 val = _gameObject.transform.position - _position; if (((Vector3)(ref val)).sqrMagnitude > 1E-06f || Quaternion.Angle(_gameObject.transform.rotation, _rotation) > 0.05f) { ApplyFinalPose(); } return true; } internal void ReleaseAtFinalPose() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_gameObject == (Object)null) { return; } ApplyFinalPose(); Physics.SyncTransforms(); if (!((Object)(object)_body == (Object)null)) { _body.constraints = _originalConstraints; _body.detectCollisions = _originalDetectCollisions; if ((Object)(object)_grabObject == (Object)null) { _body.isKinematic = _originalIsKinematic; } } } internal bool TrySettleAfterVanillaEnable() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_gameObject == (Object)null || (Object)(object)_body == (Object)null) { return true; } if ((Object)(object)_grabObject != (Object)null && _body.isKinematic) { return false; } ApplyFinalPose(); Physics.SyncTransforms(); if (!_body.isKinematic) { _body.velocity = Vector3.zero; _body.angularVelocity = Vector3.zero; _body.Sleep(); } return true; } private void ApplyFinalPose() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result ty