Decompiled source of 9 Bottle Guardians v0.20.4

BepInEx/plugins/TrophyGuard/TrophyGuard.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Enoq")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.20.4.0")]
[assembly: AssemblyInformationalVersion("0.20.4")]
[assembly: AssemblyProduct("9 Bottle Guardians")]
[assembly: AssemblyTitle("TrophyGuard")]
[assembly: AssemblyVersion("0.20.4.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TrophyGuard
{
	internal static class AdditionalGuardians
	{
		internal static void ConfigureDeath(Species species, Character character)
		{
			//IL_0048: 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_0079: Expected O, but got Unknown
			string explosion = ((species.Id == "Writhan") ? "writhan_explosion" : ((species.Id == "BlobLava") ? "BlobLava_explosion" : null));
			if (explosion != null)
			{
				character.m_deathEffects = new EffectList
				{
					m_effectPrefabs = character.m_deathEffects.m_effectPrefabs.Where((EffectData e) => !Object.op_Implicit((Object)(object)e.m_prefab) || ((Object)e.m_prefab).name != explosion).ToArray()
				};
			}
			if (species.Id == "Writhan" || species.Id == "Unbjorn" || species.Id == "Serpent")
			{
				NorthGuardians.ConfigureDeath(species, character);
			}
		}

		internal static void ConfigureWeapon(Species species, string weapon, SharedData data)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			//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_0154: 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_0163: Expected O, but got Unknown
			string text = ((species.Id == "Writhan" && weapon == "writhan_explode_aoe") ? "writhan_explosion" : ((species.Id == "BlobLava" && weapon == "blobLava_attack_aoe") ? "BlobLava_explosion" : null));
			if (text != null)
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab(text);
				Aoe val = ((prefab != null) ? prefab.GetComponent<Aoe>() : null);
				if (!Object.op_Implicit((Object)(object)val))
				{
					throw new InvalidOperationException("Missing guardian explosion: " + text);
				}
				data.m_damages = val.m_damage;
				data.m_damages.m_chop = 0f;
				data.m_damages.m_pickaxe = 0f;
				Attack attack = data.m_attack;
				attack.m_attackKillsSelf = false;
				attack.m_attackHealth = 0f;
				attack.m_attackHealthPercentage = 0f;
				attack.m_selfDamage = 0;
				attack.m_attackRayWidth = val.m_radius * species.Scale;
				attack.m_lowerDamagePerHit = false;
				string text2 = ((species.Id == "Writhan") ? "fx_writhan_explosion" : "fx_blobLava_explosion");
				GameObject prefab2 = PrefabManager.Instance.GetPrefab(text2);
				if (!Object.op_Implicit((Object)(object)prefab2))
				{
					throw new InvalidOperationException("Missing guardian explosion visual: " + text2);
				}
				EffectList val2 = new EffectList();
				val2.m_effectPrefabs = (EffectData[])(object)new EffectData[1]
				{
					new EffectData
					{
						m_prefab = prefab2,
						m_enabled = true,
						m_scale = true
					}
				};
				attack.m_triggerEffect = val2;
			}
		}
	}
	internal static class AllianceValidation
	{
		internal static string DeniedMessage(bool synchronized)
		{
			if (!synchronized)
			{
				return "tg_allies_loading";
			}
			return "tg_denied";
		}

		internal static string Check(long owner, long ally, bool live, float distance, float health)
		{
			if (!live || owner == 0L || ally == 0L || owner == ally || float.IsNaN(health) || float.IsInfinity(health) || health <= 0f)
			{
				return "unavailable";
			}
			if (float.IsNaN(distance) || float.IsInfinity(distance) || distance < 0f || distance > 5f)
			{
				return "distance";
			}
			return "ok";
		}
	}
	internal sealed class AllianceSet
	{
		private readonly struct Pair : IEquatable<Pair>
		{
			private readonly long owner;

			private readonly long ally;

			internal Pair(long owner, long ally)
			{
				this.owner = owner;
				this.ally = ally;
			}

			public bool Equals(Pair other)
			{
				if (owner == other.owner)
				{
					return ally == other.ally;
				}
				return false;
			}

			public override bool Equals(object obj)
			{
				if (obj is Pair other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				long num = owner;
				int num2 = num.GetHashCode() * 397;
				num = ally;
				return num2 ^ num.GetHashCode();
			}

			internal string Encode()
			{
				long num = owner;
				string text = num.ToString(CultureInfo.InvariantCulture);
				num = ally;
				return text + ":" + num.ToString(CultureInfo.InvariantCulture);
			}
		}

		private readonly HashSet<Pair> pairs = new HashSet<Pair>();

		internal bool Allows(long owner, long actor)
		{
			if (owner != 0L && actor != 0L)
			{
				if (owner != actor)
				{
					return pairs.Contains(new Pair(owner, actor));
				}
				return true;
			}
			return false;
		}

		internal void Set(long owner, long ally, bool allowed)
		{
			if (owner == 0L || ally == 0L || owner == ally)
			{
				throw new InvalidDataException("Invalid ally pair");
			}
			if (allowed)
			{
				pairs.Add(new Pair(owner, ally));
			}
			else
			{
				pairs.Remove(new Pair(owner, ally));
			}
		}

		internal string Encode()
		{
			return string.Join("\n", pairs.Select((Pair p) => p.Encode()).OrderBy<string, string>((string p) => p, StringComparer.Ordinal));
		}

		internal static AllianceSet Decode(string data)
		{
			AllianceSet allianceSet = new AllianceSet();
			if (string.IsNullOrEmpty(data))
			{
				return allianceSet;
			}
			string[] array = data.Split(new char[1] { '\n' });
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ':' });
				if (array2.Length != 2 || !long.TryParse(array2[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || !long.TryParse(array2[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2))
				{
					throw new InvalidDataException("Invalid allies snapshot");
				}
				allianceSet.Set(result, result2, allowed: true);
			}
			return allianceSet;
		}
	}
	internal sealed class AllianceReplica
	{
		private AllianceSet permissions = new AllianceSet();

		internal int Revision { get; private set; } = -1;

		internal bool Allows(long owner, long actor)
		{
			return permissions.Allows(owner, actor);
		}

		internal bool Apply(int revision, string snapshot)
		{
			if (revision < 0 || revision <= Revision)
			{
				return false;
			}
			AllianceSet allianceSet = AllianceSet.Decode(snapshot);
			permissions = allianceSet;
			Revision = revision;
			return true;
		}
	}
	internal sealed class AllianceJournal
	{
		private readonly string path;

		private readonly object state = new object();

		private readonly object writer = new object();

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

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

		private readonly AllianceSet permissions = new AllianceSet();

		private string encoded;

		internal AllianceJournal(string path)
		{
			this.path = path;
			if (File.Exists(path))
			{
				string[] array = File.ReadAllLines(path);
				foreach (string line in array)
				{
					Index(line);
				}
			}
		}

		private void Index(string line)
		{
			string[] array = line.Split(new char[1] { '|' });
			if (array.Length != 4 || !long.TryParse(array[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || !long.TryParse(array[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) || !Guid.TryParseExact(array[2], "N", out var _) || (array[3] != "0" && array[3] != "1") || !requests.Add(array[0] + "|" + array[2]))
			{
				throw new InvalidDataException("Invalid allies journal");
			}
			permissions.Set(result, result2, array[3] == "1");
			rows.Add(line);
			encoded = null;
		}

		internal bool Allows(long owner, long actor)
		{
			lock (state)
			{
				return permissions.Allows(owner, actor);
			}
		}

		internal bool HasRequest(long owner, string nonce)
		{
			lock (state)
			{
				return requests.Contains(owner.ToString(CultureInfo.InvariantCulture) + "|" + nonce);
			}
		}

		internal string Snapshot(out int revision, int knownRevision = -1)
		{
			lock (state)
			{
				revision = rows.Count;
				if (knownRevision == revision)
				{
					return null;
				}
				return encoded ?? (encoded = permissions.Encode());
			}
		}

		internal Task SetAsync(long owner, long ally, string nonce, bool allowed)
		{
			return Task.Run(delegate
			{
				if (owner == 0L || ally == 0L || owner == ally || !Guid.TryParseExact(nonce, "N", out var _))
				{
					throw new InvalidDataException("Invalid ally request");
				}
				string item = owner.ToString(CultureInfo.InvariantCulture) + "|" + nonce;
				string text = owner.ToString(CultureInfo.InvariantCulture) + "|" + ally.ToString(CultureInfo.InvariantCulture) + "|" + nonce + "|" + (allowed ? "1" : "0");
				lock (writer)
				{
					string[] array;
					lock (state)
					{
						if (requests.Contains(item))
						{
							return;
						}
						array = rows.ToArray();
					}
					Directory.CreateDirectory(Path.GetDirectoryName(path));
					string sourceFileName = path + ".tmp";
					using (FileStream fileStream = new FileStream(sourceFileName, FileMode.Create, FileAccess.Write, FileShare.None))
					{
						using StreamWriter streamWriter = new StreamWriter(fileStream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
						string[] array2 = array;
						foreach (string value in array2)
						{
							streamWriter.WriteLine(value);
						}
						streamWriter.WriteLine(text);
						streamWriter.Flush();
						fileStream.Flush(flushToDisk: true);
					}
					if (File.Exists(path))
					{
						File.Replace(sourceFileName, path, path + ".bak");
					}
					else
					{
						File.Move(sourceFileName, path);
					}
					lock (state)
					{
						Index(text);
					}
				}
			});
		}
	}
	internal static class BossGuardians
	{
		private static readonly Dictionary<string, GameObject> Effects = new Dictionary<string, GameObject>();

		internal static void Configure(Species species, Character character, BaseAI ai)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			character.m_bossOrder = 0;
			character.m_dontHideBossHud = false;
			character.m_dreamCinematic = "";
			character.m_killedForAchievements = (AchievementInclusion)2;
			ai.m_spawnMessage = "";
			ai.m_deathMessage = "";
			ai.m_alertedMessage = "";
			Humanoid val = (Humanoid)(object)((character is Humanoid) ? character : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				val.m_defaultItems = val.m_defaultItems.Where((GameObject p) => Object.op_Implicit((Object)(object)p) && !BossRules.ExcludeWeapon(((Object)p).name)).ToArray();
			}
			MovementDamage[] components = ((Component)character).GetComponents<MovementDamage>();
			for (int num = 0; num < components.Length; num++)
			{
				Object.DestroyImmediate((Object)(object)components[num]);
			}
			DropProjectileOverDistance[] components2 = ((Component)character).GetComponents<DropProjectileOverDistance>();
			for (int num = 0; num < components2.Length; num++)
			{
				Object.DestroyImmediate((Object)(object)components2[num]);
			}
			Aoe[] componentsInChildren = ((Component)character).GetComponentsInChildren<Aoe>(true);
			for (int num = 0; num < componentsInChildren.Length; num++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[num]);
			}
			foreach (Transform item in from t in ((Component)character).GetComponentsInChildren<Transform>(true)
				where ((Object)t).name == "RunHitDamager"
				select t)
			{
				((Component)item).gameObject.SetActive(false);
			}
			if (species.Id == "GoblinKing")
			{
				RemoveYagluthAura(((Component)character).gameObject);
			}
			if (species.Id == "Dragon")
			{
				ai.m_maxLandAltitude = 4f;
				ai.m_flyAbsMinAltitude = 0f;
				character.m_flySlowSpeed *= species.Scale;
				character.m_flyFastSpeed *= species.Scale;
			}
			Animator[] componentsInChildren2 = ((Component)character).GetComponentsInChildren<Animator>(true);
			foreach (Animator val2 in componentsInChildren2)
			{
				if (!Object.op_Implicit((Object)(object)val2.runtimeAnimatorController))
				{
					continue;
				}
				AnimationClip[] animationClips = val2.runtimeAnimatorController.animationClips;
				for (int num2 = 0; num2 < animationClips.Length; num2++)
				{
					AnimationEvent[] events = animationClips[num2].events;
					foreach (AnimationEvent val3 in events)
					{
						if (val3.functionName == "Effect" || val3.functionName == "Attach")
						{
							Object objectReferenceParameter = val3.objectReferenceParameter;
							GameObject val4 = (GameObject)(object)((objectReferenceParameter is GameObject) ? objectReferenceParameter : null);
							if (val4 != null)
							{
								CloneVisual(species, val4);
							}
						}
					}
				}
			}
			character.m_deathEffects = CopyEffects(species, character.m_deathEffects);
		}

		internal static void ConfigureWeapon(Species species, SharedData original, SharedData copy)
		{
			if (Object.op_Implicit((Object)(object)original.m_attack.m_spawnOnTrigger) && ((Object)original.m_attack.m_spawnOnTrigger).name == "aoe_nova")
			{
				copy.m_attack.m_spawnOnTrigger = Catalog.CloneProjectile(original.m_attack.m_spawnOnTrigger, species);
			}
			copy.m_triggerEffect = CopyEffects(species, copy.m_triggerEffect);
			copy.m_hitEffect = CopyEffects(species, copy.m_hitEffect);
		}

		internal static void ConfigureProjectile(Species species, GameObject prefab)
		{
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			ScaleVisuals(prefab, species.Scale);
			CinderSpawner[] componentsInChildren = prefab.GetComponentsInChildren<CinderSpawner>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			Projectile[] componentsInChildren2 = prefab.GetComponentsInChildren<Projectile>(true);
			foreach (Projectile val in componentsInChildren2)
			{
				((DamageTypes)(ref val.m_damage)).Modify(Rules.StatFactorFor(species.Id));
				val.m_damage.m_chop = 0f;
				val.m_damage.m_pickaxe = 0f;
				val.m_attackForce *= 0.2f;
				val.m_hitEffects = CopyEffects(species, val.m_hitEffects);
				val.m_spawnOnHitEffects = new EffectList();
			}
			SpawnAbility[] components = prefab.GetComponents<SpawnAbility>();
			foreach (SpawnAbility val2 in components)
			{
				string text = ((Object)prefab).name.Substring(("TG_Projectile_" + species.Id + "_").Length);
				if (!BossRules.OwnedVolley(text))
				{
					throw new InvalidOperationException("Unsupported boss spawn ability: " + text);
				}
				GuardianBossVolley guardianBossVolley = prefab.AddComponent<GuardianBossVolley>();
				guardianBossVolley.Projectiles = val2.m_spawnPrefab.Select((GameObject p) => Catalog.CloneProjectile(p, species)).ToArray();
				guardianBossVolley.MinCount = val2.m_minToSpawn;
				guardianBossVolley.MaxCount = val2.m_maxToSpawn;
				guardianBossVolley.Delay = val2.m_spawnDelay;
				guardianBossVolley.InitialDelay = val2.m_initialSpawnDelay;
				guardianBossVolley.Radius = val2.m_spawnRadius * species.Scale;
				guardianBossVolley.Height = val2.m_spawnGroundOffset * species.Scale;
				guardianBossVolley.Speed = val2.m_projectileVelocity;
				guardianBossVolley.Accuracy = val2.m_projectileAccuracy;
				guardianBossVolley.Circle = val2.m_circleSpawn;
				guardianBossVolley.AtTarget = val2.m_spawnAtTarget;
				guardianBossVolley.SnapToGround = val2.m_snapToTerrain;
				guardianBossVolley.MaxRange = Mathf.Min(25f, val2.m_maxTargetRange * species.Scale);
				Object.DestroyImmediate((Object)(object)val2);
			}
		}

		private static void RemoveYagluthAura(GameObject prefab)
		{
			Light[] componentsInChildren = prefab.GetComponentsInChildren<Light>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Component)componentsInChildren[i]).gameObject.SetActive(false);
			}
			ParticleSystem[] componentsInChildren2 = prefab.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val in componentsInChildren2)
			{
				if (((Object)val).name == "Particle System (2)")
				{
					((Component)val).gameObject.SetActive(false);
				}
			}
		}

		private static void ScaleVisuals(GameObject prefab, float scale)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystem[] componentsInChildren = prefab.GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				MainModule main = componentsInChildren[i].main;
				((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0;
			}
			Light[] componentsInChildren2 = prefab.GetComponentsInChildren<Light>(true);
			foreach (Light obj in componentsInChildren2)
			{
				obj.range *= scale;
			}
			CamShaker[] componentsInChildren3 = prefab.GetComponentsInChildren<CamShaker>(true);
			foreach (CamShaker obj2 in componentsInChildren3)
			{
				obj2.m_range *= scale;
				obj2.m_strength *= 0.2f;
			}
		}

		private static EffectList CopyEffects(Species species, EffectList effects)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			return new EffectList
			{
				m_effectPrefabs = ((IEnumerable<EffectData>)(effects?.m_effectPrefabs ?? Array.Empty<EffectData>())).Select((Func<EffectData, EffectData>)((EffectData e) => new EffectData
				{
					m_prefab = CloneVisual(species, e.m_prefab),
					m_enabled = e.m_enabled,
					m_variant = e.m_variant,
					m_attach = e.m_attach,
					m_follow = e.m_follow,
					m_inheritParentRotation = e.m_inheritParentRotation,
					m_inheritParentScale = false,
					m_multiplyParentVisualScale = false,
					m_randomRotation = e.m_randomRotation,
					m_scale = false,
					m_childTransform = e.m_childTransform
				})).ToArray()
			};
		}

		private static GameObject CloneVisual(Species species, GameObject original)
		{
			//IL_00a5: 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)
			if (!Object.op_Implicit((Object)(object)original))
			{
				return null;
			}
			bool flag = ((Object)original).name.StartsWith("TG_Remains_", StringComparison.Ordinal);
			string key = species.Id + ":" + ((Object)original).name;
			if (Effects.TryGetValue(key, out var value))
			{
				return value;
			}
			GameObject val = (flag ? original : PrefabManager.Instance.CreateClonedPrefab("TG_BossVisual_" + species.Id + "_" + ((Object)original).name, original));
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new InvalidOperationException("Missing boss guardian visual: " + ((Object)original).name);
			}
			Effects.Add(key, val);
			if (!flag)
			{
				Transform transform = val.transform;
				transform.localScale *= species.Scale;
			}
			ScaleVisuals(val, species.Scale);
			MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val2 in componentsInChildren)
			{
				if (val2 is Aoe || val2 is Projectile || val2 is SpawnAbility || val2 is CinderSpawner || val2 is SpawnOnDamaged || val2 is SpawnPrefab || val2 is TerrainModifier || val2 is TerrainOp || val2 is CharacterDrop || val2 is DropProjectileOverDistance)
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
			}
			Ragdoll[] componentsInChildren2 = val.GetComponentsInChildren<Ragdoll>(true);
			foreach (Ragdoll val3 in componentsInChildren2)
			{
				val3.m_dropItems = false;
				val3.m_removeEffect = CopyEffects(species, val3.m_removeEffect);
			}
			if (!flag)
			{
				PrefabManager.Instance.AddPrefab(val);
			}
			return val;
		}

		internal static GameObject Visual(Guardian guardian, GameObject original)
		{
			if (!Object.op_Implicit((Object)(object)guardian) || !Object.op_Implicit((Object)(object)original) || !Effects.TryGetValue(guardian.SpeciesId + ":" + ((Object)original).name, out var value))
			{
				return null;
			}
			return value;
		}
	}
	[HarmonyPatch(typeof(AnimationEffect), "Attach")]
	internal static class GuardianBossAttachment
	{
		private static void Prefix(AnimationEffect __instance, AnimationEvent e)
		{
			Guardian componentInParent = ((Component)__instance).GetComponentInParent<Guardian>();
			Object objectReferenceParameter = e.objectReferenceParameter;
			GameObject val = BossGuardians.Visual(componentInParent, (GameObject)(object)((objectReferenceParameter is GameObject) ? objectReferenceParameter : null));
			if (Object.op_Implicit((Object)(object)val))
			{
				e.objectReferenceParameter = (Object)(object)val;
				if (e.intParameter == 10)
				{
					e.intParameter = 1;
				}
				else if (e.intParameter == -10)
				{
					e.intParameter = -1;
				}
			}
		}
	}
	[HarmonyPatch(typeof(AnimationEffect), "Effect")]
	internal static class GuardianBossVisual
	{
		private static bool Prefix(AnimationEffect __instance, AnimationEvent e)
		{
			//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)
			Guardian componentInParent = ((Component)__instance).GetComponentInParent<Guardian>();
			Object objectReferenceParameter = e.objectReferenceParameter;
			GameObject val = BossGuardians.Visual(componentInParent, (GameObject)(object)((objectReferenceParameter is GameObject) ? objectReferenceParameter : null));
			if (!Object.op_Implicit((Object)(object)val))
			{
				return true;
			}
			Transform val2 = (string.IsNullOrEmpty(e.stringParameter) ? null : Utils.FindChild(((Component)__instance).transform, e.stringParameter, (IterativeSearchType)0));
			if (!Object.op_Implicit((Object)(object)val2))
			{
				val2 = (Object.op_Implicit((Object)(object)__instance.m_effectRoot) ? __instance.m_effectRoot : ((Component)__instance).transform);
			}
			Object.Instantiate<GameObject>(val, val2.position, val2.rotation);
			return false;
		}
	}
	internal static class BossHealth
	{
		internal const string RevisionKey = "enoq.tg.v1.bossHealthRevision";

		internal static void Upgrade(Character character)
		{
			Guardian guardian = (Object.op_Implicit((Object)(object)character) ? ((Component)character).GetComponent<Guardian>() : null);
			if (!Object.op_Implicit((Object)(object)guardian) || !BossRules.IsBoss(guardian.SpeciesId))
			{
				return;
			}
			ZNetView component = ((Component)character).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || !component.IsOwner())
			{
				return;
			}
			ZDO zDO = component.GetZDO();
			if (zDO.GetLong("enoq.tg.v1.owner", 0L) != 0L && !zDO.GetBool("enoq.tg.v1.stored", false))
			{
				float num = zDO.GetFloat(ZDOVars.s_maxHealth, 0f);
				if (BossRules.TryUpgradeHealth(zDO.GetInt("enoq.tg.v1.bossHealthRevision", 0), num, zDO.GetFloat(ZDOVars.s_health, num), out var newMaximum, out var newHealth))
				{
					zDO.Set(ZDOVars.s_maxHealth, newMaximum);
					zDO.Set(ZDOVars.s_health, newHealth);
					zDO.Set("enoq.tg.v1.bossHealthRevision", 1);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Character), "Awake")]
	internal static class GuardianBossHealthLoad
	{
		private static void Prefix(Character __instance)
		{
			BossHealth.Upgrade(__instance);
		}
	}
	internal static class BossRules
	{
		internal const float StatFactor = 0.3f;

		internal const int HealthRevision = 1;

		internal static bool TryUpgradeHealth(int revision, float maximum, float health, out float newMaximum, out float newHealth)
		{
			newMaximum = maximum;
			newHealth = health;
			if (revision >= 1 || !Rules.Finite(maximum) || !Rules.Finite(health) || maximum <= 0f || health <= 0f)
			{
				return false;
			}
			float num = 1.5f;
			newMaximum = maximum * num;
			newHealth = Math.Min(health, maximum) * num;
			if (Rules.Finite(newMaximum))
			{
				return Rules.Finite(newHealth);
			}
			return false;
		}

		internal static bool IsBoss(string id)
		{
			switch (id)
			{
			default:
				return id == "Fader";
			case "Eikthyr":
			case "gd_king":
			case "Bonemass":
			case "Dragon":
			case "GoblinKing":
			case "SeekerQueen":
				return true;
			}
		}

		internal static bool ExcludeWeapon(string name)
		{
			switch (name)
			{
			default:
				return name == "Fader_Roar_Intense";
			case "gd_king_rootspawn":
			case "bonemass_attack_throw":
			case "SeekerQueen_Call":
			case "SeekerQueen_Teleport":
			case "Fader_Roar":
				return true;
			}
		}

		internal static bool OwnedVolley(string name)
		{
			switch (name)
			{
			default:
				return name == "Fader_WallOfFire_Spawn";
			case "spawn_meteors":
			case "spawn_fader_meteors":
			case "Fader_Fissure_Spawn":
				return true;
			}
		}
	}
	internal enum BottleBiome
	{
		Meadows,
		BlackForest,
		Swamp,
		Mountain,
		Plains,
		Mistlands,
		AshLands,
		DeepNorth,
		Ocean
	}
	internal static class BottleIcon
	{
		private static readonly Dictionary<BottleBiome, Sprite> Icons = new Dictionary<BottleBiome, Sprite>();

		private static readonly Dictionary<BottleBiome, string> Files = new Dictionary<BottleBiome, string>
		{
			{
				BottleBiome.Meadows,
				"frasco_praderas"
			},
			{
				BottleBiome.BlackForest,
				"frasco_bosque_negro"
			},
			{
				BottleBiome.Swamp,
				"frasco_pantano"
			},
			{
				BottleBiome.Mountain,
				"frasco_montanas"
			},
			{
				BottleBiome.Plains,
				"frasco_llanuras"
			},
			{
				BottleBiome.Mistlands,
				"frasco_tierras_brumosas"
			},
			{
				BottleBiome.AshLands,
				"frasco_tierras_ceniza"
			},
			{
				BottleBiome.DeepNorth,
				"frasco_norte_profundo"
			},
			{
				BottleBiome.Ocean,
				"frasco_bosque_negro"
			}
		};

		internal static Sprite Get(BottleBiome biome)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			if (Icons.TryGetValue(biome, out var value) && Object.op_Implicit((Object)(object)value))
			{
				return value;
			}
			if (!Files.TryGetValue(biome, out var value2))
			{
				throw new ArgumentOutOfRangeException("biome");
			}
			using Stream stream = typeof(BottleIcon).Assembly.GetManifestResourceStream("TrophyGuard.Assets.Biomes." + value2 + ".png");
			using MemoryStream memoryStream = new MemoryStream();
			if (stream == null)
			{
				throw new InvalidDataException("Missing guardian bottle icon: " + value2);
			}
			stream.CopyTo(memoryStream);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false)
			{
				name = "TG_" + value2,
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			if (!AssetUtils.LoadImage(val, memoryStream.ToArray()))
			{
				Object.Destroy((Object)(object)val);
				throw new InvalidDataException("Invalid guardian bottle PNG: " + value2);
			}
			value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
			((Object)value).name = "TG_" + value2;
			val.Apply(false, true);
			Icons[biome] = value;
			return value;
		}
	}
	internal static class BottleModel
	{
		private sealed class Part
		{
			internal int Track;

			internal int Material;

			internal Mesh Mesh;
		}

		private struct Pose
		{
			internal Vector3 Position;

			internal Vector3 Scale;

			internal Quaternion Rotation;
		}

		private static Part[] parts;

		private static Pose[,] poses;

		private static float duration;

		private static Texture2D atlas;

		private static Texture2D fade;

		private static readonly Dictionary<BottleBiome, Material[]> Materials = new Dictionary<BottleBiome, Material[]>();

		private static readonly Color[] Palettes = (Color[])(object)new Color[9]
		{
			new Color(0.025f, 0.5f, 0.08f),
			new Color(0.028f, 0.14f, 0.64f),
			new Color(0.64f, 0.14f, 0.016f),
			new Color(0.015f, 0.48f, 0.6f),
			new Color(0.62f, 0.42f, 0.02f),
			new Color(0.22f, 0.018f, 0.56f),
			new Color(0.62f, 0.018f, 0.028f),
			new Color(0.6f, 0.024f, 0.23f),
			new Color(0.028f, 0.14f, 0.64f)
		};

		internal static void Install(ItemDrop drop, BottleBiome biome)
		{
			//IL_01c2: 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_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Expected O, but got Unknown
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_0357: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Expected O, but got Unknown
			Load();
			GameObject gameObject = ((Component)drop).gameObject;
			Material[] materials = GetMaterials(gameObject, biome);
			Renderer[] componentsInChildren = gameObject.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			MeshFilter[] componentsInChildren2 = gameObject.GetComponentsInChildren<MeshFilter>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			Transform val = gameObject.transform.Find("attach");
			if (Object.op_Implicit((Object)(object)val))
			{
				Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
			}
			Transform val2 = Child(gameObject.transform, "attach", gameObject.layer);
			Transform[] array = (Transform[])(object)new Transform[poses.GetLength(1)];
			for (int j = 0; j < array.Length; j++)
			{
				array[j] = Child(val2, "Motion_" + j, gameObject.layer);
			}
			Part[] array2 = parts;
			foreach (Part part in array2)
			{
				GameObject gameObject2 = ((Component)Child((part.Track < 0) ? val2 : array[part.Track], ((Object)part.Mesh).name, gameObject.layer)).gameObject;
				gameObject2.AddComponent<MeshFilter>().sharedMesh = part.Mesh;
				MeshRenderer obj = gameObject2.AddComponent<MeshRenderer>();
				((Renderer)obj).sharedMaterial = materials[part.Material];
				bool flag = part.Material == 0 || part.Material >= 5;
				((Renderer)obj).shadowCastingMode = (ShadowCastingMode)(!flag);
				((Renderer)obj).receiveShadows = !flag;
			}
			Sample(array, 0f);
			Transform obj2 = Child(val2, "Interior_light", gameObject.layer);
			obj2.localPosition = new Vector3(0f, 0.073f, -0.032f);
			obj2.localRotation = Quaternion.LookRotation(new Vector3(0f, 0.095f, 0.021f));
			Light val3 = ((Component)obj2).gameObject.AddComponent<Light>();
			val3.type = (LightType)0;
			val3.color = ((Color)(ref Palettes[(int)biome])).gamma;
			val3.intensity = 0.8f;
			val3.range = 0.28f;
			val3.spotAngle = 95f;
			val3.shadows = (LightShadows)0;
			val3.cullingMask = 1 << gameObject.layer;
			((Behaviour)val3).enabled = false;
			((Component)val2).gameObject.AddComponent<BottleMotion>().Configure(array, val3);
			BoxCollider[] componentsInChildren3 = gameObject.GetComponentsInChildren<BoxCollider>(true);
			foreach (BoxCollider obj3 in componentsInChildren3)
			{
				((Component)obj3).transform.localPosition = Vector3.zero;
				((Component)obj3).transform.localRotation = Quaternion.identity;
				((Component)obj3).transform.localScale = Vector3.one;
				obj3.center = new Vector3(0f, 0.1745f, 0f);
				obj3.size = new Vector3(0.156f, 0.343f, 0.156f);
			}
			drop.m_itemData.m_shared.m_itemStandOffsets = new List<OrientationSettings>
			{
				new OrientationSettings
				{
					m_orientations = (Orientation)2,
					m_position = new Vector3(0f, 0.05f, 0f)
				},
				new OrientationSettings
				{
					m_orientations = (Orientation)1,
					m_position = new Vector3(0f, 0f, -0.1745f),
					m_rotation = new Vector3(90f, 0f, 0f)
				}
			};
		}

		private static Transform Child(Transform parent, string name, int layer)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name)
			{
				layer = layer
			};
			val.transform.SetParent(parent, false);
			return val.transform;
		}

		internal static void Sample(Transform[] tracks, float time)
		{
			//IL_0079: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
			if (poses != null && tracks != null && tracks.Length == poses.GetLength(1))
			{
				int num = poses.GetLength(0) - 1;
				float num2 = Mathf.Repeat(time, duration) * (float)num / duration;
				int num3 = Mathf.Min((int)num2, num - 1);
				int num4 = num3 + 1;
				float num5 = num2 - (float)num3;
				for (int i = 0; i < tracks.Length; i++)
				{
					Pose pose = poses[num3, i];
					Pose pose2 = poses[num4, i];
					tracks[i].localPosition = Vector3.LerpUnclamped(pose.Position, pose2.Position, num5);
					tracks[i].localRotation = Quaternion.SlerpUnclamped(pose.Rotation, pose2.Rotation, num5);
					tracks[i].localScale = Vector3.LerpUnclamped(pose.Scale, pose2.Scale, num5);
				}
			}
		}

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

		private static void Load()
		{
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: 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_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Expected O, but got Unknown
			if (parts != null)
			{
				return;
			}
			using Stream stream = typeof(BottleModel).Assembly.GetManifestResourceStream("TrophyGuard.Assets.Runtime.bottle.bin");
			using BinaryReader binaryReader = new BinaryReader(stream ?? throw new InvalidDataException("Missing bottle mesh"));
			if (binaryReader.ReadInt32() != 1296515641 || binaryReader.ReadInt32() != 1)
			{
				throw new InvalidDataException("Bottle mesh version");
			}
			int num = binaryReader.ReadInt32();
			int num2 = binaryReader.ReadInt32();
			int num3 = binaryReader.ReadInt32();
			duration = binaryReader.ReadSingle();
			if (num < 1 || num > 32 || num2 != 10 || num3 != 97 || duration != 8f)
			{
				throw new InvalidDataException("Bottle mesh header");
			}
			Part[] array = new Part[num];
			for (int i = 0; i < num; i++)
			{
				int num4 = binaryReader.ReadInt32();
				int num5 = binaryReader.ReadInt32();
				int num6 = binaryReader.ReadInt32();
				int num7 = binaryReader.ReadInt32();
				if (num4 < -1 || num4 >= num2 || num5 < 0 || num5 > 6 || num6 < 3 || num6 > 16000 || num7 < 3 || num7 > 48000 || num7 % 3 != 0)
				{
					throw new InvalidDataException("Bottle mesh counts");
				}
				Vector3[] array2 = (Vector3[])(object)new Vector3[num6];
				Vector3[] array3 = (Vector3[])(object)new Vector3[num6];
				Vector2[] array4 = (Vector2[])(object)new Vector2[num6];
				for (int j = 0; j < num6; j++)
				{
					array2[j] = Vector(binaryReader);
					array3[j] = Vector(binaryReader);
					array4[j] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
				}
				int[] array5 = new int[num7];
				for (int k = 0; k < num7; k++)
				{
					array5[k] = binaryReader.ReadInt32();
					if (array5[k] < 0 || array5[k] >= num6)
					{
						throw new InvalidDataException("Bottle mesh index");
					}
				}
				Mesh val = new Mesh
				{
					name = "Bottle_part_" + i,
					vertices = array2,
					normals = array3,
					uv = array4,
					triangles = array5
				};
				val.RecalculateBounds();
				val.UploadMeshData(true);
				array[i] = new Part
				{
					Track = num4,
					Material = num5,
					Mesh = val
				};
			}
			poses = new Pose[num3, num2];
			for (int l = 0; l < num3; l++)
			{
				for (int m = 0; m < num2; m++)
				{
					poses[l, m] = new Pose
					{
						Position = Vector(binaryReader),
						Rotation = new Quaternion(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()),
						Scale = Vector(binaryReader)
					};
				}
			}
			if (stream.Position != stream.Length)
			{
				throw new InvalidDataException("Trailing bottle mesh data");
			}
			parts = array;
		}

		private static Material[] GetMaterials(GameObject source, BottleBiome biome)
		{
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: 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_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_008c: 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_009c: 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_00af: Expected O, but got Unknown
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Expected O, but got Unknown
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: 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_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0499: Unknown result type (might be due to invalid IL or missing references)
			//IL_049f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0492: Unknown result type (might be due to invalid IL or missing references)
			//IL_047e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Unknown result type (might be due to invalid IL or missing references)
			//IL_0465: Unknown result type (might be due to invalid IL or missing references)
			//IL_045e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			if (Materials.TryGetValue(biome, out var value))
			{
				return value;
			}
			if (!Object.op_Implicit((Object)(object)atlas))
			{
				using (Stream stream = typeof(BottleModel).Assembly.GetManifestResourceStream("TrophyGuard.Assets.Runtime.bottle_atlas.png"))
				{
					using MemoryStream memoryStream = new MemoryStream();
					if (stream == null)
					{
						throw new InvalidDataException("Missing bottle atlas");
					}
					stream.CopyTo(memoryStream);
					Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
					try
					{
						if (!AssetUtils.LoadImage(val, memoryStream.ToArray()))
						{
							throw new InvalidDataException("Invalid bottle atlas");
						}
						atlas = new Texture2D(128, 128, (TextureFormat)4, false)
						{
							name = "Bottle_atlas",
							filterMode = (FilterMode)0,
							wrapMode = (TextureWrapMode)1
						};
						Color[] array = (Color[])(object)new Color[16384];
						for (int i = 0; i < 128; i++)
						{
							for (int j = 0; j < 128; j++)
							{
								array[i * 128 + j] = val.GetPixel((int)(((float)j + 0.5f) * (float)((Texture)val).width / 128f), (int)(((float)i + 0.5f) * (float)((Texture)val).height / 128f));
							}
						}
						atlas.SetPixels(array);
						atlas.Apply(false, true);
					}
					finally
					{
						Object.Destroy((Object)(object)val);
					}
				}
				fade = new Texture2D(256, 1, (TextureFormat)4, false)
				{
					name = "Bottle_mist_fade",
					filterMode = (FilterMode)1,
					wrapMode = (TextureWrapMode)1
				};
				Color[] array2 = (Color[])(object)new Color[256];
				for (int k = 0; k < array2.Length; k++)
				{
					array2[k] = new Color(1f, 1f, 1f, (float)k / 255f);
				}
				fade.SetPixels(array2);
				fade.Apply(false, true);
			}
			Material sharedMaterial = ((Renderer)source.GetComponentInChildren<MeshRenderer>(true)).sharedMaterial;
			Material[] array3 = (Material[])(object)new Material[7];
			Color val2 = Palettes[(int)biome];
			for (int l = 0; l < array3.Length; l++)
			{
				Material val3 = new Material(sharedMaterial)
				{
					name = "Bottle_" + biome.ToString() + "_" + l
				};
				val3.shaderKeywords = Array.Empty<string>();
				string[] array4 = new string[7] { "_BumpMap", "_DetailNormalMap", "_DetailAlbedoMap", "_MetallicGlossMap", "_OcclusionMap", "_ParallaxMap", "_EmissionMap" };
				foreach (string text in array4)
				{
					if (val3.HasProperty(text))
					{
						val3.SetTexture(text, (Texture)null);
					}
				}
				val3.mainTexture = (Texture)(object)((l < 4) ? atlas : ((l >= 5) ? fade : Texture2D.whiteTexture));
				val3.mainTextureScale = Vector2.one;
				val3.mainTextureOffset = Vector2.zero;
				Color val4 = (Color)(l switch
				{
					4 => Color.Lerp(val2, Color.white, 0.18f), 
					0 => Color.Lerp(new Color(0.75f, 0.83f, 0.8f), val2, 0.12f), 
					3 => Color.Lerp(new Color(0.16f, 0.16f, 0.18f), val2, 0.25f), 
					2 => new Color(0.88f, 0.73f, 0.55f), 
					1 => new Color(0.72f, 0.75f, 0.71f), 
					_ => val2, 
				});
				val3.color = ((Color)(ref val4)).gamma;
				if (l == 0)
				{
					Color color = val3.color;
					color.a = 0.19f;
					val3.color = color;
				}
				Set(val3, "_Glossiness", (l == 0) ? 0.24f : 0.08f);
				Set(val3, "_Metallic", (l == 1) ? 0.18f : 0f);
				Set(val3, "_BumpScale", 0f);
				Set(val3, "_ValueNoise", 0f);
				Set(val3, "_AddRain", 0f);
				Set(val3, "_MoveableObject", 1f);
				Color val5 = ((l == 0) ? (val2 * 0.025f) : ((l == 3) ? (val2 * 0.02f) : ((l == 4) ? (val4 * 2.8f) : ((l >= 5) ? (val2 * ((l == 5) ? 1.35f : 2f)) : Color.black))));
				val3.SetColor("_EmissionColor", val5);
				if (((Color)(ref val5)).maxColorComponent > 0f)
				{
					val3.EnableKeyword("_EMISSION");
				}
				bool flag = l == 0 || l >= 5;
				Set(val3, "_Mode", flag ? 2 : 0);
				Set(val3, "_SrcBlend", (!flag) ? 1 : 5);
				Set(val3, "_DstBlend", flag ? 10 : 0);
				Set(val3, "_ZWrite", (!flag) ? 1 : 0);
				val3.SetOverrideTag("RenderType", flag ? "Transparent" : "Opaque");
				if (flag)
				{
					val3.EnableKeyword("_ALPHABLEND_ON");
				}
				val3.renderQueue = ((l == 0) ? 3010 : (flag ? 3000 : 2000));
				array3[l] = val3;
			}
			Materials[biome] = array3;
			return array3;
		}

		private static void Set(Material material, string name, float value)
		{
			if (material.HasProperty(name))
			{
				material.SetFloat(name, value);
			}
		}
	}
	public sealed class BottleMotion : MonoBehaviour
	{
		[SerializeField]
		private Transform[] tracks;

		[SerializeField]
		private Light interiorLight;

		private static Camera camera;

		private static int cameraFrame = -1;

		private float nextCheck;

		private float phase;

		private bool animate;

		internal void Configure(Transform[] targets, Light light)
		{
			tracks = targets;
			interiorLight = light;
		}

		private void OnEnable()
		{
			phase = (float)(((Object)this).GetInstanceID() & 0x3FF) / 128f;
			nextCheck = 0f;
		}

		private void OnDisable()
		{
			if (Object.op_Implicit((Object)(object)interiorLight))
			{
				((Behaviour)interiorLight).enabled = false;
			}
		}

		private void LateUpdate()
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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)
			if (Time.unscaledTime >= nextCheck)
			{
				nextCheck = Time.unscaledTime + 0.3f;
				if (cameraFrame != Time.frameCount)
				{
					if (!Object.op_Implicit((Object)(object)camera) || !((Behaviour)camera).isActiveAndEnabled)
					{
						camera = Camera.main;
					}
					cameraFrame = Time.frameCount;
				}
				float num;
				if (!Object.op_Implicit((Object)(object)camera))
				{
					num = float.PositiveInfinity;
				}
				else
				{
					Vector3 val = ((Component)camera).transform.position - ((Component)this).transform.position;
					num = ((Vector3)(ref val)).sqrMagnitude;
				}
				float num2 = num;
				animate = num2 < 900f;
				if (Object.op_Implicit((Object)(object)interiorLight))
				{
					((Behaviour)interiorLight).enabled = num2 < 36f;
				}
			}
			if (animate)
			{
				BottleModel.Sample(tracks, Time.time + phase);
			}
		}
	}
	[HarmonyPatch(typeof(ItemStand), "CanAttach")]
	internal static class BottleStand
	{
		private static bool Prefix(ItemStand __instance, ItemData item, ref bool __result)
		{
			if (Catalog.FromItem(item) == null)
			{
				return true;
			}
			string text = ((Object)((Component)__instance).gameObject).name.Replace("(Clone)", "");
			if (text != "itemstand" && text != "itemstandh")
			{
				return true;
			}
			__result = (Object)(object)ItemStand.GetAttachPrefab(item.m_dropPrefab) != (Object)null;
			return false;
		}
	}
	internal sealed class BottleState
	{
		internal const string ItemKey = "TrophyGuard.resting";

		internal const double FullRestSeconds = 240.0;

		internal readonly string Token;

		internal readonly string Species;

		internal readonly string Name;

		internal readonly string OwnerName;

		internal readonly long StoredBy;

		private readonly int format;

		internal readonly long Owner;

		internal readonly long World;

		internal readonly long StoredTicks;

		internal readonly long SourceUser;

		internal readonly uint SourceId;

		internal readonly float Health;

		internal readonly int Phase;

		internal readonly int Xp;

		internal BottleState(string token, string species, string name, long owner, long world, float health, long ticks, long sourceUser, uint sourceId, string ownerName = "", long storedBy = 0L, int format = 4, int phase = 0, int xp = 0)
		{
			if (Guid.TryParseExact(token, "N", out var _) && OperationTicket.Identifier(species) && owner != 0L && world != 0L && Rules.Finite(health) && !(health <= 0f) && !(health > 1f) && ticks > 0)
			{
				DateTime maxValue = DateTime.MaxValue;
				if (ticks <= maxValue.Ticks && sourceUser != 0L && sourceId != 0 && name != null && !(Rules.CleanName(name) != name) && ownerName != null && !(Rules.CleanName(ownerName) != ownerName) && format >= 1 && format <= 4 && DuoRules.ValidPhase(species, phase) && (format >= 3 || phase == 0) && xp >= 0 && xp <= 1000000 && (format >= 4 || xp == 0))
				{
					Token = token;
					Species = species;
					Name = name;
					Owner = owner;
					World = world;
					Health = health;
					StoredTicks = ticks;
					SourceUser = sourceUser;
					SourceId = sourceId;
					OwnerName = ownerName;
					StoredBy = ((storedBy == 0L) ? owner : storedBy);
					this.format = format;
					Phase = phase;
					Xp = xp;
					return;
				}
			}
			throw new InvalidDataException("Invalid resting guardian");
		}

		internal float HealthAt(long utcTicks)
		{
			return (float)Math.Min(1.0, (double)Health + Math.Max(0.0, ((double)utcTicks - (double)StoredTicks) / 10000000.0) / 240.0);
		}

		internal double SecondsLeft(long utcTicks)
		{
			return Math.Max(0.0, (double)(1f - HealthAt(utcTicks)) * 240.0);
		}

		internal string Encode()
		{
			using MemoryStream memoryStream = new MemoryStream();
			using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream, Encoding.UTF8, leaveOpen: true))
			{
				binaryWriter.Write(format);
				binaryWriter.Write(Token);
				binaryWriter.Write(Species);
				binaryWriter.Write(Name);
				binaryWriter.Write(Owner);
				binaryWriter.Write(World);
				binaryWriter.Write(Health);
				binaryWriter.Write(StoredTicks);
				binaryWriter.Write(SourceUser);
				binaryWriter.Write(SourceId);
				if (format >= 2)
				{
					binaryWriter.Write(OwnerName);
					binaryWriter.Write(StoredBy);
				}
				if (format >= 3)
				{
					binaryWriter.Write(Phase);
				}
				if (format >= 4)
				{
					binaryWriter.Write(Xp);
				}
			}
			return Convert.ToBase64String(memoryStream.ToArray());
		}

		internal static BottleState Decode(string encoded)
		{
			if (string.IsNullOrEmpty(encoded) || encoded.Length > 2048)
			{
				throw new InvalidDataException("Invalid bottle payload length");
			}
			try
			{
				using MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(encoded));
				using BinaryReader binaryReader = new BinaryReader(memoryStream, Encoding.UTF8);
				int num = binaryReader.ReadInt32();
				if (num < 1 || num > 4)
				{
					throw new InvalidDataException("Unknown bottle format");
				}
				string token = binaryReader.ReadString();
				string species = binaryReader.ReadString();
				string name = binaryReader.ReadString();
				long num2 = binaryReader.ReadInt64();
				long world = binaryReader.ReadInt64();
				float health = binaryReader.ReadSingle();
				long ticks = binaryReader.ReadInt64();
				long sourceUser = binaryReader.ReadInt64();
				uint sourceId = binaryReader.ReadUInt32();
				string ownerName = ((num == 1) ? "" : binaryReader.ReadString());
				long num3 = ((num == 1) ? num2 : binaryReader.ReadInt64());
				int phase = ((num >= 3) ? binaryReader.ReadInt32() : 0);
				int xp = ((num >= 4) ? binaryReader.ReadInt32() : 0);
				if (num3 == 0L)
				{
					throw new InvalidDataException("Missing bottle recipient");
				}
				BottleState result = new BottleState(token, species, name, num2, world, health, ticks, sourceUser, sourceId, ownerName, num3, num, phase, xp);
				if (memoryStream.Position != memoryStream.Length)
				{
					throw new InvalidDataException("Extra bottle data");
				}
				return result;
			}
			catch (Exception ex) when (ex is FormatException || ex is EndOfStreamException || ex is ArgumentException)
			{
				throw new InvalidDataException("Invalid bottle payload", ex);
			}
		}
	}
	internal sealed class OperationTicket
	{
		internal readonly string Nonce;

		internal readonly string Species;

		internal readonly string Action;

		internal readonly string Payload;

		internal readonly string Vial;

		internal readonly float X;

		internal readonly float Y;

		internal readonly float Z;

		internal bool Capture => Action == "capture";

		internal OperationTicket(string nonce, string species, float x, float y, float z, string action = "spawn", string payload = "", string vial = "")
		{
			if (Guid.TryParseExact(nonce, "N", out var _) && Identifier(species) && Rules.Finite(x) && Rules.Finite(y) && Rules.Finite(z) && (!(action != "spawn") || !(action != "capture")) && payload != null && payload.Length <= 2048 && payload.IndexOfAny(new char[3] { '|', '\r', '\n' }) < 0)
			{
				bool num;
				if (!(action == "capture"))
				{
					if (!(vial != ""))
					{
						goto IL_00d1;
					}
					num = !Identifier(vial);
				}
				else
				{
					num = !Identifier(vial);
				}
				if (!num)
				{
					goto IL_00d1;
				}
			}
			throw new InvalidDataException("Invalid operation ticket");
			IL_00d1:
			Nonce = nonce;
			Species = species;
			X = x;
			Y = y;
			Z = z;
			Action = action;
			Payload = payload;
			Vial = vial;
		}

		internal static bool Identifier(string value)
		{
			if (string.IsNullOrEmpty(value) || value.Length > 128)
			{
				return false;
			}
			foreach (char c in value)
			{
				if (!char.IsLetterOrDigit(c) && c != '_')
				{
					return false;
				}
			}
			return true;
		}

		internal OperationTicket WithPayload(string payload)
		{
			return new OperationTicket(Nonce, Species, X, Y, Z, Action, payload, Vial);
		}

		internal string Encode()
		{
			string[] obj = new string[8] { Nonce, Species, null, null, null, null, null, null };
			float x = X;
			obj[2] = x.ToString("R", CultureInfo.InvariantCulture);
			x = Y;
			obj[3] = x.ToString("R", CultureInfo.InvariantCulture);
			x = Z;
			obj[4] = x.ToString("R", CultureInfo.InvariantCulture);
			obj[5] = Action;
			obj[6] = Payload;
			obj[7] = Vial;
			return string.Join("|", obj);
		}

		internal static OperationTicket Decode(string text)
		{
			string[] array = (text ?? "").Split(new char[1] { '|' });
			if ((array.Length != 5 && array.Length != 8) || !float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) || !float.TryParse(array[4], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
			{
				throw new InvalidDataException("Invalid operation ticket");
			}
			return new OperationTicket(array[0], array[1], result, result2, result3, (array.Length == 5) ? "spawn" : array[5], (array.Length == 5) ? "" : array[6], (array.Length == 5) ? "" : array[7]);
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(bool),
		typeof(float),
		typeof(int),
		typeof(bool)
	})]
	internal static class BottleTooltip
	{
		private static void Postfix(ItemData item, ref string __result)
		{
			if (Catalog.FromItem(item) == null)
			{
				return;
			}
			__result = __result + "\n" + Texts.T("tg_training_hint");
			if (!item.m_customData.TryGetValue("TrophyGuard.resting", out var value))
			{
				return;
			}
			try
			{
				BottleState bottleState = BottleState.Decode(value);
				long ticks = DateTime.UtcNow.Ticks;
				__result = __result + "\n\n" + Texts.T("tg_rest_name") + ": " + ((bottleState.Name.Length > 0) ? bottleState.Name : Localization.instance.Localize(Catalog.Find(bottleState.Species)?.Label ?? "Guardian"));
				string[] obj = new string[5]
				{
					__result,
					"\n",
					Texts.T("tg_owner"),
					": ",
					null
				};
				string text;
				if (bottleState.OwnerName.Length <= 0)
				{
					long owner = bottleState.Owner;
					text = owner.ToString(CultureInfo.InvariantCulture);
				}
				else
				{
					text = bottleState.OwnerName;
				}
				obj[4] = text;
				__result = string.Concat(obj);
				__result = __result + "\n" + Texts.T("tg_rest_health") + ": " + Math.Floor(bottleState.HealthAt(ticks) * 100f) + "%";
				string[] obj2 = new string[6]
				{
					__result,
					"\n",
					Training.Summary(Catalog.Find(bottleState.Species), bottleState.Xp),
					" · ",
					null,
					null
				};
				int xp = bottleState.Xp;
				obj2[4] = xp.ToString();
				obj2[5] = " XP";
				__result = string.Concat(obj2);
				if (bottleState.Species == "GoblinBruteBros")
				{
					__result = __result + "\n" + Texts.T((bottleState.Phase == 1) ? "tg_duo_phase_zil" : "tg_duo_phase_both");
				}
				double num = bottleState.SecondsLeft(ticks);
				__result = __result + "\n" + ((num <= 0.0) ? Texts.T("tg_rest_ready") : (Texts.T("tg_rest_time") + ": " + Math.Ceiling(num) + " s"));
				__result = __result + "\n" + Texts.T("tg_rest_bound");
			}
			catch (InvalidDataException)
			{
				__result = __result + "\n" + Texts.T("tg_invalid_bottle");
			}
		}
	}
	[HarmonyPatch(typeof(Character), "ApplyDamage")]
	internal static class CaptureDamage
	{
		private static bool Prefix(Character __instance)
		{
			return !(((Component)__instance).GetComponent<Guardian>()?.Capturing ?? false);
		}
	}
	internal static class Network
	{
		private sealed class CaptureProbe
		{
			internal long Sender;

			internal long Owner;

			internal long Authority;

			internal string Nonce;

			internal string Species;

			internal ZDOID Target;

			internal float SentAt;
		}

		private sealed class NoticeReport
		{
			internal ZDOID Id;

			internal string Token;

			internal string Name;

			internal GuardianNoticeKind Kind;

			internal int Rank;
		}

		private sealed class NoticeMessage
		{
			internal NoticeReport Report;

			internal long Owner;

			internal string Species;

			internal string Token;
		}

		private sealed class NoticeDelivery
		{
			internal NoticeMessage Message;

			internal ZNetPeer Connection;
		}

		private sealed class RemovedGuardian
		{
			internal Species Species;

			internal long Owner;

			internal long Authority;
		}

		private sealed class Commit
		{
			internal long Sender;

			internal long Owner;

			internal string Nonce;

			internal string Outcome;

			internal ZDO Created;

			internal ZDO Captured;

			internal string BottleToken;

			internal Task Write;
		}

		private sealed class AllyWrite
		{
			internal long Sender;

			internal long Owner;

			internal string Nonce;

			internal bool Allowed;

			internal Task Write;
		}

		private sealed class TrainingDelivery
		{
			internal ZDOID Guardian;

			internal string Token;

			internal int Reward;

			internal Vector3 Point;

			internal float Until;

			internal float Next;
		}

		internal const string CaptureRpc = "TG_Capture_v1";

		internal const string PrepareRpc = "TG_PrepareCapture_v1";

		internal const string PreparedRpc = "TG_CaptureReady_v3";

		internal const string CancelRpc = "TG_CancelCapture_v1";

		internal const string RecoverRpc = "TG_RecoverCapture_v1";

		private static readonly Dictionary<string, CaptureProbe> Probes = new Dictionary<string, CaptureProbe>();

		private static readonly Dictionary<string, BottleState> CapturedSources = new Dictionary<string, BottleState>();

		private static readonly GuardianIndex<ZDOID> MapIndex = new GuardianIndex<ZDOID>();

		private static ZDOMan indexedWorld;

		private const string NoticeReportRpc = "TG_NoticeReport_v2";

		private const string NoticeRpc = "TG_Notice_v2";

		private const string NoticeReportAckRpc = "TG_NoticeReportAck_v1";

		private const string NoticeDeliveryAckRpc = "TG_NoticeDeliveryAck_v1";

		private static readonly GuardianNoticeHistory reportedNotices = new GuardianNoticeHistory();

		private static readonly GuardianNoticeHistory shownNotices = new GuardianNoticeHistory();

		private static readonly GuardianNoticeOutbox<NoticeReport> noticeReports = new GuardianNoticeOutbox<NoticeReport>();

		private static readonly GuardianNoticeOutbox<NoticeDelivery> noticeDeliveries = new GuardianNoticeOutbox<NoticeDelivery>();

		private static readonly GuardianNoticeCache<bool> noticeReceipts = new GuardianNoticeCache<bool>();

		private static readonly GuardianNoticeCache<bool> recentNoticeAuthorities = new GuardianNoticeCache<bool>();

		private static readonly GuardianNoticeCache<RemovedGuardian> removedGuardians = new GuardianNoticeCache<RemovedGuardian>();

		private static float nextNoticePrune;

		internal const string SpawnRpc = "TG_Summon_v2";

		internal const string ReplyRpc = "TG_Reply_v1";

		internal const string OrderRpc = "TG_Order_v1";

		internal const string ApplyRpc = "TG_Apply_v1";

		private static readonly FieldRef<ZDOMan, Dictionary<ZDOID, ZDO>> Objects = AccessTools.FieldRefAccess<ZDOMan, Dictionary<ZDOID, ZDO>>("m_objectsByID");

		private static ZRoutedRpc registered;

		private static readonly NetworkSession<ZRoutedRpc> Session = new NetworkSession<ZRoutedRpc>();

		private static long world;

		private static Receipts receipts;

		private static readonly List<Commit> Commits = new List<Commit>();

		private const string AllyRpc = "TG_AllySet_v1";

		private const string AllyReplyRpc = "TG_AllyReply_v2";

		private const string StatusRpc = "TG_Status_v2";

		private const string StatusReplyRpc = "TG_StatusReply_v1";

		private const string AlliesRpc = "TG_Allies_v1";

		private static AllianceJournal alliances;

		private static AllianceReplica clientAlliances = new AllianceReplica();

		private static float nextStatus;

		private static float nextAllyRetry;

		private static string allyNonce;

		private static ZDOID allyTarget;

		private static bool allyDesired;

		private static long statusPlayer;

		private static readonly List<AllyWrite> AllyWrites = new List<AllyWrite>();

		private static readonly List<ZDO> mapGuardians = new List<ZDO>();

		internal const string TrainingRpc = "TG_TrainingDefeat_v1";

		internal const string AwardRpc = "TG_TrainingAward_v1";

		internal const string AwardAckRpc = "TG_TrainingAck_v1";

		private static readonly HashSet<ZDOID> TrainingDeaths = new HashSet<ZDOID>();

		private static readonly Dictionary<string, TrainingDelivery> TrainingDeliveries = new Dictionary<string, TrainingDelivery>();

		internal static long Server
		{
			get
			{
				if (Object.op_Implicit((Object)(object)ZNet.instance))
				{
					if (!ZNet.instance.IsServer())
					{
						return ZNet.instance.GetServerPeer()?.m_uid ?? 0;
					}
					return ZNet.GetUID();
				}
				return 0L;
			}
		}

		internal static bool SessionReady
		{
			get
			{
				if (Session.Ready && Object.op_Implicit((Object)(object)ZNet.instance))
				{
					return registered == ZRoutedRpc.instance;
				}
				return false;
			}
		}

		internal static bool AlliesReady
		{
			get
			{
				if (SessionReady)
				{
					if (!ZNet.instance.IsServer())
					{
						return clientAlliances.Revision >= 0;
					}
					return alliances != null;
				}
				return false;
			}
		}

		internal static string AccessDeniedText => AllianceValidation.DeniedMessage(AlliesReady);

		internal static string Source(ZDOID id)
		{
			return ((ZDOID)(ref id)).UserID.ToString(CultureInfo.InvariantCulture) + ":" + ((ZDOID)(ref id)).ID.ToString(CultureInfo.InvariantCulture);
		}

		private static bool TrySource(string text, out ZDOID id)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			id = ZDOID.None;
			string[] array = (text ?? "").Split(new char[1] { ':' });
			if (array.Length != 2 || !long.TryParse(array[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || result == 0L || !uint.TryParse(array[1], NumberStyles.None, CultureInfo.InvariantCulture, out var result2) || result2 == 0)
			{
				return false;
			}
			id = new ZDOID(result, result2);
			return true;
		}

		private static void RegisterCaptures(ZRoutedRpc rpc)
		{
			rpc.Register<string, string, string>("TG_Capture_v1", (Action<long, string, string, string>)Capture);
			rpc.Register<ZPackage>("TG_CaptureReady_v3", (Action<long, ZPackage>)Prepared);
			rpc.Register<ZDOID, string>("TG_RecoverCapture_v1", (Action<long, ZDOID, string>)Recover);
		}

		private static void RestoreCaptures()
		{
			//IL_002b: 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)
			BottleState[] array = receipts.Bottles();
			ZDOID val = default(ZDOID);
			foreach (BottleState bottleState in array)
			{
				((ZDOID)(ref val))..ctor(bottleState.SourceUser, bottleState.SourceId);
				CapturedSources[Source(val)] = bottleState;
				DestroyStored(ZDOMan.instance.GetZDO(val));
			}
		}

		private static void DestroyStored(ZDO zdo)
		{
			if (zdo != null)
			{
				zdo.Set("enoq.tg.v1.stored", true);
				ForgetGuardian(zdo);
				zdo.SetOwner(ZNet.GetUID());
				ZDOMan.instance.DestroyZDO(zdo);
			}
		}

		private static void CancelCapture(ZDO zdo, string nonce)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (zdo != null)
			{
				if (zdo.GetString("enoq.tg.v1.capture", "") == nonce)
				{
					zdo.Set("enoq.tg.v1.capture", "");
				}
				long owner = zdo.GetOwner();
				if (owner != 0L)
				{
					registered.InvokeRoutedRPC(owner, zdo.m_uid, "TG_CancelCapture_v1", new object[1] { nonce });
				}
			}
		}

		private static void Capture(long sender, string nonce, string species, string source)
		{
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: 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_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			if (!Guid.TryParseExact(nonce, "N", out var _) || !TrySource(source, out var id) || Catalog.Find(species) == null || !Caller(sender, out var owner, out var character, out var _))
			{
				return;
			}
			if (receipts == null)
			{
				Answer(sender, nonce, "busy");
				return;
			}
			string text = receipts.Get(owner, nonce, "Capture_" + species);
			if (text != null)
			{
				if (text.StartsWith("stored:", StringComparison.Ordinal))
				{
					BottleState bottleState = BottleState.Decode(text.Substring(7));
					DestroyStored(ZDOMan.instance.GetZDO(new ZDOID(bottleState.SourceUser, bottleState.SourceId)));
				}
				Answer(sender, nonce, text);
				return;
			}
			if (Commits.Any((Commit c) => c.Owner == owner && c.Nonce == nonce))
			{
				Answer(sender, nonce, "busy");
				return;
			}
			ZDO zdo = ZDOMan.instance.GetZDO(id);
			if (zdo == null || zdo.GetBool("enoq.tg.v1.stored", false) || CapturedSources.ContainsKey(source))
			{
				CaptureResult(sender, owner, nonce, species, "gone");
				return;
			}
			if (!CanUse(zdo.GetLong("enoq.tg.v1.owner", 0L), owner) || Catalog.FromPrefab(zdo.GetPrefab())?.Id != species)
			{
				CaptureResult(sender, owner, nonce, species, "denied");
				return;
			}
			if (Vector3.Distance(character.GetPosition(), zdo.GetPosition()) > 5f)
			{
				CaptureResult(sender, owner, nonce, species, "position");
				return;
			}
			if (Probes.Values.Any((CaptureProbe p) => p.Target == id && (p.Nonce != nonce || p.Owner != owner)) || Commits.Any((Commit c) => c.Captured == zdo))
			{
				Answer(sender, nonce, "busy");
				return;
			}
			long owner2 = zdo.GetOwner();
			if (owner2 == 0L)
			{
				Answer(sender, nonce, "busy");
				return;
			}
			string key = owner + ":" + nonce;
			if (!Probes.TryGetValue(key, out var value) || !(Time.unscaledTime - value.SentAt < 3f))
			{
				Probes[key] = new CaptureProbe
				{
					Sender = sender,
					Owner = owner,
					Authority = owner2,
					Nonce = nonce,
					Species = species,
					Target = id,
					SentAt = Time.unscaledTime
				};
				registered.InvokeRoutedRPC(owner2, id, "TG_PrepareCapture_v1", new object[2] { nonce, owner });
			}
		}

		internal static void Prepare(Guardian guardian, long sender, string nonce, long owner)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (FromServer(sender) && guardian.View.IsOwner() && Guid.TryParseExact(nonce, "N", out var _))
			{
				string text = ((!guardian.Valid || !CanUse(guardian.Owner, owner)) ? "denied" : (guardian.Character.IsDead() ? "gone" : (guardian.CanBottle() ? "stored" : "combat")));
				ZDO zDO = guardian.View.GetZDO();
				if (text == "stored")
				{
					zDO.Set("enoq.tg.v1.capture", nonce);
					guardian.Ai.StopMoving();
				}
				ZPackage val = new ZPackage();
				val.Write(nonce);
				val.Write(zDO.m_uid);
				val.Write(text);
				val.Write(guardian.Character.GetHealthPercentage());
				val.Write(zDO.GetString("enoq.tg.v1.name", ""));
				val.Write(Catalog.PhaseOf(zDO.GetPrefab()));
				val.Write(Training.Xp(guardian));
				registered.InvokeRoutedRPC(Server, "TG_CaptureReady_v3", new object[1] { val });
			}
		}

		private static void Prepared(long sender, ZPackage packet)
		{
			//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_0086: Unknown result type (might be due to invalid IL or missing references)
			if (!ZNet.instance.IsServer() || receipts == null)
			{
				return;
			}
			string nonce = packet.ReadString();
			ZDOID id = packet.ReadZDOID();
			string text = packet.ReadString();
			float num = packet.ReadSingle();
			string value = packet.ReadString();
			int phase = packet.ReadInt();
			int num2 = packet.ReadInt();
			CaptureProbe captureProbe = Probes.Values.FirstOrDefault((CaptureProbe p) => p.Nonce == nonce && p.Target == id && p.Authority == sender);
			if (captureProbe == null)
			{
				return;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(id);
			if (zDO == null || zDO.GetOwner() != sender)
			{
				return;
			}
			Probes.Remove(captureProbe.Owner + ":" + nonce);
			if (text != "stored")
			{
				switch (text)
				{
				case "combat":
				case "gone":
				case "denied":
					CaptureResult(captureProbe.Sender, captureProbe.Owner, nonce, captureProbe.Species, text);
					break;
				}
			}
			else if (!Rules.Finite(num) || num <= 0f || num > 1f || !DuoRules.ValidPhase(captureProbe.Species, phase) || num2 < 0 || num2 > 1000000)
			{
				CancelCapture(zDO, nonce);
			}
			else if (!CanUse(zDO.GetLong("enoq.tg.v1.owner", 0L), captureProbe.Owner))
			{
				CancelCapture(zDO, nonce);
				CaptureResult(captureProbe.Sender, captureProbe.Owner, nonce, captureProbe.Species, "denied");
			}
			else
			{
				zDO.Set("enoq.tg.v1.capture", nonce);
				BottleState bottleState = new BottleState(Guid.NewGuid().ToString("N"), captureProbe.Species, Rules.CleanName(value), zDO.GetLong("enoq.tg.v1.owner", 0L), world, num, DateTime.UtcNow.Ticks, ((ZDOID)(ref id)).UserID, ((ZDOID)(ref id)).ID, Rules.CleanName(zDO.GetString("enoq.tg.v1.ownerName", "")), captureProbe.Owner, 4, phase, num2);
				CaptureResult(captureProbe.Sender, captureProbe.Owner, nonce, captureProbe.Species, "stored:" + bottleState.Encode(), zDO);
			}
		}

		private static void CaptureResult(long sender, long owner, string nonce, string species, string code, ZDO captured = null)
		{
			Commits.Add(new Commit
			{
				Sender = sender,
				Owner = owner,
				Nonce = nonce,
				Outcome = code,
				Captured = captured,
				Write = receipts.PutAsync(owner, nonce, "Capture_" + species, code)
			});
		}

		private static void ExpireProbes()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			KeyValuePair<string, CaptureProbe>[] array = Probes.Where((KeyValuePair<string, CaptureProbe> p) => Time.unscaledTime - p.Value.SentAt >= 15f).ToArray();
			for (int num = 0; num < array.Length; num++)
			{
				KeyValuePair<string, CaptureProbe> keyValuePair = array[num];
				Probes.Remove(keyValuePair.Key);
				CancelCapture(ZDOMan.instance.GetZDO(keyValuePair.Value.Target), keyValuePair.Value.Nonce);
			}
		}

		internal static void RecoverGuardian(Guardian guardian)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (Server != 0L && registered != null)
			{
				registered.InvokeRoutedRPC(Server, "TG_RecoverCapture_v1", new object[2]
				{
					guardian.View.GetZDO().m_uid,
					guardian.View.GetZDO().GetString("enoq.tg.v1.capture", "")
				});
			}
		}

		private static void Recover(long sender, ZDOID id, string nonce)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			if (!ZNet.instance.IsServer() || receipts == null)
			{
				return;
			}
			ZDO zdo = ZDOMan.instance.GetZDO(id);
			if (zdo == null || zdo.GetOwner() != sender)
			{
				return;
			}
			if (CapturedSources.ContainsKey(Source(id)))
			{
				DestroyStored(zdo);
			}
			else
			{
				if (Commits.Any((Commit c) => c.Captured == zdo))
				{
					return;
				}
				CaptureProbe captureProbe = Probes.Values.FirstOrDefault((CaptureProbe p) => p.Target == id);
				if (captureProbe != null)
				{
					if (Time.unscaledTime - captureProbe.SentAt < 15f)
					{
						return;
					}
					Probes.Remove(captureProbe.Owner + ":" + captureProbe.Nonce);
				}
				CancelCapture(zdo, nonce);
			}
		}

		internal static void ClearGuardianIndex()
		{
			if (indexedWorld != null)
			{
				ZDOMan obj = indexedWorld;
				obj.m_onZDODestroyed = (Action<ZDO>)Delegate.Remove(obj.m_onZDODestroyed, new Action<ZDO>(ForgetGuardian));
			}
			indexedWorld = null;
			MapIndex.Clear();
			mapGuardians.Clear();
		}

		private static void StartGuardianIndex()
		{
			ClearGuardianIndex();
			if (!ZNet.instance.IsServer())
			{
				return;
			}
			indexedWorld = ZDOMan.instance;
			ZDOMan obj = indexedWorld;
			obj.m_onZDODestroyed = (Action<ZDO>)Delegate.Combine(obj.m_onZDODestroyed, new Action<ZDO>(ForgetGuardian));
			foreach (ZDO value in Objects.Invoke(indexedWorld).Values)
			{
				TrackGuardian(value);
			}
		}

		internal static void TrackGuardian(ZDO data)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (indexedWorld != null && indexedWorld == ZDOMan.instance && data != null && data.GetLong("enoq.tg.v1.owner", 0L) != 0L && !data.GetBool("enoq.tg.v1.stored", false))
			{
				MapIndex.Track(data.m_uid);
			}
		}

		private static void ForgetGuardian(ZDO data)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			RememberRemovedGuardian(data);
			MapIndex.Remove(data.m_uid);
		}

		private static void RegisterNotices(ZRoutedRpc rpc)
		{
			rpc.Register<ZPackage>("TG_NoticeReport_v2", (Action<long, ZPackage>)ReceiveGuardianNotice);
			rpc.Register<ZPackage>("TG_Notice_v2", (Action<long, ZPackage>)ShowGuardianNotice);
			rpc.Register<long, string>("TG_NoticeReportAck_v1", (Action<long, long, string>)GuardianReportAck);
			rpc.Register<long, string>("TG_NoticeDeliveryAck_v1", (Action<long, long, string>)GuardianDeliveryAck);
		}

		internal static void ResetNotices()
		{
			reportedNotices.Clear();
			shownNotices.Clear();
			noticeReports.Clear();
			noticeDeliveries.Clear();
			noticeReceipts.Clear();
			recentNoticeAuthorities.Clear();
			removedGuardians.Clear();
			nextNoticePrune = 0f;
		}

		internal static void ReportGuardianNotice(Guardian guardian, GuardianNoticeKind kind)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			if (!SessionReady || Server == 0L || !Object.op_Implicit((Object)(object)guardian) || !guardian.Valid || !guardian.View.IsOwner() || guardian.Capturing)
			{
				return;
			}
			ZDO zDO = guardian.View.GetZDO();
			NoticeReport noticeReport = new NoticeReport
			{
				Id = zDO.m_uid,
				Token = Guid.NewGuid().ToString("N"),
				Kind = kind,
				Rank = Training.Rank(guardian),
				Name = Rules.CleanName(zDO.GetString("enoq.tg.v1.name", ""))
			};
			if (!noticeReports.Enqueue(noticeReport.Token, Server, noticeReport, Time.unscaledTime))
			{
				Plugin.Warn("Guardian notice queue full; presentation skipped.");
				return;
			}
			if (!ZNet.instance.IsServer())
			{
				ZDOMan.instance.ForceSendZDO(Server, zDO.m_uid);
			}
			TickGuardianNotices();
		}

		private static void ReceiveGuardianNotice(long sender, ZPackage packet)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			if (!SessionReady || !ZNet.instance.IsServer() || packet.ReadLong() != world)
			{
				return;
			}
			if (sender != ZNet.GetUID())
			{
				ZNetPeer peer = ZNet.instance.GetPeer(sender);
				if (peer == null || !peer.IsReady())
				{
					return;
				}
			}
			string text = packet.ReadString();
			if (!Guid.TryParseExact(text, "N", out var _))
			{
				return;
			}
			string key = NoticeKey(sender, text);
			if (noticeReceipts.TryGet(key, Time.unscaledTime, out var value))
			{
				registered.InvokeRoutedRPC(sender, "TG_NoticeReportAck_v1", new object[2] { world, text });
				return;
			}
			ZDOID val = packet.ReadZDOID();
			GuardianNoticeKind guardianNoticeKind = (GuardianNoticeKind)packet.ReadInt();
			int rank = packet.ReadInt();
			string text2 = packet.ReadString();
			ZDO zDO = ZDOMan.instance.GetZDO(val);
			Species species = ((zDO == null) ? null : Catalog.FromPrefab(zDO.GetPrefab()));
			long num = ((zDO != null) ? zDO.GetLong("enoq.tg.v1.owner", 0L) : 0);
			long num2 = ((zDO != null) ? zDO.GetOwner() : 0);
			string text3 = Source(val);
			if (zDO == null && guardianNoticeKind == GuardianNoticeKind.Death && removedGuardians.TryGet(text3, Time.unscaledTime, out var value2))
			{
				species = value2.Species;
				num = value2.Owner;
				num2 = value2.Authority;
			}
			if (species == null || num == 0L || !GuardianNoticeRules.AuthorityAllowed(num2, sender, num2 != sender && recentNoticeAuthorities.TryGet(NoticeKey(sender, text3), Time.unscaledTime, out value)) || (zDO != null && (zDO.GetBool("enoq.tg.v1.stored", false) || zDO.GetString("enoq.tg.v1.capture", "").Length > 0)) || text2.Length > 128 || !GuardianNoticeRules.Valid(guardianNoticeKind, rank, Training.HasStars(species), species.Id == "GoblinBruteBros"))
			{
				return;
			}
			if (reportedNotices.CanAccept(text3, guardianNoticeKind, rank))
			{
				if (!QueueGuardianNotice(new NoticeReport
				{
					Id = val,
					Token = text,
					Kind = guardianNoticeKind,
					Rank = rank,
					Name = Rules.CleanName(text2)
				}, num, species))
				{
					return;
				}
				reportedNotices.Accept(text3, guardianNoticeKind, rank);
			}
			noticeReceipts.Put(key, value: true, Time.unscaledTime, 20.0);
			registered.InvokeRoutedRPC(sender, "TG_NoticeReportAck_v1", new object[2] { world, text });
		}

		private static void ShowGuardianNotice(long sender, ZPackage packet)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			if (!FromServer(sender) || packet.ReadLong() != world)
			{
				return;
			}
			string text = packet.ReadString();
			if (!Guid.TryParseExact(text, "N", out var _))
			{
				return;
			}
			ZDOID id = packet.ReadZDOID();
			long num = packet.ReadLong();
			Species species = Catalog.Find(packet.ReadString());
			string text2 = packet.ReadString();
			GuardianNoticeKind guardianNoticeKind = (GuardianNoticeKind)packet.ReadInt();
			int rank = packet.ReadInt();
			if (species == null || text2.Length > 128 || !GuardianNoticeRules.Valid(guardianNoticeKind, rank, Training.HasStars(species), species.Id == "GoblinBruteBros"))
			{
				return;
			}
			string id2 = Source(id);
			if (shownNotices.CanAccept(id2, guardianNoticeKind, rank))
			{
				if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || !Object.op_Implicit((Object)(object)MessageHud.instance) || (!AlliesReady && num != Player.m_localPlayer.GetPlayerID()))
				{
					return;
				}
				if (CanUse(num, Player.m_localPlayer.GetPlayerID()))
				{
					GuardianNotices.Show(species, text2, guardianNoticeKind, rank);
				}
				if (guardianNoticeKind == GuardianNoticeKind.Promotion)
				{
					GuardianNotices.PlayPromotion(id);
				}
				shownNotices.Accept(id2, guardianNoticeKind, rank);
			}
			registered.InvokeRoutedRPC(Server, "TG_NoticeDeliveryAck_v1", new object[2] { world, text });
		}

		private static string NoticeKey(long peer, string token)
		{
			return peer.ToString(CultureInfo.InvariantCulture) + "/" + token;
		}

		internal static void RememberNoticeAuthority(ZDO data, long next)
		{
			//IL_0019: 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)
			if (SessionReady && ZNet.instance.IsServer() && MapIndex.Contains(data.m_uid))
			{
				long owner = data.GetOwner();
				if (owner != 0L && owner != next)
				{
					recentNoticeAuthorities.Put(NoticeKey(owner, Source(data.m_uid)), value: true, Time.unscaledTime, 10.0);
				}
			}
		}

		private static void RememberRemovedGuardian(ZDO data)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (!SessionReady || !ZNet.instance.IsServer())
			{
				return;
			}
			string key = Source(data.m_uid);
			if (data.GetBool("enoq.tg.v1.stored", false) || data.GetString("enoq.tg.v1.capture", "").Length > 0)
			{
				removedGuardians.Remove(key);
				return;
			}
			long num = data.GetLong("enoq.tg.v1.owner", 0L);
			Species species = Catalog.FromPrefab(data.GetPrefab());
			if (num != 0L && species != null)
			{
				removedGuardians.Put(key, new RemovedGuardian
				{
					Owner = num,
					Authority = data.GetOwner(),
					Species = species
				}, Time.unscaledTime, 10.0);
			}
		}

		private static void TickGuardianNotices()
		{
			if (!SessionReady)
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			noticeReports.Tick(unscaledTime, (long peer, NoticeReport report) => peer == Server, SendGuardianReport);
			if (ZNet.instance.IsServer())
			{
				noticeDeliveries.Tick(unscaledTime, NoticeRecipientConnected, SendGuardianDelivery);
				if (!(unscaledTime < nextNoticePrune))
				{
					nextNoticePrune = unscaledTime + 1f;
					noticeReceipts.Prune(unscaledTime);
					recentNoticeAuthorities.Prune(unscaledTime);
					removedGuardians.Prune(unscaledTime);
				}
			}
		}

		private static void SendGuardianReport(long peer, NoticeReport report)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(world);
			val.Write(report.Token);
			val.Write(report.Id);
			val.Write((int)report.Kind);
			val.Write(report.Rank);
			val.Write(report.Name);
			registered.InvokeRoutedRPC(peer, "TG_NoticeReport_v2", new object[1] { val });
		}

		private static bool QueueGuardianNotice(NoticeReport report, long owner, Species species)
		{
			bool flag = !ZNet.instance.IsDedicated();
			int num = (flag ? 1 : 0);
			List<ZNetPeer> peers = ZNet.instance.GetPeers();
			foreach (ZNetPeer item in peers)
			{
				if (item.IsReady())
				{
					num++;
				}
			}
			if (noticeDeliveries.Count + num > 4096)
			{
				return false;
			}
			NoticeMessage noticeMessage = new NoticeMessage
			{
				Report = report,
				Owner = owner,
				Species = species.Id,
				Token = Guid.NewGuid().ToString("N")
			};
			if (flag)
			{
				noticeDeliveries.Enqueue(NoticeKey(ZNet.GetUID(), noticeMessage.Token), ZNet.GetUID(), new NoticeDelivery
				{
					Message = noticeMessage
				}, Time.unscaledTime);
			}
			foreach (ZNetPeer item2 in peers)
			{
				if (item2.IsReady())
				{
					noticeDeliveries.Enqueue(NoticeKey(item2.m_uid, noticeMessage.Token), item2.m_uid, new NoticeDelivery
					{
						Message = noticeMessage,
						Connection = item2
					}, Time.unscaledTime);
				}
			}
			return true;
		}

		private static bool NoticeRecipientConnected(long peer, NoticeDelivery delivery)
		{
			if (peer != ZNet.GetUID())
			{
				if (ZNet.instance.GetPeer(peer) == delivery.Connection && delivery.Connection != null)
				{
					return delivery.Connection.IsReady();
				}
				return false;
			}
			return !ZNet.instance.IsDedicated();
		}

		private static void SendGuardianDelivery(long peer, NoticeDelivery delivery)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			NoticeMessage message = delivery.Message;
			NoticeReport report = message.Report;
			ZPackage val = new ZPackage();
			val.Write(world);
			val.Write(message.Token);
			val.Write(report.Id);
			val.Write(message.Owner);
			val.Write(message.Species);
			val.Write(report.Name);
			val.Write((int)report.Kind);
			val.Write(report.Rank);
			registered.InvokeRoutedRPC(peer, "TG_Notice_v2", new object[1] { val });
		}

		private static void GuardianReportAck(long sender, long worldId, string token)
		{
			if (FromServer(sender) && worldId == world && Guid.TryParseExact(token, "N", out var _))
			{
				noticeReports.Acknowledge(token, sender);
			}
		}

		private static void GuardianDeliveryAck(long sender, long worldId, string token)
		{
			if (SessionReady && ZNet.instance.IsServer() && worldId == world && Guid.TryParseExact(token, "N", out var _))
			{
				noticeDeliveries.Acknowledge(NoticeKey(sender, token), sender);
			}
		}

		internal static bool FromServer(long sender)
		{
			if (SessionReady)
			{
				return sender == Server;
			}
			return false;
		}

		internal static void Tick()
		{
			ZNet instance = ZNet.instance;
			long? worldId = ((!Object.op_Implicit((Object)(object)instance)) ? ((long?)null) : instance.GetWorld()?.m_uid);
			bool connected = Object.op_Implicit((Object)(object)instance) && ZDOMan.instance != null && (instance.IsServer() || instance.GetServerPeer() != null);
			if (!Session.Start(ZRoutedRpc.instance, worldId, connected, RegisterHandlers, EnterWorld))
			{
				ClearGuardianIndex();
				ResetNotices();
				return;
			}
			registered = ZRoutedRpc.instance;
			CompleteWrites();
			ExpireProbes();
			TickSharing();
			TickTraining();
			TickGuardianNotices();
		}

		private static void RegisterHandlers(ZRoutedRpc rpc)
		{
			rpc.Register<string, string, Vector3, string>("TG_Summon_v2", (Method<string, string, Vector3, string>)Spawn);
			rpc.Register<string, string>("TG_Reply_v1", (Action<long, string, string>)Summoning.Reply);
			rpc.Register<ZDOID, int, string>("TG_Order_v1", (Action<long, ZDOID, int, string>)Command);
			RegisterCaptures(rpc);
			RegisterSharing(rpc);
			RegisterTraining(rpc);
			RegisterNotices(rpc);
		}

		private static void EnterWorld(long worldId)
		{
			world = worldId;
			receipts = null;
			Commits.Clear();
			Guardian.KnownIds.Clear();
			Probes.Clear();
			CapturedSources.Clear();
			ResetSharing();
			ResetTraining();
			ResetNotices();
			StartGuardianIndex();
			if (ZNet.instance.IsServer())
			{
				try
				{
					receipts = new Receipts(Path.Combine(Paths.ConfigPath, "TrophyGuard", "summons-" + world + ".txt"));
					RestoreCaptures();
				}
				catch (Exception ex)
				{
					Plugin.Warn("Summoning disabled: cannot read journal. Preserve the file and repair it: " + ex);
				}
			}
			Plugin.Info("Guardian network ready (" + (ZNet.instance.IsServer() ? "server" : "client") + ").");
		}

		private static void CompleteWrites()
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			for (int num = Commits.Count - 1; num >= 0; num--)
			{
				Commit commit = Commits[num];
				if (commit.Write.IsCompleted)
				{
					Commits.RemoveAt(num);
					bool flag = false;
					try
					{
						commit.Write.GetAwaiter().GetResult();
						flag = true;
						if (commit.Captured != null)
						{
							BottleState value = BottleState.Decode(commit.Outcome.Substring(7));
							CapturedSources[Source(commit.Captured.m_uid)] = value;
							DestroyStored(commit.Captured);
						}
						if (commit.Created != null)
						{
							ZDOMan.instance.ForceSendZDO(commit.Sender, commit.Created.m_uid);
						}
						Answer(commit.Sender, commit.Nonce, commit.Outcome);
					}
					catch (Exception ex)
					{
						bool flag2 = !string.IsNullOrEmpty(commit.BottleToken) && receipts.ReleaseResult(commit.BottleToken, commit.Owner, commit.Nonce) == "ok";
						if (!flag && !flag2 && commit.Created != null && ZDOMan.instance.GetZDO(commit.Created.m_uid) != null)
						{
							ZDOMan.instance.DestroyZDO(commit.Created);
						}
						if (!flag && commit.Captured != null)
						{
							CancelCapture(commit.Captured, commit.Nonce);
						}
						Plugin.Warn("Server summon journal write failed; request retained: " + ex);
						Answer(commit.Sender, commit.Nonce, "busy");
					}
				}
			}
		}

		private static void BeginCommit(long sender, long owner, string nonce, string species, string outcome, ZDO created = null, string token = "")
		{
			Commits.Add(new Commit
			{
				Sender = sender,
				Owner = owner,
				Nonce = nonce,
				Outcome = outcome,
				Created = created,
				BottleToken = token,
				Write = ((outcome == "ok") ? receipts.PutSpawnAsync(owner, nonce, species, token) : receipts.PutAsync(owner, nonce, species, outcome))
			});
		}

		private static bool Caller(long sender, out long owner, out ZDO character, out string name)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			owner = 0L;
			character = null;
			name = "";
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer())
			{
				return false;
			}
			if (sender == ZNet.GetUID() && Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				owner = Player.m_localPlayer.GetPlayerID();
				name = Player.m_localPlayer.GetPlayerName();
				character = ZDOMan.instance.GetZDO(((Character)Player.m_localPlayer).GetZDOID());
			}
			else
			{
				ZNetPeer peer = ZNet.instance.GetPeer(sender);
				if (peer == null || !peer.IsReady())
				{
					return false;
				}
				name = peer.m_playerName;
				character = ZDOMan.instance.GetZDO(peer.m_characterID);
				if (character == null || !Object.op_Implicit((Object)(object)Game.instance) || !Object.op_Implicit((Object)(object)Game.instance.m_playerPrefab) || character.GetPrefab() != StringExtensionMethods.GetStableHashCode(((Object)Game.instance.m_playerPrefab).name))
				{
					return false;
				}
				owner = PlayerIdentity.Resolve(sender, character.GetOwner(), character.GetLong(ZDOVars.s_playerID, 0L));
			}
			if (owner != 0L && character != null)
			{
				return character.GetLong(ZDOVars.s_playerID, 0L) == owner;
			}
			return false;
		}

		private static void Answer(long sender, string nonce, string code)
		{
			registered.InvokeRoutedRPC(sender, "TG_Reply_v1", new object[2] { nonce, code });
		}

		private static void Spawn(long sender, string nonce, string speciesId, Vector3 position, string payload)
		{
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04af: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ca: Unknown result type (might be due to invalid IL or missing references)
			if (!ZNet.instance.IsServer() || nonce == null || !Guid.TryParseExact(nonce, "N", out var _))
			{
				return;
			}
			Species species = Catalog.Find(speciesId);
			if (species == null || !Object.op_Implicit((Object)(object)species.Creature) || !Caller(sender, out var owner, out var character, out var name))
			{
				return;
			}
			if (receipts == null)
			{
				Answer(sender, nonce, "busy");
				return;
			}
			if (Commits.Any((Commit c) => c.Owner == owner && c.Nonce == nonce))
			{
				Answer(sender, nonce, "busy");
				return;
			}
			string text = receipts.Get(owner, nonce, speciesId);
			if (text != null)
			{
				Answer(sender, nonce, text);
				return;
			}
			BottleState resting = null;
			if (!string.IsNullOrEmpty(payload))
			{
				try
				{
					BottleState bottleState = BottleState.Decode(payload);
					resting = receipts.Bottle(bottleState.Token);
					if (resting == null || resting.Encode() != payload || resting.World != world || resting.Species != speciesId)
					{
						BeginCommit(sender, owner, nonce, speciesId, "denied");
						return;
					}
				}
				catch (InvalidDataException)
				{
					BeginCommit(sender, owner, nonce, speciesId, "denied");
					return;
				}
				string text2 = receipts.ReleaseResult(resting.Token, owner, nonce);
				if (text2 == "used")
				{
					BeginCommit(sender, owner, nonce, speciesId, "used");
					return;
				}
				if (Commits.Any((Commit c) => c.BottleToken == resting.Token))
				{
					Answer(sender, nonce, "busy");
					return;
				}
				if (text2 != null)
				{
					BeginCommit(sender, owner, nonce, speciesId, "ok", null, resting.Token);
					return;
				}
				if (!CanUse(resting.Owner, owner))
				{
					BeginCommit(sender, owner, nonce, speciesId, "denied");
					return;
				}
			}
			ZDO val = null;
			try
			{
				long originalOwner = resting?.Owner ?? owner;
				string text3 = SummonRules.ExistingOutcome(from z in Objects.Invoke(ZDOMan.instance).Values
					where z.GetLong("enoq.tg.v1.owner", 0L) == originalOwner
					select new GuardianRecord
					{
						Owner = z.GetLong("enoq.tg.v1.owner", 0L),
						Requester = z.GetLong("enoq.tg.v1.requester", z.GetLong("enoq.tg.v1.owner", 0L)),
						Request = z.GetString("enoq.tg.v1.request", ""),
						Alive = (!z.GetBool("enoq.tg.v1.stored", false) && z.GetFloat(ZDOVars.s_health, 1f) > 0f)
					}, validPosition: Rules.Finite(position.x) && Rules.Finite(position.y) && Rules.Finite(positio