Decompiled source of Polyfill v0.11.16

Plugins/Polyfill.Boot.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Melons;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using Polyfill.Boot;
using Polyfill.Bridges;
using Polyfill.Bridges.Steps.S0_4_5f2_To_0_4_6f5;
using Polyfill.Contract;
using Polyfill.Core;
using Polyfill.Dynamic;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Plugin), "Polyfill.Boot", "0.11.16", "DooDesch", "https://github.com/DooDesch-Mods/ScheduleOne-Polyfill")]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: MelonPriority(int.MinValue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("DooDesch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © DooDesch")]
[assembly: AssemblyFileVersion("0.11.16.0")]
[assembly: AssemblyInformationalVersion("0.11.16+a991f1874ad4639ca4259d22a7773c7b8489caa5")]
[assembly: AssemblyProduct("Polyfill.Boot")]
[assembly: AssemblyTitle("Polyfill.Boot")]
[assembly: AssemblyVersion("0.11.16.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 DooDesch
{
	internal static class ModVersion
	{
		internal const string Current = "0.11.16";
	}
}
namespace Polyfill.Bridges
{
	internal sealed class Bridge
	{
		internal string Assembly;

		internal string DeclaringType;

		internal string OldName;

		internal int ParameterCount;

		internal string Because;

		internal Func<ModuleDefinition, TypeDefinition, MethodDefinition> Emit;

		internal string Creates;

		internal string[] ParameterTypes;

		internal BridgeSet Set;

		internal bool AllowOverload;

		internal bool Unprompted;

		internal string Id
		{
			get
			{
				string text = DeclaringType ?? "";
				int num = text.LastIndexOfAny(new char[2] { '.', '/' });
				if (num >= 0)
				{
					text = text.Substring(num + 1);
				}
				string text2 = (OldName ?? "").Replace("get_", "get-").Replace("set_", "set-");
				string text3 = (text + "-" + text2).ToLowerInvariant();
				string[] parameterTypes = ParameterTypes;
				if (parameterTypes != null && parameterTypes.Length > 0)
				{
					string text4 = ParameterTypes[0];
					int num2 = text4.LastIndexOfAny(new char[2] { '.', '/' });
					text3 = text3 + "-" + ((num2 >= 0) ? text4.Substring(num2 + 1) : text4).ToLowerInvariant();
				}
				return text3;
			}
		}

		internal bool Fits(IReadOnlyList<string> parameterTypes)
		{
			if (ParameterTypes == null)
			{
				return true;
			}
			if (parameterTypes == null || parameterTypes.Count != ParameterTypes.Length)
			{
				return false;
			}
			for (int i = 0; i < ParameterTypes.Length; i++)
			{
				if (!string.Equals(ParameterTypes[i], parameterTypes[i], StringComparison.Ordinal))
				{
					return false;
				}
			}
			return true;
		}

		internal bool Verified(GameVersion game)
		{
			if (Set != null)
			{
				return Set.VerifiedRange.Allows(game);
			}
			return true;
		}
	}
	internal sealed class TypeRename
	{
		internal string Assembly;

		internal string OldFullName;

		internal string NewFullName;

		internal string Because;

		internal bool ByNativeClass;

		internal Answer[] Answers;

		internal BridgeSet Set;
	}
	internal sealed class Answer
	{
		internal string Name;

		internal string Returns;

		internal string[] Takes;

		internal Func<ModuleDefinition, TypeDefinition, TypeDefinition, MethodDefinition> Emit;
	}
	internal abstract class BridgeSet
	{
		private List<Bridge> _bridges;

		private List<TypeRename> _renames;

		private VersionRange _verified;

		internal abstract string Step { get; }

		internal abstract string From { get; }

		internal abstract string VerifiedTo { get; }

		internal IReadOnlyList<TypeRename> Renames
		{
			get
			{
				if (_renames != null)
				{
					return _renames;
				}
				_renames = new List<TypeRename>();
				foreach (TypeRename item in DeclareRenames())
				{
					if (item != null)
					{
						item.Set = this;
						_renames.Add(item);
					}
				}
				return _renames;
			}
		}

		internal IReadOnlyList<Bridge> Bridges
		{
			get
			{
				if (_bridges != null)
				{
					return _bridges;
				}
				_bridges = new List<Bridge>();
				foreach (Bridge item in Declare())
				{
					if (item != null)
					{
						item.Set = this;
						_bridges.Add(item);
					}
				}
				return _bridges;
			}
		}

		internal VersionRange VerifiedRange => _verified ?? (_verified = VersionRange.Parse(From + ".." + VerifiedTo));

		internal abstract IEnumerable<Bridge> Declare();

		internal virtual IEnumerable<TypeRename> DeclareRenames()
		{
			return Array.Empty<TypeRename>();
		}
	}
	internal static class Registry
	{
		private static readonly BridgeSet[] Sets = new BridgeSet[1]
		{
			new Set()
		};

		internal static IEnumerable<BridgeSet> All => Sets;

		internal static IEnumerable<Bridge> Bridges()
		{
			BridgeSet[] sets = Sets;
			foreach (BridgeSet bridgeSet in sets)
			{
				foreach (Bridge bridge in bridgeSet.Bridges)
				{
					yield return bridge;
				}
			}
		}

		internal static Bridge Find(string assembly, string declaringType, string oldName, int parameterCount, IReadOnlyList<string> parameterTypes = null)
		{
			Bridge bridge = null;
			foreach (Bridge item in Bridges())
			{
				if (item.OldName != oldName || item.DeclaringType != declaringType || item.ParameterCount != parameterCount || !string.Equals(item.Assembly, assembly, StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				if (item.ParameterTypes == null)
				{
					if (bridge == null)
					{
						bridge = item;
					}
				}
				else if (item.Fits(parameterTypes))
				{
					return item;
				}
			}
			if (parameterTypes != null)
			{
				foreach (Bridge item2 in Bridges())
				{
					if (item2.OldName == oldName && item2.DeclaringType == declaringType && item2.ParameterCount == parameterCount && item2.ParameterTypes != null && string.Equals(item2.Assembly, assembly, StringComparison.OrdinalIgnoreCase))
					{
						return null;
					}
				}
			}
			return bridge;
		}

		internal static Bridge FindByName(string assembly, string declaringType, string name, int parameterCount)
		{
			Bridge bridge = null;
			foreach (Bridge item in Bridges())
			{
				if (!(item.OldName != name) && !(item.DeclaringType != declaringType) && string.Equals(item.Assembly, assembly, StringComparison.OrdinalIgnoreCase) && (parameterCount < 0 || item.ParameterCount == parameterCount))
				{
					if (bridge != null)
					{
						return null;
					}
					bridge = item;
				}
			}
			return bridge;
		}

		internal static Bridge Creator(string assembly, string typeFullName)
		{
			Bridge bridge = null;
			foreach (Bridge item in Bridges())
			{
				if (!(item.Creates != typeFullName) && string.Equals(item.Assembly, assembly, StringComparison.OrdinalIgnoreCase))
				{
					if (bridge != null)
					{
						return null;
					}
					bridge = item;
				}
			}
			return bridge;
		}

		internal static TypeRename FindType(string assembly, string oldFullName)
		{
			BridgeSet[] sets = Sets;
			for (int i = 0; i < sets.Length; i++)
			{
				foreach (TypeRename rename in sets[i].Renames)
				{
					if (rename.OldFullName == oldFullName && string.Equals(rename.Assembly, assembly, StringComparison.OrdinalIgnoreCase))
					{
						return rename;
					}
				}
			}
			return null;
		}

		internal static string PastTheHorizon(GameVersion game)
		{
			if (!game.IsKnown)
			{
				return null;
			}
			GameVersion gameVersion = GameVersion.Unknown;
			BridgeSet[] sets = Sets;
			for (int i = 0; i < sets.Length; i++)
			{
				GameVersion gameVersion2 = GameVersion.Parse(sets[i].VerifiedTo);
				if (!gameVersion.IsKnown || gameVersion2 > gameVersion)
				{
					gameVersion = gameVersion2;
				}
			}
			if (!gameVersion.IsKnown || game <= gameVersion)
			{
				return null;
			}
			return $"Schedule I {game} is newer than anything these repairs were read against ({gameVersion}). " + "They still run: each one checks the game you have before it does anything. What no longer fits is named in the log and in `polyfillexport`, which is what turns it into an update.";
		}
	}
}
namespace Polyfill.Bridges.Steps.S0_4_5f2_To_0_4_6f5
{
	internal sealed class Set : BridgeSet
	{
		private const string Stations = "Il2CppScheduleOne.UI.Stations.";

		private const string StationSweep = "0.4.6 factored the station screens onto a shared StationInterface<T> base and renamed the four that still said Canvas; same members, same namespace, one word different";

		private const string StationOwner = "the screen's own station was called after the station (PackagingStationCanvas.PackagingStation, MixingStationCanvas.MixingStation) and 0.4.6 calls both Station - the other five screens kept theirs, so this is two names and not a pattern";

		private static readonly List<TypeRename> Renamed_ = new List<TypeRename>
		{
			Pair("Il2CppScheduleOne.UI.Stations.MixingStationCanvas", "Il2CppScheduleOne.UI.Stations.MixingStationInterface"),
			Pair("Il2CppScheduleOne.UI.Stations.ChemistryStationCanvas", "Il2CppScheduleOne.UI.Stations.ChemistryStationInterface"),
			Pair("Il2CppScheduleOne.UI.Stations.CauldronCanvas", "Il2CppScheduleOne.UI.Stations.CauldronInterface"),
			Pair("Il2CppScheduleOne.UI.Stations.DryingRackCanvas", "Il2CppScheduleOne.UI.Stations.DryingRackInterface"),
			new TypeRename
			{
				Assembly = "Assembly-CSharp",
				OldFullName = "Il2CppScheduleOne.UI.MainMenu.MainMenuScreen",
				NewFullName = "Il2CppScheduleOne.UI.MainMenu.MenuScreen",
				Because = "the base class of every main-menu screen was renamed in place: 0.4.5f2 has ContinueScreen : MainMenuScreen, 0.4.6f13 has ContinueScreen : MenuScreen, and MenuScreen is the only type of that name on the build"
			},
			new TypeRename
			{
				Assembly = "Assembly-CSharp",
				OldFullName = "Il2CppScheduleOne.UI.Handover.HandoverScreenPriceSelector",
				NewFullName = "Il2CppScheduleOne.UI.AmountSelector",
				Because = "the price control became the game's general amount box in 0.4.6 and moved out of the handover namespace; HandoverScreen.PriceSelector is an AmountSelector now"
			},
			new TypeRename
			{
				Assembly = "Assembly-CSharp",
				OldFullName = "Il2CppScheduleOne.UI.InputPromptsCanvas",
				NewFullName = "Il2CppScheduleOne.UI.Input.InputPromptsManager",
				ByNativeClass = true,
				Answers = new Answer[4]
				{
					new Answer
					{
						Name = "LoadModule",
						Takes = new string[1] { "System.String" },
						Emit = EmitLoadModule
					},
					new Answer
					{
						Name = "UnloadModule",
						Emit = EmitUnloadModule
					},
					new Answer
					{
						Name = "get_currentModuleLabel",
						Returns = "System.String",
						Emit = EmitCurrentModuleLabel
					},
					new Answer
					{
						Name = "set_currentModuleLabel",
						Takes = new string[1] { "System.String" }
					}
				},
				Because = "InputPromptsCanvas is gone since 0.4.6f5 and InputPromptsManager took over with a panel dictionary instead of one module slot - so the name is put back around the manager's native class, and the three members it needs call the manager, keeping the id they loaded because the manager has no current one"
			}
		};

		internal const string StackLabel = "Polyfill";

		private const string Npc = "Il2CppScheduleOne.NPCs.NPC";

		private const string Inv = "Il2CppScheduleOne.NPCs.NPCInventory";

		private static readonly string[] BasicInfo = new string[2] { "NPCData", "BasicInfo" };

		private static readonly string[] Appearance = new string[2] { "NPCData", "Appearance" };

		private static readonly string[] Interaction = new string[2] { "NPCData", "Interaction" };

		private static readonly string[] Messaging = new string[2] { "NPCData", "Messaging" };

		private const string SpeedController = "Il2CppScheduleOne.NPCs.NPCSpeedController";

		private static readonly string[] Inventory = new string[3] { "_npc", "NPCData", "Inventory" };

		private const bool Write = true;

		private const bool Read = false;

		private static readonly string[] NoParameters = Array.Empty<string>();

		private const string Storage = "Il2CppScheduleOne.UI.StorageMenu";

		private const string Owner = "Il2CppScheduleOne.ItemFramework.IItemSlotOwner";

		private const string Text = "System.String";

		private static readonly object[] OneCallback = new object[1];

		private const string Speed = "npc.NPCData.Movement, which is where NPCMovement's own getter reads it from (NPCMovement.cs:170-172)";

		private const string StationCanvas = "0.4.6 pulled the canvas off every station screen into the shared StationInterface<T> base and renamed it _canvas";

		private const string Avatar = "Il2CppScheduleOne.AvatarFramework.Avatar";

		private const string PlayerType = "Il2CppScheduleOne.PlayerScripts.Player";

		private const string PlayerToggle = "Player.cs:1423-1441 until 0.4.5f2; 0.4.6 deleted both and rewrote its own three callers to register a UI element instead, leaving every line these ran still there";

		private const string Number = "System.Single";

		private const string Pickpocketed = "NPCInventory.cs:40 until 0.4.5f2; the same InteractableObject under the name the private field carries now, which NPCInventory.cs:338-348 sets the pickpocket state on";

		private const string ShapeKeys = "bodyOnly stopped the method before the accessory loop; 0.4.6 dropped the flag and always runs that loop, so the two-argument form is what passing false always did (Avatar.cs:292-297)";

		private const string NameSplit = "NPC.cs:63-69 until 0.4.5f2, now BasicInfo.cs:4-7";

		private const string Hideable = "NPC.cs:130 until 0.4.5f2, now Messaging.cs:11 - the same default and the same use, moved into the NPCData object with the rest of the per-NPC settings";

		private const string Summon = "NPC.cs:116 until 0.4.5f2, now Interaction.cs:8 - and the game reads it from there in NPCEnterableBuilding.cs:96";

		private const string SlotCount = "NPCInventory.cs:45 until 0.4.5f2, now Inventory.InventorySlotCount, which NPCInventory.cs:62 builds the slots from";

		private const string Renamed = "NPCInventory.cs:51-65 until 0.4.5f2; the value kept its meaning and lost its old name in Inventory.cs";

		private const string Pickpocket = "NPCInventory.cs:47 until 0.4.5f2, now Inventory.CanBePickpocketed, read at NPCInventory.cs:372";

		private const string Counteroffer = "Il2CppScheduleOne.UI.Phone.CounterofferInterface";

		private static readonly string[] PriceSelector = new string[1] { "PriceSelector" };

		private const string PriceSelectorType = "Il2CppScheduleOne.UI.AmountSelector";

		private static readonly string[] DealerData = new string[1] { "DealerData" };

		private const string CutMoved = "Dealer.cs:102 until 0.4.5f2, now DealerNPCData.SalesCutPercentage (:20) - and the payout reads it from there with the same expression the old field was used in (Dealer.cs:1892 against :2031 in 0.4.5f2)";

		private const string SigningMoved = "Dealer.cs:100 until 0.4.5f2, now DealerNPCData.cs:17 with the same 500 default, copied across when a dealer's data is built (:40) - the same move DealerType made";

		private const string Movement = "Il2CppScheduleOne.NPCs.NPCMovement";

		private const string Amount = "Il2CppScheduleOne.UI.AmountSelector";

		private const string CompassElement = "Il2CppScheduleOne.UI.Compass.CompassManager/Element";

		private const string PriceControl = "the handover price control became the game's general amount box in 0.4.6; Price is SelectedAmount and SetPrice is SetAmount, same values (AmountSelector.cs)";

		private static readonly string[] NpcSpeed = new string[3] { "npc", "NPCData", "Movement" };

		private static readonly string[] NpcHealthData = new string[3] { "npc", "NPCData", "Health" };

		private static readonly string[] SupplierData = new string[1] { "SupplierData" };

		private const string ShopListings = "the same PhoneShopInterface.Listing[]; 0.4.6 keeps it on SupplierNPCData and Supplier.SupplierData is the way in";

		private const string LobbyType = "Il2CppScheduleOne.Networking.Lobby";

		private const string Blackjack = "Il2CppScheduleOne.Casino.UI.BlackjackInterface";

		private const string RouletteTable = "Il2CppScheduleOne.Casino.UI.RTBInterface";

		private static readonly string[] BetPanel = new string[1] { "BetPanel" };

		private const string BetMoved = "the betting half of a casino screen became CasinoGameBetPanel, which every casino game shares; the screen's own BetPanel is the way in (CasinoGameBetPanel.cs:20,23,26, 38, 103)";

		private const string PlayerCameraType = "Il2CppScheduleOne.PlayerScripts.PlayerCamera";

		private const string MouseControllerType = "Il2CppScheduleOne.Input.MouseController";

		private static readonly string[] OneBool = new string[1] { "System.Boolean" };

		private const string CursorMoved = "the cursor flag left PlayerCamera for MouseController, which 0.4.6 added and which its LockMouse and FreeMouse write the same way the camera's used to (MouseController.cs:9,13,25)";

		private const string PlayerManager = "Il2CppScheduleOne.PlayerScripts.PlayerManager";

		private const string PlayerLookups = "0.4.6 moved the player lookups off Player onto PlayerManager with the same names, parameters and return type; the game's own callers went with them (Supplier.cs:236 is one)";

		private const string StructArrayName = "Il2CppStructArray`1";

		private const string PriceBox = "CounterofferInterface.cs:20 held the price box directly until 0.4.5f2; 0.4.6 wraps it in an AmountSelector, whose _inputField is the same control (AmountSelector.cs:19)";

		private const string Emitter = "Il2CppScheduleOne.VoiceOver.VOEmitter";

		private const string Camera = "Il2CppScheduleOne.PlayerScripts.PlayerCamera";

		private const string AmountSelector = "Il2CppScheduleOne.UI.AmountSelector";

		private static readonly string[] NoHops = new string[0];

		private const string BotanistConfig = "Il2CppScheduleOne.Management.BotanistConfiguration";

		private const string PriceRenamed = "0.4.6 turned the handover price selector into the general amount box, and Price into SelectedAmount on it - same float, same meaning (AmountSelector.cs:27)";

		private const string Packaging = "Il2CppScheduleOne.ObjectScripts.PackagingStation";

		private const string Bool = "System.Boolean";

		private const string GameplayMenu = "Il2CppScheduleOne.UI.GameplayMenu";

		private const string SleepCanvas = "Il2CppScheduleOne.UI.SleepCanvas";

		private const string DealerType = "Il2CppScheduleOne.Economy.Dealer";

		private const string DealerDataType = "Il2CppScheduleOne.NPCs.Framework.DealerNPCData";

		private const string DealerCut = "0.4.6 moved the dealer's cut onto the data object the NPC carries: 0.4.5f2 had a serialized Cut field on Dealer defaulting to 0.2f, 0.4.6f13 has DealerNPCData.SalesCutPercentage with the same type and the same default, and the consumer line is the same expression with one identifier swapped - ChangeCash(payment * (1f - Cut)) became ChangeCash(payment * (1f - DealerData.SalesCutPercentage)) (Dealer.cs:132, DealerNPCData.cs:17)";

		private const string Clipboard = "Il2CppScheduleOne.Tools.ManagementClipboard";

		private const string Customer = "Il2CppScheduleOne.Economy.CustomerData";

		private const string VoDatabase = "VOEmitter.cs:12 until 0.4.5f2 held one serialized Database field, and Play() read it; 0.4.6 split it into a default and a current one and Play() reads _currentDatabase";

		private const string VoPitch = "VOEmitter.cs:15 until 0.4.5f2; Play() multiplied PitchMultiplier by the runtime one, and 0.4.6 multiplies _defaultPitch by _runtimePitchMultiplier in the same expression";

		private const string Crosshair = "the crosshair became a parameter; true is what the call did before it existed (PlayerCamera.cs:483-490)";

		private static readonly List<Bridge> All = new List<Bridge>
		{
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.NPCs.NPCMovement",
				OldName = "get_MovementSpeedScale",
				ParameterCount = 0,
				Because = "the field was folded into UpdateSpeed(); the same value is now SpeedController.ActiveSpeedControl.speed * SpeedController.SpeedMultiplier",
				Emit = EmitMovementSpeedScaleGetter
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.NPCs.NPCMovement",
				OldName = "set_MovementSpeedScale",
				ParameterCount = 1,
				Because = "writing the field wrote the BASE speed the controller derived; the base slot is now a priority-0 entry on the speed stack, which everything the game does outranks",
				Emit = EmitMovementSpeedScaleSetter
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.NPCs.NPC",
				OldName = "OverrideAggression",
				ParameterCount = 1,
				Because = "Aggression became a read-only view over AggressionController; vanilla's own migration of this call is MethInstance.cs:51",
				Emit = EmitOverrideAggression
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.Management.ManagementInterface",
				OldName = "get_NPCSelector",
				ParameterCount = 0,
				Because = "0.4.6 removed the NPC selector screen with no replacement and left its own stub behind (NPCFieldUI.cs:79 logs \"NPCSelector not implemented\"). The only use is a null check for \"is that screen open\", and a screen that does not exist is not open - see Removed.cs for why answering costs less than refusing",
				Creates = "Il2CppScheduleOne.UI.Management.NPCSelector",
				Emit = Removed.EmitNpcSelectorGetter
			},
			Moved("Il2CppScheduleOne.UI.Phone.Delivery.DeliveryApp", "StatusDisplayPrefab", write: false, NoHops, "_deliveryStatusDisplayPrefab", "the same DeliveryStatusDisplay prefab, kept in a private field now and instantiated into the same StatusDisplayContainer (DeliveryApp.cs:332)"),
			Moved("Il2CppScheduleOne.Management.BotanistConfiguration", "AssignedStations", write: false, NoHops, "Assigns", "BotanistConfiguration.cs:27 is the same ObjectListField, taking the same pots, racks and beds (:15) with the same cap (:61); only the name moved"),
			Unprompted(Moved("Il2CppScheduleOne.UI.AmountSelector", "Price", write: false, NoHops, "SelectedAmount", "0.4.6 turned the handover price selector into the general amount box, and Price into SelectedAmount on it - same float, same meaning (AmountSelector.cs:27)")),
			Unprompted(Moved("Il2CppScheduleOne.UI.AmountSelector", "Price", write: true, NoHops, "SelectedAmount", "0.4.6 turned the handover price selector into the general amount box, and Price into SelectedAmount on it - same float, same meaning (AmountSelector.cs:27)")),
			Moved("Il2CppScheduleOne.NPCs.NPC", "ID", write: true, BasicInfo, "ID", "NPC.cs:63-69 until 0.4.5f2, now BasicInfo.cs:4-7"),
			Moved("Il2CppScheduleOne.NPCs.NPC", "FirstName", write: true, BasicInfo, "FirstName", "NPC.cs:63-69 until 0.4.5f2, now BasicInfo.cs:4-7"),
			Moved("Il2CppScheduleOne.NPCs.NPC", "LastName", write: true, BasicInfo, "LastName", "NPC.cs:63-69 until 0.4.5f2, now BasicInfo.cs:4-7"),
			Moved("Il2CppScheduleOne.NPCs.NPC", "hasLastName", write: true, BasicInfo, "HasLastName", "NPC.cs:63-69 until 0.4.5f2, now BasicInfo.cs:4-7"),
			Moved("Il2CppScheduleOne.NPCs.NPC", "MugshotSprite", write: true, Appearance, "Mugshot", "NPC.cs:71 until 0.4.5f2, now Appearance.Mugshot"),
			Moved("Il2CppScheduleOne.NPCs.NPC", "CanBeSummoned", write: true, Interaction, "CanBeSummoned", "NPC.cs:116 until 0.4.5f2, now Interaction.cs:8 - and the game reads it from there in NPCEnterableBuilding.cs:96"),
			Moved("Il2CppScheduleOne.NPCs.NPC", "CanBeSummoned", write: false, Interaction, "CanBeSummoned", "NPC.cs:116 until 0.4.5f2, now Interaction.cs:8 - and the game reads it from there in NPCEnterableBuilding.cs:96"),
			NowStatic("Il2CppScheduleOne.NPCs.NPCSpeedController", "get_DefaultWalkSpeed", 0, "get_DefaultNormalizedSpeed", "NPCSpeedController.cs:29 until 0.4.5f2, where nothing ever wrote it; 0.4.6 makes it the const DefaultNormalizedSpeed = 0.08f (:27), the same value it was initialised to"),
			Moved("Il2CppScheduleOne.NPCs.NPC", "ConversationCanBeHidden", write: true, Messaging, "ConversationCanBeHidden", "NPC.cs:130 until 0.4.5f2, now Messaging.cs:11 - the same default and the same use, moved into the NPCData object with the rest of the per-NPC settings"),
			Moved("Il2CppScheduleOne.NPCs.NPC", "ConversationCanBeHidden", write: false, Messaging, "ConversationCanBeHidden", "NPC.cs:130 until 0.4.5f2, now Messaging.cs:11 - the same default and the same use, moved into the NPCData object with the rest of the per-NPC settings"),
			Moved("Il2CppScheduleOne.NPCs.NPCInventory", "SlotCount", write: true, Inventory, "InventorySlotCount", "NPCInventory.cs:45 until 0.4.5f2, now Inventory.InventorySlotCount, which NPCInventory.cs:62 builds the slots from"),
			Moved("Il2CppScheduleOne.NPCs.NPCInventory", "SlotCount", write: false, Inventory, "InventorySlotCount", "NPCInventory.cs:45 until 0.4.5f2, now Inventory.InventorySlotCount, which NPCInventory.cs:62 builds the slots from"),
			Moved("Il2CppScheduleOne.NPCs.NPCInventory", "ClearInventoryEachNight", write: true, Inventory, "ClearInventoryOnNewDay", "NPCInventory.cs:51-65 until 0.4.5f2; the value kept its meaning and lost its old name in Inventory.cs"),
			Moved("Il2CppScheduleOne.NPCs.NPCInventory", "RandomCash", write: true, Inventory, "RandomizeCash", "NPCInventory.cs:51-65 until 0.4.5f2; the value kept its meaning and lost its old name in Inventory.cs"),
			Moved("Il2CppScheduleOne.NPCs.NPCInventory", "RandomItems", write: true, Inventory, "RandomizeInventory", "NPCInventory.cs:51-65 until 0.4.5f2; the value kept its meaning and lost its old name in Inventory.cs"),
			Moved("Il2CppScheduleOne.NPCs.NPCInventory", "CanBePickpocketed", write: true, Inventory, "CanBePickpocketed", "NPCInventory.cs:47 until 0.4.5f2, now Inventory.CanBePickpocketed, read at NPCInventory.cs:372"),
			Moved("Il2CppScheduleOne.UI.Phone.CounterofferInterface", "PriceInput", write: false, PriceSelector, "_inputField", "CounterofferInterface.cs:20 held the price box directly until 0.4.5f2; 0.4.6 wraps it in an AmountSelector, whose _inputField is the same control (AmountSelector.cs:19)"),
			Moved("Il2CppScheduleOne.UI.Phone.CounterofferInterface", "price", write: false, PriceSelector, "SelectedAmount", "CounterofferInterface.cs:164 reads PriceSelector.SelectedAmount where the screen's own `price` field used to be, and AmountSelector.cs:63 is what writes it"),
			Onto("Il2CppScheduleOne.UI.Phone.CounterofferInterface", "ChangePrice", 1, PriceSelector, "ChangeAmount", "CounterofferInterface.cs:196-200 until 0.4.5f2 clamped price + change into its own field and wrote the box; AmountSelector.cs:56 is that line with the bounds the box carries (ChangeAmount -> SetAmount(SelectedAmount + change))"),
			Moved("Il2CppScheduleOne.NPCs.NPCHealth", "MaxHealth", write: true, NpcHealthData, "MaxHealth", "NPCHealth.cs:32 until 0.4.5f2, now Health.cs:8 - and NPCHealth.cs:82 reads it straight back from there, so a write goes to the value the getter answers with"),
			Moved("Il2CppScheduleOne.NPCs.NPCMovement", "WalkSpeed", write: true, NpcSpeed, "WalkSpeed", "npc.NPCData.Movement, which is where NPCMovement's own getter reads it from (NPCMovement.cs:170-172)"),
			Moved("Il2CppScheduleOne.NPCs.NPCMovement", "RunSpeed", write: true, NpcSpeed, "SprintSpeed", "npc.NPCData.Movement, which is where NPCMovement's own getter reads it from (NPCMovement.cs:170-172)"),
			Moved("Il2CppScheduleOne.Economy.Supplier", "OnlineShopItems", write: false, SupplierData, "DeliveryShopListings", "the same PhoneShopInterface.Listing[]; 0.4.6 keeps it on SupplierNPCData and Supplier.SupplierData is the way in"),
			Moved("Il2CppScheduleOne.Economy.Supplier", "OnlineShopItems", write: true, SupplierData, "DeliveryShopListings", "the same PhoneShopInterface.Listing[]; 0.4.6 keeps it on SupplierNPCData and Supplier.SupplierData is the way in"),
			Moved("Il2CppScheduleOne.Casino.UI.BlackjackInterface", "BetSlider", write: false, BetPanel, "_betSlider", "the betting half of a casino screen became CasinoGameBetPanel, which every casino game shares; the screen's own BetPanel is the way in (CasinoGameBetPanel.cs:20,23,26, 38, 103)"),
			Moved("Il2CppScheduleOne.Casino.UI.BlackjackInterface", "BetAmount", write: false, BetPanel, "_betAmount", "the betting half of a casino screen became CasinoGameBetPanel, which every casino game shares; the screen's own BetPanel is the way in (CasinoGameBetPanel.cs:20,23,26, 38, 103)"),
			Moved("Il2CppScheduleOne.Casino.UI.BlackjackInterface", "ReadyButton", write: false, BetPanel, "_readyButton", "the betting half of a casino screen became CasinoGameBetPanel, which every casino game shares; the screen's own BetPanel is the way in (CasinoGameBetPanel.cs:20,23,26, 38, 103)"),
			Onto("Il2CppScheduleOne.Casino.UI.BlackjackInterface", "BetSliderChanged", 1, BetPanel, "BetSliderChanged", "the betting half of a casino screen became CasinoGameBetPanel, which every casino game shares; the screen's own BetPanel is the way in (CasinoGameBetPanel.cs:20,23,26, 38, 103)", new string[1] { "newValue" }),
			Onto("Il2CppScheduleOne.Casino.UI.BlackjackInterface", "RefreshDisplayedBet", 0, BetPanel, "RefreshDisplayedBet", "the betting half of a casino screen became CasinoGameBetPanel, which every casino game shares; the screen's own BetPanel is the way in (CasinoGameBetPanel.cs:20,23,26, 38, 103)"),
			Moved("Il2CppScheduleOne.Casino.UI.RTBInterface", "BetSlider", write: false, BetPanel, "_betSlider", "the betting half of a casino screen became CasinoGameBetPanel, which every casino game shares; the screen's own BetPanel is the way in (CasinoGameBetPanel.cs:20,23,26, 38, 103)"),
			Moved("Il2CppScheduleOne.Casino.UI.RTBInterface", "BetAmount", write: false, BetPanel, "_betAmount", "the betting half of a casino screen became CasinoGameBetPanel, which every casino game shares; the screen's own BetPanel is the way in (CasinoGameBetPanel.cs:20,23,26, 38, 103)"),
			Moved("Il2CppScheduleOne.Casino.UI.RTBInterface", "ReadyButton", write: false, BetPanel, "_readyButton", "the betting half of a casino screen became CasinoGameBetPanel, which every casino game shares; the screen's own BetPanel is the way in (CasinoGameBetPanel.cs:20,23,26, 38, 103)"),
			ElsewhereStatic("Il2CppScheduleOne.PlayerScripts.PlayerCamera", "LockMouse", 0, "Il2CppScheduleOne.Input.MouseController", "PlayerCamera.cs:523 until 0.4.5f2, now MouseController.cs:11 with the same body; its showCrosshair guards the line the old one ran unconditionally, so true is the old behaviour", new object[1] { true }),
			ElsewhereStatic("Il2CppScheduleOne.PlayerScripts.PlayerCamera", "FreeMouse", 0, "Il2CppScheduleOne.Input.MouseController", "PlayerCamera.cs:534 until 0.4.5f2, now MouseController.cs:23 with the same body; its hideCrosshair guards the line the old one ran unconditionally, so true is the old behaviour", new object[1] { true }),
			Elsewhere("Il2CppScheduleOne.PlayerScripts.PlayerCamera", "get_isCursorShowing", NoParameters, "Il2CppScheduleOne.Input.MouseController", "the cursor flag left PlayerCamera for MouseController, which 0.4.6 added and which its LockMouse and FreeMouse write the same way the camera's used to (MouseController.cs:9,13,25)", "get_IsMouseVisible"),
			Elsewhere("Il2CppScheduleOne.PlayerScripts.PlayerCamera", "set_isCursorShowing", OneBool, "Il2CppScheduleOne.Input.MouseController", "the cursor flag left PlayerCamera for MouseController, which 0.4.6 added and which its LockMouse and FreeMouse write the same way the camera's used to (MouseController.cs:9,13,25)", "set_IsMouseVisible"),
			Elsewhere("Il2CppScheduleOne.PlayerScripts.Player", "GetPlayer", new string[1] { "System.String" }, "Il2CppScheduleOne.PlayerScripts.PlayerManager", "0.4.6 moved the player lookups off Player onto PlayerManager with the same names, parameters and return type; the game's own callers went with them (Supplier.cs:236 is one)"),
			Elsewhere("Il2CppScheduleOne.PlayerScripts.Player", "GetPlayer", new string[1] { "Il2CppFishNet.Connection.NetworkConnection" }, "Il2CppScheduleOne.PlayerScripts.PlayerManager", "0.4.6 moved the player lookups off Player onto PlayerManager with the same names, parameters and return type; the game's own callers went with them (Supplier.cs:236 is one)"),
			Elsewhere("Il2CppScheduleOne.PlayerScripts.Player", "GetPlayerByName", new string[1] { "System.String" }, "Il2CppScheduleOne.PlayerScripts.PlayerManager", "0.4.6 moved the player lookups off Player onto PlayerManager with the same names, parameters and return type; the game's own callers went with them (Supplier.cs:236 is one)"),
			Elsewhere("Il2CppScheduleOne.PlayerScripts.Player", "GetRandomPlayer", new string[2] { "System.Boolean", "System.Boolean" }, "Il2CppScheduleOne.PlayerScripts.PlayerManager", "0.4.6 moved the player lookups off Player onto PlayerManager with the same names, parameters and return type; the game's own callers went with them (Supplier.cs:236 is one)"),
			Elsewhere("Il2CppScheduleOne.PlayerScripts.Player", "AreAllPlayersReadyToSleep", NoParameters, "Il2CppScheduleOne.PlayerScripts.PlayerManager", "0.4.6 moved the player lookups off Player onto PlayerManager with the same names, parameters and return type; the game's own callers went with them (Supplier.cs:236 is one)"),
			ElsewhereByShape("Il2CppScheduleOne.PlayerScripts.Player", "GetClosestPlayer", 3, "Il2CppScheduleOne.PlayerScripts.PlayerManager", "0.4.6 moved the player lookups off Player onto PlayerManager with the same names, parameters and return type; the game's own callers went with them (Supplier.cs:236 is one)", (MethodDefinition m) => ((ParameterReference)((MethodReference)m).Parameters[2]).ParameterType.IsGenericInstance),
			FromBase("Il2CppScheduleOne.UI.Stations.PackagingStationCanvas", "Canvas", "_canvas", "0.4.6 pulled the canvas off every station screen into the shared StationInterface<T> base and renamed it _canvas"),
			FromBase("Il2CppScheduleOne.UI.Stations.BrickPressCanvas", "Canvas", "_canvas", "0.4.6 pulled the canvas off every station screen into the shared StationInterface<T> base and renamed it _canvas"),
			FromBase("Il2CppScheduleOne.UI.Stations.LabOvenCanvas", "Canvas", "_canvas", "0.4.6 pulled the canvas off every station screen into the shared StationInterface<T> base and renamed it _canvas"),
			FromBase("Il2CppScheduleOne.UI.Stations.MushroomSpawnStationInterface", "Canvas", "_canvas", "0.4.6 pulled the canvas off every station screen into the shared StationInterface<T> base and renamed it _canvas"),
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.UI.AmountSelector",
				OldName = "get_onPriceChanged",
				ParameterCount = 0,
				Because = "the control became the game's general amount box, whose notification is the C# event OnAmountChanged (AmountSelector.cs:29) and not a UnityEvent - so the old name has no successor of that shape, and the callers guard it",
				Emit = EmitNoPriceEvent
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.Networking.Lobby",
				OldName = "get_LobbySteamID",
				ParameterCount = 0,
				Because = "the id moved into the lobby service: Lobby.LobbyID is still declared and 0.4.6 writes it nowhere, so this reads SteamLobbyService._lobbyID, which is set when a lobby is created or entered (SteamLobbyService.cs:210,237)",
				Emit = EmitLobbySteamId
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.Networking.Lobby",
				OldName = "get_LocalPlayerID",
				ParameterCount = 0,
				Because = "the field held this client's own Steam id, which is what SteamUser.GetSteamID() answers; 0.4.6 stopped keeping a copy of it on Lobby",
				Emit = EmitLocalPlayerId
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.Networking.Lobby",
				OldName = "get_Players",
				ParameterCount = 0,
				Because = "the same ids, rebuilt from GetLobbyMemberIDs() - which SteamLobbyService.cs:178 builds out of the very array this used to be",
				Emit = EmitLobbyPlayers
			},
			Moved("Il2CppScheduleOne.Economy.Dealer", "DealerType", write: false, DealerData, "DealerType", "Dealer.cs held the type itself until 0.4.5f2; 0.4.6 keeps every dealer-specific value on DealerNPCData and Dealer.DealerData is the way in"),
			Moved("Il2CppScheduleOne.Economy.Dealer", "Cut", write: false, DealerData, "SalesCutPercentage", "Dealer.cs:102 until 0.4.5f2, now DealerNPCData.SalesCutPercentage (:20) - and the payout reads it from there with the same expression the old field was used in (Dealer.cs:1892 against :2031 in 0.4.5f2)"),
			Moved("Il2CppScheduleOne.Economy.Dealer", "Cut", write: true, DealerData, "SalesCutPercentage", "Dealer.cs:102 until 0.4.5f2, now DealerNPCData.SalesCutPercentage (:20) - and the payout reads it from there with the same expression the old field was used in (Dealer.cs:1892 against :2031 in 0.4.5f2)"),
			Moved("Il2CppScheduleOne.Economy.Dealer", "SigningFee", write: true, DealerData, "SigningFee", "Dealer.cs:100 until 0.4.5f2, now DealerNPCData.cs:17 with the same 500 default, copied across when a dealer's data is built (:40) - the same move DealerType made"),
			Moved("Il2CppScheduleOne.Economy.Dealer", "SigningFee", write: false, DealerData, "SigningFee", "Dealer.cs:100 until 0.4.5f2, now DealerNPCData.cs:17 with the same 500 default, copied across when a dealer's data is built (:40) - the same move DealerType made"),
			NowCalled("Il2CppScheduleOne.VoiceOver.VOEmitter", "get_Database", 0, "get__currentDatabase", "VOEmitter.cs:12 until 0.4.5f2 held one serialized Database field, and Play() read it; 0.4.6 split it into a default and a current one and Play() reads _currentDatabase"),
			NowCalled("Il2CppScheduleOne.VoiceOver.VOEmitter", "set_Database", 1, "set__currentDatabase", "VOEmitter.cs:12 until 0.4.5f2 held one serialized Database field, and Play() read it; 0.4.6 split it into a default and a current one and Play() reads _currentDatabase"),
			NowCalled("Il2CppScheduleOne.VoiceOver.VOEmitter", "get_PitchMultiplier", 0, "get__defaultPitch", "VOEmitter.cs:15 until 0.4.5f2; Play() multiplied PitchMultiplier by the runtime one, and 0.4.6 multiplies _defaultPitch by _runtimePitchMultiplier in the same expression"),
			NowCalled("Il2CppScheduleOne.VoiceOver.VOEmitter", "set_PitchMultiplier", 1, "SetDefaultPitch", "VOEmitter.cs:15 until 0.4.5f2; Play() multiplied PitchMultiplier by the runtime one, and 0.4.6 multiplies _defaultPitch by _runtimePitchMultiplier in the same expression"),
			NowCalled("Il2CppScheduleOne.PlayerScripts.PlayerCrimeData", "set_SyncAccessor_<CurrentPursuitLevel>k__BackingField", 1, "set_CurrentPursuitLevel", "the generated assembly carries the property without accessor methods under that name, and CurrentPursuitLevel's own setter is the same write - its getter is a plain `return CurrentPursuitLevel` (PlayerCrimeData.cs:151)"),
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.NPCs.NPC",
				OldName = "get_fullName",
				ParameterCount = 0,
				Because = "0.4.6 renamed fullName to FullName and moved the names it reads behind NPCData, which is null until an NPC is set up - the old one read fields that were never null, so this answers the empty string there instead of throwing",
				Emit = EmitNpcFullName
			},
			NowCalled("Il2CppScheduleOne.PlayerScripts.Player", "get_CurrentAvatarSettings", 0, "get_CurrentBasicAppearance", "Player.cs:450 until 0.4.5f2, now :415 as CurrentBasicAppearance - the same BasicAvatarSettings with the same protected setter, saved by the same line (:754)"),
			NowCalled("Il2CppScheduleOne.UI.DialogueCanvas", "get_isActive", 0, "get_IsOpen", "DialogueCanvas.cs:57 until 0.4.5f2 and :60 now - the same `currentHandler != null`, renamed from isActive to IsOpen"),
			NowCalled("Il2CppScheduleOne.UI.Relations.RelationCircle", "get_AssignedNPC_ID", 0, "get_NPCId", "RelationCircle.cs:23 until 0.4.5f2 cached the id in a field; NPCId reads it off the assigned NPC and returns string.Empty for none, which is what the field held"),
			NowCalled("Il2CppScheduleOne.PlayerScripts.Health.PlayerHealth", "get_MAX_HEALTH", 0, "get_MaxHealth", "the same constant, renamed to PascalCase (PlayerHealth.cs:18)"),
			NowCalled("Il2CppScheduleOne.UI.StorageMenu", "get_CloseButton", 0, "get_CloseButtonContainer", "the same RectTransform, renamed when the button got its own container (StorageMenu.cs:24)"),
			NowCalled("Il2CppScheduleOne.NPCs.NPCInventory", "get_PickpocketIntObj", 0, "get__interactable", "NPCInventory.cs:40 until 0.4.5f2; the same InteractableObject under the name the private field carries now, which NPCInventory.cs:338-348 sets the pickpocket state on"),
			NowCalled("Il2CppScheduleOne.UI.AmountSelector", "SetPrice", 1, "SetAmount", "the handover price control became the game's general amount box in 0.4.6; Price is SelectedAmount and SetPrice is SetAmount, same values (AmountSelector.cs)", new string[1] { "price" }),
			NowCalled("Il2CppScheduleOne.UI.AmountSelector", "get_Price", 0, "get_SelectedAmount", "the handover price control became the game's general amount box in 0.4.6; Price is SelectedAmount and SetPrice is SetAmount, same values (AmountSelector.cs)"),
			NowCalled("Il2CppScheduleOne.UI.Compass.CompassManager/Element", "get_Transform", 0, "get_TargetTransform", "CompassManager.cs:32 until 0.4.5f2 was a public Transform field; 0.4.6 makes it a property the constructor fills from the same argument (CompassManager.cs:27-34)"),
			NowCalled("Il2CppScheduleOne.Economy.Dealer", "GetProductCount", 3, "GetOrderableProductQuantity", "the same three parameters in the same order and the same int back, and Dealer.cs:625 counts exactly what the old name says - the dealer's stock of one product within a quality range. The rename is older than the version archive, so this is read from the body rather than from a diff"),
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.UI.StorageMenu",
				OldName = "get_onClosed",
				ParameterCount = 0,
				Because = "StorageMenu.cs:35 until 0.4.5f2 was a UnityEvent the menu fired when it closed; 0.4.6 keeps a private Action instead, which nothing can subscribe to from outside - so the event is put back and Polyfill fires it",
				Emit = EmitStorageClosedEvent
			},
			NowCalled("Il2CppScheduleOne.NPCs.NPCInventory", "set_PickpocketIntObj", 1, "set__interactable", "NPCInventory.cs:40 until 0.4.5f2; the same InteractableObject under the name the private field carries now, which NPCInventory.cs:338-348 sets the pickpocket state on"),
			NowCalled("Il2CppScheduleOne.UI.Stations.PackagingStationCanvas", "get_PackagingStation", 0, "get_Station", "the screen's own station was called after the station (PackagingStationCanvas.PackagingStation, MixingStationCanvas.MixingStation) and 0.4.6 calls both Station - the other five screens kept theirs, so this is two names and not a pattern"),
			NowCalled("Il2CppScheduleOne.UI.Stations.MixingStationInterface", "get_MixingStation", 0, "get_Station", "the screen's own station was called after the station (PackagingStationCanvas.PackagingStation, MixingStationCanvas.MixingStation) and 0.4.6 calls both Station - the other five screens kept theirs, so this is two names and not a pattern"),
			Dropped("Il2CppScheduleOne.AvatarFramework.Avatar", "ApplyShapeKeys", new string[2] { "System.Single", "System.Single" }, "System.Boolean", "bodyOnly stopped the method before the accessory loop; 0.4.6 dropped the flag and always runs that loop, so the two-argument form is what passing false always did (Avatar.cs:292-297)"),
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.AvatarFramework.Avatar",
				OldName = "set_InitialAvatarSettings",
				ParameterCount = 1,
				Because = "Avatar.cs until 0.4.5f2 kept the settings an avatar was built from; 0.4.6 dropped the field and nothing reads it any more, so the write is accepted and discarded - and no getter is offered, because there is nothing to give back",
				Emit = EmitForgottenSetter
			},
			SplitInTwo(0),
			SplitInTwo(1),
			SplitInTwo(2),
			SplitInTwo(3),
			SplitInTwo(4),
			ReplacedByTwo(0),
			ReplacedByTwo(1),
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.Economy.Dealer",
				OldName = "get_Cut",
				ParameterCount = 0,
				Because = "0.4.6 moved the dealer's cut onto the data object the NPC carries: 0.4.5f2 had a serialized Cut field on Dealer defaulting to 0.2f, 0.4.6f13 has DealerNPCData.SalesCutPercentage with the same type and the same default, and the consumer line is the same expression with one identifier swapped - ChangeCash(payment * (1f - Cut)) became ChangeCash(payment * (1f - DealerData.SalesCutPercentage)) (Dealer.cs:132, DealerNPCData.cs:17)",
				Emit = (ModuleDefinition module, TypeDefinition type) => EmitDealerCut(module, type, setter: false)
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.Economy.Dealer",
				OldName = "set_Cut",
				ParameterCount = 1,
				ParameterTypes = new string[1] { "System.Single" },
				Because = "0.4.6 moved the dealer's cut onto the data object the NPC carries: 0.4.5f2 had a serialized Cut field on Dealer defaulting to 0.2f, 0.4.6f13 has DealerNPCData.SalesCutPercentage with the same type and the same default, and the consumer line is the same expression with one identifier swapped - ChangeCash(payment * (1f - Cut)) became ChangeCash(payment * (1f - DealerData.SalesCutPercentage)) (Dealer.cs:132, DealerNPCData.cs:17)",
				Emit = (ModuleDefinition module, TypeDefinition type) => EmitDealerCut(module, type, setter: true)
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.UI.GameplayMenu",
				OldName = "SetIsOpen",
				ParameterCount = 1,
				ParameterTypes = new string[1] { "System.Boolean" },
				Because = "0.4.6 split GameplayMenu.SetIsOpen(bool) into Open() and Close(): 0.4.5f2 has SetIsOpen and neither of them, 0.4.6f13 has both and no SetIsOpen (GameplayMenu.cs:238,243)",
				Emit = EmitGameplayMenuSetIsOpen
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.UI.SleepCanvas",
				OldName = "SetIsOpen",
				ParameterCount = 1,
				ParameterTypes = new string[1] { "System.Boolean" },
				Because = "0.4.6 replaced SleepCanvas.SetIsOpen(bool) with OpenMenu() and the menu stack: 0.4.5f2 has SetIsOpen and neither, 0.4.6f13 has OpenMenu, a MenuState field and no SetIsOpen (SleepCanvas.cs:88,92)",
				Emit = EmitSleepCanvasSetIsOpen
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.PlayerScripts.Player",
				OldName = "Activate",
				ParameterCount = 0,
				Because = "Player.cs:1423-1441 until 0.4.5f2; 0.4.6 deleted both and rewrote its own three callers to register a UI element instead, leaving every line these ran still there",
				Emit = (ModuleDefinition module, TypeDefinition type) => EmitPlayerToggle(module, type, "Activate", on: true)
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.PlayerScripts.Player",
				OldName = "Deactivate",
				ParameterCount = 1,
				Because = "Player.cs:1423-1441 until 0.4.5f2; 0.4.6 deleted both and rewrote its own three callers to register a UI element instead, leaving every line these ran still there",
				Emit = (ModuleDefinition module, TypeDefinition type) => EmitPlayerToggle(module, type, "Deactivate", on: false)
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.ObjectScripts.PackagingStation",
				OldName = "Close",
				ParameterCount = 0,
				Because = "0.4.6 renamed PackagingStation.Close() to OnEndUse(): both close the canvas and release the player user, and it is the only zero-argument method on the type that does (PackagingStation.cs:416)",
				Emit = (ModuleDefinition module, TypeDefinition type) => EmitSelfCall(module, type, "Close", "OnEndUse")
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.PlayerScripts.PlayerCamera",
				OldName = "CloseInterface",
				ParameterCount = 2,
				ParameterTypes = new string[2] { "System.Single", "System.Boolean" },
				Because = "0.4.6 deleted PlayerCamera.CloseInterface(float, bool) along with the way screens used to close; every line of its body still exists, so it is rebuilt rather than pointed somewhere (0.4.5f2 PlayerCamera.cs:1157-1169)",
				Emit = EmitCloseInterface
			},
			Defaulted("Il2CppScheduleOne.PlayerScripts.PlayerCamera", "FreeMouse", NoParameters, new object[1] { true }, "the crosshair became a parameter; true is what the call did before it existed (PlayerCamera.cs:483-490)"),
			Defaulted("Il2CppScheduleOne.PlayerScripts.PlayerCamera", "LockMouse", NoParameters, new object[1] { true }, "the crosshair became a parameter; true is what the call did before it existed (PlayerCamera.cs:483-490)"),
			Defaulted("Il2CppScheduleOne.UI.StorageMenu", "Open", new string[3] { "Il2CppScheduleOne.ItemFramework.IItemSlotOwner", "System.String", "System.String" }, OneCallback, "Open took a callback in 0.4.6 and the old three-argument form passed none (StorageMenu.cs:56)"),
			Defaulted("Il2CppScheduleOne.UI.StorageMenu", "Open", new string[3] { "System.String", "System.String", "Il2CppScheduleOne.ItemFramework.IItemSlotOwner" }, OneCallback, "the same callback, on the overload that names the storage last (StorageMenu.cs:62)"),
			Defaulted("Il2CppScheduleOne.UI.StorageMenu", "Open", new string[1] { "Il2CppScheduleOne.Storage.StorageEntity" }, OneCallback, "the same callback, on the overload that takes a storage entity (StorageMenu.cs:50)"),
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.Tools.ManagementClipboard",
				OldName = "Close",
				ParameterCount = 1,
				AllowOverload = true,
				Because = "Close(preserveState) became two methods that differ by HOW they close, not by the flag: only the popping one hands the player back their movement, so both values write the flag and pop (ManagementClipboard.cs:103-113, 0.4.5f2 106-120)",
				Emit = EmitClipboardClose
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.Economy.CustomerData",
				OldName = "GetOrderDays",
				ParameterCount = 2,
				AllowOverload = true,
				Because = "it stopped returning the list and started filling one it is handed (CustomerData.cs:92)",
				Emit = EmitGetOrderDays
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.UI.App`1",
				OldName = "Exit",
				ParameterCount = 1,
				AllowOverload = true,
				Because = "ExitAction moved from ScheduleOne.DevUtilities to ScheduleOne; this takes the name the mod knows and hands it to the one method there is",
				Emit = EmitAppExit
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.GameInput/ExitDelegate",
				OldName = "op_Implicit",
				ParameterCount = 1,
				AllowOverload = true,
				Because = "an Action of the old ExitAction cannot be an Action of the new one - the conversion goes the wrong way for a delegate - so this wraps it rather than casting it",
				Emit = EmitExitDelegateConversion
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.Economy.Supplier",
				OldName = "get_meetingGreeting",
				ParameterCount = 0,
				Because = "Supplier.cs:186-199 until 0.4.5f2 kept the greeting and the choice in fields; 0.4.6 builds the same two objects as locals in Start() and hands them to the DialogueController, so they are still there and only the way to them is gone",
				Emit = (ModuleDefinition module, TypeDefinition type) => EmitFromController(module, type, "get_meetingGreeting", "GreetingOverrides", "Greeting", MeetingGreetingLine)
			},
			new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = "Il2CppScheduleOne.Economy.Supplier",
				OldName = "get_meetingChoice",
				ParameterCount = 0,
				Because = "Supplier.cs:186-199 until 0.4.5f2 kept the greeting and the choice in fields; 0.4.6 builds the same two objects as locals in Start() and hands them to the DialogueController, so they are still there and only the way to them is gone",
				Emit = (ModuleDefinition module, TypeDefinition type) => EmitFromController(module, type, "get_meetingChoice", "Choices", "ChoiceText", delegate(ModuleDefinition val, MethodDefinition method, ILProcessor il, Instruction giveUp)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					il.Emit(OpCodes.Ldstr, "Yes");
				})
			}
		};

		private const string ExitActionOld = "Il2CppScheduleOne.DevUtilities.ExitAction";

		private const string Supplier = "Il2CppScheduleOne.Economy.Supplier";

		private const string Controller = "Il2CppScheduleOne.Dialogue.DialogueController";

		private const string MeetingWhy = "Supplier.cs:186-199 until 0.4.5f2 kept the greeting and the choice in fields; 0.4.6 builds the same two objects as locals in Start() and hands them to the DialogueController, so they are still there and only the way to them is gone";

		internal override string Step => "0.4.5f2 -> 0.4.6f5";

		internal override string From => "0.4.6f5";

		internal override string VerifiedTo => "0.4.6f13";

		private static FieldDefinition Slot(ModuleDefinition module, TypeDefinition facade)
		{
			//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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			Enumerator<FieldDefinition> enumerator = facade.Fields.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					FieldDefinition current = enumerator.Current;
					if (((MemberReference)current).Name == "polyfillLoadedModule")
					{
						return current;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			FieldDefinition val = new FieldDefinition("polyfillLoadedModule", (FieldAttributes)17, module.TypeSystem.String);
			facade.Fields.Add(val);
			return val;
		}

		private static MethodDefinition TakingOneString(TypeDefinition type, string name)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_0051: Invalid comparison between Unknown and I4
			if (type == null)
			{
				return null;
			}
			MethodDefinition val = null;
			Enumerator<MethodDefinition> enumerator = type.Methods.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					MethodDefinition current = enumerator.Current;
					if (!(((MemberReference)current).Name != name) && ((MethodReference)current).Parameters.Count == 1 && (int)((ParameterReference)((MethodReference)current).Parameters[0]).ParameterType.MetadataType == 14)
					{
						if (val != null)
						{
							return null;
						}
						val = current;
					}
				}
				return val;
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void PushManager(ILProcessor il, MethodReference pointer, MethodReference make)
		{
			//IL_0001: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			il.Emit(OpCodes.Ldarg_0);
			il.Emit(OpCodes.Call, pointer);
			il.Emit(OpCodes.Newobj, make);
		}

		private static MethodDefinition EmitLoadModule(ModuleDefinition module, TypeDefinition facade, TypeDefinition manager)
		{
			//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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			MethodDefinition val = TakingOneString(manager, "LoadModule");
			MethodDefinition val2 = TakingOneString(manager, "UnloadModule");
			MethodDefinition val3 = ShadowTypes.PointerGetter(manager);
			MethodDefinition val4 = ShadowTypes.PointerConstructorOf(manager);
			if (val == null || val2 == null || val3 == null || val4 == null)
			{
				return null;
			}
			FieldDefinition val5 = Slot(module, facade);
			MethodDefinition val6 = new MethodDefinition("LoadModule", (MethodAttributes)134, module.TypeSystem.Void);
			((MethodReference)val6).Parameters.Add(new ParameterDefinition("key", (ParameterAttributes)0, module.TypeSystem.String));
			ILProcessor iLProcessor = val6.Body.GetILProcessor();
			Instruction val7 = iLProcessor.Create(OpCodes.Ldarg_0);
			iLProcessor.Emit(OpCodes.Ldsfld, (FieldReference)(object)val5);
			iLProcessor.Emit(OpCodes.Brfalse, val7);
			PushManager(iLProcessor, module.ImportReference((MethodReference)(object)val3), module.ImportReference((MethodReference)(object)val4));
			iLProcessor.Emit(OpCodes.Ldsfld, (FieldReference)(object)val5);
			iLProcessor.Emit(OpCodes.Callvirt, module.ImportReference((MethodReference)(object)val2));
			iLProcessor.Append(val7);
			iLProcessor.Emit(OpCodes.Call, module.ImportReference((MethodReference)(object)val3));
			iLProcessor.Emit(OpCodes.Newobj, module.ImportReference((MethodReference)(object)val4));
			iLProcessor.Emit(OpCodes.Ldarg_1);
			iLProcessor.Emit(OpCodes.Callvirt, module.ImportReference((MethodReference)(object)val));
			iLProcessor.Emit(OpCodes.Ldarg_1);
			iLProcessor.Emit(OpCodes.Stsfld, (FieldReference)(object)val5);
			iLProcessor.Emit(OpCodes.Ret);
			return val6;
		}

		private static MethodDefinition EmitUnloadModule(ModuleDefinition module, TypeDefinition facade, TypeDefinition manager)
		{
			//IL_0042: 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_0053: 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_006c: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			MethodDefinition val = TakingOneString(manager, "UnloadModule");
			MethodDefinition val2 = ShadowTypes.PointerGetter(manager);
			MethodDefinition val3 = ShadowTypes.PointerConstructorOf(manager);
			if (val == null || val2 == null || val3 == null)
			{
				return null;
			}
			FieldDefinition val4 = Slot(module, facade);
			MethodDefinition val5 = new MethodDefinition("UnloadModule", (MethodAttributes)134, module.TypeSystem.Void);
			ILProcessor iLProcessor = val5.Body.GetILProcessor();
			Instruction val6 = iLProcessor.Create(OpCodes.Ret);
			iLProcessor.Emit(OpCodes.Ldsfld, (FieldReference)(object)val4);
			iLProcessor.Emit(OpCodes.Brfalse, val6);
			PushManager(iLProcessor, module.ImportReference((MethodReference)(object)val2), module.ImportReference((MethodReference)(object)val3));
			iLProcessor.Emit(OpCodes.Ldsfld, (FieldReference)(object)val4);
			iLProcessor.Emit(OpCodes.Callvirt, module.ImportReference((MethodReference)(object)val));
			iLProcessor.Emit(OpCodes.Ldnull);
			iLProcessor.Emit(OpCodes.Stsfld, (FieldReference)(object)val4);
			iLProcessor.Append(val6);
			return val5;
		}

		private static MethodDefinition EmitCurrentModuleLabel(ModuleDefinition module, TypeDefinition facade, TypeDefinition manager)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_0050: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			MethodDefinition val = TakingOneString(manager, "HasActivePrompt");
			MethodDefinition val2 = ShadowTypes.PointerGetter(manager);
			MethodDefinition val3 = ShadowTypes.PointerConstructorOf(manager);
			if (val == null || (int)((MethodReference)val).ReturnType.MetadataType != 2 || val2 == null || val3 == null)
			{
				return null;
			}
			FieldDefinition val4 = Slot(module, facade);
			MethodDefinition val5 = new MethodDefinition("get_currentModuleLabel", (MethodAttributes)2182, module.TypeSystem.String);
			ILProcessor iLProcessor = val5.Body.GetILProcessor();
			Instruction val6 = iLProcessor.Create(OpCodes.Ldstr, "");
			iLProcessor.Emit(OpCodes.Ldsfld, (FieldReference)(object)val4);
			iLProcessor.Emit(OpCodes.Brfalse, val6);
			PushManager(iLProcessor, module.ImportReference((MethodReference)(object)val2), module.ImportReference((MethodReference)(object)val3));
			iLProcessor.Emit(OpCodes.Ldsfld, (FieldReference)(object)val4);
			iLProcessor.Emit(OpCodes.Callvirt, module.ImportReference((MethodReference)(object)val));
			iLProcessor.Emit(OpCodes.Brfalse, val6);
			iLProcessor.Emit(OpCodes.Ldsfld, (FieldReference)(object)val4);
			iLProcessor.Emit(OpCodes.Ret);
			iLProcessor.Append(val6);
			iLProcessor.Emit(OpCodes.Ret);
			return val5;
		}

		internal override IEnumerable<Bridge> Declare()
		{
			return All;
		}

		internal override IEnumerable<TypeRename> DeclareRenames()
		{
			return Renamed_;
		}

		private static Bridge Unprompted(Bridge bridge)
		{
			bridge.Unprompted = true;
			return bridge;
		}

		private static TypeRename Pair(string oldFullName, string newFullName)
		{
			return new TypeRename
			{
				Assembly = "Assembly-CSharp",
				OldFullName = oldFullName,
				NewFullName = newFullName,
				Because = "0.4.6 factored the station screens onto a shared StationInterface<T> base and renamed the four that still said Canvas; same members, same namespace, one word different"
			};
		}

		private static MethodDefinition EmitMovementSpeedScaleGetter(ModuleDefinition module, TypeDefinition movement)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Expected O, but got Unknown
			MethodDefinition val = Getter(movement, "SpeedController");
			object type;
			if (val == null)
			{
				type = null;
			}
			else
			{
				TypeReference returnType = ((MethodReference)val).ReturnType;
				type = ((returnType != null) ? returnType.Resolve() : null);
			}
			MethodDefinition val2 = Getter((TypeDefinition)type, "ActiveSpeedControl");
			MethodDefinition val3 = Getter((TypeDefinition)type, "SpeedMultiplier");
			object type2;
			if (val2 == null)
			{
				type2 = null;
			}
			else
			{
				TypeReference returnType2 = ((MethodReference)val2).ReturnType;
				type2 = ((returnType2 != null) ? returnType2.Resolve() : null);
			}
			MethodDefinition val4 = Getter((TypeDefinition)type2, "speed");
			if (val == null || val2 == null || val3 == null || val4 == null)
			{
				return null;
			}
			MethodDefinition val5 = new MethodDefinition("get_MovementSpeedScale", (MethodAttributes)134, module.TypeSystem.Single);
			ILProcessor iLProcessor = val5.Body.GetILProcessor();
			Instruction val6 = iLProcessor.Create(OpCodes.Ldc_R4, 0f);
			Instruction val7 = iLProcessor.Create(OpCodes.Nop);
			iLProcessor.Emit(OpCodes.Ldarg_0);
			iLProcessor.Emit(OpCodes.Call, (MethodReference)(object)val);
			iLProcessor.Emit(OpCodes.Dup);
			iLProcessor.Emit(OpCodes.Brtrue_S, val7);
			iLProcessor.Emit(OpCodes.Pop);
			iLProcessor.Append(val6);
			iLProcessor.Emit(OpCodes.Ret);
			iLProcessor.Append(val7);
			iLProcessor.Emit(OpCodes.Callvirt, (MethodReference)(object)val2);
			Instruction val8 = iLProcessor.Create(OpCodes.Callvirt, (MethodReference)(object)val4);
			iLProcessor.Emit(OpCodes.Dup);
			iLProcessor.Emit(OpCodes.Brtrue_S, val8);
			iLProcessor.Emit(OpCodes.Pop);
			iLProcessor.Emit(OpCodes.Ldc_R4, 0f);
			iLProcessor.Emit(OpCodes.Ret);
			iLProcessor.Append(val8);
			iLProcessor.Emit(OpCodes.Ldarg_0);
			iLProcessor.Emit(OpCodes.Call, (MethodReference)(object)val);
			iLProcessor.Emit(OpCodes.Callvirt, (MethodReference)(object)val3);
			iLProcessor.Emit(OpCodes.Mul);
			iLProcessor.Emit(OpCodes.Ret);
			return val5;
		}

		private static MethodDefinition EmitMovementSpeedScaleSetter(ModuleDefinition module, TypeDefinition movement)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Expected O, but got Unknown
			MethodDefinition val = Getter(movement, "SpeedController");
			object type;
			if (val == null)
			{
				type = null;
			}
			else
			{
				TypeReference returnType = ((MethodReference)val).ReturnType;
				type = ((returnType != null) ? returnType.Resolve() : null);
			}
			MethodDefinition val2 = Method((TypeDefinition)type, "AddSpeedControl", 1);
			MethodDefinition val3 = Method((TypeDefinition)type, "RemoveSpeedControl", 1);
			MethodDefinition val4 = Method(Nested((TypeDefinition)type, "SpeedControl"), ".ctor", 3);
			if (val == null || val2 == null || val3 == null || val4 == null)
			{
				return null;
			}
			MethodDefinition val5 = new MethodDefinition("set_MovementSpeedScale", (MethodAttributes)134, module.TypeSystem.Void);
			((MethodReference)val5).Parameters.Add(new ParameterDefinition("value", (ParameterAttributes)0, module.TypeSystem.Single));
			ILProcessor iLProcessor = val5.Body.GetILProcessor();
			Instruction val6 = iLProcessor.Create(OpCodes.Ret);
			iLProcessor.Emit(OpCodes.Ldarg_0);
			iLProcessor.Emit(OpCodes.Call, (MethodReference)(object)val);
			iLProcessor.Emit(OpCodes.Dup);
			Instruction val7 = iLProcessor.Create(OpCodes.Dup);
			iLProcessor.Emit(OpCodes.Brtrue_S, val7);
			iLProcessor.Emit(OpCodes.Pop);
			iLProcessor.Emit(OpCodes.Br_S, val6);
			iLProcessor.Append(val7);
			iLProcessor.Emit(OpCodes.Ldstr, "Polyfill");
			iLProcessor.Emit(OpCodes.Callvirt, (MethodReference)(object)val3);
			iLProcessor.Emit(OpCodes.Ldstr, "Polyfill");
			iLProcessor.Emit(OpCodes.Ldc_I4_0);
			iLProcessor.Emit(OpCodes.Ldarg_1);
			iLProcessor.Emit(OpCodes.Newobj, (MethodReference)(object)val4);
			iLProcessor.Emit(OpCodes.Callvirt, (MethodReference)(object)val2);
			iLProcessor.Append(val6);
			return val5;
		}

		private static MethodDefinition EmitOverrideAggression(ModuleDefinition module, TypeDefinition npc)
		{
			//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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			MethodDefinition val = Getter(npc, "AggressionController");
			object type;
			if (val == null)
			{
				type = null;
			}
			else
			{
				TypeReference returnType = ((MethodReference)val).ReturnType;
				type = ((returnType != null) ? returnType.Resolve() : null);
			}
			MethodDefinition val2 = Method((TypeDefinition)type, "Add", 1);
			TypeDefinition type2 = Nested((TypeDefinition)type, "StackEntry");
			TypeDefinition val3 = Nested((TypeDefinition)type, "EStackMode");
			MethodDefinition val4 = Method(type2, ".ctor", 4);
			if (val == null || val2 == null || val4 == null || val3 == null)
			{
				return null;
			}
			MethodDefinition val5 = new MethodDefinition("OverrideAggression", (MethodAttributes)134, module.TypeSystem.Void);
			((MethodReference)val5).Parameters.Add(new ParameterDefinition("aggression", (ParameterAttributes)0, module.TypeSystem.Single));
			ILProcessor iLProcessor = val5.Body.GetILProcessor();
			iLProcessor.Emit(OpCodes.Ldarg_0);
			iLProcessor.Emit(OpCodes.Call, (MethodReference)(object)val);
			iLProcessor.Emit(OpCodes.Ldstr, "Polyfill");
			iLProcessor.Emit(OpCodes.Ldarg_1);
			iLProcessor.Emit(OpCodes.Ldc_I4_1);
			iLProcessor.Emit(OpCodes.Ldc_I4_0);
			iLProcessor.Emit(OpCodes.Newobj, (MethodReference)(object)val4);
			iLProcessor.Emit(OpCodes.Callvirt, (MethodReference)(object)val2);
			iLProcessor.Emit(OpCodes.Ret);
			return val5;
		}

		private static Bridge Moved(string declaringType, string oldName, bool write, string[] hops, string target, string because)
		{
			string accessor = (write ? "set_" : "get_") + oldName;
			return new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = declaringType,
				OldName = accessor,
				ParameterCount = (write ? 1 : 0),
				Because = because,
				Emit = (ModuleDefinition module, TypeDefinition type) => EmitThrough(module, type, accessor, hops, target, write)
			};
		}

		private static MethodDefinition EmitThrough(ModuleDefinition module, TypeDefinition owner, string accessor, string[] hops, string target, bool write)
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_00f6: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			List<MethodDefinition> list = new List<MethodDefinition>();
			TypeDefinition val = owner;
			foreach (string member in hops)
			{
				MethodDefinition val2 = Getter(val, member);
				if (val2 == null)
				{
					return null;
				}
				list.Add(val2);
				TypeReference returnType = ((MethodReference)val2).ReturnType;
				val = ((returnType != null) ? returnType.Resolve() : null);
				if (val == null)
				{
					return null;
				}
			}
			MethodDefinition val3 = (write ? Method(val, "set_" + target, 1) : Getter(val, target));
			if (val3 == null)
			{
				return null;
			}
			TypeReference val4 = (write ? ((ParameterReference)((MethodReference)val3).Parameters[0]).ParameterType : ((MethodReference)val3).ReturnType);
			TypeReference val5 = (write ? module.TypeSystem.Void : module.ImportReference(val4));
			MethodDefinition val6 = new MethodDefinition(accessor, (MethodAttributes)134, val5);
			if (write)
			{
				((MethodReference)val6).Parameters.Add(new ParameterDefinition("value", (ParameterAttributes)0, module.ImportReference(val4)));
			}
			ILProcessor iLProcessor = val6.Body.GetILProcessor();
			Instruction val7 = iLProcessor.Create(OpCodes.Nop);
			iLProcessor.Emit(OpCodes.Ldarg_0);
			for (int j = 0; j < list.Count; j++)
			{
				iLProcessor.Emit((j == 0) ? OpCodes.Call : OpCodes.Callvirt, module.ImportReference((MethodReference)(object)list[j]));
				iLProcessor.Emit(OpCodes.Dup);
				iLProcessor.Emit(OpCodes.Brfalse, val7);
			}
			if (write)
			{
				iLProcessor.Emit(OpCodes.Ldarg_1);
			}
			iLProcessor.Emit(OpCodes.Callvirt, module.ImportReference((MethodReference)(object)val3));
			iLProcessor.Emit(OpCodes.Ret);
			iLProcessor.Append(val7);
			iLProcessor.Emit(OpCodes.Pop);
			if (!write)
			{
				EmitDefault(val6, iLProcessor, val5);
			}
			iLProcessor.Emit(OpCodes.Ret);
			val6.Body.InitLocals = true;
			return val6;
		}

		private static Bridge Elsewhere(string declaringType, string name, string[] parameters, string nowOn, string because, string nowCalled = null)
		{
			return new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = declaringType,
				OldName = name,
				ParameterCount = parameters.Length,
				ParameterTypes = parameters,
				AllowOverload = true,
				Because = because,
				Emit = (ModuleDefinition module, TypeDefinition type) => EmitElsewhere(module, type, name, parameters, nowOn, nowCalled ?? name)
			};
		}

		private static Bridge ElsewhereByShape(string declaringType, string name, int parameterCount, string nowOn, string because, Func<MethodDefinition, bool> pick)
		{
			return new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = declaringType,
				OldName = name,
				ParameterCount = parameterCount,
				AllowOverload = true,
				Because = because,
				Emit = (ModuleDefinition module, TypeDefinition type) => EmitPicked(module, type, name, parameterCount, nowOn, pick)
			};
		}

		private static MethodDefinition EmitPicked(ModuleDefinition module, TypeDefinition owner, string name, int parameterCount, string nowOn, Func<MethodDefinition, bool> pick)
		{
			//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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			TypeDefinition type = module.GetType(nowOn);
			if (type == null)
			{
				return null;
			}
			MethodDefinition val = null;
			Enumerator<MethodDefinition> enumerator = type.Methods.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					MethodDefinition current = enumerator.Current;
					if (((MemberReference)current).Name != name || !current.IsStatic || ((MethodReference)current).Parameters.Count != parameterCount)
					{
						continue;
					}
					bool flag;
					try
					{
						flag = pick(current);
					}
					catch
					{
						return null;
					}
					if (flag)
					{
						if (val != null)
						{
							return null;
						}
						val = current;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			if (val == null || ((MethodReference)val).HasGenericParameters)
			{
				return null;
			}
			MethodDefinition val2 = new MethodDefinition(name, (MethodAttributes)150, module.ImportReference(((MethodReference)val).ReturnType));
			Enumerator<ParameterDefinition> enumerator2 = ((MethodReference)val).Parameters.GetEnumerator();
			try
			{
				while (enumerator2.MoveNext())
				{
					ParameterDefinition current2 = enumerator2.Current;
					((MethodReference)val2).Parameters.Add(new ParameterDefinition(((ParameterReference)current2).Name, (ParameterAttributes)0, module.ImportReference(((ParameterReference)current2).ParameterType)));
				}
			}
			finally
			{
				((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
			}
			ILProcessor iLProcessor = val2.Body.GetILProcessor();
			enumerator2 = ((MethodReference)val2).Parameters.GetEnumerator();
			try
			{
				while (enumerator2.MoveNext())
				{
					ParameterDefinition current3 = enumerator2.Current;
					iLProcessor.Emit(OpCodes.Ldarg, current3);
				}
			}
			finally
			{
				((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
			}
			iLProcessor.Emit(OpCodes.Call, module.ImportReference((MethodReference)(object)val));
			iLProcessor.Emit(OpCodes.Ret);
			return val2;
		}

		private static Bridge ElsewhereStatic(string declaringType, string oldName, int oldParameterCount, string nowOn, string because, object[] defaults = null)
		{
			return new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = declaringType,
				OldName = oldName,
				ParameterCount = oldParameterCount,
				Because = because,
				Emit = (ModuleDefinition module, TypeDefinition type) => EmitElsewhereStatic(module, oldName, oldParameterCount, nowOn, defaults ?? Array.Empty<object>())
			};
		}

		private static MethodDefinition EmitElsewhereStatic(ModuleDefinition module, string name, int oldParameterCount, string nowOn, object[] defaults)
		{
			//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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			//IL_00ff: 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_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Invalid comparison between Unknown and I4
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Invalid comparison between Unknown and I4
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			TypeDefinition type = module.GetType(nowOn);
			if (type == null)
			{
				return null;
			}
			int num = oldParameterCount + defaults.Length;
			MethodDefinition val = null;
			Enumerator<MethodDefinition> enumerator = type.Methods.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					MethodDefinition current = enumerator.Current;
					if (!(((MemberReference)current).Name != name) && current.IsStatic && ((MethodReference)current).Parameters.Count == num)
					{
						if (val != null)
						{
							return null;
						}
						val = current;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			if (val == null || ((MethodReference)val).HasGenericParameters)
			{
				return null;
			}
			MethodDefinition val2 = new MethodDefinition(name, (MethodAttributes)134, module.ImportReference(((MethodReference)val).ReturnType));
			for (int i = 0; i < oldParameterCount; i++)
			{
				((MethodReference)val2).Parameters.Add(new ParameterDefinition(((ParameterReference)((MethodReference)val).Parameters[i]).Name, (ParameterAttributes)0, module.ImportReference(((ParameterReference)((MethodReference)val).Parameters[i]).ParameterType)));
			}
			ILProcessor iLProcessor = val2.Body.GetILProcessor();
			Enumerator<ParameterDefinition> enumerator2 = ((MethodReference)val2).Parameters.GetEnumerator();
			try
			{
				while (enumerator2.MoveNext())
				{
					ParameterDefinition current2 = enumerator2.Current;
					iLProcessor.Emit(OpCodes.Ldarg, current2);
				}
			}
			finally
			{
				((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
			}
			for (int j = 0; j < defaults.Length; j++)
			{
				TypeReference parameterType = ((ParameterReference)((MethodReference)val).Parameters[oldParameterCount + j]).ParameterType;
				if (defaults[j] is bool flag && (int)parameterType.MetadataType == 2)
				{
					iLProcessor.Emit(flag ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
					continue;
				}
				if (defaults[j] is int num2 && (int)parameterType.MetadataType == 8)
				{
					iLProcessor.Emit(OpCodes.Ldc_I4, num2);
					continue;
				}
				return null;
			}
			iLProcessor.Emit(OpCodes.Call, module.ImportReference((MethodReference)(object)val));
			iLProcessor.Emit(OpCodes.Ret);
			return val2;
		}

		private static MethodDefinition EmitElsewhere(ModuleDefinition module, TypeDefinition owner, string name, string[] parameters, string nowOn, string nowCalled)
		{
			//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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Expected O, but got Unknown
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			TypeDefinition type = module.GetType(nowOn);
			if (type == null)
			{
				return null;
			}
			MethodDefinition val = null;
			Enumerator<MethodDefinition> enumerator = type.Methods.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					MethodDefinition current = enumerator.Current;
					if (((MemberReference)current).Name != nowCalled || !current.IsStatic || ((MethodReference)current).Parameters.Count != parameters.Length)
					{
						continue;
					}
					bool flag = true;
					for (int i = 0; i < parameters.Length; i++)
					{
						if (((MemberReference)((ParameterReference)((MethodReference)current).Parameters[i]).ParameterType).FullName != parameters[i])
						{
							flag = false;
							break;
						}
					}
					if (flag)
					{
						if (val != null)
						{
							return null;
						}
						val = current;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			if (val == null || ((MethodReference)val).HasGenericParameters)
			{
				return null;
			}
			MethodDefinition val2 = new MethodDefinition(name, (MethodAttributes)150, module.ImportReference(((MethodReference)val).ReturnType));
			Enumerator<ParameterDefinition> enumerator2 = ((MethodReference)val).Parameters.GetEnumerator();
			try
			{
				while (enumerator2.MoveNext())
				{
					ParameterDefinition current2 = enumerator2.Current;
					((MethodReference)val2).Parameters.Add(new ParameterDefinition(((ParameterReference)current2).Name, (ParameterAttributes)0, module.ImportReference(((ParameterReference)current2).ParameterType)));
				}
			}
			finally
			{
				((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
			}
			ILProcessor iLProcessor = val2.Body.GetILProcessor();
			enumerator2 = ((MethodReference)val2).Parameters.GetEnumerator();
			try
			{
				while (enumerator2.MoveNext())
				{
					ParameterDefinition current3 = enumerator2.Current;
					iLProcessor.Emit(OpCodes.Ldarg, current3);
				}
			}
			finally
			{
				((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
			}
			iLProcessor.Emit(OpCodes.Call, module.ImportReference((MethodReference)(object)val));
			iLProcessor.Emit(OpCodes.Ret);
			return val2;
		}

		private static Bridge Onto(string declaringType, string oldName, int parameterCount, string[] hops, string target, string because, string[] keptArgumentNames = null)
		{
			return new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = declaringType,
				OldName = oldName,
				ParameterCount = parameterCount,
				Because = because,
				Emit = (ModuleDefinition module, TypeDefinition type) => EmitOnto(module, type, oldName, hops, target, parameterCount, keptArgumentNames)
			};
		}

		private static MethodDefinition EmitOnto(ModuleDefinition module, TypeDefinition owner, string oldName, string[] hops, string target, int parameterCount, string[] keptArgumentNames = null)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			List<MethodDefinition> list = new List<MethodDefinition>();
			TypeDefinition val = owner;
			foreach (string member in hops)
			{
				MethodDefinition val2 = Getter(val, member);
				if (val2 == null)
				{
					return null;
				}
				list.Add(val2);
				TypeReference returnType = ((MethodReference)val2).ReturnType;
				val = ((returnType != null) ? returnType.Resolve() : null);
				if (val == null)
				{
					return null;
				}
			}
			MethodDefinition val3 = MethodUp(val, target, parameterCount);
			if (val3 == null || ((MethodReference)val3).HasGenericParameters)
			{
				return null;
			}
			MethodDefinition val4 = new MethodDefinition(oldName, (MethodAttributes)134, module.ImportReference(((MethodReference)val3).ReturnType));
			for (int j = 0; j < ((MethodReference)val3).Parameters.Count; j++)
			{
				ParameterDefinition val5 = ((MethodReference)val3).Parameters[j];
				string text = ((keptArgumentNames != null && j < keptArgumentNames.Length) ? keptArgumentNames[j] : ((ParameterReference)val5).Name);
				((MethodReference)val4).Parameters.Add(new ParameterDefinition(text, (ParameterAttributes)0, module.ImportReference(((ParameterReference)val5).ParameterType)));
			}
			ILProcessor iLProcessor = val4.Body.GetILProcessor();
			Instruction val6 = iLProcessor.Create(OpCodes.Nop);
			iLProcessor.Emit(OpCodes.Ldarg_0);
			for (int k = 0; k < list.Count; k++)
			{
				iLProcessor.Emit((k == 0) ? OpCodes.Call : OpCodes.Callvirt, module.ImportReference((MethodReference)(object)list[k]));
				iLProcessor.Emit(OpCodes.Dup);
				iLProcessor.Emit(OpCodes.Brfalse, val6);
			}
			Enumerator<ParameterDefinition> enumerator = ((MethodReference)val4).Parameters.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					ParameterDefinition current = enumerator.Current;
					iLProcessor.Emit(OpCodes.Ldarg, current);
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			iLProcessor.Emit(OpCodes.Callvirt, module.ImportReference((MethodReference)(object)val3));
			iLProcessor.Emit(OpCodes.Ret);
			iLProcessor.Append(val6);
			iLProcessor.Emit(OpCodes.Pop);
			if (((MemberReference)((MethodReference)val4).ReturnType).FullName != "System.Void")
			{
				EmitDefault(val4, iLProcessor, ((MethodReference)val4).ReturnType);
			}
			iLProcessor.Emit(OpCodes.Ret);
			val4.Body.InitLocals = true;
			return val4;
		}

		private static Bridge NowCalled(string declaringType, string oldName, int parameterCount, string newName, string because, string[] keptArgumentNames = null)
		{
			return new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = declaringType,
				OldName = oldName,
				ParameterCount = parameterCount,
				Because = because,
				Emit = (ModuleDefinition module, TypeDefinition type) => EmitCall(module, type, oldName, newName, parameterCount, keptArgumentNames)
			};
		}

		private static Bridge Defaulted(string declaringType, string name, string[] leading, object[] defaults, string because)
		{
			return new Bridge
			{
				Assembly = "Assembly-CSharp",
				DeclaringType = declaringType,
				OldName = name,
				ParameterCount = leading.Length,
				ParameterTypes = leading,
				AllowOverload = true,
				Because = because,
				Emit = (ModuleDefinition module, TypeDefinition type) => EmitWithDefaults(module, type, name, leading, defaults)
			};
		}

		private static MethodDefinition EmitPlayerToggle(ModuleDefinition module, TypeDefinition player, string name, bool on)
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			(TypeDefinition, MethodReference) tuple = Singleton(module, "Il2CppScheduleOne.PlayerScripts.PlayerCamera", player: true);
			(TypeDefinition, MethodReference) tuple2 = Singleton(module, "Il2CppScheduleOne.PlayerScripts.PlayerMovement", player: true);
			(TypeDefinition, MethodReference) tuple3 = Singleton(module, "Il2CppScheduleOne.PlayerScripts.PlayerInventory", player: true);
			(TypeDefinition, MethodReference) tuple4 = Singleton(module, "Il2CppScheduleOne.UI.HUD", player: false);
			if (tuple.Item2 == null || tuple2.Item2 == null || tuple3.Item2 == null || tuple4.Item2 == null)
			{
				return null;
			}
			MethodDefinition val = Method(tuple.Item1, "SetCanLook", 1);
			MethodDefinition val2 = Method(tuple2.Item1, "set_CanMove", 1);
			MethodDefinition val3 = Method(tuple3.Item1, "SetInventoryEnabled", 1);
			MethodDefinition val4 = Method(tuple4.Item1, "SetCrosshairVisible", 1);
			MethodDefinition val5 = Method(tuple.Item1, on ? "LockMouse" : "FreeMouse", 1);
			MethodDefinition val6 = Method(tuple.Item1, "ResetRotation", 0);
			if (val == null || val2 == null || val3 == null || val4 == null || val5 == null || (!on && val6 == null))
			{
				return null;
			}
			MethodDefinition val7 = new MethodDefinition(name, (MethodAttributes)150, module.TypeSystem.Void);
			if (!on)
			{
				((MethodReference)val7).Parameters.Add(new ParameterDefinition("freeMouse", (ParameterAttributes)0, module.TypeSystem.Boolean));
			}
			ILProcessor iLProcessor = val7.Body.GetILProcessor();
			OpCode val8 = (on ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
			iLProcessor.Emit(OpCodes.Call, tuple.Item2);
			iLProcessor.Emit(val8);
			iLProcessor.Emit(OpCodes.Callvirt, module.ImportReference((MethodReference)(object)val));
			if (!on)
			{
				iLProcessor.Emit(OpCodes.Call, tuple.Item2);
				iLProcessor.Emit(OpCodes.Callvirt, module.ImportReference((MethodReference)(object)val6));
			}
			iLProcessor.Emit(OpCodes.Call, tuple2.Item2);
			iLProcessor.Emit(val8);
			iLProcessor.Emit(OpCodes.Callvirt, module.ImportReference((MethodReference)(object)val2));
			iLProcessor.Emit(OpCodes.Call, tuple3.Item2);
			iLProcessor.Emit(val8);
			iLProcessor.Emit(OpCodes.Callvirt, module.ImportReference((MethodReference)(object)val3));
			if (on)
			{
				iLProcessor.Emit(OpCodes.Call, tuple4.Item2);
				iLProcessor.Emit(OpCodes.Ldc_I4_1);
				iLProcessor.Emit(OpCodes.Callvirt, module.ImportReference((MethodReference)(object)val4));
				iLProcessor.Emit(OpCodes.Call, tuple.I

Mods/Polyfill.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net.Http;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using HarmonyLib;
using Hash.Api;
using Il2CppFishNet;
using Il2CppFishNet.Managing;
using Il2CppFishNet.Managing.Object;
using Il2CppFishNet.Object;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne;
using Il2CppScheduleOne.AvatarFramework;
using Il2CppScheduleOne.Building.Doors;
using Il2CppScheduleOne.Economy;
using Il2CppScheduleOne.Employees;
using Il2CppScheduleOne.GameTime;
using Il2CppScheduleOne.Instancing;
using Il2CppScheduleOne.Management;
using Il2CppScheduleOne.Map;
using Il2CppScheduleOne.NPCs;
using Il2CppScheduleOne.NPCs.Behaviour;
using Il2CppScheduleOne.NPCs.Framework;
using Il2CppScheduleOne.NPCs.Schedules;
using Il2CppScheduleOne.Police;
using Il2CppScheduleOne.Product;
using Il2CppScheduleOne.Property;
using Il2CppScheduleOne.Tools;
using Il2CppScheduleOne.UI;
using Il2CppScheduleOne.UI.Handover;
using Il2CppScheduleOne.Weather;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using Polyfill.Boot;
using Polyfill.Contract;
using Polyfill.Core;
using Polyfill.ModFixes;
using Polyfill.Report;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "Polyfill", "0.11.16", "DooDesch", "https://github.com/DooDesch-Mods/ScheduleOne-Polyfill")]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("DooDesch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © DooDesch")]
[assembly: AssemblyFileVersion("0.11.16.0")]
[assembly: AssemblyInformationalVersion("0.11.16+a991f1874ad4639ca4259d22a7773c7b8489caa5")]
[assembly: AssemblyProduct("Polyfill")]
[assembly: AssemblyTitle("Polyfill")]
[assembly: AssemblyVersion("0.11.16.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DooDesch
{
	internal static class ModVersion
	{
		internal const string Current = "0.11.16";
	}
}
namespace Hash.Api
{
	public static class HashCommands
	{
		private const string BridgeTypeName = "Hash.Bridge.HashBridge, Hash";

		private static readonly List<string[]> _pending = new List<string[]>();

		private static Action<string, string, string, string> _declare;

		private static bool _bound;

		public static bool Available
		{
			get
			{
				Bind();
				return _bound;
			}
		}

		private static string Owner
		{
			get
			{
				try
				{
					return Assembly.GetExecutingAssembly().GetName().Name ?? "";
				}
				catch
				{
					return "";
				}
			}
		}

		public static void Add(string word, string description, string example = null)
		{
			if (!string.IsNullOrEmpty(word))
			{
				Bind();
				if (_declare != null)
				{
					Safely(word, description, example);
					return;
				}
				_pending.Add(new string[3]
				{
					word,
					description ?? "",
					example ?? ""
				});
			}
		}

		private static void Safely(string word, string description, string example)
		{
			try
			{
				_declare(word, description ?? "", example ?? "", Owner);
			}
			catch
			{
			}
		}

		private static void Bind()
		{
			if (_bound)
			{
				return;
			}
			try
			{
				Type type = Type.GetType("Hash.Bridge.HashBridge, Hash", throwOnError: false);
				if (type == null)
				{
					return;
				}
				_declare = type.GetField("Declare", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) as Action<string, string, string, string>;
				if (_declare == null)
				{
					return;
				}
				_bound = true;
				foreach (string[] item in _pending)
				{
					Safely(item[0], item[1], item[2]);
				}
				_pending.Clear();
			}
			catch
			{
			}
		}
	}
}
namespace Polyfill.Boot
{
	internal sealed class MelonConsentStore : IConsentStore
	{
		private const string Category = "Polyfill";

		internal static void Install()
		{
			Consent.Use(new MelonConsentStore());
		}

		public bool TryReadBool(string key, out bool value)
		{
			return Read(key, fallback: false, out value);
		}

		public bool TryReadInt(string key, out int value)
		{
			return Read(key, 0, out value);
		}

		private static bool Read<T>(string key, T fallback, out T value)
		{
			value = fallback;
			try
			{
				MelonPreferences_Category val = MelonPreferences.GetCategory("Polyfill") ?? MelonPreferences.CreateCategory("Polyfill");
				if (val == null)
				{
					return false;
				}
				MelonPreferences_Entry<T> val2 = val.GetEntry<T>(key) ?? val.CreateEntry<T>(key, fallback, key, Describe(key), false, false, (ValueValidator)null, (string)null);
				value = val2.Value;
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static string Describe(string key)
		{
			return key switch
			{
				"ShareFindings" => "Send anonymous findings - which mod, which symbol, repaired or not. Never your name, your paths or your save.", 
				"ShareFindingsAnswered" => "Whether the question has been answered. Clear this to be asked again.", 
				"ShareFindingsAsked" => "How many launches have asked. After three, the question stops.", 
				_ => key, 
			};
		}

		public void Write<T>(string key, T value, string description)
		{
			try
			{
				MelonPreferences_Category val = MelonPreferences.GetCategory("Polyfill") ?? MelonPreferences.CreateCategory("Polyfill");
				if (val != null)
				{
					MelonPreferences_Entry<T> entry = val.GetEntry<T>(key);
					if (entry == null)
					{
						val.CreateEntry<T>(key, value, key, description, false, false, (ValueValidator)null, (string)null);
					}
					else
					{
						entry.Value = value;
					}
				}
			}
			catch
			{
			}
		}

		public void Flush()
		{
			try
			{
				MelonPreferences.Save();
			}
			catch
			{
			}
		}
	}
}
namespace Polyfill.Core
{
	internal sealed class GeneratorIdentity
	{
		internal string GameAssemblyHash;

		internal string UnityVersion;

		internal string DumperVersion;

		internal string DumperScrsVersion;

		internal string Loader;

		internal bool IsKnown => !string.IsNullOrEmpty(GameAssemblyHash);

		internal string Digest()
		{
			string text = GameAssemblyHash ?? "";
			if (text.Length > 16)
			{
				text = text.Substring(0, 16);
			}
			return $"{text}/{UnityVersion}/{DumperVersion}/{DumperScrsVersion}/{Loader}";
		}

		internal static GeneratorIdentity Read()
		{
			GeneratorIdentity generatorIdentity = new GeneratorIdentity
			{
				Loader = MelonLoaderVersion()
			};
			string text = ConfigPath();
			if (text == null || !File.Exists(text))
			{
				return generatorIdentity;
			}
			try
			{
				string[] array = File.ReadAllLines(text);
				foreach (string text2 in array)
				{
					int num = text2.IndexOf('=');
					if (num > 0)
					{
						string text3 = text2.Substring(0, num).Trim();
						string text4 = text2.Substring(num + 1).Trim().Trim('"');
						switch (text3)
						{
						case "GameAssemblyHash":
							generatorIdentity.GameAssemblyHash = text4;
							break;
						case "UnityVersion":
							generatorIdentity.UnityVersion = text4;
							break;
						case "DumperVersion":
							generatorIdentity.DumperVersion = text4;
							break;
						case "DumperSCRSVersion":
							generatorIdentity.DumperScrsVersion = text4;
							break;
						}
					}
				}
			}
			catch
			{
			}
			return generatorIdentity;
		}

		internal static string ConfigPath()
		{
			try
			{
				string melonLoaderDirectory = MelonEnvironment.MelonLoaderDirectory;
				if (string.IsNullOrEmpty(melonLoaderDirectory))
				{
					return null;
				}
				return Path.Combine(melonLoaderDirectory, "Dependencies", "Il2CppAssemblyGenerator", "Config.cfg");
			}
			catch
			{
				return null;
			}
		}

		private static string MelonLoaderVersion()
		{
			try
			{
				return typeof(MelonPlugin).Assembly.GetName().Version?.ToString() ?? "?";
			}
			catch
			{
				return "?";
			}
		}
	}
}
namespace Polyfill.Contract
{
	internal static class CommandTable
	{
		internal sealed class Command
		{
			internal string Name;

			internal string Help;

			internal string Example;
		}

		internal static readonly Command[] All = new Command[12]
		{
			C("polyfill", "what Polyfill found in your mods at startup", "polyfill"),
			C("polyfilllist", "every mod, with its verdict", "polyfilllist"),
			C("polyfillshow", "everything one mod asks for that is missing", "polyfillshow hitman"),
			C("polyfillunfixed", "only what cannot be pointed at anything", "polyfillunfixed hitman"),
			C("polyfillexport", "write one file with everything, ready to send", "polyfillexport"),
			C("polyfillprobe", "can the runtime resolve this type, and does Type::Member really run?", "polyfillprobe Il2CppScheduleOne.UI.InputPromptsCanvas::LoadModule objectselector"),
			C("polyfillprefab", "does the game still have this prefab, and what is near it", "polyfillprefab Basic Metal Glass Door"),
			C("polyfillfixes", "the per-mod fixes, and switch one off", "polyfillfixes off s1mapi-prefabs"),
			C("polyfillrestore", "undo every repair, restart to take effect", "polyfillrestore"),
			C("polyfillregen", "have MelonLoader rebuild the game's generated assemblies", "polyfillregen"),
			C("polyfillshare", "share anonymous findings, or see what would be sent", "polyfillshare show"),
			C("polyfillhelp", "list the polyfill commands", "polyfillhelp")
		};

		internal static bool Owns(string command)
		{
			if (string.IsNullOrEmpty(command))
			{
				return false;
			}
			Command[] all = All;
			for (int i = 0; i < all.Length; i++)
			{
				if (string.Equals(all[i].Name, command, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static Command C(string name, string help, string example)
		{
			return new Command
			{
				Name = name,
				Help = help,
				Example = example
			};
		}
	}
	internal interface IConsentStore
	{
		bool TryReadBool(string key, out bool value);

		bool TryReadInt(string key, out int value);

		void Write<T>(string key, T value, string description);

		void Flush();
	}
	internal static class Consent
	{
		internal sealed class State
		{
			internal bool Sharing;

			internal bool Answered;

			internal int Asked;
		}

		internal const string SharingKey = "ShareFindings";

		internal const string AnsweredKey = "ShareFindingsAnswered";

		internal const string AskedKey = "ShareFindingsAsked";

		private static IConsentStore _store;

		internal static bool Sharing => Read().Sharing;

		internal static void Use(IConsentStore store)
		{
			_store = store;
		}

		internal static State Read()
		{
			State state = new State();
			IConsentStore store = _store;
			if (store == null)
			{
				return state;
			}
			try
			{
				if (store.TryReadBool("ShareFindings", out var value))
				{
					state.Sharing = value;
				}
				if (store.TryReadBool("ShareFindingsAnswered", out var value2))
				{
					state.Answered = value2;
				}
				if (store.TryReadInt("ShareFindingsAsked", out var value3))
				{
					state.Asked = value3;
				}
			}
			catch
			{
			}
			return state;
		}

		internal static void Write(bool sharing, bool answered)
		{
			IConsentStore store = _store;
			if (store == null)
			{
				return;
			}
			try
			{
				store.Write("ShareFindings", sharing, "Send anonymous findings - which mod, which symbol, repaired or not. Never your name, your paths or your save.");
				store.Write("ShareFindingsAnswered", answered, "Whether the question has been answered. Clear this to be asked again.");
				store.Flush();
			}
			catch
			{
			}
		}

		internal static void CountOneAsk(State state)
		{
			IConsentStore store = _store;
			if (store == null)
			{
				return;
			}
			try
			{
				store.Write("ShareFindingsAsked", state.Asked + 1, "How many launches have asked. After three, the question stops.");
				store.Flush();
			}
			catch
			{
			}
		}
	}
	internal static class CoveredElsewhere
	{
		internal sealed class Entry
		{
			internal string Type;

			internal string Member;

			internal string FixId;

			internal string Because;
		}

		internal static readonly Entry[] All = new Entry[3]
		{
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.AmountSelector",
				Member = "get_onPriceChanged",
				FixId = "amount-changed-after-override",
				Because = "the UnityEvent this returned cannot be handed back - interop wrappers are pooled by weak reference, so it could not be the same object twice - but the change it announced is raised again when a mod replaces the setter that used to raise it"
			},
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.Handover.HandoverScreen",
				Member = "get_OriginalItemLocations",
				FixId = "otc-smart-fill-tracking",
				Because = "the dictionary and the nested enum it was keyed by are both gone, and nothing of that shape can be handed back - but it was write-only bookkeeping even in 0.4.5f2, so the fix drops the call instead of answering it"
			},
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.Handover.HandoverScreen/EItemSource",
				Member = null,
				FixId = "otc-smart-fill-tracking",
				Because = "the enum only ever typed HandoverScreen.OriginalItemLocations, and 0.4.6 deleted both - a copy would have its own identity and could not satisfy the signature. The one method that names it is OverTheCounter's TrackItemAsPlayer, and the fix takes the call to it out, so nothing reaches the name"
			}
		};

		internal static Entry For(string type, string member)
		{
			if (type == null || member == null)
			{
				return null;
			}
			Entry[] all = All;
			foreach (Entry entry in all)
			{
				if (string.Equals(entry.Type, type, StringComparison.Ordinal) && string.Equals(entry.Member, member, StringComparison.Ordinal))
				{
					return entry;
				}
			}
			return null;
		}

		internal static Entry ForType(string type)
		{
			if (type == null)
			{
				return null;
			}
			Entry[] all = All;
			foreach (Entry entry in all)
			{
				if (entry.Member == null && string.Equals(entry.Type, type, StringComparison.Ordinal))
				{
					return entry;
				}
			}
			return null;
		}
	}
	internal readonly struct GameVersion : IComparable<GameVersion>, IEquatable<GameVersion>
	{
		internal readonly int[] Parts;

		internal readonly string Raw;

		internal static readonly GameVersion Unknown = new GameVersion(null, "");

		internal bool IsKnown
		{
			get
			{
				if (Parts != null)
				{
					return Parts.Length != 0;
				}
				return false;
			}
		}

		private GameVersion(int[] parts, string raw)
		{
			Parts = parts;
			Raw = raw;
		}

		internal static bool TryParse(string text, out GameVersion version)
		{
			version = Unknown;
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			List<int> list = new List<int>(4);
			long num = 0L;
			bool flag = false;
			foreach (char c in text)
			{
				if (c >= '0' && c <= '9')
				{
					if (num < 214748364)
					{
						num = num * 10 + (c - 48);
					}
					flag = true;
				}
				else if (flag)
				{
					list.Add((int)num);
					num = 0L;
					flag = false;
				}
			}
			if (flag)
			{
				list.Add((int)num);
			}
			if (list.Count == 0)
			{
				return false;
			}
			version = new GameVersion(list.ToArray(), text);
			return true;
		}

		internal static GameVersion Parse(string text)
		{
			if (!TryParse(text, out var version))
			{
				return Unknown;
			}
			return version;
		}

		public int CompareTo(GameVersion other)
		{
			int[] array = Parts ?? Array.Empty<int>();
			int[] array2 = other.Parts ?? Array.Empty<int>();
			int num = Math.Min(array.Length, array2.Length);
			for (int i = 0; i < num; i++)
			{
				if (array[i] != array2[i])
				{
					if (array[i] >= array2[i])
					{
						return 1;
					}
					return -1;
				}
			}
			return array.Length.CompareTo(array2.Length);
		}

		internal bool StartsWith(GameVersion prefix, int count)
		{
			if (Parts == null || prefix.Parts == null)
			{
				return false;
			}
			if (count > prefix.Parts.Length || count > Parts.Length)
			{
				return false;
			}
			for (int i = 0; i < count; i++)
			{
				if (Parts[i] != prefix.Parts[i])
				{
					return false;
				}
			}
			return true;
		}

		public bool Equals(GameVersion other)
		{
			if (CompareTo(other) == 0)
			{
				return IsKnown == other.IsKnown;
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is GameVersion other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			int num = 17;
			if (Parts != null)
			{
				int[] parts = Parts;
				foreach (int num2 in parts)
				{
					num = num * 31 + num2;
				}
			}
			return num;
		}

		public override string ToString()
		{
			if (!IsKnown)
			{
				return "unknown";
			}
			return Raw;
		}

		public static bool operator <(GameVersion a, GameVersion b)
		{
			return a.CompareTo(b) < 0;
		}

		public static bool operator >(GameVersion a, GameVersion b)
		{
			return a.CompareTo(b) > 0;
		}

		public static bool operator <=(GameVersion a, GameVersion b)
		{
			return a.CompareTo(b) <= 0;
		}

		public static bool operator >=(GameVersion a, GameVersion b)
		{
			return a.CompareTo(b) >= 0;
		}

		public static bool operator ==(GameVersion a, GameVersion b)
		{
			return a.Equals(b);
		}

		public static bool operator !=(GameVersion a, GameVersion b)
		{
			return !a.Equals(b);
		}
	}
	internal static class GameVersionSource
	{
		private static string _raw;

		internal static string Raw => _raw ?? (_raw = Read());

		internal static GameVersion Current => GameVersion.Parse(Raw);

		private static string Read()
		{
			string[] array = new string[2] { "MelonLoader.InternalUtils.UnityInformationHandler, MelonLoader", "MelonLoader.MelonUtils, MelonLoader" };
			foreach (string typeName in array)
			{
				try
				{
					if ((Type.GetType(typeName, throwOnError: false)?.GetProperty("GameVersion", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(null) is string { Length: >0 } text)
					{
						return text;
					}
				}
				catch
				{
				}
			}
			return "unknown";
		}

		internal static string Disagreement(string other)
		{
			if (string.IsNullOrEmpty(other))
			{
				return null;
			}
			if (GameVersion.Parse(other) == Current)
			{
				return null;
			}
			return $"MelonLoader says the game is '{Raw}' and Unity says '{other}'. Polyfill went with " + "MelonLoader's, which is the one every version decision was made against.";
		}
	}
	internal static class SplitScreens
	{
		internal sealed class Entry
		{
			internal string Type;

			internal string Station;

			internal string StationName;

			internal bool HasRemoveUi;
		}

		private const string Stations = "Il2CppScheduleOne.UI.Stations.";

		private const string Objects = "Il2CppScheduleOne.ObjectScripts.";

		internal static readonly Entry[] All = new Entry[5]
		{
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.Stations.PackagingStationCanvas",
				Station = "Il2CppScheduleOne.ObjectScripts.PackagingStation",
				StationName = "station",
				HasRemoveUi = true
			},
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.Stations.BrickPressCanvas",
				Station = "Il2CppScheduleOne.ObjectScripts.BrickPress",
				StationName = "press",
				HasRemoveUi = true
			},
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.Stations.LabOvenCanvas",
				Station = "Il2CppScheduleOne.ObjectScripts.LabOven",
				StationName = "oven",
				HasRemoveUi = true
			},
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.Stations.CauldronCanvas",
				Station = "Il2CppScheduleOne.ObjectScripts.Cauldron",
				StationName = "cauldron",
				HasRemoveUi = true
			},
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.Stations.DryingRackCanvas",
				Station = "Il2CppScheduleOne.ObjectScripts.DryingRack",
				StationName = "rack",
				HasRemoveUi = false
			}
		};
	}
	internal static class GrownOverloads
	{
		internal sealed class Entry
		{
			internal string Type;

			internal string Name;

			internal string[] OldParameters;

			internal string Because;
		}

		internal static readonly Entry[] All = new Entry[4]
		{
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.StorageMenu",
				Name = "Open",
				OldParameters = new string[3] { "System.String", "System.String", "Il2CppScheduleOne.ItemFramework.IItemSlotOwner" },
				Because = "0.4.6 gave every StorageMenu.Open a closing callback"
			},
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.StorageMenu",
				Name = "Open",
				OldParameters = new string[3] { "Il2CppScheduleOne.ItemFramework.IItemSlotOwner", "System.String", "System.String" },
				Because = "0.4.6 gave every StorageMenu.Open a closing callback"
			},
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.StorageMenu",
				Name = "Open",
				OldParameters = new string[1] { "Il2CppScheduleOne.Storage.StorageEntity" },
				Because = "the third Open took the same trailing callback as its two siblings and was missed when they were listed (0.4.5f2 Open_Public_Virtual_New_Void_StorageEntity_0 against 0.4.6f13 ..._StorageEntity_Action_0)"
			},
			new Entry
			{
				Type = "Il2CppScheduleOne.Economy.CustomerData",
				Name = "GetOrderDays",
				OldParameters = new string[2] { "System.Single", "System.Single" },
				Because = "GetOrderDays stopped returning the list and started filling one it is handed"
			}
		};

		internal static bool Doubled(string type, string name)
		{
			Entry[] all = All;
			foreach (Entry entry in all)
			{
				if (entry.Name == name && string.Equals(entry.Type, type, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		internal static bool IsStandIn(string type, string name, int parameterCount)
		{
			Entry[] all = All;
			foreach (Entry entry in all)
			{
				if (entry.Name == name && entry.OldParameters.Length == parameterCount && string.Equals(entry.Type, type, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class Headless
	{
		private static bool _asked;

		private static bool _answer;

		private static string _why;

		internal static bool Yes(out string why)
		{
			if (!_asked)
			{
				_asked = true;
				_answer = Look(out _why);
			}
			why = _why;
			return _answer;
		}

		internal static bool Yes()
		{
			string why;
			return Yes(out why);
		}

		private static bool Look(out string why)
		{
			why = null;
			try
			{
				string[] commandLineArgs = Environment.GetCommandLineArgs();
				for (int i = 0; i < commandLineArgs.Length; i++)
				{
					switch (commandLineArgs[i].TrimStart('-').ToLowerInvariant())
					{
					case "batchmode":
						why = "the game is running in batch mode";
						return true;
					case "nographics":
						why = "the game is running without graphics";
						return true;
					case "dedicated-server":
					case "dedicatedserver":
						why = "this is a dedicated server";
						return true;
					}
				}
			}
			catch (Exception)
			{
			}
			return false;
		}
	}
	internal interface ILog
	{
		void Msg(string message);

		void Warning(string message);

		void Error(string message);
	}
	internal static class NarrowedOverloads
	{
		internal sealed class Entry
		{
			internal string Type;

			internal string Name;

			internal string[] RealParameters;

			internal string ParameterName;

			internal string Because;
		}

		internal static readonly Entry[] All = new Entry[1]
		{
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.Phone.CounterofferInterface",
				Name = "ChangeQuantity",
				RealParameters = new string[1] { "System.Single" },
				ParameterName = "change",
				Because = "the quantity step took an int until 0.4.5f2 and takes a float now, and a second ChangeQuantity(string) arrived beside it for the text box (CounterofferInterface.cs:191-207)"
			}
		};
	}
	internal static class PolyfillPaths
	{
		internal const string BackupSuffix = ".polyfill-orig";

		internal const string TempSuffix = ".polyfill-tmp";

		internal const string FolderName = "Polyfill";

		internal const string LastRunFile = "last-run.txt";

		internal const string ReportFile = "polyfill-report.txt";

		internal const string StampFileName = "interop.stamp";

		internal const string RestorePendingFile = "restore-pending";

		internal static string Folder(string userDataDirectory)
		{
			return Path.Combine(userDataDirectory ?? ".", "Polyfill");
		}

		internal static string LastRun(string userDataDirectory)
		{
			return Path.Combine(Folder(userDataDirectory), "last-run.txt");
		}

		internal static string Report(string userDataDirectory)
		{
			return Path.Combine(Folder(userDataDirectory), "polyfill-report.txt");
		}

		internal static string Stamp(string userDataDirectory)
		{
			return Path.Combine(Folder(userDataDirectory), "interop.stamp");
		}

		internal static string RestorePending(string userDataDirectory)
		{
			return Path.Combine(Folder(userDataDirectory), "restore-pending");
		}

		internal static string Backup(string assemblyPath)
		{
			return assemblyPath + ".polyfill-orig";
		}
	}
	internal static class RenamedMethods
	{
		internal sealed class Entry
		{
			internal string Type;

			internal string OldName;

			internal string NewName;

			internal string Because;
		}

		internal static readonly Entry[] All = new Entry[2]
		{
			new Entry
			{
				Type = "Il2CppScheduleOne.ObjectScripts.PackagingStation",
				OldName = "Open",
				NewName = "Use",
				Because = "0.4.5f2 PackagingStation.Open() set the camera up and opened the canvas; 0.4.6f13 Use() pushes a state and opens the canvas, on the same type (PackagingStation.cs:405)"
			},
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.Handover.HandoverScreenPriceSelector",
				OldName = "SetPrice",
				NewName = "SetAmount",
				Because = "the price control became the game's general amount box in 0.4.6, and SetPrice(float) became SetAmount(float) on it (AmountSelector.cs:61)"
			}
		};

		internal static string Successor(string type, string oldName)
		{
			if (type == null || oldName == null)
			{
				return null;
			}
			Entry[] all = All;
			foreach (Entry entry in all)
			{
				if (string.Equals(entry.Type, type, StringComparison.Ordinal) && string.Equals(entry.OldName, oldName, StringComparison.Ordinal))
				{
					return entry.NewName;
				}
			}
			return null;
		}

		internal static string Because(string type, string oldName)
		{
			if (type == null || oldName == null)
			{
				return null;
			}
			Entry[] all = All;
			foreach (Entry entry in all)
			{
				if (string.Equals(entry.Type, type, StringComparison.Ordinal) && string.Equals(entry.OldName, oldName, StringComparison.Ordinal))
				{
					return entry.Because;
				}
			}
			return null;
		}
	}
	internal static class RenamedParameters
	{
		internal sealed class Entry
		{
			internal string Type;

			internal string Method;

			internal int ParameterCount;

			internal int Index;

			internal string OldName;

			internal string NewName;

			internal string Because;
		}

		internal static readonly Entry[] All = new Entry[2]
		{
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.Shop.ShopInterface",
				Method = "SetIsOpen",
				ParameterCount = 1,
				Index = 0,
				OldName = "isOpen",
				NewName = "open",
				Because = "the flag kept its type and its meaning and lost its name in 0.4.6"
			},
			new Entry
			{
				Type = "Il2CppScheduleOne.UI.AmountSelector",
				Method = "SetAmount",
				ParameterCount = 1,
				Index = 0,
				OldName = "price",
				NewName = "amount",
				Because = "SetPrice(float price) became SetAmount(float amount) when the handover price control turned into the game's general amount box (AmountSelector.cs:61)"
			}
		};

		internal static IEnumerable<Entry> For(string type, string method, int parameterCount)
		{
			Entry[] all = All;
			foreach (Entry entry in all)
			{
				if (entry.Method == method && entry.ParameterCount == parameterCount && string.Equals(entry.Type, type, StringComparison.Ordinal))
				{
					yield return entry;
				}
			}
		}
	}
	internal static class RenamedTypes
	{
		internal static readonly string[] StandIns = new string[10] { "Il2CppScheduleOne.UI.Stations.MixingStationCanvas", "Il2CppScheduleOne.UI.Stations.ChemistryStationCanvas", "Il2CppScheduleOne.UI.Stations.CauldronCanvas", "Il2CppScheduleOne.UI.Stations.DryingRackCanvas", "Il2CppScheduleOne.UI.Handover.HandoverScreenPriceSelector", "Il2CppScheduleOne.Weather.WeatherConditions", "Il2CppScheduleOne.DevUtilities.ExitAction", "Il2CppScheduleOne.UI.ATM.ATMInterface", "Il2CppScheduleOne.UI.Stations.Drying_rack.DryingOperationUI", "Il2CppScheduleOne.UI.MainMenu.MainMenuScreen" };

		internal static bool IsStandIn(string fullName)
		{
			if (fullName == null)
			{
				return false;
			}
			string[] standIns = StandIns;
			for (int i = 0; i < standIns.Length; i++)
			{
				if (string.Equals(standIns[i], fullName, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class ReplacedMethods
	{
		internal sealed class Replacement
		{
			internal string Name;

			internal string[] Parameters = new string[0];

			internal object[] Arguments = new object[0];
		}

		internal sealed class Entry
		{
			internal string Type;

			internal string OldName;

			internal string[] Parameters;

			internal string[] ParameterNames;

			internal Replacement[] Replacements;

			internal string Because;
		}

		private const string Bool = "System.Boolean";

		private const string Management = "Il2CppScheduleOne.UI.Management.";

		internal static readonly Entry[] All = new Entry[2]
		{
			Selector("ObjectSelector"),
			Selector("TransitEntitySelector")
		};

		private static Entry Selector(string type)
		{
			Entry entry = new Entry();
			entry.Type = "Il2CppScheduleOne.UI.Management." + type;
			entry.OldName = "Close";
			entry.Parameters = new string[2] { "System.Boolean", "System.Boolean" };
			entry.ParameterNames = new string[2] { "returnToClipboard", "pushChanges" };
			entry.Replacements = new Replacement[2]
			{
				new Replacement
				{
					Name = "CloseAndSubmit",
					Arguments = new object[2] { true, true }
				},
				new Replacement
				{
					Name = "CloseAndCancel",
					Arguments = new object[2] { true, false }
				}
			};
			entry.Because = "0.4.5f2 " + type + ".Close(bool returnToClipboard, bool pushChanges); 0.4.6f13 has CloseAndSubmit and CloseAndCancel over a shared OnClose that always returns to the clipboard (ObjectSelector.cs:120-143)";
			return entry;
		}
	}
	internal static class Outcome
	{
		internal const string Applied = "applied";

		internal const string Refused = "refused";

		internal const string StoodDown = "stood-down";

		internal const string None = "none";
	}
	internal sealed class Finding
	{
		internal string Kind;

		internal bool Note;

		internal string Scope;

		internal string Symbol;

		internal string Reason;

		internal string Hint;

		internal string Site;

		internal string Outcome = "none";

		internal string OutcomeDetail;

		internal bool Covered;

		internal string RepairKey;

		internal bool Fixable => !string.IsNullOrEmpty(Hint);
	}
	internal sealed class ModReport
	{
		internal string Path;

		internal string AssemblyName;

		internal string Name;

		internal string Version;

		internal string Author;

		internal int TypeRefs;

		internal int MemberRefs;

		internal int HarmonyTargetsChecked;

		internal readonly List<Finding> Findings = new List<Finding>();

		internal readonly List<string> Namespaces = new List<string>();

		internal string Display
		{
			get
			{
				if (string.IsNullOrEmpty(Name))
				{
					if (string.IsNullOrEmpty(AssemblyName))
					{
						return System.IO.Path.GetFileName(Path ?? "");
					}
					return AssemblyName;
				}
				return Name;
			}
		}

		internal string Verdict
		{
			get
			{
				bool flag = false;
				foreach (Finding finding in Findings)
				{
					if (!finding.Note)
					{
						flag = true;
						if (!(finding.Outcome == "applied") && !finding.Covered)
						{
							return "blocked";
						}
					}
				}
				if (!flag)
				{
					return "clean";
				}
				return "adaptable";
			}
		}
	}
	internal sealed class RunReport
	{
		internal const int Format = 2;

		internal const string HeaderPrefix = "# polyfill-report ";

		private const char CarriageReturn = '\r';

		internal string Generated = "";

		internal string Game = "?";

		internal string Interop = "";

		internal int AssemblyCount;

		internal readonly List<ModReport> Mods = new List<ModReport>();

		internal readonly List<string> Dropped = new List<string>();

		internal string Problem;

		internal string Text()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("# polyfill-report " + 2);
			stringBuilder.AppendLine("# generated=" + Escape(Generated));
			stringBuilder.AppendLine("# game=" + Escape(Game));
			stringBuilder.AppendLine("# interop=" + Escape(Interop));
			stringBuilder.AppendLine("# assemblies=" + AssemblyCount);
			stringBuilder.AppendLine("# mods=" + Mods.Count);
			foreach (ModReport mod in Mods)
			{
				stringBuilder.AppendLine(string.Join("|", "M", Escape(mod.Path), Escape(mod.AssemblyName), Escape(mod.Name), Escape(mod.Version), Escape(mod.Author), mod.Verdict, mod.TypeRefs.ToString(), mod.MemberRefs.ToString(), mod.HarmonyTargetsChecked.ToString(), mod.Findings.Count.ToString()));
				foreach (Finding finding in mod.Findings)
				{
					stringBuilder.AppendLine(string.Join("|", "F", Escape(mod.Path), Escape(finding.Kind), Escape(finding.Scope), Escape(finding.Symbol), Escape(finding.Reason), Escape(finding.Hint), Escape(finding.Site), Escape(finding.Outcome), Escape(finding.OutcomeDetail)));
				}
			}
			foreach (ModReport mod2 in Mods)
			{
				if (mod2.Namespaces.Count > 0)
				{
					stringBuilder.AppendLine(string.Join("|", "N", Escape(mod2.Path), Escape(string.Join(",", mod2.Namespaces))));
				}
			}
			foreach (string item in Dropped)
			{
				stringBuilder.AppendLine("D|" + Escape(item));
			}
			return stringBuilder.ToString();
		}

		internal static RunReport Read(IEnumerable<string> lines)
		{
			RunReport runReport = new RunReport();
			Dictionary<string, ModReport> dictionary = new Dictionary<string, ModReport>(StringComparer.OrdinalIgnoreCase);
			bool flag = false;
			foreach (string line in lines)
			{
				if (line == null)
				{
					continue;
				}
				string text = line.TrimEnd('\r');
				if (!flag)
				{
					if (!text.StartsWith("# polyfill-report ", StringComparison.Ordinal))
					{
						runReport.Problem = "this is not a Polyfill report";
						return runReport;
					}
					string text2 = text.Substring("# polyfill-report ".Length).Trim();
					if (!int.TryParse(text2, out var result))
					{
						runReport.Problem = "the format is written as '" + text2 + "', which is not a number";
						return runReport;
					}
					if (result > 2)
					{
						runReport.Problem = $"it is format {result} and this build reads {2}. " + "Polyfill.dll in Mods/ and Polyfill.Boot.dll in Plugins/ are from different releases - update both.";
						return runReport;
					}
					flag = true;
				}
				else if (text.StartsWith("# game=", StringComparison.Ordinal))
				{
					runReport.Game = text.Substring(7);
				}
				else if (text.StartsWith("# interop=", StringComparison.Ordinal))
				{
					runReport.Interop = text.Substring(10);
				}
				else if (text.StartsWith("# generated=", StringComparison.Ordinal))
				{
					runReport.Generated = text.Substring(12);
				}
				else if (text.StartsWith("# assemblies=", StringComparison.Ordinal))
				{
					runReport.AssemblyCount = Int(text.Substring(13));
				}
				else
				{
					if (text.Length == 0 || text[0] == '#')
					{
						continue;
					}
					string[] array = text.Split('|');
					switch (array[0])
					{
					case "M":
						if (array.Length >= 10)
						{
							ModReport modReport = new ModReport
							{
								Path = array[1],
								AssemblyName = array[2],
								Name = array[3],
								Version = array[4],
								Author = array[5],
								TypeRefs = Int(array[7]),
								MemberRefs = Int(array[8]),
								HarmonyTargetsChecked = Int(array[9])
							};
							runReport.Mods.Add(modReport);
							dictionary[modReport.Path] = modReport;
						}
						break;
					case "F":
					{
						if (array.Length >= 8 && dictionary.TryGetValue(array[1], out var value))
						{
							value.Findings.Add(new Finding
							{
								Kind = array[2],
								Scope = array[3],
								Symbol = array[4],
								Reason = array[5],
								Hint = array[6],
								Site = array[7],
								Outcome = ((array.Length > 8) ? array[8] : "none"),
								OutcomeDetail = ((array.Length > 9) ? array[9] : "")
							});
						}
						break;
					}
					case "N":
					{
						if (array.Length < 3 || !dictionary.TryGetValue(array[1], out var value2))
						{
							break;
						}
						string[] array2 = array[2].Split(',');
						foreach (string text3 in array2)
						{
							if (!string.IsNullOrEmpty(text3))
							{
								value2.Namespaces.Add(text3);
							}
						}
						break;
					}
					case "D":
						if (array.Length >= 2)
						{
							runReport.Dropped.Add(array[1]);
						}
						break;
					}
				}
			}
			if (!flag)
			{
				runReport.Problem = "the file is empty";
			}
			return runReport;
		}

		private static int Int(string s)
		{
			if (!int.TryParse(s, out var result))
			{
				return 0;
			}
			return result;
		}

		internal static string Escape(string value)
		{
			if (!string.IsNullOrEmpty(value))
			{
				return value.Replace('|', '/').Replace('\r', ' ').Replace('\n', ' ');
			}
			return "";
		}
	}
	internal static class SplitMethods
	{
		internal sealed class Entry
		{
			internal string Type;

			internal string Name;

			internal string[] StandInParameters;

			internal string[] RealParameters;

			internal string Because;
		}

		internal static readonly Entry[] All = new Entry[1]
		{
			new Entry
			{
				Type = "Il2CppScheduleOne.Tools.ManagementClipboard",
				Name = "Close",
				StandInParameters = new string[1] { "System.Boolean" },
				RealParameters = new string[0],
				Because = "the player's own exit calls Close() and never the flagged one, so a mod's postfix on the old signature stopped seeing ordinary closes"
			}
		};
	}
	internal sealed class VersionDb
	{
		internal static class Op
		{
			internal const string Rename = "R";

			internal const string Removed = "-";

			internal const string Ambiguous = "?";

			internal const string Merge = "M";
		}

		internal static class Origin
		{
			internal const string Derived = "derived";

			internal const string Curated = "curated";

			internal const string Override = "override";
		}

		internal sealed class Row
		{
			internal string Op;

			internal string Kind;

			internal string Type;

			internal string From;

			internal string To;

			internal string RuleName;

			internal string Confidence;

			internal string Note;

			internal string Origin;

			internal int Arity;

			internal string Key => Kind + "|" + Type + "|" + From + "|" + Arity;

			internal string NameKey => Kind + "|" + Type + "|" + From;
		}

		internal sealed class Step
		{
			internal GameVersion From;

			internal GameVersion To;

			internal string Source = "";

			internal readonly Dictionary<string, Row> Renames = new Dictionary<string, Row>(StringComparer.Ordinal);

			internal readonly Dictionary<string, Row> Removed = new Dictionary<string, Row>(StringComparer.Ordinal);

			internal readonly HashSet<string> Refused = new HashSet<string>(StringComparer.Ordinal);
		}

		internal const string HeaderPrefix = "# polyfill-versiondb ";

		internal const int Format = 1;

		private readonly List<Step> _steps = new List<Step>();

		private readonly Dictionary<string, Row> _overrides = new Dictionary<string, Row>(StringComparer.Ordinal);

		private readonly List<VersionRange> _overrideRanges = new List<VersionRange>();

		internal readonly List<string> Notes = new List<string>();

		internal int RenameCount { get; private set; }

		internal int StepCount => _steps.Count;

		internal GameVersion Newest
		{
			get
			{
				if (_steps.Count != 0)
				{
					List<Step> steps = _steps;
					return steps[steps.Count - 1].To;
				}
				return GameVersion.Unknown;
			}
		}

		internal static VersionDb Load(IEnumerable<(string Name, IEnumerable<string> Lines)> files)
		{
			VersionDb versionDb = new VersionDb();
			Dictionary<string, Step> dictionary = new Dictionary<string, Step>(StringComparer.Ordinal);
			foreach (var file in files)
			{
				try
				{
					versionDb.ReadOne(file.Name, file.Lines, dictionary);
				}
				catch (Exception ex)
				{
					versionDb.Notes.Add(file.Name + " could not be read (" + ex.Message + ")");
				}
			}
			versionDb._steps.AddRange(dictionary.Values);
			versionDb._steps.Sort((Step a, Step b) => a.From.CompareTo(b.From));
			foreach (Step step in versionDb._steps)
			{
				versionDb.RenameCount += step.Renames.Count;
			}
			return versionDb;
		}

		private void ReadOne(string name, IEnumerable<string> lines, Dictionary<string, Step> steps)
		{
			Step step = null;
			VersionRange range = null;
			bool flag = false;
			List<Row> list = new List<Row>();
			foreach (string line in lines)
			{
				if (line == null)
				{
					continue;
				}
				string text = line.TrimEnd('\r');
				if (!flag)
				{
					if (!text.StartsWith("# polyfill-versiondb ", StringComparison.Ordinal))
					{
						Notes.Add(name + " is not a version database");
						return;
					}
					if (!int.TryParse(text.Substring("# polyfill-versiondb ".Length).Trim(), out var result) || result > 1)
					{
						Notes.Add(name + " is a newer format than this build reads; skipped");
						return;
					}
					flag = true;
				}
				else if (text.StartsWith("# from=", StringComparison.Ordinal))
				{
					(step ?? (step = new Step())).From = GameVersion.Parse(text.Substring(7));
				}
				else if (text.StartsWith("# to=", StringComparison.Ordinal))
				{
					(step ?? (step = new Step())).To = GameVersion.Parse(text.Substring(5));
				}
				else if (text.StartsWith("# source=", StringComparison.Ordinal))
				{
					(step ?? (step = new Step())).Source = text.Substring(9);
				}
				else if (text.StartsWith("# applies=", StringComparison.Ordinal))
				{
					if (!VersionRange.TryParse(text.Substring(10), out range, out var problem))
					{
						Notes.Add($"{name} applies to '{text.Substring(10)}', which is not a range ({problem})");
						return;
					}
				}
				else
				{
					if (text.Length == 0 || text[0] == '#')
					{
						continue;
					}
					Row row = Parse(text);
					if (row == null)
					{
						continue;
					}
					if (range != null)
					{
						TakeOverride(name, row, range);
						continue;
					}
					if (step == null)
					{
						Notes.Add(name + " has rows but no step");
						return;
					}
					switch (row.Op)
					{
					case "R":
						list.Add(row);
						break;
					case "-":
						step.Removed[row.Key] = row;
						break;
					case "?":
					case "M":
						step.Refused.Add(row.NameKey);
						break;
					}
				}
			}
			if (range != null)
			{
				return;
			}
			if (step == null || !step.From.IsKnown || !step.To.IsKnown)
			{
				Notes.Add(name + " does not say which two builds it is between");
				return;
			}
			Dictionary<string, Row> dictionary = new Dictionary<string, Row>(StringComparer.Ordinal);
			foreach (Row item in list)
			{
				if (step.Renames.TryGetValue(item.Key, out var value))
				{
					step.Refused.Add(item.NameKey);
					step.Renames.Remove(item.Key);
					Notes.Add($"{name}: {item.Type}.{item.From} is renamed twice in one step ({value.To} and {item.To}); neither is used");
					continue;
				}
				string key = item.Kind + "|" + item.Type + "|" + item.To + "|" + item.Arity;
				if (dictionary.TryGetValue(key, out var value2))
				{
					step.Refused.Add(item.NameKey);
					step.Refused.Add(value2.NameKey);
					step.Renames.Remove(value2.Key);
					Notes.Add($"{name}: {value2.From} and {item.From} both became {item.To} on {item.Type}; " + "neither is used");
				}
				else
				{
					dictionary[key] = item;
					step.Renames[item.Key] = item;
				}
			}
			string text2 = step.From.ToString() + "->" + step.To;
			if (steps.ContainsKey(text2))
			{
				Notes.Add(name + " replaces the step " + text2 + " that was loaded before it");
			}
			steps[text2] = step;
		}

		private void TakeOverride(string name, Row row, VersionRange applies)
		{
			if (row.Origin == "override" && string.IsNullOrEmpty(row.Note))
			{
				Notes.Add($"{name}: {row.Type}.{row.From} overrides the history with no reason given; skipped");
			}
			else if (_overrides.ContainsKey(row.Key))
			{
				Notes.Add($"{name}: {row.Type}.{row.From} is decided twice by hand; neither is used");
				_overrides.Remove(row.Key);
			}
			else
			{
				_overrides[row.Key] = row;
				_overrideRanges.Add(applies);
			}
		}

		private static Row Parse(string line)
		{
			string[] array = line.Split('|');
			if (array.Length < 10)
			{
				return null;
			}
			int result;
			return new Row
			{
				Op = array[0],
				Kind = array[1],
				Type = array[2],
				From = array[3],
				To = array[4],
				Arity = (int.TryParse(array[5], out result) ? result : 0),
				Origin = array[6],
				RuleName = array[7],
				Confidence = array[8],
				Note = array[9]
			};
		}

		internal string Successor(string kind, string type, string name, int arity, GameVersion game)
		{
			string key = kind + "|" + type + "|" + name + "|" + arity;
			if (_overrides.TryGetValue(key, out var value))
			{
				return value.To;
			}
			string text = name;
			foreach (Step step in _steps)
			{
				if (game.IsKnown && step.To > game)
				{
					break;
				}
				string text2 = kind + "|" + type + "|" + text;
				if (step.Refused.Contains(text2))
				{
					return null;
				}
				if (step.Renames.TryGetValue(text2 + "|" + arity, out var value2))
				{
					text = value2.To;
				}
			}
			if (!(text == name))
			{
				return text;
			}
			return null;
		}

		internal string RemovedIn(string kind, string type, string name, int arity)
		{
			string key = kind + "|" + type + "|" + name + "|" + arity;
			foreach (Step step in _steps)
			{
				if (step.Removed.ContainsKey(key))
				{
					return step.To.ToString();
				}
			}
			return null;
		}

		internal bool WasRefused(string kind, string type, string name)
		{
			string item = kind + "|" + type + "|" + name;
			foreach (Step step in _steps)
			{
				if (step.Refused.Contains(item))
				{
					return true;
				}
			}
			return false;
		}

		internal IEnumerable<string> Versions()
		{
			foreach (Step step in _steps)
			{
				yield return step.From.ToString();
			}
			if (_steps.Count > 0)
			{
				List<Step> steps = _steps;
				yield return steps[steps.Count - 1].To.ToString();
			}
		}

		internal string Gap()
		{
			for (int i = 1; i < _steps.Count; i++)
			{
				if (_steps[i - 1].To != _steps[i].From)
				{
					return $"{_steps[i - 1].To} is followed by a step that starts at {_steps[i].From}";
				}
			}
			return null;
		}
	}
	internal sealed class VersionRange
	{
		private enum Kind
		{
			Any,
			Prefix,
			AtLeast,
			Above,
			AtMost,
			Below,
			Between,
			Exact
		}

		private readonly struct Term
		{
			internal readonly Kind Kind;

			internal readonly GameVersion Low;

			internal readonly GameVersion High;

			internal readonly int PrefixParts;

			internal Term(Kind kind, GameVersion low, GameVersion high = default(GameVersion), int prefixParts = 0)
			{
				Kind = kind;
				Low = low;
				High = high;
				PrefixParts = prefixParts;
			}
		}

		private readonly Term[] _terms;

		internal static readonly VersionRange Any = new VersionRange(new Term[1]
		{
			new Term(Kind.Any, GameVersion.Unknown)
		}, "*");

		internal static readonly VersionRange None = new VersionRange(Array.Empty<Term>(), "nothing");

		internal string Text { get; }

		private VersionRange(Term[] terms, string text)
		{
			_terms = terms;
			Text = text;
		}

		internal static VersionRange Parse(string text)
		{
			if (!TryParse(text, out var range, out var problem))
			{
				throw new FormatException("'" + text + "' is not a version range: " + problem);
			}
			return range;
		}

		internal static bool TryParse(string text, out VersionRange range, out string problem)
		{
			range = null;
			problem = null;
			if (string.IsNullOrWhiteSpace(text))
			{
				range = Any;
				return true;
			}
			List<Term> list = new List<Term>();
			string[] array = text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length == 0)
				{
					continue;
				}
				if (text2 == "*")
				{
					list.Add(new Term(Kind.Any, GameVersion.Unknown));
					continue;
				}
				if (text2.EndsWith("*", StringComparison.Ordinal))
				{
					if (!GameVersion.TryParse(text2.Substring(0, text2.Length - 1).TrimEnd('.', 'f', ' '), out var version))
					{
						problem = "'" + text2 + "' has no version in front of the star";
						return false;
					}
					list.Add(new Term(Kind.Prefix, version, default(GameVersion), version.Parts.Length));
					continue;
				}
				int num = text2.IndexOf("..", StringComparison.Ordinal);
				if (num > 0)
				{
					if (!GameVersion.TryParse(text2.Substring(0, num), out var version2) || !GameVersion.TryParse(text2.Substring(num + 2), out var version3))
					{
						problem = "'" + text2 + "' is not two versions with .. between them";
						return false;
					}
					if (version2 > version3)
					{
						problem = "'" + text2 + "' starts after it ends";
						return false;
					}
					list.Add(new Term(Kind.Between, version2, version3));
					continue;
				}
				Kind kind = Kind.Exact;
				string text3 = text2;
				if (text3.StartsWith(">=", StringComparison.Ordinal))
				{
					kind = Kind.AtLeast;
					text3 = text3.Substring(2);
				}
				else if (text3.StartsWith("<=", StringComparison.Ordinal))
				{
					kind = Kind.AtMost;
					text3 = text3.Substring(2);
				}
				else if (text3.StartsWith(">", StringComparison.Ordinal))
				{
					kind = Kind.Above;
					text3 = text3.Substring(1);
				}
				else if (text3.StartsWith("<", StringComparison.Ordinal))
				{
					kind = Kind.Below;
					text3 = text3.Substring(1);
				}
				if (!GameVersion.TryParse(text3.Trim(), out var version4))
				{
					problem = "'" + text2 + "' has no version in it";
					return false;
				}
				list.Add(new Term(kind, version4));
			}
			if (list.Count == 0)
			{
				problem = "it is empty";
				return false;
			}
			range = new VersionRange(list.ToArray(), text);
			return true;
		}

		internal bool Allows(GameVersion version)
		{
			return Matches(version, unknownAnswer: false);
		}

		internal bool AllowsOrUnknown(GameVersion version)
		{
			return Matches(version, unknownAnswer: true);
		}

		internal bool Allows(string version)
		{
			return Allows(GameVersion.Parse(version));
		}

		internal bool AllowsOrUnknown(string version)
		{
			return AllowsOrUnknown(GameVersion.Parse(version));
		}

		private bool Matches(GameVersion version, bool unknownAnswer)
		{
			Term[] terms = _terms;
			for (int i = 0; i < terms.Length; i++)
			{
				Term term = terms[i];
				if (term.Kind == Kind.Any)
				{
					return true;
				}
				if (!version.IsKnown)
				{
					return unknownAnswer;
				}
				if (term.Kind switch
				{
					Kind.Prefix => version.StartsWith(term.Low, term.PrefixParts), 
					Kind.AtLeast => version >= term.Low, 
					Kind.Above => version > term.Low, 
					Kind.AtMost => version <= term.Low, 
					Kind.Below => version < term.Low, 
					Kind.Between => version >= term.Low && version <= term.High, 
					_ => version == term.Low, 
				})
				{
					return true;
				}
			}
			return false;
		}

		public override string ToString()
		{
			return Text;
		}

		internal IEnumerable<GameVersion> Bounds()
		{
			Term[] terms = _terms;
			for (int i = 0; i < terms.Length; i++)
			{
				Term term = terms[i];
				if (term.Kind != Kind.Any)
				{
					if (term.Low.IsKnown)
					{
						yield return term.Low;
					}
					if (term.Kind == Kind.Between && term.High.IsKnown)
					{
						yield return term.High;
					}
				}
			}
		}

		internal string Describe()
		{
			StringBuilder stringBuilder = new StringBuilder();
			Term[] terms = _terms;
			for (int i = 0; i < terms.Length; i++)
			{
				Term term = terms[i];
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append(", ");
				}
				StringBuilder stringBuilder2 = stringBuilder;
				stringBuilder2.Append(term.Kind switch
				{
					Kind.Any => "any build", 
					Kind.Prefix => term.Low.ToString() + " and its builds", 
					Kind.AtLeast => term.Low.ToString() + " and newer", 
					Kind.Above => "newer than " + term.Low, 
					Kind.AtMost => term.Low.ToString() + " and older", 
					Kind.Below => "older than " + term.Low, 
					Kind.Between => term.Low.ToString() + " to " + term.High, 
					_ => term.Low.ToString(), 
				});
			}
			return stringBuilder.ToString();
		}
	}
}
namespace Polyfill.ModFixes
{
	internal sealed class AmountChangedAfterOverride : Fix
	{
		private static Instance _log;

		private static bool _said;

		private static readonly HashSet<string> Complained = new HashSet<string>();

		internal override string Id => "amount-changed-after-override";

		internal override string Mod => "Tweakables";

		internal override string ModVersions => "*";

		internal override string GameVersions => ">=0.4.6";

		internal override string What => "raising the deal cap tells the rest of the screen the price moved, so it does not show a stale number";

		internal override string StandsDownBecause => "the field this mod used to announce a price change with does not exist in 0.4.6, and the event that replaced it is only raised by the method the mod replaces.";

		internal override bool Apply(Instance log)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			_log = log;
			Type type = AccessTools.TypeByName("Il2CppScheduleOne.UI.AmountSelector");
			if (type == null)
			{
				log.Warning("[fix] amount-changed-after-override: Il2CppScheduleOne.UI.AmountSelector is not on this build, so there is nothing to listen to.");
				return false;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "SetAmount", new Type[1] { typeof(float) }, (Type[])null);
			if (methodInfo == null)
			{
				log.Warning("[fix] amount-changed-after-override: AmountSelector.SetAmount(float) is not here, so the moment the notification goes missing cannot be found.");
				return false;
			}
			new Harmony("doodesch.polyfill.fixes").Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(AmountChangedAfterOverride), "After", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			return true;
		}

		private static void After(object __instance, bool __runOriginal)
		{
			if (__runOriginal || __instance == null)
			{
				return;
			}
			try
			{
				Type type = __instance.GetType();
				object obj = AccessTools.PropertyGetter(type, "OnAmountChanged")?.Invoke(__instance, null);
				if (obj == null)
				{
					return;
				}
				object obj2 = AccessTools.PropertyGetter(type, "SelectedAmount")?.Invoke(__instance, null);
				if (obj2 == null)
				{
					Complain("the selector has no SelectedAmount to announce");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(obj.GetType(), "Invoke", new Type[1] { typeof(float) }, (Type[])null);
				if (methodInfo == null)
				{
					Complain("the event on this build takes something other than a single float, so what to pass it cannot be worked out without guessing");
					return;
				}
				methodInfo.Invoke(obj, new object[1] { obj2 });
				if (!_said)
				{
					_said = true;
					Instance log = _log;
					if (log != null)
					{
						log.Msg("[fix] amount-changed-after-override: a mod replaced the amount box's own setter, so Polyfill raises the change event it would have raised.");
					}
				}
			}
			catch (Exception ex)
			{
				Complain("could not raise the change event: " + ex.GetType().Name + ": " + ex.Message);
			}
		}

		private static void Complain(string why)
		{
			if (Complained.Add(why))
			{
				Instance log = _log;
				if (log != null)
				{
					log.Warning("[fix] amount-changed-after-override: " + why + ". Whatever listens for a price change will not hear this one.");
				}
				Fixes.Record("amount-changed-after-override", "did nothing: " + why);
			}
		}
	}
	internal sealed class BiggerTreesScale : Fix
	{
		private const string TerrainPath = "Hyland Point/Main Terrain";

		private const int WaitSeconds = 75;

		private static Instance _log;

		private static MelonPreferences_Entry<float> _factor;

		private static readonly Dictionary<int, Color[]> Original = new Dictionary<int, Color[]>();

		private static float _largest;

		internal override string Id => "biggertrees-instance-scale";

		internal override string Mod => "BiggerTrees";

		internal override string ModVersions => "*";

		internal override string GameVersions => ">=0.4.6f5";

		internal override bool NeedsAScreen => true;

		internal override string What => "the trees actually get bigger";

		internal override string StandsDownBecause => "Bigger Trees will apply its setting and nothing will change on screen, because the terrain has drawn no trees since 0.4.6f5.";

		internal override bool Apply(Instance log)
		{
			_log = log;
			ReadPreference();
			float num = _factor?.Value ?? 2f;
			if (num <= 1.0001f)
			{
				log.Msg($"[fix] biggertrees-instance-scale: the size is set to {num:0.##}, so the trees " + "are left as they are. `TreeScale` in MelonPreferences changes it.");
				return false;
			}
			MelonCoroutines.Start(Mirror());
			return true;
		}

		private static IEnumerator Mirror()
		{
			int done = 0;
			int waitingFor = 0;
			int waited = 0;
			while (true)
			{
				yield return (object)new WaitForSecondsRealtime(1f);
				Terrain val = FindTerrain();
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				int instanceID = ((Object)val).GetInstanceID();
				if (instanceID == done)
				{
					continue;
				}
				if (instanceID != waitingFor)
				{
					waitingFor = instanceID;
					waited = 0;
				}
				if (ModHasApplied(val))
				{
					done = instanceID;
					if (!Resize(_factor?.Value ?? 2f))
					{
						Fixes.Record("biggertrees-instance-scale", "did nothing");
					}
					continue;
				}
				int num = waited + 1;
				waited = num;
				if (num >= 75)
				{
					done = instanceID;
					Fixes.Record("biggertrees-instance-scale", "did nothing");
					Instance log = _log;
					if (log != null)
					{
						log.Msg("[fix] biggertrees-instance-scale: the terrain's tree LOD bias never moved off 1, so Bigger Trees did not apply and nothing was resized.");
					}
				}
			}
		}

		private static bool ModHasApplied(Terrain terrain)
		{
			try
			{
				return terrain.treeLODBiasMultiplier > 1.0001f;
			}
			catch
			{
				return false;
			}
		}

		private static bool Resize(float factor)
		{
			InstancingManager val = null;
			try
			{
				val = Object.FindObjectOfType<InstancingManager>();
			}
			catch (Exception ex)
			{
				Instance log = _log;
				if (log != null)
				{
					log.Warning("[fix] biggertrees-instance-scale: " + ex.Message);
				}
				return false;
			}
			if ((Object)(object)val == (Object)null)
			{
				Instance log2 = _log;
				if (log2 != null)
				{
					log2.Warning("[fix] biggertrees-instance-scale: this build has no instanced renderer, so the mod's own setting works as it always did.");
				}
				return false;
			}
			List<InstanceObjectData> backedInstanceObjects = val.BackedInstanceObjects;
			if (backedInstanceObjects == null || backedInstanceObjects.Count == 0)
			{
				return false;
			}
			int num = 0;
			int num2 = 0;
			_largest = 0f;
			for (int i = 0; i < backedInstanceObjects.Count; i++)
			{
				int num3 = ScaleOne(backedInstanceObjects[i], factor);
				if (num3 > 0)
				{
					num++;
					num2 = Mathf.Max(num2, num3);
				}
			}
			if (num == 0)
			{
				Instance log3 = _log;
				if (log3 != null)
				{
					log3.Warning("[fix] biggertrees-instance-scale: nothing carried a size to change.");
				}
				return false;
			}
			Instance log4 = _log;
			if (log4 != null)
			{
				log4.Msg($"[fix] biggertrees-instance-scale: {num2} tree(s) resized to {factor:0.##}x across {num} level(s) of detail, largest now {_largest:0.###}. `TreeScale` in " + "MelonPreferences changes it.");
			}
			return true;
		}

		private static int ScaleOne(InstanceObjectData data, float factor)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = ((data != null) ? data.PositionData : null);
			if ((Object)(object)val == (Object)null)
			{
				return 0;
			}
			int width = ((Texture)val).width;
			int height = ((Texture)val).height;
			if (width <= 0 || height <= 0)
			{
				return 0;
			}
			try
			{
				Texture2D val2 = Readable(val, width, height);
				Il2CppStructArray<Color> pixels = val2.GetPixels();
				int instanceID = ((Object)data).GetInstanceID();
				if (!Original.TryGetValue(instanceID, out var value) || value.Length != ((Il2CppArrayBase<Color>)(object)pixels).Length)
				{
					value = (Color[])(object)new Color[((Il2CppArrayBase<Color>)(object)pixels).Length];
					for (int i = 0; i < ((Il2CppArrayBase<Color>)(object)pixels).Length; i++)
					{
						value[i] = ((Il2CppArrayBase<Color>)(object)pixels)[i];
					}
					Original[instanceID] = value;
				}
				int num = 0;
				for (int j = 0; j < ((Il2CppArrayBase<Color>)(object)pixels).Length; j++)
				{
					Color val3 = value[j];
					if (val3.a <= 0f)
					{
						((Il2CppArrayBase<Color>)(object)pixels)[j] = val3;
						continue;
					}
					num++;
					float num2 = val3.a * factor;
					if (num2 > _largest)
					{
						_largest = num2;
					}
					((Il2CppArrayBase<Color>)(object)pixels)[j] = new Color(val3.r, val3.g, val3.b, num2);
				}
				if (num == 0)
				{
					return 0;
				}
				val2.SetPixels(pixels);
				val2.Apply(false, false);
				data.PositionData = val2;
				return num;
			}
			catch (Exception ex)
			{
				Instance log = _log;
				if (log != null)
				{
					log.Warning("[fix] biggertrees-instance-scale: could not resize a level of detail: " + ex.Message);
				}
				return 0;
			}
		}

		private static Texture2D Readable(Texture2D source, int width, int height)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			RenderTexture temporary = RenderTexture.GetTemporary(width, height, 0, (RenderTextureFormat)11, (RenderTextureReadWrite)1);
			RenderTexture active = RenderTexture.active;
			try
			{
				Graphics.Blit((Texture)(object)source, temporary);
				RenderTexture.active = temporary;
				Texture2D val = new Texture2D(width, height, (TextureFormat)20, false);
				val.ReadPixels(new Rect(0f, 0f, (float)width, (float)height), 0, 0);
				val.Apply(false, false);
				return val;
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
		}

		private static Terrain FindTerrain()
		{
			try
			{
				GameObject obj = GameObject.Find("Map");
				Transform val = ((obj != null) ? obj.transform.Find("Hyland Point/Main Terrain") : null);
				return ((Object)(object)val == (Object)null) ? null : ((Component)val).GetComponent<Terrain>();
			}
			catch
			{
				return null;
			}
		}

		private static void ReadPreference()
		{
			if (_factor != null)
			{
				return;
			}
			try
			{
				MelonPreferences_Category val = MelonPreferences.GetCategory("Polyfill") ?? MelonPreferences.CreateCategory("Polyfill");
				_factor = val.GetEntry<float>("TreeScale") ?? val.CreateEntry<float>("TreeScale", 2f, "How much bigger the trees get", "Only with the Bigger Trees mod installed. 1 leaves them alone.", false, false, (ValueValidator)null, (string)null);
			}
			catch
			{
			}
		}
	}
	internal sealed class BorrowedAppLayout : Fix
	{
		private static readonly (string Type, string Method, string Field)[] Hooks = new(string, string, string)[3]
		{
			("MediaPlayer.PhoneIntegration", "ClearContainer", null),
			("Tweakables.TweakablesApp", "ClonePanel", "_appPanel"),
			("ElDiablo59WagesManager.WagesApp", "BuildAppRoot", "_appRoot")
		};

		private static Instance _log;

		private static readonly HashSet<int> Done = new HashSet<int>();

		private static readonly Dictionary<MethodBase, FieldInfo> Owners = new Dictionary<MethodBase, FieldInfo>();

		private static readonly HashSet<string> Complained = new HashSet<string>();

		internal override string Id => "borrowed-app-layout";

		internal override string Mod => "*";

		internal override string ModVersions => "*";

		internal override string GameVersions => "0.4.6*";

		internal override bool NeedsAScreen => true;

		internal override string What => "phone apps built inside a borrowed vanilla one fill the screen again instead of being squeezed into a strip at the top";

		internal override string StandsDownBecause => "0.4.6 put a vertical layout group on the app container these mods clone, which overrules where they put their own panels.";

		internal override bool Apply(Instance log)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Expected O, but got Unknown
			_log = log;
			int num = 0;
			Harmony val = new Harmony("doodesch.polyfill.fixes");
			(string, string, string)[] hooks = Hooks;
			for (int i = 0; i < hooks.Length; i++)
			{
				(string, string, string) tuple = hooks[i];
				string item = tuple.Item1;
				string item2 = tuple.Item2;
				string item3 = tuple.Item3;
				Type type = AccessTools.TypeByName(item);
				if (type == null)
				{
					continue;
				}
				MethodInfo methodInfo = AccessTools.Method(type, item2, (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					log.Warning($"[fix] borrowed-app-layout: {item} is here but {item2} is not, " + "so this version of the mod builds its app some other way and the moment to act cannot be found.");
					continue;
				}
				FieldInfo fieldInfo = ((item3 == null) ? null : AccessTools.Field(type, item3));
				if (item3 != null && fieldInfo == null)
				{
					log.Warning($"[fix] borrowed-app-layout: {item} has no {item3}, so the app it " + "clones cannot be identified - and guessing which one is its would risk the game's own screens.");
					continue;
				}
				try
				{
					Owners[methodInfo] = fieldInfo;
					val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(BorrowedAppLayout), "Loosen", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
				}
				catch (Exception ex)
				{
					log.Warning($"[fix] borrowed-app-layout: could not hook {item}.{item2}: " + ex.Message);
				}
			}
			return num > 0;
		}

		private static string Path(Transform transform)
		{
			try
			{
				List<string> list = new List<string>();
				Transform val = transform;
				while ((Object)(object)val != (Object)null)
				{
					list.Add(((Object)val).name);
					if (list.Count > 12)
					{
						break;
					}
					val = val.parent;
				}
				list.Reverse();
				return string.Join("/", list);
			}
			catch
			{
				return ((Object)(object)transform == (Object)null) ? "(nothing)" : ((Object)transform).name;
			}
		}

		private static void Loosen(MethodBase __originalMethod, object[] __args)
		{
			try
			{
				Owners.TryGetValue(__originalMethod, out var value);
				GameObject val = null;
				if (value != null)
				{
					object? value2 = value.GetValue(null);
					val = (GameObject)((value2 is GameObject) ? value2 : null);
				}
				else if (__args != null && __args.Length != 0)
				{
					object obj = __args[0];
					val = (GameObject)((obj is GameObject) ? obj : null);
				}
				if ((Object)(object)val == (Object)null)
				{
					Complain("the mod's own app object was not there to read after it built, so the container cannot be identified");
					return;
				}
				Transform val2 = ((((Object)val.transform).name == "Container") ? val.transform : val.transform.Find("Container"));
				if ((Object)(object)val2 == (Object)null)
				{
					Complain("the cloned app has no Container child, so the shape it was written against is not the shape it got");
				}
				else
				{
					if (!Done.Add(((Object)val2).GetInstanceID()))
					{
						return;
					}
					VerticalLayoutGroup component = ((Component)val2).GetComponent<VerticalLayoutGroup>();
					if ((Object)(object)component == (Object)null)
					{
						Complain("the app container has no vertical layout group any more, so there is nothing to loosen and the mod's own anchors already decide");
					}
					else if (((Behaviour)component).enabled)
					{
						((Behaviour)component).enabled = false;
						Instance log = _log;
						if (log != null)
						{
							log.Msg("[fix] borrowed-app-layout: switched off the vertical layout group on " + Path(val2) + ", inherited from the game's product manager, so the app's own panels decide where they go again.");
						}
					}
				}
			}
			catch (Exception ex)
			{
				Complain("could not read the cloned app: " + ex.GetType().Name + ": " + ex.Message);
			}
		}

		private static void Complain(string why)
		{
			if (Complained.Add(why))
			{
				Instance log = _log;
				if (log != null)
				{
					log.Warning("[fix] borrowed-app-layout: " + why + ". The app is left exactly as the mod built it.");
				}
				Fixes.Record("borrowed-app-layout", "did nothing: " + why);
			}
		}
	}
	internal static class ButtonCodeShift
	{
		private static readonly string[] OldOrder = new string[34]
		{
			"PrimaryClick", "SecondaryClick", "TertiaryClick", "Forward", "Backward", "Left", "Right", "Jump", "Crouch", "Sprint",
			"Escape", "Back", "Interact", "Submit", "TogglePhone", "VehicleToggleLights", "VehicleHandbrake", "RotateLeft", "RotateRight", "ManagementMode",
			"OpenMap", "OpenJournal", "OpenTexts", "QuickMove", "ToggleFlashlight", "ViewAvatar", "Reload", "InventoryLeft", "InventoryRight", "Holster",
			"VehicleResetCamera", "SkateboardDismount", "SkateboardMount", "TogglePauseMenu"
		};

		private const int Nowhere = -1;

		private static readonly Dictionary<string, Dictionary<string, string>> Instead = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase) { ["otc-button-codes"] = new Dictionary<string, string>(StringComparer.Ordinal)
		{
			["Escape"] = "SecondaryClick",
			["Back"] = "SecondaryClick"
		} };

		private static int[] _map;

		private static Instance _log;

		private static readonly List<(int Old, int Now)> _pointed = new List<(int, int)>();

		private static string Current = "?";

		internal static int[] Map(Instance log)
		{
			if (_map != null)
			{
				return _map;
			}
			_log = log;
			string[] array = InstalledOrder();
			if (array == null || array.Length == 0)
			{
				return null;
			}
			bool flag = array.Length != OldOrder.Length;
			int[] array2 = new int[OldOrder.Length];
			for (int i = 0; i < OldOrder.Length; i++)
			{
				array2[i] = -1;
				for (int j = 0; j < array.Length; j++)
				{
					if (string.Equals(array[j], OldOrder[i], StringComparison.Ordinal))
					{
						array2[i] = j;
						break;
					}
				}
				if (array2[i] != i)
				{
					flag = true;
				}
			}
			return _map = (flag ? array2 : null);
		}

		private static string[] InstalledOrder()
		{
			try
			{
				Type nestedType = typeof(GameInput).GetNestedType("ButtonCode");
				return (nestedType == null) ? null : Enum.GetNames(nestedType);
			}
			catch
			{
				return null;
			}
		}

		private static int InsteadOf(int old)
		{
			if (!Instead.TryGetValue(Current, out var value))
			{
				return -1;
			}
			if (!value.TryGetValue(OldName(old), out var value2))
			{
				return -1;
			}
			string[] array = InstalledOrder();
			if (array == null)
			{
				return -1;
			}
			for (int i = 0; i < array.Length; i++)
			{
				if (string.Equals(array[i], value2, StringComparison.Ordinal))
				{
					return i;
				}
			}
			return -1;
		}

		internal static string OldName(int value)
		{
			if (value < 0 || value >= OldOrder.Length)
			{
				return value.ToString();
			}
			return OldOrder[value];
		}

		internal static IEnumerable<CodeInstruction> Transpile(IEnumerable<CodeInstruction> instructions, string who)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int[] map = _map;
			if (map == null)
			{
				return list;
			}
			for (int i = 0; i + 1 < list.Count; i++)
			{
				if (TakesAButton(list[i + 1]) && Constant(list[i], out var value) && value >= 0 && value < map.Length)
				{
					int num = map[value];
					if (num == -1)
					{
						num = InsteadOf(value);
					}
					if (num != value)
					{
						CodeInstruction val = Load(num);
						list[i].opcode = val.opcode;
						list[i].operand = val.operand;
						_pointed.Add((value, num));
					}
				}
			}
			return list;
		}

		private static bool TakesAButton(CodeInstruction instruction)
		{
			if (instruction.opcode != OpCodes.Call && instruction.opcode != OpCodes.Callvirt)
			{
				return false;
			}
			if (instruction.operand is MethodInfo methodInfo && methodInfo.DeclaringType == typeof(GameInput))
			{
				return methodInfo.Name.StartsWith("GetButton", StringComparison.Ordinal);
			}
			return false;
		}

		private static bool Constant(CodeInstruction instruction, out int value)
		{
			value = 0;
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Ldc_I4)
			{
				value = (int)instruction.operand;
				return true;
			}
			if (opcode == OpCodes.Ldc_I4_S)
			{
				value = Convert.ToInt32(instruction.operand);
				return true;
			}
			if (opcode == OpCodes.Ldc_I4_M1)
			{
				value = -1;
				return true;
			}
			for (int i = 0; i <= 8; i++)
			{
				if (opcode == Short(i))
				{
					value = i;
					return true;
				}
			}
			return false;
		}

		private static CodeInstruction Load(int value)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			if (value < 0 || value > 8)
			{
				if (value >= -128 && value <= 127)
				{
					return new CodeInstruction(OpCodes.Ldc_I4_S, (object)(sbyte)value);
				}
				return new CodeInstruction(OpCodes.Ldc_I4, (object)value);
			}
			return new CodeInstruction(Short(value), (object)null);
		}

		private static OpCode Short(int value)
		{
			return value switch
			{
				0 => OpCodes.Ldc_I4_0, 
				1 => OpCodes.Ldc_I4_1, 
				2 => OpCodes.Ldc_I4_2, 
				3 => OpCodes.Ldc_I4_3, 
				4 => OpCodes.Ldc_I4_4, 
				5 => OpCodes.Ldc_I4_5, 
				6 => OpCodes.Ldc_I4_6, 
				7 => OpCodes.Ldc_I4_7, 
				_ => OpCodes.Ldc_I4_8, 
			};
		}

		internal static int Apply(Instance log, string who, string assembly, params (string Type, string Method)[] targets)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Expected O, but got Unknown
			if (Map(log) == null)
			{
				log.Msg("[fix] " + who + ": this game orders the buttons the way the mod expects, so nothing needed pointing anywhere.");
				return 0;
			}
			Assembly assembly2 = null;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly3 in assemblies)
			{
				if (string.Equals(assembly3.GetName()?.Name, assembly, StringComparison.OrdinalIgnoreCase))
				{
					assembly2 = assembly3;
					break;
				}
			}
			if (assembly2 == null)
			{
				return 0;
			}
			Harmony val = new Harmony("doodesch.polyfill.fixes");
			int num = 0;
			for (int i = 0; i < targets.Length; i++)
			{
				var (text, text2) = targets[i];
				try
				{
					Type type = assembly2.GetType(text, throwOnError: false);
					MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, text2, (Type[])null, (Type[])null));
					if (methodInfo == null)
					{
						log.Warning($"[fix] {who}: {text}.{text2} is not where it was.");
						continue;
					}
					Current = who;
					_pointed.Clear();
					val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ButtonCodeShift), "Rewrite", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
					foreach (var (value, num2) in _pointed)
					{
						Dictionary<string, string> value2;
						if (num2 == -1)
						{
							log.Warning($"[fix] {who}: {text} asks for the {OldName(value)} button, which " + "this build of the game does not have any more, so that key does nothing.");
						}
						else if (Instead.TryGetValue(who, out value2) && value2.ContainsKey(OldName(value)))
						{
							log.Msg($"[fix] {who}: {text}.{text2} asked for the {OldName(value)} button, which this build does not have. Pointed at {value2[OldName(value)]}, which is what the mod's own maintainers " + "chose when they hit this.");
						}
						else
						{
							log.Msg($"[fix] {who}: {text}.{text2} asked for button {value}, which was {OldName(value)} and is now {num2}. Pointed at {num2}.");
						}
					}
					if (_pointed.Count > 0)
					{
						num++;
					}
				}
				catch (Exception ex)
				{
					log.Warning($"[fix] {who}: {text}.{text2} could not be pointed: {ex.Message}");
				}
			}
			return num;
		}

		private static IEnumerable<CodeInstruction> Rewrite(IEnumerable<CodeInstruction> instructions)
		{
			return Transpile(instructions, Current);
		}
	}
	internal sealed class DeepPocketsEarlyBroadcast : Fix
	{
		private static Instance _log;

		internal override bool Early => true;

		internal override string Id => "deeppockets-early-broadcast";

		internal override string Mod => "Deep Pockets";

		internal override string ModVersions => "*";

		internal override string GameVersions => ">=0.4.6";

		internal override string What => "Deep Pockets answers every other mod's settings save by looking for players who are not there yet, before the game is loaded.";

		internal override bool Apply(Instance log)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			_log = log;
			Type type = AccessTools.TypeByName("DeepPockets.Config");
			if (type == null)
			{
				log.Msg("[fix] deeppockets-early-broadcast: Deep Pockets is not loaded, so there is nothing to guard.");
				return false;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "BroadcastHostConfigLive", (Type[])null, (Type[])null);
			if (methodInfo == null || methodInfo.GetParameters().Length != 0)
			{
				log.Warning("[fix] deeppockets-early-broadcast: DeepPockets.Config has no no-argument BroadcastHostConfigLive on this build, so it was left alone.");
				return false;
			}
			try
			{
				new Harmony("doodesch.polyfill.fixes").Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(DeepPocketsEarlyBroadcast), "NotBeforeTheGameIsUp", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			catch (Exception ex)
			{
				log.Warning("[fix] deeppockets-early-broadcast: could not guard DeepPockets.Config.BroadcastHostConfigLive: " + ex.Message);
				return false;
			}
			log.Msg("[fix] deeppockets-early-broadcast: Deep Pockets waits for the game before it looks for players to send its settings to.");
			return true;
		}

		private static bool NotBeforeTheGameIsUp()
		{
			return MainSceneLatch.Reached;
		}
	}
	internal sealed class EmptyDeadDropSearch : Fix
	{
		private static Instance _log;

		private static bool _said;

		private static readonly HashSet<string> Complained = new HashSet<string>();

		internal override string Id => "empty-dead-drop-search";

		internal override string Mod => "*";

		internal override string ModVersions => "*";

		internal override string GameVersions => "*";

		internal override string What => "asking for a free dead drop when every one is full answers 'none' instead of throwing, so a mod that puts something in one carries on";

		internal override string StandsDownBecause => "DeadDrop.GetRandomEmptyDrop drops the nearest candidate before checking whether it had any, so a world with no free dead drop throws out of the middle of whatever called it.";

		internal override bool Apply(Instance log)
		{
			//IL_0050: 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_0074: Expected O, but got Unknown
			_log = log;
			Type type = AccessTools.TypeByName("Il2CppScheduleOne.Economy.DeadDrop");
			if (type == null)
			{
				log.Warning("[fix] empty-dead-drop-search: Il2CppScheduleOne.Economy.DeadDrop is not on this build, so there is nothing to guard.");
				return false;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "GetRandomEmptyDrop", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				log.Warning("[fix] empty-dead-drop-search: DeadDrop.GetRandomEmptyDrop is not here. If the game renamed it, a mod calling the old name has a bigger problem than this guard.");
				return false;
			}
			new Harmony("doodesch.polyfill.fixes").Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(EmptyDeadDropSearch), "Before", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			return true;
		}

		private static bool Before(ref object __result)
		{
			try
			{
				Type type = AccessTools.TypeByName("Il2CppScheduleOne.Economy.DeadDrop");
				object obj = AccessTools.Property(type, "DeadDrops")?.GetValue(null) ?? AccessTools.Field(type, "DeadDrops")?.GetValue(null);
				if (obj == null)
				{
					Complain("neither a property nor a field called DeadDrops");
					return true;
				}
				int num = 0;
				foreach (object item in Enumerate(obj))
				{
					if (item == null)
					{
						continue;
					}
					object obj2 = AccessTools.Property(item.GetType(), "Storage")?.GetValue(item) ?? AccessTools.Field(item.GetType(), "Storage")?.GetValue(item);
					if (obj2 != null)
					{
						object obj3 = AccessTools.Property(obj2.GetType(), "ItemCount")?.GetValue(obj2);
						if (obj3 is int && (int)obj3 == 0)
						{
							num++;
						}
					}
				}
				if (num > 0)
				{
					return true;
				}
				__result = null;
				if (!_said)
				{
					_said = true;
					Instance log = _log;
					if (log != null)
					{
						log.Msg("[fix] empty-dead-drop-search: every dead drop in the world is full, so the game was asked for one and answered instead of throwing.");
					}
				}
				return false;
			}
			catch (Exception ex)
			{
				Complain(ex.GetType().Name + ": " + ex.Message);
				return true;
			}
		}

		private static IEnumerable<object> Enumerate(object list)
		{
			int count = (AccessTools.Property(list.GetType(), "Count")?.GetValue(list) as int?).GetValueOrDefault();
			PropertyInfo item = AccessTools.Property(list.GetType(), "Item");
			if (item == null)
			{
				yield break;
			}
			for (int i = 0; i < count; i++)
			{
				object obj = null;
				try
				{
					obj = item.GetValue(list, new object[1] { i });
				}
				catch
				{
				}
				if (obj != null)
				{
					yield return obj;
				}
			}
		}

		private static void Complain(string why)
		{
			if (Complained.Add(why))
			{
				Instance log = _log;
				if (log != null)
				{
					log.Warning("[fix] empty-dead-drop-search: could not read the dead drop list (" + why + "), so the game answers this one itself.");
				}
				Fixes.Record("empty-dead-drop-search", "stood aside: " + why);
			}
		}
	}
	internal abstract class Fix
	{
		private VersionRange _forMod;

		private VersionRange _forGame;

		internal abstract string Id { get; }

		internal abstract string Mod { get; }

		internal abstract string ModVersions { get; }

		internal abstract string GameVersions { get; }

		internal virtual string StandsDownBecause => null;

		internal virtual bool Early => false;

		internal virtual bool NeedsAScreen => false;

		internal abstract string What { get; }

		internal VersionRange ForMod => _forMod ?? (_forMod = Range(ModVersions, "ModVersions"));

		internal VersionRange ForGame => _forGame ?? (_forGame = Range(GameVersions, "GameVersions"));

		internal string RangeProblem { get; private set; }

		internal abstract bool Apply(Instance log);

		internal bool AppliesTo(string modVersion, string gameVersion)
		{
			if (ForMod.Allows(modVersion))
			{
				return ForGame.Allows(gameVersion);
			}
			return false;
		}

		internal bool GameIsNewerThanKnown(string gameVersion)
		{
			GameVersion gameVersion2 = GameVersion.Parse(gameVersion);
			if (!gameVersion2.IsKnown)
			{
				return false;
			}
			bool result = false;
			foreach (GameVersion item in ForGame.Bounds())
			{
				result = true;
				if (gameVersion2 <= item)
				{
					return false;
				}
			}
			return result;
		}

		private VersionRange Range(string text, string which)
		{
			if (VersionRange.TryParse(text, out var range, out var problem))
			{
				return range;
			}
			RangeProblem = $"{which} is '{text}', which is not a version range ({problem})";
			return VersionRange.None;
		}
	}
	internal static class Fixes
	{
		internal sealed class Outcome
		{
			internal Fix Fix;

			internal string Mod;

			internal string State;
		}

		internal static readonly HashSet<string> Repaired = new HashSet<string>(StringComparer.Ordinal);

		internal static readonly List<Outcome> Results = new List<Outcome>();

		private static readonly List<Fix> All = new List<Fix>
		{
			new S1MapiPrefabLookup(),
			new S1MapiClonedDoors(),
			new S1MapiPrefabs(),
			new S1MapiInstancedTrees(),
			new OverTheCounterNetworkLib(),
			new OverTheCounterDrifterPrefab(),
			new OverTheCounterAdoptsOnlyClones(),
			new OverTheCounterButtonCodes(),
			new OverTheCounterClipboard(),
			new OverTheCounterStalePanel(),
			new OverTheCounterSmartFill(),
			new OverTheCounterHandover(),
			new MeetPointsLobbyChat(),
			new SmartEmployeesLobbyChat(),
			new MoreRealisticSleepingPhoneFonts(),
			new DeepPocketsEarlyBroadcast(),
			new MulesPrefsReloadOnAWorker(),
			new SupplierMeetingNeverStarts(),
			new PhoneAppIconWithoutFile(),
			new ThmButtonCodes(),
			new BiggerTreesScale(),
			new GraphicsModSunToggle(),
			new ScheduleActionsSurviveDeath(),
			new MoreFootPatrolsOfficerPool(),
			new GuiDrawTexture(),
			new BorrowedAppLayout(),
			new EmptyDeadDropSearch(),
			new AmountChangedAfterOverride(),
			new StorageMenuClosedEvent(),
			new PatchesOnGrownOverloads(),
			new PatchesOnSplitMethods(),
			new PatchesOnNarrowedOverloads(),
			new PatchesOnResultTurnedArgument(),
			new SplitScreenPatches(),
			new PatchesOnReplacedMethods()
		};

		private static MelonPreferences_Entry<string> _disabled;

		internal static void RunEarly(Instance log)
		{
			Run(log, early: true);
		}

		internal static void Run(Instance log)
		{
			Run(log, early: false);
		}

		private static void Run(Instance log, bool early)
		{
			ReadPreference();
			string text = GameVersion();
			foreach (Fix item in All)
			{
				if (item.Early != early)
				{
					continue;
				}
				Outcome outcome = new Outcome
				{
					Fix = item,
					Mod = InstalledVersion(item.Mod)
				};
				Results.Add(outcome);
				string why;
				if (outcome.Mod == null)
				{
					outcome.State = "not installed";
				}
				else if (item.RangeProblem != null)
				{
					outcome.State = "broken: " + item.RangeProblem;
					log.Error($"[fix] {item.Id}: {item.RangeProblem}. It will not run. This is a bug in " + "Polyfill, not in your setup.");
				}
				else if (IsOff(item.Id))
				{
					outcome.State = "off";
				}
				else if (!item.AppliesTo(outcome.Mod, text))
				{
					outcome.State = "wrong version";
					if (item.GameIsNewerThanKnown(text))
					{
						outcome.State = "needs checking on " + text;
						log.Warning($"[fix] {item.Id} was written for {item.ForGame.Describe()} and this game is {text}, so it did not run. {item.StandsDownBecause ?? item.What} ({item.Mod} {outcome.Mod} is installed.)");
					}
				}
				else if (item.NeedsAScreen && Headless.Yes(out why))
				{
					outcome.State = "not needed without a screen";
					log.Msg($"[fix] {item.Id} did not run: {why}, and this repair only changes what a player sees. {item.What}");
				}
				else
				{
					bool flag;
					try
					{
						flag = item.Apply(log);
					}
					catch (Exception ex)
					{
						outcome.State = "failed: " + ex.Message;
						log.Warning("[fix] " + item.Id + " failed and changed nothing: " + ex.Message);
						continue;
					}
					outcome.State = (flag ? "applied" : "did nothing");
					if (flag)
					{
						log.Msg("[fix] " + item.Id + ": " + item.What);
					}
				}
			}
		}

		internal static void Record(string id, string state)
		{
			foreach (Outcome result in Results)
			{
				if (string.Equals(result.Fix.Id, id, StringComparison.OrdinalIgnoreCase))
				{
					result.State = state;
				}
			}
		}

		private static string InstalledVersion(string name)
		{
			if (name == "*")
			{
				return "*";
			}
			try
			{
				foreach (MelonBase registeredMelon in MelonBase.RegisteredMelons)
				{
					if (((registeredMelon != null) ? registeredMelon.Info : null) != null && string.Equals(registeredMelon.Info.Name, name, StringComparison.OrdinalIgnoreCase))
					{
						return registeredMelon.Info.Version ?? "";
					}
				}
			}
			catch
			{
			}
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					string text = assembly.GetName()?.Name;
					if (text != null && (string.Equals(text, name, StringComparison.OrdinalIgnoreCase) || string.Equals(text, name + "_Il2Cpp", StringComparison.OrdinalIgnoreCase)))
					{
						return assembly.GetName().Version?.ToString() ?? "";
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static string GameVersion()
		{
			try
			{
				return Application.version;
			}
			catch
			{
				return "";
			}
		}

		internal static bool IsOff(string id)
		{
			string text = _disabled?.Value;
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			string[] array = text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				if (string.Equals(array[i].Trim(), id, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		internal static void Set(string id, bool on)
		{
			ReadPreference();
			List<string> list = new List<string>();
			string[] array = (_disabled.Value ?? "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0 && !string.Equals(text, id, StringComparison.OrdinalIgnoreCase))
				{
					list.Add(text);
				}
			}
			if (!on)
			{
				list.Add(id);
			}
			_disabled.Value = string.Join(",", list);
			try
			{
				MelonPreferences.Save();
			}
			catch
			{
			}
		}

		internal static bool Known(string id)
		{
			foreach (Fix item in All)
			{
				if (string.Equals(item.Id, id, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static void ReadPreference()
		{
			if (_disabled != null)
			{
				return;
			}
			try
			{
				MelonPreferences_Category val = MelonPreferences.GetCategory("Polyfill") ?? MelonPreferences.CreateCategory("Polyfill");
				_disabled = val.GetEntry<string>("DisabledFixes") ?? val.CreateEntry<string>("DisabledFixes", "", "Mod fixes to leave alone", "Comma separated ids of per-mod fixes that should not run. Type `polyfillfixes` in the console to see the ids.", false, false, (ValueValidator)null, (string)null);
			}
			catch
			{
			}
		}
	}
	internal sealed class GraphicsModSunToggle : Fix
	{
		private const string OldPath = "Managers/@EnvironmentFX/SkySystemController";

		private static Instance _log;

		private static MethodInfo _sunLight;

		private static bool _said;

		internal override string Id => "graphicsmod-sun-toggle";

		internal override string Mod => "GraphicsMOD";

		internal override string ModVersions => "2.0.0";

		internal override string GameVersions => "0.4.6f13";

		internal override bool NeedsAScreen => true;

		internal override string What => "GraphicsMOD's lighting toggle reaches the sun the game holds now";

		internal override string StandsDownBecause => "GraphicsMOD's lighting option does nothing at all - it looks for the sun under a path 0.4.6 no longer has, and says so in the log.";

		internal override bool Apply(Instance log)
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			_log = log;
			Type type = AccessTools.TypeByName("GraphicsSettings");
			if (type == null)
			{
				return false;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "OptimitationLights", (Type[])null, (Type[])null);
			ParameterInfo[] array = methodInfo?.GetParameters();
			if (methodInfo == null || methodInfo.ReturnType != typeof(void) || array.Length != 1 || array[0].ParameterType != typeof(bool))
			{
				log.Warning("[fix] " + Id + ": GraphicsSettings.OptimitationLights is not the one-argument method this knows, so the lighting toggle stays as it is.");
				return false;
			}
			_sunLight = AccessTools.PropertyGetter(typeof(DayNightController), "_sunLight");
			if (_sunLight == null)
			{
				log.Warning("[fix] " + Id + ": DayNightController has no _sunLight on this build, so there is no sun to point the toggle at.");
				return false;
			}
			new Harmony("doodesch.polyfill.graphicsmodsun").Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(GraphicsModSunToggle), "ToggleTheSunTheGameHolds", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			return true;
		}

		private static bool ToggleTheSunTheGameHolds(bool enabled)
		{
			try
			{
				if ((Object)(object)GameObject.Find("Managers/@EnvironmentFX/SkySystemController") != (Object)null)
				{
					return true;
				}
			}
			catch
			{
				return true;
			}
			try
			{
				DayNightController val = Object.FindObjectOfType<DayNightController>();
				if ((Object)(object)val == (Object)null)
				{
					return Complain("no DayNightController is loaded");
				}
				object? obj2 = _sunLight.Invoke(val, null);
				Light val2 = (Light)((obj2 is Light) ? obj2 : null);
				if (val2 == null || (Object)(object)val2 == (Object)null)
				{
					return Complain("the controller has no sun light");
				}
				((Component)val2).gameObject.SetActive(enabled);
				if (!_said)
				{
					_said = true;
					Instance log = _log;
					if (log != null)
					{
						log.Msg("[fix] graphicsmod-sun-toggle: the lighting option now switches the sun the game holds, which is where 0.4.6 moved it.");
					}
				}
				return false;
			}
			catch (Exception ex)
			{
				return Complain(ex.Message);
			}
		}

		private static bool Complain(string why)
		{
			if (!_said)
			{
				_said = true;
				Instance log = _log;
				if (log != null)
				{
					log.Warning("[fix] graphicsmod-sun-toggle: " + why + ", so the lighting option was left alone and changed nothing.");
				}
			}
			return true;
		}
	}
	internal sealed class GuiDrawTexture : Fix
	{
		private const string StubMessage = "Method unstripping failed";

		private static Instance _log;

		private static bool _saidBorders;

		private static string _gaveUp;

		internal override string Id => "gui-drawtexture";

		internal override string Mod => "*";

		internal override string ModVersions => "*";

		internal override string GameVersions => ">=0.4.6";

		internal override bool NeedsAScreen => true;

		internal override string What => "mods that draw an image over the screen with GUI.DrawTexture draw it instead of throwing";

		internal override string StandsDownBecause => "GUI.DrawTexture is a stub that throws in this build, and a mod calling it from OnGUI throws once per frame until the game dies.";

		internal override bool Apply(Instance log)
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Expected O, but got Unknown
			_log = log;
			MethodInfo methodInfo = AccessTools.Method(typeof(GUI), "DrawTexture", new Type[12]
			{
				typeof(Rect),
				typeof(Texture),
				typeof(ScaleMode),
				typeof(bool),
				typeof(float),
				typeof(Color),
				typeof(Color),
				typeof(Color),
				typeof(Color),
				typeof(Vector4),
				typeof(Vector4),
				typeof(bool)
			}, (Type[])null);
			if (methodInfo == null)
			{
				log.Warning("[fix] gui-drawtexture: the overload every other one calls is not where it was, so the family cannot be repaired in one place.");
				return false;
			}
			if (!IsStub(methodInfo))
			{
				log.Msg("[fix] gui-drawtexture: GUI.DrawTexture works in this build. Nothing to repair.");
				return false;
			}
			new Harmony("doodesch.polyfill.fixes").Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(GuiDrawTexture), "Draw", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			return true;
		}

		private static bool IsStub(MethodBase method)
		{
			try
			{
				byte[] array = method.GetMethodBody()?.GetILAsByteArray();
				if (array == null || array.Length < 5)
				{
					return false;
				}
				Module module = method.Module;
				for (int i = 0; i + 4 < array.Length; i++)
				{
					if (array[i] == 114)
					{
						int metadataToken = array[i + 1] | (array[i + 2] << 8) | (array[i + 3] << 16) | (array[i + 4] << 24);
						if (module.ResolveString(metadataToken) == "Method unstripping failed")
						{
							return true;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Instance log = _log;
				if (log != null)
				{
					log.Warning("[fix] gui-drawtexture: could not read GUI.DrawTexture to see whether it is a stub, so it was left alone: " + ex.Message);
				}
			}
			return false;
		}

		private static bool Draw(Rect position, Texture image, ScaleMode scaleMode, bool alphaBlend, float imageAspect, Color leftColor, Vector4 borderWidths)
		{
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)