Decompiled source of ScalerCore v1.1.1

ScalerCore.dll

Decompiled 3 days 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.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using ScalerCore.AprilFools;
using ScalerCore.Compat;
using ScalerCore.Configuration;
using ScalerCore.Handlers;
using ScalerCore.Handlers.EnemyVisuals;
using ScalerCore.Utilities;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Audio;
using UnityEngine.Rendering.PostProcessing;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("Vippy")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Scaling library API for R.E.P.O. shrink and grow mods. Handles physics, mass, audio, NavMesh, animation, colliders, and multiplayer sync. Compile-time reference only: ship the runtime through the ScalerCore Thunderstore dependency.")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1+c1b6f75113d95cf2fd7578b0f8d5bcccad3a9632")]
[assembly: AssemblyProduct("ScalerCore")]
[assembly: AssemblyTitle("ScalerCore")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/VirtualPixel/ScalerCore.git")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.1.0")]
[module: UnverifiableCode]
[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 ScalerCore
{
	internal static class BuildInfo
	{
		public const string Version = "1.1.1";
	}
	internal static class NativeRespawn
	{
		private static readonly Dictionary<Assembly, bool> KnownAssemblies = new Dictionary<Assembly, bool>();

		internal static bool KindEligible(ScaleController ctrl)
		{
			IScaleHandler handler = ctrl.Handler;
			if (handler is ValuableHandler || handler is ItemHandler || handler is CosmeticHandler)
			{
				return true;
			}
			return false;
		}

		internal static bool Held(ScaleController ctrl)
		{
			if ((Object)(object)ctrl._physGrabObject != (Object)null)
			{
				if (!ctrl._physGrabObject.grabbed)
				{
					return ctrl._physGrabObject.playerGrabbing.Count > 0;
				}
				return true;
			}
			return false;
		}

		internal static bool InCart(ScaleController ctrl)
		{
			PhysGrabObject physGrabObject = ctrl._physGrabObject;
			if ((Object)(object)physGrabObject == (Object)null)
			{
				return false;
			}
			PhysGrabObjectImpactDetector impactDetector = physGrabObject.impactDetector;
			if ((Object)(object)impactDetector == (Object)null)
			{
				return false;
			}
			if (impactDetector.inCart)
			{
				return true;
			}
			PhysGrabCart currentCart = impactDetector.currentCart;
			if ((Object)(object)currentCart != (Object)null)
			{
				return currentCart.itemsInCart.Contains(physGrabObject);
			}
			return false;
		}

		private static bool IsRebuildable(Assembly assembly)
		{
			if (KnownAssemblies.TryGetValue(assembly, out var value))
			{
				return value;
			}
			if (assembly == typeof(NativeRespawn).Assembly)
			{
				KnownAssemblies[assembly] = true;
				return true;
			}
			string name = assembly.GetName().Name;
			bool flag = name.StartsWith("Assembly-CSharp") || name.StartsWith("UnityEngine") || name.StartsWith("Unity.") || name.StartsWith("Photon") || name.StartsWith("System") || name == "mscorlib" || name == "netstandard";
			KnownAssemblies[assembly] = flag;
			return flag;
		}

		internal static bool HasForeignComponent(ScaleController ctrl)
		{
			if (ctrl._foreignChecked)
			{
				return ctrl._foreignComponent != null;
			}
			ctrl._foreignChecked = true;
			MonoBehaviour[] componentsInChildren = ((Component)ctrl).GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Type type = ((object)val).GetType();
					if (!IsRebuildable(type.Assembly))
					{
						ctrl._foreignComponent = type.FullName + " (" + type.Assembly.GetName().Name + ")";
						break;
					}
				}
			}
			return ctrl._foreignComponent != null;
		}

		internal static RespawnRules.Exclusion ExclusionFor(ScaleController ctrl)
		{
			RespawnRules.Exclusion exclusion = RespawnRules.Excluded(KindEligible(ctrl), InCart(ctrl), HasForeignComponent(ctrl), Held(ctrl));
			if (exclusion != RespawnRules.Exclusion.None && ctrl._loggedExclusion != exclusion)
			{
				ctrl._loggedExclusion = exclusion;
				if (exclusion != RespawnRules.Exclusion.Kind)
				{
					Plugin.Log.LogDebug((object)("[SC] " + ctrl._displayName + " stays on the shrink RPC: " + Because(exclusion, ctrl)));
				}
			}
			return exclusion;
		}

		private static string Because(RespawnRules.Exclusion reason, ScaleController ctrl)
		{
			return reason switch
			{
				RespawnRules.Exclusion.Kind => "nothing to respawn it from", 
				RespawnRules.Exclusion.InCart => "it is in a cart, and a swap would orphan it in the cart's list and in every mod keeping one", 
				RespawnRules.Exclusion.Foreign => "another mod put " + ctrl._foreignComponent + " on it, and the prefab has no such thing", 
				RespawnRules.Exclusion.Held => "someone is holding it, the swap waits until they are not", 
				_ => "no reason", 
			};
		}

		internal static bool Driven(ScaleController ctrl)
		{
			ItemVehicle component = ((Component)ctrl).GetComponent<ItemVehicle>();
			if ((Object)(object)component != (Object)null)
			{
				return (Object)(object)component.Driver != (Object)null;
			}
			return false;
		}

		internal static RespawnRules.Verdict Decide(ScaleController ctrl)
		{
			PhotonView component = ((Component)ctrl).GetComponent<PhotonView>();
			bool hasSceneView = (Object)(object)component != (Object)null && component.ViewID != 0 && component.IsRoomView;
			return RespawnRules.Decide(ScaleManager.NativeSync, SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom, PhotonNetwork.IsMasterClient, hasSceneView, ResolvePrefabPath(ctrl) != null, RespawnRules.RespawnAllowed(ExclusionFor(ctrl)), Held(ctrl), ctrl.InInventory, Driven(ctrl), ScaleManager.NativeSyncWhileHeld);
		}

		internal static string? ResolvePrefabPath(ScaleController ctrl)
		{
			if (ctrl._prefabPath != null)
			{
				if (ctrl._prefabPath.Length <= 0)
				{
					return null;
				}
				return ctrl._prefabPath;
			}
			string text = null;
			ItemAttributes component = ((Component)ctrl).GetComponent<ItemAttributes>();
			string text2 = (((Object)(object)component != (Object)null && (Object)(object)component.item != (Object)null && component.item.prefab != null) ? ((PrefabRef<GameObject>)(object)component.item.prefab).ResourcePath : null);
			string[] array = new string[3]
			{
				text2,
				RespawnRules.PathFromName(((Object)((Component)ctrl).gameObject).name, "Valuables"),
				RespawnRules.PathFromName(((Object)((Component)ctrl).gameObject).name, "Items")
			};
			foreach (string text3 in array)
			{
				if (!string.IsNullOrEmpty(text3))
				{
					GameObject val = Resources.Load<GameObject>(text3);
					if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponent<PhysGrabObject>() != (Object)null)
					{
						text = text3;
						break;
					}
				}
			}
			ctrl._prefabPath = text ?? "";
			return text;
		}

		internal static bool Swap(ScaleController ctrl, Vector3 targetScale, ScaleOptions options, float remaining, float fromFactor)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: 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_0100: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0459: Unknown result type (might be due to invalid IL or missing references)
			string text = ResolvePrefabPath(ctrl);
			if (text == null)
			{
				return false;
			}
			GameObject gameObject = ((Component)ctrl).gameObject;
			Transform transform = gameObject.transform;
			Rigidbody rb = ctrl._rb;
			Vector3 position = transform.position;
			Quaternion rotation = transform.rotation;
			Vector3 velocity = (((Object)(object)rb != (Object)null) ? rb.velocity : Vector3.zero);
			Vector3 angularVelocity = (((Object)(object)rb != (Object)null) ? rb.angularVelocity : Vector3.zero);
			ValuableObject component = gameObject.GetComponent<ValuableObject>();
			ItemAttributes component2 = gameObject.GetComponent<ItemAttributes>();
			ItemBattery component3 = gameObject.GetComponent<ItemBattery>();
			ItemToggle component4 = gameObject.GetComponent<ItemToggle>();
			string text2 = (((Object)(object)component2 != (Object)null) ? component2.instanceName : null);
			if ((Object)(object)component3 != (Object)null && !string.IsNullOrEmpty(text2))
			{
				SemiFunc.StatSetBattery(text2, Mathf.RoundToInt(component3.batteryLife));
			}
			object[] array = NativeScaleData.Pack(new float[3] { targetScale.x, targetScale.y, targetScale.z }, new float[3]
			{
				ctrl.OriginalScale.x,
				ctrl.OriginalScale.y,
				ctrl.OriginalScale.z
			}, fromFactor, remaining, ScaleOptionsCodec.PackFloats(in options), ScaleOptionsCodec.PackBools(in options));
			GameObject val;
			try
			{
				val = PhotonNetwork.InstantiateRoomObject(text, position, rotation, (byte)0, array);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[SC] native respawn of " + ctrl._displayName + " failed at spawn (" + text + "): " + ex.Message));
				return false;
			}
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)("[SC] native respawn of " + ctrl._displayName + ": the game refused to spawn " + text + ", keeping the RPC path"));
				return false;
			}
			ItemVolume componentInChildren = val.GetComponentInChildren<ItemVolume>();
			if ((Object)(object)componentInChildren != (Object)null && (Object)(object)val.GetComponent<ItemAttributes>() != (Object)null)
			{
				Vector3 val2 = ((Component)componentInChildren).transform.position - val.transform.position;
				val.transform.position = position + val2;
				Rigidbody component5 = val.GetComponent<Rigidbody>();
				if ((Object)(object)component5 != (Object)null)
				{
					component5.position = position + val2;
				}
			}
			Rigidbody component6 = val.GetComponent<Rigidbody>();
			if ((Object)(object)component6 != (Object)null)
			{
				component6.velocity = velocity;
				component6.angularVelocity = angularVelocity;
			}
			ValuableObject component7 = val.GetComponent<ValuableObject>();
			if ((Object)(object)component != (Object)null && (Object)(object)component7 != (Object)null)
			{
				component7.dollarValueOriginal = component.dollarValueOriginal;
				component7.dollarValueCurrent = component.dollarValueCurrent;
				component7.dollarValueOverride = component.dollarValueOverride;
				component7.dollarValueSet = true;
				PhysGrabObjectImpactDetector component8 = gameObject.GetComponent<PhysGrabObjectImpactDetector>();
				PhysGrabObjectImpactDetector component9 = val.GetComponent<PhysGrabObjectImpactDetector>();
				if ((Object)(object)component8 != (Object)null && (Object)(object)component9 != (Object)null)
				{
					component9.durability = component8.durability;
				}
				if ((Object)(object)RoundDirector.instance != (Object)null)
				{
					RoundDirector instance = RoundDirector.instance;
					instance.haulGoalMax -= (int)component.dollarValueCurrent;
				}
			}
			ItemAttributes component10 = val.GetComponent<ItemAttributes>();
			if ((Object)(object)component2 != (Object)null && (Object)(object)component10 != (Object)null && component2.value > 0)
			{
				component10.value = component2.value;
				PhotonView component11 = val.GetComponent<PhotonView>();
				if ((Object)(object)component11 != (Object)null && component11.ViewID != 0)
				{
					component11.RPC("GetValueRPC", (RpcTarget)1, new object[1] { component2.value });
				}
			}
			ItemBattery component12 = val.GetComponent<ItemBattery>();
			if ((Object)(object)component3 != (Object)null && (Object)(object)component12 != (Object)null)
			{
				component12.SetBatteryLife(Mathf.RoundToInt(component3.batteryLife));
			}
			ScaleController component13 = val.GetComponent<ScaleController>();
			if ((Object)(object)component13 != (Object)null)
			{
				component13._carry = new RespawnCarry
				{
					InstanceName = text2,
					Discovered = ((Object)(object)component != (Object)null && component.discovered),
					ToggleOn = ((Object)(object)component4 != (Object)null && component4.toggleState)
				};
				ScaleManager.NoteRespawn(gameObject, val, component13);
			}
			else
			{
				Plugin.Log.LogWarning((object)("[SC] native respawn of " + ctrl._displayName + ": the clone came up without a ScaleController, so nothing carried over and no mod was told where it went"));
			}
			ManualLogSource log = Plugin.Log;
			string text3 = $"[SC] native respawn {ctrl._displayName}: {text} at scale {targetScale.x:F2} (from x{fromFactor:F2}), ";
			string arg = ((remaining > 0f) ? (remaining.ToString("F0") + "s left") : "no timer");
			PhotonView component14 = val.GetComponent<PhotonView>();
			log.LogInfo((object)(text3 + $"{arg}, view {((component14 != null) ? new int?(component14.ViewID) : ((int?)null))}"));
			PhotonNetwork.Destroy(gameObject);
			return true;
		}
	}
	internal sealed class RespawnCarry
	{
		internal string? InstanceName;

		internal bool Discovered;

		internal bool ToggleOn;
	}
	[HarmonyPatch(typeof(PunManager), "Start")]
	internal static class AttachNetRelayPatch
	{
		private static void Postfix(PunManager __instance)
		{
			if (!((Object)(object)((Component)__instance).GetComponent<ScaleNetRelay>() != (Object)null))
			{
				((Component)__instance).gameObject.AddComponent<ScaleNetRelay>();
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObject), "Awake")]
	internal static class AttachToValuablePatch
	{
		private static void Postfix(PhysGrabObject __instance)
		{
			if (!((Object)(object)((Component)__instance).GetComponent<ScaleController>() != (Object)null))
			{
				bool num = (Object)(object)((Component)__instance).GetComponent<ValuableObject>() != (Object)null;
				bool flag = (Object)(object)((Component)__instance).GetComponent<ItemAttributes>() != (Object)null;
				bool flag2 = (Object)(object)((Component)__instance).GetComponent<CosmeticWorldObject>() != (Object)null;
				bool flag3 = (Object)(object)((Component)__instance).GetComponent<PlayerDeathHead>() != (Object)null;
				bool flag4 = (Object)(object)((Component)__instance).GetComponent<ShopRadio>() != (Object)null;
				if (num || flag || flag2 || flag3 || flag4)
				{
					((Component)__instance).gameObject.AddComponent<ScaleController>();
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyRigidbody), "Awake")]
	internal static class AttachToEnemyPatch
	{
		private static void Postfix(EnemyRigidbody __instance)
		{
			if (!((Object)(object)((Component)__instance).GetComponent<ScaleController>() != (Object)null))
			{
				((Component)__instance).gameObject.AddComponent<ScaleController>();
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "Start")]
	internal static class AttachToPlayerPatch
	{
		private static void Postfix(PlayerAvatar __instance)
		{
			if (!((Object)(object)((Component)__instance).GetComponent<ScaleController>() != (Object)null))
			{
				((Component)__instance).gameObject.AddComponent<ScaleController>();
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabHinge), "Awake")]
	internal static class AttachToDoorPatch
	{
		private static void Postfix(PhysGrabHinge __instance)
		{
			if (!((Object)(object)((Component)__instance).GetComponent<ScaleController>() != (Object)null))
			{
				((Component)__instance).gameObject.AddComponent<ScaleController>();
			}
		}
	}
	[HarmonyPatch(typeof(RunManager), "ChangeLevel")]
	internal static class LevelChangePatch
	{
		private static void Prefix(RunManager __instance, out bool __state)
		{
			__state = LevelChangeGate.Proceeds(SemiFunc.MenuLevel(), SemiFunc.IsMasterClientOrSingleplayer(), __instance.restarting);
		}

		private static void Postfix(bool __state)
		{
			if (__state)
			{
				ScaleManager.CleanupAll();
				MapCollapse.OnLevelChange();
			}
		}
	}
	[HarmonyPatch(typeof(RunManagerPUN), "UpdateLevelRPC")]
	internal static class LevelChangeNonHostPatch
	{
		private static void Postfix()
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				ScaleManager.CleanupAll();
				MapCollapse.OnLevelChange();
			}
		}
	}
	[HarmonyPatch(typeof(ParticleScriptExplosion), "Spawn")]
	internal static class ExplosionScalePatch
	{
		private static ScaleController? ScaledSpawner(ParticleScriptExplosion spawner)
		{
			ScaleController scaleController = null;
			EnemyParent componentInParent = ((Component)spawner).GetComponentInParent<EnemyParent>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				EnemyRigidbody componentInChildren = ((Component)componentInParent).GetComponentInChildren<EnemyRigidbody>(true);
				scaleController = ((componentInChildren != null) ? ((Component)componentInChildren).GetComponent<ScaleController>() : null);
			}
			if (scaleController == null)
			{
				scaleController = ((Component)spawner).GetComponentInParent<ScaleController>();
			}
			if (!((Object)(object)scaleController != (Object)null) || !scaleController.IsScaled)
			{
				return null;
			}
			return scaleController;
		}

		private static void Prefix(ParticleScriptExplosion __instance, out ScaleController? __state, ref float size, ref int damage, ref int enemyDamage, ref float forceMulti)
		{
			__state = ScaledSpawner(__instance);
			if (!((Object)(object)__state == (Object)null))
			{
				float factor = __state._options.Factor;
				size *= factor;
				damage = Mathf.RoundToInt((float)damage * factor);
				enemyDamage = Mathf.RoundToInt((float)enemyDamage * factor);
				forceMulti *= factor;
				Plugin.Log.LogDebug((object)$"[SC] explosion scaled x{factor:F2} on {__state._displayName} (size={size:F2} dmg={damage} force={forceMulti:F2})");
			}
		}

		private static void Postfix(ScaleController? __state, ParticlePrefabExplosion __result)
		{
			if (!((Object)(object)__state == (Object)null) && !((Object)(object)__result == (Object)null))
			{
				AudioPitchHelper.PitchOneShot((Component)(object)__result, __state._options.Factor, __state._options.AudioPresence);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerTumble), "SetupDone")]
	internal static class PlayerTumbleLinkPatch
	{
		private static void Postfix(PlayerTumble __instance)
		{
			PlayerAvatar playerAvatar = __instance.playerAvatar;
			ScaleController scaleController = ((playerAvatar != null) ? ((Component)playerAvatar).GetComponent<ScaleController>() : null);
			if (!((Object)(object)scaleController == (Object)null))
			{
				AttachLink(((Component)__instance).gameObject, scaleController);
				Collider[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Collider>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					AttachLink(((Component)componentsInChildren[i]).gameObject, scaleController);
				}
				Plugin.Log.LogDebug((object)("[SC] PlayerShrinkLink (tumble) attached → " + ((Object)((Component)__instance).gameObject).name + "  avatar=" + ((Object)((Component)scaleController).gameObject).name));
			}
		}

		private static void AttachLink(GameObject go, ScaleController ctrl)
		{
			(go.GetComponent<PlayerShrinkLink>() ?? go.AddComponent<PlayerShrinkLink>()).Controller = ctrl;
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathRPC")]
	internal static class PlayerDeathExpandPatch
	{
		private static void Postfix(PlayerAvatar __instance)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				ScaleController component = ((Component)__instance).GetComponent<ScaleController>();
				if (!((Object)(object)component == (Object)null) && component.IsScaled && !component._invertedActive)
				{
					component.DispatchExpand();
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerHealth), "Hurt")]
	internal static class PlayerBonkPatch
	{
		private static void Prefix(PlayerHealth __instance, out int __state)
		{
			__state = __instance.health;
		}

		private static void Postfix(PlayerHealth __instance, int __state)
		{
			if (__instance.health >= __state)
			{
				return;
			}
			ScaleController scaleController = ((Component)__instance).GetComponentInParent<ScaleController>() ?? ((Component)__instance).GetComponentInChildren<ScaleController>();
			if ((Object)(object)scaleController == (Object)null)
			{
				return;
			}
			if (scaleController.IsScaled)
			{
				if (!scaleController._invertedActive)
				{
					scaleController.RequestBonkExpand();
				}
			}
			else if (scaleController._invertedActive)
			{
				scaleController.RequestInvertedReshrink();
			}
		}
	}
	[HarmonyPatch(typeof(ItemEquippable), "RequestEquip")]
	internal static class ShrunkEquipBlockPatch
	{
		private static bool Prefix(ItemEquippable __instance)
		{
			ScaleController component = ((Component)__instance).GetComponent<ScaleController>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			bool flag = false;
			if (component.HandlerState is CartHandler.State state)
			{
				flag = state.AddedEquippable;
			}
			else if (component.HandlerState is ItemHandler.State state2)
			{
				flag = state2.AddedEquippable;
			}
			else if (component.HandlerState is VehicleHandler.State state3)
			{
				flag = state3.AddedEquippable;
			}
			if (!flag)
			{
				return true;
			}
			PlayerAvatar instance = PlayerAvatar.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return true;
			}
			ScaleController component2 = ((Component)instance).GetComponent<ScaleController>();
			if ((Object)(object)component2 != (Object)null && component2.IsScaled)
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PlayerCollisionGrounded), "Update")]
	internal static class GroundedWallJumpFix
	{
		private static void Postfix(PlayerCollisionGrounded __instance)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (!__instance.Grounded)
			{
				return;
			}
			PlayerAvatar instance = PlayerAvatar.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			ScaleController component = ((Component)instance).GetComponent<ScaleController>();
			if (!((Object)(object)component == (Object)null) && component.IsScaled)
			{
				float num = __instance.Collider.radius * 1.5f;
				if (!Physics.Raycast(((Component)__instance).transform.position, Vector3.down, num, LayerMask.op_Implicit(__instance.LayerMask), (QueryTriggerInteraction)1))
				{
					__instance.Grounded = false;
					__instance.GroundedTimer = 0f;
					__instance.CollisionController.Grounded = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabber), "OverrideGrabDistance")]
	internal static class GrabDistanceScalePatch
	{
		private static void Prefix(ref float dist)
		{
			if ((Object)(object)PhysGrabber.instance?.playerAvatar == (Object)null)
			{
				return;
			}
			ScaleController component = ((Component)PhysGrabber.instance.playerAvatar).GetComponent<ScaleController>();
			if (!((Object)(object)component == (Object)null) && component.IsScaled)
			{
				float factor = component._options.Factor;
				if (factor > 1f)
				{
					dist *= factor;
				}
				else
				{
					dist *= 0.7f;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObject), "OverrideGrabVerticalPosition")]
	internal static class GrabVerticalPositionScalePatch
	{
		private static void Prefix(ref float pos)
		{
			PhysGrabber instance = PhysGrabber.instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				PlayerAvatar playerAvatar = instance.playerAvatar;
				obj = ((playerAvatar != null) ? ((Component)playerAvatar).GetComponent<ScaleController>() : null);
			}
			ScaleController scaleController = (ScaleController)obj;
			if (!((Object)(object)scaleController == (Object)null) && scaleController.IsScaled)
			{
				float factor = scaleController._options.Factor;
				if (factor > 1f)
				{
					pos *= factor;
				}
				else
				{
					pos = 0f;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabber), "StartGrabbingPhysObject")]
	internal static class ForceGrabPointVerticalScalePatch
	{
		private static void Postfix(PhysGrabber __instance, PhysGrabObject ___grabbedPhysGrabObject)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar playerAvatar = __instance.playerAvatar;
			if ((Object)(object)playerAvatar == (Object)null)
			{
				return;
			}
			ScaleController component = ((Component)playerAvatar).GetComponent<ScaleController>();
			if ((Object)(object)component == (Object)null || !component.IsScaled || (Object)(object)___grabbedPhysGrabObject == (Object)null)
			{
				return;
			}
			Transform forceGrabPoint = ___grabbedPhysGrabObject.forceGrabPoint;
			if (!((Object)(object)forceGrabPoint == (Object)null) && ((Component)forceGrabPoint).gameObject.activeSelf)
			{
				PlayerLocalCamera localCamera = playerAvatar.localCamera;
				Transform val = ((localCamera != null) ? localCamera.GetOverrideTransform() : null);
				if (!((Object)(object)val == (Object)null))
				{
					float num = 0.3f * (1f - component._options.Factor);
					Vector3 val2 = val.up * num;
					Transform physGrabPointPuller = __instance.physGrabPointPuller;
					physGrabPointPuller.position += val2;
					Transform physGrabPointPlane = __instance.physGrabPointPlane;
					physGrabPointPlane.position += val2;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabCart), "CartSteer")]
	internal static class CartHandledDistancePatch
	{
		private static float ScalePullDist(float d, PhysGrabCart cart, PhysGrabber grabber)
		{
			ScaleController component = ((Component)cart).GetComponent<ScaleController>();
			if ((Object)(object)component != (Object)null && component.IsScaled)
			{
				return d * Mathf.Lerp(component._options.Factor, 1f, 0.15f);
			}
			if ((Object)(object)grabber == (Object)null)
			{
				return d;
			}
			ScaleController component2 = ((Component)grabber.playerAvatar).GetComponent<ScaleController>();
			if ((Object)(object)component2 != (Object)null && component2.IsScaled)
			{
				return d * Mathf.Lerp(1f, component2._options.Factor, 0.15f);
			}
			return d;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase originalMethod)
		{
			MethodInfo lerpMethod = AccessTools.Method(typeof(Mathf), "Lerp", new Type[3]
			{
				typeof(float),
				typeof(float),
				typeof(float)
			}, (Type[])null);
			MethodInfo scaleMethod = AccessTools.Method(typeof(CartHandledDistancePatch), "ScalePullDist", (Type[])null, (Type[])null);
			IList<LocalVariableInfo> localVariables = originalMethod.GetMethodBody().LocalVariables;
			int grabberIndex = -1;
			int num = 0;
			foreach (LocalVariableInfo item in localVariables)
			{
				if (item.LocalType == typeof(PhysGrabber))
				{
					num++;
					if (num == 2)
					{
						grabberIndex = item.LocalIndex;
						break;
					}
				}
			}
			if (grabberIndex == -1)
			{
				Plugin.Log.LogWarning((object)"[SC] CartSteer transpiler: second PhysGrabber local not found. Cart pull-distance scaling is DISABLED this session; if this appears after a game update, report it.");
				foreach (CodeInstruction instruction in instructions)
				{
					yield return instruction;
				}
				yield break;
			}
			int injected = 0;
			foreach (CodeInstruction code in instructions)
			{
				yield return code;
				if (code.opcode == OpCodes.Call && (MethodInfo)code.operand == lerpMethod)
				{
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Ldloc, (object)grabberIndex);
					yield return new CodeInstruction(OpCodes.Call, (object)scaleMethod);
					injected++;
				}
			}
			if (injected == 0)
			{
				Plugin.Log.LogWarning((object)"[SC] CartSteer transpiler: no Mathf.Lerp callsites matched. Cart pull-distance scaling is DISABLED this session; if this appears after a game update, report it.");
			}
		}
	}
	[HarmonyPatch(typeof(CameraGlitch), "Update")]
	internal static class CameraGlitchScalePatch
	{
		private static void Postfix(CameraGlitch __instance)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar instance = PlayerAvatar.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			ScaleController component = ((Component)instance).GetComponent<ScaleController>();
			if (!((Object)(object)component == (Object)null) && component.IsScaled)
			{
				float num = ((component.OriginalScale.x > 0f) ? (component._t.localScale.x / component.OriginalScale.x) : 1f);
				if (!(num >= 1f) && !(num <= 0f))
				{
					Transform transform = ((Component)__instance).transform;
					transform.localScale /= num;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "Footstep")]
	internal static class FootstepPitchPatch
	{
		private static void Prefix(PlayerAvatar __instance)
		{
			ScaleController component = ((Component)__instance).GetComponent<ScaleController>();
			if ((Object)(object)component != (Object)null && component.IsScaled)
			{
				ScaleController.FootstepPitchMult = component._options.FootstepPitchMultiplier;
			}
		}

		private static void Postfix()
		{
			ScaleController.FootstepPitchMult = 1f;
		}
	}
	[HarmonyPatch(typeof(Sound), "Play", new Type[]
	{
		typeof(Vector3),
		typeof(float),
		typeof(float),
		typeof(float),
		typeof(float)
	})]
	internal static class SoundPlayPitchPatch
	{
		private static void Postfix(AudioSource __result)
		{
			if (ScaleController.FootstepPitchMult != 1f && (Object)(object)__result != (Object)null)
			{
				__result.pitch *= ScaleController.FootstepPitchMult;
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager), "ItemFetchName")]
	internal static class RespawnKeepsTheItemNamePatch
	{
		private static bool Prefix(ItemAttributes itemAttributes, int photonViewID)
		{
			if ((Object)(object)itemAttributes == (Object)null)
			{
				return true;
			}
			ScaleController component = ((Component)itemAttributes).GetComponent<ScaleController>();
			string text = (((Object)(object)component != (Object)null && component._carry != null) ? component._carry.InstanceName : null);
			if (string.IsNullOrEmpty(text))
			{
				return true;
			}
			component._carry.InstanceName = null;
			if ((Object)(object)PunManager.instance == (Object)null)
			{
				return true;
			}
			PunManager.instance.SetItemName(text, itemAttributes, photonViewID);
			Plugin.Log.LogDebug((object)("[SC] " + ((Object)((Component)itemAttributes).gameObject).name + " came back from a respawn as " + text + ", not as a new item"));
			return false;
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class DriverFullyMountedScalePatch
	{
		private static void Postfix(ItemVehicle __instance, ref bool __result)
		{
			if (!__result && __instance.seats != null && __instance.seats.Length != 0 && !((Object)(object)__instance.seats[0].seatedPlayer == (Object)null))
			{
				ScaleController component = ((Component)__instance).GetComponent<ScaleController>();
				if ((Object)(object)component != (Object)null && component.IsScaled && component.CurrentOptions.Factor < 1f)
				{
					__result = true;
				}
			}
		}
	}
	[HarmonyPatch(typeof(ValuableTeethBot), "Update")]
	internal static class TeethVoiceScalePatch
	{
		private static void Postfix(ValuableTeethBot __instance)
		{
			ScaleController scaleController = ((Component)__instance).GetComponent<ScaleController>() ?? ((Component)__instance).GetComponentInParent<ScaleController>();
			if ((Object)(object)scaleController == (Object)null || !scaleController.IsScaled)
			{
				return;
			}
			float num = PlayerHandler.VoicePitchMult(scaleController._options.Factor);
			foreach (PhysGrabber item in __instance.physGrabObject.playerGrabbing)
			{
				if (item.playerAvatar.voiceChatFetched)
				{
					item.playerAvatar.voiceChat.OverridePitch(1.25f * num, 0.1f, 0.1f, 0.2f, 0.05f, 100f);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ItemWalkieTalkie), "Update")]
	internal static class WalkieVoiceScalePatch
	{
		private static void Postfix(ItemWalkieTalkie __instance)
		{
			ScaleController scaleController = ((Component)__instance).GetComponent<ScaleController>() ?? ((Component)__instance).GetComponentInParent<ScaleController>();
			if (!((Object)(object)scaleController == (Object)null) && scaleController.IsScaled)
			{
				PlayerAvatar inThisWalkie = __instance.inThisWalkie;
				if (!((Object)(object)inThisWalkie == (Object)null) && inThisWalkie.voiceChatFetched && !inThisWalkie.isLocal)
				{
					float num = PlayerHandler.VoicePitchMult(scaleController._options.Factor);
					inThisWalkie.voiceChat.OverridePitch(1.5f * num, 0.1f, 0.1f, 0.1f, 0f, 0f);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerDeathHead), "Update")]
	internal static class DeathHeadVoiceScalePatch
	{
		private static void Postfix(PlayerDeathHead __instance)
		{
			if (__instance.spectated && !((Object)(object)__instance.playerAvatar == (Object)null) && __instance.playerAvatar.voiceChatFetched)
			{
				ScaleController scaleController = ((Component)__instance).GetComponent<ScaleController>() ?? ((Component)__instance).GetComponentInParent<ScaleController>();
				if (!((Object)(object)scaleController == (Object)null) && scaleController.IsScaled)
				{
					float num = PlayerHandler.VoicePitchMult(scaleController._options.Factor);
					float num2 = (__instance.spectatedLowEnergy ? 0.5f : 1f);
					__instance.playerAvatar.voiceChat.OverridePitch(num2 * num, 0.2f, 0.2f, 0.1f, 0f, 0f);
				}
			}
		}
	}
	public class PlayerShrinkLink : MonoBehaviour
	{
		public ScaleController Controller;
	}
	[BepInPlugin("Vippy.ScalerCore", "ScalerCore", "1.1.1")]
	public class Plugin : BaseUnityPlugin
	{
		internal static Harmony Harmony = null;

		internal static ManualLogSource Log = null;

		internal static readonly bool DiagMass = Environment.GetEnvironmentVariable("SCALERCORE_DIAG") == "1";

		internal static readonly bool DebugDraw = Environment.GetEnvironmentVariable("SCALERCORE_DEBUG") == "1" || File.Exists(Path.Combine(Paths.ConfigPath, "scalercore_debug"));

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony = new Harmony("Vippy.ScalerCore");
			Harmony.PatchAll();
			RepoXRBridge.Warm();
			PluginConfig.Init(((BaseUnityPlugin)this).Config);
			((Component)this).gameObject.AddComponent<MapCollapse>();
			if (DebugDraw)
			{
				((Component)this).gameObject.AddComponent<ExtractionVolumeDebug>();
			}
		}
	}
	public class ScaleController : MonoBehaviourPunCallbacks
	{
		public static readonly HashSet<ScaleController> Scaled = new HashSet<ScaleController>();

		internal static float FootstepPitchMult = 1f;

		public static bool AllowManualScale = true;

		public Transform? ScaleTarget;

		internal IScaleHandler? Handler;

		internal object? HandlerState;

		internal bool HandlerOwnsScale;

		internal PhysGrabObject? _physGrabObject;

		internal Transform _t;

		internal Rigidbody? _rb;

		internal float _originalMass;

		private RoomVolumeCheck? _roomVolumeCheck;

		private Vector3 _originalRoomVolumeSize;

		private Vector3 _originalCheckPosition;

		private bool _isItem;

		internal ItemEquippable? _itemEquippable;

		internal List<ItemHandler.ScaledField>? _scaledItemFields;

		internal bool _invertedActive;

		internal Vector3 _target;

		internal Vector3 _animScale;

		internal bool _transitioning;

		private bool _wasForcing;

		internal float _currentAnimSpeed = ScaleOptions.Default.Speed;

		private Coroutine? _playerBounceAnim;

		private float _shrinkTimer;

		internal ScaleOptions _options;

		internal float _bonkImmuneTimer;

		internal string _displayName = "";

		internal PhotonView? _networkPV;

		private bool _inited;

		private (Vector3 target, float[] opts, bool[] flags)? _pendingShrink;

		internal AudioPitchHelper _audioPitch = new AudioPitchHelper();

		private ScaleOptions? _respawnSession;

		internal bool _native;

		private bool _nativeApplied;

		private object[]? _nativeData;

		internal bool _nativeDeferred;

		private float _nextDeferredCheck;

		internal string? _prefabPath;

		internal RespawnRules.Exclusion _loggedExclusion;

		internal bool _foreignChecked;

		internal string? _foreignComponent;

		internal RespawnCarry? _carry;

		private int _carryFrames;

		private float _pgoVanillaMassOriginal;

		public static bool ChallengeMode { get; set; }

		public Vector3 OriginalScale { get; internal set; }

		public bool IsScaled { get; private set; }

		public ScaleOptions CurrentOptions => _options;

		public ScaleTargets TargetType
		{
			get
			{
				if (!(Handler is PlayerHandler))
				{
					if (!(Handler is EnemyHandler))
					{
						if (!(Handler is ItemHandler))
						{
							if (!(Handler is VehicleHandler))
							{
								return ScaleTargets.Valuables;
							}
							return ScaleTargets.Items;
						}
						return ScaleTargets.Items;
					}
					return ScaleTargets.Enemies;
				}
				return ScaleTargets.Players;
			}
		}

		internal string DisplayName
		{
			get
			{
				if (!string.IsNullOrEmpty(_displayName))
				{
					return _displayName;
				}
				return ((Object)((Component)this).gameObject).name;
			}
		}

		internal bool InInventory => IsItemInInventory();

		internal bool WidthCapped
		{
			get
			{
				if (Handler is EnemyHandler && _options.EnemyWidthFactorCap > 0f && _options.Factor > 1f)
				{
					return _options.Factor > _options.EnemyWidthFactorCap;
				}
				return false;
			}
		}

		internal bool UniformCapped
		{
			get
			{
				if (Handler is EnemyHandler && _options.EnemyPhysicalFactorCap > 0f && _options.Factor > 1f)
				{
					return _options.Factor > _options.EnemyPhysicalFactorCap;
				}
				return false;
			}
		}

		internal bool HeightCapped
		{
			get
			{
				if (Handler is EnemyHandler && _options.EnemyHeightFactorCap > 0f && _options.Factor > 1f)
				{
					return _options.Factor > _options.EnemyHeightFactorCap;
				}
				return false;
			}
		}

		internal bool PhysicallyCapped
		{
			get
			{
				if (!WidthCapped && !UniformCapped)
				{
					return HeightCapped;
				}
				return true;
			}
		}

		private float XZCapFactor
		{
			get
			{
				if (!WidthCapped)
				{
					if (!UniformCapped)
					{
						return 0f;
					}
					return Mathf.Max(1f, _options.EnemyPhysicalFactorCap);
				}
				return Mathf.Max(1f, _options.EnemyWidthFactorCap);
			}
		}

		private float YCapFactor
		{
			get
			{
				if (!HeightCapped)
				{
					if (!UniformCapped || WidthCapped)
					{
						return 0f;
					}
					return Mathf.Max(1f, _options.EnemyPhysicalFactorCap);
				}
				return Mathf.Max(1f, _options.EnemyHeightFactorCap);
			}
		}

		internal float PhysicalFactor
		{
			get
			{
				if (!(XZCapFactor > 0f))
				{
					return _options.Factor;
				}
				return XZCapFactor;
			}
		}

		internal float NavRadiusFactor
		{
			get
			{
				if (!(Handler is EnemyHandler) || !(_options.EnemyNavRadiusFactorCap > 0f) || !(_options.Factor > 1f) || !(_options.Factor > _options.EnemyNavRadiusFactorCap))
				{
					return PhysicalFactor;
				}
				return Mathf.Max(1f, _options.EnemyNavRadiusFactorCap);
			}
		}

		private void Awake()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: 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)
			_t = ((Component)this).transform;
			OriginalScale = ((Component)this).transform.localScale;
			_target = OriginalScale;
			_animScale = OriginalScale;
			PhotonView component = ((Component)this).GetComponent<PhotonView>();
			if ((Object)(object)component != (Object)null && NativeScaleData.TryUnpack(component.InstantiationData, out float[] original, out float fromFactor, out float _, out float[] opts, out bool[] flags))
			{
				_native = true;
				_nativeData = component.InstantiationData;
				OriginalScale = new Vector3(original[0], original[1], original[2]);
				_options = ScaleOptionsCodec.Unpack(opts, flags, ScaleOptions.Default);
				_target = OriginalScale * _options.Factor;
				float num = ((fromFactor > 0f) ? fromFactor : _options.Factor);
				_t.localScale = OriginalScale * num;
				_animScale = _t.localScale;
				if (!Mathf.Approximately(_options.Factor, 1f))
				{
					IsScaled = true;
					Scaled.Add(this);
				}
			}
			EnsureNetworkPV();
		}

		private void Start()
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			EnsureInitialized();
			string text = ((Handler != null) ? Handler.GetType().Name.Replace("Handler", "").ToLower() : "base");
			EnemyParent componentInParent = ((Component)this).GetComponentInParent<EnemyParent>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				int num = 0;
				ScaleController[] componentsInChildren = ((Component)componentInParent).GetComponentsInChildren<ScaleController>();
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if ((Object)(object)componentsInChildren[i] != (Object)(object)this)
					{
						num++;
					}
				}
				if (num > 0)
				{
					Plugin.Log.LogWarning((object)$"[SC] *** DUPLICATE: {_displayName} already has {num} other ScaleController(s) under same EnemyParent ***");
				}
			}
			EnemyHandler.State state = HandlerState as EnemyHandler.State;
			Plugin.Log.LogDebug((object)("[SC] Registered " + _displayName + " (" + text + ")" + $"  scale={OriginalScale}" + "  mass=" + (((Object)(object)_rb != (Object)null) ? _rb.mass.ToString("F2") : "none") + "  animTarget=" + (((Object)(object)state?.AnimTarget != (Object)null) ? ((Object)((Component)state.AnimTarget).gameObject).name : "NONE") + "  navAgent=" + (((Object)(object)state?.NavAgent != (Object)null) ? "yes" : "no") + "  groundMarker=" + (((Object)(object)state?.GroundMarker != (Object)null) ? ((Object)((Component)state.GroundMarker).gameObject).name : "none")));
			(Vector3, float[], bool[])? pendingShrink = _pendingShrink;
			if (pendingShrink.HasValue)
			{
				(Vector3, float[], bool[]) valueOrDefault = pendingShrink.GetValueOrDefault();
				_pendingShrink = null;
				Plugin.Log.LogDebug((object)("[SC] applying shrink that arrived before Start on " + _displayName));
				ApplyRemoteShrink(valueOrDefault.Item1, valueOrDefault.Item2, valueOrDefault.Item3);
			}
			if (Handler is PlayerHandler && SemiFunc.RunIsLobbyMenu())
			{
				((MonoBehaviour)this).StartCoroutine(LobbyPitchDeferred());
			}
			if (ChallengeMode && Handler is PlayerHandler && !SemiFunc.RunIsLobbyMenu())
			{
				((MonoBehaviour)this).StartCoroutine(ChallengeModeDeferred());
			}
		}

		private void EnsureInitialized()
		{
			//IL_0054: 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_0065: 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_0071: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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)
			if (!_inited)
			{
				_inited = true;
				Handler = ScaleHandlerRegistry.Resolve(((Component)this).gameObject);
				Handler?.Setup(this);
				if ((Object)(object)ScaleTarget != (Object)null)
				{
					_t = ScaleTarget;
					OriginalScale = _t.localScale;
					_target = OriginalScale;
					_animScale = OriginalScale;
				}
				_rb = ((Component)this).GetComponent<Rigidbody>();
				if ((Object)(object)_rb != (Object)null)
				{
					_originalMass = _rb.mass;
				}
				if ((Object)(object)_physGrabObject == (Object)null)
				{
					_physGrabObject = ((Component)this).GetComponent<PhysGrabObject>();
				}
				_roomVolumeCheck = ((Component)this).GetComponent<RoomVolumeCheck>();
				if ((Object)(object)_roomVolumeCheck != (Object)null)
				{
					_originalRoomVolumeSize = _roomVolumeCheck.currentSize;
					_originalCheckPosition = _roomVolumeCheck.CheckPosition;
				}
				EnemyParent componentInParent = ((Component)this).GetComponentInParent<EnemyParent>();
				_displayName = (((Object)(object)componentInParent != (Object)null) ? ((Object)((Component)componentInParent).gameObject).name : ((Object)((Component)this).gameObject).name);
				_isItem = (Object)(object)((Component)this).GetComponent<ItemAttributes>() != (Object)null;
				_itemEquippable = ((Component)this).GetComponent<ItemEquippable>();
				EnsureNetworkPV();
				if (_native && !_nativeApplied)
				{
					_nativeApplied = true;
					ApplyNative();
				}
			}
		}

		private void ApplyNative()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: 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_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: 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)
			if (!NativeScaleData.TryUnpack(_nativeData, out float[] _, out float fromFactor, out float remaining, out float[] _, out bool[] _))
			{
				return;
			}
			float factor = _options.Factor;
			Vector3 val = OriginalScale * factor;
			Vector3 val2 = OriginalScale * ((fromFactor > 0f) ? fromFactor : factor);
			bool flag = SemiFunc.IsMasterClientOrSingleplayer();
			Plugin.Log.LogDebug((object)$"[SC] native session {_displayName}  factor={factor}  from=x{fromFactor}  host={flag}  remaining={remaining:F1}");
			_t.localScale = val2;
			_animScale = val2;
			if (!IsScaled)
			{
				_currentAnimSpeed = ResolveExpandSpeed();
				ApplyScale(OriginalScale);
				SetForceGrabPoint(active: true);
				PlayImpactEffect();
				PlayCameraShake();
				return;
			}
			_invertedActive = _options.InvertedMode;
			_currentAnimSpeed = _options.Speed;
			ApplySessionLocal(val);
			if (flag)
			{
				_shrinkTimer = ((remaining > 0f) ? remaining : 0f);
				Vector3 val3 = val2 - val;
				float magnitude = ((Vector3)(ref val3)).magnitude;
				float speed = _options.Speed;
				val3 = OriginalScale;
				float num = speed * ((Vector3)(ref val3)).magnitude;
				float num2 = ((num > 0f) ? (magnitude / num * 1.1f) : 0.75f);
				_bonkImmuneTimer = Mathf.Max(num2, _options.BonkImmuneDuration);
			}
		}

		private void TickDeferredRespawn()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (_nativeDeferred && IsScaled && !(Time.unscaledTime < _nextDeferredCheck))
			{
				_nextDeferredCheck = Time.unscaledTime + 0.25f;
				if (!_transitioning && NativeRespawn.Decide(this) == RespawnRules.Verdict.Now)
				{
					_nativeDeferred = false;
					NativeRespawn.Swap(this, _target, _options, _shrinkTimer, _options.Factor);
				}
			}
		}

		private void ApplyCarry()
		{
			RespawnCarry carry = _carry;
			_carry = null;
			if (carry.Discovered)
			{
				ValuableObject component = ((Component)this).GetComponent<ValuableObject>();
				PhotonView component2 = ((Component)this).GetComponent<PhotonView>();
				if ((Object)(object)component != (Object)null && !component.discovered && (Object)(object)component2 != (Object)null && component2.ViewID != 0)
				{
					component2.RPC("DiscoverRPC", (RpcTarget)0, Array.Empty<object>());
				}
			}
			if (carry.ToggleOn)
			{
				ItemToggle component3 = ((Component)this).GetComponent<ItemToggle>();
				if ((Object)(object)component3 != (Object)null && !component3.toggleState)
				{
					component3.ToggleItem(true, -1);
				}
			}
			Plugin.Log.LogDebug((object)("[SC] respawn carry applied on " + _displayName + ": " + string.Format("name={0}  discovered={1}  switchedOn={2}", carry.InstanceName ?? "none", carry.Discovered, carry.ToggleOn)));
		}

		private void Update()
		{
			bool flag = SemiFunc.IsMasterClientOrSingleplayer();
			if (flag)
			{
				if (_carry != null && ++_carryFrames > 1)
				{
					ApplyCarry();
				}
				if (IsScaled && _shrinkTimer > 0f)
				{
					_shrinkTimer -= Time.deltaTime;
					if (_shrinkTimer <= 0f)
					{
						DispatchExpand();
					}
				}
				if (_bonkImmuneTimer > 0f)
				{
					_bonkImmuneTimer -= Time.deltaTime;
				}
				if (IsScaled && Handler != null)
				{
					Handler.OnUpdate(this);
				}
				TickDeferredRespawn();
			}
			if (!flag && IsScaled && Handler is PlayerHandler)
			{
				Handler.OnUpdate(this);
			}
			if (IsScaled && Handler is ValuableHandler)
			{
				ValuableHandler.OnDiagnoseMass(this, flag);
			}
		}

		private bool IsItemInInventory()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			if ((Object)(object)_itemEquippable == (Object)null)
			{
				return false;
			}
			if (_itemEquippable.IsEquipped())
			{
				return true;
			}
			return (int)_itemEquippable.currentState > 0;
		}

		private void LateUpdate()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0071: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//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_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: 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)
			bool flag = IsItemInInventory();
			bool flag2 = Handler is PlayerHandler;
			if (_transitioning && !flag2 && !flag)
			{
				float currentAnimSpeed = _currentAnimSpeed;
				Vector3 originalScale = OriginalScale;
				float num = currentAnimSpeed * ((Vector3)(ref originalScale)).magnitude;
				_animScale = Vector3.MoveTowards(_animScale, _target, num * Time.deltaTime);
				if (!HandlerOwnsScale)
				{
					_t.localScale = ClampPhysical(_animScale);
				}
				if (_animScale == _target)
				{
					_transitioning = false;
					Plugin.Log.LogDebug((object)$"[SC] LATE_ANIM DONE  {_displayName}  finalScale={_animScale}");
				}
			}
			Handler?.OnLateUpdate(this);
			if (!flag2 && !HandlerOwnsScale && IsScaled && !_transitioning && !flag)
			{
				Vector3 val = ClampPhysical(_target);
				bool flag3 = _t.localScale != val;
				if (flag3 && !_wasForcing)
				{
					Plugin.Log.LogDebug((object)$"[SC] LATE_FORCE  {_displayName}  was={_t.localScale}  forcing={val}");
				}
				_wasForcing = flag3;
				_t.localScale = val;
			}
			else
			{
				_wasForcing = false;
			}
		}

		private Vector3 ClampPhysical(Vector3 intended)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if (OriginalScale.x <= 0f)
			{
				return intended;
			}
			Vector3 result = intended;
			float xZCapFactor = XZCapFactor;
			if (xZCapFactor > 0f)
			{
				result.x = Mathf.Min(intended.x, OriginalScale.x * xZCapFactor);
				result.z = Mathf.Min(intended.z, OriginalScale.z * xZCapFactor);
			}
			float yCapFactor = YCapFactor;
			if (yCapFactor > 0f)
			{
				result.y = Mathf.Min(intended.y, OriginalScale.y * yCapFactor);
			}
			return result;
		}

		private void ScalePgoMassOriginal(float f)
		{
			if (!((Object)(object)_physGrabObject == (Object)null) && !_isItem && !_options.PreserveMass)
			{
				if (_pgoVanillaMassOriginal == 0f)
				{
					_pgoVanillaMassOriginal = ((_physGrabObject.massOriginal > 0f) ? _physGrabObject.massOriginal : _originalMass);
				}
				if (!(_pgoVanillaMassOriginal <= 0f))
				{
					_physGrabObject.massOriginal = Mathf.Clamp(_pgoVanillaMassOriginal * f, 0.5f, _options.MassCap);
				}
			}
		}

		private void RestorePgoMassOriginal()
		{
			if ((Object)(object)_physGrabObject != (Object)null && _pgoVanillaMassOriginal > 0f)
			{
				_physGrabObject.massOriginal = _pgoVanillaMassOriginal;
			}
			_pgoVanillaMassOriginal = 0f;
		}

		public override void OnDisable()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_0118: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			((MonoBehaviourPunCallbacks)this).OnDisable();
			if (IsScaled && Handler is EnemyHandler)
			{
				_respawnSession = ((_options.KeepThroughRespawn && SemiFunc.IsMasterClientOrSingleplayer()) ? new ScaleOptions?(_options) : ((ScaleOptions?)null));
				Plugin.Log.LogDebug((object)("[SC] DISABLE (despawn) " + _displayName + "  restoring scale" + (_respawnSession.HasValue ? "  (session held for the respawn)" : "")));
				_t.localScale = OriginalScale;
				_animScale = OriginalScale;
				_target = OriginalScale;
				_transitioning = false;
				IsScaled = false;
				_invertedActive = false;
				_shrinkTimer = 0f;
				Scaled.Remove(this);
				if ((Object)(object)_rb != (Object)null)
				{
					_rb.mass = _originalMass;
				}
				RestorePgoMassOriginal();
				if ((Object)(object)_roomVolumeCheck != (Object)null)
				{
					_roomVolumeCheck.currentSize = _originalRoomVolumeSize;
					_roomVolumeCheck.CheckPosition = _originalCheckPosition;
				}
				Handler?.OnRestore(this, isBonk: false);
				_audioPitch.RestorePitch();
				ItemHandler.OnRestoreFields(_scaledItemFields);
				_scaledItemFields = null;
			}
		}

		public override void OnEnable()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			((MonoBehaviourPunCallbacks)this).OnEnable();
			if (!_inited)
			{
				return;
			}
			(Vector3, float[], bool[])? pendingShrink = _pendingShrink;
			if (pendingShrink.HasValue)
			{
				(Vector3, float[], bool[]) valueOrDefault = pendingShrink.GetValueOrDefault();
				_pendingShrink = null;
				Plugin.Log.LogDebug((object)("[SC] applying shrink that arrived while " + _displayName + " was switched off"));
				ApplyRemoteShrink(valueOrDefault.Item1, valueOrDefault.Item2, valueOrDefault.Item3);
				return;
			}
			ScaleOptions? respawnSession = _respawnSession;
			if (respawnSession.HasValue)
			{
				ScaleOptions valueOrDefault2 = respawnSession.GetValueOrDefault();
				_respawnSession = null;
				if (!IsScaled && SemiFunc.IsMasterClientOrSingleplayer())
				{
					Plugin.Log.LogDebug((object)$"[SC] RESPAWN re-scaling {_displayName} to x{valueOrDefault2.Factor}");
					DispatchShrink(valueOrDefault2);
				}
			}
		}

		private void OnDestroy()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (IsScaled)
			{
				_t.localScale = OriginalScale;
				PlayerHandler.State obj = HandlerState as PlayerHandler.State;
				if (obj != null)
				{
					PlayerVoiceChat voiceChat = obj.PlayerAvatar.voiceChat;
					if (voiceChat != null)
					{
						voiceChat.OverridePitchCancel();
					}
				}
				Handler?.OnDestroy(this);
			}
			Scaled.Remove(this);
		}

		private void EnsureNetworkPV()
		{
			if (!((Object)(object)_networkPV != (Object)null))
			{
				_networkPV = ((MonoBehaviourPun)this).photonView ?? ((Component)this).GetComponentInParent<PhotonView>();
				PhotonView? networkPV = _networkPV;
				if (networkPV != null)
				{
					networkPV.RefreshRpcMonoBehaviourCache();
				}
			}
		}

		internal void EnsureReady()
		{
			EnsureInitialized();
		}

		public void DispatchShrink(ScaleOptions options)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_047e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0483: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Unknown result type (might be due to invalid IL or missing references)
			//IL_0489: Unknown result type (might be due to invalid IL or missing references)
			//IL_049f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: 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_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_050f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0515: Unknown result type (might be due to invalid IL or missing references)
			//IL_051a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0526: Unknown result type (might be due to invalid IL or missing references)
			//IL_052c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0531: Unknown result type (might be due to invalid IL or missing references)
			//IL_0396: Unknown result type (might be due to invalid IL or missing references)
			//IL_0592: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_065c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0666: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			EnsureInitialized();
			if (!ScaleManager.AllowDeadHeads && (Object)(object)((Component)this).GetComponent<PlayerDeathHead>() != (Object)null)
			{
				Plugin.Log.LogDebug((object)("[SC] DispatchShrink ignored: " + _displayName + " is a dead Semibot head and ScaleManager.AllowDeadHeads is off"));
				return;
			}
			Plugin.Log.LogDebug((object)$"[SC] DispatchShrink ENTER  {_displayName}  instanceID={((Object)this).GetInstanceID()}  IsScaled={IsScaled}  currentScale={_t.localScale}  GO={((Object)((Component)this).gameObject).name}");
			if (!IsScaled || !Mathf.Approximately(options.Factor, _options.Factor))
			{
				if (options.Factor <= 0f)
				{
					options.Factor = ScaleOptions.Default.Factor;
				}
				if (options.Speed <= 0f)
				{
					options.Speed = ScaleOptions.Default.Speed;
				}
				RespawnRules.Verdict verdict = NativeRespawn.Decide(this);
				if (verdict == RespawnRules.Verdict.Now)
				{
					float fromFactor = (IsScaled ? _options.Factor : 1f);
					if (NativeRespawn.Swap(this, OriginalScale * options.Factor, options, options.Duration, fromFactor))
					{
						return;
					}
				}
				_nativeDeferred = verdict == RespawnRules.Verdict.WhenFree;
			}
			Stopwatch swApply = Stopwatch.StartNew();
			if (IsScaled)
			{
				if (Mathf.Approximately(options.Factor, _options.Factor))
				{
					DispatchExpand();
					if (_invertedActive)
					{
						_bonkImmuneTimer = _options.BonkImmuneDuration;
					}
					return;
				}
				Plugin.Log.LogDebug((object)$"[SC] RESCALE {_displayName}  {_options.Factor} → {options.Factor}");
				_options = options;
				_shrinkTimer = _options.Duration;
				if (_shrinkTimer < 0f)
				{
					_shrinkTimer = 0f;
				}
				float factor = _options.Factor;
				Vector3 val = OriginalScale * factor;
				_bonkImmuneTimer = _options.BonkImmuneDuration;
				_currentAnimSpeed = _options.Speed;
				ApplyScale(val);
				if ((Object)(object)_roomVolumeCheck != (Object)null)
				{
					_roomVolumeCheck.currentSize = _originalRoomVolumeSize * factor;
					_roomVolumeCheck.CheckPosition = _originalCheckPosition * factor;
				}
				if ((Object)(object)_rb != (Object)null && !_isItem && !_options.PreserveMass)
				{
					_rb.mass = Mathf.Clamp(_originalMass * factor, 0.5f, _options.MassCap);
				}
				ScalePgoMassOriginal(factor);
				SetForceGrabPoint(factor >= 1f);
				if (!_options.SuppressVoicePitch)
				{
					EnemyParent componentInParent = ((Component)this).GetComponentInParent<EnemyParent>();
					_audioPitch.ApplyPitch((Component)(object)(((Object)(object)componentInParent != (Object)null) ? ((ScaleController)(object)componentInParent) : this), factor, _options.AudioPresence);
				}
				ItemHandler.OnRestoreFields(_scaledItemFields);
				_scaledItemFields = ItemHandler.OnShrinkFields(this, factor);
				if (Handler is PlayerHandler)
				{
					Handler.OnScale(this);
				}
				if ((Object)(object)_networkPV != (Object)null && PhotonNetwork.InRoom)
				{
					_networkPV.RPC("RPC_Shrink", (RpcTarget)1, new object[3]
					{
						val,
						PackOpts(),
						PackBools()
					});
				}
				WarnIfSlow("rescale");
				return;
			}
			if (options.Factor <= 0f)
			{
				options.Factor = ScaleOptions.Default.Factor;
			}
			if (options.Speed <= 0f)
			{
				options.Speed = ScaleOptions.Default.Speed;
			}
			_options = options;
			_invertedActive = _options.InvertedMode;
			IsScaled = true;
			_shrinkTimer = _options.Duration;
			if (_shrinkTimer < 0f)
			{
				_shrinkTimer = 0f;
			}
			_currentAnimSpeed = _options.Speed;
			Scaled.Add(this);
			float factor2 = _options.Factor;
			Vector3 val2 = OriginalScale * factor2;
			Vector3 val3 = OriginalScale - val2;
			float magnitude = ((Vector3)(ref val3)).magnitude;
			float speed = _options.Speed;
			val3 = OriginalScale;
			float num = speed * ((Vector3)(ref val3)).magnitude;
			float num2 = ((num > 0f) ? (magnitude / num * 1.1f) : 0.75f);
			_bonkImmuneTimer = Mathf.Max(num2, _options.BonkImmuneDuration);
			ApplyScale(val2);
			if (factor2 < 1f)
			{
				SetForceGrabPoint(active: false);
			}
			if ((Object)(object)_roomVolumeCheck != (Object)null)
			{
				_roomVolumeCheck.currentSize = _originalRoomVolumeSize * factor2;
				_roomVolumeCheck.CheckPosition = _originalCheckPosition * factor2;
			}
			if ((Object)(object)_networkPV != (Object)null && PhotonNetwork.InRoom)
			{
				Plugin.Log.LogDebug((object)$"[SC] RPC_Shrink SEND  {_displayName}  viewID={_networkPV.ViewID}  isMine={_networkPV.IsMine}  target={val2}");
				_networkPV.RPC("RPC_Shrink", (RpcTarget)1, new object[3]
				{
					val2,
					PackOpts(),
					PackBools()
				});
			}
			else
			{
				Plugin.Log.LogDebug((object)string.Format("[SC] RPC_Shrink SKIP  {0}  networkPV={1}  inRoom={2}", _displayName, ((Object)(object)_networkPV == (Object)null) ? "null" : "set", PhotonNetwork.InRoom));
			}
			PlayImpactEffect();
			Plugin.Log.LogDebug((object)("[SC] SHRINK " + _displayName + $"  factor={_options.Factor}" + $"  scale {OriginalScale} → {val2}" + $"  animTime={magnitude / ((num > 0f) ? num : 1f):F2}s" + $"  bonkImmune={_bonkImmuneTimer:F2}s" + "  shrinkDuration=" + ((_shrinkTimer > 0f) ? (_shrinkTimer.ToString("F0") + "s") : "infinite")));
			if ((Object)(object)_rb != (Object)null)
			{
				float num3 = _originalMass * factor2;
				if (!_isItem && !_options.PreserveMass)
				{
					_rb.mass = Mathf.Clamp(num3, 0.5f, _options.MassCap);
				}
				bool flag = !_isItem && !_options.PreserveMass && num3 < 0.5f;
				if (Plugin.DiagMass)
				{
					Plugin.Log.LogDebug((object)("[SC-DIAG][HOST] SHRINK_APPLY  " + _displayName + "  " + $"mass {_originalMass:F3} → {_rb.mass:F3}  wantRaw={num3:F3}  cap={_options.MassCap:F2}" + (flag ? "  *FLOOR_HIT*" : "") + (_isItem ? "  (item, mass untouched)" : "") + (_options.PreserveMass ? "  (PreserveMass, mass untouched)" : "") + (((Object)(object)_physGrabObject != (Object)null) ? $"  pgo.massOrig={_physGrabObject.massOriginal:F3}  pgo.timerAlter={_physGrabObject.timerAlterMass:F2}" : "")));
				}
			}
			ScalePgoMassOriginal(factor2);
			Handler?.OnScale(this);
			if (factor2 < 1f && (Object)(object)_physGrabObject != (Object)null && Handler is ValuableHandler)
			{
				_physGrabObject.OverrideIndestructible(0.5f);
			}
			if (!_options.SuppressVoicePitch)
			{
				EnemyParent componentInParent2 = ((Component)this).GetComponentInParent<EnemyParent>();
				_audioPitch.ApplyPitch((Component)(object)(((Object)(object)componentInParent2 != (Object)null) ? ((ScaleController)(object)componentInParent2) : this), _options.Factor, _options.AudioPresence);
			}
			_scaledItemFields = ItemHandler.OnShrinkFields(this, _options.Factor);
			ScaleMapIcon(factor2);
			WarnIfSlow("fresh");
			void WarnIfSlow(string path)
			{
				swApply.Stop();
				if (swApply.ElapsedMilliseconds >= 10)
				{
					Plugin.Log.LogWarning((object)$"[SC] slow scale apply ({path}): {swApply.ElapsedMilliseconds}ms on {_displayName}");
				}
			}
		}

		public void DispatchExpand()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !IsScaled)
			{
				return;
			}
			EnsureInitialized();
			if (!TryNativeRestore())
			{
				IsScaled = false;
				_respawnSession = null;
				Scaled.Remove(this);
				float num = ((OriginalScale.x > 0f) ? (_t.localScale.x / OriginalScale.x) : 0f);
				Plugin.Log.LogDebug((object)("[SC] EXPAND (timer/shot) " + _displayName + $"  currentSize={num * 100f:F0}%" + string.Format("  mass {0} → {1:F3}", ((Object)(object)_rb != (Object)null) ? _rb.mass.ToString("F3") : "N/A", _originalMass)));
				_currentAnimSpeed = ResolveExpandSpeed();
				ApplyScale(OriginalScale);
				SetForceGrabPoint(active: true);
				if ((Object)(object)_networkPV != (Object)null && PhotonNetwork.InRoom)
				{
					_networkPV.RPC("RPC_Expand", (RpcTarget)1, Array.Empty<object>());
				}
				PlayImpactEffect();
				PlayCameraShake();
				if ((Object)(object)_rb != (Object)null)
				{
					_rb.mass = _originalMass;
				}
				RestorePgoMassOriginal();
				if ((Object)(object)_roomVolumeCheck != (Object)null)
				{
					_roomVolumeCheck.currentSize = _originalRoomVolumeSize;
					_roomVolumeCheck.CheckPosition = _originalCheckPosition;
				}
				Handler?.OnRestore(this, isBonk: false);
				if (!_options.SuppressVoicePitch)
				{
					_audioPitch.RestorePitch();
				}
				ItemHandler.OnRestoreFields(_scaledItemFields);
				_scaledItemFields = null;
				ScaleMapIcon(1f);
			}
		}

		public void DispatchExpandNow()
		{
			//IL_0086: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !IsScaled || _options.IgnoreBonkExpand)
			{
				return;
			}
			if (_bonkImmuneTimer > 0f)
			{
				Plugin.Log.LogDebug((object)$"[SC] BONK BLOCKED {_displayName}  immune={_bonkImmuneTimer:F2}s remaining");
			}
			else if (!TryNativeRestore())
			{
				IsScaled = false;
				_respawnSession = null;
				_shrinkTimer = 0f;
				Scaled.Remove(this);
				float num = ((OriginalScale.x > 0f) ? (_t.localScale.x / OriginalScale.x) : 0f);
				Plugin.Log.LogDebug((object)("[SC] EXPAND (bonk/instant) " + _displayName + $"  currentSize={num * 100f:F0}%" + string.Format("  mass {0} → {1:F3}", ((Object)(object)_rb != (Object)null) ? _rb.mass.ToString("F3") : "N/A", _originalMass)));
				_currentAnimSpeed = ResolveExpandSpeed();
				ApplyScale(OriginalScale);
				SetForceGrabPoint(active: true);
				if ((Object)(object)_networkPV != (Object)null && PhotonNetwork.InRoom)
				{
					_networkPV.RPC("RPC_Expand", (RpcTarget)1, Array.Empty<object>());
				}
				PlayImpactEffect();
				PlayCameraShake();
				if ((Object)(object)_rb != (Object)null)
				{
					_rb.mass = _originalMass;
				}
				RestorePgoMassOriginal();
				if ((Object)(object)_roomVolumeCheck != (Object)null)
				{
					_roomVolumeCheck.currentSize = _originalRoomVolumeSize;
					_roomVolumeCheck.CheckPosition = _originalCheckPosition;
				}
				Handler?.OnRestore(this, isBonk: true);
				if (!_options.SuppressVoicePitch)
				{
					_audioPitch.RestorePitch();
				}
				ItemHandler.OnRestoreFields(_scaledItemFields);
				_scaledItemFields = null;
				ScaleMapIcon(1f);
			}
		}

		private bool TryNativeRestore()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			RespawnRules.Verdict verdict = NativeRespawn.Decide(this);
			if (verdict == RespawnRules.Verdict.Now)
			{
				ScaleOptions options = _options;
				options.Factor = 1f;
				if (NativeRespawn.Swap(this, OriginalScale, options, 0f, _options.Factor))
				{
					return true;
				}
			}
			_nativeDeferred = verdict == RespawnRules.Verdict.WhenFree;
			return false;
		}

		private void ApplyScale(Vector3 target)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			_target = target;
			if (!PhysicallyCapped)
			{
				_animScale = _t.localScale;
			}
			_transitioning = true;
			if (Handler is PlayerHandler)
			{
				if (_playerBounceAnim != null)
				{
					((MonoBehaviour)this).StopCoroutine(_playerBounceAnim);
				}
				_playerBounceAnim = ((MonoBehaviour)this).StartCoroutine(PlayerBounceAnim(_t.localScale, target));
			}
		}

		private void PlayImpactEffect()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!_options.SuppressImpactFlash)
			{
				AssetManager instance = AssetManager.instance;
				if (instance != null)
				{
					instance.PhysImpactEffect(_t.position);
				}
			}
		}

		private void PlayCameraShake()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!_options.SuppressCameraShake)
			{
				SemiFunc.CameraShakeImpactDistance(_t.position, 2f, 0.1f, 1f, 8f);
			}
		}

		private float ResolveExpandSpeed()
		{
			if (!(_options.RestoreSpeed > 0f))
			{
				return _options.Speed;
			}
			return _options.RestoreSpeed;
		}

		private void ScaleMapIcon(float factor)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			MapCustom val = ((Component)this).GetComponent<MapCustom>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)this).GetComponentInParent<MapCustom>();
			}
			if ((Object)(object)val?.mapCustomEntity != (Object)null)
			{
				((Component)val.mapCustomEntity).transform.localScale = Vector3.one * Mathf.Max(factor, 0.3f);
			}
		}

		private void SetForceGrabPoint(bool active)
		{
			if ((Object)(object)_physGrabObject != (Object)null && (Object)(object)_physGrabObject.forceGrabPoint != (Object)null)
			{
				((Component)_physGrabObject.forceGrabPoint).gameObject.SetActive(active);
			}
		}

		private static float BackOutEase(float t)
		{
			return 1f + 2.70158f * Mathf.Pow(t - 1f, 3f) + 1.70158f * Mathf.Pow(t - 1f, 2f);
		}

		private IEnumerator PlayerBounceAnim(Vector3 from, Vector3 to)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			float duration = 0.4f;
			float elapsed = 0f;
			while (elapsed < duration)
			{
				elapsed += Time.deltaTime;
				float num = BackOutEase(Mathf.Clamp01(elapsed / duration));
				_t.localScale = Vector3.LerpUnclamped(from, to, num);
				yield return null;
			}
			_t.localScale = to;
			_transitioning = false;
			_playerBounceAnim = null;
		}

		private IEnumerator ChallengeModeDeferred()
		{
			while ((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
			{
				yield return null;
			}
			if (SemiFunc.IsMultiplayer())
			{
				PlayerHandler.State playerState = HandlerState as PlayerHandler.State;
				while ((Object)(object)playerState?.PlayerAvatar.voiceChat == (Object)null)
				{
					yield return null;
				}
			}
			if (!IsScaled && SemiFunc.IsMasterClientOrSingleplayer())
			{
				ScaleOptions options = ScaleOptions.Default;
				options.InvertedMode = true;
				options.Duration = 0f;
				DispatchShrink(options);
			}
		}

		private IEnumerator LobbyPitchDeferred()
		{
			for (int i = 0; i < 10; i++)
			{
				yield return null;
			}
			PlayerVoiceChat[] array = Object.FindObjectsOfType<PlayerVoiceChat>();
			foreach (PlayerVoiceChat val in array)
			{
				if (ChallengeMode)
				{
					val.OverridePitch(1.3f, 0.2f, 0.5f, 9999f, 0f, 0f);
				}
				else
				{
					val.OverridePitchCancel();
				}
			}
		}

		private float[] PackOpts()
		{
			return ScaleOptionsCodec.PackFloats(in _options);
		}

		private bool[] PackBools()
		{
			return ScaleOptionsCodec.PackBools(in _options);
		}

		[PunRPC]
		private void RPC_Shrink(Vector3 target, float[] opts, bool[] flags, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.InRoom || (info.Sender != null && info.Sender == PhotonNetwork.MasterClient))
			{
				if (!_inited)
				{
					_pendingShrink = (target, opts, flags);
				}
				else
				{
					ApplyRemoteShrink(target, opts, flags);
				}
			}
		}

		private void ApplyRemoteShrink(Vector3 target, float[] opts, bool[] flags)
		{
			//IL_001b: 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)
			Plugin.Log.LogDebug((object)string.Format("[SC] RPC_Shrink RECV  {0}  target={1}  factor={2}  handler={3}", _displayName, target, (opts.Length != 0) ? opts[0] : 0f, Handler?.GetType().Name ?? "null"));
			_options = ScaleOptionsCodec.Unpack(opts, flags, _options);
			_invertedActive = _options.InvertedMode;
			_currentAnimSpeed = _options.Speed;
			ApplySessionLocal(target);
		}

		private void ApplySessionLocal(Vector3 target)
		{
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: 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_01bf: Unknown result type (might be due to invalid IL or missing references)
			float factor = _options.Factor;
			IsScaled = true;
			Scaled.Add(this);
			if ((Object)(object)_rb != (Object)null && !_isItem && !_options.PreserveMass)
			{
				_rb.mass = Mathf.Clamp(_originalMass * factor, 0.5f, _options.MassCap);
			}
			ScalePgoMassOriginal(factor);
			if ((Object)(object)_rb != (Object)null && Handler is ValuableHandler)
			{
				float num = _originalMass * factor;
				bool flag = !_isItem && !_options.PreserveMass && num < 0.5f;
				if (Plugin.DiagMass)
				{
					Plugin.Log.LogDebug((object)("[SC-DIAG][CLIENT] RPC_SHRINK_APPLY  " + _displayName + "  " + $"mass {_originalMass:F3} → {_rb.mass:F3}  wantRaw={num:F3}  cap={_options.MassCap:F2}" + (flag ? "  *FLOOR_HIT*" : "") + (((Object)(object)_physGrabObject != (Object)null) ? $"  pgo.massOrig={_physGrabObject.massOriginal:F3}" : "")));
				}
			}
			if ((Object)(object)_roomVolumeCheck != (Object)null)
			{
				_roomVolumeCheck.currentSize = _originalRoomVolumeSize * factor;
				_roomVolumeCheck.CheckPosition = _originalCheckPosition * factor;
			}
			ApplyScale(target);
			if (factor < 1f)
			{
				SetForceGrabPoint(active: false);
			}
			PlayImpactEffect();
			if (!_options.SuppressVoicePitch)
			{
				EnemyParent componentInParent = ((Component)this).GetComponentInParent<EnemyParent>();
				_audioPitch.ApplyPitch((Component)(object)(((Object)(object)componentInParent != (Object)null) ? ((ScaleController)(object)componentInParent) : this), factor, _options.AudioPresence);
			}
			_scaledItemFields = ItemHandler.OnShrinkFields(this, factor);
			Handler?.OnScale(this);
			if (factor < 1f && (Object)(object)_physGrabObject != (Object)null && Handler is ValuableHandler)
			{
				_physGrabObject.OverrideIndestructible(0.5f);
			}
			ScaleMapIcon(factor);
		}

		[PunRPC]
		private void RPC_Expand(PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.InRoom && (info.Sender == null || info.Sender != PhotonNetwork.MasterClient))
			{
				return;
			}
			if (!_inited)
			{
				_pendingShrink = null;
				return;
			}
			IsScaled = false;
			Scaled.Remove(this);
			if ((Object)(object)_rb != (Object)null)
			{
				_rb.mass = _originalMass;
			}
			RestorePgoMassOriginal();
			if ((Object)(object)_roomVolumeCheck != (Object)null)
			{
				_roomVolumeCheck.currentSize = _originalRoomVolumeSize;
				_roomVolumeCheck.CheckPosition = _originalCheckPosition;
			}
			_currentAnimSpeed = ResolveExpandSpeed();
			ApplyScale(OriginalScale);
			SetForceGrabPoint(active: true);
			PlayImpactEffect();
			PlayCameraShake();
			if (!_options.SuppressVoicePitch)
			{
				_audioPitch.RestorePitch();
			}
			ItemHandler.OnRestoreFields(_scaledItemFields);
			_scaledItemFields = null;
			Handler?.OnRestore(this, isBonk: false);
			ScaleMapIcon(1f);
		}

		[PunRPC]
		private void RPC_PlayerPitchCancel(PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.InRoom && (info.Sender == null || info.Sender != PhotonNetwork.MasterClient))
			{
				return;
			}
			PlayerHandler.State state = HandlerState as PlayerHandler.State;
			if (state != null)
			{
				PlayerVoiceChat voiceChat = state.PlayerAvatar.voiceChat;
				if (voiceChat != null)
				{
					voiceChat.OverridePitchCancel();
				}
			}
			if (state != null)
			{
				PlayerHandler.RestoreVoicePresence(state);
			}
		}

		private bool SenderOwnsView(PhotonMessageInfo info)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.InRoom)
			{
				return true;
			}
			if (info.Sender != null && (Object)(object)_networkPV != (Object)null)
			{
				return info.Sender == _networkPV.Owner;
			}
			return false;
		}

		public void RequestBonkExpand()
		{
			if (IsScaled)
			{
				if (SemiFunc.IsMasterClientOrSingleplayer())
				{
					DispatchExpandNow();
				}
				else if ((Object)(object)_networkPV != (Object)null && _networkPV.IsMine && PhotonNetwork.InRoom)
				{
					_networkPV.RPC("RPC_RequestExpand", (RpcTarget)2, new object[1] { true });
				}
			}
		}

		public void RequestInvertedReshrink()
		{
			if (!IsScaled && _invertedActive && !(_bonkImmuneTimer > 0f))
			{
				if (SemiFunc.IsMasterClientOrSingleplayer())
				{
					DispatchShrink(_options);
				}
				else if ((Object)(object)_networkPV != (Object)null && _networkPV.IsMine && PhotonNetwork.InRoom)
				{
					_networkPV.RPC("RPC_RequestInvertedReshrink", (RpcTarget)2, Array.Empty<object>());
				}
			}
		}

		[PunRPC]
		private void RPC_RequestInvertedReshrink(PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer() && SenderOwnsView(info) && !IsScaled && _invertedActive)
			{
				ScaleOptions options = ScaleOptions.Default;
				options.InvertedMode = true;
				options.Duration = 0f;
				DispatchShrink(options);
			}
		}

		public void RequestManualShrink()
		{
			if (IsScaled)
			{
				return;
			}
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				if (AllowManualScale)
				{
					DispatchShrink(ScaleOptions.Default);
				}
			}
			else if ((Object)(object)_networkPV != (Object)null && _networkPV.IsMine && PhotonNetwork.InRoom)
			{
				_networkPV.RPC("RPC_RequestShrink", (RpcTarget)2, Array.Empty<object>());
			}
		}

		[PunRPC]
		private void RPC_RequestShrink(PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer() && SenderOwnsView(info) && AllowManualScale && !IsScaled)
			{
				DispatchShrink(ScaleOptions.Default);
			}
		}

		public void RequestManualExpand()
		{
			if (!IsScaled)
			{
				return;
			}
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				if (AllowManualScale)
				{
					DispatchExpand();
				}
			}
			else if ((Object)(object)_networkPV != (Object)null && _networkPV.IsMine && PhotonNetwork.InRoom)
			{
				_networkPV.RPC("RPC_RequestExpand", (RpcTarget)2, new object[1] { false });
			}
		}

		[PunRPC]
		private void RPC_RequestExpand(bool checkImmunity, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer() && SenderOwnsView(info) && IsScaled)
			{
				if (checkImmunity)
				{
					DispatchExpandNow();
				}
				else if (AllowManualScale)
				{
					DispatchExpand();
				}
			}
		}

		public static void CleanupAll()
		{
			//IL_0091: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			foreach (ScaleController item in Scaled)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				item._audioPitch.RestorePitch();
				ItemHandler.OnRestoreFields(item._scaledItemFields);
				item._scaledItemFields = null;
				PlayerHandler.State obj = item.HandlerState as PlayerHandler.State;
				if (obj != null)
				{
					PlayerVoiceChat voiceChat = obj.PlayerAvatar.voiceChat;
					if (voiceChat != null)
					{
						voiceChat.OverridePitchCancel();
					}
				}
				item.Handler?.OnRestore(item, isBonk: false);
				item.IsScaled = false;
				item._invertedActive = false;
				item._transitioning = false;
				item._target = item.OriginalScale;
				item._animScale = item.OriginalScale;
				item._t.localScale = item.OriginalScale;
			}
			Scaled.Clear();
			ScaleManager.ClearRedirects();
		}

		public override void OnJoinedRoom()
		{
			PhotonView? networkPV = _networkPV;
			if (networkPV != null)
			{
				networkPV.RefreshRpcMonoBehaviourCache();
			}
		}

		internal void ResendTo(Player player)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			if (IsScaled && !((Object)(object)_networkPV == (Object)null) && !_native)
			{
				Plugin.Log.LogDebug((object)$"[SC] RPC_Shrink RESEND  {DisplayName}  viewID={_networkPV.ViewID}  to={player.NickName}  target={_target}");
				_networkPV.RPC("RPC_Shrink", player, new object[3]
				{
					_target,
					PackOpts(),
					PackBools()
				});
			}
		}

		public override void OnPlayerEnteredRoom(Player newPlayer)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && ChallengeMode && Handler is PlayerHandler)
			{
				((MonoBehaviour)this).StartCoroutine(LobbyPitchDeferred());
			}
		}
	}
	public static class ScaleManager
	{
		private static readonly RedirectMap<ScaleController> Redirects = new RedirectMap<ScaleController>();

		public static bool AllowDeadHeads { get; set; }

		public static bool NativeSync { get; set; } = false;

		public static bool NativeSyncWhileHeld { get; set; } = true;

		public static event Action<GameObject, GameObject, ScaleController>? ObjectRespawned;

		public static void Apply(GameObject target)
		{
			Apply(target, ScaleOptions.Default);
		}

		public static void Apply(GameObject target, ScaleOptions options)
		{
			ScaleController scaleController = Resolve(target, "Apply");
			if (!((Object)(object)scaleController == (Object)null) && !Locked(scaleController, "Apply") && Allowed(scaleController, options.AllowedTargets, "Apply"))
			{
				scaleController.DispatchShrink(options);
			}
		}

		public static bool ApplyIfNotScaled(GameObject target)
		{
			return ApplyIfNotScaled(target, ScaleOptions.Default);
		}

		public static bool ApplyIfNotScaled(GameObject target, ScaleOptions options)
		{
			ScaleController scaleController = Resolve(target, "ApplyIfNotScaled");
			if ((Object)(object)scaleController == (Object)null)
			{
				return false;
			}
			if (scaleController.IsScaled)
			{
				Plugin.Log.LogDebug((object)string.Format("[SC] {0} refused on {1}: already scaled at x{2}", "ApplyIfNotScaled", scaleController.DisplayName, scaleController.CurrentOptions.Factor));
				return false;
			}
			if (Locked(scaleController, "ApplyIfNotScaled"))
			{
				return false;
			}
			if (!Allowed(scaleController, options.AllowedTargets, "ApplyIfNotScaled"))
			{
				return false;
			}
			scaleController.DispatchShrink(options);
			return true;
		}

		public static void ForceApply(GameObject target, ScaleOptions options)
		{
			ScaleController scaleController = Resolve(target, "ForceApply");
			if (!((Object)(object)scaleController == (Object)null) && Allowed(scaleController, options.AllowedTargets, "ForceApply"))
			{
				scaleController.DispatchShrink(options);
			}
		}

		public static ScaleController? GetController(GameObject target)
		{
			if (target == null)
			{
				return null;
			}
			ScaleController scaleController = Redirects.Resolve(((Object)target).GetInstanceID());
			if ((Object)(object)scaleController != (Object)null)
			{
				return scaleController;
			}
			if ((Object)(object)target == (Object)null)
			{
				return null;
			}
			ScaleController scaleController2 = target.GetComponent<ScaleController>();
			if (scaleController2 == null)
			{
				PlayerShrinkLink component = target.GetComponent<PlayerShrinkLink>();
				if (component == null)
				{
					return null;
				}
				scaleController2 = component.Controller;
			}
			return scaleController2;
		}

		internal static void NoteRespawn(GameObject old, GameObject fresh, ScaleController controller)
		{
			Redirects.Add(((Object)old).GetInstanceID(), ((Object)fresh).GetInstanceID(), controller);
			Action<GameObject, GameObject, ScaleController> objectRespawned = ScaleManager.ObjectRespawned;
			if (objectRespawned == null)
			{
				return;
			}
			Delegate[] invocationList = objectRespawned.GetInvocationList();
			foreach (Delegate obj in invocationList)
			{
				try
				{
					((Action<GameObject, GameObject, ScaleController>)obj)(old, fresh, controller);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)$"[SC] {obj.Method.DeclaringType?.FullName}.{obj.Method.Name} threw on ObjectRespawned for {((Object)old).name}: {ex}");
				}
			}
		}

		internal static void ClearRedirects()
		{
			Redirects.Clear();
		}

		public static void Restore(GameObject target)
		{
			ScaleController controller = GetController(target);
			if (!((Object)(object)controller == (Object)null) && !IsLockedFromExternal(controller))
			{
				controller.DispatchExpand();
			}
		}

		public static void RestoreImmediate(GameObject target)
		{
			ScaleController controller = GetController(target);
			if (!((Object)(object)controller == (Object)null) && !IsLockedFromExternal(controller))
			{
				controller.DispatchExpandNow();
			}
		}

		public static void ForceRestore(GameObject target)
		{
			ScaleController controller = GetController(target);
			if (!((Object)(object)controller == (Object)null))
			{
				controller.DispatchExpand();
			}
		}

		public static bool UpdateOptions(GameObject target, ScaleOptions options)
		{
			ScaleController controller = GetController(target);
			if ((Object)(object)controller == (Object)null || !controller.IsScaled)
			{
				return false;
			}
			if (IsLockedFromExternal(controller))
			{
				return false;
			}
			controller._options = options;
			return true;
		}

		public static bool ForceUpdateOptions(GameObject target, ScaleOptions options)
		{
			ScaleController controller = GetController(target);
			if ((Object)(object)controller == (Object)null || !controller.IsScaled)
			{
				return false;
			}
			controller._options = options;
			return true;
		}

		public static bool IsScaled(GameObject target)
		{
			ScaleController controller = GetController(target);
			if ((Object)(object)controller != (Object)null)
			{
				return controller.IsScaled;
			}
			return false;
		}

		public static void CleanupAll()
		{
			ScaleController.CleanupAll();
		}

		private static ScaleController? Resolve(GameObject target, string call)
		{
			ScaleController controller = GetController(target);
			if ((Object)(object)controller == (Object)null)
			{
				Plugin.Log.LogDebug((object)("[SC] " + call + " refused on " + NameFor(target) + ": no ScaleController on this object"));
				return null;
			}
			controller.EnsureReady();
			return controller;
		}

		private static string NameFor(GameObject target)
		{
			if (target == null)
			{
				return "nothing";
			}
			if (!((Object)(object)target == (Object)null))
			{
				return ((Object)target).name;
			}
			return "an object that