Decompiled source of Bestiary v1.0.1

plugins/AuraiFieldGuide/AuraiFieldGuide.dll

Decompiled 13 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("1.0.1.0")]
namespace AuraiFieldGuide;

internal static class EnemyFilter
{
	internal static bool TryClassify(Character player, Character actor, out bool enemy)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Invalid comparison between Unknown and I4
		//IL_0027: 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_008e: Unknown result type (might be due to invalid IL or missing references)
		enemy = false;
		if (!Plugin.Local(player) || !Plugin.Creature(actor))
		{
			return false;
		}
		if ((int)actor.Faction == 0 || (int)actor.Faction == 7 || actor.Faction == player.Faction || actor.QuestNonTargetable)
		{
			return true;
		}
		TargetingSystem targetingSystem = player.TargetingSystem;
		if (!Object.op_Implicit((Object)(object)targetingSystem) || targetingSystem.TargetableFactions == null)
		{
			return false;
		}
		if (!targetingSystem.IsTargetable(actor))
		{
			return true;
		}
		TargetingSystem targetingSystem2 = actor.TargetingSystem;
		if (Object.op_Implicit((Object)(object)targetingSystem2) && targetingSystem2.TargetableFactions != null && (actor.IsAI || targetingSystem2.TargetableFactions.Length > 0) && !targetingSystem2.IsTargetable(player.Faction))
		{
			return true;
		}
		if (!actor.IsAI)
		{
			NPCInteraction componentInChildren = ((Component)actor).GetComponentInChildren<NPCInteraction>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren) && ((Behaviour)componentInChildren).enabled)
			{
				return true;
			}
		}
		enemy = true;
		return true;
	}

	internal static bool IsEnemy(Character player, Character actor)
	{
		if (TryClassify(player, actor, out var enemy))
		{
			return enemy;
		}
		return false;
	}
}
[Serializable]
public sealed class GuideBook
{
	public int Schema = 3;

	public string CharacterId = "";

	public List<CreatureEntry> Creatures = new List<CreatureEntry>();

	public List<string> Receipts = new List<string>();

	[NonSerialized]
	public bool Dirty;

	[NonSerialized]
	public int Revision;

	public CreatureEntry Find(string key)
	{
		return Creatures.Find((CreatureEntry e) => e.Key == key);
	}

	public CreatureEntry Discover(string key, string name, string family, string area)
	{
		if (string.IsNullOrEmpty(key))
		{
			throw new ArgumentException("Missing creature identity");
		}
		CreatureEntry creatureEntry = Find(key);
		if (creatureEntry == null)
		{
			CreatureEntry creatureEntry2 = new CreatureEntry();
			creatureEntry2.Key = key;
			creatureEntry2.Name = Clean(name, 100);
			creatureEntry2.Family = Clean(family, 80);
			creatureEntry2.FirstSeen = DateTime.UtcNow.ToString("yyyy-MM-dd");
			creatureEntry = creatureEntry2;
			Creatures.Add(creatureEntry);
			Touch();
		}
		if (!string.IsNullOrEmpty(area) && creatureEntry.LastArea != area)
		{
			creatureEntry.LastArea = Clean(area, 120);
			Touch();
		}
		return creatureEntry;
	}

	public void Touch()
	{
		Dirty = true;
		Revision++;
	}

	public void ConfirmEnemy(CreatureEntry entry)
	{
		if (entry != null && (!entry.EnemyConfirmed || entry.HiddenNonEnemy))
		{
			entry.EnemyConfirmed = true;
			entry.HiddenNonEnemy = false;
			Touch();
		}
	}

	public void HideNonEnemy(string key)
	{
		CreatureEntry creatureEntry = Find(key);
		if (creatureEntry != null && !creatureEntry.EnemyConfirmed && !creatureEntry.HiddenNonEnemy)
		{
			creatureEntry.HiddenNonEnemy = true;
			Touch();
		}
	}

	public void Hit(CreatureEntry e, float damage, bool outgoing, string attack)
	{
		if (!float.IsNaN(damage) && !float.IsInfinity(damage) && !(damage < 0f))
		{
			if (outgoing)
			{
				e.HitsLanded++;
				e.BiggestHit = Math.Max(e.BiggestHit, damage);
			}
			else
			{
				e.HitsTaken++;
				e.BiggestReceived = Math.Max(e.BiggestReceived, damage);
			}
			if (!outgoing && !string.IsNullOrEmpty(attack))
			{
				AddDistinct(e.Attacks, Clean(attack, 100));
			}
			Touch();
		}
	}

	public void Resistance(CreatureEntry e, int type, string label, float resistance)
	{
		if (type >= 0 && type <= 255 && !float.IsNaN(resistance) && !float.IsInfinity(resistance))
		{
			ResistanceNote resistanceNote = e.Resistances.Find((ResistanceNote r) => r.Type == type);
			if (resistanceNote == null)
			{
				ResistanceNote resistanceNote2 = new ResistanceNote();
				resistanceNote2.Type = type;
				resistanceNote2.Label = Clean(label, 50);
				resistanceNote = resistanceNote2;
				e.Resistances.Add(resistanceNote);
			}
			resistanceNote.Percent = resistance;
			resistanceNote.Samples++;
			Touch();
		}
	}

	public bool CountDeath(CreatureEntry e, string receipt, bool playerDefeated)
	{
		if (string.IsNullOrEmpty(receipt))
		{
			return false;
		}
		string item = (playerDefeated ? "defeat/" : "kill/") + receipt;
		if (Receipts.Contains(item))
		{
			return false;
		}
		Receipts.Add(item);
		if (playerDefeated)
		{
			e.Defeats++;
		}
		else
		{
			e.Kills++;
		}
		Touch();
		return true;
	}

	public void Status(CreatureEntry e, string name)
	{
		if (!string.IsNullOrEmpty(name) && AddDistinct(e.Statuses, Clean(name, 100)))
		{
			Touch();
		}
	}

	public void Loot(CreatureEntry e, int id, string name, int amount)
	{
		if (amount > 0 && !string.IsNullOrEmpty(name))
		{
			LootNote lootNote = e.Loot.Find((LootNote n) => n.ItemId == id);
			if (lootNote == null)
			{
				LootNote lootNote2 = new LootNote();
				lootNote2.ItemId = id;
				lootNote2.Name = Clean(name, 100);
				lootNote = lootNote2;
				e.Loot.Add(lootNote);
			}
			lootNote.Amount += Math.Min(amount, 100000);
			Touch();
		}
	}

	private static bool AddDistinct(List<string> list, string value)
	{
		if (list.Contains(value))
		{
			return false;
		}
		list.Add(value);
		return true;
	}

	public static string Clean(string value, int max)
	{
		value = Regex.Replace(value ?? "", "<[^>]*>", "");
		value = Regex.Replace(value, "[\\p{Cc}]", " ").Trim();
		if (value.Length > max)
		{
			return value.Substring(0, max);
		}
		return value;
	}

	public static string Canonical(string value)
	{
		value = Regex.Replace(value ?? "", "\\(Clone\\)|\\s*\\[Instance[^\\]]*\\]", "", RegexOptions.IgnoreCase);
		return Regex.Replace(value.Replace('\\', '/').Trim().ToLowerInvariant(), "\\s+", " ");
	}

	public static string Hash(string input)
	{
		using SHA256 sHA = SHA256.Create();
		byte[] array = sHA.ComputeHash(Encoding.UTF8.GetBytes(input ?? ""));
		return BitConverter.ToString(array).Replace("-", "").ToLowerInvariant();
	}

	public static string Identity(string prefab, string stableName, string visual)
	{
		return Hash(Canonical(prefab) + "|" + Canonical(stableName) + "|" + Canonical(visual));
	}
}
[Serializable]
public sealed class CreatureEntry
{
	[OptionalField(VersionAdded = 3)]
	public bool EnemyConfirmed;

	[OptionalField(VersionAdded = 3)]
	public bool HiddenNonEnemy;

	public string Key = "";

	public string Name = "";

	public string Family = "";

	public string FirstSeen = "";

	public string LastArea = "";

	public int Kills;

	public int Defeats;

	public int HitsLanded;

	public int HitsTaken;

	public float BiggestHit;

	public float BiggestReceived;

	public List<ResistanceNote> Resistances = new List<ResistanceNote>();

	public List<string> Attacks = new List<string>();

	public List<string> Statuses = new List<string>();

	public List<LootNote> Loot = new List<LootNote>();
}
[Serializable]
public sealed class ResistanceNote
{
	public int Type;

	public int Samples;

	public string Label = "";

	public float Percent;
}
[Serializable]
public sealed class LootNote
{
	public int ItemId;

	public int Amount;

	public string Name = "";
}
internal sealed class GuideSkin
{
	private readonly Dictionary<string, Sprite> sprites = new Dictionary<string, Sprite>();

	internal Font Body;

	internal Font Heading;

	internal GuideSkin(Font fallback)
	{
		Sprite[] array = Resources.FindObjectsOfTypeAll<Sprite>();
		foreach (Sprite val in array)
		{
			if (Object.op_Implicit((Object)(object)val) && !sprites.ContainsKey(((Object)val).name))
			{
				sprites.Add(((Object)val).name, val);
			}
		}
		Body = fallback;
		Heading = fallback;
		Font[] array2 = Resources.FindObjectsOfTypeAll<Font>();
		foreach (Font val2 in array2)
		{
			if (((Object)val2).name == "Philosopher-Regular_Unicode")
			{
				Body = val2;
			}
			if (((Object)val2).name == "Philosopher-Bold")
			{
				Heading = val2;
			}
		}
	}

	internal Sprite Find(string name)
	{
		if (!sprites.TryGetValue(name, out var value) || !Object.op_Implicit((Object)(object)value))
		{
			return null;
		}
		return value;
	}

	internal void Surface(Image image, string name)
	{
		//IL_001a: 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_0038: Unknown result type (might be due to invalid IL or missing references)
		Sprite val = Find(name);
		if (Object.op_Implicit((Object)(object)val))
		{
			image.sprite = val;
			Vector4 border = val.border;
			image.type = (Type)(((Vector4)(ref border)).sqrMagnitude > 0f);
			((Graphic)image).color = Color.white;
		}
	}

	internal void Button(Button button, bool row, bool selected)
	{
		//IL_006d: 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)
		Image component = ((Component)button).GetComponent<Image>();
		Surface(component, (!row) ? "tex_men_buttonUnpressed" : (selected ? "tex_men_backgroundDialogueSelected" : "tex_men_backgroundDialogueUnselected"));
		Sprite val = Find(row ? "tex_men_backgroundDialogueSelected" : "tex_men_buttonUnpressedHover");
		Sprite val2 = Find(row ? "tex_men_backgroundDialogueSelected" : "tex_men_buttonPressed");
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2))
		{
			((Selectable)button).transition = (Transition)2;
			SpriteState spriteState = default(SpriteState);
			((SpriteState)(ref spriteState)).highlightedSprite = val;
			((SpriteState)(ref spriteState)).pressedSprite = val2;
			((SpriteState)(ref spriteState)).selectedSprite = val;
			((SpriteState)(ref spriteState)).disabledSprite = Find("tex_men_buttonDisabled");
			((Selectable)button).spriteState = spriteState;
		}
	}
}
public sealed class GuideStore
{
	private readonly string folder;

	private readonly Action<Exception> error;

	private readonly Dictionary<string, GuideBook> books = new Dictionary<string, GuideBook>();

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

	public GuideStore(string path, Action<Exception> report)
	{
		folder = path;
		error = report;
		Directory.CreateDirectory(folder);
	}

	public GuideBook Get(string uid)
	{
		if (string.IsNullOrEmpty(uid))
		{
			return null;
		}
		if (books.TryGetValue(uid, out var value))
		{
			return value;
		}
		string text = FilePath(uid);
		value = Read(text, uid) ?? Read(text + ".bak", uid);
		if (value == null)
		{
			GuideBook guideBook = new GuideBook();
			guideBook.CharacterId = uid;
			value = guideBook;
			if (File.Exists(text) || File.Exists(text + ".bak"))
			{
				readOnly.Add(uid);
			}
		}
		books.Add(uid, value);
		return value;
	}

	private GuideBook Read(string path, string uid)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		if (!File.Exists(path))
		{
			return null;
		}
		try
		{
			if (new FileInfo(path).Length > 33554432)
			{
				throw new InvalidDataException("Field guide file too large");
			}
			GuideBook guideBook;
			using (FileStream fileStream = File.OpenRead(path))
			{
				guideBook = (GuideBook)((XmlObjectSerializer)new DataContractJsonSerializer(typeof(GuideBook))).ReadObject((Stream)fileStream);
			}
			if (guideBook == null || guideBook.Schema < 1 || guideBook.Schema > 3 || guideBook.CharacterId != uid || guideBook.Creatures == null || guideBook.Receipts == null)
			{
				throw new InvalidDataException("Unsupported or incomplete field guide");
			}
			foreach (CreatureEntry creature in guideBook.Creatures)
			{
				if (creature == null || string.IsNullOrEmpty(creature.Key) || creature.Resistances == null || creature.Loot == null || creature.Attacks == null || creature.Statuses == null)
				{
					throw new InvalidDataException("Incomplete creature entry");
				}
			}
			if (guideBook.Schema == 1)
			{
				foreach (CreatureEntry creature2 in guideBook.Creatures)
				{
					foreach (ResistanceNote resistance in creature2.Resistances)
					{
						resistance.Percent *= 100f;
					}
				}
			}
			if (guideBook.Schema < 3)
			{
				guideBook.Schema = 3;
				guideBook.Touch();
			}
			return guideBook;
		}
		catch (Exception obj)
		{
			error(obj);
			return null;
		}
	}

	public string FilePath(string uid)
	{
		return Path.Combine(folder, GuideBook.Hash(uid) + ".json");
	}

	public void Flush()
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		foreach (GuideBook value in books.Values)
		{
			if (!value.Dirty || readOnly.Contains(value.CharacterId))
			{
				continue;
			}
			try
			{
				using (MemoryStream memoryStream = new MemoryStream())
				{
					((XmlObjectSerializer)new DataContractJsonSerializer(typeof(GuideBook))).WriteObject((Stream)memoryStream, (object)value);
					AtomicWrite(FilePath(value.CharacterId), memoryStream.ToArray());
				}
				value.Dirty = false;
			}
			catch (Exception obj)
			{
				error(obj);
			}
		}
	}

	public static void AtomicWrite(string path, byte[] bytes)
	{
		Directory.CreateDirectory(Path.GetDirectoryName(path));
		string text = path + ".tmp";
		using (FileStream fileStream = new FileStream(text, FileMode.Create, FileAccess.Write, FileShare.None))
		{
			fileStream.Write(bytes, 0, bytes.Length);
			fileStream.Flush(flushToDisk: true);
		}
		if (File.Exists(path))
		{
			File.Replace(text, path, path + ".bak");
		}
		else
		{
			File.Move(text, path);
		}
	}
}
public sealed class GuideView : MonoBehaviour
{
	private CharacterUI ui;

	private Plugin plugin;

	private Character character;

	private GuideBook book;

	private RectTransform root;

	private RectTransform page;

	private RectTransform list;

	private RectTransform notes;

	private Button entryButton;

	private Button backButton;

	private RectTransform journalFooter;

	private Text title;

	private Text subtitle;

	private Text count;

	private Text records;

	private Text specimenHint;

	private InputField search;

	private RawImage model;

	private Font font;

	private GuideSkin skin;

	private CanvasGroup journalGroup;

	private float journalAlpha;

	private bool journalInteractable;

	private bool journalRaycasts;

	private readonly List<GameObject> rows = new List<GameObject>();

	private readonly Dictionary<string, Button> rowButtons = new Dictionary<string, Button>();

	private readonly Dictionary<string, Text> rowCounts = new Dictionary<string, Text>();

	private int listCount = -1;

	private int listDefeatedCount = -1;

	private string listQuery = "";

	private bool listFilter;

	private SpecimenViewer viewer;

	private string selected = "";

	private int revision = -1;

	private float refreshAt;

	private float renderAt;

	private bool open;

	private bool defeatedOnly;

	private static readonly Color Ink = new Color(0.86f, 0.84f, 0.79f);

	private static readonly Color Muted = new Color(0.68f, 0.65f, 0.58f);

	private static readonly Color Gold = new Color(0.93f, 0.69f, 0.23f);

	private static readonly Color Dark = new Color(0.075f, 0.085f, 0.08f);

	private static readonly Color Cream = new Color(0.88f, 0.82f, 0.67f);

	public bool IsOpen
	{
		get
		{
			if (open && Object.op_Implicit((Object)(object)page))
			{
				return ((Component)page).gameObject.activeInHierarchy;
			}
			return false;
		}
	}

	public void Initialize(CharacterUI owner, Plugin instance)
	{
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Expected O, but got Unknown
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0218: Unknown result type (might be due to invalid IL or missing references)
		//IL_0246: Unknown result type (might be due to invalid IL or missing references)
		//IL_0282: Unknown result type (might be due to invalid IL or missing references)
		//IL_028c: Expected O, but got Unknown
		//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02be: Expected O, but got Unknown
		//IL_0313: Unknown result type (might be due to invalid IL or missing references)
		//IL_031d: Expected O, but got Unknown
		//IL_0345: Unknown result type (might be due to invalid IL or missing references)
		//IL_0377: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0417: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0502: Unknown result type (might be due to invalid IL or missing references)
		//IL_050c: Expected O, but got Unknown
		//IL_052f: Unknown result type (might be due to invalid IL or missing references)
		//IL_056a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0574: Expected O, but got Unknown
		//IL_0598: Unknown result type (might be due to invalid IL or missing references)
		//IL_0602: Unknown result type (might be due to invalid IL or missing references)
		ui = owner;
		plugin = instance;
		character = ui.TargetCharacter;
		Text componentInChildren = ((Component)ui).GetComponentInChildren<Text>(true);
		font = ((Object.op_Implicit((Object)(object)componentInChildren) && Object.op_Implicit((Object)(object)componentInChildren.font)) ? componentInChildren.font : Resources.GetBuiltinResource<Font>("Arial.ttf"));
		skin = new GuideSkin(font);
		font = skin.Body;
		root = Rect("Aurai Field Guide", (Transform)(Object.op_Implicit((Object)(object)ui.UIPanel) ? ((object)ui.UIPanel) : ((object)(RectTransform)((Component)ui).transform)), 0f, 0f, 1f, 1f);
		((Component)root).gameObject.AddComponent<CanvasGroup>();
		entryButton = Button((Transform)(object)root, "BESTIARY", 0.065f, 0.095f, 0.26f, 0.142f, new UnityAction(Open));
		page = Rect("Field Guide Book", (Transform)(object)root, 0.025f, 0.115f, 0.975f, 0.89f);
		Image val = ((Component)page).gameObject.AddComponent<Image>();
		((Graphic)val).color = Dark;
		skin.Surface(val, "tex_men_backgroundDialogue");
		RectTransform val2 = Rect("Creature record", (Transform)(object)page, 0.255f, 0.024f, 0.981f, 0.976f);
		Image val3 = ((Component)val2).gameObject.AddComponent<Image>();
		((Graphic)val3).color = new Color(0.07f, 0.075f, 0.08f);
		skin.Surface(val3, "tex_men_backgroundDetailPanel");
		Label((Transform)(object)page, "BESTIARY OF AURAI", 0.025f, 0.922f, 0.23f, 0.974f, 16, Muted);
		Label((Transform)(object)page, "Bestiary", 0.025f, 0.848f, 0.24f, 0.928f, 36, Gold);
		count = Label((Transform)(object)page, "Your discoveries", 0.026f, 0.8f, 0.237f, 0.85f, 14, Gold);
		BuildSearch();
		Button((Transform)(object)page, "All", 0.024f, 0.665f, 0.124f, 0.712f, (UnityAction)delegate
		{
			defeatedOnly = false;
			RefreshList();
		});
		Button((Transform)(object)page, "Defeated", 0.132f, 0.665f, 0.238f, 0.712f, (UnityAction)delegate
		{
			defeatedOnly = true;
			RefreshList();
		});
		list = Scroll((Transform)(object)page, "Creature index", 0.015f, 0.105f, 0.245f, 0.65f, 5);
		backButton = Button((Transform)(object)page, "BACK TO JOURNAL", 0.025f, 0.025f, 0.236f, 0.079f, new UnityAction(Close));
		title = Label((Transform)(object)page, "Every encounter tells a story", 0.287f, 0.858f, 0.957f, 0.95f, 36, Gold);
		subtitle = Label((Transform)(object)page, "Discover creatures through exploration, combat and looting.", 0.29f, 0.804f, 0.958f, 0.865f, 15, Muted);
		Rule((Transform)(object)page, 0.287f, 0.795f, 0.957f);
		RectTransform val4 = Rect("Specimen", (Transform)(object)page, 0.275f, 0.205f, 0.613f, 0.78f);
		Image val5 = ((Component)val4).gameObject.AddComponent<Image>();
		((Graphic)val5).color = new Color(0.055f, 0.06f, 0.065f);
		skin.Surface(val5, "tex_men_backgroundCompare");
		((Graphic)val5).color = new Color(0.8f, 0.8f, 0.8f, 1f);
		model = ((Component)Rect("Creature portrait", (Transform)(object)val4, 0f, 0f, 1f, 1f)).gameObject.AddComponent<RawImage>();
		((Graphic)model).raycastTarget = true;
		AspectRatioFitter val6 = ((Component)model).gameObject.AddComponent<AspectRatioFitter>();
		val6.aspectRatio = 1.28f;
		val6.aspectMode = (AspectMode)3;
		SpecimenDrag specimenDrag = ((Component)model).gameObject.AddComponent<SpecimenDrag>();
		specimenDrag.View = this;
		specimenHint = Label((Transform)(object)page, "CREATURE SPECIMEN", 0.29f, 0.205f, 0.602f, 0.253f, 12, Muted);
		specimenHint.alignment = (TextAnchor)4;
		Button((Transform)(object)page, "<", 0.297f, 0.12f, 0.351f, 0.177f, (UnityAction)delegate
		{
			Rotate(-30f);
		});
		Text val7 = Label((Transform)(object)page, "DRAG TO ROTATE", 0.36f, 0.12f, 0.529f, 0.177f, 12, Muted);
		val7.alignment = (TextAnchor)4;
		Button((Transform)(object)page, ">", 0.539f, 0.12f, 0.594f, 0.177f, (UnityAction)delegate
		{
			Rotate(30f);
		});
		records = Label((Transform)(object)page, "No creatures recorded yet.", 0.291f, 0.035f, 0.615f, 0.11f, 15, Ink);
		records.alignment = (TextAnchor)4;
		notes = Scroll((Transform)(object)page, "Creature notes", 0.642f, 0.06f, 0.958f, 0.775f, 11);
		Text val8 = Label((Transform)(object)page, "Scroll for more field notes", 0.644f, 0.023f, 0.956f, 0.053f, 12, Muted);
		val8.alignment = (TextAnchor)5;
		((Component)page).gameObject.SetActive(false);
		((Component)entryButton).gameObject.SetActive(false);
		viewer = new SpecimenViewer();
	}

	private void BuildSearch()
	{
		//IL_0046: 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)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = Rect("Search", (Transform)(object)page, 0.025f, 0.73f, 0.236f, 0.786f);
		Image val2 = ((Component)val).gameObject.AddComponent<Image>();
		((Graphic)val2).color = new Color(1f, 1f, 1f, 0.08f);
		skin.Surface(val2, "tex_men_characterCreationTextFieldBackgroundSlice");
		search = ((Component)val).gameObject.AddComponent<InputField>();
		Text textComponent = Label((Transform)(object)val, "", 0.04f, 0.04f, 0.96f, 0.96f, 16, Cream);
		Text placeholder = Label((Transform)(object)val, "Search discoveries...", 0.04f, 0.04f, 0.96f, 0.96f, 14, Gold);
		search.textComponent = textComponent;
		search.placeholder = (Graphic)(object)placeholder;
		search.characterLimit = 80;
		((UnityEvent<string>)(object)search.onValueChanged).AddListener((UnityAction<string>)delegate
		{
			RefreshList();
		});
	}

	private void LateUpdate()
	{
		if (!Object.op_Implicit((Object)(object)root) || !Object.op_Implicit((Object)(object)ui) || !Object.op_Implicit((Object)(object)plugin))
		{
			return;
		}
		try
		{
			bool flag = Plugin.Ready && Object.op_Implicit((Object)(object)ui.TargetCharacter) && ui.TargetCharacter.IsLocalPlayer && ui.GetIsMenuDisplayed((MenuScreens)10);
			MenuPanel val = (flag ? ui.GetMenu((MenuScreens)10) : null);
			if ((Object)(object)character != (Object)(object)ui.TargetCharacter)
			{
				Close();
				character = ui.TargetCharacter;
				book = null;
				selected = "";
				revision = -1;
			}
			if (!flag && open)
			{
				Close();
			}
			bool flag2 = flag && Object.op_Implicit((Object)(object)val) && (Object)(object)ui.GetCurrentMenu() == (Object)(object)val && !open && AttachJournalLauncher();
			((Component)entryButton).gameObject.SetActive(flag2);
			if (flag2 || open)
			{
				((Transform)root).SetAsLastSibling();
			}
			if (!open)
			{
				return;
			}
			if (Object.op_Implicit((Object)(object)journalGroup))
			{
				journalGroup.alpha = 0f;
				journalGroup.interactable = false;
				journalGroup.blocksRaycasts = false;
			}
			((Transform)root).SetAsLastSibling();
			if (Time.unscaledTime >= refreshAt)
			{
				refreshAt = Time.unscaledTime + 0.75f;
				GuideBook guideBook = plugin.Book(character);
				if (book != guideBook || revision != guideBook.Revision)
				{
					book = guideBook;
					revision = book.Revision;
					RefreshList();
					RefreshDetails(changeModel: false);
				}
			}
			if (viewer != null && viewer.Available && Time.unscaledTime >= renderAt)
			{
				renderAt = Time.unscaledTime + 0.05f;
				viewer.Render(0.05f);
			}
		}
		catch (Exception ex)
		{
			plugin.Report(ex);
			Close();
		}
	}

	private bool AttachJournalLauncher()
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Expected O, but got Unknown
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)journalFooter))
		{
			RectTransform[] componentsInChildren = ((Component)ui.UIPanel).GetComponentsInChildren<RectTransform>(true);
			foreach (RectTransform val in componentsInChildren)
			{
				if (((Object)val).name == "Journal PanelFooter")
				{
					journalFooter = val;
					break;
				}
			}
		}
		if (!Object.op_Implicit((Object)(object)journalFooter))
		{
			return false;
		}
		RectTransform val2 = (RectTransform)((Component)entryButton).transform;
		if ((Object)(object)((Transform)val2).parent != (Object)(object)journalFooter)
		{
			((Transform)val2).SetParent((Transform)(object)journalFooter, false);
			Vector2 anchorMin = (val2.anchorMax = new Vector2(0f, 0.5f));
			val2.anchorMin = anchorMin;
			val2.pivot = new Vector2(0f, 0.5f);
			val2.anchoredPosition = new Vector2(8f, 0f);
			val2.sizeDelta = new Vector2(170f, 30f);
			((Transform)val2).SetAsLastSibling();
			Transform[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren<Transform>(true);
			foreach (Transform val4 in componentsInChildren2)
			{
				((Component)val4).gameObject.layer = ((Component)journalFooter).gameObject.layer;
			}
		}
		return true;
	}

	public void Open()
	{
		if (!open && Plugin.Ready && Plugin.Local(ui.TargetCharacter) && ui.GetIsMenuDisplayed((MenuScreens)10))
		{
			character = ui.TargetCharacter;
			ui.ShowMenu((MenuScreens)10);
			MenuPanel menu = ui.GetMenu((MenuScreens)10);
			journalGroup = (Object.op_Implicit((Object)(object)menu) ? ((Component)menu).GetComponent<CanvasGroup>() : null);
			if (Object.op_Implicit((Object)(object)journalGroup))
			{
				journalAlpha = journalGroup.alpha;
				journalInteractable = journalGroup.interactable;
				journalRaycasts = journalGroup.blocksRaycasts;
				journalGroup.alpha = 0f;
				journalGroup.interactable = false;
				journalGroup.blocksRaycasts = false;
			}
			open = true;
			((Component)page).gameObject.SetActive(true);
			((Transform)root).SetAsLastSibling();
			((Component)entryButton).gameObject.SetActive(false);
			book = plugin.Book(character);
			revision = book.Revision;
			RefreshList();
			RefreshDetails(changeModel: true);
			ui.SetSelectedGameObject(((Component)backButton).gameObject);
		}
	}

	public void Close()
	{
		open = false;
		if (Object.op_Implicit((Object)(object)page))
		{
			((Component)page).gameObject.SetActive(false);
		}
		if (Object.op_Implicit((Object)(object)journalGroup))
		{
			bool flag = Object.op_Implicit((Object)(object)ui) && ui.GetIsMenuDisplayed((MenuScreens)10);
			journalGroup.alpha = (flag ? journalAlpha : 0f);
			journalGroup.interactable = flag && journalInteractable;
			journalGroup.blocksRaycasts = flag && journalRaycasts;
			journalGroup = null;
		}
		if (viewer != null)
		{
			viewer.Dispose();
		}
		if (Object.op_Implicit((Object)(object)model))
		{
			model.texture = null;
		}
	}

	private void RefreshList()
	{
		//IL_0364: Unknown result type (might be due to invalid IL or missing references)
		//IL_036e: Expected O, but got Unknown
		//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0445: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d7: Unknown result type (might be due to invalid IL or missing references)
		if (book == null || !Object.op_Implicit((Object)(object)this.list))
		{
			return;
		}
		List<CreatureEntry> list = book.Creatures.Where((CreatureEntry e) => !e.HiddenNonEnemy).ToList();
		count.text = list.Count + ((list.Count == 1) ? " enemy discovered" : " enemies discovered");
		string query = (Object.op_Implicit((Object)(object)search) ? search.text.Trim() : "");
		int num = list.Count((CreatureEntry e) => e.Kills > 0);
		if (listCount == list.Count && list.All((CreatureEntry e) => rowButtons.ContainsKey(e.Key)) && listQuery == query && listFilter == defeatedOnly && (!defeatedOnly || listDefeatedCount == num))
		{
			foreach (KeyValuePair<string, Button> rowButton in rowButtons)
			{
				CreatureEntry creatureEntry = book.Find(rowButton.Key);
				if (creatureEntry != null && Object.op_Implicit((Object)(object)rowButton.Value))
				{
					skin.Button(rowButton.Value, row: true, selected == rowButton.Key);
					rowCounts[rowButton.Key].text = ((creatureEntry.Kills > 0) ? (creatureEntry.Kills + " defeated") : "Encountered");
				}
			}
			return;
		}
		foreach (GameObject row in rows)
		{
			Object.Destroy((Object)(object)row);
		}
		rows.Clear();
		rowButtons.Clear();
		rowCounts.Clear();
		listCount = list.Count;
		listQuery = query;
		listFilter = defeatedOnly;
		listDefeatedCount = num;
		List<CreatureEntry> list2 = list.Where((CreatureEntry e) => (!defeatedOnly || e.Kills > 0) && (query.Length == 0 || e.Name.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0)).OrderBy<CreatureEntry, string>((CreatureEntry e) => e.Name, StringComparer.OrdinalIgnoreCase).ToList();
		if (!list2.Any((CreatureEntry e) => e.Key == selected))
		{
			selected = "";
		}
		if (string.IsNullOrEmpty(selected) && list2.Count > 0)
		{
			selected = list2[0].Key;
		}
		foreach (CreatureEntry item in list2)
		{
			string key = item.Key;
			Button val = Button((Transform)(object)this.list, "", 0f, 0f, 1f, 1f, (UnityAction)delegate
			{
				selected = key;
				RefreshList();
				RefreshDetails(changeModel: true);
			});
			LayoutElement val2 = ((Component)val).gameObject.AddComponent<LayoutElement>();
			val2.preferredHeight = 66f;
			val2.minHeight = 66f;
			((Component)val).gameObject.AddComponent<ScrollSelectedRow>();
			skin.Button(val, row: true, selected == key);
			Label(((Component)val).transform, item.Name, 0.04f, 0.39f, 0.96f, 0.95f, 18, Cream);
			rowCounts.Add(key, Label(((Component)val).transform, (item.Kills > 0) ? (item.Kills + " defeated") : "Encountered", 0.04f, 0.04f, 0.96f, 0.4f, 12, Gold));
			rowButtons.Add(key, val);
			rows.Add(((Component)val).gameObject);
		}
		if (list2.Count == 0)
		{
			Text val3 = Label((Transform)(object)this.list, (query.Length > 0) ? "No matching discoveries." : "Your guide begins with your first encounter.", 0f, 0f, 1f, 1f, 16, Cream);
			((Component)val3).gameObject.AddComponent<LayoutElement>().preferredHeight = 90f;
			rows.Add(((Component)val3).gameObject);
		}
	}

	private void RefreshDetails(bool changeModel)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Expected O, but got Unknown
		foreach (Transform item in (Transform)notes)
		{
			Transform val = item;
			Object.Destroy((Object)(object)((Component)val).gameObject);
		}
		CreatureEntry creatureEntry = ((book != null) ? book.Find(selected) : null);
		if (creatureEntry != null && creatureEntry.HiddenNonEnemy)
		{
			creatureEntry = null;
		}
		if (creatureEntry == null)
		{
			if (viewer != null)
			{
				viewer.Dispose();
			}
			model.texture = null;
			title.text = "Every encounter tells a story";
			subtitle.text = "See a creature, fight it or loot its remains to begin an entry.";
			AddHeading("A guide earned through experience");
			AddNote("Unknown weaknesses and rewards stay hidden. Your own encounters fill these pages.");
			records.text = "Your adventure starts here.";
			((Behaviour)model).enabled = false;
			specimenHint.text = "NO SPECIMEN DISCOVERED";
			return;
		}
		title.text = creatureEntry.Name;
		subtitle.text = "Last encountered: " + creatureEntry.LastArea + "  |  First recorded: " + creatureEntry.FirstSeen;
		records.text = creatureEntry.Kills + " defeated  /  " + creatureEntry.Defeats + " defeats\nBest strike: " + creatureEntry.BiggestHit.ToString("0.#") + " damage";
		AddHeading("TESTED DEFENSES");
		AddNote("Only damage types you have landed are revealed. Values reflect the last observed encounter.", 13);
		int[] knownTypes = new int[6] { 0, 5, 4, 3, 1, 2 };
		string[] array = new string[6] { "Physical", "Fire", "Frost", "Lightning", "Ethereal", "Decay" };
		int i;
		for (i = 0; i < knownTypes.Length; i++)
		{
			ResistanceNote note = creatureEntry.Resistances.Find((ResistanceNote n) => n.Type == knownTypes[i]);
			AddResistance(array[i], note);
		}
		foreach (ResistanceNote resistance in creatureEntry.Resistances)
		{
			if (!Extensions.Contains(knownTypes, resistance.Type))
			{
				AddResistance(resistance.Label, resistance);
			}
		}
		AddHeading("ATTACKS WITNESSED");
		if (creatureEntry.Attacks.Count == 0)
		{
			AddNote("No hits received from this creature yet.");
		}
		foreach (string attack in creatureEntry.Attacks)
		{
			AddNote("• " + attack);
		}
		if (creatureEntry.HitsTaken > 0)
		{
			AddNote("Hardest received hit: " + creatureEntry.BiggestReceived.ToString("0.#") + " damage", 13);
		}
		AddHeading("HARMFUL EFFECTS");
		if (creatureEntry.Statuses.Count == 0)
		{
			AddNote("No harmful effects recorded.");
		}
		foreach (string status in creatureEntry.Statuses)
		{
			AddNote("• " + status);
		}
		AddHeading("LOOT DISCOVERED");
		if (creatureEntry.Loot.Count == 0)
		{
			AddNote("Loot this creature's remains to record its rewards.");
		}
		foreach (LootNote item2 in creatureEntry.Loot)
		{
			AddNote("• " + item2.Name + "  ×" + item2.Amount + " collected");
		}
		AddNote("Records belong to this character. Defeated counts include fights you participated in; observed loot is not a complete drop table.", 12);
		if (changeModel || !Object.op_Implicit((Object)(object)model.texture))
		{
			if (plugin.Models.Value)
			{
				viewer.Show(plugin.CacheFolder, creatureEntry.Key);
			}
			else
			{
				viewer.Dispose();
			}
			model.texture = (Texture)(object)viewer.Texture;
			((Behaviour)model).enabled = viewer.Available;
			specimenHint.text = (viewer.Available ? "DRAG TO ROTATE  •  SCROLL TO ZOOM" : (plugin.Models.Value ? "SPECIMEN NOT YET CAPTURED\nRecording its appearance may take a few seconds." : "CREATURE MODELS DISABLED"));
		}
	}

	private void AddResistance(string name, ResistanceNote note)
	{
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = Rect("Defense: " + name, (Transform)(object)notes, 0f, 0f, 1f, 1f);
		((Component)val).gameObject.AddComponent<LayoutElement>().preferredHeight = 34f;
		Label((Transform)(object)val, name, 0f, 0f, 0.44f, 1f, 16, Ink);
		string value = ((note == null) ? "Not tested" : ((note.Percent < 0f) ? ("Weak  " + note.Percent.ToString("0.#") + "%") : ((note.Percent == 0f) ? "Neutral  0%" : ("Resists  " + note.Percent.ToString("0.#") + "%"))));
		Text val2 = Label((Transform)(object)val, value, 0.44f, 0f, 1f, 1f, 14, (Color)((note == null) ? Muted : ((note.Percent < 0f) ? new Color(0.48f, 0.8f, 0.66f) : Ink)));
		val2.alignment = (TextAnchor)5;
	}

	private void AddHeading(string text)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		Text val = Label((Transform)(object)notes, text, 0f, 0f, 1f, 1f, 18, Gold);
		val.fontStyle = (FontStyle)1;
		((Component)val).gameObject.AddComponent<LayoutElement>().preferredHeight = 40f;
	}

	private void AddNote(string text, int size = 16)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		Text val = Label((Transform)(object)notes, text, 0f, 0f, 1f, 1f, size, Ink);
		val.alignment = (TextAnchor)0;
		LayoutElement val2 = ((Component)val).gameObject.AddComponent<LayoutElement>();
		val2.minHeight = size + 10;
		val2.preferredHeight = -1f;
		((Component)val).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
	}

	public void Rotate(float amount)
	{
		if (viewer != null)
		{
			viewer.Rotate(amount);
		}
	}

	public void Zoom(float amount)
	{
		if (viewer != null)
		{
			viewer.Zoom(amount);
		}
	}

	internal void ModelChanged(string key)
	{
		if (open && selected == key)
		{
			RefreshDetails(changeModel: true);
		}
	}

	private RectTransform Scroll(Transform parent, string name, float x0, float y0, float x1, float y1, int spacing)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: 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_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = Rect(name, parent, x0, y0, x1, y1);
		((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.001f);
		ScrollRect val2 = ((Component)val).gameObject.AddComponent<ScrollRect>();
		val2.horizontal = false;
		val2.scrollSensitivity = 32f;
		RectTransform val3 = Rect("Viewport", (Transform)(object)val, 0f, 0f, 1f, 1f);
		((Component)val3).gameObject.AddComponent<RectMask2D>();
		val3.offsetMax = new Vector2(-16f, 0f);
		RectTransform val4 = Rect("Content", (Transform)(object)val3, 0f, 1f, 1f, 1f);
		val4.pivot = new Vector2(0.5f, 1f);
		VerticalLayoutGroup val5 = ((Component)val4).gameObject.AddComponent<VerticalLayoutGroup>();
		((HorizontalOrVerticalLayoutGroup)val5).spacing = spacing;
		((HorizontalOrVerticalLayoutGroup)val5).childForceExpandHeight = false;
		((HorizontalOrVerticalLayoutGroup)val5).childForceExpandWidth = true;
		((HorizontalOrVerticalLayoutGroup)val5).childControlHeight = true;
		((HorizontalOrVerticalLayoutGroup)val5).childControlWidth = true;
		((Component)val4).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
		val2.viewport = val3;
		val2.content = val4;
		RectTransform val6 = Rect("Scroll track", (Transform)(object)val, 0.993f, 0f, 1f, 1f);
		((Graphic)((Component)val6).gameObject.AddComponent<Image>()).color = new Color(0.5f, 0.4f, 0.22f, 0.17f);
		Scrollbar val7 = ((Component)val6).gameObject.AddComponent<Scrollbar>();
		val7.direction = (Direction)2;
		RectTransform val8 = Rect("Handle", (Transform)(object)val6, 0f, 0f, 1f, 1f);
		Image val9 = ((Component)val8).gameObject.AddComponent<Image>();
		((Graphic)val9).color = Gold;
		val7.handleRect = val8;
		((Selectable)val7).targetGraphic = (Graphic)(object)val9;
		val2.verticalScrollbar = val7;
		val2.verticalScrollbarVisibility = (ScrollbarVisibility)1;
		return val4;
	}

	internal static RectTransform Rect(string name, Transform parent, float x0, float y0, float x1, float y1)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: 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)
		//IL_0060: 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)
		GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
		val.layer = ((Component)parent).gameObject.layer;
		RectTransform component = val.GetComponent<RectTransform>();
		((Transform)component).SetParent(parent, false);
		component.anchorMin = new Vector2(x0, y0);
		component.anchorMax = new Vector2(x1, y1);
		Vector2 offsetMin = (component.offsetMax = Vector2.zero);
		component.offsetMin = offsetMin;
		return component;
	}

	private Text Label(Transform parent, string value, float x0, float y0, float x1, float y1, int size, Color color)
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		Text val = ((Component)Rect("Text", parent, x0, y0, x1, y1)).gameObject.AddComponent<Text>();
		val.text = value;
		val.font = ((skin != null && size >= 24) ? skin.Heading : font);
		val.fontSize = ((size >= 24) ? size : (size + 2));
		((Graphic)val).color = color;
		val.supportRichText = false;
		val.alignment = (TextAnchor)3;
		((Graphic)val).raycastTarget = false;
		val.horizontalOverflow = (HorizontalWrapMode)0;
		return val;
	}

	private Button Button(Transform parent, string caption, float x0, float y0, float x1, float y1, UnityAction action)
	{
		//IL_003a: 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)
		//IL_006f: 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_0095: 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)
		RectTransform val = Rect((caption.Length == 0) ? "Creature entry" : caption, parent, x0, y0, x1, y1);
		Image val2 = ((Component)val).gameObject.AddComponent<Image>();
		((Graphic)val2).color = new Color(0.16f, 0.2f, 0.17f);
		Button val3 = ((Component)val).gameObject.AddComponent<Button>();
		((Selectable)val3).targetGraphic = (Graphic)(object)val2;
		ColorBlock colors = ((Selectable)val3).colors;
		((ColorBlock)(ref colors)).highlightedColor = new Color(1.5f, 1.5f, 1.3f);
		((ColorBlock)(ref colors)).pressedColor = new Color(0.7f, 0.7f, 0.65f);
		((Selectable)val3).colors = colors;
		((UnityEvent)val3.onClick).AddListener(action);
		if (skin != null)
		{
			skin.Button(val3, caption.Length == 0, selected: false);
		}
		if (caption.Length > 0)
		{
			Text val4 = Label((Transform)(object)val, caption, 0.04f, 0f, 0.96f, 1f, 15, Cream);
			val4.alignment = (TextAnchor)4;
		}
		return val3;
	}

	private static void Rule(Transform parent, float x0, float y, float x1)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = Rect("Gold rule", parent, x0, y, x1, y);
		val.sizeDelta = new Vector2(0f, 1f);
		((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = Gold;
	}

	private void OnDestroy()
	{
		Close();
		if (Object.op_Implicit((Object)(object)entryButton))
		{
			Object.Destroy((Object)(object)((Component)entryButton).gameObject);
		}
		if (Object.op_Implicit((Object)(object)root))
		{
			Object.Destroy((Object)(object)((Component)root).gameObject);
		}
	}
}
public sealed class SpecimenDrag : MonoBehaviour, IDragHandler, IScrollHandler, IEventSystemHandler
{
	public GuideView View;

	public void OnDrag(PointerEventData data)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)View))
		{
			View.Rotate((0f - data.delta.x) * 0.45f);
		}
	}

	public void OnScroll(PointerEventData data)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)View))
		{
			View.Zoom((0f - data.scrollDelta.y) * 0.075f);
		}
	}
}
public sealed class ScrollSelectedRow : MonoBehaviour, ISelectHandler, IEventSystemHandler
{
	public void OnSelect(BaseEventData data)
	{
		//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_0047: 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_004f: 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_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		ScrollRect componentInParent = ((Component)this).GetComponentInParent<ScrollRect>();
		if (Object.op_Implicit((Object)(object)componentInParent) && Object.op_Implicit((Object)(object)componentInParent.viewport) && Object.op_Implicit((Object)(object)componentInParent.content))
		{
			Canvas.ForceUpdateCanvases();
			Bounds val = RectTransformUtility.CalculateRelativeRectTransformBounds((Transform)(object)componentInParent.viewport, ((Component)this).transform);
			Rect rect = componentInParent.viewport.rect;
			float num = ((((Bounds)(ref val)).max.y > ((Rect)(ref rect)).yMax) ? (((Rect)(ref rect)).yMax - ((Bounds)(ref val)).max.y) : ((((Bounds)(ref val)).min.y < ((Rect)(ref rect)).yMin) ? (((Rect)(ref rect)).yMin - ((Bounds)(ref val)).min.y) : 0f));
			RectTransform content = componentInParent.content;
			content.anchoredPosition += new Vector2(0f, num);
			componentInParent.velocity = Vector2.zero;
		}
	}
}
public static class ModelArchive
{
	private sealed class MaterialSnapshot
	{
		internal string Shader;

		internal string[] Keywords;

		internal int Queue;

		internal readonly List<MaterialProperty> Properties = new List<MaterialProperty>();

		internal byte[] Bytes;
	}

	private sealed class MaterialProperty
	{
		internal string Name;

		internal byte Kind;

		internal Vector4 Value;

		internal TextureCopy Texture;

		internal Vector2 Scale;

		internal Vector2 Offset;

		internal int WrapU;

		internal int WrapV;
	}

	private sealed class TextureCopy
	{
		internal byte[] Pixels;

		internal int Width;

		internal int Height;

		internal GraphicsFormat Format;

		internal string Filename;

		internal bool Linear;
	}

	private sealed class Part
	{
		internal Vector3[] Vertices;

		internal Vector3[] Normals;

		internal Vector2[] UV;

		internal Vector2[] UV2;

		internal Vector4[] Tangents;

		internal Color32[] Colors;

		internal int[] Triangles;

		internal Color Color;

		internal Color Emission;

		internal TextureCopy Texture;

		internal MaterialSnapshot Surface;
	}

	private sealed class WorkResult
	{
		internal volatile bool Done;

		internal Exception Error;
	}

	private const int Magic = 1095124786;

	private const int LegacyMagic = 1095124785;

	private const int VertexBudget = 2000000;

	private const int PartBudget = 2048;

	private const int MaxTextureEdge = 2048;

	private const int TextureByteBudget = 100663296;

	private static Renderer[] CaptureRenderers(Character actor)
	{
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Invalid comparison between Unknown and I4
		HashSet<Renderer> hashSet = new HashSet<Renderer>();
		LODGroup[] componentsInChildren = ((Component)actor).GetComponentsInChildren<LODGroup>(true);
		foreach (LODGroup val in componentsInChildren)
		{
			LOD[] lODs = val.GetLODs();
			if (lODs.Length < 2)
			{
				continue;
			}
			HashSet<Renderer> hashSet2 = new HashSet<Renderer>(lODs[0].renderers);
			for (int j = 1; j < lODs.Length; j++)
			{
				Renderer[] renderers = lODs[j].renderers;
				foreach (Renderer val2 in renderers)
				{
					if (Object.op_Implicit((Object)(object)val2) && !hashSet2.Contains(val2))
					{
						hashSet.Add(val2);
					}
				}
			}
		}
		List<Renderer> list = new List<Renderer>();
		Renderer[] componentsInChildren2 = ((Component)actor).GetComponentsInChildren<Renderer>(false);
		foreach (Renderer val3 in componentsInChildren2)
		{
			if (val3.enabled && (int)val3.shadowCastingMode != 3 && !hashSet.Contains(val3))
			{
				list.Add(val3);
			}
		}
		return list.ToArray();
	}

	private static MaterialSnapshot CaptureSurface(Material material, Dictionary<Texture, TextureCopy> textures, ref int bytes)
	{
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: 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_0095: Expected I4, but got Unknown
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: 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_010f: Invalid comparison between Unknown and I4
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: 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_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Invalid comparison between Unknown and I4
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Expected I4, but got Unknown
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Expected I4, but got Unknown
		Shader shader = material.shader;
		MaterialSnapshot materialSnapshot = new MaterialSnapshot();
		materialSnapshot.Shader = ((Object)shader).name;
		materialSnapshot.Keywords = material.shaderKeywords;
		materialSnapshot.Queue = material.renderQueue;
		MaterialSnapshot materialSnapshot2 = materialSnapshot;
		int num = Mathf.Min(512, shader.GetPropertyCount());
		for (int i = 0; i < num; i++)
		{
			string propertyName = shader.GetPropertyName(i);
			ShaderPropertyType propertyType = shader.GetPropertyType(i);
			MaterialProperty materialProperty = new MaterialProperty();
			materialProperty.Name = propertyName;
			MaterialProperty materialProperty2 = materialProperty;
			ShaderPropertyType val = propertyType;
			switch ((int)val)
			{
			case 2:
			case 3:
				materialProperty2.Kind = 0;
				materialProperty2.Value = new Vector4(material.GetFloat(propertyName), 0f, 0f, 0f);
				break;
			case 0:
				materialProperty2.Kind = 1;
				materialProperty2.Value = Color.op_Implicit(material.GetColor(propertyName));
				break;
			case 1:
				materialProperty2.Kind = 2;
				materialProperty2.Value = material.GetVector(propertyName);
				break;
			case 4:
			{
				if ((int)shader.GetPropertyTextureDimension(i) != 2)
				{
					continue;
				}
				materialProperty2.Kind = 3;
				materialProperty2.Scale = material.GetTextureScale(propertyName);
				materialProperty2.Offset = material.GetTextureOffset(propertyName);
				Texture texture = material.GetTexture(propertyName);
				if (!Object.op_Implicit((Object)(object)texture) || (int)texture.dimension != 2)
				{
					break;
				}
				if (!textures.TryGetValue(texture, out var value))
				{
					value = ReadTexture(texture, 100663296 - bytes);
					textures.Add(texture, value);
					if (value != null)
					{
						bytes += value.Pixels.Length;
					}
				}
				materialProperty2.Texture = value;
				materialProperty2.WrapU = (int)texture.wrapModeU;
				materialProperty2.WrapV = (int)texture.wrapModeV;
				break;
			}
			default:
				continue;
			}
			materialSnapshot2.Properties.Add(materialProperty2);
		}
		return materialSnapshot2;
	}

	private static void SaveCopy(TextureCopy copy, string folder)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		if (copy != null && copy.Filename == null)
		{
			byte[] array = ImageConversion.EncodeArrayToPNG((Array)copy.Pixels, copy.Format, (uint)copy.Width, (uint)copy.Height, 0u);
			using (SHA256 sHA = SHA256.Create())
			{
				copy.Filename = BitConverter.ToString(sHA.ComputeHash(array)).Replace("-", "").ToLowerInvariant() + ".png";
			}
			string path = Path.Combine(folder, copy.Filename);
			if (!File.Exists(path))
			{
				GuideStore.AtomicWrite(path, array);
			}
			copy.Pixels = null;
		}
	}

	private static void WriteSurface(BinaryWriter writer, MaterialSnapshot surface)
	{
		if (surface.Bytes == null)
		{
			using MemoryStream memoryStream = new MemoryStream();
			using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream, Encoding.UTF8, leaveOpen: true))
			{
				binaryWriter.Write(surface.Shader);
				binaryWriter.Write(surface.Queue);
				binaryWriter.Write(surface.Keywords.Length);
				string[] keywords = surface.Keywords;
				foreach (string value in keywords)
				{
					binaryWriter.Write(value);
				}
				binaryWriter.Write(surface.Properties.Count);
				foreach (MaterialProperty property in surface.Properties)
				{
					binaryWriter.Write(property.Name);
					binaryWriter.Write(property.Kind);
					if (property.Kind == 3)
					{
						binaryWriter.Write((property.Texture != null) ? property.Texture.Filename : "");
						binaryWriter.Write(property.Texture != null && property.Texture.Linear);
						binaryWriter.Write(property.Scale.x);
						binaryWriter.Write(property.Scale.y);
						binaryWriter.Write(property.Offset.x);
						binaryWriter.Write(property.Offset.y);
						binaryWriter.Write(property.WrapU);
						binaryWriter.Write(property.WrapV);
					}
					else
					{
						binaryWriter.Write(property.Value.x);
						binaryWriter.Write(property.Value.y);
						binaryWriter.Write(property.Value.z);
						binaryWriter.Write(property.Value.w);
					}
				}
			}
			surface.Bytes = memoryStream.ToArray();
		}
		writer.Write(surface.Bytes.Length);
		writer.Write(surface.Bytes);
	}

	private static Material ReadSurface(BinaryReader reader, string folder, Dictionary<string, Texture2D> textures, Dictionary<string, Material> materials, List<Object> owned)
	{
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Expected O, but got Unknown
		//IL_0233: Unknown result type (might be due to invalid IL or missing references)
		//IL_023e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02db: Unknown result type (might be due to invalid IL or missing references)
		int num = reader.ReadInt32();
		if (num < 1 || num > 1048576)
		{
			throw new InvalidDataException("Invalid material snapshot size");
		}
		byte[] array = reader.ReadBytes(num);
		if (array.Length != num)
		{
			throw new EndOfStreamException();
		}
		string text;
		using (SHA256 sHA = SHA256.Create())
		{
			text = BitConverter.ToString(sHA.ComputeHash(array));
		}
		if (materials.TryGetValue(text, out var value))
		{
			return value;
		}
		using (BinaryReader binaryReader = new BinaryReader(new MemoryStream(array)))
		{
			string text2 = binaryReader.ReadString();
			if (text2.Length > 512)
			{
				throw new InvalidDataException("Invalid material shader");
			}
			Shader val = Shader.Find(text2);
			bool flag = Object.op_Implicit((Object)(object)val) && val.isSupported;
			value = new Material(flag ? val : Shader.Find("Standard"));
			owned.Add((Object)(object)value);
			((Object)value).name = "Archived material " + text;
			int renderQueue = binaryReader.ReadInt32();
			int num2 = binaryReader.ReadInt32();
			if (num2 < 0 || num2 > 256)
			{
				throw new InvalidDataException("Invalid material keywords");
			}
			string[] array2 = new string[num2];
			for (int i = 0; i < num2; i++)
			{
				array2[i] = binaryReader.ReadString();
			}
			if (flag)
			{
				value.shaderKeywords = array2;
				value.renderQueue = renderQueue;
			}
			int num3 = binaryReader.ReadInt32();
			if (num3 < 0 || num3 > 512)
			{
				throw new InvalidDataException("Invalid material properties");
			}
			Vector2 val2 = default(Vector2);
			Vector2 val3 = default(Vector2);
			Vector4 val5 = default(Vector4);
			for (int j = 0; j < num3; j++)
			{
				string text3 = binaryReader.ReadString();
				byte b = binaryReader.ReadByte();
				if (text3.Length > 256)
				{
					throw new InvalidDataException("Invalid material property");
				}
				string text4 = (flag ? text3 : FallbackProperty(text3));
				if (b == 3)
				{
					string file = binaryReader.ReadString();
					bool linear = binaryReader.ReadBoolean();
					((Vector2)(ref val2))..ctor(binaryReader.ReadSingle(), binaryReader.ReadSingle());
					((Vector2)(ref val3))..ctor(binaryReader.ReadSingle(), binaryReader.ReadSingle());
					int wrapU = binaryReader.ReadInt32();
					int wrapV = binaryReader.ReadInt32();
					if (value.HasProperty(text4))
					{
						Texture2D val4 = LoadSurfaceTexture(folder, file, linear, wrapU, wrapV, textures, owned);
						value.SetTexture(text4, (Texture)(object)val4);
						value.SetTextureScale(text4, val2);
						value.SetTextureOffset(text4, val3);
						if (!flag && Object.op_Implicit((Object)(object)val4) && text4 == "_BumpMap")
						{
							value.EnableKeyword("_NORMALMAP");
						}
					}
					continue;
				}
				((Vector4)(ref val5))..ctor(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
				if (value.HasProperty(text4))
				{
					switch (b)
					{
					case 0:
						value.SetFloat(text4, val5.x);
						break;
					case 1:
						value.SetColor(text4, Color.op_Implicit(val5));
						break;
					case 2:
						value.SetVector(text4, val5);
						break;
					default:
						throw new InvalidDataException("Invalid material property kind");
					}
				}
			}
		}
		materials.Add(text, value);
		return value;
	}

	private static Texture2D LoadSurfaceTexture(string folder, string file, bool linear, int wrapU, int wrapV, Dictionary<string, Texture2D> textures, List<Object> owned)
	{
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Expected O, but got Unknown
		if (!Regex.IsMatch(file, "^[a-f0-9]{64}\\.png$"))
		{
			return null;
		}
		string key = file + "/" + linear + "/" + wrapU + "/" + wrapV;
		if (textures.TryGetValue(key, out var value))
		{
			return value;
		}
		string text = Path.Combine(folder, file);
		if (!File.Exists(text) || new FileInfo(text).Length >= 33554432)
		{
			return null;
		}
		value = new Texture2D(2, 2, (TextureFormat)4, true, linear);
		if (!ImageConversion.LoadImage(value, File.ReadAllBytes(text), true))
		{
			Object.Destroy((Object)(object)value);
			return null;
		}
		((Object)value).name = file;
		((Texture)value).filterMode = (FilterMode)2;
		((Texture)value).anisoLevel = 4;
		if (wrapU >= 0 && wrapU <= 3)
		{
			((Texture)value).wrapModeU = (TextureWrapMode)wrapU;
		}
		if (wrapV >= 0 && wrapV <= 3)
		{
			((Texture)value).wrapModeV = (TextureWrapMode)wrapV;
		}
		owned.Add((Object)(object)value);
		textures.Add(key, value);
		return value;
	}

	private static string FallbackProperty(string name)
	{
		if (name == "_NormTex")
		{
			return "_BumpMap";
		}
		if (name == "_EmissionTex")
		{
			return "_EmissionMap";
		}
		return name;
	}

	internal static string Fingerprint(Character actor)
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.Append("native-materials-lod-v3;");
		Renderer[] array = CaptureRenderers(actor);
		foreach (Renderer val in array)
		{
			if (!val.enabled || val is ParticleSystemRenderer || val is LineRenderer || val is TrailRenderer)
			{
				continue;
			}
			Mesh val2 = null;
			SkinnedMeshRenderer val3 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null);
			if (Object.op_Implicit((Object)(object)val3))
			{
				val2 = val3.sharedMesh;
			}
			else
			{
				MeshFilter component = ((Component)val).GetComponent<MeshFilter>();
				if (Object.op_Implicit((Object)(object)component))
				{
					val2 = component.sharedMesh;
				}
			}
			if (Object.op_Implicit((Object)(object)val2))
			{
				stringBuilder.Append(GuideBook.Canonical(((Object)val).name)).Append('|').Append(GuideBook.Canonical(((Object)val2).name))
					.Append('|')
					.Append(val2.vertexCount)
					.Append('|')
					.Append(val2.subMeshCount)
					.Append(';');
			}
		}
		return GuideBook.Hash(stringBuilder.ToString());
	}

	public static bool Capture(Character actor, string key, string folder)
	{
		List<Part> list = new List<Part>();
		IEnumerator enumerator = Collect(actor, folder, list);
		while (enumerator.MoveNext())
		{
		}
		if (list.Count == 0)
		{
			return false;
		}
		WriteParts(key, folder, list);
		return true;
	}

	public static IEnumerator CaptureAsync(Character actor, string key, string folder, Action<bool> completed)
	{
		List<Part> parts = new List<Part>();
		IEnumerator collect = Collect(actor, folder, parts);
		Stopwatch timer = new Stopwatch();
		bool more = true;
		while (more)
		{
			timer.Restart();
			do
			{
				more = collect.MoveNext();
			}
			while (more && timer.ElapsedMilliseconds < 3);
			if (more)
			{
				yield return null;
			}
		}
		if (!Object.op_Implicit((Object)(object)actor) || parts.Count == 0)
		{
			completed(obj: false);
			yield break;
		}
		WorkResult work = new WorkResult();
		ThreadPool.QueueUserWorkItem(delegate
		{
			try
			{
				WriteParts(key, folder, parts);
			}
			catch (Exception error)
			{
				work.Error = error;
			}
			finally
			{
				work.Done = true;
			}
		});
		while (!work.Done)
		{
			yield return null;
		}
		if (work.Error != null)
		{
			throw work.Error;
		}
		completed(obj: true);
	}

	private static IEnumerator Collect(Character actor, string folder, List<Part> parts)
	{
		Dictionary<Texture, TextureCopy> textures = new Dictionary<Texture, TextureCopy>();
		Dictionary<Material, MaterialSnapshot> surfaces = new Dictionary<Material, MaterialSnapshot>();
		int textureBytes = 0;
		int totalVertices = 0;
		try
		{
			Renderer[] array = CaptureRenderers(actor);
			foreach (Renderer renderer in array)
			{
				if (!Object.op_Implicit((Object)(object)actor))
				{
					break;
				}
				if (!Object.op_Implicit((Object)(object)renderer) || !renderer.enabled || renderer is ParticleSystemRenderer || renderer is TrailRenderer || renderer is LineRenderer || (Object)(object)((Component)renderer).GetComponentInParent<Character>() != (Object)(object)actor)
				{
					continue;
				}
				Matrix4x4 toRoot = ((Component)actor).transform.worldToLocalMatrix;
				Mesh mesh = null;
				bool owned = false;
				try
				{
					SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
					if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.sharedMesh))
					{
						mesh = new Mesh();
						owned = true;
						val.BakeMesh(mesh);
					}
					else
					{
						MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>();
						if (Object.op_Implicit((Object)(object)component))
						{
							mesh = component.sharedMesh;
						}
					}
					if (!Object.op_Implicit((Object)(object)mesh) || mesh.vertexCount == 0 || totalVertices + mesh.vertexCount > 2000000 || parts.Count >= 2048)
					{
						continue;
					}
					Vector3[] vertices = mesh.vertices;
					Vector3[] normals = mesh.normals;
					Vector2[] uv = mesh.uv;
					Vector2[] uv2 = mesh.uv2;
					Vector4[] tangents = mesh.tangents;
					Color32[] colors = mesh.colors32;
					Matrix4x4 val2 = toRoot * renderer.localToWorldMatrix;
					Matrix4x4 inverse = ((Matrix4x4)(ref val2)).inverse;
					Matrix4x4 transpose = ((Matrix4x4)(ref inverse)).transpose;
					for (int j = 0; j < vertices.Length; j++)
					{
						ref Vector3 reference = ref vertices[j];
						reference = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(vertices[j]);
						if (normals.Length == vertices.Length)
						{
							ref Vector3 reference2 = ref normals[j];
							Vector3 val3 = ((Matrix4x4)(ref transpose)).MultiplyVector(normals[j]);
							reference2 = ((Vector3)(ref val3)).normalized;
						}
						if (tangents.Length == vertices.Length)
						{
							Vector4 val4 = tangents[j];
							Vector3 val5 = ((Matrix4x4)(ref val2)).MultiplyVector(new Vector3(val4.x, val4.y, val4.z));
							Vector3 normalized = ((Vector3)(ref val5)).normalized;
							ref Vector4 reference3 = ref tangents[j];
							reference3 = new Vector4(normalized.x, normalized.y, normalized.z, val4.w * (float)((!(((Matrix4x4)(ref val2)).determinant < 0f)) ? 1 : (-1)));
						}
					}
					Material[] sharedMaterials = renderer.sharedMaterials;
					for (int k = 0; k < mesh.subMeshCount && k < sharedMaterials.Length; k++)
					{
						Material val6 = sharedMaterials[k];
						if (!Object.op_Implicit((Object)(object)val6) || (int)mesh.GetTopology(k) != 0 || parts.Count >= 2048)
						{
							continue;
						}
						Part part = new Part();
						part.Vertices = vertices;
						part.Normals = normals;
						part.UV = uv;
						part.UV2 = uv2;
						part.Tangents = tangents;
						part.Colors = colors;
						part.Triangles = mesh.GetTriangles(k);
						part.Color = (val6.HasProperty("_Color") ? val6.GetColor("_Color") : Color.white);
						part.Emission = (val6.HasProperty("_EmissionColor") ? val6.GetColor("_EmissionColor") : Color.black);
						Part part2 = part;
						if (!surfaces.TryGetValue(val6, out var value))
						{
							value = CaptureSurface(val6, textures, ref textureBytes);
							surfaces.Add(val6, value);
						}
						part2.Surface = value;
						Texture val7 = (val6.HasProperty("_MainTex") ? val6.GetTexture("_MainTex") : null);
						if (Object.op_Implicit((Object)(object)val7))
						{
							if (!textures.TryGetValue(val7, out var value2))
							{
								value2 = ReadTexture(val7, 100663296 - textureBytes);
								textures.Add(val7, value2);
								if (value2 != null)
								{
									textureBytes += value2.Pixels.Length;
								}
							}
							part2.Texture = value2;
						}
						parts.Add(part2);
					}
					totalVertices += mesh.vertexCount;
					goto IL_0591;
				}
				catch (Exception ex)
				{
					if (Object.op_Implicit((Object)(object)Plugin.Instance))
					{
						Plugin.Instance.Report(new InvalidOperationException("Cannot archive mesh " + ((Object)renderer).name + ": " + ex.Message));
					}
					goto IL_0591;
				}
				finally
				{
					if (owned && Object.op_Implicit((Object)(object)mesh))
					{
						Object.Destroy((Object)(object)mesh);
					}
				}
				IL_0591:
				yield return null;
			}
		}
		finally
		{
		}
	}

	private static void WriteParts(string key, string folder, List<Part> parts)
	{
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: 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)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: 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)
		//IL_0269: Unknown result type (might be due to invalid IL or missing references)
		//IL_0283: Unknown result type (might be due to invalid IL or missing references)
		//IL_02de: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
		foreach (Part part in parts)
		{
			SaveCopy(part.Texture, folder);
			foreach (MaterialProperty property in part.Surface.Properties)
			{
				SaveCopy(property.Texture, folder);
			}
		}
		using MemoryStream memoryStream = new MemoryStream();
		using (GZipStream output = new GZipStream(memoryStream, CompressionMode.Compress, leaveOpen: true))
		{
			using BinaryWriter binaryWriter = new BinaryWriter(output);
			binaryWriter.Write(1095124786);
			binaryWriter.Write(parts.Count);
			foreach (Part part2 in parts)
			{
				Write(binaryWriter, part2.Color);
				Write(binaryWriter, part2.Emission);
				binaryWriter.Write((part2.Texture != null) ? part2.Texture.Filename : "");
				WriteSurface(binaryWriter, part2.Surface);
				binaryWriter.Write(part2.Vertices.Length);
				binaryWriter.Write(part2.Tangents.Length == part2.Vertices.Length);
				for (int i = 0; i < part2.Vertices.Length; i++)
				{
					Write(binaryWriter, part2.Vertices[i]);
					Write(binaryWriter, (part2.Normals.Length == part2.Vertices.Length) ? part2.Normals[i] : Vector3.up);
					Vector2 val = ((part2.UV.Length == part2.Vertices.Length) ? part2.UV[i] : Vector2.zero);
					binaryWriter.Write(val.x);
					binaryWriter.Write(val.y);
					Vector4 val2 = (Vector4)((part2.Tangents.Length == part2.Vertices.Length) ? part2.Tangents[i] : new Vector4(1f, 0f, 0f, 1f));
					binaryWriter.Write(val2.x);
					binaryWriter.Write(val2.y);
					binaryWriter.Write(val2.z);
					binaryWriter.Write(val2.w);
					Vector2 val3 = ((part2.UV2.Length == part2.Vertices.Length) ? part2.UV2[i] : Vector2.zero);
					binaryWriter.Write(val3.x);
					binaryWriter.Write(val3.y);
					Color32 val4 = (Color32)((part2.Colors.Length == part2.Vertices.Length) ? part2.Colors[i] : new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue));
					binaryWriter.Write(val4.r);
					binaryWriter.Write(val4.g);
					binaryWriter.Write(val4.b);
					binaryWriter.Write(val4.a);
				}
				binaryWriter.Write(part2.Triangles.Length);
				int[] triangles = part2.Triangles;
				foreach (int value in triangles)
				{
					binaryWriter.Write(value);
				}
			}
		}
		GuideStore.AtomicWrite(Path.Combine(folder, key + ".afg"), memoryStream.ToArray());
	}

	private static TextureCopy ReadTexture(Texture texture, int remainingBytes)
	{
		//IL_007c: 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_00bd: Expected O, but got Unknown
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		if (remainingBytes < 4)
		{
			return null;
		}
		float num = Mathf.Min(1f, 2048f / (float)Mathf.Max(texture.width, texture.height));
		int num2 = Mathf.Max(1, Mathf.RoundToInt((float)texture.width * num));
		int num3 = Mathf.Max(1, Mathf.RoundToInt((float)texture.height * num));
		while ((long)num2 * (long)num3 * 4 > remainingBytes)
		{
			num2 = Mathf.Max(1, num2 / 2);
			num3 = Mathf.Max(1, num3 / 2);
		}
		RenderTexture active = RenderTexture.active;
		bool flag = !GraphicsFormatUtility.IsSRGBFormat(texture.graphicsFormat);
		RenderTexture temporary = RenderTexture.GetTemporary(num2, num3, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)(flag ? 1 : 2));
		Texture2D val = null;
		try
		{
			Graphics.Blit(texture, temporary);
			RenderTexture.active = temporary;
			val = new Texture2D(num2, num3, (TextureFormat)4, false, flag);
			val.ReadPixels(new Rect(0f, 0f, (float)num2, (float)num3), 0, 0, false);
			TextureCopy textureCopy = new TextureCopy();
			textureCopy.Width = num2;
			textureCopy.Height = num3;
			textureCopy.Format = ((Texture)val).graphicsFormat;
			textureCopy.Pixels = val.GetRawTextureData();
			textureCopy.Linear = flag;
			return textureCopy;
		}
		finally
		{
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
			if (Object.op_Implicit((Object)(object)val))
			{
				Object.Destroy((Object)(object)val);
			}
		}
	}

	private static void Write(BinaryWriter writer, Vector3 v)
	{
		writer.Write(v.x);
		writer.Write(v.y);
		writer.Write(v.z);
	}

	private static void Write(BinaryWriter writer, Color c)
	{
		writer.Write(c.r);
		writer.Write(c.g);
		writer.Write(c.b);
		writer.Write(c.a);
	}

	private static Vector3 ReadVector(BinaryReader r)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
	}

	private static Color ReadColor(BinaryReader r)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		return new Color(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
	}

	public static GameObject Load(string folder, string key, List<Object> owned)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: 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_0604: Unknown result type (might be due to invalid IL or missing references)
		//IL_061f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0629: Unknown result type (might be due to invalid IL or missing references)
		//IL_0589: Unknown result type (might be due to invalid IL or missing references)
		//IL_058e: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0660: Unknown result type (might be due to invalid IL or missing references)
		//IL_0667: Expected O, but got Unknown
		//IL_06ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d5: Expected O, but got Unknown
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0202: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		//IL_0236: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bd: Expected O, but got Unknown
		//IL_0357: Unknown result type (might be due to invalid IL or missing references)
		//IL_035e: Expected O, but got Unknown
		//IL_0368: Unknown result type (might be due to invalid IL or missing references)
		//IL_0387: Unknown result type (might be due to invalid IL or missing references)
		//IL_046c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0473: Expected O, but got Unknown
		//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f0: Expected O, but got Unknown
		string path = Path.Combine(folder, key + ".afg");
		if (!File.Exists(path))
		{
			return null;
		}
		GameObject val = new GameObject("Field Guide Visual Specimen");
		val.layer = 31;
		val.SetActive(false);
		try
		{
			Dictionary<string, Texture2D> dictionary = new Dictionary<string, Texture2D>();
			Dictionary<string, Material> materials = new Dictionary<string, Material>();
			using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
			{
				using GZipStream input = new GZipStream(stream, CompressionMode.Decompress);
				using BinaryReader binaryReader = new BinaryReader(input);
				int num = binaryReader.ReadInt32();
				if (num != 1095124786 && num != 1095124785)
				{
					throw new InvalidDataException("Unsupported specimen format");
				}
				bool flag = num == 1095124786;
				int num2 = binaryReader.ReadInt32();
				if (num2 < 1 || num2 > 2048)
				{
					throw new InvalidDataException("Invalid specimen part count");
				}
				int num3 = 0;
				for (int i = 0; i < num2; i++)
				{
					Color color = ReadColor(binaryReader);
					Color val2 = ReadColor(binaryReader);
					string text = binaryReader.ReadString();
					Material val3 = (flag ? ReadSurface(binaryReader, folder, dictionary, materials, owned) : null);
					int num4 = binaryReader.ReadInt32();
					num3 += num4;
					if (num4 < 1 || num4 > 2000000 || num3 > 16000000)
					{
						throw new InvalidDataException("Specimen vertex budget exceeded");
					}
					bool flag2 = flag && binaryReader.ReadBoolean();
					Vector3[] array = (Vector3[])(object)new Vector3[num4];
					Vector3[] array2 = (Vector3[])(object)new Vector3[num4];
					Vector2[] array3 = (Vector2[])(object)new Vector2[num4];
					Vector4[] array4 = (Vector4[])(object)new Vector4[num4];
					Vector2[] array5 = (Vector2[])(object)new Vector2[num4];
					Color32[] array6 = (Color32[])(object)new Color32[num4];
					for (int j = 0; j < num4; j++)
					{
						ref Vector3 reference = ref array[j];
						reference = ReadVector(binaryReader);
						ref Vector3 reference2 = ref array2[j];
						reference2 = ReadVector(binaryReader);
						ref Vector2 reference3 = ref array3[j];
						reference3 = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
						if (flag)
						{
							ref Vector4 reference4 = ref array4[j];
							reference4 = new Vector4(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
							ref Vector2 reference5 = ref array5[j];
							reference5 = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
							ref Color32 reference6 = ref array6[j];
							reference6 = new Color32(binaryReader.ReadByte(), binaryReader.ReadByte(), binaryReader.ReadByte(), binaryReader.ReadByte());
						}
					}
					int num5 = binaryReader.ReadInt32();
					if (num5 < 0 || num5 > 36000000 || num5 % 3 != 0)
					{
						throw new InvalidDataException("Invalid specimen topology");
					}
					int[] array7 = new int[num5];
					for (int k = 0; k < array7.Length; k++)
					{
						array7[k] = binaryReader.ReadInt32();
						if (array7[k] < 0 || array7[k] >= num4)
						{
							throw new InvalidDataException("Invalid specimen index");
						}
					}
					Mesh val4 = new Mesh();
					((Object)val4).name = "Archived specimen mesh";
					val4.indexFormat = (IndexFormat)(num4 > 65535);
					Mesh val5 = val4;
					owned.Add((Object)(object)val5);
					val5.vertices = array;
					val5.normals = array2;
					val5.uv = array3;
					val5.triangles = array7;
					val5.RecalculateBounds();
					if (flag)
					{
						val5.uv2 = array5;
						val5.colors32 = array6;
						if (flag2)
						{
							val5.tangents = array4;
						}
						else
						{
							val5.RecalculateTangents();
						}
					}
					Material val6 = val3;
					if (!Object.op_Implicit((Object)(object)val6))
					{
						val6 = new Material(Shader.Find("Standard"));
						owned.Add((Object)(object)val6);
						val6.color = color;
						val6.SetFloat("_Glossiness", 0.25f);
						val6.SetColor("_EmissionColor", val2);
						val6.EnableKeyword("_EMISSION");
					}
					if (!flag && Regex.IsMatch(text, "^[a-f0-9]{64}\\.png$"))
					{
						if (!dictionary.TryGetValue(text, out var value))
						{
							string text2 = Path.Combine(folder, text);
							if (File.Exists(text2) && new FileInfo(text2).Length < 33554432)
							{
								value = new Texture2D(2, 2, (TextureFormat)4, true);
								if (!ImageConversion.LoadImage(value, File.ReadAllBytes(text2), true))
								{
									Object.Destroy((Object)(object)value);
									value = null;
								}
								else
								{
									((Texture)value).filterMode = (FilterMode)2;
									((Texture)value).anisoLevel = 4;
									owned.Add((Object)(object)value);
									dictionary.Add(text, value);
								}
							}
						}
						if (Object.op_Implicit((Object)(object)value))
						{
							val6.mainTexture = (Texture)(object)value;
						}
					}
					GameObject val7 = new GameObject("Visual part", new Type[2]
					{
						typeof(MeshFilter),
						typeof(MeshRenderer)
					});
					val7.layer = 31;
					val7.transform.SetParent(val.transform, false);
					val7.GetComponent<MeshFilter>().sharedMesh = val5;
					MeshRenderer component = val7.GetComponent<MeshRenderer>();
					((Renderer)component).sharedMaterial = val6;
					((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
					((Renderer)component).receiveShadows = false;
					((Renderer)component).lightProbeUsage = (LightProbeUsage)0;
				}
			}
			Dictionary<string, List<CombineInstance>> dictionary2 = new Dictionary<string, List<CombineInstance>>();
			Dictionary<string, Material> dictionary3 = new Dictionary<string, Material>();
			MeshRenderer[] componentsInChildren = val.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val8 in componentsInChildren)
			{
				Material sharedMaterial = ((Renderer)val8).sharedMaterial;
				string text3;
				if (!((Object)sharedMaterial).name.StartsWith("Archived material "))
				{
					string[] array8 = new string[5]
					{
						Object.op_Implicit((Object)(object)sharedMaterial.mainTexture) ? ((Object)sharedMaterial.mainTexture).GetInstanceID().ToString() : "none",
						"|",
						null,
						null,
						null
					};
					Color color2 = sharedMaterial.color;
					array8[2] = ((Color)(ref color2)).ToString("F3");
					array8[3] = "|";
					Color color3 = sharedMaterial.GetColor("_EmissionColor");
					array8[4] = ((Color)(ref color3)).ToString("F3");
					text3 = string.Concat(array8);
				}
				else
				{
					text3 = ((Object)sharedMaterial).name;
				}
				string key2 = text3;
				if (!dictionary2.TryGetValue(key2, out var value2))
				{
					value2 = new List<CombineInstance>();
					dictionary2.Add(key2, value2);
					dictionary3.Add(key2, sharedMaterial);
				}
				List<CombineInstance> list = value2;
				CombineInstance item = default(CombineInstance);
				((CombineInstance)(ref item)).mesh = ((Component)val8).GetComponent<MeshFilter>().sharedMesh;
				((CombineInstance)(ref item)).transform = Matrix4x4.identity;
				list.Add(item);
				((Renderer)val8).enabled = false;
			}
			foreach (KeyValuePair<string, List<CombineInstance>> item2 in dictionary2)
			{
				Mesh val9 = new Mesh();
				val9.indexFormat = (IndexFormat)1;
				((Object)val9).name = "Combined visual specimen";
				Mesh val10 = val9;
				owned.Add((Object)(object)val10);
				val10.CombineMeshes(item2.Value.ToArray(), true, true);
				val10.RecalculateBounds();
				GameObject val11 = new GameObject("Combined specimen surface", new Type[2]
				{
					typeof(MeshFilter),
					typeof(MeshRenderer)
				});
				val11.layer = 31;
				val11.transform.SetParent(val.transform, false);
				val11.GetComponent<MeshFilter>().sharedMesh = val10;
				MeshRenderer component2 = val11.GetComponent<MeshRenderer>();
				((Renderer)component2).sharedMaterial = dictionary3[item2.Key];
				((Renderer)component2).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)component2).receiveShadows = false;
				((Renderer)component2).lightProbeUsage = (LightProbeUsage)0;
				((Renderer)component2).reflectionProbeUsage = (ReflectionProbeUsage)0;
			}
			return val;
		}
		catch
		{
			Object.Destroy((Object)(object)val);
			throw;
		}
	}
}
public sealed class SpecimenViewer : IDisposable
{
	private static int nextSlot;

	private readonly int slot = nextSlot++ % 64;

	private readonly List<Object> owned = new List<Object>();

	private GameObject root;

	private GameObject rig;

	private Camera camera;

	private Vector3 center;

	private float yaw = 25f;

	private float radius = 1f;

	private float zoom = 1f;

	private float distance = 4f;

	private Light[] sceneLights;

	private int[] sceneLightMasks;

	private float nextLightScan;

	public RenderTexture Texture;

	public bool Available => Object.op_Implicit((Object)(object)root);

	public void Show(string folder, string key)
	{
		//IL_004f: 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_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_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Expected O, but got Unknown
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Expected O, but got Unknown
		//IL_0213: Unknown result type (might be due to invalid IL or missing references)
		//IL_021f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: Unknown result type (might be due to invalid IL or missing references)
		//IL_025a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02de: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Expected O, but got Unknown
		//IL_031d: Unknown result type (might be due to invalid IL or missing references)
		//IL_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0375: 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_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		Clear();
		root = ModelArchive.Load(folder, key, owned);
		if (!Object.op_Implicit((Object)(object)root))
		{
			return;
		}
		root.transform.position = new Vector3((float)(12000 + slot * 4096), 12000f, 12000f);
		root.SetActive(true);
		Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>();
		Bounds val = default(Bounds);
		bool flag = true;
		Renderer[] array = componentsInChildren;
		foreach (Renderer val2 in array)
		{
			if (val2.enabled)
			{
				if (flag)
				{
					val = val2.bounds;
					flag = false;
				}
				else
				{
					((Bounds)(ref val)).Encapsulate(val2.bounds);
				}
			}
		}
		center = ((Bounds)(ref val)).center;
		Vector3 extents = ((Bounds)(ref val)).extents;
		radius = Mathf.Max(0.3f, ((Vector3)(ref extents)).magnitude);
		zoom = 1f;
		rig = new GameObject("Field Guide Specimen Camera");
		camera = rig.AddComponent<Camera>();
		((Behaviour)camera).enabled = false;
		camera.cullingMask = int.MinValue;
		camera.clearFlags = (CameraClearFlags)2;
		camera.backgroundColor = new Color(0f, 0f, 0f, 0f);
		camera.nearClipPlane = 0.03f;
		camera.farClipPlane = radius * 12f + 10f;
		camera.fieldOfView = 34f;
		camera.allowHDR = false;
		camera.allowMSAA = true;
		Texture = new RenderTexture(1536, 1200, 24, (RenderTextureFormat)0);
		Texture.antiAliasing = 4;
		((Texture)Texture).filterMode = (FilterMode)1;
		Texture.Create();
		camera.targetTexture = Texture;
		camera.aspect = 1.28f;
		Vector2 val3 = new Vector2(((Bounds)(ref val)).extents.x, ((Bounds)(ref val)).extents.z);
		float magnitude = ((Vector2)(ref val3)).magnitude;
		float num = Mathf.Tan(camera.fieldOfView * 0.5f * ((float)Math.PI / 180f));
		distance = Mathf.Max(((Bounds)(ref val)).extents.y / num, magnitude / (num * camera.aspect)) * 1.12f + magnitude * 0.45f;
		Light val4 = rig.AddComponent<Light>();
		val4.type = (LightType)1;
		val4.intensity = 0.9f;
		val4.color = new Color(1f, 0.97f, 0.93f);
		val4.cullingMask = int.MinValue;
		GameObject val5 = new GameObject("Specimen fill light");
		val5.transform.SetParent(rig.transform, false);
		val5.transform.localPosition = new Vector3((0f - radius) * 2f, radius, radius);
		val5.transform.localRotation = Quaternion.Euler(10f, -65f, 0f);
		Light val6 = val5.AddComponent<Light>();
		val6.type = (LightType)1;
		val6.intensity = 0.32f;
		val6.color = new Color(0.75f, 0.85f, 1f);
		val6.cullingMask = int.MinValue;
		nextLightScan = 0f;
		Render(0f);
	}

	public void Rotate(float amount)
	{
		yaw += amount;
	}

	public void Zoom(float amount)
	{
		zoom = Mathf.Clamp(zoom + amount, 0.65f, 1.7f);
	}

	public void Render(float delta)
	{
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_004e: 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_0060: 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_0072: 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_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: 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_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)root) || !Object.op_Implicit((Object)(object)camera))
		{
			return;
		}
		yaw += delta * 8f;
		Vector3 val = Quaternion.Euler(7f, yaw, 0f) * Vector3.forward;
		((Component)camera).transform.position = center + val * distance * zoom;
		((Component)camera).transform.LookAt(center);
		if (sceneLights == null || Time.unscaledTime >= nextLightScan)
		{
			nextLightScan = Time.unscaledTime + 2f;
			sceneLights = Object.FindObjectsOfType<Light>();
			sceneLightMasks = new int[sceneLights.Length];
		}
		AmbientMode ambientMode = RenderSettings.ambientMode;
		Color ambientLight = RenderSettings.ambientLight;
		SphericalHarmonicsL2 ambientProbe = RenderSettings.ambientProbe;
		bool fog = RenderSettings.fog;
		try
		{
			for (int i = 0; i < sceneLights.Length; i++)
			{
				Light val2 = sceneLights[i];
				if (Object.op_Implicit((Object)(object)val2))
				{
					sceneLightMasks[i] = val2.cullingMask;
					if (!((Component)val2).transform.IsChildOf(rig.transform))
					{
						val2.cullingMask &= 0x7FFFFFFF;
					}
				}
			}
			RenderSettings.ambientMode = (AmbientMode)3;
			RenderSettings.ambientLight = new Color(0.18f, 0.19f, 0.21f);
			SphericalHarmonicsL2 ambientProbe2 = default(SphericalHarmonicsL2);
			((SphericalHarmonicsL2)(ref ambientProbe2)).AddAmbientLight(new Color(0.18f, 0.19f, 0.21f));
			RenderSettings.ambientProbe = ambientProbe2;
			RenderSettings.fog = false;
			camera.Render();
		}
		finally
		{
			RenderSettings.ambientMode = ambientMode;
			RenderSettings.ambientLight = ambientLight;
			RenderSettings.ambientProbe = ambientProbe;
			RenderSettings.fog = fog;
			for (int j = 0; j < sceneLights.Length; j++)
			{
				if (Object.op_Implicit((Object)(object)sceneLights[j]))
				{
					sceneLights[j].cullingMask = sceneLightMasks[j];
				}
			}
		}
	}

	private void Clear()
	{
		if (Object.op_Implicit((Object)(object)rig))
		{
			rig.SetActive(false);
			Object.Destroy((Object)(object)rig);
		}
		if (Object.op_Implicit((Object)(object)root))
		{
			root.SetActive(false);
			Object.Destroy((Object)(object)root);
		}
		foreach (Object item in owned)
		{
			if (Object.op_Implicit(item))
			{
				Object.Destroy(item);
			}
		}
		owned.Clear();
		if (Object.op_Implicit((Object)(object)Texture))
		{
			Texture.Release();
			Object.Destroy((Object)(object)Texture);
		}
		root = null;
		rig = null;
		camera = null;
		Texture = null;
		sceneLights = null;
		sceneLightMasks = null;
	}

	public void Dispose()
	{
		Clear();
	}
}
[HarmonyPatch(typeof(Character), "ReceiveHit", new Type[]
{
	typeof(Object),
	typeof(DamageList),
	typeof(Vector3),
	typeof(Vector3),
	typeof(float),
	typeof(float),
	typeof(Character),
	typeof(float),
	typeof(bool)
})]
internal static class HitSourceContext
{
	[ThreadStatic]
	internal static Object Source;

	private static void Prefix(Object __0, out Object __state)
	{
		__state = Source;
		Source = __0;
	}

	private static void Finalizer(Object __state)
	{
		Source = __state;
	}

	internal static string Description(Weapon weapon, DamageList damage)
	{
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)weapon))
		{
			return ((Item)weapon).Name;
		}
		Object source = Source;
		Item val = (Item)(object)((source is Item) ? source : null);
		if (Object.op_Implicit((Object)(object)val))
		{
			return val.Name;
		}
		Object source2 = Source;
		StatusEffect val2 = (StatusEffect)(object)((source2 is StatusEffect) ? source2 : null);
		if (Object.op_Implicit((Object)(object)val2))
		{
			return val2.StatusName;
		}
		List<string> list = new List<string>();
		if (RawHitContext.Types != null)
		{
			foreach (int type in RawHitContext.Types)
			{
				string typeName = DamageType.GetTypeName((Types)type);
				if (!list.Contains(typeName))
				{
					list.Add(typeName);
				}
			}
		}
		else if (damage != null)
		{
			foreach (DamageType item in damage.List)
			{
				if (item.Damage > 0f && !list.Contains(DamageType.GetTypeName(item.Type)))
				{
					list.Add(DamageType.GetTypeName(item.Type));
				}
			}
		}
		if (list.Count <= 0)
		{
			return "Ability hit";
		}
		return string.Join(" / ", list.ToArray()) + " attack";
	}
}
[HarmonyPatch(typeof(Character), "VitalityHit", new Type[]
{
	typeof(Character),
	typeof(float),
	typeof(Vector3)
})]
internal static class DirectDamageObserver
{
	private static void Prefix(Character __instance, Character __0, float __1)
	{
		try
		{
			if (!Plugin.Ready || __1 <= 0f)
			{
				return;
			}
			Character val = ((Plugin.Local(__0) && Plugin.Creature(__instance)) ? __0 : ((Plugin.Local(__instance) && Plugin.Creature(__0)) ? __instance : null));
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			Character val2 = (((Object)(object)val == (Object)(object)__instance) ? __0 : __instance);
			if (EnemyFilter.IsEnemy(val, val2))
			{
				Plugin.Instance.Discover(val, val2);
				Plugin.Instance.RegisterCombat(val, val2);
				if ((Object)(object)val == (Object)(object)__instance)
				{
					Plugin.Instance.LastEnemies[Plugin.Uid(val)] = new Plugin.Opponent
					{
						Actor = val2,
						Time = Time.unscaledTime
					};
				}
			}
		}
		catch (Exception ex)
		{
			if (Object.op_Implicit((Object)(object)Plugin.Instance))
			{
				Plugin.Instance.Report(ex);
			}
		}
	}
}
[HarmonyPatch(typeof(Character), "ReceiveHit", new Type[]
{
	typeof(Object),
	typeof(DamageList),
	typeof(Vector3),
	typeof(Vector3),
	typeof(float),
	typeof(float),
	typeof(Character),
	typeof(float),
	typeof(bool)
})]
internal static class RawHitContext
{
	[ThreadStatic]
	internal static List<int> Types;

	private static void Prefix(DamageList __1, out List<int> __state)
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Expected I4, but got Unknown
		__state = Types;
		Types = null;
		if (!Plugin.Ready || __1 == null)
		{
			return;
		}
		Types = new List<int>();
		foreach (DamageType item in __1.List)
		{
			if (item.Damage > 0f)
			{
				Types.Add((int)item.Type);
			}
		}
	}

	private static void Finalizer(List<int> __state)
	{
		Types = __state;
	}
}
[HarmonyPatch(typeof(Character), "OnReceiveHit")]
internal static class HitObserver
{
	internal sealed class State
	{
		internal float Health;

		internal bool Alive;
	}

	private static void Prefix(Character __instance, Character __7, out State __state)
	{
		__state = null;
		try
		{
			if (!Plugin.Ready)
			{
				return;
			}
			__state = new State
			{
				Health = __instance.Health,
				Alive = __instance.Alive
			};
			Character val = ((Plugin.Local(__7) && Plugin.Creature(__instance)) ? __7 : ((Plugin.Local(__instance) && Plugin.Creature(__7)) ? __instance : null));
			if (!Object.op_Implicit((Object)(object)val) || !__state.Alive)
			{
				return;
			}
			Character val2 = (((Object)(object)val == (Object)(object)__instance) ? __7 : __instance);
			if (EnemyFilter.IsEnemy(val, val2))
			{
				Plugin.Instance.Discover(val, val2);
				Plugin.Instance.RegisterCombat(val, val2);
				if ((Object)(object)val == (Object)(object)__instance)
				{
					Plugin.Instance.LastEnemies[Plugin.Uid(val)] = new Plugin.Opponent
					{
						Actor = val2,
						Time = Time.unscaledTime
					};
				}
			}
		}
		catch (Exception ex)
		{
			if (Object.op_Implicit((Object)(object)Plugin.Instance))
			{
				Plugin.Instance.Report(ex);
			}
		}
	}

	private static void Postfix(Character __instance, Weapon __0, float __1, DamageList __2, Character __7, State __state)
	{
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Expected I4, but got Unknown
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Expected I4, but got U