Decompiled source of PotentialDraught v1.3.9

PotentialDraught.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Splatform;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Potential Draught")]
[assembly: AssemblyDescription("A server-synchronized Forge of Potential potion for Valheim.")]
[assembly: AssemblyCompany("Potential Draught contributors")]
[assembly: AssemblyProduct("Potential Draught")]
[assembly: AssemblyCopyright("Copyright © 2026 Potential Draught contributors")]
[assembly: AssemblyFileVersion("1.3.9.0")]
[assembly: AssemblyVersion("1.3.9.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 PotentialDraught
{
	[BepInPlugin("com.forgepotential.potentialdraught", "Potential Draught", "1.3.9")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class PotentialDraughtPlugin : BaseUnityPlugin
	{
		private enum FallbackParticleKind
		{
			None,
			Shield,
			Fist
		}

		private sealed class ArmorQualityState
		{
			internal int ChestHash;

			internal int ChestQuality;

			internal int LegHash;

			internal int LegQuality;

			internal int HelmetHash;

			internal int HelmetQuality;

			internal int ShoulderHash;

			internal int ShoulderQuality;

			internal int UtilityHash;

			internal int UtilityQuality;
		}

		private sealed class PurgeAdminPotionsCommand : ConsoleCommand
		{
			public override string Name => "purgeadminpotions";

			public override string Help => "purgeadminpotions - removes all admin potions from every other currently connected player";

			public override bool IsCheat => true;

			public override void Run(string[] args)
			{
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Expected O, but got Unknown
				if (args != null && args.Length != 0)
				{
					Console instance = Console.instance;
					if (instance != null)
					{
						instance.Print("Usage: " + ((ConsoleCommand)this).Help + ".");
					}
					return;
				}
				if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null || (Object)(object)Player.m_localPlayer == (Object)null)
				{
					Console instance2 = Console.instance;
					if (instance2 != null)
					{
						instance2.Print("The purge command is only available while playing in a world.");
					}
					return;
				}
				RegisterAdminPotionRpcs();
				ZPackage val = new ZPackage();
				val.Write((byte)7);
				val.Write(Player.m_localPlayer.GetPlayerID());
				SendAdminPotionRequestToServer(val);
				Console instance3 = Console.instance;
				if (instance3 != null)
				{
					instance3.Print("Requesting removal of all admin potions from other players and world storage...");
				}
			}
		}

		private abstract class SetAdminPotionPermissionCommand : ConsoleCommand
		{
			protected abstract bool Allowed { get; }

			public override bool IsCheat => true;

			public override List<string> CommandOptionList()
			{
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				List<string> list = new List<string>();
				if ((Object)(object)ZNet.instance == (Object)null)
				{
					return list;
				}
				foreach (PlayerInfo player in ZNet.instance.GetPlayerList())
				{
					string text = player.m_name?.Trim();
					if (!string.IsNullOrEmpty(text) && !list.Contains(text))
					{
						list.Add(text);
					}
				}
				list.Sort(StringComparer.OrdinalIgnoreCase);
				return list;
			}

			public override void Run(string[] args)
			{
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_008f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Expected O, but got Unknown
				if (args == null || args.Length == 0)
				{
					Console instance = Console.instance;
					if (instance != null)
					{
						instance.Print("Usage: " + ((ConsoleCommand)this).Help + ".");
					}
					return;
				}
				if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null || (Object)(object)Player.m_localPlayer == (Object)null)
				{
					Console instance2 = Console.instance;
					if (instance2 != null)
					{
						instance2.Print("This command is only available while playing in a world.");
					}
					return;
				}
				string text = string.Join(" ", args).Trim();
				ZPackage val = new ZPackage();
				val.Write((byte)2);
				val.Write(Player.m_localPlayer.GetPlayerID());
				val.Write(text);
				val.Write(Allowed);
				SendAdminPotionRequestToServer(val);
				Console instance3 = Console.instance;
				if (instance3 != null)
				{
					instance3.Print("Requesting server permission change for '" + text + "'...");
				}
			}
		}

		private sealed class AllowAdminPotionCommand : SetAdminPotionPermissionCommand
		{
			public override string Name => "allowadminpotion";

			public override string Help => "allowadminpotion <player name> - permits a connected player to use admin potions";

			protected override bool Allowed => true;
		}

		private sealed class DisableAdminPotionCommand : SetAdminPotionPermissionCommand
		{
			public override string Name => "disableadminpotion";

			public override string Help => "disableadminpotion <player name> - revokes a connected player's admin-potion permission";

			protected override bool Allowed => false;
		}

		private sealed class MaximumItemQualityCommand : ConsoleCommand
		{
			public override string Name => "maximumitemquality";

			public override string Help => "maximumitemquality <quality> - changes the server's normal Forge upgrade cap";

			public override bool IsCheat => true;

			public override void Run(string[] args)
			{
				//IL_0079: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0085: Unknown result type (might be due to invalid IL or missing references)
				//IL_0095: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a1: Expected O, but got Unknown
				if (args == null || args.Length != 1 || !int.TryParse(args[0], out var result) || result < 1)
				{
					Console instance = Console.instance;
					if (instance != null)
					{
						instance.Print($"Usage: {((ConsoleCommand)this).Help}. Current cap: {MaximumItemQuality}.");
					}
					return;
				}
				if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null || (Object)(object)Player.m_localPlayer == (Object)null)
				{
					Console instance2 = Console.instance;
					if (instance2 != null)
					{
						instance2.Print("This command is only available while playing in a world.");
					}
					return;
				}
				ZPackage val = new ZPackage();
				val.Write((byte)5);
				val.Write(Player.m_localPlayer.GetPlayerID());
				val.Write(result);
				SendAdminPotionRequestToServer(val);
				Console instance3 = Console.instance;
				if (instance3 != null)
				{
					instance3.Print($"Requesting maximum item quality {result} from the server...");
				}
			}
		}

		private sealed class PotentialLevelsCommand : ConsoleCommand
		{
			public override string Name => "potentiallevels";

			public override string Help => "potentiallevels <levels> - sets the number of levels added by your next admin-potion Forge upgrade";

			public override bool IsCheat => true;

			public override void Run(string[] args)
			{
				if (args == null || args.Length != 1 || !int.TryParse(args[0], out var result) || result < 1)
				{
					Console instance = Console.instance;
					if (instance != null)
					{
						instance.Print($"Usage: {((ConsoleCommand)this).Help}. Current value: {PendingAdminUpgradeLevels}.");
					}
					return;
				}
				PendingAdminUpgradeLevels = result;
				AdminLevelOverrideArmed = true;
				Console instance2 = Console.instance;
				if (instance2 != null)
				{
					instance2.Print("The next Forge of Potential upgrade made while Absolute Potential is active will add " + string.Format("{0} level{1}. The setting resets to 1 after that click.", result, (result == 1) ? string.Empty : "s"));
				}
			}
		}

		[HarmonyPatch(typeof(Player), "OnSpawned")]
		private static class AdminPotionPermissionSyncPatch
		{
			private static void Postfix(Player __instance)
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Expected O, but got Unknown
				if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && ZRoutedRpc.instance != null)
				{
					_localAdminPotionUseAllowed = false;
					ZPackage val = new ZPackage();
					val.Write((byte)1);
					val.Write(__instance.GetPlayerID());
					SendAdminPotionRequestToServer(val);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "ConsumeItem")]
		private static class AdminPotionConsumptionPatch
		{
			private static bool Prefix(Player __instance, ItemData item, ref bool __result)
			{
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Expected O, but got Unknown
				if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !IsAdminPotionItem(item) || _localAdminPotionUseAllowed)
				{
					return true;
				}
				((Character)__instance).Message((MessageType)2, "You are not authorized to use admin potions.", 0, (Sprite)null, false);
				__result = false;
				if (ZRoutedRpc.instance != null)
				{
					ZPackage val = new ZPackage();
					val.Write((byte)1);
					val.Write(__instance.GetPlayerID());
					SendAdminPotionRequestToServer(val);
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		private static class ForgeCraftingPatch
		{
			private struct PatchState
			{
				internal SharedData SharedData;

				internal float OriginalChance;

				internal float OriginalBreakChance;

				internal ItemData UpgradeItem;

				internal int OriginalQuality;

				internal bool Changed;

				internal bool QualityChanged;

				internal bool ConsumeAdminLevels;
			}

			private static bool Prefix(Player player, Recipe ___m_craftRecipe, ItemData ___m_craftUpgradeItem, ref PatchState __state)
			{
				bool flag = HasAdminPotionEffect(player);
				if (___m_craftRecipe?.m_resources == null)
				{
					return true;
				}
				Requirement[] resources = ___m_craftRecipe.m_resources;
				foreach (Requirement val in resources)
				{
					if (val == null || !val.m_upgraderResource || (Object)(object)val.m_resItem == (Object)null)
					{
						continue;
					}
					SharedData val2 = val.m_resItem.m_itemData?.m_shared;
					if (val2 == null)
					{
						continue;
					}
					bool flag2 = flag && AdminLevelOverrideArmed;
					int num = ((!flag2) ? 1 : PendingAdminUpgradeLevels);
					long num2 = ((___m_craftUpgradeItem == null) ? 1 : ((long)___m_craftUpgradeItem.m_quality + (long)num));
					int maximumItemQuality = MaximumItemQuality;
					if (___m_craftUpgradeItem != null && num2 > maximumItemQuality && !flag2)
					{
						if (player != null)
						{
							((Character)player).Message((MessageType)2, $"The Forge of Potential is capped at level {maximumItemQuality}. " + "Use potentiallevels with the admin potion to override it.", 0, (Sprite)null, false);
						}
						return false;
					}
					if (!flag && !HasPotionEffect(player))
					{
						return true;
					}
					__state.SharedData = val2;
					__state.OriginalChance = val2.m_upgradeChance;
					__state.OriginalBreakChance = val2.m_breakChance;
					__state.Changed = true;
					val2.m_upgradeChance = (flag ? 1f : 0.75f);
					val2.m_breakChance = (flag ? 0f : 0.1f);
					if (flag && ___m_craftUpgradeItem != null)
					{
						int num3 = ((!flag2) ? 1 : PendingAdminUpgradeLevels);
						__state.ConsumeAdminLevels = flag2;
						if (num3 > 1)
						{
							__state.UpgradeItem = ___m_craftUpgradeItem;
							__state.OriginalQuality = ___m_craftUpgradeItem.m_quality;
							__state.QualityChanged = true;
							long num4 = (long)___m_craftUpgradeItem.m_quality + (long)num3 - 1;
							___m_craftUpgradeItem.m_quality = (int)((num4 > int.MaxValue) ? int.MaxValue : num4);
						}
					}
					((BaseUnityPlugin)Instance).Logger.LogDebug((object)($"Potential Draught active: this attempt uses {val2.m_upgradeChance:P0} success, " + $"{val2.m_breakChance:P0} break" + (flag ? $", adding {PendingAdminUpgradeLevels} level(s)." : ".")));
					return true;
				}
				return true;
			}

			private static void Postfix(PatchState __state)
			{
				Restore(__state);
			}

			private static Exception Finalizer(Exception __exception, PatchState __state)
			{
				Restore(__state);
				return __exception;
			}

			private static void Restore(PatchState state)
			{
				if (state.Changed && state.SharedData != null)
				{
					state.SharedData.m_upgradeChance = state.OriginalChance;
					state.SharedData.m_breakChance = state.OriginalBreakChance;
				}
				if (state.QualityChanged && state.UpgradeItem != null)
				{
					state.UpgradeItem.m_quality = state.OriginalQuality;
				}
				if (state.ConsumeAdminLevels)
				{
					PendingAdminUpgradeLevels = 1;
					AdminLevelOverrideArmed = false;
				}
			}
		}

		[HarmonyPatch(typeof(ParticleIntensityScaler), "EvaluateIntensityColor")]
		private static class PotentialGlowColorPatch
		{
			private static void Postfix(int ___lastItemDropLevel, ref Color __result)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				if (___lastItemDropLevel >= 5)
				{
					__result = GetPotentialGlowColor(___lastItemDropLevel);
				}
			}
		}

		[HarmonyPatch(typeof(VisEquipment), "AttachItem")]
		private static class EquippedItemGlowPatch
		{
			private static void Prefix(VisEquipment __instance, int itemHash, ref int quality)
			{
				quality = ResolveEquipmentQuality(__instance, itemHash, quality);
			}

			private static void Postfix(VisEquipment __instance, int itemHash, int quality, ref GameObject __result)
			{
				ApplyPotentialGlow(__result, quality, IsArmorVisual(__instance, itemHash), GetFallbackParticleKind(itemHash));
			}
		}

		[HarmonyPatch(typeof(VisEquipment), "AttachArmor")]
		private static class EquippedArmorGlowPatch
		{
			private static void Prefix(VisEquipment __instance, int itemHash, ref int quality)
			{
				quality = ResolveEquipmentQuality(__instance, itemHash, quality);
			}

			private static void Postfix(VisEquipment __instance, int itemHash, int quality, ref List<GameObject> __result)
			{
				if (__result == null || __result.Count <= 0)
				{
					return;
				}
				bool subtleArmorGlow = IsArmorPrefab(itemHash);
				foreach (GameObject item in __result)
				{
					ApplyPotentialGlow(item, quality, subtleArmorGlow, GetFallbackParticleKind(itemHash));
				}
			}
		}

		[HarmonyPatch(typeof(VisEquipment), "UpdateEquipmentVisuals")]
		private static class FinalHandVisualGlowPatch
		{
			private static void Postfix(VisEquipment __instance, GameObject ___m_leftItemInstance, GameObject ___m_rightItemInstance, int ___m_leftItem, int ___m_rightItem, int ___m_leftItemQuality, int ___m_rightItemQuality)
			{
				int quality = ResolveEquipmentQuality(__instance, ___m_leftItem, ___m_leftItemQuality);
				int quality2 = ResolveEquipmentQuality(__instance, ___m_rightItem, ___m_rightItemQuality);
				ApplyPotentialGlow(___m_leftItemInstance, quality, subtleArmorGlow: false, GetFallbackParticleKind(___m_leftItem));
				ApplyPotentialGlow(___m_rightItemInstance, quality2, subtleArmorGlow: false, GetFallbackParticleKind(___m_rightItem));
			}
		}

		[HarmonyPatch(typeof(VisEquipment), "CustomUpdate")]
		private static class FistHandGlowPatch
		{
			private static void Postfix(Transform ___m_leftHand, Transform ___m_rightHand, int ___m_leftItem, int ___m_rightItem, int ___m_leftItemQuality, int ___m_rightItemQuality)
			{
				bool equipped = IsFistWeaponPrefab(___m_leftItem) || IsFistWeaponPrefab(___m_rightItem);
				int quality = Mathf.Max(___m_leftItemQuality, ___m_rightItemQuality);
				UpdateFistHandFog(___m_leftHand, equipped, quality);
				UpdateFistHandFog(___m_rightHand, equipped, quality);
			}
		}

		[HarmonyPatch(typeof(ArmorStand), "SetVisualItem")]
		private static class ArmorStandStoredQualityPatch
		{
			private struct QualityState
			{
				internal ItemDrop PrefabDrop;

				internal int OriginalQuality;

				internal bool Changed;
			}

			private static void Prefix(int index, int itemHash, ZNetView ___m_nview, ref QualityState __state)
			{
				if (itemHash == 0 || (Object)(object)___m_nview == (Object)null || !___m_nview.IsValid())
				{
					return;
				}
				ObjectDB instance = ObjectDB.instance;
				GameObject obj = ((instance != null) ? instance.GetItemPrefab(itemHash) : null);
				ItemDrop val = ((obj != null) ? obj.GetComponent<ItemDrop>() : null);
				ZDO zDO = ___m_nview.GetZDO();
				if (!((Object)(object)val == (Object)null) && zDO != null)
				{
					ItemData val2 = val.m_itemData.Clone();
					ItemDrop.LoadFromZDO(val2, zDO, index);
					if (val2.m_quality > val.m_itemData.m_quality)
					{
						__state.PrefabDrop = val;
						__state.OriginalQuality = val.m_itemData.m_quality;
						__state.Changed = true;
						val.m_itemData.m_quality = val2.m_quality;
					}
				}
			}

			private static void Postfix(QualityState __state)
			{
				Restore(__state);
			}

			private static Exception Finalizer(Exception __exception, QualityState __state)
			{
				Restore(__state);
				return __exception;
			}

			private static void Restore(QualityState state)
			{
				if (state.Changed && (Object)(object)state.PrefabDrop != (Object)null)
				{
					state.PrefabDrop.m_itemData.m_quality = state.OriginalQuality;
				}
			}
		}

		[HarmonyPatch(typeof(ItemStand), "SetVisualItem")]
		private static class ItemStandGlowPatch
		{
			private static void Postfix(int itemHash, int quality, GameObject ___m_visualItem)
			{
				ApplyPotentialGlow(___m_visualItem, quality, IsArmorPrefab(itemHash), GetFallbackParticleKind(itemHash));
			}
		}

		[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
		private static class InventoryItemIconGlowPatch
		{
			private static void Postfix(Inventory ___m_inventory, List<InventoryElement> ___m_elements)
			{
				UpdateInventoryIconGlows(___m_inventory, ___m_elements);
			}
		}

		[HarmonyPatch(typeof(HotkeyBar), "UpdateIcons")]
		private static class HotkeyItemIconGlowPatch
		{
			private static void Postfix(HotkeyBar __instance)
			{
				UpdateHotkeyIconGlows(__instance);
			}
		}

		[HarmonyPatch(typeof(VisEquipment), "SetChestEquipped")]
		private static class ChestGlowCleanupPatch
		{
			private static void Postfix(VisEquipment __instance, int hash)
			{
				if (hash == 0)
				{
					RemoveBodyArmorGlow(__instance, "Chest");
				}
			}
		}

		[HarmonyPatch(typeof(VisEquipment), "SetLegEquipped")]
		private static class LegGlowCleanupPatch
		{
			private static void Postfix(VisEquipment __instance, int hash)
			{
				if (hash == 0)
				{
					RemoveBodyArmorGlow(__instance, "Legs");
				}
			}
		}

		[HarmonyPatch(typeof(VisEquipment), "SetShoulderEquipped")]
		private static class CapeGlowCleanupPatch
		{
			private static void Postfix(VisEquipment __instance, int hash)
			{
				if (hash == 0)
				{
					RemoveBodyArmorGlow(__instance, "Cape");
				}
			}
		}

		[HarmonyPatch(typeof(VisEquipment), "SetUtilityEquipped")]
		private static class UtilityGlowCleanupPatch
		{
			private static void Postfix(VisEquipment __instance, int hash)
			{
				if (hash == 0)
				{
					RemoveBodyArmorGlow(__instance, "Utility");
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "SetupVisEquipment")]
		private static class ArmorQualityTrackingPatch
		{
			private static void Postfix(VisEquipment __0, ItemData ___m_rightItem, ItemData ___m_leftItem, ItemData ___m_hiddenLeftItem, ItemData ___m_hiddenRightItem, ItemData ___m_chestItem, ItemData ___m_legItem, ItemData ___m_helmetItem, ItemData ___m_shoulderItem, ItemData ___m_utilityItem)
			{
				RecordArmorQualities(__0, ___m_chestItem, ___m_legItem, ___m_helmetItem, ___m_shoulderItem, ___m_utilityItem);
				RecordHandQualities(__0, ___m_rightItem, ___m_leftItem, ___m_hiddenLeftItem, ___m_hiddenRightItem);
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "Start")]
		private static class DroppedItemGlowPatch
		{
			private static void Postfix(ItemDrop __instance)
			{
				if (__instance?.m_itemData != null && !IsArmorItem(__instance.m_itemData))
				{
					int itemHash = GetItemHash(__instance.m_itemData);
					ApplyPotentialGlow(((Component)__instance).gameObject, __instance.m_itemData.m_quality, subtleArmorGlow: false, GetFallbackParticleKind(itemHash));
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")]
		private static class ForgeDurationPatch
		{
			private struct DurationState
			{
				internal float OriginalBaseDuration;

				internal float OriginalPerLevelDuration;

				internal bool Changed;
			}

			private static void Prefix(Player player, ref float ___m_upgraderDuration, ref float ___m_upgraderDurationPerLevel, ref DurationState __state)
			{
				CraftingStation val = ((player != null) ? player.GetCurrentCraftingStation() : null);
				bool flag = HasAdminPotionEffect(player);
				if ((flag || HasPotionEffect(player)) && !((Object)(object)val == (Object)null) && val.m_upgrader)
				{
					__state.OriginalBaseDuration = ___m_upgraderDuration;
					__state.OriginalPerLevelDuration = ___m_upgraderDurationPerLevel;
					__state.Changed = true;
					float num = (flag ? 0.01f : 0.5f);
					___m_upgraderDuration *= num;
					___m_upgraderDurationPerLevel *= num;
				}
			}

			private static void Postfix(ref float ___m_upgraderDuration, ref float ___m_upgraderDurationPerLevel, DurationState __state)
			{
				Restore(ref ___m_upgraderDuration, ref ___m_upgraderDurationPerLevel, __state);
			}

			private static Exception Finalizer(Exception __exception, ref float ___m_upgraderDuration, ref float ___m_upgraderDurationPerLevel, DurationState __state)
			{
				Restore(ref ___m_upgraderDuration, ref ___m_upgraderDurationPerLevel, __state);
				return __exception;
			}

			private static void Restore(ref float baseDuration, ref float perLevelDuration, DurationState state)
			{
				if (state.Changed)
				{
					baseDuration = state.OriginalBaseDuration;
					perLevelDuration = state.OriginalPerLevelDuration;
				}
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static CoroutineHandler <0>__AdminPotionPermissionServerReceive;

			public static CoroutineHandler <1>__AdminPotionPermissionClientReceive;

			public static Action<long, long> <2>__RPC_RequestAdminPotionPurge;

			public static Action<long, long> <3>__RPC_ExecuteAdminPotionPurge;

			public static Action<long, long> <4>__RPC_RequestAdminPotionPermission;

			public static Action<long, long, string, bool> <5>__RPC_SetAdminPotionPermission;

			public static Action<long, long, bool> <6>__RPC_SyncAdminPotionPermission;

			public static Action<long, long, string> <7>__RPC_AdminPotionCommandResult;
		}

		public const string PluginGuid = "com.forgepotential.potentialdraught";

		public const string PluginName = "Potential Draught";

		public const string PluginVersion = "1.3.9";

		internal const float PotionSuccessChance = 0.75f;

		internal const float PotionBreakChance = 0.1f;

		internal const float PotionDurationSeconds = 300f;

		internal const int DefaultForgeMaxQuality = 25;

		internal const string ItemPrefabName = "PotionPotentialDraught";

		internal const string StatusEffectPrefabName = "SE_PotentialDraught";

		internal const string AdminItemPrefabName = "PotionPotentialDraughtAdmin";

		internal const string AdminStatusEffectPrefabName = "SE_PotentialDraughtAdmin";

		private Harmony _harmony;

		private Sprite _icon;

		private static readonly FieldInfo VisEquipmentNetViewField = AccessTools.Field(typeof(VisEquipment), "m_nview");

		private static readonly FieldInfo VisEquipmentBodyModelField = AccessTools.Field(typeof(VisEquipment), "m_bodyModel");

		private static readonly FieldInfo VisEquipmentBoneMapField = AccessTools.Field(typeof(VisEquipment), "m_boneMap");

		private static readonly FieldInfo ZNetPeerSocketField = AccessTools.Field(typeof(ZNetPeer), "m_socket");

		private static readonly FieldInfo PlayFabSocketPlatformUserIdField = AccessTools.Field(typeof(ZPlayFabSocket), "m_platformPlayerId");

		private static readonly FieldInfo ZdoObjectsByIdField = AccessTools.Field(typeof(ZDOMan), "m_objectsByID");

		private static readonly MethodInfo ContainerSaveMethod = AccessTools.Method(typeof(Container), "Save", (Type[])null, (Type[])null);

		private static readonly FieldInfo InventoryElementButtonField = AccessTools.Field(typeof(InventoryElement), "m_button");

		private static readonly FieldInfo HotkeyElementsField = AccessTools.Field(typeof(HotkeyBar), "m_elements");

		private static readonly FieldInfo HotkeyItemsField = AccessTools.Field(typeof(HotkeyBar), "m_items");

		private static readonly Type HotkeyElementDataType = AccessTools.Inner(typeof(HotkeyBar), "ElementData");

		private static readonly FieldInfo HotkeyElementObjectField = AccessTools.Field(HotkeyElementDataType, "m_go");

		private static readonly Dictionary<VisEquipment, ArmorQualityState> ArmorQualities = new Dictionary<VisEquipment, ArmorQualityState>();

		private static Shader _surfaceGlowShader;

		private static ParticleIntensityScaler _nativeGlowTemplate;

		private static GameObject _frostnerFogContainerTemplate;

		private static GameObject _shieldParticleTemplate;

		private static GameObject _fistParticleTemplate;

		private static ZRoutedRpc _registeredAdminPotionRpcInstance;

		private static CustomRPC _adminPotionPermissionRpc;

		private static ConfigEntry<string> _allowedAdminPotionPlayerIdentitiesConfig;

		private static ConfigEntry<int> _maximumItemQualityConfig;

		private static int _synchronizedMaximumItemQuality;

		private static readonly HashSet<string> AllowedAdminPotionPlayerIdentities = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static bool _localAdminPotionUseAllowed;

		private static readonly MethodInfo ParticleApplyIntensityMethod = AccessTools.Method(typeof(ParticleIntensityScaler), "ApplyIntensity", (Type[])null, (Type[])null);

		private static readonly MethodInfo RoutedRpcGetServerPeerIdMethod = AccessTools.Method(typeof(ZRoutedRpc), "GetServerPeerID", (Type[])null, (Type[])null);

		private const string RequestAdminPotionPurgeRpc = "PotentialDraught_RequestAdminPotionPurge";

		private const string ExecuteAdminPotionPurgeRpc = "PotentialDraught_ExecuteAdminPotionPurge";

		private const string RequestAdminPotionPermissionRpc = "PotentialDraught_RequestAdminPotionPermission";

		private const string SetAdminPotionPermissionRpc = "PotentialDraught_SetAdminPotionPermission";

		private const string SyncAdminPotionPermissionRpc = "PotentialDraught_SyncAdminPotionPermission";

		private const string AdminPotionCommandResultRpc = "PotentialDraught_AdminPotionCommandResult";

		private const byte AdminPotionRequestPermissionMessage = 1;

		private const byte AdminPotionSetPermissionMessage = 2;

		private const byte AdminPotionSyncPermissionMessage = 3;

		private const byte AdminPotionCommandResultMessage = 4;

		private const byte SetMaximumItemQualityMessage = 5;

		private const byte SyncMaximumItemQualityMessage = 6;

		private const byte RequestAdminPotionPurgeMessage = 7;

		private const byte ExecuteAdminPotionPurgeMessage = 8;

		private const string SurfaceGlowPrefix = "PotentialDraught_SurfaceGlow_";

		private const string ArmorElectricPrefix = "PotentialDraught_ArmorElectric_";

		private const string FistFogName = "PotentialDraught_FistFog";

		private const string ChestQualityZdoKey = "PotentialDraught_ChestQuality";

		private const string LegQualityZdoKey = "PotentialDraught_LegQuality";

		private const string HelmetQualityZdoKey = "PotentialDraught_HelmetQuality";

		private const string UtilityQualityZdoKey = "PotentialDraught_UtilityQuality";

		private const string LeftHandQualityZdoKey = "PotentialDraught_LeftHandQuality";

		private const string RightHandQualityZdoKey = "PotentialDraught_RightHandQuality";

		private const string LeftBackQualityZdoKey = "PotentialDraught_LeftBackQuality";

		private const string RightBackQualityZdoKey = "PotentialDraught_RightBackQuality";

		internal static PotentialDraughtPlugin Instance { get; private set; }

		internal static CustomStatusEffect PotentialStatusEffect { get; private set; }

		internal static CustomStatusEffect AdminPotentialStatusEffect { get; private set; }

		internal static int PendingAdminUpgradeLevels { get; set; } = 1;

		internal static bool AdminLevelOverrideArmed { get; set; }

		public static int MaximumItemQuality
		{
			get
			{
				if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer() && _synchronizedMaximumItemQuality > 0)
				{
					return _synchronizedMaximumItemQuality;
				}
				return Mathf.Max(1, _maximumItemQualityConfig?.Value ?? 25);
			}
		}

		private void Awake()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//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_0090: Expected O, but got Unknown
			Instance = this;
			_allowedAdminPotionPlayerIdentitiesConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Admin Potion", "AllowedPlayerIdentities", string.Empty, "Pipe-separated stable network identities permitted to consume the admin potion. Manage this with allowadminpotion and disableadminpotion.");
			_maximumItemQualityConfig = ((BaseUnityPlugin)this).Config.Bind<int>("Forge", "MaximumItemQuality", 25, "Maximum item quality permitted by normal Forge of Potential upgrades. Change this with maximumitemquality.");
			LoadAllowedAdminPotionPlayerIdentities();
			NetworkManager instance = NetworkManager.Instance;
			object obj = <>O.<0>__AdminPotionPermissionServerReceive;
			if (obj == null)
			{
				CoroutineHandler val = AdminPotionPermissionServerReceive;
				<>O.<0>__AdminPotionPermissionServerReceive = val;
				obj = (object)val;
			}
			object obj2 = <>O.<1>__AdminPotionPermissionClientReceive;
			if (obj2 == null)
			{
				CoroutineHandler val2 = AdminPotionPermissionClientReceive;
				<>O.<1>__AdminPotionPermissionClientReceive = val2;
				obj2 = (object)val2;
			}
			_adminPotionPermissionRpc = instance.AddRPC("AdminPotionPermission", (CoroutineHandler)obj, (CoroutineHandler)obj2);
			AddLocalization();
			RegisterStatusEffect();
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new PotentialLevelsCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new PurgeAdminPotionsCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new AllowAdminPotionCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new DisableAdminPotionCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new MaximumItemQualityCommand());
			PrefabManager.OnVanillaPrefabsAvailable += RegisterPotion;
			_harmony = new Harmony("com.forgepotential.potentialdraught");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			((BaseUnityPlugin)this).Logger.LogInfo((object)(string.Format("{0} {1} loaded. Fixed chances: {2:P0} success, ", "Potential Draught", "1.3.9", 0.75f) + $"{0.1f:P0} break; " + $"duration: {300f:0}s."));
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void AddLocalization()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "English";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{ "item_potentialdraught", "Draught of Tempered Potential" },
				{ "item_potentialdraught_description", "A volatile golden draught that steadies the Forge of Potential without silencing its danger." },
				{ "se_potentialdraught", "Tempered Potential" },
				{ "se_potentialdraught_tooltip", "Improves the Forge of Potential refinement chance while active. Failure can still destroy the item." },
				{ "se_potentialdraught_start", "The threads of possibility burn brighter." },
				{ "se_potentialdraught_stop", "The golden certainty fades." },
				{ "item_potentialdraught_admin", "Draught of Absolute Potential [Admin]" },
				{ "item_potentialdraught_admin_description", "An admin-only draught of absolute certainty. Spawn ID: PotionPotentialDraughtAdmin" },
				{ "se_potentialdraught_admin", "Absolute Potential" },
				{ "se_potentialdraught_admin_tooltip", "Forge of Potential attempts always succeed and complete almost instantly." },
				{ "se_potentialdraught_admin_start", "Every possible path becomes one." },
				{ "se_potentialdraught_admin_stop", "Absolute certainty releases its hold." }
			});
		}

		private void RegisterStatusEffect()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Expected O, but got Unknown
			_icon = LoadEmbeddedIcon();
			StatusEffect obj = ScriptableObject.CreateInstance<StatusEffect>();
			((Object)obj).name = "SE_PotentialDraught";
			obj.m_name = "$se_potentialdraught";
			obj.m_tooltip = "$se_potentialdraught_tooltip";
			obj.m_icon = _icon;
			obj.m_category = "potion";
			obj.m_ttl = 300f;
			obj.m_startMessageType = (MessageType)2;
			obj.m_startMessage = "$se_potentialdraught_start";
			obj.m_stopMessageType = (MessageType)2;
			obj.m_stopMessage = "$se_potentialdraught_stop";
			obj.m_cooldownIcon = false;
			obj.m_flashIcon = false;
			obj.m_effectsOnlyOnPlayer = true;
			PotentialStatusEffect = new CustomStatusEffect(obj, false);
			if (!ItemManager.Instance.AddStatusEffect(PotentialStatusEffect))
			{
				throw new InvalidOperationException("Could not register the Potential Draught status effect.");
			}
			StatusEffect obj2 = ScriptableObject.CreateInstance<StatusEffect>();
			((Object)obj2).name = "SE_PotentialDraughtAdmin";
			obj2.m_name = "$se_potentialdraught_admin";
			obj2.m_tooltip = "$se_potentialdraught_admin_tooltip";
			obj2.m_icon = _icon;
			obj2.m_category = "potential_admin_potion";
			obj2.m_ttl = 300f;
			obj2.m_startMessageType = (MessageType)2;
			obj2.m_startMessage = "$se_potentialdraught_admin_start";
			obj2.m_stopMessageType = (MessageType)2;
			obj2.m_stopMessage = "$se_potentialdraught_admin_stop";
			obj2.m_cooldownIcon = false;
			obj2.m_flashIcon = true;
			obj2.m_effectsOnlyOnPlayer = true;
			AdminPotentialStatusEffect = new CustomStatusEffect(obj2, false);
			if (!ItemManager.Instance.AddStatusEffect(AdminPotentialStatusEffect))
			{
				throw new InvalidOperationException("Could not register the admin Potential Draught status effect.");
			}
		}

		private void RegisterPotion()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterPotion;
			RegisterAdminPotionRpcs();
			CacheNativeGlowTemplate();
			ItemConfig val = new ItemConfig();
			val.Name = "$item_potentialdraught";
			val.Description = "$item_potentialdraught_description";
			val.Amount = 1;
			val.CraftingStation = "piece_cauldron";
			val.MinStationLevel = 3;
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[4]
			{
				new RequirementConfig("Honey", 10, 0, false),
				new RequirementConfig("Bloodbag", 5, 0, false),
				new RequirementConfig("DragonTear", 5, 0, false),
				new RequirementConfig("GreydwarfEye", 5, 0, false)
			};
			ItemConfig val2 = val;
			CustomItem val3 = new CustomItem("PotionPotentialDraught", "MeadFrostResist", val2);
			val3.ItemDrop.m_itemData.m_shared.m_name = "$item_potentialdraught";
			val3.ItemDrop.m_itemData.m_shared.m_description = "$item_potentialdraught_description";
			val3.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { _icon };
			val3.ItemDrop.m_itemData.m_shared.m_consumeStatusEffect = PotentialStatusEffect.StatusEffect;
			val3.ItemDrop.m_itemData.m_shared.m_maxStackSize = 10;
			if (!ItemManager.Instance.AddItem(val3))
			{
				throw new InvalidOperationException("Could not register the Potential Draught item.");
			}
			CustomItem val4 = new CustomItem("PotionPotentialDraughtAdmin", "MeadFrostResist");
			val4.ItemDrop.m_itemData.m_shared.m_name = "$item_potentialdraught_admin";
			val4.ItemDrop.m_itemData.m_shared.m_description = "$item_potentialdraught_admin_description";
			val4.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { _icon };
			val4.ItemDrop.m_itemData.m_shared.m_consumeStatusEffect = AdminPotentialStatusEffect.StatusEffect;
			val4.ItemDrop.m_itemData.m_shared.m_maxStackSize = 10;
			if (!ItemManager.Instance.AddItem(val4))
			{
				throw new InvalidOperationException("Could not register the admin Potential Draught item.");
			}
		}

		private static void CacheNativeGlowTemplate()
		{
			if (ObjectDB.instance?.m_items == null)
			{
				return;
			}
			_shieldParticleTemplate = FindItemParticleTemplate("FistGold_FrostFire", "FistGold_BloodLightning", "FistGold");
			_fistParticleTemplate = FindItemParticleTemplate("FistGold_FrostFire", "FistGold_BloodLightning", "FistGold");
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Frostner");
			if ((Object)(object)itemPrefab != (Object)null)
			{
				Transform val = itemPrefab.transform.Find("attach");
				if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponentInChildren<ParticleSystem>(true) != (Object)null)
				{
					_frostnerFogContainerTemplate = ((Component)val).gameObject;
					_nativeGlowTemplate = ((Component)val).GetComponentInChildren<ParticleIntensityScaler>(true);
					((BaseUnityPlugin)Instance).Logger.LogInfo((object)$"Using Frostner attach particles directly ({((Component)val).GetComponentsInChildren<ParticleSystem>(true).Length} systems).");
					return;
				}
			}
			if (TryCacheGlowTemplate(itemPrefab, "Frostner"))
			{
				return;
			}
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				if (TryCacheGlowTemplate(item, (item != null) ? ((Object)item).name : null))
				{
					return;
				}
			}
			((BaseUnityPlugin)Instance).Logger.LogWarning((object)"No native potential glow template was found; material emission will be used as a fallback.");
		}

		private static GameObject FindItemParticleTemplate(params string[] prefabNames)
		{
			foreach (string text in prefabNames)
			{
				ObjectDB instance = ObjectDB.instance;
				GameObject val = ((instance != null) ? instance.GetItemPrefab(text) : null);
				if (!((Object)(object)val == (Object)null))
				{
					Transform val2 = val.transform.Find("attach");
					if ((Object)(object)val2 != (Object)null && (Object)(object)((Component)val2).GetComponentInChildren<ParticleSystem>(true) != (Object)null)
					{
						((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Using '" + text + "' attach particles as a specialized fallback."));
						return ((Component)val2).gameObject;
					}
					ParticleIntensityScaler componentInChildren = val.GetComponentInChildren<ParticleIntensityScaler>(true);
					if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((Component)componentInChildren).GetComponentInChildren<ParticleSystem>(true) != (Object)null)
					{
						((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Using '" + text + "' particle scaler as a specialized fallback."));
						return ((Component)componentInChildren).gameObject;
					}
				}
			}
			return null;
		}

		private static bool TryCacheGlowTemplate(GameObject itemPrefab, string sourceName)
		{
			if ((Object)(object)itemPrefab == (Object)null)
			{
				return false;
			}
			ParticleIntensityScaler[] componentsInChildren = itemPrefab.GetComponentsInChildren<ParticleIntensityScaler>(true);
			foreach (ParticleIntensityScaler val in componentsInChildren)
			{
				if (!((Object)(object)((Component)val).GetComponentInChildren<ParticleSystem>(true) == (Object)null))
				{
					_nativeGlowTemplate = val;
					((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Using Frostner-style fog container '" + ((Object)val).name + "' from '" + sourceName + "'."));
					return true;
				}
			}
			return false;
		}

		private static bool CreateNativeFogGlow(GameObject visual, int quality, Bounds? forcedBounds = null, string glowObjectName = "PotentialDraught_FogGlow", GameObject preferredTemplate = null)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: 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_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_frostnerFogContainerTemplate == (Object)null && (Object)(object)_nativeGlowTemplate == (Object)null)
			{
				CacheNativeGlowTemplate();
			}
			GameObject val = preferredTemplate ?? _frostnerFogContainerTemplate ?? (((Object)(object)_nativeGlowTemplate == (Object)null) ? null : ((Component)_nativeGlowTemplate).gameObject);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			GameObject val2 = new GameObject(glowObjectName);
			val2.transform.SetParent(visual.transform, false);
			Vector3 lossyScale = visual.transform.lossyScale;
			val2.transform.localScale = new Vector3(Mathf.Clamp(1f / Mathf.Max(0.0001f, Mathf.Abs(lossyScale.x)), 0.05f, 20f), Mathf.Clamp(1f / Mathf.Max(0.0001f, Mathf.Abs(lossyScale.y)), 0.05f, 20f), Mathf.Clamp(1f / Mathf.Max(0.0001f, Mathf.Abs(lossyScale.z)), 0.05f, 20f));
			Bounds bounds;
			if (forcedBounds.HasValue)
			{
				bounds = forcedBounds.Value;
			}
			else if (!TryGetLocalEquipmentBounds(visual, out bounds))
			{
				Object.Destroy((Object)(object)val2);
				return false;
			}
			val2.transform.localPosition = ((Bounds)(ref bounds)).center;
			GameObject val3 = Object.Instantiate<GameObject>(val, val2.transform, false);
			((Object)val3).name = "PotentialFallbackParticles";
			val3.transform.localPosition = Vector3.zero;
			val3.transform.localRotation = Quaternion.identity;
			val3.transform.localScale = Vector3.one;
			Renderer[] componentsInChildren = val3.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val4 in componentsInChildren)
			{
				if (!(val4 is ParticleSystemRenderer))
				{
					val4.enabled = false;
				}
			}
			Collider[] componentsInChildren2 = val3.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				componentsInChildren2[i].enabled = false;
			}
			Light[] componentsInChildren3 = val3.GetComponentsInChildren<Light>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				((Behaviour)componentsInChildren3[i]).enabled = false;
			}
			ParticleSystem[] componentsInChildren4 = val3.GetComponentsInChildren<ParticleSystem>(true);
			if (componentsInChildren4.Length == 0)
			{
				Object.Destroy((Object)(object)val2);
				return false;
			}
			ShapeModule shape = componentsInChildren4[0].shape;
			Vector3 val5 = ((Component)componentsInChildren4[0]).transform.TransformPoint(((ShapeModule)(ref shape)).enabled ? ((ShapeModule)(ref shape)).position : Vector3.zero);
			Bounds val6 = default(Bounds);
			((Bounds)(ref val6))..ctor(val3.transform.InverseTransformPoint(val5), Vector3.zero);
			for (int j = 1; j < componentsInChildren4.Length; j++)
			{
				ShapeModule shape2 = componentsInChildren4[j].shape;
				Vector3 val7 = ((Component)componentsInChildren4[j]).transform.TransformPoint(((ShapeModule)(ref shape2)).enabled ? ((ShapeModule)(ref shape2)).position : Vector3.zero);
				((Bounds)(ref val6)).Encapsulate(val3.transform.InverseTransformPoint(val7));
			}
			Vector3 val8 = Vector3.one * 0.75f;
			val3.transform.localScale = val8;
			Vector3 localPosition = -Vector3.Scale(((Bounds)(ref val6)).center, val8);
			val3.transform.localPosition = localPosition;
			ParticleIntensityScaler componentInChildren = val3.GetComponentInChildren<ParticleIntensityScaler>(true);
			MonoBehaviour[] componentsInChildren5 = val3.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val9 in componentsInChildren5)
			{
				if ((Object)(object)val9 != (Object)(object)componentInChildren)
				{
					((Behaviour)val9).enabled = false;
				}
			}
			val3.SetActive(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.CacheOriginalValues();
				componentInChildren.SetQuality(quality);
				componentInChildren.intensity *= 0.8f;
				ParticleApplyIntensityMethod?.Invoke(componentInChildren, null);
				((Behaviour)componentInChildren).enabled = false;
			}
			ParticleSystem[] array = componentsInChildren4;
			foreach (ParticleSystem obj in array)
			{
				((Component)obj).gameObject.SetActive(true);
				obj.Clear(true);
				obj.Play(true);
			}
			((BaseUnityPlugin)Instance).Logger.LogDebug((object)$"Attached vanilla fallback particles from '{((Object)val).name}' to '{((Object)visual).name}' at 80% native intensity and quality {quality}.");
			return true;
		}

		private static bool TryGetLocalEquipmentBounds(GameObject visual, out Bounds bounds)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			bounds = default(Bounds);
			bool flag = false;
			Renderer[] componentsInChildren = visual.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (val is ParticleSystemRenderer || ((Object)((Component)val).gameObject).name.StartsWith("PotentialDraught_SurfaceGlow_"))
				{
					continue;
				}
				Bounds bounds2 = val.bounds;
				for (int j = -1; j <= 1; j += 2)
				{
					for (int k = -1; k <= 1; k += 2)
					{
						for (int l = -1; l <= 1; l += 2)
						{
							Vector3 val2 = ((Bounds)(ref bounds2)).center + Vector3.Scale(((Bounds)(ref bounds2)).extents, new Vector3((float)j, (float)k, (float)l));
							Vector3 val3 = visual.transform.InverseTransformPoint(val2);
							if (!flag)
							{
								bounds = new Bounds(val3, Vector3.zero);
								flag = true;
							}
							else
							{
								((Bounds)(ref bounds)).Encapsulate(val3);
							}
						}
					}
				}
			}
			return flag;
		}

		internal static Color GetPotentialGlowColor(int quality)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			if (quality >= 30)
			{
				return new Color(1f, 0.05f, 0.55f, 1f);
			}
			if (quality >= 25)
			{
				return new Color(1f, 0.04f, 0.04f, 1f);
			}
			if (quality >= 20)
			{
				return new Color(1f, 0.62f, 0.05f, 1f);
			}
			if (quality >= 15)
			{
				return new Color(0.65f, 0.18f, 1f, 1f);
			}
			if (quality >= 10)
			{
				return new Color(0.12f, 1f, 0.22f, 1f);
			}
			return new Color(0.12f, 0.42f, 1f, 1f);
		}

		private static void ConfigureItemIconGlow(GameObject slot, int quality)
		{
			if (!((Object)(object)slot == (Object)null))
			{
				PotentialItemIconGlow potentialItemIconGlow = slot.GetComponent<PotentialItemIconGlow>();
				if ((Object)(object)potentialItemIconGlow == (Object)null)
				{
					potentialItemIconGlow = slot.AddComponent<PotentialItemIconGlow>();
				}
				potentialItemIconGlow.Configure(quality);
			}
		}

		private static void UpdateInventoryIconGlows(Inventory inventory, List<InventoryElement> elements)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (inventory == null || elements == null)
			{
				return;
			}
			foreach (InventoryElement element in elements)
			{
				if (!((Object)(object)element == (Object)null))
				{
					Vector2i position = element.Position;
					ItemData itemAt = inventory.GetItemAt(position.x, position.y);
					object? obj = InventoryElementButtonField?.GetValue(element);
					object? obj2 = ((obj is Button) ? obj : null);
					ConfigureItemIconGlow((obj2 != null) ? ((Component)obj2).gameObject : null, itemAt?.m_quality ?? 0);
				}
			}
		}

		private static void UpdateHotkeyIconGlows(HotkeyBar hotkeyBar)
		{
			IList list = HotkeyElementsField?.GetValue(hotkeyBar) as IList;
			IList list2 = HotkeyItemsField?.GetValue(hotkeyBar) as IList;
			if (list != null)
			{
				for (int i = 0; i < list.Count; i++)
				{
					object obj = list[i];
					ConfigureItemIconGlow((GameObject)((obj == null) ? null : /*isinst with value type is only supported in some contexts*/), ((ItemData)(((list2 != null && i < list2.Count) ? /*isinst with value type is only supported in some contexts*/: null)?)).m_quality ?? 0);
				}
			}
		}

		private static void ConfigureRainbowGlow(GameObject visual, int quality, bool animateSurface = false)
		{
			if (!((Object)(object)visual == (Object)null))
			{
				PotentialRainbowGlowController component = visual.GetComponent<PotentialRainbowGlowController>();
				if ((Object)(object)component != (Object)null)
				{
					((Behaviour)component).enabled = false;
					Object.Destroy((Object)(object)component);
				}
			}
		}

		internal static void RefreshRainbowParticleColors(GameObject visual)
		{
			if (!((Object)(object)visual == (Object)null) && !(ParticleApplyIntensityMethod == null))
			{
				ParticleIntensityScaler[] componentsInChildren = visual.GetComponentsInChildren<ParticleIntensityScaler>(true);
				foreach (ParticleIntensityScaler obj in componentsInChildren)
				{
					ParticleApplyIntensityMethod.Invoke(obj, null);
				}
			}
		}

		private static void ApplyPotentialGlow(GameObject visual, int quality, bool subtleArmorGlow = false, FallbackParticleKind fallbackKind = FallbackParticleKind.None)
		{
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)visual == (Object)null)
			{
				return;
			}
			if (quality < 5)
			{
				ConfigureRainbowGlow(visual, quality);
				return;
			}
			Transform val = visual.transform.Find("PotentialDraught_FogGlow");
			if (fallbackKind == FallbackParticleKind.Shield || fallbackKind == FallbackParticleKind.Fist)
			{
				ConfigureRainbowGlow(visual, 0);
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
				ParticleSystem[] componentsInChildren = visual.GetComponentsInChildren<ParticleSystem>(true);
				foreach (ParticleSystem obj in componentsInChildren)
				{
					obj.Stop(true, (ParticleSystemStopBehavior)0);
					((Component)obj).gameObject.SetActive(false);
				}
				return;
			}
			if ((Object)(object)val != (Object)null)
			{
				ConfigureRainbowGlow(visual, quality);
				return;
			}
			ParticleIntensityScaler[] componentsInChildren2 = visual.GetComponentsInChildren<ParticleIntensityScaler>(true);
			ParticleIntensityScaler[] array;
			if (subtleArmorGlow)
			{
				ConfigureRainbowGlow(visual, 0);
				array = componentsInChildren2;
				foreach (ParticleIntensityScaler obj2 in array)
				{
					obj2.SetQuality(obj2.maxQuality);
				}
				return;
			}
			ParticleSystem[] componentsInChildren3 = visual.GetComponentsInChildren<ParticleSystem>(true);
			if (componentsInChildren3.Length != 0 && fallbackKind == FallbackParticleKind.None)
			{
				array = componentsInChildren2;
				for (int i = 0; i < array.Length; i++)
				{
					array[i].SetQuality(quality);
				}
				ParticleSystem[] componentsInChildren = componentsInChildren3;
				foreach (ParticleSystem val2 in componentsInChildren)
				{
					((Component)val2).gameObject.SetActive(true);
					if (!val2.isPlaying)
					{
						val2.Play(true);
					}
				}
				ConfigureRainbowGlow(visual, quality);
				return;
			}
			array = componentsInChildren2;
			foreach (ParticleIntensityScaler obj3 in array)
			{
				obj3.SetQuality(obj3.maxQuality);
			}
			if (CreateNativeFogGlow(visual, quality, null, "PotentialDraught_FogGlow", (GameObject)(fallbackKind switch
			{
				FallbackParticleKind.Fist => _fistParticleTemplate, 
				FallbackParticleKind.Shield => _shieldParticleTemplate, 
				_ => null, 
			})))
			{
				ConfigureRainbowGlow(visual, quality);
				return;
			}
			Color val3 = GetPotentialGlowColor(quality) * 0.54f;
			val3.a = 1f;
			Renderer[] componentsInChildren4 = visual.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val4 in componentsInChildren4)
			{
				if (((Object)((Component)val4).gameObject).name.StartsWith("PotentialDraught_SurfaceGlow_"))
				{
					continue;
				}
				bool flag = false;
				Material[] materials = val4.materials;
				foreach (Material val5 in materials)
				{
					if (val5.HasProperty("_EmissionColor"))
					{
						val5.EnableKeyword("_EMISSION");
						val5.SetColor("_EmissionColor", val3);
						flag = true;
					}
					else if (val5.HasProperty("_EmissiveColor"))
					{
						val5.SetColor("_EmissiveColor", val3);
						flag = true;
					}
				}
				if (!flag)
				{
					EnsureSurfaceGlowOverlay(val4, val3, null, "Item", 0.28f);
				}
			}
			ConfigureRainbowGlow(visual, quality, animateSurface: true);
		}

		private static Shader GetSurfaceGlowShader()
		{
			if ((Object)(object)_surfaceGlowShader != (Object)null)
			{
				return _surfaceGlowShader;
			}
			_surfaceGlowShader = Shader.Find("Legacy Shaders/Particles/Additive");
			if ((Object)(object)_surfaceGlowShader == (Object)null)
			{
				_surfaceGlowShader = Shader.Find("Particles/Standard Unlit");
			}
			if ((Object)(object)_surfaceGlowShader == (Object)null)
			{
				_surfaceGlowShader = Shader.Find("Unlit/Transparent");
			}
			return _surfaceGlowShader;
		}

		private static string GetSurfaceGlowName(Renderer source, string slot)
		{
			return "PotentialDraught_SurfaceGlow_" + slot + "_" + ((Object)source).GetInstanceID();
		}

		private static Material CreateSurfaceGlowMaterial(Material sourceMaterial, Texture textureOverride, Color emission, float overlayAlpha)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			Shader surfaceGlowShader = GetSurfaceGlowShader();
			if ((Object)(object)surfaceGlowShader == (Object)null)
			{
				return null;
			}
			Material val = new Material(surfaceGlowShader)
			{
				name = "PotentialDraught_SurfaceGlowMaterial",
				renderQueue = 3100
			};
			Texture val2 = textureOverride;
			if ((Object)(object)val2 == (Object)null && (Object)(object)sourceMaterial != (Object)null && sourceMaterial.HasProperty("_MainTex"))
			{
				val2 = sourceMaterial.GetTexture("_MainTex");
			}
			if ((Object)(object)val2 != (Object)null && val.HasProperty("_MainTex"))
			{
				val.SetTexture("_MainTex", val2);
			}
			Color val3 = emission;
			val3.a = overlayAlpha;
			if (val.HasProperty("_TintColor"))
			{
				val.SetColor("_TintColor", val3);
			}
			if (val.HasProperty("_Color"))
			{
				val.SetColor("_Color", val3);
			}
			return val;
		}

		private static void EnsureSurfaceGlowOverlay(Renderer source, Color emission, Texture textureOverride, string slot, float overlayAlpha)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null || (Object)(object)((Component)source).transform.parent == (Object)null)
			{
				return;
			}
			string surfaceGlowName = GetSurfaceGlowName(source, slot);
			Transform obj = ((Component)source).transform.parent.Find(surfaceGlowName);
			Renderer val = ((obj != null) ? ((Component)obj).GetComponent<Renderer>() : null);
			if ((Object)(object)val == (Object)null)
			{
				GameObject val2 = new GameObject(surfaceGlowName);
				val2.layer = ((Component)source).gameObject.layer;
				val2.transform.SetParent(((Component)source).transform.parent, false);
				val2.transform.localPosition = ((Component)source).transform.localPosition;
				val2.transform.localRotation = ((Component)source).transform.localRotation;
				val2.transform.localScale = ((Component)source).transform.localScale * 1.003f;
				SkinnedMeshRenderer val3 = (SkinnedMeshRenderer)(object)((source is SkinnedMeshRenderer) ? source : null);
				if ((Object)(object)val3 != (Object)null)
				{
					SkinnedMeshRenderer obj2 = val2.AddComponent<SkinnedMeshRenderer>();
					obj2.sharedMesh = val3.sharedMesh;
					obj2.bones = val3.bones;
					obj2.rootBone = val3.rootBone;
					((Renderer)obj2).localBounds = ((Renderer)val3).localBounds;
					obj2.updateWhenOffscreen = val3.updateWhenOffscreen;
					val = (Renderer)(object)obj2;
				}
				else
				{
					MeshFilter component = ((Component)source).GetComponent<MeshFilter>();
					if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null)
					{
						Object.Destroy((Object)(object)val2);
						return;
					}
					val2.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
					val = (Renderer)(object)val2.AddComponent<MeshRenderer>();
				}
				val.receiveShadows = false;
				val.sortingLayerID = source.sortingLayerID;
				val.sortingOrder = source.sortingOrder + 1;
			}
			Material[] sharedMaterials = source.sharedMaterials;
			int num = Mathf.Max(1, sharedMaterials.Length);
			Material[] array = (Material[])(object)new Material[num];
			for (int i = 0; i < num; i++)
			{
				Material sourceMaterial = ((sharedMaterials.Length > i) ? sharedMaterials[i] : null);
				array[i] = CreateSurfaceGlowMaterial(sourceMaterial, textureOverride, emission, overlayAlpha);
			}
			val.sharedMaterials = array;
			val.enabled = source.enabled;
		}

		private static void RemoveBodyArmorGlow(VisEquipment equipment, string slot)
		{
			object? obj = VisEquipmentBodyModelField?.GetValue(equipment);
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)((obj is SkinnedMeshRenderer) ? obj : null);
			if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).transform.parent != (Object)null)
			{
				Transform val2 = ((Component)val).transform.parent.Find(GetSurfaceGlowName((Renderer)(object)val, slot));
				if ((Object)(object)val2 != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val2).gameObject);
				}
			}
			if ((Object)(object)equipment == (Object)null)
			{
				return;
			}
			ArmorElectricArcController[] componentsInChildren = ((Component)equipment).GetComponentsInChildren<ArmorElectricArcController>(true);
			foreach (ArmorElectricArcController armorElectricArcController in componentsInChildren)
			{
				if (((Object)((Component)armorElectricArcController).gameObject).name == "PotentialDraught_ArmorElectric_" + slot)
				{
					Object.Destroy((Object)(object)((Component)armorElectricArcController).gameObject);
				}
			}
		}

		private static Transform FindArmorBone(VisEquipment equipment, bool upperBody)
		{
			if (!(VisEquipmentBoneMapField?.GetValue(equipment) is Dictionary<string, Transform> { Count: not 0 } dictionary))
			{
				return null;
			}
			string[] array = ((!upperBody) ? new string[4] { "Hips", "Pelvis", "Hip", "Root" } : new string[5] { "Spine2", "UpperChest", "Chest", "Spine1", "Spine" });
			foreach (string b in array)
			{
				foreach (KeyValuePair<string, Transform> item in dictionary)
				{
					if (string.Equals(item.Key, b, StringComparison.OrdinalIgnoreCase))
					{
						return item.Value;
					}
				}
			}
			array = ((!upperBody) ? new string[3] { "hips", "pelvis", "hip" } : new string[5] { "spine2", "upperchest", "chest", "spine1", "spine" });
			foreach (string value in array)
			{
				foreach (KeyValuePair<string, Transform> item2 in dictionary)
				{
					if (item2.Key.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return item2.Value;
					}
				}
			}
			object? obj = VisEquipmentBodyModelField?.GetValue(equipment);
			object? obj2 = ((obj is SkinnedMeshRenderer) ? obj : null);
			if (obj2 == null)
			{
				return null;
			}
			return ((SkinnedMeshRenderer)obj2).rootBone;
		}

		private static void EnsureArmorElectricEffect(GameObject visual, int quality, string slot, Vector3? worldPosition = null)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)visual == (Object)null) && quality >= 5)
			{
				string text = "PotentialDraught_ArmorElectric_" + slot;
				Transform obj = visual.transform.Find(text);
				ArmorElectricArcController armorElectricArcController = ((obj != null) ? ((Component)obj).GetComponent<ArmorElectricArcController>() : null);
				if ((Object)(object)armorElectricArcController == (Object)null)
				{
					GameObject val = new GameObject(text);
					val.transform.SetParent(visual.transform, false);
					val.transform.localPosition = Vector3.zero;
					armorElectricArcController = val.AddComponent<ArmorElectricArcController>();
				}
				if (worldPosition.HasValue)
				{
					((Component)armorElectricArcController).transform.position = worldPosition.Value;
				}
				Vector3 areaScale = ((slot == "Chest") ? new Vector3(0.38f, 0.32f, 0.24f) : ((slot == "Legs") ? new Vector3(0.32f, 0.4f, 0.22f) : new Vector3(0.28f, 0.28f, 0.28f)));
				armorElectricArcController.Configure(GetPotentialGlowColor(quality), areaScale);
			}
		}

		private static bool ApplyAnchoredArmorElectricity(VisEquipment equipment, int itemHash, int quality)
		{
			ZDO equipmentZdo = GetEquipmentZdo(equipment);
			ArmorQualities.TryGetValue(equipment, out var value);
			bool flag = (value != null && value.ChestHash == itemHash) || (equipmentZdo != null && equipmentZdo.GetInt(ZDOVars.s_chestItem, 0) == itemHash);
			bool flag2 = (value != null && value.LegHash == itemHash) || (equipmentZdo != null && equipmentZdo.GetInt(ZDOVars.s_legItem, 0) == itemHash);
			bool flag3 = (value != null && value.ShoulderHash == itemHash) || (equipmentZdo != null && equipmentZdo.GetInt(ZDOVars.s_shoulderItem, 0) == itemHash);
			bool flag4 = (value != null && value.UtilityHash == itemHash) || (equipmentZdo != null && equipmentZdo.GetInt(ZDOVars.s_utilityItem, 0) == itemHash);
			if (!flag && !flag2 && !flag3 && !flag4)
			{
				return false;
			}
			string slot = (flag ? "Chest" : (flag2 ? "Legs" : (flag3 ? "Cape" : "Utility")));
			RemoveBodyArmorGlow(equipment, slot);
			if (quality < 5)
			{
				return true;
			}
			Transform val = FindArmorBone(equipment, !flag2);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			EnsureArmorElectricEffect(((Component)val).gameObject, quality, slot);
			return true;
		}

		private static bool IsArmorVisual(VisEquipment equipment, int itemHash)
		{
			if ((Object)(object)equipment == (Object)null || itemHash == 0)
			{
				return false;
			}
			if (ArmorQualities.TryGetValue(equipment, out var value) && (value.ChestHash == itemHash || value.LegHash == itemHash || value.HelmetHash == itemHash || value.ShoulderHash == itemHash || value.UtilityHash == itemHash))
			{
				return true;
			}
			ZDO equipmentZdo = GetEquipmentZdo(equipment);
			if (equipmentZdo != null)
			{
				if (equipmentZdo.GetInt(ZDOVars.s_chestItem, 0) != itemHash && equipmentZdo.GetInt(ZDOVars.s_legItem, 0) != itemHash && equipmentZdo.GetInt(ZDOVars.s_helmetItem, 0) != itemHash && equipmentZdo.GetInt(ZDOVars.s_shoulderItem, 0) != itemHash)
				{
					return equipmentZdo.GetInt(ZDOVars.s_utilityItem, 0) == itemHash;
				}
				return true;
			}
			return false;
		}

		private static bool IsArmorItem(ItemData item)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			if (item?.m_shared == null)
			{
				return false;
			}
			ItemType itemType = item.m_shared.m_itemType;
			if ((int)itemType != 6 && (int)itemType != 7 && (int)itemType != 11 && (int)itemType != 17)
			{
				return (int)itemType == 18;
			}
			return true;
		}

		private static bool IsArmorPrefab(int itemHash)
		{
			ObjectDB instance = ObjectDB.instance;
			GameObject obj = ((instance != null) ? instance.GetItemPrefab(itemHash) : null);
			ItemDrop val = ((obj != null) ? obj.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val != (Object)null)
			{
				return IsArmorItem(val.m_itemData);
			}
			return false;
		}

		private static bool IsFistWeaponPrefab(int itemHash)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Invalid comparison between Unknown and I4
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			ObjectDB instance = ObjectDB.instance;
			GameObject obj = ((instance != null) ? instance.GetItemPrefab(itemHash) : null);
			SharedData val = ((obj != null) ? obj.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared;
			if (val != null)
			{
				if ((int)val.m_itemType != 12)
				{
					return (int)val.m_skillType == 11;
				}
				return true;
			}
			return false;
		}

		private static bool IsShieldPrefab(int itemHash)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Invalid comparison between Unknown and I4
			ObjectDB instance = ObjectDB.instance;
			GameObject obj = ((instance != null) ? instance.GetItemPrefab(itemHash) : null);
			ItemDrop val = ((obj != null) ? obj.GetComponent<ItemDrop>() : null);
			if (val?.m_itemData?.m_shared != null)
			{
				return (int)val.m_itemData.m_shared.m_itemType == 5;
			}
			return false;
		}

		private static FallbackParticleKind GetFallbackParticleKind(int itemHash)
		{
			if (IsShieldPrefab(itemHash))
			{
				return FallbackParticleKind.Shield;
			}
			if (IsFistWeaponPrefab(itemHash))
			{
				return FallbackParticleKind.Fist;
			}
			return FallbackParticleKind.None;
		}

		private static void UpdateFistHandFog(Transform hand, bool equipped, int quality)
		{
			if (!((Object)(object)hand == (Object)null))
			{
				Transform val = hand.Find("PotentialDraught_FistFog");
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
		}

		private static int GetItemHash(ItemData item)
		{
			if (!((Object)(object)item?.m_dropPrefab == (Object)null))
			{
				return GetStableHashCode(((Object)item.m_dropPrefab).name);
			}
			return 0;
		}

		private static int GetStableHashCode(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return 0;
			}
			int num = 5381;
			int num2 = num;
			for (int i = 0; i < value.Length; i += 2)
			{
				num = ((num << 5) + num) ^ value[i];
				if (i == value.Length - 1)
				{
					break;
				}
				num2 = ((num2 << 5) + num2) ^ value[i + 1];
			}
			return num + num2 * 1566083941;
		}

		private static ZDO GetEquipmentZdo(VisEquipment equipment)
		{
			object? obj = VisEquipmentNetViewField?.GetValue(equipment);
			object? obj2 = ((obj is ZNetView) ? obj : null);
			if (obj2 == null)
			{
				return null;
			}
			return ((ZNetView)obj2).GetZDO();
		}

		private static void RecordArmorQualities(VisEquipment equipment, ItemData chest, ItemData legs, ItemData helmet, ItemData shoulder, ItemData utility)
		{
			if (!((Object)(object)equipment == (Object)null))
			{
				if (!ArmorQualities.TryGetValue(equipment, out var value))
				{
					value = new ArmorQualityState();
					ArmorQualities[equipment] = value;
				}
				value.ChestHash = GetItemHash(chest);
				value.ChestQuality = chest?.m_quality ?? 0;
				value.LegHash = GetItemHash(legs);
				value.LegQuality = legs?.m_quality ?? 0;
				value.HelmetHash = GetItemHash(helmet);
				value.HelmetQuality = helmet?.m_quality ?? 0;
				value.ShoulderHash = GetItemHash(shoulder);
				value.ShoulderQuality = shoulder?.m_quality ?? 0;
				value.UtilityHash = GetItemHash(utility);
				value.UtilityQuality = utility?.m_quality ?? 0;
				object? obj = VisEquipmentNetViewField?.GetValue(equipment);
				ZNetView val = (ZNetView)((obj is ZNetView) ? obj : null);
				ZDO val2 = ((val != null) ? val.GetZDO() : null);
				if (val2 != null && val.IsOwner())
				{
					val2.Set("PotentialDraught_ChestQuality", value.ChestQuality);
					val2.Set("PotentialDraught_LegQuality", value.LegQuality);
					val2.Set("PotentialDraught_HelmetQuality", value.HelmetQuality);
					val2.Set("PotentialDraught_UtilityQuality", value.UtilityQuality);
				}
			}
		}

		private static int ResolveArmorQuality(VisEquipment equipment, int itemHash, int originalQuality)
		{
			if ((Object)(object)equipment == (Object)null || itemHash == 0)
			{
				return originalQuality;
			}
			int num = originalQuality;
			if (ArmorQualities.TryGetValue(equipment, out var value))
			{
				if (value.ChestHash == itemHash)
				{
					num = Mathf.Max(num, value.ChestQuality);
				}
				if (value.LegHash == itemHash)
				{
					num = Mathf.Max(num, value.LegQuality);
				}
				if (value.HelmetHash == itemHash)
				{
					num = Mathf.Max(num, value.HelmetQuality);
				}
				if (value.ShoulderHash == itemHash)
				{
					num = Mathf.Max(num, value.ShoulderQuality);
				}
				if (value.UtilityHash == itemHash)
				{
					num = Mathf.Max(num, value.UtilityQuality);
				}
			}
			ZDO equipmentZdo = GetEquipmentZdo(equipment);
			if (equipmentZdo != null)
			{
				if (equipmentZdo.GetInt(ZDOVars.s_chestItem, 0) == itemHash)
				{
					num = Mathf.Max(num, equipmentZdo.GetInt("PotentialDraught_ChestQuality", 0));
				}
				if (equipmentZdo.GetInt(ZDOVars.s_legItem, 0) == itemHash)
				{
					num = Mathf.Max(num, equipmentZdo.GetInt("PotentialDraught_LegQuality", 0));
				}
				if (equipmentZdo.GetInt(ZDOVars.s_helmetItem, 0) == itemHash)
				{
					num = Mathf.Max(num, equipmentZdo.GetInt("PotentialDraught_HelmetQuality", 0));
				}
				if (equipmentZdo.GetInt(ZDOVars.s_shoulderItem, 0) == itemHash)
				{
					num = Mathf.Max(num, equipmentZdo.GetInt(ZDOVars.s_shoulderItemQuality, 0));
				}
				if (equipmentZdo.GetInt(ZDOVars.s_utilityItem, 0) == itemHash)
				{
					num = Mathf.Max(num, equipmentZdo.GetInt("PotentialDraught_UtilityQuality", 0));
				}
			}
			return num;
		}

		private static void RecordHandQualities(VisEquipment equipment, ItemData rightHand, ItemData leftHand, ItemData leftBack, ItemData rightBack)
		{
			if (!((Object)(object)equipment == (Object)null))
			{
				object? obj = VisEquipmentNetViewField?.GetValue(equipment);
				ZNetView val = (ZNetView)((obj is ZNetView) ? obj : null);
				ZDO val2 = ((val != null) ? val.GetZDO() : null);
				if (val2 != null && val.IsOwner())
				{
					val2.Set("PotentialDraught_LeftHandQuality", leftHand?.m_quality ?? 0);
					val2.Set("PotentialDraught_RightHandQuality", rightHand?.m_quality ?? 0);
					val2.Set("PotentialDraught_LeftBackQuality", leftBack?.m_quality ?? 0);
					val2.Set("PotentialDraught_RightBackQuality", rightBack?.m_quality ?? 0);
				}
			}
		}

		private static int ResolveEquipmentQuality(VisEquipment equipment, int itemHash, int originalQuality)
		{
			int num = ResolveArmorQuality(equipment, itemHash, originalQuality);
			ZDO equipmentZdo = GetEquipmentZdo(equipment);
			if (equipmentZdo == null || itemHash == 0)
			{
				return num;
			}
			if (equipmentZdo.GetInt(ZDOVars.s_leftItem, 0) == itemHash)
			{
				num = Mathf.Max(num, equipmentZdo.GetInt("PotentialDraught_LeftHandQuality", equipmentZdo.GetInt(ZDOVars.s_leftItemQuality, 0)));
			}
			if (equipmentZdo.GetInt(ZDOVars.s_rightItem, 0) == itemHash)
			{
				num = Mathf.Max(num, equipmentZdo.GetInt("PotentialDraught_RightHandQuality", equipmentZdo.GetInt(ZDOVars.s_rightItemQuality, 0)));
			}
			if (equipmentZdo.GetInt(ZDOVars.s_leftBackItem, 0) == itemHash)
			{
				num = Mathf.Max(num, equipmentZdo.GetInt("PotentialDraught_LeftBackQuality", equipmentZdo.GetInt(ZDOVars.s_leftBackItemQuality, 0)));
			}
			if (equipmentZdo.GetInt(ZDOVars.s_rightBackItem, 0) == itemHash)
			{
				num = Mathf.Max(num, equipmentZdo.GetInt("PotentialDraught_RightBackQuality", equipmentZdo.GetInt(ZDOVars.s_rightBackItemQuality, 0)));
			}
			return num;
		}

		private static bool HasPotionEffect(Player player)
		{
			if ((Object)(object)player != (Object)null)
			{
				CustomStatusEffect potentialStatusEffect = PotentialStatusEffect;
				if ((Object)(object)((potentialStatusEffect != null) ? potentialStatusEffect.StatusEffect : null) != (Object)null)
				{
					return ((Character)player).GetSEMan().HaveStatusEffect(PotentialStatusEffect.StatusEffect.NameHash());
				}
			}
			return false;
		}

		private static bool HasAdminPotionEffect(Player player)
		{
			if ((Object)(object)player != (Object)null)
			{
				CustomStatusEffect adminPotentialStatusEffect = AdminPotentialStatusEffect;
				if ((Object)(object)((adminPotentialStatusEffect != null) ? adminPotentialStatusEffect.StatusEffect : null) != (Object)null)
				{
					return ((Character)player).GetSEMan().HaveStatusEffect(AdminPotentialStatusEffect.StatusEffect.NameHash());
				}
			}
			return false;
		}

		private static bool IsAdminPotionItem(ItemData item)
		{
			if (item?.m_shared == null)
			{
				return false;
			}
			if ((Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name == "PotionPotentialDraughtAdmin")
			{
				return true;
			}
			CustomStatusEffect adminPotentialStatusEffect = AdminPotentialStatusEffect;
			if ((Object)(object)((adminPotentialStatusEffect != null) ? adminPotentialStatusEffect.StatusEffect : null) != (Object)null)
			{
				return (Object)(object)item.m_shared.m_consumeStatusEffect == (Object)(object)AdminPotentialStatusEffect.StatusEffect;
			}
			return false;
		}

		private Sprite LoadEmbeddedIcon()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PotentialDraught.Assets.potential_draught_icon.png");
			if (stream == null)
			{
				throw new FileNotFoundException("Embedded icon resource not found: PotentialDraught.Assets.potential_draught_icon.png");
			}
			byte[] array = new byte[stream.Length];
			int num;
			for (int i = 0; i < array.Length; i += num)
			{
				num = stream.Read(array, i, array.Length - i);
				if (num == 0)
				{
					break;
				}
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false)
			{
				name = "PotentialDraughtIcon",
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			if (!ImageConversion.LoadImage(val, array, false))
			{
				throw new InvalidDataException("Could not decode the embedded potion icon.");
			}
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
		}

		private static void RegisterAdminPotionRpcs()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null && instance != _registeredAdminPotionRpcInstance)
			{
				instance.Register<long>("PotentialDraught_RequestAdminPotionPurge", (Action<long, long>)RPC_RequestAdminPotionPurge);
				instance.Register<long>("PotentialDraught_ExecuteAdminPotionPurge", (Action<long, long>)RPC_ExecuteAdminPotionPurge);
				instance.Register<long>("PotentialDraught_RequestAdminPotionPermission", (Action<long, long>)RPC_RequestAdminPotionPermission);
				instance.Register<long, string, bool>("PotentialDraught_SetAdminPotionPermission", (Action<long, long, string, bool>)RPC_SetAdminPotionPermission);
				instance.Register<long, bool>("PotentialDraught_SyncAdminPotionPermission", (Action<long, long, bool>)RPC_SyncAdminPotionPermission);
				instance.Register<long, string>("PotentialDraught_AdminPotionCommandResult", (Action<long, long, string>)RPC_AdminPotionCommandResult);
				_registeredAdminPotionRpcInstance = instance;
			}
		}

		private static IEnumerator AdminPotionPermissionServerReceive(long sender, ZPackage package)
		{
			if (package != null && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
			{
				byte b = package.ReadByte();
				switch (b)
				{
				case 1:
					RPC_RequestAdminPotionPermission(sender, package.ReadLong());
					break;
				case 2:
					RPC_SetAdminPotionPermission(sender, package.ReadLong(), package.ReadString(), package.ReadBool());
					break;
				case 5:
					SetMaximumItemQualityOnServer(sender, package.ReadLong(), package.ReadInt());
					break;
				case 7:
					ExecuteAdminPotionPurgeOnServer(sender, package.ReadLong());
					break;
				default:
					((BaseUnityPlugin)Instance).Logger.LogWarning((object)$"Ignored unknown admin-potion server message {b} from {sender}.");
					break;
				}
				yield return null;
			}
		}

		private static IEnumerator AdminPotionPermissionClientReceive(long sender, ZPackage package)
		{
			if (package == null)
			{
				yield break;
			}
			byte b = package.ReadByte();
			switch (b)
			{
			case 3:
				RPC_SyncAdminPotionPermission(sender, package.ReadLong(), package.ReadBool());
				break;
			case 4:
				RPC_AdminPotionCommandResult(sender, package.ReadLong(), package.ReadString());
				break;
			case 6:
			{
				long num = package.ReadLong();
				int num2 = package.ReadInt();
				if ((Object)(object)Player.m_localPlayer != (Object)null && (num == 0L || Player.m_localPlayer.GetPlayerID() == num))
				{
					_synchronizedMaximumItemQuality = Mathf.Max(1, num2);
					((BaseUnityPlugin)Instance).Logger.LogInfo((object)$"Synchronized Forge maximum item quality: {_synchronizedMaximumItemQuality}.");
				}
				break;
			}
			case 8:
				RemoveAdminPotionsFromLocalPlayer(package.ReadLong());
				break;
			default:
				((BaseUnityPlugin)Instance).Logger.LogWarning((object)$"Ignored unknown admin-potion client message {b} from {sender}.");
				break;
			}
			yield return null;
		}

		private static void SendAdminPotionRequestToServer(ZPackage package)
		{
			if (_adminPotionPermissionRpc != null && ZRoutedRpc.instance != null)
			{
				long serverPeerUid = GetServerPeerUid();
				((BaseUnityPlugin)Instance).Logger.LogDebug((object)$"Sending admin-potion request to routed server peer {serverPeerUid}.");
				_adminPotionPermissionRpc.SendPackage(serverPeerUid, package);
			}
		}

		private static void BroadcastAdminPotionPackage(ZPackage package)
		{
			if (_adminPotionPermissionRpc != null && !((Object)(object)ZNet.instance == (Object)null))
			{
				_adminPotionPermissionRpc.SendPackage(new List<ZNetPeer>(ZNet.instance.GetConnectedPeers()), package);
			}
		}

		private static void SendAdminPotionPermissionSync(long playerId, bool allowed)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write((byte)3);
			val.Write(playerId);
			val.Write(allowed);
			BroadcastAdminPotionPackage(val);
			if ((Object)(object)Player.m_localPlayer != (Object)null && Player.m_localPlayer.GetPlayerID() == playerId)
			{
				_localAdminPotionUseAllowed = allowed;
			}
		}

		private static void SendMaximumItemQualitySync(long targetPlayerId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write((byte)6);
			val.Write(targetPlayerId);
			val.Write(MaximumItemQuality);
			BroadcastAdminPotionPackage(val);
		}

		private static int RemoveAdminPotionsFromLocalPlayer(long requestingPlayerId)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || localPlayer.GetPlayerID() == requestingPlayerId)
			{
				return 0;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			if (inventory == null)
			{
				return 0;
			}
			int num = RemoveAdminPotionItems(inventory);
			if (num > 0)
			{
				((Character)localPlayer).Message((MessageType)2, $"An administrator removed {num} Absolute Potential potion" + ((num == 1) ? string.Empty : "s") + " from your inventory.", 0, (Sprite)null, false);
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)$"Removed {num} admin potion(s) from local player '{localPlayer.GetPlayerName()}'.");
			}
			return num;
		}

		private static int RemoveAdminPotionItems(Inventory inventory)
		{
			if (inventory == null)
			{
				return 0;
			}
			List<ItemData> list = new List<ItemData>(inventory.GetAllItems());
			int num = 0;
			foreach (ItemData item in list)
			{
				if (IsAdminPotionItem(item))
				{
					num += Mathf.Max(1, item.m_stack);
					inventory.RemoveItem(item);
				}
			}
			return num;
		}

		private static int PurgeAdminPotionsFromWorldStorage()
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			int num = 0;
			Container[] array = Object.FindObjectsOfType<Container>();
			foreach (Container val in array)
			{
				int num2 = RemoveAdminPotionItems(val.GetInventory());
				if (num2 > 0)
				{
					num += num2;
					ContainerSaveMethod?.Invoke(val, null);
				}
			}
			if (!(ZdoObjectsByIdField?.GetValue(ZDOMan.instance) is IDictionary dictionary))
			{
				return num;
			}
			foreach (object value in dictionary.Values)
			{
				ZDO val2 = (ZDO)((value is ZDO) ? value : null);
				if (val2 == null)
				{
					continue;
				}
				string text = val2.GetString(ZDOVars.s_items, string.Empty);
				if (string.IsNullOrEmpty(text))
				{
					continue;
				}
				try
				{
					Inventory val3 = new Inventory("PotentialDraught_Purge", (Sprite)null, 8, 100);
					val3.Load(new ZPackage(text));
					int num3 = RemoveAdminPotionItems(val3);
					if (num3 > 0)
					{
						ZPackage val4 = new ZPackage();
						val3.Save(val4);
						val2.Set(ZDOVars.s_items, val4.GetBase64());
						num += num3;
					}
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)Instance).Logger.LogWarning((object)("Could not inspect a stored world inventory during admin-potion purge: " + ex.Message));
				}
			}
			return num;
		}

		private static void ExecuteAdminPotionPurgeOnServer(long sender, long requestingPlayerId)
		{
			//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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return;
			}
			if (!IsAdminOrHostPeer(sender, requestingPlayerId))
			{
				SendAdminPotionCommandResult(requestingPlayerId, "The server rejected the purge: host or administrator access is required.");
				return;
			}
			int num = 0;
			foreach (ZNetPeer connectedPeer in ZNet.instance.GetConnectedPeers())
			{
				if (connectedPeer != null && connectedPeer.m_playerID != requestingPlayerId)
				{
					num++;
				}
			}
			if ((Object)(object)Player.m_localPlayer != (Object)null && Player.m_localPlayer.GetPlayerID() != requestingPlayerId)
			{
				num++;
			}
			RemoveAdminPotionsFromLocalPlayer(requestingPlayerId);
			int num2 = PurgeAdminPotionsFromWorldStorage();
			ZPackage val = new ZPackage();
			val.Write((byte)8);
			val.Write(requestingPlayerId);
			BroadcastAdminPotionPackage(val);
			SendAdminPotionCommandResult(requestingPlayerId, $"Purge complete: removed {num2} admin potion" + ((num2 == 1) ? string.Empty : "s") + " from world storage and delivered the inventory purge to " + string.Format("{0} other connected player{1}.", num, (num == 1) ? string.Empty : "s"));
		}

		private static void SetMaximumItemQualityOnServer(long sender, long requestingPlayerId, int requestedQuality)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
			{
				if (!IsAdminOrHostPeer(sender, requestingPlayerId))
				{
					SendAdminPotionCommandResult(requestingPlayerId, "The server rejected the command: host or administrator access is required.");
					return;
				}
				if (requestedQuality < 1)
				{
					SendAdminPotionCommandResult(requestingPlayerId, "Maximum item quality must be a positive whole number.");
					return;
				}
				_maximumItemQualityConfig.Value = requestedQuality;
				((BaseUnityPlugin)Instance).Config.Save();
				SendMaximumItemQualitySync(0L);
				SendAdminPotionCommandResult(requestingPlayerId, $"Maximum item quality is now {requestedQuality}. Creature scaling will adjust automatically.");
			}
		}

		private static void LoadAllowedAdminPotionPlayerIdentities()
		{
			AllowedAdminPotionPlayerIdentities.Clear();
			string text = _allowedAdminPotionPlayerIdentitiesConfig?.Value;
			if (string.IsNullOrWhiteSpace(text))
			{
				return;
			}
			string[] array = text.Split('|');
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (!string.IsNullOrEmpty(text2))
				{
					AllowedAdminPotionPlayerIdentities.Add(text2);
				}
			}
		}

		private static void SaveAllowedAdminPotionPlayerIdentities()
		{
			List<string> list = new List<string>();
			foreach (string allowedAdminPotionPlayerIdentity in AllowedAdminPotionPlayerIdentities)
			{
				list.Add(allowedAdminPotionPlayerIdentity);
			}
			list.Sort(StringComparer.OrdinalIgnoreCase);
			_allowedAdminPotionPlayerIdentitiesConfig.Value = string.Join("|", list.ToArray());
			((BaseUnityPlugin)Instance).Config.Save();
		}

		private unsafe static string GetPeerIdentity(ZNetPeer peer)
		{
			if (peer == null)
			{
				return string.Empty;
			}
			if (TryGetPeerPlatformUserId(peer, out var platformUserId))
			{
				return ((object)(*(PlatformUserID*)(&platformUserId))/*cast due to .constrained prefix*/).ToString();
			}
			object? obj = ZNetPeerSocketField?.GetValue(peer);
			object? obj2 = ((obj is ISocket) ? obj : null);
			string text = ((obj2 == null) ? null : ((ISocket)obj2).GetHostName()?.Trim());
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			if (!string.IsNullOrWhiteSpace(peer.m_playfabId))
			{
				return "playfab:" + peer.m_playfabId.Trim();
			}
			if (peer.m_uid == 0L)
			{
				return string.Empty;
			}
			return "peer:" + peer.m_uid;
		}

		private static bool TryGetPeerPlatformUserId(ZNetPeer peer, out PlatformUserID platformUserId)
		{
			//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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			platformUserId = PlatformUserID.None;
			ISocket obj = peer?.m_socket;
			ZPlayFabSocket val = (ZPlayFabSocket)(object)((obj is ZPlayFabSocket) ? obj : null);
			if (val == null || PlayFabSocketPlatformUserIdField == null)
			{
				return false;
			}
			if (!(PlayFabSocketPlatformUserIdField.GetValue(val) is PlatformUserID val2) || !((PlatformUserID)(ref val2)).IsValid)
			{
				return false;
			}
			platformUserId = val2;
			return true;
		}

		private static long GetServerPeerUid()
		{
			if (ZRoutedRpc.instance != null && RoutedRpcGetServerPeerIdMethod != null && RoutedRpcGetServerPeerIdMethod.Invoke(ZRoutedRpc.instance, null) is long num && num != 0L)
			{
				return num;
			}
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return 0L;
			}
			if (ZNet.instance.IsServer())
			{
				return ZNet.GetUID();
			}
			return ZNet.instance.GetServerPeer()?.m_uid ?? 0;
		}

		private static ZNetPeer FindPeerByPlayerId(long playerId)
		{
			if ((Object)(object)ZNet.instance == (Object)null || playerId == 0L)
			{
				return null;
			}
			foreach (ZNetPeer connectedPeer in ZNet.instance.GetConnectedPeers())
			{
				if (connectedPeer != null && connectedPeer.m_playerID == playerId)
				{
					return connectedPeer;
				}
			}
			return null;
		}

		private static bool IsAdminOrHostPeer(long sender, long playerId = 0L)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return false;
			}
			if (sender == ZNet.GetUID() || sender == GetServerPeerUid())
			{
				return true;
			}
			if ((Object)(object)Player.m_localPlayer != (Object)null && Player.m_localPlayer.GetPlayerID() == playerId)
			{
				return true;
			}
			ZNetPeer val = ZNet.instance.GetPeer(sender) ?? FindPeerByPlayerId(playerId);
			if (TryGetPeerPlatformUserId(val, out var platformUserId) && ZNet.instance.PlayerIsAdmin(platformUserId))
			{
				return true;
			}
			object? obj = ZNetPeerSocketField?.GetValue(val);
			ISocket val2 = (ISocket)((obj is ISocket) ? obj : null);
			if (val2 != null)
			{
				return ZNet.instance.IsAdmin(val2.GetHostName());
			}
			return false;
		}

		private static bool IsAdminPotionAllowed(long sender, long playerId)
		{
			if (IsAdminOrHostPeer(sender, playerId))
			{
				return true;
			}
			ZNet instance = ZNet.instance;
			string peerIdentity = GetPeerIdentity(((instance != null) ? instance.GetPeer(sender) : null) ?? FindPeerByPlayerId(playerId));
			if (!string.IsNullOrEmpty(peerIdentity))
			{
				return AllowedAdminPotionPlayerIdentities.Contains(peerIdentity);
			}
			return false;
		}

		private static void RPC_RequestAdminPotionPurge(long sender, long requestingPlayerId)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && ZRoutedRpc.instance != null)
			{
				if (!IsAdminOrHostPeer(sender, requestingPlayerId))
				{
					((BaseUnityPlugin)Instance).Logger.LogWarning((object)$"Rejected unauthorized admin-potion purge request from routed peer {sender}.");
					return;
				}
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "PotentialDr