Decompiled source of BalloonMochi v1.0.1

plugins/com.github.MuttFromMars.BalloonMochi.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PEAKLib.Core;
using Photon.Pun;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.MuttFromMars.BalloonMochi")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("com.github.MuttFromMars.BalloonMochi")]
[assembly: AssemblyTitle("BalloonMochi")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal sealed class FreezeUntilFirstPickup : MonoBehaviour
{
	private bool _everPickedUp;

	private Rigidbody[] _rbs = Array.Empty<Rigidbody>();

	private Transform? _spawnParent;

	private void Awake()
	{
		_spawnParent = ((Component)this).transform.parent;
		Cache();
		Freeze(on: true);
	}

	private void Start()
	{
		EvaluateParent();
	}

	private void OnTransformParentChanged()
	{
		EvaluateParent();
	}

	private void EvaluateParent()
	{
		if (!_everPickedUp && (Object)(object)((Component)this).transform.parent != (Object)(object)_spawnParent)
		{
			_everPickedUp = true;
			Freeze(on: false);
			Object.Destroy((Object)(object)this);
		}
	}

	private void Freeze(bool on)
	{
		Rigidbody[] rbs = _rbs;
		foreach (Rigidbody val in rbs)
		{
			if (!((Object)(object)val == (Object)null))
			{
				val.isKinematic = on;
				val.detectCollisions = true;
				if (on)
				{
					val.Sleep();
				}
			}
		}
	}

	private void Cache()
	{
		_rbs = ((Component)this).GetComponentsInChildren<Rigidbody>(true);
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BalloonMochi
{
	[BepInPlugin("com.github.MuttFromMars.BalloonMochi", "Balloon Mochi", "1.0.1")]
	public class PrefabRedirector : BaseUnityPlugin
	{
		private sealed class BoxUShort
		{
			public ushort V;

			public BoxUShort(ushort v)
			{
				V = v;
			}
		}

		private sealed class RedirectingPool : IPunPrefabPool
		{
			private readonly IPunPrefabPool _inner;

			public RedirectingPool(IPunPrefabPool inner)
			{
				_inner = inner;
			}

			public GameObject Instantiate(string prefabId, Vector3 pos, Quaternion rot)
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: 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)
				TryMap(ref prefabId);
				GameObject val = ((_inner != null) ? _inner.Instantiate(prefabId, pos, rot) : null);
				if ((Object)(object)val == (Object)null)
				{
					GameObject val2 = Resources.Load<GameObject>(prefabId) ?? Resources.Load<GameObject>(prefabId + ".prefab");
					if ((Object)(object)val2 != (Object)null)
					{
						val = Object.Instantiate<GameObject>(val2, pos, rot);
					}
				}
				if ((Object)(object)val != (Object)null && prefabId.Equals("balloonmochi", StringComparison.OrdinalIgnoreCase))
				{
					try
					{
						val.AddComponent<FreezeUntilFirstPickup>();
					}
					catch
					{
					}
				}
				return val;
			}

			public void Destroy(GameObject go)
			{
				if (_inner != null)
				{
					_inner.Destroy(go);
				}
				else if ((Object)(object)go != (Object)null)
				{
					Object.Destroy((Object)(object)go);
				}
			}
		}

		[CompilerGenerated]
		private sealed class <EnsureWrappedPool>d__23 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			private int <i>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <EnsureWrappedPool>d__23(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<i>5__2 = 0;
					break;
				case 1:
					<>1__state = -1;
					<i>5__2++;
					break;
				}
				if (<i>5__2 < 120)
				{
					IPunPrefabPool prefabPool = PhotonNetwork.PrefabPool;
					if (prefabPool is RedirectingPool)
					{
						return false;
					}
					if (prefabPool != null)
					{
						PhotonNetwork.PrefabPool = (IPunPrefabPool)(object)new RedirectingPool(prefabPool);
						return false;
					}
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private const ushort TARGET_ITEM_ID = 13;

		private const string DISPLAY_NAME = "MOCHI";

		private const string BUNDLE_FILE = "balloonmochi";

		private const string PREFAB_NAME = "BalloonMochi.prefab";

		private const string MAT_NAME = "M_BalloonMochi.mat";

		private const string ICON_NAME = "balloonmochi_icon";

		private const string SHADER_NAME = "W/Character";

		private const string MATCH_ICON_NAME = "BingBong";

		private static readonly Dictionary<string, string> s_NameRedirectMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { { "bingbong", "balloonmochi" } };

		private AssetBundle? _bundle;

		private Material? _mat;

		private Harmony _harmony;

		internal static ManualLogSource? s_Log;

		private UnityAction<Scene, Scene>? _sceneChangedHandler;

		private static Texture2D? s_IconTex;

		private static int? s_PrefabCarryWeight;

		private static FieldInfo? s_Field_carryWeight;

		private static readonly ConditionalWeakTable<ItemUIData, BoxUShort> s_UIToId = new ConditionalWeakTable<ItemUIData, BoxUShort>();

		private void Awake()
		{
			s_Log = ((BaseUnityPlugin)this).Logger;
			TryLoadBundleAndRegister();
			((MonoBehaviour)this).StartCoroutine(EnsureWrappedPool());
			_sceneChangedHandler = delegate
			{
				((MonoBehaviour)this).StartCoroutine(EnsureWrappedPool());
			};
			SceneManager.activeSceneChanged += _sceneChangedHandler;
			Patch();
		}

		private void OnDestroy()
		{
			if (_sceneChangedHandler != null)
			{
				SceneManager.activeSceneChanged -= _sceneChangedHandler;
			}
			s_Log = null;
		}

		private void TryLoadBundleAndRegister()
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
				string text = Path.Combine(directoryName, "balloonmochi");
				_bundle = (File.Exists(text) ? AssetBundle.LoadFromFile(text) : null);
				GameObject val = (((Object)(object)_bundle != (Object)null) ? _bundle.LoadAsset<GameObject>("BalloonMochi.prefab") : null);
				if ((Object)(object)val != (Object)null)
				{
					RebindShaders(val);
					Material val2 = (((Object)(object)_bundle != (Object)null) ? _bundle.LoadAsset<Material>("M_BalloonMochi.mat") : null);
					Shader val3 = Shader.Find("W/Character");
					object obj = this;
					obj = (object)((!((Object)(object)val3 != (Object)null)) ? ((Material)null) : new Material(val3));
					((PrefabRedirector)obj)._mat = (Material?)obj;
					if ((Object)(object)_mat != (Object)null && (Object)(object)val2 != (Object)null)
					{
						_mat.CopyPropertiesFromMaterial(val2);
					}
					if ((Object)(object)_mat != (Object)null)
					{
						ApplyMaterial(val, _mat, "HeadTorso", "TongueMouth");
					}
					try
					{
						Item component = val.GetComponent<Item>();
						if ((Object)(object)component != (Object)null)
						{
							if ((object)s_Field_carryWeight == null)
							{
								s_Field_carryWeight = AccessTools.Field(typeof(Item), "carryWeight");
							}
							if (s_Field_carryWeight != null && s_Field_carryWeight.FieldType == typeof(int))
							{
								s_PrefabCarryWeight = (int)s_Field_carryWeight.GetValue(component);
								ManualLogSource? obj2 = s_Log;
								if (obj2 != null)
								{
									obj2.LogInfo((object)$"[BalloonMochi] prefab carryWeight = {s_PrefabCarryWeight}");
								}
							}
						}
					}
					catch (Exception arg)
					{
						ManualLogSource? obj3 = s_Log;
						if (obj3 != null)
						{
							obj3.LogWarning((object)$"[BalloonMochi] Failed to capture carryWeight: {arg}");
						}
					}
					NetworkPrefabManager.RegisterNetworkPrefab("balloonmochi", val);
				}
				if ((Object)(object)_bundle != (Object)null)
				{
					s_IconTex = _bundle.LoadAsset<Texture2D>("balloonmochi_icon");
					_bundle.Unload(false);
					_bundle = null;
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
			}
		}

		[IteratorStateMachine(typeof(<EnsureWrappedPool>d__23))]
		private IEnumerator EnsureWrappedPool()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <EnsureWrappedPool>d__23(0);
		}

		private static bool TryMap(ref string id)
		{
			if (string.IsNullOrEmpty(id))
			{
				return false;
			}
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(id);
			if (string.IsNullOrEmpty(fileNameWithoutExtension))
			{
				return false;
			}
			if (s_NameRedirectMap.TryGetValue(fileNameWithoutExtension, out string value))
			{
				id = value;
				return true;
			}
			return false;
		}

		private void Patch()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Expected O, but got Unknown
			_harmony = new Harmony("com.github.MuttFromMars.BalloonMochi");
			TryPostfix(typeof(Item), "GetName", "Postfix_Item_GetName");
			MethodInfo methodInfo = AccessTools.Property(typeof(Item), "CarryWeight")?.GetGetMethod();
			if (methodInfo != null)
			{
				try
				{
					_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(PrefabRedirector), "Postfix_Item_get_CarryWeight", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				catch (Exception arg)
				{
					ManualLogSource? obj = s_Log;
					if (obj != null)
					{
						obj.LogWarning((object)$"[BalloonMochi] Failed to patch Item.get_CarryWeight: {arg}");
					}
				}
			}
			TryPostfix(typeof(Item), "Awake", "Postfix_Item_Awake");
			Type typeFromHandle = typeof(ItemUIData);
			MethodInfo methodInfo2 = AccessTools.Method(typeFromHandle, "GetIcon", Type.EmptyTypes, (Type[])null);
			if (methodInfo2 != null)
			{
				try
				{
					_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(PrefabRedirector), "Postfix_UIData_GetIcon_Tex", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				catch (Exception arg2)
				{
					ManualLogSource? obj2 = s_Log;
					if (obj2 != null)
					{
						obj2.LogWarning((object)$"[BalloonMochi] Failed to patch ItemUIData.GetIcon: {arg2}");
					}
				}
			}
			Type type = AccessTools.TypeByName("ItemUI");
			MethodInfo methodInfo3 = ((type != null) ? AccessTools.Method(type, "GetIcon", Type.EmptyTypes, (Type[])null) : null);
			if (!(methodInfo3 != null))
			{
				return;
			}
			try
			{
				_harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(PrefabRedirector), "Postfix_UI_Fallback_GetIcon_Tex", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			catch (Exception arg3)
			{
				ManualLogSource? obj3 = s_Log;
				if (obj3 != null)
				{
					obj3.LogWarning((object)$"[BalloonMochi] Failed to patch ItemUI.GetIcon: {arg3}");
				}
			}
		}

		private void TryPostfix(Type t, string name, string postfix)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(t, name, Type.EmptyTypes, (Type[])null);
			if (methodInfo != null)
			{
				try
				{
					_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(PrefabRedirector), postfix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					return;
				}
				catch (Exception arg)
				{
					ManualLogSource? obj = s_Log;
					if (obj != null)
					{
						obj.LogWarning((object)$"[BalloonMochi] Failed to patch {t.FullName}.{name}(): {arg}");
					}
					return;
				}
			}
			ManualLogSource? obj2 = s_Log;
			if (obj2 != null)
			{
				obj2.LogWarning((object)("[BalloonMochi] Method not found: " + t.FullName + "." + name + "()"));
			}
		}

		private static void RebindShaders(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				try
				{
					Material[] sharedMaterials = val.sharedMaterials;
					foreach (Material val2 in sharedMaterials)
					{
						if (!((Object)(object)val2 == (Object)null))
						{
							Shader val3 = Shader.Find(((Object)(object)val2.shader != (Object)null) ? ((Object)val2.shader).name : "W/Character");
							if ((Object)(object)val3 != (Object)null && (Object)(object)val2.shader != (Object)(object)val3)
							{
								val2.shader = val3;
							}
						}
					}
				}
				catch
				{
				}
			}
		}

		private static void ApplyMaterial(GameObject root, Material mat, params string[] targets)
		{
			if ((Object)(object)root == (Object)null || (Object)(object)mat == (Object)null || targets == null || targets.Length == 0)
			{
				return;
			}
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				bool flag = false;
				string text = ((Object)((Component)val).gameObject).name ?? string.Empty;
				foreach (string value in targets)
				{
					if (text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					continue;
				}
				try
				{
					Material[] sharedMaterials = val.sharedMaterials;
					if (sharedMaterials == null || sharedMaterials.Length == 0)
					{
						val.sharedMaterial = mat;
						continue;
					}
					for (int k = 0; k < sharedMaterials.Length; k++)
					{
						sharedMaterials[k] = mat;
					}
					val.sharedMaterials = sharedMaterials;
				}
				catch
				{
				}
			}
		}

		public static void Postfix_Item_GetName(Item __instance, ref string __result)
		{
			try
			{
				if (__instance.itemID == 13)
				{
					__result = "MOCHI";
				}
			}
			catch
			{
			}
		}

		public static void Postfix_Item_get_CarryWeight(Item __instance, ref int __result)
		{
			try
			{
				if (s_PrefabCarryWeight.HasValue && __instance.itemID == 13)
				{
					int num = 0;
					try
					{
						num = Ascents.itemWeightModifier;
					}
					catch
					{
					}
					__result = s_PrefabCarryWeight.Value + num;
				}
			}
			catch
			{
			}
		}

		public static void Postfix_Item_Awake(Item __instance)
		{
			try
			{
				if (__instance?.UIData == null)
				{
					return;
				}
				try
				{
					s_UIToId.Remove(__instance.UIData);
				}
				catch
				{
				}
				try
				{
					s_UIToId.Add(__instance.UIData, new BoxUShort(__instance.itemID));
				}
				catch
				{
				}
			}
			catch
			{
			}
		}

		public static void Postfix_UIData_GetIcon_Tex(ItemUIData __instance, ref Texture2D __result)
		{
			try
			{
				if (!((Object)(object)s_IconTex == (Object)null))
				{
					if (s_UIToId.TryGetValue(__instance, out BoxUShort value) && value != null && value.V == 13)
					{
						__result = s_IconTex;
					}
					else if ((Object)(object)__result != (Object)null && TextureNameLooksLikeStock(((Object)__result).name))
					{
						__result = s_IconTex;
					}
				}
			}
			catch
			{
			}
		}

		private static bool TextureNameLooksLikeStock(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			if (!name.Equals("BingBong", StringComparison.OrdinalIgnoreCase))
			{
				return name.IndexOf("BingBong", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		public static void Postfix_UI_Fallback_GetIcon_Tex(object __instance, ref Texture2D __result)
		{
			try
			{
				if (!((Object)(object)s_IconTex == (Object)null) && (Object)(object)__result != (Object)null && TextureNameLooksLikeStock(((Object)__result).name))
				{
					__result = s_IconTex;
				}
			}
			catch
			{
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}