Decompiled source of FG Sticker Emotes v2.3.0

BepInEx\plugins\FGStickerEmotes\FGStickerEmotes.dll

Decompiled 4 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PEAKEmoteLib;
using UnityEngine;
using UnityEngine.Networking;

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

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FGStickerEmotes
{
	internal sealed class EmoteBubble : MonoBehaviour
	{
		private static readonly Dictionary<CharacterAnimations, EmoteBubble> Active = new Dictionary<CharacterAnimations, EmoteBubble>();

		private CharacterAnimations _owner;

		private Transform _target;

		private SpriteRenderer _renderer;

		private float _age;

		internal static void ShowFor(CharacterAnimations owner, Transform target, StickerAsset sticker)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			ClearFor(owner);
			GameObject val = new GameObject("FGStickerBubble");
			SpriteRenderer val2 = val.AddComponent<SpriteRenderer>();
			val2.sprite = sticker.Sprite;
			((Renderer)val2).sortingOrder = 1000;
			if (Plugin.EnableSounds && (Object)(object)sticker.AudioClip != (Object)null)
			{
				AudioSource obj = val.AddComponent<AudioSource>();
				obj.clip = sticker.AudioClip;
				obj.volume = Plugin.SoundVolume;
				obj.spatialBlend = Plugin.SoundSpatialBlend;
				obj.playOnAwake = false;
				obj.Play();
			}
			EmoteBubble emoteBubble = val.AddComponent<EmoteBubble>();
			emoteBubble._owner = owner;
			emoteBubble._target = target;
			emoteBubble._renderer = val2;
			emoteBubble.UpdateTransform();
			Active[owner] = emoteBubble;
		}

		internal static void ClearFor(CharacterAnimations owner)
		{
			if (Active.TryGetValue(owner, out EmoteBubble value) && (Object)(object)value != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)value).gameObject);
			}
			Active.Remove(owner);
		}

		internal static void ClearAll()
		{
			foreach (EmoteBubble value in Active.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
			}
			Active.Clear();
		}

		private void LateUpdate()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_owner == (Object)null || (Object)(object)_target == (Object)null)
			{
				RemoveAndDestroy();
				return;
			}
			_age += Time.deltaTime;
			float displaySeconds = Plugin.DisplaySeconds;
			if (_age >= displaySeconds)
			{
				RemoveAndDestroy();
				return;
			}
			UpdateTransform();
			float num = displaySeconds - _age;
			float num2 = ((num < 0.4f) ? Mathf.Clamp01(num / 0.4f) : 1f);
			_renderer.color = new Color(1f, 1f, 1f, num2);
		}

		private void UpdateTransform()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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)
			//IL_00ab: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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)
			float num = 1f;
			if (Plugin.AnimatePop && _age < 0.25f)
			{
				float num2 = Mathf.Clamp01(_age / 0.25f);
				num = Mathf.Sin(num2 * MathF.PI * 0.5f) * (1.15f - 0.15f * num2);
			}
			float num3 = Plugin.WorldScale * num;
			((Component)this).transform.localScale = Vector3.one * num3;
			Bounds bounds = _renderer.sprite.bounds;
			float num4 = ((Bounds)(ref bounds)).extents.y * num3;
			Camera main = Camera.main;
			Vector3 val = (((Object)(object)main != (Object)null) ? ((Component)main).transform.right : Vector3.right);
			((Component)this).transform.position = _target.position + Vector3.up * (Plugin.HeightOffset + num4) + val * Plugin.HorizontalOffset;
			if ((Object)(object)main != (Object)null)
			{
				((Component)this).transform.rotation = ((Component)main).transform.rotation;
			}
		}

		private void RemoveAndDestroy()
		{
			if ((Object)(object)_owner != (Object)null)
			{
				Active.Remove(_owner);
			}
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
	}
	[HarmonyPatch(typeof(CharacterAnimations), "RPCA_PlayRemove")]
	internal static class EmoteBubblePatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(600)]
		private static bool Prefix(CharacterAnimations __instance, string emoteName)
		{
			if (!Plugin.Stickers.TryGetValue(emoteName, out StickerAsset value))
			{
				return true;
			}
			EmoteBubble.ShowFor(__instance, ResolveHead(__instance), value);
			return false;
		}

		private static Transform ResolveHead(CharacterAnimations animations)
		{
			Transform val = FindCharacterRoot(animations);
			Animator componentInChildren = ((Component)val).GetComponentInChildren<Animator>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				if ((Object)(object)componentInChildren.avatar != (Object)null && componentInChildren.avatar.isHuman)
				{
					Transform boneTransform = componentInChildren.GetBoneTransform((HumanBodyBones)10);
					if ((Object)(object)boneTransform != (Object)null)
					{
						return boneTransform;
					}
				}
				Transform val2 = FindNamedHead(((Component)componentInChildren).transform);
				if ((Object)(object)val2 != (Object)null)
				{
					return val2;
				}
			}
			SkinnedMeshRenderer componentInChildren2 = ((Component)val).GetComponentInChildren<SkinnedMeshRenderer>(true);
			if ((Object)(object)componentInChildren2 != (Object)null && (Object)(object)componentInChildren2.rootBone != (Object)null)
			{
				Transform val3 = FindNamedHead(componentInChildren2.rootBone);
				if ((Object)(object)val3 != (Object)null)
				{
					return val3;
				}
			}
			return val;
		}

		private static Transform FindCharacterRoot(CharacterAnimations animations)
		{
			Component[] componentsInParent = ((Component)animations).GetComponentsInParent<Component>(true);
			foreach (Component val in componentsInParent)
			{
				if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == "Character")
				{
					return val.transform;
				}
			}
			return ((Component)animations).transform;
		}

		private static Transform FindNamedHead(Transform root)
		{
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (((Object)val).name.ToLowerInvariant().Contains("head"))
				{
					return val;
				}
			}
			return null;
		}
	}
	[BepInPlugin("MuTu.FGStickerEmotes", "FG Sticker Emotes", "2.3.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class BuiltInSticker
		{
			internal string Id { get; }

			internal string FileName { get; }

			internal string EnglishName { get; }

			internal string JapaneseName { get; }

			internal BuiltInSticker(string id, string fileName, string englishName, string japaneseName)
			{
				Id = id;
				FileName = fileName;
				EnglishName = englishName;
				JapaneseName = japaneseName;
			}
		}

		public const string Guid = "MuTu.FGStickerEmotes";

		public const string Name = "FG Sticker Emotes";

		public const string Version = "2.3.0";

		private static readonly BuiltInSticker[] BuiltIns = new BuiltInSticker[9]
		{
			new BuiltInSticker("MuTu_FingerHeart", "finger_heart.png", "Happy", "シアワセ"),
			new BuiltInSticker("MuTu_AwkwardSweat", "awkward_sweat.png", "Sad", "カナシイ"),
			new BuiltInSticker("MuTu_Angry", "angry.png", "Angry", "イカリ"),
			new BuiltInSticker("MuTu_ExcitedCrown", "excited_crown.png", "Surprised", "ビックリ"),
			new BuiltInSticker("MuTu_Turkey", "turkey.png", "Turkey", "ターキー"),
			new BuiltInSticker("MuTu_Help", "help.png", "Help", "助けて"),
			new BuiltInSticker("MuTu_OnMyWay", "on_my_way.png", "On My Way", "今いくよ"),
			new BuiltInSticker("MuTu_OverHere", "over_here.png", "Over Here", "こっちだよ"),
			new BuiltInSticker("MuTu_Thanks", "thanks.png", "Thanks", "ありがとう")
		};

		private static readonly Dictionary<string, StickerAsset> StickerAssets = new Dictionary<string, StickerAsset>(StringComparer.Ordinal);

		private static ConfigEntry<float> DisplaySecondsEntry = null;

		private static ConfigEntry<float> WorldScaleEntry = null;

		private static ConfigEntry<float> HeightOffsetEntry = null;

		private static ConfigEntry<float> HorizontalOffsetEntry = null;

		private static ConfigEntry<bool> AnimatePopEntry = null;

		private static ConfigEntry<bool> LoadCustomStickersEntry = null;

		private static ConfigEntry<bool> EnableSoundsEntry = null;

		private static ConfigEntry<float> SoundVolumeEntry = null;

		private static ConfigEntry<float> SoundSpatialBlendEntry = null;

		private static ConfigEntry<float> PositionStepEntry = null;

		private static ConfigEntry<KeyboardShortcut> MoveUpShortcutEntry = null;

		private static ConfigEntry<KeyboardShortcut> MoveDownShortcutEntry = null;

		private static ConfigEntry<KeyboardShortcut> MoveLeftShortcutEntry = null;

		private static ConfigEntry<KeyboardShortcut> MoveRightShortcutEntry = null;

		private static ConfigEntry<KeyboardShortcut> ResetPositionShortcutEntry = null;

		private Harmony? _harmony;

		internal static ManualLogSource Log { get; private set; } = null;

		internal static IReadOnlyDictionary<string, StickerAsset> Stickers => StickerAssets;

		internal static float DisplaySeconds => DisplaySecondsEntry.Value;

		internal static float WorldScale => WorldScaleEntry.Value;

		internal static float HeightOffset => HeightOffsetEntry.Value;

		internal static float HorizontalOffset => HorizontalOffsetEntry.Value;

		internal static bool AnimatePop => AnimatePopEntry.Value;

		internal static bool EnableSounds => EnableSoundsEntry.Value;

		internal static float SoundVolume => SoundVolumeEntry.Value;

		internal static float SoundSpatialBlend => SoundSpatialBlendEntry.Value;

		private void Awake()
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			BindConfiguration();
			string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "icons");
			BuiltInSticker[] builtIns = BuiltIns;
			foreach (BuiltInSticker builtInSticker in builtIns)
			{
				RegisterSticker(text, builtInSticker.Id, builtInSticker.FileName, builtInSticker.EnglishName, builtInSticker.JapaneseName);
			}
			if (LoadCustomStickersEntry.Value)
			{
				RegisterCustomStickers(text);
			}
			((MonoBehaviour)this).StartCoroutine(LoadStickerSounds(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "sounds")));
			_harmony = new Harmony("MuTu.FGStickerEmotes");
			_harmony.PatchAll();
			Log.LogInfo((object)string.Format("{0} {1} loaded with {2} stickers.", "FG Sticker Emotes", "2.3.0", StickerAssets.Count));
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			EmoteBubble.ClearAll();
			foreach (StickerAsset value in StickerAssets.Values)
			{
				Object.Destroy((Object)(object)value.Sprite);
				Object.Destroy((Object)(object)value.Texture);
				if ((Object)(object)value.AudioClip != (Object)null)
				{
					Object.Destroy((Object)(object)value.AudioClip);
				}
			}
			StickerAssets.Clear();
		}

		private void Update()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			float num2 = 0f;
			KeyboardShortcut value = MoveLeftShortcutEntry.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				num -= PositionStepEntry.Value;
			}
			value = MoveRightShortcutEntry.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				num += PositionStepEntry.Value;
			}
			value = MoveDownShortcutEntry.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				num2 -= PositionStepEntry.Value;
			}
			value = MoveUpShortcutEntry.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				num2 += PositionStepEntry.Value;
			}
			if (!Mathf.Approximately(num, 0f) || !Mathf.Approximately(num2, 0f))
			{
				HorizontalOffsetEntry.Value = Mathf.Clamp(HorizontalOffsetEntry.Value + num, -3f, 3f);
				HeightOffsetEntry.Value = Mathf.Clamp(HeightOffsetEntry.Value + num2, 0f, 3f);
				((BaseUnityPlugin)this).Config.Save();
				Log.LogInfo((object)$"Sticker position: horizontal={HorizontalOffsetEntry.Value:0.00}, height={HeightOffsetEntry.Value:0.00}");
			}
			value = ResetPositionShortcutEntry.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				HorizontalOffsetEntry.Value = 0f;
				HeightOffsetEntry.Value = 0.75f;
				((BaseUnityPlugin)this).Config.Save();
				Log.LogInfo((object)"Sticker position reset.");
			}
		}

		private void BindConfiguration()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Expected O, but got Unknown
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Expected O, but got Unknown
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Expected O, but got Unknown
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			DisplaySecondsEntry = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Duration", 5f, new ConfigDescription("Seconds each sticker remains visible.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 15f), Array.Empty<object>()));
			WorldScaleEntry = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Scale", 1.25f, new ConfigDescription("Sticker size in world space.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 4f), Array.Empty<object>()));
			HeightOffsetEntry = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "HeightOffset", 0.75f, new ConfigDescription("World-space gap between the detected head point and the bottom of the sticker.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
			HorizontalOffsetEntry = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "HorizontalOffset", 0f, new ConfigDescription("Camera-relative horizontal sticker offset.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-3f, 3f), Array.Empty<object>()));
			AnimatePopEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "AnimatePop", true, "Animate stickers when they appear.");
			LoadCustomStickersEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("Stickers", "LoadCustomPngFiles", true, "Register additional PNG files placed in the icons folder.");
			EnableSoundsEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("Sound", "Enabled", true, "Play a sound when a sticker appears.");
			SoundVolumeEntry = ((BaseUnityPlugin)this).Config.Bind<float>("Sound", "Volume", 0.8f, new ConfigDescription("Sticker sound volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			SoundSpatialBlendEntry = ((BaseUnityPlugin)this).Config.Bind<float>("Sound", "SpatialBlend", 1f, new ConfigDescription("0 is 2D and 1 is fully positional 3D audio.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			PositionStepEntry = ((BaseUnityPlugin)this).Config.Bind<float>("Position Controls", "Step", 0.1f, new ConfigDescription("Distance moved by each position shortcut press.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.5f), Array.Empty<object>()));
			MoveUpShortcutEntry = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Position Controls", "MoveUp", new KeyboardShortcut((KeyCode)273, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Move stickers up.");
			MoveDownShortcutEntry = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Position Controls", "MoveDown", new KeyboardShortcut((KeyCode)274, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Move stickers down.");
			MoveLeftShortcutEntry = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Position Controls", "MoveLeft", new KeyboardShortcut((KeyCode)276, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Move stickers left.");
			MoveRightShortcutEntry = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Position Controls", "MoveRight", new KeyboardShortcut((KeyCode)275, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Move stickers right.");
			ResetPositionShortcutEntry = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Position Controls", "Reset", new KeyboardShortcut((KeyCode)278, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Reset sticker position.");
		}

		private void RegisterCustomStickers(string iconDirectory)
		{
			if (!Directory.Exists(iconDirectory))
			{
				return;
			}
			HashSet<string> hashSet = new HashSet<string>(BuiltIns.Select((BuiltInSticker sticker) => sticker.FileName), StringComparer.OrdinalIgnoreCase);
			foreach (string item in Directory.GetFiles(iconDirectory, "*.png").OrderBy<string, string>((string path) => path, StringComparer.OrdinalIgnoreCase))
			{
				string fileName = Path.GetFileName(item);
				if (!hashSet.Contains(fileName))
				{
					string text = Path.GetFileNameWithoutExtension(item).Replace('_', ' ').Trim();
					string id = "MuTu_Custom_" + SanitizeId(Path.GetFileNameWithoutExtension(item));
					RegisterSticker(iconDirectory, id, fileName, text, text);
				}
			}
		}

		private void RegisterSticker(string directory, string id, string fileName, string englishName, string japaneseName)
		{
			//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_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_0055: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			string text = Path.Combine(directory, fileName);
			if (!File.Exists(text))
			{
				Log.LogWarning((object)("Sticker icon not found: " + text));
				return;
			}
			try
			{
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false)
				{
					name = "FGSticker_" + id + "_Texture",
					filterMode = (FilterMode)1,
					wrapMode = (TextureWrapMode)1
				};
				if (!ImageConversion.LoadImage(val, File.ReadAllBytes(text), false))
				{
					Object.Destroy((Object)(object)val);
					Log.LogWarning((object)("Could not decode sticker icon: " + text));
					return;
				}
				Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), (float)((Texture)val).width);
				((Object)val2).name = "FGSticker_" + id + "_Sprite";
				AnimationClip val3 = new AnimationClip
				{
					name = id,
					frameRate = 30f
				};
				Emote val4 = new Emote(id, val3, val2, (EmoteType)0, true);
				val4.AddLocalization(englishName, (Language)0);
				val4.AddLocalization(japaneseName, (Language)11);
				BaseUnityPluginExtensions.RegisterEmote((BaseUnityPlugin)(object)this, val4);
				StickerAssets.Add(val4.Name, new StickerAsset(val, val2, Path.GetFileNameWithoutExtension(fileName)));
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to register sticker '{fileName}': {arg}");
			}
		}

		private IEnumerator LoadStickerSounds(string soundDirectory)
		{
			if (!Directory.Exists(soundDirectory))
			{
				yield break;
			}
			foreach (StickerAsset asset in StickerAssets.Values)
			{
				string soundPath = FindSoundFile(soundDirectory, asset.SoundBaseName);
				if (soundPath != null)
				{
					AudioType val = (AudioType)(Path.GetExtension(soundPath).Equals(".wav", StringComparison.OrdinalIgnoreCase) ? 20 : 14);
					UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(soundPath).AbsoluteUri, val);
					yield return request.SendWebRequest();
					if ((int)request.result == 1)
					{
						asset.AudioClip = DownloadHandlerAudioClip.GetContent(request);
						((Object)asset.AudioClip).name = "FGSticker_" + asset.SoundBaseName + "_Audio";
					}
					else
					{
						Log.LogWarning((object)("Could not load sticker sound '" + soundPath + "': " + request.error));
					}
					request.Dispose();
				}
			}
		}

		private static string? FindSoundFile(string directory, string baseName)
		{
			string text = Path.Combine(directory, baseName + ".ogg");
			if (File.Exists(text))
			{
				return text;
			}
			string text2 = Path.Combine(directory, baseName + ".wav");
			if (!File.Exists(text2))
			{
				return null;
			}
			return text2;
		}

		private static string SanitizeId(string value)
		{
			StringBuilder stringBuilder = new StringBuilder(value.Length);
			foreach (char c in value)
			{
				stringBuilder.Append(char.IsLetterOrDigit(c) ? c : '_');
			}
			return stringBuilder.ToString();
		}
	}
	internal sealed class StickerAsset
	{
		internal Texture2D Texture { get; }

		internal Sprite Sprite { get; }

		internal string SoundBaseName { get; }

		internal AudioClip? AudioClip { get; set; }

		internal StickerAsset(Texture2D texture, Sprite sprite, string soundBaseName)
		{
			Texture = texture;
			Sprite = sprite;
			SoundBaseName = soundBaseName;
		}
	}
}