Decompiled source of MistlandsNoBugs v0.5.0

BepInEx/plugins/MistlandsNoBugs/MistlandsNoBugs.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyFileVersion("0.5.0.0")]
[assembly: AssemblyVersion("0.5.0.0")]
namespace MistlandsNoBugs;

internal enum Kind
{
	Seeker,
	Soldier,
	Brood,
	Tick,
	Queen,
	Gjall
}
[BepInPlugin("local.mistlands.nobugvisuals", "Mistlands No Bugs", "0.5.0")]
[BepInProcess("valheim.x86_64")]
[BepInProcess("valheim.exe")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string Id = "local.mistlands.nobugvisuals";

	internal static Plugin Instance;

	internal ConfigEntry<bool> ModEnabled;

	internal ConfigEntry<bool> ReplaceDeathVisuals;

	internal ConfigEntry<float> VisualScale;

	internal ConfigEntry<bool> Animate;

	internal ConfigEntry<bool> CuteSeeker;

	internal ConfigEntry<bool> CuteBrood;

	internal ConfigEntry<bool> CuteSoldier;

	internal ConfigEntry<bool> CuteTick;

	internal ConfigEntry<bool> CuteQueen;

	private readonly Dictionary<Kind, ConfigEntry<bool>> options = new Dictionary<Kind, ConfigEntry<bool>>();

	private readonly Dictionary<string, Kind> deathNames = new Dictionary<string, Kind>(StringComparer.OrdinalIgnoreCase);

	private readonly HashSet<string> logged = new HashSet<string>();

	private Harmony harmony;

	private Type characterType;

	private Type ragdollType;

	private float nextScan;

	private bool running;

	private void Awake()
	{
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Expected O, but got Unknown
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Invalid comparison between Unknown and I4
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Expected O, but got Unknown
		//IL_0285: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Expected O, but got Unknown
		Instance = this;
		ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable the visual replacement. Restart the game after changing settings.");
		ReplaceDeathVisuals = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ReplaceDeathVisuals", true, "Best-effort replacement of recognized death effects and ragdolls; not every effect is verified.");
		VisualScale = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "Scale", 1f, new ConfigDescription("Visual size multiplier only; never changes hitboxes.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), new object[0]));
		Animate = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance", "AnimateConstructs", true, "Gentle bobbing and an approximate attack lean. Not a reconstruction of original attack animations.");
		CuteSeeker = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance", "CuteSeeker", true, "Use the Blender-modeled Seeker with the original game skeleton. Restart required.");
		CuteBrood = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance", "CuteBrood", true, "Use the rounded baby Brood on the original game skeleton. Restart required.");
		CuteSoldier = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance", "CuteSoldier", true, "Use the armored Soldier on the original game skeleton, with a visible rear weak spot. Restart required.");
		CuteTick = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance", "CuteTick", true, "Use the round Tick with its original walking, biting and attached feeding animations. Restart required.");
		CuteQueen = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance", "CuteQueen", true, "Use the crowned Queen with its original skeleton and attacks, replacing the original spiky surface details. Restart required.");
		Bind(Kind.Seeker, enabled: true);
		Bind(Kind.Soldier, enabled: true);
		Bind(Kind.Brood, enabled: true);
		Bind(Kind.Tick, enabled: true);
		Bind(Kind.Queen, enabled: true);
		Bind(Kind.Gjall, enabled: false);
		if (!ModEnabled.Value || (int)SystemInfo.graphicsDeviceType == 4)
		{
			return;
		}
		try
		{
			characterType = AccessTools.TypeByName("Character");
			ragdollType = AccessTools.TypeByName("Ragdoll");
			if (characterType == null)
			{
				throw new InvalidOperationException("Valheim Character type was not found.");
			}
			harmony = new Harmony("local.mistlands.nobugvisuals");
			PatchAwake(characterType, "CharacterAwakePostfix", required: true);
			PatchAwake(ragdollType, "CorpseAwakePostfix", required: false);
			PatchAwake(AccessTools.TypeByName("ZNetView"), "CorpseAwakePostfix", required: false);
			Type type = AccessTools.TypeByName("EffectList");
			int num = 0;
			if (type != null)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (!(methodInfo.Name != "Create") && !(methodInfo.ReturnType != typeof(GameObject[])))
					{
						try
						{
							harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "EffectsPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
							num++;
						}
						catch (Exception ex)
						{
							WarnOnce("effecthook", "Death-effect hook unavailable: " + ex.Message);
						}
					}
				}
			}
			if (num == 0)
			{
				WarnOnce("noeffects", "Death-effect interception is unavailable on this build. Live creatures are still targeted.");
			}
			running = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Mistlands No Bugs 0.5.0 loaded. Cute Seeker, Brood, Soldier, Tick and Queen models; local visual-only hooks.");
		}
		catch (Exception ex2)
		{
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			((BaseUnityPlugin)this).Logger.LogError((object)("Mistlands No Bugs could not initialize: " + ex2));
		}
	}

	private void Bind(Kind kind, bool enabled)
	{
		options[kind] = ((BaseUnityPlugin)this).Config.Bind<bool>("Creatures", "Replace" + kind, enabled, string.Concat("Replace the ", kind, " with its configured visual model. Restart required."));
	}

	private void PatchAwake(Type type, string patch, bool required)
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Expected O, but got Unknown
		MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "Awake", Type.EmptyTypes, (Type[])null));
		if (methodInfo == null)
		{
			if (required)
			{
				throw new MissingMethodException("Required Character.Awake hook is missing.");
			}
			return;
		}
		try
		{
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), patch, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		catch (Exception ex)
		{
			if (required)
			{
				throw;
			}
			WarnOnce("hook-" + patch, "Optional hook failed: " + ex.Message);
		}
	}

	internal bool IsEnabled(Kind kind)
	{
		if (running && ModEnabled.Value && options.TryGetValue(kind, out var value))
		{
			return value.Value;
		}
		return false;
	}

	private static string CleanName(string name)
	{
		if (name == null)
		{
			return "";
		}
		int num = name.IndexOf("(Clone)", StringComparison.Ordinal);
		return ((num >= 0) ? name.Substring(0, num) : name).Trim();
	}

	private static bool TryKind(string name, out Kind kind)
	{
		switch (CleanName(name).ToLowerInvariant())
		{
		case "seeker":
			kind = Kind.Seeker;
			return true;
		case "seekerbrute":
			kind = Kind.Soldier;
			return true;
		case "seekerbrood":
			kind = Kind.Brood;
			return true;
		case "tick":
			kind = Kind.Tick;
			return true;
		case "seekerqueen":
			kind = Kind.Queen;
			return true;
		case "gjall":
			kind = Kind.Gjall;
			return true;
		default:
			kind = Kind.Seeker;
			return false;
		}
	}

	private static void CharacterAwakePostfix(Component __instance)
	{
		if ((Object)(object)Instance != (Object)null)
		{
			Instance.TryLive(__instance);
		}
	}

	private static void CorpseAwakePostfix(Component __instance)
	{
		if ((Object)(object)Instance != (Object)null && (Object)(object)__instance != (Object)null)
		{
			Instance.TryDeath(__instance.gameObject);
		}
	}

	private static void EffectsPostfix(GameObject[] __result)
	{
		if (!((Object)(object)Instance == (Object)null) && __result != null)
		{
			foreach (GameObject go in __result)
			{
				Instance.TryDeath(go);
			}
		}
	}

	private void TryLive(Component character)
	{
		if ((Object)(object)character == (Object)null || !running || (Object)(object)character.GetComponent<ConstructVisual>() != (Object)null || (Object)(object)character.GetComponent<CuteSeekerVisual>() != (Object)null || !TryKind(((Object)character.gameObject).name, out var kind) || !IsEnabled(kind))
		{
			return;
		}
		try
		{
			RememberDeathPrefabs(character, kind);
			if ((kind == Kind.Seeker && CuteSeeker.Value) || (kind == Kind.Brood && CuteBrood.Value) || (kind == Kind.Soldier && CuteSoldier.Value) || (kind == Kind.Tick && CuteTick.Value) || (kind == Kind.Queen && CuteQueen.Value))
			{
				CuteSeekerVisual cuteSeekerVisual = character.gameObject.AddComponent<CuteSeekerVisual>();
				try
				{
					if (cuteSeekerVisual.Initialize(kind))
					{
						if (logged.Add("cute-" + kind))
						{
							((BaseUnityPlugin)this).Logger.LogInfo((object)string.Concat("Cute ", kind, " attached to original animation rig."));
						}
						return;
					}
					WarnOnce("cute-rig-" + kind, string.Concat("The ", kind, " rig was not recognized; using the existing crystal replacement."));
				}
				catch (Exception ex)
				{
					WarnOnce("cute-error-" + kind, string.Concat("Cute ", kind, " could not attach; using crystal replacement: ", ex.Message));
				}
				cuteSeekerVisual.Shutdown();
				Object.Destroy((Object)(object)cuteSeekerVisual);
			}
			Attach(character.gameObject, kind, character, corpse: false);
		}
		catch (Exception ex2)
		{
			WarnOnce("live-" + kind, string.Concat("Could not replace ", kind, ": ", ex2));
		}
	}

	private void TryDeath(GameObject go)
	{
		if ((Object)(object)go == (Object)null || !running || !ReplaceDeathVisuals.Value)
		{
			return;
		}
		string text = CleanName(((Object)go).name);
		if (!deathNames.TryGetValue(text, out var value))
		{
			string text2 = text.ToLowerInvariant();
			if (!text2.EndsWith("_ragdoll") && !text2.EndsWith("_death") && !text2.EndsWith("_dead"))
			{
				return;
			}
			if (text2.Contains("seekerqueen"))
			{
				value = Kind.Queen;
			}
			else if (text2.Contains("seekerbrute"))
			{
				value = Kind.Soldier;
			}
			else if (text2.Contains("seekerbrood"))
			{
				value = Kind.Brood;
			}
			else if (text2.Contains("seeker"))
			{
				value = Kind.Seeker;
			}
			else if (text2.StartsWith("tick_"))
			{
				value = Kind.Tick;
			}
			else
			{
				if (!text2.StartsWith("gjall_"))
				{
					return;
				}
				value = Kind.Gjall;
			}
		}
		if (!IsEnabled(value))
		{
			return;
		}
		try
		{
			Attach(go, value, null, corpse: true);
		}
		catch (Exception ex)
		{
			WarnOnce("death-" + value, "Could not replace a death visual: " + ex);
		}
	}

	private void RememberDeathPrefabs(Component character, Kind kind)
	{
		FieldInfo fieldInfo = AccessTools.Field(characterType, "m_deathEffects");
		object obj = ((fieldInfo == null) ? null : fieldInfo.GetValue(character));
		if (obj == null)
		{
			return;
		}
		FieldInfo fieldInfo2 = AccessTools.Field(obj.GetType(), "m_effectPrefabs");
		IEnumerable enumerable = ((fieldInfo2 == null) ? null : (fieldInfo2.GetValue(obj) as IEnumerable));
		if (enumerable == null)
		{
			return;
		}
		foreach (object item in enumerable)
		{
			if (item == null)
			{
				continue;
			}
			FieldInfo fieldInfo3 = AccessTools.Field(item.GetType(), "m_prefab");
			GameObject val = (GameObject)((fieldInfo3 == null) ? null : /*isinst with value type is only supported in some contexts*/);
			if (!((Object)(object)val == (Object)null))
			{
				string text = CleanName(((Object)val).name);
				string text2 = text.ToLowerInvariant();
				if (text2.Contains("seeker") || text2.Contains("tick") || text2.Contains("gjall"))
				{
					deathNames[text] = kind;
				}
			}
		}
	}

	private void Attach(GameObject go, Kind kind, Component character, bool corpse)
	{
		//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)
		Scene scene = go.scene;
		if (!((Scene)(ref scene)).IsValid() || (Object)(object)go.GetComponent<ConstructVisual>() != (Object)null)
		{
			return;
		}
		ConstructVisual constructVisual = go.AddComponent<ConstructVisual>();
		try
		{
			if (!constructVisual.Initialize(kind, character, corpse))
			{
				constructVisual.Shutdown();
				Object.Destroy((Object)(object)constructVisual);
				return;
			}
			string item = (corpse ? "corpse-" : "live-ok-") + kind;
			if (logged.Add(item))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Visual replacement attached: " + ((Object)go).name + (corpse ? " (death effect)" : "")));
			}
		}
		catch
		{
			constructVisual.Shutdown();
			Object.Destroy((Object)(object)constructVisual);
			throw;
		}
	}

	private void Update()
	{
		if (!running || !ModEnabled.Value || Time.unscaledTime < nextScan)
		{
			return;
		}
		nextScan = Time.unscaledTime + 2f;
		try
		{
			Object[] array = Object.FindObjectsOfType(characterType);
			foreach (Object val in array)
			{
				TryLive((Component)(object)((val is Component) ? val : null));
			}
			if (!ReplaceDeathVisuals.Value || !(ragdollType != null))
			{
				return;
			}
			Object[] array2 = Object.FindObjectsOfType(ragdollType);
			foreach (Object val2 in array2)
			{
				Component val3 = (Component)(object)((val2 is Component) ? val2 : null);
				if ((Object)(object)val3 != (Object)null)
				{
					TryDeath(val3.gameObject);
				}
			}
		}
		catch (Exception ex)
		{
			WarnOnce("scan", "Fallback scan failed: " + ex.Message);
		}
	}

	internal void WarnOnce(string key, string text)
	{
		if (logged.Add("warning-" + key))
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)text);
		}
	}

	private void OnDestroy()
	{
		running = false;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		CuteSeekerVisual[] array = Object.FindObjectsOfType<CuteSeekerVisual>();
		foreach (CuteSeekerVisual cuteSeekerVisual in array)
		{
			cuteSeekerVisual.Shutdown();
			Object.Destroy((Object)(object)cuteSeekerVisual);
		}
		ConstructVisual[] array2 = Object.FindObjectsOfType<ConstructVisual>();
		foreach (ConstructVisual constructVisual in array2)
		{
			constructVisual.Shutdown();
			Object.Destroy((Object)(object)constructVisual);
		}
		Geometry.Dispose();
		CuteSeekerAssets.Dispose();
		if ((Object)(object)Instance == (Object)(object)this)
		{
			Instance = null;
		}
	}
}
[DefaultExecutionOrder(10000)]
public sealed class ConstructVisual : MonoBehaviour
{
	private Kind kind;

	private Component character;

	private bool corpse;

	private bool initialized;

	private GameObject display;

	private Transform body;

	private Transform visualAnchor;

	private Animator animator;

	private AnimatorCullingMode oldCulling;

	private bool changedCulling;

	private MethodInfo inAttack;

	private Vector3 baseCenter;

	private Vector3 baseSize;

	private float phase;

	private float age;

	private float attack;

	private float nextCapture;

	private float nextAttackRead;

	private bool attacking;

	private readonly Dictionary<Renderer, bool> originals = new Dictionary<Renderer, bool>();

	private readonly List<Renderer> replacements = new List<Renderer>();

	internal bool Initialize(Kind creatureKind, Component liveCharacter, bool isCorpse)
	{
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Expected O, but got Unknown
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		kind = creatureKind;
		character = liveCharacter;
		corpse = isCorpse;
		CaptureSources();
		if (originals.Count == 0)
		{
			return false;
		}
		Material source = null;
		foreach (Renderer key in originals.Keys)
		{
			if ((Object)(object)key != (Object)null && (Object)(object)key.sharedMaterial != (Object)null)
			{
				source = key.sharedMaterial;
				break;
			}
		}
		Geometry.Ensure(source);
		Measure();
		display = new GameObject("__MNB_Visual");
		display.transform.SetParent(((Component)this).transform, false);
		display.transform.localPosition = baseCenter;
		display.transform.localScale = baseSize;
		display.layer = 0;
		body = new GameObject("Construct").transform;
		body.SetParent(display.transform, false);
		BuildAppearance();
		replacements.AddRange(display.GetComponentsInChildren<Renderer>(true));
		if ((Object)(object)character != (Object)null)
		{
			animator = character.GetComponentInChildren<Animator>(true);
			if ((Object)(object)animator != (Object)null)
			{
				oldCulling = animator.cullingMode;
				animator.cullingMode = (AnimatorCullingMode)0;
				changedCulling = true;
			}
			FieldInfo fieldInfo = AccessTools.Field(((object)character).GetType(), "m_visual");
			object obj = ((fieldInfo == null) ? null : fieldInfo.GetValue(character));
			GameObject val = (GameObject)((obj is GameObject) ? obj : null);
			Component val2 = (Component)((obj is Component) ? obj : null);
			visualAnchor = (((Object)(object)val != (Object)null) ? val.transform : (((Object)(object)val2 != (Object)null) ? val2.transform : null));
			inAttack = AccessTools.Method(((object)character).GetType(), "InAttack", Type.EmptyTypes, (Type[])null);
			if (inAttack != null && inAttack.ReturnType != typeof(bool))
			{
				inAttack = null;
			}
		}
		phase = (float)(((Object)this).GetInstanceID() & 0x3FF) * 0.031f;
		initialized = true;
		ApplyVisibility();
		return true;
	}

	private void CaptureSources()
	{
		Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val in componentsInChildren)
		{
			if (!((Object)(object)display != (Object)null) || !((Component)val).transform.IsChildOf(display.transform))
			{
				bool flag = val is MeshRenderer || val is SkinnedMeshRenderer;
				if (corpse && ((object)val).GetType().Name == "ParticleSystemRenderer")
				{
					flag = true;
				}
				if (flag && !originals.ContainsKey(val))
				{
					originals.Add(val, val.forceRenderingOff);
				}
			}
		}
	}

	private void Measure()
	{
		//IL_008d: 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_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_027c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0290: Unknown result type (might be due to invalid IL or missing references)
		//IL_0295: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		CapsuleCollider component = ((Component)this).GetComponent<CapsuleCollider>();
		if (!corpse && (Object)(object)component != (Object)null)
		{
			float num = Mathf.Max(0.2f, component.radius * 2f);
			float num2 = Mathf.Max(num, component.height);
			baseCenter = component.center;
			baseSize = new Vector3(num, num2, num);
			if (component.direction == 0)
			{
				baseSize = new Vector3(num2, num, num);
			}
			if (component.direction == 2)
			{
				baseSize = new Vector3(num, num, num2);
			}
		}
		else
		{
			Bounds val = default(Bounds);
			((Bounds)(ref val))..ctor(Vector3.zero, Vector3.one);
			bool flag = false;
			foreach (Renderer key in originals.Keys)
			{
				if ((Object)(object)key == (Object)null || (!(key is MeshRenderer) && !(key is SkinnedMeshRenderer)))
				{
					continue;
				}
				Bounds bounds = key.bounds;
				for (int i = 0; i < 8; i++)
				{
					Vector3 val2 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((i & 1) != 0) ? 1 : (-1)), (float)(((i & 2) != 0) ? 1 : (-1)), (float)(((i & 4) != 0) ? 1 : (-1))));
					Vector3 val3 = ((Component)this).transform.InverseTransformPoint(val2);
					if (!flag)
					{
						val = new Bounds(val3, Vector3.zero);
						flag = true;
					}
					else
					{
						((Bounds)(ref val)).Encapsulate(val3);
					}
				}
			}
			baseCenter = ((Bounds)(ref val)).center;
			baseSize = ((Bounds)(ref val)).size;
			if (corpse)
			{
				float num3 = Mathf.Clamp(Mathf.Max(new float[3] { baseSize.x, baseSize.y, baseSize.z }) * 0.45f, 0.35f, 4f);
				baseSize = Vector3.one * num3;
			}
		}
		baseSize.x = Mathf.Clamp(baseSize.x, 0.15f, 30f);
		baseSize.y = Mathf.Clamp(baseSize.y, 0.15f, 30f);
		baseSize.z = Mathf.Clamp(baseSize.z, 0.15f, 30f);
		baseSize *= Plugin.Instance.VisualScale.Value;
	}

	private void Part(string name, bool cube, Vector3 position, Vector3 size, Material material)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_0026: 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)
		GameObject val = new GameObject(name);
		val.layer = 0;
		val.transform.SetParent(body, false);
		val.transform.localPosition = position;
		val.transform.localScale = size;
		val.AddComponent<MeshFilter>().sharedMesh = (cube ? Geometry.Cube : Geometry.Diamond);
		MeshRenderer val2 = val.AddComponent<MeshRenderer>();
		((Renderer)val2).sharedMaterial = material;
		((Renderer)val2).shadowCastingMode = (ShadowCastingMode)1;
		((Renderer)val2).receiveShadows = true;
	}

	private void BuildAppearance()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: 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_0066: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		Material material = Geometry.ForKind(kind);
		if (corpse)
		{
			Part("Fading crystal", cube: false, Vector3.zero, Vector3.one, material);
			return;
		}
		bool flag = kind == Kind.Soldier || kind == Kind.Tick || kind == Kind.Gjall;
		Part("Body", flag, Vector3.zero, new Vector3(0.9f, 0.85f, 0.9f), material);
		float num = (flag ? 0.459f : 0.305f);
		Part("Left eye", cube: true, new Vector3(-0.1f, 0.08f, num), new Vector3(0.11f, 0.07f, 0.045f), Geometry.Pale);
		Part("Right eye", cube: true, new Vector3(0.1f, 0.08f, num), new Vector3(0.11f, 0.07f, 0.045f), Geometry.Pale);
		if (kind == Kind.Soldier)
		{
			Part("Left block", cube: true, new Vector3(-0.47f, 0.05f, 0f), new Vector3(0.2f, 0.36f, 0.5f), Geometry.Dark);
			Part("Right block", cube: true, new Vector3(0.47f, 0.05f, 0f), new Vector3(0.2f, 0.36f, 0.5f), Geometry.Dark);
		}
		if (kind == Kind.Queen)
		{
			for (int i = -1; i <= 1; i++)
			{
				Part("Crown " + i, cube: false, new Vector3((float)i * 0.23f, 0.47f, 0f), new Vector3(0.15f, 0.23f, 0.15f), Geometry.Gold);
			}
		}
	}

	private void ApplyVisibility()
	{
		bool flag = (Object)(object)Plugin.Instance != (Object)null && Plugin.Instance.IsEnabled(kind);
		bool flag2 = false;
		foreach (KeyValuePair<Renderer, bool> original in originals)
		{
			Renderer key = original.Key;
			if (!((Object)(object)key == (Object)null))
			{
				if (key.enabled && ((Component)key).gameObject.activeInHierarchy && !original.Value)
				{
					flag2 = true;
				}
				key.forceRenderingOff = flag || original.Value;
			}
		}
		if ((Object)(object)visualAnchor != (Object)null && !((Component)visualAnchor).gameObject.activeInHierarchy)
		{
			flag2 = false;
		}
		bool enabled = flag && flag2 && (!corpse || age < 1.15f);
		foreach (Renderer replacement in replacements)
		{
			if ((Object)(object)replacement != (Object)null)
			{
				replacement.enabled = enabled;
			}
		}
	}

	private void LateUpdate()
	{
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		if (!initialized || (Object)(object)display == (Object)null)
		{
			return;
		}
		try
		{
			age += Time.deltaTime;
			if (Time.unscaledTime >= nextCapture)
			{
				nextCapture = Time.unscaledTime + 0.75f;
				CaptureSources();
			}
			ApplyVisibility();
			if (corpse)
			{
				float num = Mathf.Clamp01(1f - age / 1.15f);
				display.transform.localScale = baseSize * Mathf.Max(0.001f, num);
			}
			else
			{
				if ((Object)(object)Plugin.Instance == (Object)null || !Plugin.Instance.Animate.Value)
				{
					return;
				}
				if ((Object)(object)character != (Object)null && inAttack != null && Time.unscaledTime >= nextAttackRead)
				{
					nextAttackRead = Time.unscaledTime + 0.08f;
					try
					{
						attacking = (bool)inAttack.Invoke(character, null);
					}
					catch
					{
						inAttack = null;
						attacking = false;
					}
				}
				attack = Mathf.MoveTowards(attack, attacking ? 1f : 0f, Time.deltaTime * 8f);
				display.transform.localPosition = baseCenter + Vector3.up * (Mathf.Sin(Time.time * 2.2f + phase) * baseSize.y * 0.02f);
				body.localRotation = Quaternion.Euler(attack * 12f, 0f, 0f);
			}
		}
		catch (Exception ex)
		{
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				Plugin.Instance.WarnOnce("visual-" + kind, "Visual update failed; restoring original rendering rather than leaving an invisible attacker: " + ex.Message);
			}
			Shutdown();
			((Behaviour)this).enabled = false;
		}
	}

	internal void Shutdown()
	{
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		initialized = false;
		foreach (KeyValuePair<Renderer, bool> original in originals)
		{
			if ((Object)(object)original.Key != (Object)null)
			{
				original.Key.forceRenderingOff = original.Value;
			}
		}
		originals.Clear();
		if (changedCulling && (Object)(object)animator != (Object)null)
		{
			animator.cullingMode = oldCulling;
		}
		changedCulling = false;
		if ((Object)(object)display != (Object)null)
		{
			display.SetActive(false);
			Object.Destroy((Object)(object)display);
			display = null;
		}
	}

	private void OnDestroy()
	{
		if (corpse)
		{
			originals.Clear();
		}
		Shutdown();
	}
}
internal static class Geometry
{
	internal static Mesh Cube;

	internal static Mesh Diamond;

	internal static Material Pale;

	internal static Material Dark;

	internal static Material Gold;

	private static readonly Dictionary<Kind, Material> colors = new Dictionary<Kind, Material>();

	private static Shader shader;

	private static Material template;

	internal static void Ensure(Material source)
	{
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: 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_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)Cube != (Object)null) || !((Object)(object)Diamond != (Object)null) || colors.Count != 6)
		{
			if ((Object)(object)Cube != (Object)null || (Object)(object)Diamond != (Object)null || colors.Count != 0)
			{
				Dispose();
			}
			shader = Shader.Find("Standard");
			if ((Object)(object)shader == (Object)null)
			{
				shader = Shader.Find("Legacy Shaders/Diffuse");
			}
			if ((Object)(object)shader == (Object)null && (Object)(object)source != (Object)null)
			{
				shader = source.shader;
				template = source;
			}
			if ((Object)(object)shader == (Object)null || !shader.isSupported)
			{
				throw new InvalidOperationException("No supported world shader is available. Original visuals were left intact.");
			}
			Cube = MakeCube();
			Diamond = MakeDiamond();
			Pale = MaterialFor(new Color(0.9f, 0.95f, 1f));
			Dark = MaterialFor(new Color(0.19f, 0.23f, 0.27f));
			Gold = MaterialFor(new Color(0.92f, 0.67f, 0.23f));
			colors[Kind.Seeker] = MaterialFor(new Color(0.23f, 0.57f, 0.8f));
			colors[Kind.Soldier] = MaterialFor(new Color(0.5f, 0.54f, 0.58f));
			colors[Kind.Brood] = MaterialFor(new Color(0.32f, 0.76f, 0.65f));
			colors[Kind.Tick] = MaterialFor(new Color(0.92f, 0.53f, 0.2f));
			colors[Kind.Queen] = MaterialFor(new Color(0.62f, 0.39f, 0.78f));
			colors[Kind.Gjall] = MaterialFor(new Color(0.55f, 0.59f, 0.65f));
		}
	}

	internal static Material ForKind(Kind kind)
	{
		return colors[kind];
	}

	private static Material MaterialFor(Color color)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		Material val = (((Object)(object)template != (Object)null) ? new Material(template) : new Material(shader));
		((Object)val).name = "MNB opaque solid";
		if (val.HasProperty("_MainTex"))
		{
			val.SetTexture("_MainTex", (Texture)(object)Texture2D.whiteTexture);
		}
		if (val.HasProperty("_BaseMap"))
		{
			val.SetTexture("_BaseMap", (Texture)(object)Texture2D.whiteTexture);
		}
		string[] array = new string[6] { "_BumpMap", "_MetallicGlossMap", "_OcclusionMap", "_EmissionMap", "_DetailAlbedoMap", "_DetailNormalMap" };
		foreach (string text in array)
		{
			if (val.HasProperty(text))
			{
				val.SetTexture(text, (Texture)null);
			}
		}
		if (val.HasProperty("_Color"))
		{
			val.SetColor("_Color", color);
		}
		if (val.HasProperty("_BaseColor"))
		{
			val.SetColor("_BaseColor", color);
		}
		if (val.HasProperty("_Glossiness"))
		{
			val.SetFloat("_Glossiness", 0.15f);
		}
		if (val.HasProperty("_Metallic"))
		{
			val.SetFloat("_Metallic", 0f);
		}
		val.DisableKeyword("_NORMALMAP");
		val.DisableKeyword("_EMISSION");
		val.DisableKeyword("_ALPHATEST_ON");
		val.DisableKeyword("_ALPHABLEND_ON");
		val.DisableKeyword("_ALPHAPREMULTIPLY_ON");
		if (val.HasProperty("_Mode"))
		{
			val.SetFloat("_Mode", 0f);
		}
		if (val.HasProperty("_SrcBlend"))
		{
			val.SetFloat("_SrcBlend", 1f);
		}
		if (val.HasProperty("_DstBlend"))
		{
			val.SetFloat("_DstBlend", 0f);
		}
		if (val.HasProperty("_ZWrite"))
		{
			val.SetFloat("_ZWrite", 1f);
		}
		val.renderQueue = -1;
		return val;
	}

	private static Mesh FromFaces(string name, Vector3[] points, int[][] faces)
	{
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Expected O, but got Unknown
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		List<Vector3> list = new List<Vector3>();
		List<int> list2 = new List<int>();
		List<Vector2> list3 = new List<Vector2>();
		foreach (int[] array in faces)
		{
			int count = list.Count;
			for (int j = 0; j < array.Length; j++)
			{
				list.Add(points[array[j]]);
				list3.Add(new Vector2((float)((j == 1 || j == 2) ? 1 : 0), (float)((j >= 2) ? 1 : 0)));
			}
			for (int k = 1; k < array.Length - 1; k++)
			{
				list2.Add(count);
				list2.Add(count + k);
				list2.Add(count + k + 1);
			}
		}
		Mesh val = new Mesh();
		((Object)val).name = name;
		val.vertices = list.ToArray();
		val.triangles = list2.ToArray();
		val.uv = list3.ToArray();
		val.RecalculateNormals();
		val.RecalculateBounds();
		return val;
	}

	private static Mesh MakeCube()
	{
		//IL_001d: 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)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: 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_007d: 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_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		Vector3[] points = (Vector3[])(object)new Vector3[8]
		{
			new Vector3(-0.5f, -0.5f, -0.5f),
			new Vector3(0.5f, -0.5f, -0.5f),
			new Vector3(0.5f, 0.5f, -0.5f),
			new Vector3(-0.5f, 0.5f, -0.5f),
			new Vector3(-0.5f, -0.5f, 0.5f),
			new Vector3(0.5f, -0.5f, 0.5f),
			new Vector3(0.5f, 0.5f, 0.5f),
			new Vector3(-0.5f, 0.5f, 0.5f)
		};
		return FromFaces("MNB Cube", points, new int[6][]
		{
			new int[4] { 0, 3, 2, 1 },
			new int[4] { 4, 5, 6, 7 },
			new int[4] { 0, 4, 7, 3 },
			new int[4] { 1, 2, 6, 5 },
			new int[4] { 3, 7, 6, 2 },
			new int[4] { 0, 1, 5, 4 }
		});
	}

	private static Mesh MakeDiamond()
	{
		//IL_001d: 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)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: 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_007d: 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_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		Vector3[] points = (Vector3[])(object)new Vector3[6]
		{
			new Vector3(0f, 0.5f, 0f),
			new Vector3(0f, -0.5f, 0f),
			new Vector3(0.5f, 0f, 0f),
			new Vector3(0f, 0f, 0.5f),
			new Vector3(-0.5f, 0f, 0f),
			new Vector3(0f, 0f, -0.5f)
		};
		return FromFaces("MNB Crystal", points, new int[8][]
		{
			new int[3] { 0, 3, 2 },
			new int[3] { 0, 4, 3 },
			new int[3] { 0, 5, 4 },
			new int[3] { 0, 2, 5 },
			new int[3] { 1, 2, 3 },
			new int[3] { 1, 3, 4 },
			new int[3] { 1, 4, 5 },
			new int[3] { 1, 5, 2 }
		});
	}

	internal static void Dispose()
	{
		foreach (Material value in colors.Values)
		{
			if ((Object)(object)value != (Object)null)
			{
				Object.Destroy((Object)(object)value);
			}
		}
		colors.Clear();
		if ((Object)(object)Pale != (Object)null)
		{
			Object.Destroy((Object)(object)Pale);
		}
		if ((Object)(object)Dark != (Object)null)
		{
			Object.Destroy((Object)(object)Dark);
		}
		if ((Object)(object)Gold != (Object)null)
		{
			Object.Destroy((Object)(object)Gold);
		}
		if ((Object)(object)Cube != (Object)null)
		{
			Object.Destroy((Object)(object)Cube);
		}
		if ((Object)(object)Diamond != (Object)null)
		{
			Object.Destroy((Object)(object)Diamond);
		}
		Cube = null;
		Diamond = null;
		Pale = null;
		Dark = null;
		Gold = null;
		shader = null;
		template = null;
	}
}
public sealed class CuteSeekerVisual : MonoBehaviour
{
	private SkinnedMeshRenderer target;

	private Mesh originalMesh;

	private Material[] originalMaterials;

	private Bounds originalBounds;

	private Mesh replacement;

	private Material[] materials;

	private bool initialized;

	private float nextMaterialCheck;

	private SkinnedMeshRenderer queenDetails;

	private bool originalDetailsHidden;

	internal bool Initialize(Kind kind)
	{
		//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_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		CuteSeekerAsset cuteSeekerAsset = CuteSeekerAssets.ForKind(kind);
		SkinnedMeshRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>(true);
		SkinnedMeshRenderer val = null;
		if (kind == Kind.Queen)
		{
			int num = 0;
			int num2 = 0;
			SkinnedMeshRenderer[] array = componentsInChildren;
			foreach (SkinnedMeshRenderer val2 in array)
			{
				if (((Object)val2).name == "Cube")
				{
					num++;
				}
				if (((Object)val2).name == "Plane")
				{
					val = val2;
					num2++;
				}
			}
			if (num != 1 || num2 != 1 || (Object)(object)val.sharedMesh == (Object)null || !cuteSeekerAsset.Matches(val))
			{
				return false;
			}
			cuteSeekerAsset.ValidateBindposes(val.sharedMesh);
		}
		SkinnedMeshRenderer[] array2 = componentsInChildren;
		foreach (SkinnedMeshRenderer val3 in array2)
		{
			if ((kind != Kind.Queen || !(((Object)val3).name != "Cube")) && !((Object)(object)val3.sharedMesh == (Object)null) && cuteSeekerAsset.Matches(val3))
			{
				Mesh val4 = cuteSeekerAsset.ForRenderer(val3);
				Material[] array3 = cuteSeekerAsset.Materials(((Renderer)val3).sharedMaterial);
				target = val3;
				originalMesh = val3.sharedMesh;
				originalMaterials = ((Renderer)val3).sharedMaterials;
				originalBounds = ((Renderer)val3).localBounds;
				replacement = val4;
				materials = array3;
				Bounds localBounds = originalBounds;
				Bounds bounds = val4.bounds;
				((Bounds)(ref localBounds)).Encapsulate(((Bounds)(ref bounds)).min);
				Bounds bounds2 = val4.bounds;
				((Bounds)(ref localBounds)).Encapsulate(((Bounds)(ref bounds2)).max);
				((Bounds)(ref localBounds)).Expand(0.012f);
				target.sharedMesh = replacement;
				((Renderer)target).sharedMaterials = materials;
				((Renderer)target).localBounds = localBounds;
				if ((Object)(object)val != (Object)null)
				{
					queenDetails = val;
					originalDetailsHidden = ((Renderer)val).forceRenderingOff;
					((Renderer)val).forceRenderingOff = true;
				}
				initialized = true;
				return true;
			}
		}
		return false;
	}

	private void LateUpdate()
	{
		if (initialized && !((Object)(object)target == (Object)null) && !(Time.unscaledTime < nextMaterialCheck))
		{
			nextMaterialCheck = Time.unscaledTime + 0.5f;
			if ((Object)(object)target.sharedMesh == (Object)(object)replacement && ((Renderer)target).sharedMaterials.Length != materials.Length)
			{
				((Renderer)target).sharedMaterials = materials;
			}
			if ((Object)(object)queenDetails != (Object)null)
			{
				((Renderer)queenDetails).forceRenderingOff = true;
			}
		}
	}

	internal void Shutdown()
	{
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)target != (Object)null && (Object)(object)originalMesh != (Object)null && (Object)(object)target.sharedMesh == (Object)(object)replacement)
		{
			target.sharedMesh = originalMesh;
			((Renderer)target).sharedMaterials = originalMaterials;
			((Renderer)target).localBounds = originalBounds;
		}
		if ((Object)(object)queenDetails != (Object)null)
		{
			((Renderer)queenDetails).forceRenderingOff = originalDetailsHidden;
		}
		queenDetails = null;
		initialized = false;
		target = null;
	}

	private void OnDestroy()
	{
		Shutdown();
	}
}
internal sealed class CuteSeekerAsset
{
	private readonly string resource;

	private readonly string label;

	private string[] names;

	private Matrix4x4[] expectedBindposes;

	private Vector3[] vertices;

	private Vector3[] normals;

	private BoneWeight[] weights;

	private int[][] submeshes;

	private Color[] colors;

	private float[] metallic;

	private float[] roughness;

	private float[] emission;

	private Material[] sharedMaterials;

	private readonly Dictionary<Mesh, Mesh> meshes = new Dictionary<Mesh, Mesh>();

	internal CuteSeekerAsset(string resource, string label)
	{
		this.resource = resource;
		this.label = label;
	}

	private int Count(BinaryReader reader, int max)
	{
		int num = reader.ReadInt32();
		if (num < 1 || num > max)
		{
			throw new InvalidDataException("cute creature asset count is invalid.");
		}
		return num;
	}

	private void Load()
	{
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_027c: Unknown result type (might be due to invalid IL or missing references)
		//IL_027e: Unknown result type (might be due to invalid IL or missing references)
		if (names != null)
		{
			return;
		}
		using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource);
		if (stream == null)
		{
			throw new FileNotFoundException("The embedded " + label + " mesh is missing.");
		}
		using BinaryReader binaryReader = new BinaryReader(stream);
		if (binaryReader.ReadInt32() != 826429005)
		{
			throw new InvalidDataException("Unsupported cute creature asset.");
		}
		int num = Count(binaryReader, 256);
		string[] array = new string[num];
		Matrix4x4[] array2 = (Matrix4x4[])(object)new Matrix4x4[num];
		for (int i = 0; i < num; i++)
		{
			array[i] = binaryReader.ReadString();
			for (int j = 0; j < 4; j++)
			{
				for (int k = 0; k < 4; k++)
				{
					((Matrix4x4)(ref array2[i]))[j, k] = binaryReader.ReadSingle();
				}
			}
		}
		int num2 = Count(binaryReader, 32);
		colors = (Color[])(object)new Color[num2];
		metallic = new float[num2];
		roughness = new float[num2];
		emission = new float[num2];
		for (int l = 0; l < num2; l++)
		{
			ref Color reference = ref colors[l];
			reference = new Color(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), 1f);
			metallic[l] = binaryReader.ReadSingle();
			roughness[l] = binaryReader.ReadSingle();
			emission[l] = binaryReader.ReadSingle();
		}
		int num3 = Count(binaryReader, 60000);
		vertices = (Vector3[])(object)new Vector3[num3];
		normals = (Vector3[])(object)new Vector3[num3];
		weights = (BoneWeight[])(object)new BoneWeight[num3];
		for (int m = 0; m < num3; m++)
		{
			ref Vector3 reference2 = ref vertices[m];
			reference2 = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
			ref Vector3 reference3 = ref normals[m];
			reference3 = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
			BoneWeight val = default(BoneWeight);
			((BoneWeight)(ref val)).boneIndex0 = binaryReader.ReadInt32();
			((BoneWeight)(ref val)).boneIndex1 = binaryReader.ReadInt32();
			((BoneWeight)(ref val)).boneIndex2 = binaryReader.ReadInt32();
			((BoneWeight)(ref val)).boneIndex3 = binaryReader.ReadInt32();
			((BoneWeight)(ref val)).weight0 = binaryReader.ReadSingle();
			((BoneWeight)(ref val)).weight1 = binaryReader.ReadSingle();
			((BoneWeight)(ref val)).weight2 = binaryReader.ReadSingle();
			((BoneWeight)(ref val)).weight3 = binaryReader.ReadSingle();
			weights[m] = val;
		}
		submeshes = new int[num2][];
		for (int n = 0; n < num2; n++)
		{
			int num4 = Count(binaryReader, 300000);
			if (num4 % 3 != 0)
			{
				throw new InvalidDataException("Invalid triangle count.");
			}
			submeshes[n] = new int[num4];
			for (int num5 = 0; num5 < num4; num5++)
			{
				int num6 = binaryReader.ReadInt32();
				if (num6 < 0 || num6 >= num3)
				{
					throw new InvalidDataException("Invalid vertex index.");
				}
				submeshes[n][num5] = num6;
			}
		}
		if (stream.Position != stream.Length)
		{
			throw new InvalidDataException("Unexpected mesh payload length.");
		}
		expectedBindposes = array2;
		names = array;
	}

	internal bool Matches(SkinnedMeshRenderer renderer)
	{
		Load();
		Transform[] bones = renderer.bones;
		if (bones.Length != names.Length || renderer.sharedMesh.bindposes.Length != names.Length)
		{
			return false;
		}
		for (int i = 0; i < bones.Length; i++)
		{
			if ((Object)(object)bones[i] == (Object)null || ((Object)bones[i]).name != names[i])
			{
				return false;
			}
		}
		return true;
	}

	internal void ValidateBindposes(Mesh source)
	{
		Load();
		Matrix4x4[] bindposes = source.bindposes;
		if (bindposes.Length != names.Length)
		{
			throw new InvalidOperationException("Unexpected skeleton bind count.");
		}
		for (int i = 0; i < bindposes.Length; i++)
		{
			for (int j = 0; j < 4; j++)
			{
				for (int k = 0; k < 4; k++)
				{
					if (Mathf.Abs(((Matrix4x4)(ref bindposes[i]))[j, k] - ((Matrix4x4)(ref expectedBindposes[i]))[j, k]) > 0.0005f)
					{
						throw new InvalidOperationException("The installed " + label + " rig differs from the modeled rig. Using the crystal fallback.");
					}
				}
			}
		}
	}

	internal Mesh ForRenderer(SkinnedMeshRenderer renderer)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Expected O, but got Unknown
		Mesh sharedMesh = renderer.sharedMesh;
		if (meshes.TryGetValue(sharedMesh, out var value))
		{
			return value;
		}
		Matrix4x4[] bindposes = sharedMesh.bindposes;
		ValidateBindposes(sharedMesh);
		value = new Mesh();
		try
		{
			((Object)value).name = "MNB Cute " + label + " authored mesh";
			value.vertices = vertices;
			value.normals = normals;
			value.uv = (Vector2[])(object)new Vector2[vertices.Length];
			value.boneWeights = weights;
			value.bindposes = bindposes;
			value.subMeshCount = submeshes.Length;
			for (int i = 0; i < submeshes.Length; i++)
			{
				value.SetTriangles(submeshes[i], i);
			}
			value.RecalculateBounds();
			meshes.Add(sharedMesh, value);
			return value;
		}
		catch
		{
			Object.Destroy((Object)(object)value);
			throw;
		}
	}

	internal Material[] Materials(Material source)
	{
		//IL_007f: 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_0086: Expected O, but got Unknown
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0312: Unknown result type (might be due to invalid IL or missing references)
		//IL_031f: Unknown result type (might be due to invalid IL or missing references)
		if (sharedMaterials != null)
		{
			return sharedMaterials;
		}
		Shader val = Shader.Find("Standard");
		bool flag = false;
		if ((Object)(object)val == (Object)null || !val.isSupported)
		{
			val = (((Object)(object)source == (Object)null) ? null : source.shader);
			flag = true;
		}
		if ((Object)(object)val == (Object)null || !val.isSupported)
		{
			throw new InvalidOperationException("No supported cute creature material shader.");
		}
		Material[] array = (Material[])(object)new Material[colors.Length];
		try
		{
			for (int i = 0; i < colors.Length; i++)
			{
				Material val2 = (array[i] = (flag ? new Material(source) : new Material(val)));
				((Object)val2).name = "MNB Cute " + label + " material " + i;
				string[] array2 = new string[2] { "_MainTex", "_BaseMap" };
				foreach (string text in array2)
				{
					if (val2.HasProperty(text))
					{
						val2.SetTexture(text, (Texture)(object)Texture2D.whiteTexture);
					}
				}
				string[] array3 = new string[6] { "_BumpMap", "_MetallicGlossMap", "_OcclusionMap", "_EmissionMap", "_DetailAlbedoMap", "_DetailNormalMap" };
				foreach (string text2 in array3)
				{
					if (val2.HasProperty(text2))
					{
						val2.SetTexture(text2, (Texture)null);
					}
				}
				Color gamma = ((Color)(ref colors[i])).gamma;
				if (val2.HasProperty("_Color"))
				{
					val2.SetColor("_Color", gamma);
				}
				if (val2.HasProperty("_BaseColor"))
				{
					val2.SetColor("_BaseColor", gamma);
				}
				if (val2.HasProperty("_Glossiness"))
				{
					val2.SetFloat("_Glossiness", 1f - roughness[i]);
				}
				if (val2.HasProperty("_Metallic"))
				{
					val2.SetFloat("_Metallic", metallic[i]);
				}
				val2.DisableKeyword("_NORMALMAP");
				val2.DisableKeyword("_METALLICGLOSSMAP");
				val2.DisableKeyword("_ALPHATEST_ON");
				val2.DisableKeyword("_ALPHABLEND_ON");
				val2.DisableKeyword("_ALPHAPREMULTIPLY_ON");
				if (val2.HasProperty("_Mode"))
				{
					val2.SetFloat("_Mode", 0f);
				}
				if (val2.HasProperty("_SrcBlend"))
				{
					val2.SetFloat("_SrcBlend", 1f);
				}
				if (val2.HasProperty("_DstBlend"))
				{
					val2.SetFloat("_DstBlend", 0f);
				}
				if (val2.HasProperty("_ZWrite"))
				{
					val2.SetFloat("_ZWrite", 1f);
				}
				if (emission[i] > 0f && val2.HasProperty("_EmissionColor"))
				{
					val2.EnableKeyword("_EMISSION");
					val2.SetColor("_EmissionColor", colors[i] * emission[i]);
				}
				else
				{
					val2.DisableKeyword("_EMISSION");
				}
				val2.renderQueue = -1;
			}
			sharedMaterials = array;
			return array;
		}
		catch
		{
			Material[] array4 = array;
			foreach (Material val3 in array4)
			{
				if ((Object)(object)val3 != (Object)null)
				{
					Object.Destroy((Object)(object)val3);
				}
			}
			throw;
		}
	}

	internal void Dispose()
	{
		foreach (Mesh value in meshes.Values)
		{
			if ((Object)(object)value != (Object)null)
			{
				Object.Destroy((Object)(object)value);
			}
		}
		meshes.Clear();
		if (sharedMaterials != null)
		{
			Material[] array = sharedMaterials;
			foreach (Material val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}
		sharedMaterials = null;
	}
}
internal static class CuteSeekerAssets
{
	private static readonly CuteSeekerAsset seeker = new CuteSeekerAsset("MistlandsNoBugs.CuteSeeker.mesh", "Seeker");

	private static readonly CuteSeekerAsset brood = new CuteSeekerAsset("MistlandsNoBugs.CuteBrood.mesh", "Brood");

	private static readonly CuteSeekerAsset soldier = new CuteSeekerAsset("MistlandsNoBugs.CuteSoldier.mesh", "Soldier");

	private static readonly CuteSeekerAsset tick = new CuteSeekerAsset("MistlandsNoBugs.CuteTick.mesh", "Tick");

	private static readonly CuteSeekerAsset queen = new CuteSeekerAsset("MistlandsNoBugs.CuteQueen.mesh", "Queen");

	internal static CuteSeekerAsset ForKind(Kind kind)
	{
		return kind switch
		{
			Kind.Seeker => seeker, 
			Kind.Brood => brood, 
			Kind.Soldier => soldier, 
			Kind.Tick => tick, 
			Kind.Queen => queen, 
			_ => throw new ArgumentOutOfRangeException("kind"), 
		};
	}

	internal static void Dispose()
	{
		seeker.Dispose();
		brood.Dispose();
		soldier.Dispose();
		tick.Dispose();
		queen.Dispose();
	}
}