Decompiled source of Empress REPOPenguins v1.0.0

BepInEx/plugins/Omniscye-Empress_Pengu/EmpressPengu.dll

Decompiled a day 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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Networking;
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: AssemblyCompany("Empress")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EmpressPengu")]
[assembly: AssemblyTitle("EmpressPengu")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Empress.REPO.Pengu
{
	[BepInPlugin("com.empress.repo.pengu", "Empress REPOPenguins", "1.0.0")]
	public sealed class EmpressPenguPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.empress.repo.pengu";

		public const string PluginName = "Empress REPOPenguins";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log { get; private set; }

		internal static PenguSettings Settings { get; private set; }

		internal static string PluginDirectory { get; private set; }

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			PluginDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			Settings = new PenguSettings(((BaseUnityPlugin)this).Config);
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			PenguRuntime.EnsureHost();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Empress REPOPenguins v1.0.0 loaded.");
		}

		internal static void DebugLog(string message)
		{
			if (Settings != null && Settings.DebugLogs.Value)
			{
				Log.LogInfo((object)message);
			}
		}
	}
	internal sealed class PenguSettings
	{
		public readonly ConfigEntry<bool> Enabled;

		public readonly ConfigEntry<bool> DebugLogs;

		public readonly ConfigEntry<int> PenguinCount;

		public readonly ConfigEntry<float> Scale;

		public readonly ConfigEntry<float> WalkSpeed;

		public readonly ConfigEntry<float> Gravity;

		public readonly ConfigEntry<float> SpawnDelay;

		public readonly ConfigEntry<bool> EnableSounds;

		public readonly ConfigEntry<float> SoundVolume;

		public PenguSettings(ConfigFile config)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Expected O, but got Unknown
			Enabled = config.Bind<bool>("REPOPenguins", "Enabled", true, "Enable Empress REPOPenguins on the main menu.");
			PenguinCount = config.Bind<int>("REPOPenguins", "PenguinCount", 18, new ConfigDescription("How many penguins can run around the main menu.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 80), Array.Empty<object>()));
			Scale = config.Bind<float>("REPOPenguins", "Scale", 1.45f, new ConfigDescription("Menu penguin size.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f), Array.Empty<object>()));
			WalkSpeed = config.Bind<float>("REPOPenguins", "WalkSpeed", 90f, new ConfigDescription("Penguin walking speed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 260f), Array.Empty<object>()));
			Gravity = config.Bind<float>("REPOPenguins", "Gravity", 1700f, new ConfigDescription("Penguin falling gravity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(300f, 4000f), Array.Empty<object>()));
			SpawnDelay = config.Bind<float>("REPOPenguins", "SpawnDelay", 0.14f, new ConfigDescription("Delay between penguin spawns.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 2f), Array.Empty<object>()));
			EnableSounds = config.Bind<bool>("REPOPenguins", "EnableSounds", true, "Play penguin grab and drop sounds.");
			SoundVolume = config.Bind<float>("REPOPenguins", "SoundVolume", 0.45f, new ConfigDescription("Penguin sound volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			DebugLogs = config.Bind<bool>("Debug", "DebugLogs", false, "Logs verbose Empress REPOPenguins diagnostics.");
		}
	}
	internal static class PenguAssets
	{
		private static readonly Dictionary<string, Sprite[]> Animations = new Dictionary<string, Sprite[]>();

		private static bool _loaded;

		public static bool Ready
		{
			get
			{
				if (_loaded)
				{
					return Animations.Count > 0;
				}
				return false;
			}
		}

		public static void Load(string pluginDirectory)
		{
			if (!_loaded)
			{
				_loaded = true;
				string root = Path.Combine(pluginDirectory, "sprites", "winpenguins_large");
				LoadAnimation(root, "walker", "walk", 45, 45, 8, 0);
				LoadAnimation(root, "faller", "fall", 45, 45, 8, 0);
				LoadAnimation(root, "reader", "read", 45, 45, 12, 0);
				LoadAnimation(root, "tumbler", "tumble", 45, 45, 8, 0);
				LoadAnimation(root, "floater", "float", 45, 45, 8, 0);
				LoadAnimation(root, "superpenguin", "super", 45, 45, 8, 0);
				LoadAnimation(root, "ballooner", "balloon", 45, 93, 8, 0);
				LoadAnimation(root, "splat", "splat", 48, 48, 12, 0);
			}
		}

		public static Sprite Frame(string animation, int index)
		{
			if (!Animations.TryGetValue(animation, out var value) || value == null || value.Length == 0)
			{
				return null;
			}
			return value[Mathf.Abs(index) % value.Length];
		}

		public static int Count(string animation)
		{
			if (!Animations.TryGetValue(animation, out var value) || value == null)
			{
				return 0;
			}
			return value.Length;
		}

		private static void LoadAnimation(string root, string fileName, string key, int frameWidth, int frameHeight, int frameCount, int rowFromTop)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_009b: 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)
			string text = Path.Combine(root, fileName + ".png");
			if (!File.Exists(text))
			{
				EmpressPenguPlugin.DebugLog("Missing sprite sheet: " + text);
				return;
			}
			byte[] array = File.ReadAllBytes(text);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			((Object)val).name = "Empress REPOPenguins " + key;
			((Texture)val).filterMode = (FilterMode)0;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			if (ImageConversion.LoadImage(val, array, false))
			{
				Sprite[] array2 = (Sprite[])(object)new Sprite[frameCount];
				int num = ((Texture)val).height - (rowFromTop + 1) * frameHeight;
				Rect val2 = default(Rect);
				for (int i = 0; i < frameCount; i++)
				{
					((Rect)(ref val2))..ctor((float)(i * frameWidth), (float)num, (float)frameWidth, (float)frameHeight);
					array2[i] = Sprite.Create(val, val2, new Vector2(0.5f, 0f), 100f, 0u, (SpriteMeshType)0);
					((Object)array2[i]).name = key + "_" + i;
				}
				Animations[key] = array2;
			}
		}
	}
	internal sealed class PenguCreature : MonoBehaviour, IPointerDownHandler, IEventSystemHandler, IDragHandler, IPointerUpHandler
	{
		private enum PenguState
		{
			Falling,
			Walking,
			Reading,
			Tumbling,
			Floating,
			Dragged
		}

		private PenguRuntime _runtime;

		private RectTransform _rect;

		private Image _image;

		private Vector2 _position;

		private Vector2 _dragOffset;

		private Vector2 _lastDragPosition;

		private Vector2 _dragVelocity;

		private PenguSurface _surface;

		private PenguState _state;

		private float _direction;

		private float _fallVelocity;

		private float _horizontalVelocity;

		private float _personalSpeed;

		private float _frameTimer;

		private float _stateTimer;

		private float _choiceTimer;

		private float _scale;

		private int _frame;

		private bool _hasSurface;

		private bool _dragging;

		private float HalfWidth => 22.5f * _scale;

		public void Initialize(PenguRuntime runtime, RectTransform rect, Image image, Vector2 position, float scale)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			_runtime = runtime;
			_rect = rect;
			_image = image;
			_position = position;
			_scale = scale;
			_direction = ((Random.value < 0.5f) ? (-1f) : 1f);
			_fallVelocity = Random.Range(-180f, -20f);
			_horizontalVelocity = Random.Range(-60f, 60f);
			_personalSpeed = Random.Range(0.78f, 1.28f);
			_state = ((Random.value < 0.12f) ? PenguState.Floating : PenguState.Falling);
			_choiceTimer = Random.Range(0.8f, 3.8f);
			ApplyPosition();
			ApplySprite("fall", 0.08f);
		}

		public void Tick(float dt)
		{
			if (!((Object)(object)_runtime == (Object)null) && !((Object)(object)_rect == (Object)null) && !((Object)(object)_image == (Object)null) && !_dragging)
			{
				switch (_state)
				{
				case PenguState.Walking:
					TickWalking(dt);
					break;
				case PenguState.Reading:
					TickReading(dt);
					break;
				case PenguState.Tumbling:
					TickTumbling(dt);
					break;
				case PenguState.Floating:
					TickFloating(dt);
					break;
				default:
					TickFalling(dt);
					break;
				}
				KeepAlive();
				ApplyPosition();
			}
		}

		public void OnPointerDown(PointerEventData eventData)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0052: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_runtime == (Object)null) && _runtime.ScreenToLocal(eventData.position, out var localPosition))
			{
				_dragging = true;
				_state = PenguState.Dragged;
				_hasSurface = false;
				_dragOffset = _position - localPosition;
				_lastDragPosition = _position;
				_dragVelocity = Vector2.zero;
				((Component)this).transform.SetAsLastSibling();
				_runtime.PlaySound("pengu_grab");
				ApplySprite("tumble", 0.05f);
			}
		}

		public void OnDrag(PointerEventData eventData)
		{
			//IL_001d: 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_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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if (_dragging && !((Object)(object)_runtime == (Object)null) && _runtime.ScreenToLocal(eventData.position, out var localPosition))
			{
				Vector2 val = _runtime.ClampInside(localPosition + _dragOffset, HalfWidth);
				float num = Mathf.Max(Time.unscaledDeltaTime, 0.001f);
				_dragVelocity = (val - _lastDragPosition) / num;
				_lastDragPosition = val;
				_position = val;
				_direction = ((_dragVelocity.x < -15f) ? (-1f) : ((_dragVelocity.x > 15f) ? 1f : _direction));
				ApplyPosition();
				ApplySprite("tumble", 0.05f);
			}
		}

		public void OnPointerUp(PointerEventData eventData)
		{
			if (!_dragging)
			{
				return;
			}
			_dragging = false;
			_fallVelocity = Mathf.Clamp(_dragVelocity.y, -950f, 900f);
			_horizontalVelocity = Mathf.Clamp(_dragVelocity.x, -540f, 540f);
			_direction = ((_horizontalVelocity < -20f) ? (-1f) : ((_horizontalVelocity > 20f) ? 1f : _direction));
			if (Mathf.Abs(_horizontalVelocity) < 420f && Mathf.Abs(_fallVelocity) < 650f && _runtime.FindDropSurface(_position.x, _position.y, HalfWidth, out var result))
			{
				Land(result);
				_runtime.PlaySound("pengu_drop");
				return;
			}
			if (Mathf.Abs(_horizontalVelocity) < 300f && Mathf.Abs(_fallVelocity) < 420f)
			{
				_state = PenguState.Floating;
				_fallVelocity = Mathf.Clamp(_fallVelocity, -90f, 80f);
				_horizontalVelocity = Mathf.Clamp(_horizontalVelocity, -120f, 120f);
			}
			else
			{
				_state = ((Mathf.Abs(_horizontalVelocity) > 280f || Mathf.Abs(_fallVelocity) > 520f) ? PenguState.Tumbling : PenguState.Falling);
			}
			_runtime.PlaySound("pengu_drop");
			_stateTimer = Random.Range(0.35f, 0.8f);
			_hasSurface = false;
		}

		private void TickFalling(float dt)
		{
			float y = _position.y;
			float num = Mathf.Clamp(EmpressPenguPlugin.Settings.Gravity.Value, 300f, 4000f);
			_fallVelocity -= num * dt;
			_horizontalVelocity = Mathf.MoveTowards(_horizontalVelocity, 0f, dt * 90f);
			_position.x += _horizontalVelocity * dt;
			_position.y += _fallVelocity * dt;
			if (_runtime.FindLandingSurface(_position.x, y, _position.y, HalfWidth, out var result))
			{
				Land(result);
			}
			else
			{
				ApplySprite("fall", 0.08f);
			}
		}

		private void TickFloating(float dt)
		{
			float y = _position.y;
			_fallVelocity -= EmpressPenguPlugin.Settings.Gravity.Value * 0.18f * dt;
			_position.x += Mathf.Sin(Time.unscaledTime * 1.8f + (float)((Object)this).GetInstanceID()) * dt * 35f;
			_position.y += _fallVelocity * dt;
			if (_runtime.FindLandingSurface(_position.x, y, _position.y, HalfWidth, out var result))
			{
				Land(result);
			}
			else
			{
				ApplySprite("float", 0.1f);
			}
		}

		private void TickTumbling(float dt)
		{
			_stateTimer -= dt;
			float y = _position.y;
			_fallVelocity -= EmpressPenguPlugin.Settings.Gravity.Value * dt;
			_horizontalVelocity = Mathf.MoveTowards(_horizontalVelocity, _direction * EmpressPenguPlugin.Settings.WalkSpeed.Value, dt * 220f);
			_position.x += _horizontalVelocity * dt;
			_position.y += _fallVelocity * dt;
			if (_runtime.FindLandingSurface(_position.x, y, _position.y, HalfWidth, out var result))
			{
				Land(result);
			}
			else if (_stateTimer <= 0f)
			{
				_state = PenguState.Falling;
			}
			ApplySprite("tumble", 0.055f);
		}

		private void TickWalking(float dt)
		{
			if (!_hasSurface || !_runtime.FindSupportSurface(_position.x, _position.y, HalfWidth, out var result))
			{
				FallFromEdge();
				return;
			}
			_surface = result;
			float num = Mathf.Clamp(EmpressPenguPlugin.Settings.WalkSpeed.Value, 20f, 260f) * _personalSpeed;
			_position.x += _direction * num * dt;
			_position.y = _surface.Y;
			_choiceTimer -= dt;
			if (!_surface.Contains(_position.x, HalfWidth))
			{
				if (!_surface.Floor)
				{
					FallFromEdge();
					return;
				}
				_position.x = Mathf.Clamp(_position.x, _surface.MinX + HalfWidth, _surface.MaxX - HalfWidth);
				_direction *= -1f;
			}
			if (_choiceTimer <= 0f)
			{
				ChooseGroundAction();
			}
			ApplySprite("walk", 0.075f);
		}

		private void TickReading(float dt)
		{
			if (!_hasSurface || !_runtime.FindSupportSurface(_position.x, _position.y, HalfWidth, out var result))
			{
				FallFromEdge();
				return;
			}
			_surface = result;
			_position.y = _surface.Y;
			_stateTimer -= dt;
			ApplySprite("read", 0.12f);
			if (_stateTimer <= 0f)
			{
				_state = PenguState.Walking;
				_direction = ((Random.value < 0.5f) ? (-1f) : 1f);
				_choiceTimer = Random.Range(0.8f, 3.5f);
			}
		}

		private void ChooseGroundAction()
		{
			_choiceTimer = Random.Range(0.8f, 4.5f);
			float value = Random.value;
			if (value < 0.18f)
			{
				_direction *= -1f;
			}
			else if (value < 0.34f)
			{
				_state = PenguState.Reading;
				_stateTimer = Random.Range(1.1f, 4.2f);
			}
		}

		private void Land(PenguSurface surface)
		{
			_surface = surface;
			_hasSurface = true;
			_position.y = surface.Y;
			_fallVelocity = 0f;
			_horizontalVelocity = 0f;
			_state = ((!(Random.value < 0.2f)) ? PenguState.Walking : PenguState.Reading);
			_stateTimer = Random.Range(1f, 3.5f);
			_choiceTimer = Random.Range(0.5f, 3f);
		}

		private void FallFromEdge()
		{
			_hasSurface = false;
			_state = PenguState.Falling;
			_fallVelocity = -40f;
			_horizontalVelocity = _direction * Mathf.Clamp(EmpressPenguPlugin.Settings.WalkSpeed.Value, 20f, 260f) * _personalSpeed;
		}

		private void KeepAlive()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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)
			Rect rootRect = _runtime.RootRect;
			_position = _runtime.ClampInside(_position, HalfWidth);
			if (_position.y < ((Rect)(ref rootRect)).yMin - 150f)
			{
				_position.x = Random.Range(((Rect)(ref rootRect)).xMin + 60f, ((Rect)(ref rootRect)).xMax - 60f);
				_position.y = ((Rect)(ref rootRect)).yMax + Random.Range(60f, 240f);
				_fallVelocity = Random.Range(-240f, -40f);
				_horizontalVelocity = Random.Range(-80f, 80f);
				_state = PenguState.Falling;
				_hasSurface = false;
			}
		}

		private void ApplySprite(string animation, float frameDelay)
		{
			//IL_0076: 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)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			Sprite val = PenguAssets.Frame(animation, _frame);
			if ((Object)(object)val == (Object)null)
			{
				val = PenguAssets.Frame("walk", _frame);
			}
			if ((Object)(object)val != (Object)null)
			{
				_image.sprite = val;
			}
			_frameTimer -= Time.unscaledDeltaTime;
			if (_frameTimer <= 0f)
			{
				_frameTimer = frameDelay;
				_frame++;
			}
			Vector3 localScale = ((Transform)_rect).localScale;
			localScale.x = ((_direction < 0f) ? 1f : (-1f));
			localScale.y = 1f;
			localScale.z = 1f;
			((Transform)_rect).localScale = localScale;
		}

		private void ApplyPosition()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			_rect.anchoredPosition = _position;
		}
	}
	internal sealed class PenguRuntime : MonoBehaviour
	{
		private readonly List<PenguCreature> _penguins = new List<PenguCreature>();

		private readonly List<PenguSurface> _surfaces = new List<PenguSurface>();

		private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[4];

		private Canvas _canvas;

		private RectTransform _root;

		private AudioSource _audio;

		private float _surfaceTimer;

		private float _spawnTimer;

		private bool _lastActive;

		public static PenguRuntime Instance { get; private set; }

		public Rect RootRect
		{
			get
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_root != (Object)null))
				{
					return new Rect(-960f, -540f, 1920f, 1080f);
				}
				return _root.rect;
			}
		}

		public static PenguRuntime EnsureHost()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			if ((Object)(object)Instance != (Object)null)
			{
				return Instance;
			}
			GameObject val = new GameObject("Empress REPOPenguins Runtime");
			val.transform.parent = null;
			((Object)val).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)val);
			Instance = val.AddComponent<PenguRuntime>();
			return Instance;
		}

		private void Awake()
		{
			Instance = this;
		}

		private void Update()
		{
			if (EmpressPenguPlugin.Settings == null || !EmpressPenguPlugin.Settings.Enabled.Value || !OnMainMenu())
			{
				if (_lastActive)
				{
					ClearPenguins();
				}
				if ((Object)(object)_canvas != (Object)null)
				{
					((Component)_canvas).gameObject.SetActive(false);
				}
				_lastActive = false;
			}
			else
			{
				EnsureCanvas();
				EnsureAudio();
				PenguAssets.Load(EmpressPenguPlugin.PluginDirectory);
				PenguSounds.Initialize(EmpressPenguPlugin.PluginDirectory, (MonoBehaviour)(object)this);
				((Component)_canvas).gameObject.SetActive(true);
				_lastActive = true;
				float dt = Mathf.Clamp(Time.unscaledDeltaTime, 0f, 0.05f);
				TickSurfaces(dt);
				TickSpawning(dt);
				TickPenguins(dt);
			}
		}

		private static bool OnMainMenu()
		{
			try
			{
				return SemiFunc.MenuLevel() && (Object)(object)MenuManager.instance != (Object)null;
			}
			catch
			{
				return false;
			}
		}

		private void EnsureCanvas()
		{
			//IL_0015: 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)
			if (!((Object)(object)_canvas != (Object)null))
			{
				_canvas = new GameObject("Empress REPOPenguins Menu Layer").AddComponent<Canvas>();
				((Component)_canvas).transform.SetParent(((Component)this).transform, false);
				_canvas.renderMode = (RenderMode)0;
				_canvas.sortingOrder = 31000;
				CanvasScaler obj = ((Component)_canvas).gameObject.AddComponent<CanvasScaler>();
				obj.uiScaleMode = (ScaleMode)1;
				obj.referenceResolution = new Vector2(1920f, 1080f);
				obj.matchWidthOrHeight = 0.5f;
				((Component)_canvas).gameObject.AddComponent<GraphicRaycaster>();
				_root = ((Component)_canvas).GetComponent<RectTransform>();
			}
		}

		private void EnsureAudio()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			if (!((Object)(object)_audio != (Object)null))
			{
				GameObject val = new GameObject("Empress REPOPenguins Audio");
				val.transform.SetParent(((Component)this).transform, false);
				_audio = val.AddComponent<AudioSource>();
				_audio.playOnAwake = false;
				_audio.loop = false;
				_audio.spatialBlend = 0f;
				_audio.pitch = 1f;
			}
		}

		private void TickSurfaces(float dt)
		{
			_surfaceTimer -= dt;
			if (!(_surfaceTimer > 0f))
			{
				_surfaceTimer = 0.12f;
				RebuildSurfaces();
			}
		}

		private void TickSpawning(float dt)
		{
			if (!PenguAssets.Ready || (Object)(object)_root == (Object)null)
			{
				return;
			}
			int num = Mathf.Clamp(EmpressPenguPlugin.Settings.PenguinCount.Value, 1, 80);
			if (_penguins.Count < num)
			{
				_spawnTimer -= dt;
				if (!(_spawnTimer > 0f))
				{
					_spawnTimer = Mathf.Max(0.02f, EmpressPenguPlugin.Settings.SpawnDelay.Value);
					SpawnPenguin();
				}
			}
		}

		private void TickPenguins(float dt)
		{
			for (int num = _penguins.Count - 1; num >= 0; num--)
			{
				PenguCreature penguCreature = _penguins[num];
				if ((Object)(object)penguCreature == (Object)null)
				{
					_penguins.RemoveAt(num);
				}
				else
				{
					penguCreature.Tick(dt);
				}
			}
		}

		private void SpawnPenguin()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			Rect rootRect = RootRect;
			float num = Mathf.Clamp(EmpressPenguPlugin.Settings.Scale.Value, 0.5f, 4f);
			float num2 = Random.Range(((Rect)(ref rootRect)).xMin + 60f, ((Rect)(ref rootRect)).xMax - 60f);
			float num3 = ((Rect)(ref rootRect)).yMax + Random.Range(30f, 240f);
			GameObject val = new GameObject("Empress REPOPenguins");
			RectTransform val2 = val.AddComponent<RectTransform>();
			((Transform)val2).SetParent((Transform)(object)_root, false);
			val2.anchorMin = new Vector2(0.5f, 0.5f);
			val2.anchorMax = new Vector2(0.5f, 0.5f);
			val2.pivot = new Vector2(0.5f, 0f);
			val2.sizeDelta = new Vector2(45f, 45f) * num;
			Image val3 = val.AddComponent<Image>();
			((Graphic)val3).raycastTarget = true;
			val3.preserveAspect = true;
			val3.sprite = PenguAssets.Frame("fall", 0) ?? PenguAssets.Frame("walk", 0);
			PenguCreature penguCreature = val.AddComponent<PenguCreature>();
			penguCreature.Initialize(this, val2, val3, new Vector2(num2, num3), num);
			_penguins.Add(penguCreature);
		}

		private void ClearPenguins()
		{
			for (int i = 0; i < _penguins.Count; i++)
			{
				if ((Object)(object)_penguins[i] != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)_penguins[i]).gameObject);
				}
			}
			_penguins.Clear();
			_surfaces.Clear();
			_spawnTimer = 0f;
		}

		private void RebuildSurfaces()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			_surfaces.Clear();
			Rect rootRect = RootRect;
			_surfaces.Add(new PenguSurface(((Rect)(ref rootRect)).xMin, ((Rect)(ref rootRect)).xMax, ((Rect)(ref rootRect)).yMin + 8f, floor: true));
			MenuButton[] array = Resources.FindObjectsOfTypeAll<MenuButton>();
			foreach (MenuButton val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					TryAddSurface(((Component)val).GetComponent<RectTransform>());
				}
			}
			Button[] array2 = Resources.FindObjectsOfTypeAll<Button>();
			foreach (Button val2 in array2)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					TryAddSurface(((Component)val2).GetComponent<RectTransform>());
				}
			}
			RectTransform[] array3 = Resources.FindObjectsOfTypeAll<RectTransform>();
			foreach (RectTransform val3 in array3)
			{
				if ((Object)(object)val3 != (Object)null && LooksLikeMenuText(val3))
				{
					TryAddSurface(val3);
				}
			}
			TextMeshProUGUI[] array4 = Resources.FindObjectsOfTypeAll<TextMeshProUGUI>();
			foreach (TextMeshProUGUI text in array4)
			{
				if (LooksLikeMenuText(text))
				{
					TryAddTextSurface(text);
				}
			}
		}

		private void TryAddSurface(RectTransform source)
		{
			if (!CanUseSurfaceSource(source) || !TryMakeSurface(source, out var surface))
			{
				return;
			}
			for (int i = 0; i < _surfaces.Count; i++)
			{
				PenguSurface penguSurface = _surfaces[i];
				if (Mathf.Abs(penguSurface.Y - surface.Y) < 4f && Mathf.Abs(penguSurface.MinX - surface.MinX) < 12f && Mathf.Abs(penguSurface.MaxX - surface.MaxX) < 12f)
				{
					return;
				}
			}
			_surfaces.Add(surface);
		}

		private bool CanUseSurfaceSource(RectTransform source)
		{
			if ((Object)(object)source == (Object)null || !((Component)source).gameObject.activeInHierarchy)
			{
				return false;
			}
			Canvas componentInParent = ((Component)source).GetComponentInParent<Canvas>();
			if ((Object)(object)componentInParent == (Object)null || (Object)(object)componentInParent == (Object)(object)_canvas)
			{
				return false;
			}
			if ((Object)(object)((Component)source).GetComponentInParent<PenguCreature>() != (Object)null)
			{
				return false;
			}
			return true;
		}

		private bool LooksLikeMenuText(RectTransform source)
		{
			if (!CanUseSurfaceSource(source))
			{
				return false;
			}
			TextMeshProUGUI val = ((Component)source).GetComponent<TextMeshProUGUI>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)source).GetComponentInChildren<TextMeshProUGUI>(true);
			}
			return LooksLikeMenuText(val);
		}

		private bool LooksLikeMenuText(TextMeshProUGUI text)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)text == (Object)null || !((Behaviour)text).enabled || string.IsNullOrWhiteSpace(((TMP_Text)text).text) || ((Graphic)text).color.a < 0.08f)
			{
				return false;
			}
			if (!CanUseSurfaceSource(((TMP_Text)text).rectTransform))
			{
				return false;
			}
			string text2 = ((TMP_Text)text).text.ToUpperInvariant();
			if (!text2.Contains("PRIVATE") && !text2.Contains("PUBLIC") && !text2.Contains("JOIN") && !text2.Contains("SINGLEPLAYER") && !text2.Contains("TUTORIAL") && !text2.Contains("CUSTOMIZE") && !text2.Contains("SETTINGS") && !text2.Contains("MODS") && !text2.Contains("QUIT"))
			{
				return text2.Contains("SPAWN MANAGER");
			}
			return true;
		}

		private void TryAddTextSurface(TextMeshProUGUI text)
		{
			if (!CanUseSurfaceSource(((TMP_Text)text).rectTransform) || !TryMakeTextSurface(text, out var surface))
			{
				return;
			}
			for (int i = 0; i < _surfaces.Count; i++)
			{
				PenguSurface penguSurface = _surfaces[i];
				if (Mathf.Abs(penguSurface.Y - surface.Y) < 4f && Mathf.Abs(penguSurface.MinX - surface.MinX) < 18f && Mathf.Abs(penguSurface.MaxX - surface.MaxX) < 18f)
				{
					return;
				}
			}
			_surfaces.Add(surface);
		}

		private bool TryMakeSurface(RectTransform source, out PenguSurface surface)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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)
			surface = default(PenguSurface);
			source.GetWorldCorners(_corners);
			Canvas componentInParent = ((Component)source).GetComponentInParent<Canvas>();
			Camera val = null;
			if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0)
			{
				val = (((Object)(object)componentInParent.worldCamera != (Object)null) ? componentInParent.worldCamera : Camera.main);
			}
			float num = float.MaxValue;
			float num2 = float.MinValue;
			float num3 = float.MinValue;
			for (int i = 0; i < _corners.Length; i++)
			{
				Vector2 screenPosition = RectTransformUtility.WorldToScreenPoint(val, _corners[i]);
				if (!ScreenToLocal(screenPosition, out var localPosition))
				{
					return false;
				}
				num = Mathf.Min(num, localPosition.x);
				num2 = Mathf.Max(num2, localPosition.x);
				num3 = Mathf.Max(num3, localPosition.y);
			}
			float num4 = num2 - num;
			if (num4 < 35f || num4 > 900f)
			{
				return false;
			}
			Rect rootRect = RootRect;
			if (num3 < ((Rect)(ref rootRect)).yMin + 40f || num3 > ((Rect)(ref rootRect)).yMax - 40f)
			{
				return false;
			}
			surface = new PenguSurface(num - 8f, num2 + 8f, num3 + 3f, floor: false);
			return true;
		}

		private bool TryMakeTextSurface(TextMeshProUGUI text, out PenguSurface surface)
		{
			//IL_0010: 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_0018: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0109: 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_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)
			//IL_012e: 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_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			surface = default(PenguSurface);
			((TMP_Text)text).ForceMeshUpdate(false, false);
			Bounds textBounds = ((TMP_Text)text).textBounds;
			if (((Bounds)(ref textBounds)).size.x <= 1f || ((Bounds)(ref textBounds)).size.y <= 1f)
			{
				return TryMakeSurface(((TMP_Text)text).rectTransform, out surface);
			}
			RectTransform rectTransform = ((TMP_Text)text).rectTransform;
			Canvas componentInParent = ((Component)rectTransform).GetComponentInParent<Canvas>();
			Camera val = null;
			if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0)
			{
				val = (((Object)(object)componentInParent.worldCamera != (Object)null) ? componentInParent.worldCamera : Camera.main);
			}
			Vector3 min = ((Bounds)(ref textBounds)).min;
			Vector3 max = ((Bounds)(ref textBounds)).max;
			Vector3[] array = (Vector3[])(object)new Vector3[4]
			{
				((Transform)rectTransform).TransformPoint(new Vector3(min.x, min.y, 0f)),
				((Transform)rectTransform).TransformPoint(new Vector3(max.x, min.y, 0f)),
				((Transform)rectTransform).TransformPoint(new Vector3(max.x, max.y, 0f)),
				((Transform)rectTransform).TransformPoint(new Vector3(min.x, max.y, 0f))
			};
			float num = float.MaxValue;
			float num2 = float.MinValue;
			float num3 = float.MinValue;
			for (int i = 0; i < array.Length; i++)
			{
				Vector2 screenPosition = RectTransformUtility.WorldToScreenPoint(val, array[i]);
				if (!ScreenToLocal(screenPosition, out var localPosition))
				{
					return false;
				}
				num = Mathf.Min(num, localPosition.x);
				num2 = Mathf.Max(num2, localPosition.x);
				num3 = Mathf.Max(num3, localPosition.y);
			}
			float num4 = num2 - num;
			if (num4 < 35f || num4 > 900f)
			{
				return TryMakeSurface(((TMP_Text)text).rectTransform, out surface);
			}
			Rect rootRect = RootRect;
			if (num3 < ((Rect)(ref rootRect)).yMin + 40f || num3 > ((Rect)(ref rootRect)).yMax - 40f)
			{
				return false;
			}
			surface = new PenguSurface(num - 18f, num2 + 18f, num3 + 6f, floor: false);
			return true;
		}

		public void PlaySound(string key)
		{
			if (EmpressPenguPlugin.Settings != null && EmpressPenguPlugin.Settings.EnableSounds.Value)
			{
				EnsureAudio();
				AudioClip val = PenguSounds.Get(key);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)_audio == (Object)null))
				{
					_audio.pitch = 1f;
					_audio.PlayOneShot(val, Mathf.Clamp01(EmpressPenguPlugin.Settings.SoundVolume.Value));
				}
			}
		}

		public bool ScreenToLocal(Vector2 screenPosition, out Vector2 localPosition)
		{
			//IL_0021: 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_0014: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root == (Object)null)
			{
				localPosition = Vector2.zero;
				return false;
			}
			return RectTransformUtility.ScreenPointToLocalPointInRectangle(_root, screenPosition, (Camera)null, ref localPosition);
		}

		public Vector2 ClampInside(Vector2 position, float halfWidth)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			Rect rootRect = RootRect;
			position.x = Mathf.Clamp(position.x, ((Rect)(ref rootRect)).xMin + halfWidth, ((Rect)(ref rootRect)).xMax - halfWidth);
			position.y = Mathf.Clamp(position.y, ((Rect)(ref rootRect)).yMin - 180f, ((Rect)(ref rootRect)).yMax + 260f);
			return position;
		}

		public bool FindLandingSurface(float x, float fromY, float toY, float halfWidth, out PenguSurface result)
		{
			result = default(PenguSurface);
			float num = float.MinValue;
			float num2 = Mathf.Max(fromY, toY);
			float num3 = Mathf.Min(fromY, toY);
			for (int i = 0; i < _surfaces.Count; i++)
			{
				PenguSurface penguSurface = _surfaces[i];
				if (penguSurface.Contains(x, halfWidth) && !(num2 < penguSurface.Y - 8f) && !(num3 > penguSurface.Y + 10f) && !(penguSurface.Y <= num))
				{
					num = penguSurface.Y;
					result = penguSurface;
				}
			}
			return num > float.MinValue;
		}

		public bool FindDropSurface(float x, float y, float halfWidth, out PenguSurface result)
		{
			RebuildSurfaces();
			result = default(PenguSurface);
			float num = float.MaxValue;
			for (int i = 0; i < _surfaces.Count; i++)
			{
				PenguSurface penguSurface = _surfaces[i];
				if (penguSurface.Contains(x, halfWidth))
				{
					float num2 = Mathf.Abs(penguSurface.Y - y);
					if (!(num2 > 86f) && (!(penguSurface.Y < y - 28f) || penguSurface.Floor) && !(num2 >= num))
					{
						num = num2;
						result = penguSurface;
					}
				}
			}
			return num < float.MaxValue;
		}

		public bool FindSupportSurface(float x, float y, float halfWidth, out PenguSurface result)
		{
			result = default(PenguSurface);
			float num = float.MinValue;
			for (int i = 0; i < _surfaces.Count; i++)
			{
				PenguSurface penguSurface = _surfaces[i];
				if (penguSurface.Contains(x, halfWidth) && !(Mathf.Abs(penguSurface.Y - y) > 18f) && !(penguSurface.Y <= num))
				{
					num = penguSurface.Y;
					result = penguSurface;
				}
			}
			return num > float.MinValue;
		}
	}
	internal struct PenguSurface
	{
		public readonly float MinX;

		public readonly float MaxX;

		public readonly float Y;

		public readonly bool Floor;

		public PenguSurface(float minX, float maxX, float y, bool floor)
		{
			MinX = minX;
			MaxX = maxX;
			Y = y;
			Floor = floor;
		}

		public bool Contains(float x, float halfWidth)
		{
			float num = (Floor ? halfWidth : Mathf.Min(halfWidth * 0.35f, 20f));
			if (x >= MinX + num)
			{
				return x <= MaxX - num;
			}
			return false;
		}
	}
	internal static class PenguSounds
	{
		private static readonly Dictionary<string, AudioClip> Clips = new Dictionary<string, AudioClip>();

		private static bool _started;

		public static void Initialize(string directory, MonoBehaviour runner)
		{
			if (!_started && !((Object)(object)runner == (Object)null) && !string.IsNullOrEmpty(directory))
			{
				_started = true;
				runner.StartCoroutine(LoadClips(directory));
			}
		}

		public static AudioClip Get(string key)
		{
			Clips.TryGetValue(key, out var value);
			return value;
		}

		private static IEnumerator LoadClips(string directory)
		{
			string[] files = Directory.GetFiles(directory, "pengu_*.ogg", SearchOption.TopDirectoryOnly);
			for (int i = 0; i < files.Length; i++)
			{
				yield return LoadClip(files[i]);
			}
		}

		private static IEnumerator LoadClip(string path)
		{
			string text = "file:///" + path.Replace("\\", "/");
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(text, (AudioType)14);
			try
			{
				yield return request.SendWebRequest();
				if (!string.IsNullOrEmpty(request.error))
				{
					ManualLogSource log = EmpressPenguPlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("Empress REPOPenguins could not load " + Path.GetFileName(path) + ": " + request.error));
					}
					yield break;
				}
				AudioClip content = DownloadHandlerAudioClip.GetContent(request);
				if ((Object)(object)content == (Object)null)
				{
					yield break;
				}
				((Object)content).name = Path.GetFileNameWithoutExtension(path);
				Clips[((Object)content).name] = content;
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
		}
	}
}