Decompiled source of TooManyEmotesProgression v1.0.1

TooManyEmotesProgression.dll

Decompiled an hour ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DunGen;
using DunGen.Graph;
using GameNetcodeStuff;
using HarmonyLib;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using TooManyEmotes;
using TooManyEmotes.Networking;
using TooManyEmotes.Patches;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("DunGen")]
[assembly: IgnoresAccessChecksTo("DunGen.Integration.ASPP")]
[assembly: IgnoresAccessChecksTo("DunGen.Integration.UnityNav")]
[assembly: IgnoresAccessChecksTo("EasyTextEffects")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.XR.CoreUtils")]
[assembly: IgnoresAccessChecksTo("Unity.XR.Management")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.ConformanceAutomation")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MetaQuestSupport")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MockRuntime")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.OculusQuestSupport")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.RuntimeDebugger")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.SpatialTracking")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("UnityEngine.XR.LegacyInputHelpers")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("TooManyEmotesProgression")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("TooManyEmotes addon: emotes are no longer bought from the terminal. They turn up on moons as dancing figurines, and whoever claims one first keeps the emote.")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("TooManyEmotesProgression")]
[assembly: AssemblyTitle("TooManyEmotesProgression")]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was fully created with the assistance of Generative AI: the code, its documentation and the icon-drawing script were written by Claude (Anthropic) through Claude Code, directed and play-tested by Maco.")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "Anthropic")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TooManyEmotesProgression
{
	internal static class Cfg
	{
		public static ConfigEntry<bool> FigurinesOnly;

		public static ConfigEntry<bool> BreakOnClaim;

		public static ConfigEntry<int> FigurinesOnEasiestMoon;

		public static ConfigEntry<int> FigurinesOnHardestMoon;

		public static ConfigEntry<string> ScaleBy;

		public static ConfigEntry<int> InteriorSmall;

		public static ConfigEntry<int> InteriorLarge;

		public static ConfigEntry<int> SpawnVariance;

		public static ConfigEntry<int> MinValue;

		public static ConfigEntry<int> MaxValue;

		public static ConfigEntry<string> ItemName;

		public static ConfigEntry<string> SourceItem;

		public static ConfigEntry<string> Model;

		public static ConfigEntry<float> CubeSize;

		public static ConfigEntry<float> CubeGlow;

		public static ConfigEntry<float> FigureHeight;

		public static ConfigEntry<float> PropScale;

		public static ConfigEntry<string> SpawnFigurineKey;

		public static ConfigEntry<bool> VerboseLogs;

		public static ConfigEntry<float> WeightCommon;

		public static ConfigEntry<float> WeightRare;

		public static ConfigEntry<float> WeightEpic;

		public static ConfigEntry<float> WeightLegendary;

		public static ConfigEntry<bool> TintByRarity;

		public static ConfigEntry<float> TintStrength;

		public static ConfigEntry<bool> ShowRarityColor;

		public static ConfigEntry<bool> LogVanillaItemNames;

		public static void Bind(ConfigFile c)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Expected O, but got Unknown
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Expected O, but got Unknown
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Expected O, but got Unknown
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Expected O, but got Unknown
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Expected O, but got Unknown
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Expected O, but got Unknown
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Expected O, but got Unknown
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Expected O, but got Unknown
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Expected O, but got Unknown
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_0370: Expected O, but got Unknown
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Expected O, but got Unknown
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Expected O, but got Unknown
			//IL_040e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0418: Expected O, but got Unknown
			//IL_0461: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Expected O, but got Unknown
			FigurinesOnly = c.Bind<bool>("Progression", "FigurinesOnly", true, "Empty the terminal emote store so figurines are the only way to unlock an emote. HOST ONLY: the host's setting is sent to every client on join, so a client's own value does nothing in someone else's lobby. Off = figurines are a bonus route alongside the shop.");
			BreakOnClaim = c.Bind<bool>("Progression", "BreakOnClaim", true, "The figurine is destroyed when you claim its emote, so a spent one is not left lying around. Off = it survives, which only matters if you have also given figurines a scrap value; it stays marked as claimed either way. HOST ONLY: the host's setting is sent to every client on join.");
			FigurinesOnEasiestMoon = c.Bind<int>("Spawning", "FigurinesOnEasiestMoon", 1, new ConfigDescription("How many to place on the least dangerous moon you have installed. HOST ONLY.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			FigurinesOnHardestMoon = c.Bind<int>("Spawning", "FigurinesOnHardestMoon", 5, new ConfigDescription("How many to place on the most dangerous moon you have installed. Every other moon lands somewhere between this and FigurinesOnEasiestMoon. HOST ONLY.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ScaleBy = c.Bind<string>("Spawning", "ScaleBy", "Interior", new ConfigDescription("What decides where a run sits between the two numbers above.\nInterior - the size of the interior that actually generated, measured in scrap spawn points. This is the one that keeps big modded interiors findable: a huge dungeon and a tiny one on the same moon get different counts.\nDanger   - the moon's enemy power budget. Deadlier moons pay better.\nMapSize  - the moon's own size multiplier. Per-moon, so it ignores which interior rolled.\nNone     - ignore everything, sit at the midpoint.\nDanger and MapSize rank against the moons you actually have installed, so modded moons are sorted alongside the vanilla ones rather than against fixed numbers.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { "Interior", "Danger", "MapSize", "None" }), Array.Empty<object>()));
			InteriorSmall = c.Bind<int>("Spawning", "InteriorSmall", 30, new ConfigDescription("For ScaleBy = Interior: how many scrap spawn points count as a small interior. At or below this you get FigurinesOnEasiestMoon. The per-moon report line in the log prints the real count for every run, so land once and tune these to your interior pack.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000), Array.Empty<object>()));
			InteriorLarge = c.Bind<int>("Spawning", "InteriorLarge", 110, new ConfigDescription("For ScaleBy = Interior: how many scrap spawn points count as a large interior. At or above this you get FigurinesOnHardestMoon.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000), Array.Empty<object>()));
			SpawnVariance = c.Bind<int>("Spawning", "SpawnVariance", 1, new ConfigDescription("Random give or take on the final count, so the same moon is not identical twice.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>()));
			MinValue = c.Bind<int>("Spawning", "MinValue", 0, new ConfigDescription("Lowest scrap value a figurine can roll. Zero by default, and deliberately: a figurine that sells is a figurine worth farming, and the point of one is the emote. Worth nothing, the only thing to do with one is claim it. Raise both of these if you would rather they were loot as well. HOST ONLY.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 500), Array.Empty<object>()));
			MaxValue = c.Bind<int>("Spawning", "MaxValue", 0, new ConfigDescription("Highest scrap value a figurine can roll. HOST ONLY.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 500), Array.Empty<object>()));
			ItemName = c.Bind<string>("Appearance", "ItemName", "Emote figurine", "What the item is called in your inventory and on the scanner.");
			Model = c.Bind<string>("Appearance", "Model", "Dancer", new ConfigDescription("What a figurine looks like lying on the ground.\nDancer - a miniature of your own employee, performing the emote it holds. Copied from your player at runtime, so it wears your suit and inherits whatever model mods you are running, and driven by TooManyEmotes' own animation code, so it is the real emote rather than an impression of one. Silent.\nCube   - a plain untextured cube, painted the colour of the rarity it holds. The one you can read across a dark room.\nProp   - no replacement at all: the borrowed SourceItem keeps its own model, drawn at PropScale.\nPurely local. Two people can run different values and nothing breaks; they just see different things.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "Dancer", "Cube", "Prop" }), Array.Empty<object>()));
			CubeSize = c.Bind<float>("Appearance", "CubeSize", 2.25f, new ConfigDescription("For Model = Cube: the length of one edge, in metres. Unity's default cube is 1 and a player is about 2 tall, so the default here stands slightly taller than you do.\nThe borrowed prop's collider is NOT resized with it - see PropScale for why - so a cube much bigger than the SourceItem it was cloned from is still grabbed from where that item's grab box is, down at the base of a big one.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 6f), Array.Empty<object>()));
			CubeGlow = c.Bind<float>("Appearance", "CubeGlow", 2f, new ConfigDescription("For Model = Cube: how brightly the cube emits its own rarity colour. A matte cube in an unlit corridor is a black cube whatever colour it is painted, so this is what makes the rarity readable before your torch is on it. 0 = no glow. Past about 6 it starts to bloom.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
			FigureHeight = c.Bind<float>("Appearance", "FigureHeight", 0.7f, new ConfigDescription("For Model = Dancer: how tall the figurine stands, in metres - literally, on the floor. An employee is about 2, so the default comes up to about your hip. Measured against your own model, so a suit or a model replacement that changes your height does not change this, and the height it measured is printed in the log.\nThe grab box grows with it, so a big one is still taken from anywhere along it. A figurine in your hands is drawn a few inches from your eyes, so one set taller than about half a metre is shrunk to that while you carry it and grows back when you put it down.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 6f), Array.Empty<object>()));
			PropScale = c.Bind<float>("Appearance", "PropScale", 1f, new ConfigDescription("For Model = Prop: how much bigger (or smaller) to draw the borrowed item than its original. 1 = as the game ships it. Only the visible model grows; the grab box and where it rests on the floor stay as the original item's, so keep this within reason.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 4f), Array.Empty<object>()));
			SourceItem = c.Bind<string>("Appearance", "SourceItem", "", "Which vanilla scrap item's model a figurine borrows. This mod ships no assets of its own, so it clones an existing prop. Leave empty to auto-pick the lightest plain one-handed scrap item, which is logged on startup so you can see what you got. To choose your own, set LogVanillaItemNames to see every name your install offers and paste one here.\nPrefer an item with no behaviour of its own - cloning something like the Magic 7 ball or a clown horn brings its noise-on-use along with it. The log warns you if the item you named is one of those.\nEVERYONE SHOULD USE THE SAME VALUE, or you will each see a different model.");
			WeightCommon = c.Bind<float>("Rarity", "WeightCommon", 0.5f, new ConfigDescription("Relative chance a figurine holds a Common emote. HOST ONLY.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			WeightRare = c.Bind<float>("Rarity", "WeightRare", 0.35f, new ConfigDescription("Relative chance a figurine holds a Rare emote. HOST ONLY.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			WeightEpic = c.Bind<float>("Rarity", "WeightEpic", 0.135f, new ConfigDescription("Relative chance a figurine holds an Epic emote. HOST ONLY.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			WeightLegendary = c.Bind<float>("Rarity", "WeightLegendary", 0.015f, new ConfigDescription("Relative chance a figurine holds a Legendary emote. HOST ONLY.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			TintByRarity = c.Bind<bool>("Appearance", "TintByRarity", true, "Colour the figurine by the rarity of the emote it holds, so you can tell a Legendary from a Common across a room without scanning it. Uses the same four colours as the TooManyEmotes menu, from its accessibility config, so they match what you already see in the emote wheel.");
			TintStrength = c.Bind<float>("Appearance", "TintStrength", 0.35f, new ConfigDescription("How far the figurine is pushed toward its rarity colour. 0 leaves the suit as it is, 1 repaints it flat. The default reads as a tint, so a dancer is still recognisably wearing your suit. Model = Cube ignores this and is always painted flat - a plain cube has no look of its own worth preserving.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			ShowRarityColor = c.Bind<bool>("Display", "ShowRarityColor", true, "Colour the emote name on the scan node by rarity, using the colours from the TooManyEmotes accessibility config. Off = plain white.");
			LogVanillaItemNames = c.Bind<bool>("Display", "LogVanillaItemNames", false, "Print every vanilla item name to the BepInEx log on startup. Turn this on once to pick a SourceItem, then turn it back off.");
			SpawnFigurineKey = c.Bind<string>("Debug", "SpawnFigurineKey", "", "Drops a figurine at your feet so they can be tested without combing a moon for one. HOST ONLY, because spawning is server-authoritative - a client pressing it gets a message saying so. Unity keyboard name: k, j, f9, numpad1... Empty disables the key. Leave this empty for real sessions.");
			VerboseLogs = c.Bind<bool>("Debug", "VerboseLogs", false, "Log every figurine as it spawns and every claim as it resolves. Noisy, but it is the quickest way to see whether two machines agree about what a figurine holds - compare the id/emote pairs in both logs.");
		}
	}
	internal static class CubeFigure
	{
		public static Mesh Build(GameObject prefab, out Material[] materials)
		{
			materials = null;
			Material val = NewMaterial(prefab);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Found no shader to paint a cube with, so figurines keep the borrowed prop's own look.");
				return null;
			}
			Plugin.Log.LogInfo((object)($"Figurines drawn as a {Cfg.CubeSize.Value:0.##}m cube on " + "'" + ((Object)val.shader).name + "', coloured by rarity" + ((Cfg.CubeGlow.Value > 0f) ? $", glowing at {Cfg.CubeGlow.Value:0.#}." : ", not glowing.")));
			materials = (Material[])(object)new Material[1] { val };
			return BuildCube(Mathf.Max(0.02f, Cfg.CubeSize.Value));
		}

		private static Mesh BuildCube(float size)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: 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_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0197: 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_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: 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_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Expected O, but got Unknown
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: 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_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] array = (Vector3[])(object)new Vector3[6]
			{
				Vector3.right,
				Vector3.left,
				Vector3.up,
				Vector3.up,
				Vector3.forward,
				Vector3.back
			};
			Vector3[] array2 = (Vector3[])(object)new Vector3[6]
			{
				Vector3.up,
				Vector3.up,
				Vector3.forward,
				Vector3.back,
				Vector3.right,
				Vector3.right
			};
			float num = size * 0.5f;
			Vector3[] array3 = (Vector3[])(object)new Vector3[24];
			Vector3[] array4 = (Vector3[])(object)new Vector3[24];
			Vector2[] array5 = (Vector2[])(object)new Vector2[24];
			int[] array6 = new int[36];
			for (int i = 0; i < 6; i++)
			{
				Vector3 val = Vector3.Cross(array[i], array2[i]);
				Vector3 val2 = val * num + Vector3.up * num;
				int num2 = i * 4;
				array3[num2] = val2 - array[i] * num - array2[i] * num;
				array3[num2 + 1] = val2 - array[i] * num + array2[i] * num;
				array3[num2 + 2] = val2 + array[i] * num + array2[i] * num;
				array3[num2 + 3] = val2 + array[i] * num - array2[i] * num;
				for (int j = 0; j < 4; j++)
				{
					array4[num2 + j] = val;
				}
				array5[num2] = new Vector2(0f, 0f);
				array5[num2 + 1] = new Vector2(0f, 1f);
				array5[num2 + 2] = new Vector2(1f, 1f);
				array5[num2 + 3] = new Vector2(1f, 0f);
				int num3 = i * 6;
				array6[num3] = num2 + 2;
				array6[num3 + 1] = num2 + 1;
				array6[num3 + 2] = num2;
				array6[num3 + 3] = num2 + 2;
				array6[num3 + 4] = num2;
				array6[num3 + 5] = num2 + 3;
			}
			Mesh val3 = new Mesh
			{
				name = "EmoteTapeCube",
				hideFlags = (HideFlags)61,
				vertices = array3,
				normals = array4,
				uv = array5,
				triangles = array6
			};
			val3.RecalculateBounds();
			val3.RecalculateTangents();
			return val3;
		}

		private static Material NewMaterial(GameObject prefab)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_0091: Expected O, but got Unknown
			Shader val = Shader.Find("HDRP/Lit") ?? PropShader(prefab) ?? Shader.Find("HDRP/Unlit") ?? Shader.Find("Standard");
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Material val2 = new Material(val)
			{
				name = "EmoteTapeCube",
				hideFlags = (HideFlags)61
			};
			SetFloat(val2, "_Smoothness", 0.2f);
			SetFloat(val2, "_Glossiness", 0.2f);
			SetFloat(val2, "_Metallic", 0f);
			Paint(val2, Color.white);
			return val2;
		}

		private static Shader PropShader(GameObject prefab)
		{
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				Shader val2 = (((Object)(object)val != (Object)null && (Object)(object)val.sharedMaterial != (Object)null) ? val.sharedMaterial.shader : null);
				if ((Object)(object)val2 != (Object)null)
				{
					return val2;
				}
			}
			return null;
		}

		public static void Paint(Material material, Color colour)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)material == (Object)null))
			{
				colour.a = 1f;
				SetColor(material, "_BaseColor", colour);
				SetColor(material, "_Color", colour);
				SetColor(material, "_UnlitColor", colour);
				float num = Mathf.Max(0f, Cfg.CubeGlow.Value);
				Color value = colour * num;
				value.a = 1f;
				SetColor(material, "_EmissiveColor", value);
				SetFloat(material, "_EmissiveIntensity", num);
				if (num > 0f)
				{
					material.EnableKeyword("_EMISSIVE_COLOR_MAP");
				}
			}
		}

		private static void SetColor(Material material, string property, Color value)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (material.HasProperty(property))
			{
				material.SetColor(property, value);
			}
		}

		private static void SetFloat(Material material, string property, float value)
		{
			if (material.HasProperty(property))
			{
				material.SetFloat(property, value);
			}
		}
	}
	internal static class DancerFigure
	{
		private const float NominalHeight = 2f;

		private static GameObject _template;

		private static bool _warned;

		private static float _unitHeight = 2f;

		public static GameObject Attach(EmoteTape tape, UnlockableEmote emote)
		{
			//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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			Dancer componentInChildren = ((Component)tape).GetComponentInChildren<Dancer>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				return ((Component)componentInChildren).gameObject;
			}
			GameObject val = Template();
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject val2 = null;
			try
			{
				val2 = Object.Instantiate<GameObject>(val, ((Component)tape).transform);
				((Object)val2).name = "EmoteDancer";
				val2.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
				Vector3 val3 = LocalScale(((Component)tape).transform, Cfg.FigureHeight.Value);
				val2.transform.localScale = val3;
				SetLayer(val2, ((Component)tape).gameObject.layer);
				EmoteController val4 = val2.AddComponent<EmoteController>();
				if (!val4.initialized)
				{
					Warn("TooManyEmotes could not build an emote skeleton for the figurine.");
					Object.Destroy((Object)(object)val2);
					return null;
				}
				val4.CreateBoneMap(EmoteControllerPlayer.sourceBoneNames, (List<string>)null);
				val4.smoothTransitionToEmote = false;
				val2.AddComponent<Dancer>().Perform(val4, emote, ((Component)tape).GetComponent<GrabbableObject>(), val3);
				return val2;
			}
			catch (Exception ex)
			{
				Warn("Could not build a dancing figurine: " + ex.Message);
				if ((Object)(object)val2 != (Object)null)
				{
					Object.Destroy((Object)(object)val2);
				}
				return null;
			}
		}

		public static Vector3 LocalScale(Transform parent, float height)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			float num = ((_unitHeight > 0.01f) ? _unitHeight : 2f);
			float num2 = Mathf.Max(0.01f, height) / num;
			Vector3 val = (((Object)(object)parent != (Object)null) ? parent.lossyScale : Vector3.one);
			return new Vector3(num2 / Axis(val.x), num2 / Axis(val.y), num2 / Axis(val.z));
		}

		private static float Axis(float scale)
		{
			scale = Mathf.Abs(scale);
			if (!(scale < 0.0001f))
			{
				return scale;
			}
			return 1f;
		}

		private static GameObject Template()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			if ((Object)(object)_template != (Object)null)
			{
				return _template;
			}
			PlayerControllerB val = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.localPlayerController : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val.thisPlayerModel == (Object)null)
			{
				return null;
			}
			GameObject val2 = new GameObject("TMEProgressionDancerTemplate");
			val2.SetActive(false);
			((Object)val2).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)val2);
			try
			{
				_unitHeight = Measure(val);
				GameObject obj = Object.Instantiate<GameObject>(((Component)val).gameObject, val2.transform);
				((Object)obj).name = "Employee";
				Strip(obj);
				_template = obj;
				Plugin.Log.LogInfo((object)("Dancing figurine built from your own player model: an employee " + $"measures {_unitHeight:0.00}m, drawn at " + $"{Cfg.FigureHeight.Value:0.##}m."));
				return _template;
			}
			catch (Exception ex)
			{
				Warn("Could not copy the player model: " + ex.Message);
				Object.Destroy((Object)(object)val2);
				return null;
			}
		}

		private static float Measure(PlayerControllerB player)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_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)
			float num = Mathf.Abs(((Component)player).transform.lossyScale.y);
			if (num < 0.0001f)
			{
				num = 1f;
			}
			SkinnedMeshRenderer thisPlayerModel = player.thisPlayerModel;
			float num2 = 0f;
			if ((Object)(object)thisPlayerModel.sharedMesh != (Object)null)
			{
				Bounds bounds = thisPlayerModel.sharedMesh.bounds;
				Vector3 size = ((Bounds)(ref bounds)).size;
				num2 = Mathf.Max(size.x, Mathf.Max(size.y, size.z)) * Mathf.Abs(((Component)thisPlayerModel).transform.lossyScale.y) / num;
			}
			if (num2 < 0.5f || num2 > 6f)
			{
				Plugin.Log.LogInfo((object)($"Employee mesh bounds read {num2:0.00}m, which is not a " + "person, so figurines are scaled against the usual " + $"{2f:0.##}m. If they come out the wrong size, set " + "FigureHeight to whatever gets you there."));
				return 2f;
			}
			return num2;
		}

		private static void Strip(GameObject clone)
		{
			KeepOnly(clone.transform, "ScavengerModel");
			Transform val = clone.transform.Find("ScavengerModel");
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException("the player has no ScavengerModel");
			}
			KeepOnly(val, "LOD1", "metarig");
			Transform obj = val.Find("metarig");
			if ((Object)(object)obj == (Object)null)
			{
				throw new InvalidOperationException("the player model has no metarig");
			}
			KeepOnly(obj, "spine");
			Component[] componentsInChildren = clone.GetComponentsInChildren<Component>(true);
			foreach (Component val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && !(val2 is Transform) && !(val2 is SkinnedMeshRenderer) && !(val2 is MeshFilter) && !(val2 is MeshRenderer) && !(val2 is Animator))
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
			}
			SkinnedMeshRenderer[] componentsInChildren2 = clone.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val3 in componentsInChildren2)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					((Renderer)val3).enabled = true;
					((Renderer)val3).forceRenderingOff = false;
					val3.updateWhenOffscreen = false;
					((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0;
					((Renderer)val3).receiveShadows = true;
				}
			}
			Animator[] componentsInChildren3 = clone.GetComponentsInChildren<Animator>(true);
			foreach (Animator val4 in componentsInChildren3)
			{
				if (!((Object)(object)val4 == (Object)null))
				{
					val4.cullingMode = (AnimatorCullingMode)1;
				}
			}
		}

		private static void KeepOnly(Transform parent, params string[] names)
		{
			for (int num = parent.childCount - 1; num >= 0; num--)
			{
				Transform child = parent.GetChild(num);
				if (Array.IndexOf(names, ((Object)child).name) < 0)
				{
					Object.DestroyImmediate((Object)(object)((Component)child).gameObject);
				}
			}
		}

		private static void SetLayer(GameObject root, int layer)
		{
			root.layer = layer;
			for (int i = 0; i < root.transform.childCount; i++)
			{
				SetLayer(((Component)root.transform.GetChild(i)).gameObject, layer);
			}
		}

		private static void Warn(string message)
		{
			if (!_warned)
			{
				_warned = true;
				Plugin.Log.LogWarning((object)(message + " Figurines will keep the borrowed prop's own model. Set Model = Cube in the config to choose that deliberately."));
			}
		}
	}
	internal sealed class Dancer : MonoBehaviour
	{
		private const float PollSeconds = 0.5f;

		private const float CarryHeight = 0.4f;

		private EmoteController _controller;

		private UnlockableEmote _emote;

		private GrabbableObject _item;

		private Vector3 _standing = Vector3.one;

		private Vector3 _carried = Vector3.one;

		private bool _inHand;

		private float _nextCheck;

		private PlayerControllerB _carrier;

		private bool _heldLastFrame;

		private Quaternion _dropRotation;

		private bool _dropped;

		public void Perform(EmoteController controller, UnlockableEmote emote, GrabbableObject item, Vector3 scale)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			_controller = controller;
			_emote = emote;
			_item = item;
			_standing = scale;
			_carried = scale * Mathf.Min(1f, 0.4f / Mathf.Max(0.01f, Cfg.FigureHeight.Value));
			Restart();
		}

		private void LateUpdate()
		{
			Stand();
		}

		private void Update()
		{
			Carry();
			if (!((Object)(object)_controller == (Object)null) && _emote != null && !(Time.time < _nextCheck))
			{
				_nextCheck = Time.time + 0.5f;
				if (!_controller.isPerformingEmote)
				{
					Restart();
				}
			}
		}

		private void Stand()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_007c: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (((Object)(object)_item != (Object)null) ? _item.parentObject : null);
			if ((Object)(object)val == (Object)null)
			{
				if (_heldLastFrame)
				{
					_heldLastFrame = false;
					AimAtCarrier();
				}
				if (_dropped)
				{
					((Component)this).transform.rotation = _dropRotation;
				}
				return;
			}
			_heldLastFrame = true;
			Quaternion val2 = val.rotation * Quaternion.Euler(_item.itemProperties.rotationOffset);
			PlayerControllerB playerHeldBy = _item.playerHeldBy;
			if ((Object)(object)playerHeldBy != (Object)null)
			{
				_carrier = playerHeldBy;
			}
			Vector3 val3 = Vector3.ProjectOnPlane(((Object)(object)playerHeldBy != (Object)null) ? ((Component)playerHeldBy).transform.forward : val.forward, Vector3.up);
			if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f)
			{
				val3 = Vector3.forward;
			}
			Quaternion val4 = Quaternion.LookRotation(-val3, Vector3.up);
			((Component)this).transform.localRotation = Quaternion.Inverse(val2) * val4;
		}

		private void AimAtCarrier()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_carrier == (Object)null))
			{
				Vector3 val = Vector3.ProjectOnPlane(((Component)_carrier).transform.position - ((Component)this).transform.position, Vector3.up);
				if (!(((Vector3)(ref val)).sqrMagnitude < 0.0001f))
				{
					_dropRotation = Quaternion.LookRotation(val, Vector3.up);
					_dropped = true;
				}
			}
		}

		private void Carry()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_item == (Object)null))
			{
				bool flag = _item.isHeld || _item.isPocketed;
				if (flag != _inHand)
				{
					_inHand = flag;
					((Component)this).transform.localScale = (flag ? _carried : _standing);
				}
			}
		}

		private void Restart()
		{
			try
			{
				_controller.PerformEmote(_emote, -1, true);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("A figurine stopped dancing: " + ex.Message));
				((Behaviour)this).enabled = false;
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_controller == (Object)null || !_controller.isPerformingEmote)
			{
				return;
			}
			try
			{
				_controller.StopPerformingEmote();
			}
			catch
			{
			}
		}
	}
	internal sealed class DevTools : MonoBehaviour
	{
		private InputAction _spawnTape;

		private void Awake()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			string text = (Cfg.SpawnFigurineKey.Value ?? string.Empty).Trim();
			if (text.Length == 0)
			{
				return;
			}
			try
			{
				_spawnTape = new InputAction("Maco.TooManyEmotesProgression.SpawnTape", (InputActionType)1, "<Keyboard>/" + text, (string)null, (string)null, (string)null);
				_spawnTape.Enable();
				Plugin.Log.LogInfo((object)("Debug figurine spawner bound to '" + text + "'."));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not bind SpawnFigurineKey '" + text + "': " + ex.Message));
				_spawnTape = null;
			}
		}

		private void OnDestroy()
		{
			InputAction spawnTape = _spawnTape;
			if (spawnTape != null)
			{
				spawnTape.Disable();
			}
			InputAction spawnTape2 = _spawnTape;
			if (spawnTape2 != null)
			{
				spawnTape2.Dispose();
			}
		}

		private void Update()
		{
			if (_spawnTape == null || !_spawnTape.WasPressedThisFrame())
			{
				return;
			}
			try
			{
				SpawnOneInFront();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Debug figurine spawn failed: " + ex));
			}
		}

		private static void SpawnOneInFront()
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null);
			if ((Object)(object)val == (Object)null)
			{
				HudTip.Show("TME Progression", "Not in a round.", warning: true);
				return;
			}
			RoundManager instance = RoundManager.Instance;
			if ((Object)(object)instance == (Object)null || !((NetworkBehaviour)instance).IsServer)
			{
				HudTip.Show("TME Progression", "Host only - spawning is server-side.", warning: true);
				return;
			}
			Item tapeItem = TapeRegistry.TapeItem;
			if ((Object)(object)tapeItem == (Object)null)
			{
				HudTip.Show("TME Progression", "The figurine item failed to register; check the log.", warning: true);
				return;
			}
			Vector3 position = ((Component)val).transform.position + ((Component)val).transform.forward * 1.5f + Vector3.up * 0.5f;
			int num = Random.Range(tapeItem.minValue, tapeItem.maxValue + 1);
			NetworkObject val2 = TapeSpawner.Place(tapeItem, position, num);
			if ((Object)(object)val2 == (Object)null)
			{
				HudTip.Show("TME Progression", "Spawn failed; check the log.", warning: true);
				return;
			}
			instance.SyncScrapValuesClientRpc((NetworkObjectReference[])(object)new NetworkObjectReference[1] { NetworkObjectReference.op_Implicit(val2) }, new int[1] { num });
			HudTip.Show("TME Progression", "Dropped a figurine in front of you.");
		}
	}
	internal static class EmoteRoll
	{
		private static readonly List<UnlockableEmote>[] _tiers = new List<UnlockableEmote>[4];

		private static int _builtFromCount = -1;

		public static UnlockableEmote For(ulong networkObjectId)
		{
			try
			{
				UnlockableEmote val = TapeNet.RestoredEmote(networkObjectId);
				if (val != null)
				{
					return val;
				}
				int? sessionSeed = TapeNet.SessionSeed;
				if (!sessionSeed.HasValue)
				{
					return null;
				}
				BuildTiers();
				Random random = new Random((sessionSeed.Value * 486187739) ^ (int)(networkObjectId * 2654435761u));
				List<UnlockableEmote> list = PickTier(random);
				if (list == null || list.Count == 0)
				{
					return null;
				}
				return list[random.Next(list.Count)];
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to roll an emote for figurine " + networkObjectId + ": " + ex));
				return null;
			}
		}

		public static UnlockableEmote ById(int emoteId)
		{
			List<UnlockableEmote> allUnlockableEmotes = EmotesManager.allUnlockableEmotes;
			if (allUnlockableEmotes == null || emoteId < 0 || emoteId >= allUnlockableEmotes.Count)
			{
				return null;
			}
			return allUnlockableEmotes[emoteId];
		}

		public static UnlockableEmote ByNameHash(int nameHash)
		{
			List<UnlockableEmote> allUnlockableEmotes = EmotesManager.allUnlockableEmotes;
			if (allUnlockableEmotes == null)
			{
				return null;
			}
			foreach (UnlockableEmote item in allUnlockableEmotes)
			{
				if (item != null && !string.IsNullOrEmpty(item.emoteName) && NameHash(item.emoteName) == nameHash)
				{
					return item;
				}
			}
			return null;
		}

		public static int NameHash(string emoteName)
		{
			uint num = 2166136261u;
			foreach (char c in emoteName)
			{
				num ^= c;
				num *= 16777619;
			}
			int num2 = (int)(num & 0x3FFFFFFF);
			if (num2 != 0)
			{
				return num2;
			}
			return 1;
		}

		private static List<UnlockableEmote> PickTier(Random random)
		{
			float[] tierWeights = TapeNet.TierWeights;
			float num = 0f;
			for (int i = 0; i < 4; i++)
			{
				if (_tiers[i] != null && _tiers[i].Count > 0)
				{
					num += tierWeights[i];
				}
			}
			if (num <= 0f)
			{
				for (int j = 0; j < 4; j++)
				{
					if (_tiers[j] != null && _tiers[j].Count > 0)
					{
						return _tiers[j];
					}
				}
				return null;
			}
			float num2 = (float)random.NextDouble() * num;
			for (int k = 0; k < 4; k++)
			{
				if (_tiers[k] != null && _tiers[k].Count != 0)
				{
					num2 -= tierWeights[k];
					if (num2 <= 0f)
					{
						return _tiers[k];
					}
				}
			}
			for (int num3 = 3; num3 >= 0; num3--)
			{
				if (_tiers[num3] != null && _tiers[num3].Count > 0)
				{
					return _tiers[num3];
				}
			}
			return null;
		}

		private static void BuildTiers()
		{
			List<UnlockableEmote> allUnlockableEmotes = EmotesManager.allUnlockableEmotes;
			if (allUnlockableEmotes == null || _builtFromCount == allUnlockableEmotes.Count)
			{
				return;
			}
			for (int i = 0; i < 4; i++)
			{
				_tiers[i] = new List<UnlockableEmote>();
			}
			foreach (UnlockableEmote item in allUnlockableEmotes)
			{
				if (item != null && !((Object)(object)item.animationClip == (Object)null) && !item.complementary && item.purchasable && !item.requiresHeldProp && (EmotesManager.blacklistedEmoteIds == null || !EmotesManager.blacklistedEmoteIds.Contains(item.emoteId)))
				{
					int num = Mathf.Clamp(item.rarity, 0, 3);
					_tiers[num].Add(item);
				}
			}
			for (int j = 0; j < 4; j++)
			{
				_tiers[j].Sort((UnlockableEmote a, UnlockableEmote b) => a.emoteId.CompareTo(b.emoteId));
			}
			_builtFromCount = allUnlockableEmotes.Count;
			Plugin.Log.LogInfo((object)($"Emote pool built: {_tiers[0].Count} common, {_tiers[1].Count} rare, " + $"{_tiers[2].Count} epic, {_tiers[3].Count} legendary."));
		}
	}
	public class EmoteTape : MonoBehaviour
	{
		private static readonly string[] RarityNames = new string[4] { "Common", "Rare", "Epic", "Legendary" };

		private int _saveData;

		private bool _hasSaveData;

		private NetworkObject _netObj;

		private ScanNodeProperties _scanNode;

		private UnlockableEmote _emote;

		private bool _resolved;

		private bool _subscribed;

		private static string ItemLabel
		{
			get
			{
				if (!((Object)(object)TapeRegistry.TapeItem != (Object)null) || string.IsNullOrEmpty(TapeRegistry.TapeItem.itemName))
				{
					return "Emote figurine";
				}
				return TapeRegistry.TapeItem.itemName;
			}
		}

		public ulong Id
		{
			get
			{
				if (!((Object)(object)_netObj != (Object)null))
				{
					return 0uL;
				}
				return _netObj.NetworkObjectId;
			}
		}

		internal UnlockableEmote Emote => _emote;

		internal bool Dressed { get; set; }

		internal void Redress()
		{
			Dressed = false;
			Figurine.Dress(this, _emote);
		}

		private void Awake()
		{
			_netObj = ((Component)this).GetComponent<NetworkObject>();
			_scanNode = ((Component)this).GetComponentInChildren<ScanNodeProperties>(true);
		}

		private void Update()
		{
			if (!_resolved && !((Object)(object)_netObj == (Object)null) && _netObj.IsSpawned)
			{
				Resolve();
			}
		}

		private void OnDestroy()
		{
			if (_subscribed)
			{
				TapeNet.ClaimedChanged -= OnClaimedChanged;
				_subscribed = false;
			}
		}

		private void Resolve()
		{
			try
			{
				ApplyRestored();
				_emote = EmoteRoll.For(_netObj.NetworkObjectId);
				if (_emote != null)
				{
					_resolved = true;
					if (!_subscribed)
					{
						TapeNet.ClaimedChanged += OnClaimedChanged;
						_subscribed = true;
					}
					RefreshScanNode();
					Figurine.Dress(this, _emote);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to resolve a tape's emote: " + ex));
				_resolved = true;
			}
		}

		internal void Restore(int saveData)
		{
			_saveData = saveData;
			_hasSaveData = saveData != 0;
		}

		private void ApplyRestored()
		{
			if (!_hasSaveData || EmotesManager.allUnlockableEmotes == null)
			{
				return;
			}
			_hasSaveData = false;
			if (TapeSave.Unpack(_saveData, out var nameHash, out var claimed))
			{
				UnlockableEmote val = EmoteRoll.ByNameHash(nameHash);
				if (val == null)
				{
					Plugin.Log.LogInfo((object)"A figurine came back from the ship holding an emote this install no longer has, so it rolls a new one.");
				}
				else
				{
					TapeNet.RegisterRestored(_netObj.NetworkObjectId, val.emoteId, claimed);
				}
			}
		}

		private void OnClaimedChanged(ulong networkObjectId)
		{
			if (networkObjectId == Id)
			{
				RefreshScanNode();
			}
		}

		public void RefreshScanNode()
		{
			try
			{
				if ((Object)(object)_scanNode == (Object)null)
				{
					_scanNode = ((Component)this).GetComponentInChildren<ScanNodeProperties>(true);
					if ((Object)(object)_scanNode == (Object)null)
					{
						return;
					}
				}
				if (_emote == null)
				{
					_scanNode.headerText = ItemLabel;
					_scanNode.subText = "Unreadable";
					return;
				}
				_scanNode.headerText = (Cfg.ShowRarityColor.Value ? _emote.displayNameColorCoded : _emote.displayName);
				string text = RarityNames[Mathf.Clamp(_emote.rarity, 0, 3)];
				if (TapeNet.IsClaimed(Id))
				{
					_scanNode.subText = text + " - claimed";
				}
				else if (AlreadyKnown())
				{
					_scanNode.subText = text + " - you know this one";
				}
				else
				{
					_scanNode.subText = text;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to update a tape's scan node: " + ex));
			}
		}

		private bool AlreadyKnown()
		{
			try
			{
				return _emote != null && SessionManager.IsEmoteUnlocked(_emote, SessionManager.localPlayerUsername);
			}
			catch
			{
				return false;
			}
		}

		public void Claim()
		{
			if (!_resolved)
			{
				Resolve();
			}
			if (_emote == null)
			{
				HudTip.Show(ItemLabel, "This one is unreadable.", warning: true);
			}
			else if (TapeNet.IsClaimed(Id))
			{
				HudTip.Show(ItemLabel, TapeNet.BreakOnClaim ? "Already claimed." : "Already claimed. It still sells.", warning: true);
			}
			else if (AlreadyKnown())
			{
				HudTip.Show(ItemLabel, "You already know " + _emote.displayName + ".", warning: true);
			}
			else
			{
				TapeNet.RequestClaim(Id);
			}
		}
	}
	internal enum FigurineLook
	{
		Dancer,
		Cube,
		Prop
	}
	[HarmonyPatch]
	internal static class Figurine
	{
		private static bool _prepared;

		private static FigurineLook? _look;

		private static Mesh _shared;

		private static Material[] _sharedMaterials;

		private static readonly int BaseColor = Shader.PropertyToID("_BaseColor");

		private static readonly int LegacyColor = Shader.PropertyToID("_Color");

		public static FigurineLook Chosen
		{
			get
			{
				FigurineLook valueOrDefault = _look.GetValueOrDefault();
				if (!_look.HasValue)
				{
					valueOrDefault = (Enum.TryParse<FigurineLook>((Cfg.Model.Value ?? string.Empty).Trim(), ignoreCase: true, out var result) ? result : FigurineLook.Dancer);
					_look = valueOrDefault;
					return valueOrDefault;
				}
				return valueOrDefault;
			}
		}

		public static bool KeepsBorrowedModel => Chosen == FigurineLook.Prop;

		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPostfix]
		private static void PrepareOnAwake()
		{
			Prepare();
		}

		[HarmonyPatch(typeof(StartOfRound), "Start")]
		[HarmonyPostfix]
		private static void PrepareOnStart()
		{
			Prepare();
		}

		private static void Prepare()
		{
			GameObject tapePrefab = TapeRegistry.TapePrefab;
			if (_prepared || (Object)(object)tapePrefab == (Object)null)
			{
				return;
			}
			_prepared = true;
			try
			{
				switch (Chosen)
				{
				case FigurineLook.Cube:
					_shared = CubeFigure.Build(tapePrefab, out _sharedMaterials);
					break;
				case FigurineLook.Prop:
					_shared = PropFigure.Build(tapePrefab, out _sharedMaterials);
					break;
				}
				if ((Object)(object)_shared != (Object)null && !Draw(tapePrefab, _shared, _sharedMaterials))
				{
					Plugin.Log.LogWarning((object)"Found nothing to draw a figurine with on the borrowed prop, so it keeps its own look. Try a different SourceItem.");
					_shared = null;
					_sharedMaterials = null;
				}
				if (Chosen == FigurineLook.Dancer)
				{
					Reach(tapePrefab, Cfg.FigureHeight.Value);
				}
				RedressExisting();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not build the figurine look, so figurines will keep the borrowed prop's own model: " + ex));
			}
		}

		public static void Dress(EmoteTape tape, UnlockableEmote emote)
		{
			if ((Object)(object)tape == (Object)null || emote == null || tape.Dressed)
			{
				return;
			}
			try
			{
				if ((Object)(object)_shared != (Object)null)
				{
					Draw(((Component)tape).gameObject, _shared, _sharedMaterials);
				}
				else if (Chosen == FigurineLook.Dancer)
				{
					GameObject val = DancerFigure.Attach(tape, emote);
					if ((Object)(object)val == (Object)null)
					{
						return;
					}
					Blank(((Component)tape).gameObject, val.transform);
					Reach(((Component)tape).gameObject, Cfg.FigureHeight.Value);
				}
				Tint(tape, emote);
				tape.Dressed = true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not dress a figurine: " + ex));
			}
		}

		private static void Tint(EmoteTape tape, UnlockableEmote emote)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			Color val = default(Color);
			if (!Cfg.TintByRarity.Value || !ColorUtility.TryParseHtmlString(emote.nameColor, ref val))
			{
				return;
			}
			bool flag = Chosen == FigurineLook.Cube;
			float num = Mathf.Clamp01(Cfg.TintStrength.Value);
			if (!flag && num <= 0f)
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)tape).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if ((Object)(object)val2 == (Object)null || !Draws(val2))
				{
					continue;
				}
				Material[] materials = val2.materials;
				Material[] array = materials;
				foreach (Material val3 in array)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						if (flag)
						{
							CubeFigure.Paint(val3, val);
						}
						else
						{
							Wash(val3, val, num);
						}
					}
				}
				val2.materials = materials;
			}
		}

		private static bool Draws(Renderer renderer)
		{
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
			if (val != null)
			{
				return (Object)(object)val.sharedMesh != (Object)null;
			}
			MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>();
			if ((Object)(object)component != (Object)null)
			{
				return (Object)(object)component.sharedMesh != (Object)null;
			}
			return false;
		}

		private static void Wash(Material material, Color rarity, float strength)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			int num = (material.HasProperty(BaseColor) ? BaseColor : (material.HasProperty(LegacyColor) ? LegacyColor : 0));
			if (num != 0)
			{
				material.SetColor(num, Color.Lerp(material.GetColor(num), rarity, strength));
			}
		}

		private static void RedressExisting()
		{
			int num = 0;
			EmoteTape[] array = Object.FindObjectsOfType<EmoteTape>(true);
			foreach (EmoteTape emoteTape in array)
			{
				if (!((Object)(object)emoteTape == (Object)null) && emoteTape.Emote != null)
				{
					emoteTape.Redress();
					num++;
				}
			}
			if (num > 0)
			{
				Plugin.Log.LogInfo((object)$"Re-dressed {num} figurine(s) that already existed.");
			}
		}

		private static void Reach(GameObject root, float height)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			if (height <= 0f)
			{
				return;
			}
			GrabbableObject component = root.GetComponent<GrabbableObject>();
			if (!((Object)(object)component == (Object)null))
			{
				GameObject gameObject = ((Component)component).gameObject;
				FigurineReach figurineReach = gameObject.GetComponent<FigurineReach>() ?? gameObject.AddComponent<FigurineReach>();
				if ((Object)(object)figurineReach.Box == (Object)null)
				{
					figurineReach.Box = gameObject.AddComponent<BoxCollider>();
					((Collider)figurineReach.Box).isTrigger = true;
				}
				Vector3 lossyScale = gameObject.transform.lossyScale;
				float num = height / Axis(lossyScale.x);
				float num2 = height / Axis(lossyScale.y);
				float num3 = height / Axis(lossyScale.z);
				figurineReach.Box.size = new Vector3(num * 0.4f, num2, num3 * 0.4f);
				figurineReach.Box.center = new Vector3(0f, num2 * 0.5f, 0f);
				Scannable(root, height);
			}
		}

		private static void Scannable(GameObject root, float height)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			ScanNodeProperties componentInChildren = root.GetComponentInChildren<ScanNodeProperties>(true);
			if (!((Object)(object)componentInChildren == (Object)null))
			{
				Vector3 lossyScale = ((Component)componentInChildren).transform.lossyScale;
				if ((Object)(object)((Component)componentInChildren).transform.parent == (Object)(object)root.transform)
				{
					((Component)componentInChildren).transform.localPosition = new Vector3(0f, height / Axis(root.transform.lossyScale.y) * 0.5f, 0f);
				}
				BoxCollider component = ((Component)componentInChildren).GetComponent<BoxCollider>();
				if (!((Object)(object)component == (Object)null))
				{
					component.center = Vector3.zero;
					component.size = new Vector3(height / Axis(lossyScale.x) * 0.6f, height / Axis(lossyScale.y) * 0.8f, height / Axis(lossyScale.z) * 0.6f);
				}
			}
		}

		private static float Axis(float scale)
		{
			scale = Mathf.Abs(scale);
			if (!(scale < 0.0001f))
			{
				return scale;
			}
			return 1f;
		}

		public static bool Draw(GameObject root, Mesh mesh, Material[] materials)
		{
			MeshFilter val = Biggest(root);
			BlankAllBut(root, val, null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			val.sharedMesh = mesh;
			MeshRenderer obj = ((Component)val).GetComponent<MeshRenderer>() ?? ((Component)val).gameObject.AddComponent<MeshRenderer>();
			((Renderer)obj).sharedMaterials = materials;
			((Renderer)obj).enabled = true;
			((Renderer)obj).forceRenderingOff = false;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1;
			((Renderer)obj).receiveShadows = true;
			return true;
		}

		public static void Blank(GameObject root, Transform except = null)
		{
			BlankAllBut(root, null, except);
		}

		public static MeshFilter Biggest(GameObject root)
		{
			MeshFilter result = null;
			int num = -1;
			MeshFilter[] componentsInChildren = root.GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					int num2 = (((Object)(object)val.sharedMesh != (Object)null) ? val.sharedMesh.vertexCount : 0);
					if (num2 > num)
					{
						num = num2;
						result = val;
					}
				}
			}
			return result;
		}

		private static void BlankAllBut(GameObject root, MeshFilter keep, Transform except)
		{
			MeshFilter[] componentsInChildren = root.GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)keep && !Under(((Component)val).transform, except))
				{
					val.sharedMesh = null;
				}
			}
			SkinnedMeshRenderer[] componentsInChildren2 = root.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
			{
				if ((Object)(object)val2 != (Object)null && !Under(((Component)val2).transform, except))
				{
					val2.sharedMesh = null;
				}
			}
			LODGroup[] componentsInChildren3 = root.GetComponentsInChildren<LODGroup>(true);
			foreach (LODGroup val3 in componentsInChildren3)
			{
				if ((Object)(object)val3 != (Object)null && !Under(((Component)val3).transform, except))
				{
					Object.Destroy((Object)(object)val3);
				}
			}
		}

		private static bool Under(Transform child, Transform parent)
		{
			if ((Object)(object)parent != (Object)null && (Object)(object)child != (Object)null)
			{
				return child.IsChildOf(parent);
			}
			return false;
		}
	}
	internal sealed class FigurineReach : MonoBehaviour
	{
		public BoxCollider Box;
	}
	internal static class HudTip
	{
		public static void Show(string header, string body, bool warning = false)
		{
			try
			{
				HUDManager instance = HUDManager.Instance;
				if (!((Object)(object)instance == (Object)null))
				{
					instance.DisplayTip(header, body, warning, false, "LC_Tip1");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to show a HUD tip: " + ex));
			}
		}
	}
	[BepInPlugin("Maco.TooManyEmotesProgression", "TooManyEmotesProgression", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "Maco.TooManyEmotesProgression";

		public const string Name = "TooManyEmotesProgression";

		public const string Version = "1.0.1";

		internal static ManualLogSource Log;

		private static Harmony _harmony;

		private void Awake()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Cfg.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("Maco.TooManyEmotesProgression");
			bool num = TryPatch(typeof(TapeRegistry), "item registration") & TryPatch(typeof(TapeSpawner), "placement") & TryPatch(typeof(TapePatches), "scanning and use") & TryPatch(typeof(TapeNet), "claim networking");
			TryPatch(typeof(Figurine), "figurine model");
			TryPatch(typeof(TapeSave), "saved figurines");
			bool flag = TryPatch(typeof(ShopPatch), "emote store suppression");
			if (!num)
			{
				Log.LogError((object)"Figurines are disabled: a game or TooManyEmotes method this mod patches has moved. This usually means one of them updated.");
				return;
			}
			if (!string.IsNullOrWhiteSpace(Cfg.SpawnFigurineKey.Value))
			{
				GameObject val = new GameObject("TMEProgressionDevTools")
				{
					hideFlags = (HideFlags)61
				};
				Object.DontDestroyOnLoad((Object)val);
				val.AddComponent<DevTools>();
			}
			Log.LogInfo((object)("TooManyEmotesProgression 1.0.1 loaded. " + ((!Cfg.FigurinesOnly.Value) ? "Figurines spawn alongside the terminal emote store." : (flag ? "Figurines only: the terminal emote store is closed." : "FigurinesOnly is on but the store could not be closed; emotes are still buyable in the terminal."))));
		}

		private static bool TryPatch(Type patchClass, string what)
		{
			try
			{
				_harmony.PatchAll(patchClass);
				return true;
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not patch " + what + " (" + patchClass.Name + "): " + ex.Message));
				return false;
			}
		}
	}
	internal static class PropFigure
	{
		public static Mesh Build(GameObject prefab, out Material[] materials)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00d5: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: 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_017a: Unknown result type (might be due to invalid IL or missing references)
			materials = null;
			float value = Cfg.PropScale.Value;
			if (Mathf.Abs(value - 1f) < 0.001f)
			{
				return null;
			}
			MeshFilter val = Figurine.Biggest(prefab);
			if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null)
			{
				Plugin.Log.LogWarning((object)"PropScale: the borrowed prop has no mesh to resize.");
				return null;
			}
			Mesh sharedMesh = val.sharedMesh;
			if (!sharedMesh.isReadable)
			{
				Plugin.Log.LogWarning((object)("PropScale: '" + ((Object)sharedMesh).name + "' is not CPU-readable, so it cannot be resized. Choose a different SourceItem, or leave PropScale at 1."));
				return null;
			}
			Mesh val2 = Object.Instantiate<Mesh>(sharedMesh);
			((Object)val2).name = ((Object)sharedMesh).name + " x" + value.ToString("0.##");
			((Object)val2).hideFlags = (HideFlags)61;
			Bounds bounds = val2.bounds;
			Vector3 center = ((Bounds)(ref bounds)).center;
			Vector3[] vertices = val2.vertices;
			for (int i = 0; i < vertices.Length; i++)
			{
				vertices[i] = center + (vertices[i] - center) * value;
			}
			val2.vertices = vertices;
			val2.RecalculateBounds();
			MeshRenderer component = ((Component)val).GetComponent<MeshRenderer>();
			materials = (((Object)(object)component != (Object)null) ? ((Renderer)component).sharedMaterials : null);
			bounds = val2.bounds;
			Vector3 size = ((Bounds)(ref bounds)).size;
			Plugin.Log.LogInfo((object)($"Borrowed prop '{((Object)sharedMesh).name}' drawn at x{value:0.##}: now " + $"{size.x:0.00} x {size.y:0.00} x {size.z:0.00}m."));
			return val2;
		}
	}
	[HarmonyPatch]
	internal static class ShopPatch
	{
		private const string StoreMarker = "[[[emoteUnlockablesSelectionList]]]";

		[HarmonyPatch(typeof(Terminal), "TextPostProcess")]
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		[HarmonyBefore(new string[] { "TooManyEmotes" })]
		private static void RemoveStorePage(ref string modifiedDisplayText)
		{
			try
			{
				if (TapeNet.FigurinesOnly && !string.IsNullOrEmpty(modifiedDisplayText) && modifiedDisplayText.Contains("[[[emoteUnlockablesSelectionList]]]"))
				{
					string text = (string.IsNullOrWhiteSpace(Cfg.ItemName.Value) ? "Emote figurine" : Cfg.ItemName.Value.Trim());
					modifiedDisplayText = modifiedDisplayText.Replace("[[[emoteUnlockablesSelectionList]]]", "Emotes are no longer sold here.\n\nThey turn up on moons as scrap: look for a\n'" + text + "'. Scan one to see which emote it\nholds, then hold it and use it to keep that\nemote for yourself. First come, first served.\n");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to replace the emote store page: " + ex));
			}
		}

		[HarmonyPatch(typeof(TerminalPatcher), "RotateNewEmoteSelection")]
		[HarmonyPostfix]
		private static void EmptyTheStore()
		{
			try
			{
				if (TapeNet.FigurinesOnly)
				{
					TerminalPatcher.emoteSelection?.Clear();
					TerminalPatcher.mysteryEmoteSelection?.Clear();
					TerminalPatcher.currentEmoteCredits = 0;
					TerminalPatcher.currentEmoteCreditsByPlayer?.Clear();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to empty the emote store: " + ex));
			}
		}
	}
	[HarmonyPatch]
	internal static class TapeNet
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnClaimServer;

			public static HandleNamedMessageDelegate <1>__OnSyncRequestServer;

			public static HandleNamedMessageDelegate <2>__OnClaimedClient;

			public static HandleNamedMessageDelegate <3>__OnSyncClaimedClient;
		}

		private const string MsgClaim = "Maco.TooManyEmotesProgression.Claim";

		private const string MsgClaimed = "Maco.TooManyEmotesProgression.Claimed";

		private const string MsgSyncRequest = "Maco.TooManyEmotesProgression.SyncRequest";

		private const string MsgSyncClaimed = "Maco.TooManyEmotesProgression.SyncClaimed";

		private static readonly HashSet<ulong> _claimed = new HashSet<ulong>();

		private static readonly Dictionary<ulong, int> _restored = new Dictionary<ulong, int>();

		private static bool _isServer;

		private static bool _haveSeed;

		private static int _sessionSeed;

		private static float[] _hostWeights;

		private static bool? _hostFigurinesOnly;

		private static bool? _hostBreakOnClaim;

		public static float[] TierWeights
		{
			get
			{
				if (!_isServer && _hostWeights != null && _hostWeights.Length == 4)
				{
					return _hostWeights;
				}
				return LocalWeights();
			}
		}

		public static bool FigurinesOnly
		{
			get
			{
				if (!_isServer && _hostFigurinesOnly.HasValue)
				{
					return _hostFigurinesOnly.Value;
				}
				return Cfg.FigurinesOnly.Value;
			}
		}

		public static bool BreakOnClaim
		{
			get
			{
				if (!_isServer && _hostBreakOnClaim.HasValue)
				{
					return _hostBreakOnClaim.Value;
				}
				return Cfg.BreakOnClaim.Value;
			}
		}

		public static int? SessionSeed
		{
			get
			{
				if (!_haveSeed)
				{
					return null;
				}
				return _sessionSeed;
			}
		}

		public static event Action<ulong> ClaimedChanged;

		public static bool IsClaimed(ulong networkObjectId)
		{
			return _claimed.Contains(networkObjectId);
		}

		private static float[] LocalWeights()
		{
			return new float[4]
			{
				Math.Max(0f, Cfg.WeightCommon.Value),
				Math.Max(0f, Cfg.WeightRare.Value),
				Math.Max(0f, Cfg.WeightEpic.Value),
				Math.Max(0f, Cfg.WeightLegendary.Value)
			};
		}

		public static UnlockableEmote RestoredEmote(ulong networkObjectId)
		{
			if (!_restored.TryGetValue(networkObjectId, out var value))
			{
				return null;
			}
			return EmoteRoll.ById(value);
		}

		public static void RegisterRestored(ulong networkObjectId, int emoteId, bool claimed)
		{
			if (_isServer)
			{
				_restored[networkObjectId] = emoteId;
				if (claimed)
				{
					TryMarkClaimed(networkObjectId);
				}
				if (Cfg.VerboseLogs.Value)
				{
					Plugin.Log.LogInfo((object)("Figurine " + networkObjectId + " restored from the save holding emote " + emoteId + (claimed ? ", already claimed." : ".")));
				}
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
		[HarmonyPostfix]
		public static void Init()
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_00ab: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			//IL_00c6: 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_00d1: Expected O, but got Unknown
			try
			{
				_claimed.Clear();
				_restored.Clear();
				_haveSeed = false;
				_hostWeights = null;
				_hostFigurinesOnly = null;
				_hostBreakOnClaim = null;
				NetworkManager singleton = NetworkManager.Singleton;
				if ((Object)(object)singleton == (Object)null || singleton.CustomMessagingManager == null)
				{
					return;
				}
				_isServer = singleton.IsServer;
				CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager;
				if (_isServer)
				{
					_sessionSeed = new Random().Next(int.MinValue, int.MaxValue);
					_haveSeed = true;
					object obj = <>O.<0>__OnClaimServer;
					if (obj == null)
					{
						HandleNamedMessageDelegate val = OnClaimServer;
						<>O.<0>__OnClaimServer = val;
						obj = (object)val;
					}
					customMessagingManager.RegisterNamedMessageHandler("Maco.TooManyEmotesProgression.Claim", (HandleNamedMessageDelegate)obj);
					object obj2 = <>O.<1>__OnSyncRequestServer;
					if (obj2 == null)
					{
						HandleNamedMessageDelegate val2 = OnSyncRequestServer;
						<>O.<1>__OnSyncRequestServer = val2;
						obj2 = (object)val2;
					}
					customMessagingManager.RegisterNamedMessageHandler("Maco.TooManyEmotesProgression.SyncRequest", (HandleNamedMessageDelegate)obj2);
				}
				else
				{
					object obj3 = <>O.<2>__OnClaimedClient;
					if (obj3 == null)
					{
						HandleNamedMessageDelegate val3 = OnClaimedClient;
						<>O.<2>__OnClaimedClient = val3;
						obj3 = (object)val3;
					}
					customMessagingManager.RegisterNamedMessageHandler("Maco.TooManyEmotesProgression.Claimed", (HandleNamedMessageDelegate)obj3);
					object obj4 = <>O.<3>__OnSyncClaimedClient;
					if (obj4 == null)
					{
						HandleNamedMessageDelegate val4 = OnSyncClaimedClient;
						<>O.<3>__OnSyncClaimedClient = val4;
						obj4 = (object)val4;
					}
					customMessagingManager.RegisterNamedMessageHandler("Maco.TooManyEmotesProgression.SyncClaimed", (HandleNamedMessageDelegate)obj4);
					SendSyncRequest();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to set up figurine networking: " + ex));
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "ResetShip")]
		[HarmonyPostfix]
		public static void OnShipReset()
		{
			_claimed.Clear();
			_restored.Clear();
		}

		public unsafe static void RequestClaim(ulong networkObjectId)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (_isServer)
				{
					int num = EmoteIdOf(networkObjectId);
					if (num >= 0 && TryMarkClaimed(networkObjectId))
					{
						BroadcastClaimed(networkObjectId, NetworkManager.Singleton.LocalClientId, num);
						Award(networkObjectId, num);
					}
					return;
				}
				FastBufferWriter val = default(FastBufferWriter);
				((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1);
				try
				{
					((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
					NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("Maco.TooManyEmotesProgression.Claim", 0uL, val, (NetworkDelivery)3);
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to send claim for figurine " + networkObjectId + ": " + ex));
			}
		}

		private static void OnClaimServer(ulong senderClientId, FastBufferReader reader)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (_isServer)
				{
					ulong networkObjectId = default(ulong);
					((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
					int num = EmoteIdOf(networkObjectId);
					if (num >= 0 && TryMarkClaimed(networkObjectId))
					{
						BroadcastClaimed(networkObjectId, senderClientId, num);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to handle a claim from client " + senderClientId + ": " + ex));
			}
		}

		private static int EmoteIdOf(ulong networkObjectId)
		{
			return EmoteRoll.For(networkObjectId)?.emoteId ?? (-1);
		}

		private unsafe static void BroadcastClaimed(ulong networkObjectId, ulong winnerClientId, int emoteId)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(20, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref winnerClientId, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref emoteId, default(ForPrimitives));
				NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("Maco.TooManyEmotesProgression.Claimed", val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void OnClaimedClient(ulong _, FastBufferReader reader)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!_isServer)
				{
					ulong networkObjectId = default(ulong);
					((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
					ulong num = default(ulong);
					((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num, default(ForPrimitives));
					int emoteId = default(int);
					((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref emoteId, default(ForPrimitives));
					TryMarkClaimed(networkObjectId);
					if ((Object)(object)NetworkManager.Singleton != (Object)null && num == NetworkManager.Singleton.LocalClientId)
					{
						Award(networkObjectId, emoteId);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to handle a claim broadcast: " + ex));
			}
		}

		private static bool TryMarkClaimed(ulong networkObjectId)
		{
			if (!_claimed.Add(networkObjectId))
			{
				return false;
			}
			try
			{
				TapeNet.ClaimedChanged?.Invoke(networkObjectId);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Claim listener threw: " + ex));
			}
			return true;
		}

		private static void Award(ulong networkObjectId, int emoteId)
		{
			UnlockableEmote val = EmoteRoll.ById(emoteId);
			if (val == null)
			{
				Plugin.Log.LogWarning((object)("Won " + networkObjectId + " but could not resolve its emote."));
				return;
			}
			SyncManager.SendOnUnlockEmoteUpdate(val.emoteId, -1);
			Plugin.Log.LogInfo((object)("Claimed emote '" + val.emoteName + "' from " + networkObjectId + "."));
			HudTip.Show("Emote unlocked", val.displayNameColorCoded);
			if (BreakOnClaim)
			{
				Consume(networkObjectId);
			}
		}

		private static void Consume(ulong networkObjectId)
		{
			try
			{
				PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				GrabbableObject currentlyHeldObjectServer = val.currentlyHeldObjectServer;
				if ((Object)(object)currentlyHeldObjectServer == (Object)null || !((NetworkBehaviour)currentlyHeldObjectServer).IsSpawned || ((NetworkBehaviour)currentlyHeldObjectServer).NetworkObjectId != networkObjectId)
				{
					if (Cfg.VerboseLogs.Value)
					{
						Plugin.Log.LogInfo((object)("Not consuming " + networkObjectId + "; no longer the held item."));
					}
					return;
				}
				val.DestroyItemInSlotAndSync(val.currentItemSlot);
				if (Cfg.VerboseLogs.Value)
				{
					Plugin.Log.LogInfo((object)("Consumed " + networkObjectId + "."));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to consume " + networkObjectId + " after claiming it: " + ex));
			}
		}

		private unsafe static void SendSyncRequest()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(0, (Allocator)2, -1);
			try
			{
				NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("Maco.TooManyEmotesProgression.SyncRequest", 0uL, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private unsafe static void OnSyncRequestServer(ulong senderClientId, FastBufferReader _)
		{
			//IL_0041: 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_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)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!_isServer)
				{
					return;
				}
				float[] array = LocalWeights();
				FastBufferWriter val = default(FastBufferWriter);
				((FastBufferWriter)(ref val))..ctor(30 + 8 * _claimed.Count + 12 * _restored.Count, (Allocator)2, -1);
				try
				{
					((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref _sessionSeed, default(ForPrimitives));
					float[] array2 = array;
					int i;
					for (i = 0; i < array2.Length; i++)
					{
						float num = array2[i];
						((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref num, default(ForPrimitives));
					}
					bool value = Cfg.FigurinesOnly.Value;
					((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref value, default(ForPrimitives));
					value = Cfg.BreakOnClaim.Value;
					((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref value, default(ForPrimitives));
					i = _claimed.Count;
					((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref i, default(ForPrimitives));
					foreach (ulong item in _claimed)
					{
						ulong current = item;
						((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref current, default(ForPrimitives));
					}
					i = _restored.Count;
					((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref i, default(ForPrimitives));
					foreach (KeyValuePair<ulong, int> item2 in _restored)
					{
						ulong key = item2.Key;
						((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref key, default(ForPrimitives));
						i = item2.Value;
						((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref i, default(ForPrimitives));
					}
					NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("Maco.TooManyEmotesProgression.SyncClaimed", senderClientId, val, (NetworkDelivery)4);
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to answer a figurine sync request: " + ex));
			}
		}

		private static void OnSyncClaimedClient(ulong _, FastBufferReader reader)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!_isServer)
				{
					int sessionSeed = default(int);
					((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref sessionSeed, default(ForPrimitives));
					float[] array = new float[4];
					for (int i = 0; i < array.Length; i++)
					{
						((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref array[i], default(ForPrimitives));
					}
					bool value = default(bool);
					((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref value, default(ForPrimitives));
					bool value2 = default(bool);
					((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref value2, default(ForPrimitives));
					int num = default(int);
					((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
					ulong networkObjectId = default(ulong);
					for (int j = 0; j < num; j++)
					{
						((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
						TryMarkClaimed(networkObjectId);
					}
					int num2 = default(int);
					((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num2, default(ForPrimitives));
					ulong key = default(ulong);
					int value3 = default(int);
					for (int k = 0; k < num2; k++)
					{
						((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref key, default(ForPrimitives));
						((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref value3, default(ForPrimitives));
						_restored[key] = value3;
					}
					_hostWeights = array;
					_hostFigurinesOnly = value;
					_hostBreakOnClaim = value2;
					_sessionSeed = sessionSeed;
					_haveSeed = true;
					Plugin.Log.LogInfo((object)("Figurine