Decompiled source of OdinsBelt v0.2.5

BepInEx/plugins/OdinsBelt/OdinsBelt.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using SailingProgression;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("OdinsBelt")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.5.0")]
[assembly: AssemblyInformationalVersion("0.2.5")]
[assembly: AssemblyProduct("OdinsBelt")]
[assembly: AssemblyTitle("OdinsBelt")]
[assembly: AssemblyVersion("0.2.5.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 SailingProgression
{
	public static class TailwindVisuals
	{
		private static Material bronze;

		private static Material leather;

		private static Material dark;

		private static Material wind;

		public static void Apply(GameObject prefab, bool charm)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			SharedData shared = prefab.GetComponent<ItemDrop>().m_itemData.m_shared;
			using (Stream stream = typeof(TailwindVisuals).Assembly.GetManifestResourceStream("TailwindGear." + (charm ? "charm" : "belt") + ".png"))
			{
				using MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				Texture2D val = new Texture2D(2, 2);
				AssetUtils.LoadImage(val, memoryStream.ToArray());
				shared.m_icons = (Sprite[])(object)new Sprite[1] { Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)) };
			}
			Materials(prefab);
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].enabled = false;
			}
			LODGroup[] componentsInChildren2 = prefab.GetComponentsInChildren<LODGroup>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			Collider[] componentsInChildren3 = prefab.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
			}
			Transform val2 = prefab.transform.Find("attach");
			if (Object.op_Implicit((Object)(object)val2))
			{
				Object.DestroyImmediate((Object)(object)((Component)val2).gameObject);
			}
			Transform transform = new GameObject("attach").transform;
			transform.SetParent(prefab.transform, false);
			if (charm)
			{
				Charm(transform);
			}
			else
			{
				Belt(transform);
			}
			Bounds val3 = default(Bounds);
			((Bounds)(ref val3))..ctor(Vector3.zero, Vector3.zero);
			bool flag = true;
			MeshFilter[] componentsInChildren4 = ((Component)transform).GetComponentsInChildren<MeshFilter>();
			foreach (MeshFilter val4 in componentsInChildren4)
			{
				Vector3[] vertices = val4.sharedMesh.vertices;
				foreach (Vector3 val5 in vertices)
				{
					Vector3 val6 = prefab.transform.InverseTransformPoint(((Component)val4).transform.TransformPoint(val5));
					if (flag)
					{
						((Bounds)(ref val3))..ctor(val6, Vector3.zero);
						flag = false;
					}
					else
					{
						((Bounds)(ref val3)).Encapsulate(val6);
					}
				}
			}
			BoxCollider obj = prefab.AddComponent<BoxCollider>();
			obj.center = ((Bounds)(ref val3)).center;
			obj.size = ((Bounds)(ref val3)).size + Vector3.one * 0.008f;
			shared.m_weight = (charm ? 0.5f : 1f);
		}

		private static void Materials(GameObject prefab)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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_014e: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)bronze))
			{
				return;
			}
			Material val = null;
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material[] sharedMaterials = componentsInChildren[i].sharedMaterials;
				foreach (Material val2 in sharedMaterials)
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						val = val2;
						break;
					}
				}
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				Material[] sharedMaterials = Resources.FindObjectsOfTypeAll<Material>();
				foreach (Material val3 in sharedMaterials)
				{
					if (Object.op_Implicit((Object)(object)val3))
					{
						val = val3;
						break;
					}
				}
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new InvalidOperationException("No native item material available.");
			}
			bronze = Material(val, new Color(0.61f, 0.4f, 0.15f), 0.65f);
			leather = Material(val, new Color(0.22f, 0.105f, 0.045f), 0f);
			dark = Material(val, new Color(0.13f, 0.14f, 0.12f), 0.3f);
			wind = Material(val, new Color(0.12f, 0.78f, 0.8f), 0.25f);
			wind.EnableKeyword("_EMISSION");
			wind.SetColor("_EmissionColor", new Color(0.035f, 0.35f, 0.4f));
		}

		private static Material Material(Material source, Color color, float metal)
		{
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			Material val = new Material(source)
			{
				mainTexture = (Texture)(object)Texture2D.whiteTexture,
				color = color
			};
			val.SetFloat("_Metallic", metal);
			val.SetFloat("_Glossiness", 0.3f);
			return val;
		}

		private static GameObject MeshObject(Transform parent, string name, Vector3[] vertices, int[] triangles, Material material)
		{
			//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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			Mesh val2 = new Mesh
			{
				name = name
			};
			val2.vertices = vertices;
			val2.triangles = triangles;
			val2.RecalculateNormals();
			val2.RecalculateBounds();
			val.AddComponent<MeshFilter>().sharedMesh = val2;
			((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterial = material;
			return val;
		}

		private static GameObject Ring(Transform parent, string name, float radius, float width, float depth, Material material, int segments = 32)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] array = (Vector3[])(object)new Vector3[segments * 4];
			List<int> list = new List<int>();
			Vector2 val = default(Vector2);
			for (int i = 0; i < segments; i++)
			{
				float num = (float)i * (float)Math.PI * 2f / (float)segments;
				((Vector2)(ref val))..ctor(Mathf.Sin(num), Mathf.Cos(num));
				array[i * 4] = new Vector3(val.x * (radius - width / 2f), val.y * (radius - width / 2f), (0f - depth) / 2f);
				array[i * 4 + 1] = new Vector3(val.x * (radius + width / 2f), val.y * (radius + width / 2f), (0f - depth) / 2f);
				array[i * 4 + 2] = new Vector3(val.x * (radius - width / 2f), val.y * (radius - width / 2f), depth / 2f);
				array[i * 4 + 3] = new Vector3(val.x * (radius + width / 2f), val.y * (radius + width / 2f), depth / 2f);
				int num2 = (i + 1) % segments * 4;
				int num3 = i * 4;
				Quad(list, num3, num3 + 1, num2 + 1, num2);
				Quad(list, num3 + 2, num2 + 2, num2 + 3, num3 + 3);
				Quad(list, num3, num2, num2 + 2, num3 + 2);
				Quad(list, num3 + 1, num3 + 3, num2 + 3, num2 + 1);
			}
			return MeshObject(parent, name, array, list.ToArray(), material);
		}

		private static void Quad(List<int> t, int a, int b, int c, int d)
		{
			t.AddRange(new int[6] { a, b, c, a, c, d });
		}

		private static void Bar(Transform p, string name, Vector3 a, Vector3 b, float width, float thickness, Material m)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_007a: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = b - a;
			Vector3 val2 = new Vector3(0f - val.y, val.x, 0f);
			Vector3 val3 = ((Vector3)(ref val2)).normalized * width / 2f;
			Vector3[] vertices = (Vector3[])(object)new Vector3[8]
			{
				a + val3,
				a - val3,
				b - val3,
				b + val3,
				a + val3 + Vector3.forward * thickness,
				a - val3 + Vector3.forward * thickness,
				b - val3 + Vector3.forward * thickness,
				b + val3 + Vector3.forward * thickness
			};
			List<int> list = new List<int>();
			Quad(list, 0, 3, 2, 1);
			Quad(list, 4, 5, 6, 7);
			Quad(list, 0, 1, 5, 4);
			Quad(list, 1, 2, 6, 5);
			Quad(list, 2, 3, 7, 6);
			Quad(list, 3, 0, 4, 7);
			MeshObject(p, name, vertices, list.ToArray(), m);
		}

		private static void Gem(Transform p, string name, Vector3 center, float radius, Material m)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0069: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] vertices = (Vector3[])(object)new Vector3[6]
			{
				center + Vector3.forward * radius,
				center - Vector3.forward * radius,
				center + Vector3.up * radius,
				center - Vector3.up * radius,
				center + Vector3.right * radius,
				center - Vector3.right * radius
			};
			MeshObject(p, name, vertices, new int[24]
			{
				0, 4, 2, 0, 3, 4, 0, 5, 3, 0,
				2, 5, 1, 2, 4, 1, 4, 3, 1, 3,
				5, 1, 5, 2
			}, m);
		}

		private static void Ship(Transform p, float scale, float y, float z)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			Bar(p, "Dragonship keel", V(-0.055f, -0.028f), V(0.055f, -0.028f), 0.01f * scale, 0.006f, bronze);
			Bar(p, "Raised prow", V(-0.055f, -0.028f), V(-0.07f, 0.005f), 0.012f * scale, 0.006f, bronze);
			Bar(p, "Raised stern", V(0.055f, -0.028f), V(0.064f, -0.003f), 0.009f * scale, 0.006f, bronze);
			Bar(p, "Mast", V(0f, -0.022f), V(0f, 0.052f), 0.009f * scale, 0.008f, bronze);
			MeshObject(p, "Curved sail", (Vector3[])(object)new Vector3[4]
			{
				V(0.006f, 0.045f),
				V(0.047f, 0.036f),
				V(0.054f, 0.001f),
				V(0.007f, 0.002f)
			}, new int[12]
			{
				0, 1, 2, 0, 2, 3, 2, 1, 0, 3,
				2, 0
			}, bronze);
			Vector3 V(float x, float yy)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				return new Vector3(x * scale, yy * scale + y, z);
			}
		}

		private static void Wind(Transform p, float radius, float z)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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)
			for (int i = 0; i < 3; i++)
			{
				Vector3[] array = (Vector3[])(object)new Vector3[14];
				for (int j = 0; j < array.Length; j++)
				{
					float num = (float)j / (float)(array.Length - 1) * 1.7f + (float)i * 2.1f;
					float num2 = radius * (0.8f + 0.13f * Mathf.Sin((float)j * 0.8f));
					array[j] = new Vector3(Mathf.Sin(num) * num2, Mathf.Cos(num) * num2, z);
				}
				for (int k = 1; k < array.Length; k++)
				{
					Bar(p, "Turquoise wind", array[k - 1], array[k], 0.004f, 0.002f, wind);
				}
			}
		}

		private static void Charm(Transform p)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			Ring(p, "Bronze pendant", 0.095f, 0.016f, 0.013f, bronze);
			Ring(p, "Dark inner band", 0.078f, 0.006f, 0.01f, dark);
			Ring(p, "Suspension ring", 0.016f, 0.007f, 0.012f, bronze, 12).transform.localPosition = new Vector3(0f, 0.115f, 0f);
			Bar(p, "Leather cord left", new Vector3(-0.025f, 0.127f, 0f), new Vector3(-0.065f, 0.23f, 0f), 0.009f, 0.007f, leather);
			Bar(p, "Leather cord right", new Vector3(0.025f, 0.127f, 0f), new Vector3(0.065f, 0.23f, 0f), 0.009f, 0.007f, leather);
			Gem(p, "Wind stone", new Vector3(0f, 0.025f, -0.012f), 0.023f, wind);
			Ship(p, 1f, -0.039f, -0.015f);
			Wind(p, 0.069f, -0.023f);
			for (int i = 0; i < 12; i++)
			{
				float num = (float)i * (float)Math.PI / 6f;
				Gem(p, "Bronze rivet", new Vector3(Mathf.Sin(num) * 0.096f, Mathf.Cos(num) * 0.096f, -0.012f), 0.005f, bronze);
			}
		}

		private static void Belt(Transform p)
		{
			//IL_0035: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			Ring(p, "Leather belt", 0.16f, 0.012f, 0.067f, leather, 40).transform.localRotation = Quaternion.Euler(90f, 0f, 0f);
			Transform transform = new GameObject("Ship buckle").transform;
			transform.SetParent(p, false);
			transform.localPosition = new Vector3(0f, 0f, -0.168f);
			Ring(transform, "Bronze buckle rim", 0.063f, 0.012f, 0.014f, bronze, 24);
			Ring(transform, "Buckle inner rim", 0.049f, 0.006f, 0.009f, dark, 24);
			Ship(transform, 0.75f, 0.006f, -0.011f);
			Wind(transform, 0.052f, -0.021f);
			Gem(transform, "Turquoise buckle stone", new Vector3(0f, -0.046f, -0.015f), 0.012f, wind);
			Vector3 localPosition = default(Vector3);
			for (int i = 0; i < 20; i++)
			{
				float num = (float)i * (float)Math.PI / 10f;
				((Vector3)(ref localPosition))..ctor(Mathf.Sin(num) * 0.168f, 0f, Mathf.Cos(num) * 0.168f);
				Transform transform2 = new GameObject("Bronze belt detail").transform;
				transform2.SetParent(p, false);
				transform2.localPosition = localPosition;
				transform2.localRotation = Quaternion.Euler(0f, num * 57.29578f, 0f);
				Bar(transform2, "Stamped knot", new Vector3(-0.008f, -0.024f, 0f), new Vector3(0.008f, 0.024f, 0f), 0.003f, 0.003f, bronze);
				Bar(transform2, "Stamped knot", new Vector3(0.008f, -0.024f, 0f), new Vector3(-0.008f, 0.024f, 0f), 0.003f, 0.003f, bronze);
			}
		}

		public static GameObject CreateLeatherBand(Transform parent, float radius, float thickness, float height, Material material)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Ring(parent, "Leather belt", radius, thickness, height, material, 40);
			obj.transform.localRotation = Quaternion.Euler(90f, 0f, 0f);
			return obj;
		}
	}
}
namespace UtilityBelt
{
	internal static class BeltDragAndDrop
	{
		[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
		private static class DropIntoInventory
		{
			private static bool Prefix(InventoryGrid grid, Vector2i pos)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return DropTo(grid, pos);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "OnReleasedItem")]
		private static class Release
		{
			private static bool Prefix(InventoryGrid grid, Vector2i pos)
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				if (!Holding)
				{
					return true;
				}
				if (!Object.op_Implicit((Object)(object)grid))
				{
					Cancel();
					return false;
				}
				return DropTo(grid, pos);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "OnDropOutside")]
		private static class PreventPreviewWorldDrop
		{
			private static bool Prefix()
			{
				if (!Holding)
				{
					return true;
				}
				Cancel();
				return false;
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "SetupDragItem")]
		private static class ResetCursor
		{
			private static void Postfix(InventoryGui __instance, ItemData item)
			{
				if (item == null)
				{
					origin = -1;
				}
				else if (BeltUI.Open)
				{
					object? value = AccessTools.Field(typeof(InventoryGui), "m_dragGo").GetValue(__instance);
					GameObject val = (GameObject)((value is GameObject) ? value : null);
					if (Object.op_Implicit((Object)(object)val))
					{
						Canvas obj = val.GetComponent<Canvas>() ?? val.AddComponent<Canvas>();
						obj.overrideSorting = true;
						obj.sortingOrder = GUIManager.CustomGUIFront.GetComponent<Canvas>().sortingOrder + 1;
						(val.GetComponent<CanvasGroup>() ?? val.AddComponent<CanvasGroup>()).blocksRaycasts = false;
					}
				}
			}
		}

		private static int origin = -1;

		private static int destinationSlot = -1;

		private static long revision;

		private static Vector2i destination;

		internal static bool Holding => origin >= 0;

		internal static int Origin => origin;

		internal static bool Begin(int slot)
		{
			Player localPlayer = Player.m_localPlayer;
			InventoryGui instance = InventoryGui.instance;
			BeltInventory beltInventory = (Object.op_Implicit((Object)(object)localPlayer) ? BeltNetwork.Selected(localPlayer) : null);
			if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)instance) || !BeltUI.Open || BeltNetwork.Busy || Holding || beltInventory?.Get(slot) == null)
			{
				return false;
			}
			if (AccessTools.Field(typeof(InventoryGui), "m_dragItem").GetValue(instance) != null)
			{
				return false;
			}
			origin = slot;
			revision = beltInventory.Revision;
			ItemData val = beltInventory.Get(slot).Clone();
			val.m_stack = 1;
			AccessTools.Method(typeof(InventoryGui), "SetupDragItem", (Type[])null, (Type[])null).Invoke(instance, new object[3]
			{
				val,
				((Humanoid)localPlayer).GetInventory(),
				1
			});
			return true;
		}

		internal static void Cancel(bool clearDestination = true)
		{
			bool holding = Holding;
			origin = -1;
			if (clearDestination)
			{
				destinationSlot = -1;
			}
			if (holding && Object.op_Implicit((Object)(object)InventoryGui.instance))
			{
				AccessTools.Method(typeof(InventoryGui), "SetupDragItem", (Type[])null, (Type[])null).Invoke(InventoryGui.instance, new object[3] { null, null, 1 });
			}
		}

		internal static void End(PointerEventData pointer)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (Holding)
			{
				RaycastResult pointerCurrentRaycast = pointer.pointerCurrentRaycast;
				GameObject gameObject = ((RaycastResult)(ref pointerCurrentRaycast)).gameObject;
				InventoryElement val = (Object.op_Implicit((Object)(object)gameObject) ? gameObject.GetComponentInParent<InventoryElement>() : null);
				InventoryGrid val2 = (Object.op_Implicit((Object)(object)gameObject) ? gameObject.GetComponentInParent<InventoryGrid>() : null);
				if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2))
				{
					DropTo(val2, val.Position);
				}
				if (Holding)
				{
					Cancel();
				}
			}
		}

		private static bool DropTo(InventoryGrid grid, Vector2i pos)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			if (!Holding)
			{
				return true;
			}
			Player localPlayer = Player.m_localPlayer;
			BeltInventory beltInventory = (Object.op_Implicit((Object)(object)localPlayer) ? BeltNetwork.Selected(localPlayer) : null);
			if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)grid) || grid.GetInventory() != ((Humanoid)localPlayer).GetInventory())
			{
				BeltNetwork.LastMessage = "Drag the item to your inventory.";
				return false;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			if (pos.x < 0 || pos.y < 0 || pos.x >= inventory.GetWidth() || pos.y >= inventory.GetHeight() || inventory.GetItemAt(pos.x, pos.y) != null)
			{
				BeltNetwork.LastMessage = "Drop it into an empty inventory slot.";
				return false;
			}
			if (beltInventory == null || beltInventory.Revision != revision || beltInventory.Get(origin) == null)
			{
				Cancel();
				BeltNetwork.LastMessage = "The belt changed. Pick the item up again.";
				return false;
			}
			int slot = (destinationSlot = origin);
			destination = pos;
			if (BeltNetwork.Request(2, slot))
			{
				Cancel(clearDestination: false);
			}
			else
			{
				destinationSlot = -1;
			}
			return false;
		}

		internal static void TransferFinished(int action, int slot, ItemData? delivered)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if (action != 2 || destinationSlot != slot)
			{
				return;
			}
			destinationSlot = -1;
			Player localPlayer = Player.m_localPlayer;
			if (delivered != null && Object.op_Implicit((Object)(object)localPlayer))
			{
				Inventory inventory = ((Humanoid)localPlayer).GetInventory();
				if (inventory.GetItemAt(destination.x, destination.y) == null)
				{
					delivered.m_gridPos = destination;
					AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null).Invoke(inventory, new object[2] { true, false });
				}
			}
		}
	}
	public sealed class BeltInventory
	{
		public const int UtilityCount = 10;

		public const int KeyCount = 10;

		public const int KeyStart = 11;

		public const int VisibleCapacity = 21;

		public const int Capacity = 43;

		public readonly Inventory Inventory = new Inventory("Utility Belt", (Sprite)null, 8, 6);

		public long Revision;

		public bool LanternOn = true;

		public int ActiveSlots = 2046;

		public string LastTransaction = "";

		public string LastReceipt = "";

		public bool NativeEquipped;

		public int OverflowCount => Inventory.GetAllItems().Count((ItemData i) => i.m_gridPos.x + i.m_gridPos.y * 8 >= 21);

		public bool Equipped => NativeEquipped;

		public bool IsActive(int slot)
		{
			if (slot >= 1 && slot <= 10)
			{
				return (ActiveSlots & (1 << slot)) != 0;
			}
			return false;
		}

		public int FindUtility(string prefab, bool activeOnly = false)
		{
			return Enumerable.Range(1, 10).FirstOrDefault(delegate(int s)
			{
				ItemData val = Get(s);
				return val != null && Prefab(val) == prefab && (!activeOnly || IsActive(s));
			});
		}

		public ItemData? Utility(string prefab)
		{
			int num = FindUtility(prefab);
			if (num != 0)
			{
				return Get(num);
			}
			return null;
		}

		public static bool IsUtility(ItemData item)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			if (!Keyring.IsKey(Prefab(item)) && (Prefab(item) == "Lantern" || (int)item.m_shared.m_itemType == 18))
			{
				return Prefab(item) != "OdinsBelt";
			}
			return false;
		}

		public ItemData? Get(int slot)
		{
			return Inventory.GetItemAt(slot % 8, slot / 8);
		}

		public static string Prefab(ItemData item)
		{
			if (!Object.op_Implicit((Object)(object)item.m_dropPrefab))
			{
				return "";
			}
			return ((Object)item.m_dropPrefab).name;
		}

		public static bool ValidSlot(int slot, ItemData item, bool allowSavedTrinket = false)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Invalid comparison between Unknown and I4
			if (slot < 0 || slot >= 43 || item.m_stack != 1 || item.m_quality < 1 || item.m_quality > Math.Max(1, item.m_shared.m_maxQuality))
			{
				return false;
			}
			if (slot != 0)
			{
				if (slot >= 11)
				{
					return Keyring.IsKey(Prefab(item));
				}
				if (!IsUtility(item))
				{
					if (allowSavedTrinket)
					{
						return (int)item.m_shared.m_itemType == 24;
					}
					return false;
				}
				return true;
			}
			return Prefab(item) == "OdinsBelt";
		}

		public bool Put(int slot, ItemData item)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!ValidSlot(slot, item) || Get(slot) != null)
			{
				return false;
			}
			item.m_equipped = false;
			return Inventory.AddItem(item, new Vector2i(slot % 8, slot / 8));
		}

		public string Encode()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			Inventory.Save(val);
			ZPackage val2 = new ZPackage();
			val2.Write(4);
			val2.Write(Revision);
			val2.Write(LanternOn);
			val2.Write(LastTransaction);
			val2.Write(LastReceipt);
			val2.Write(ActiveSlots);
			val2.Write(NativeEquipped);
			val2.Write(Convert.ToBase64String(val.GetArray()));
			return Convert.ToBase64String(val2.GetArray());
		}

		public static BeltInventory Decode(string encoded)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			BeltInventory beltInventory = new BeltInventory();
			if (string.IsNullOrEmpty(encoded))
			{
				return beltInventory;
			}
			if (encoded.Length > 262144)
			{
				throw new ArgumentException("Belt save exceeds limit");
			}
			ZPackage val = new ZPackage(Convert.FromBase64String(encoded));
			int num = val.ReadInt();
			if (num < 1 || num > 4)
			{
				throw new ArgumentException("Unsupported belt save version");
			}
			beltInventory.Revision = val.ReadLong();
			beltInventory.LanternOn = val.ReadBool();
			beltInventory.LastTransaction = val.ReadString();
			beltInventory.LastReceipt = val.ReadString();
			if (num >= 2)
			{
				beltInventory.ActiveSlots = val.ReadInt() & 0x7FE;
			}
			if (num < 4)
			{
				beltInventory.ActiveSlots |= 2016;
				if (!beltInventory.LanternOn)
				{
					beltInventory.ActiveSlots &= -17;
				}
			}
			if (num >= 3)
			{
				beltInventory.NativeEquipped = val.ReadBool();
			}
			beltInventory.Inventory.Load(new ZPackage(Convert.FromBase64String(val.ReadString())));
			if (num < 4)
			{
				ItemData[] array = beltInventory.Inventory.GetAllItems().ToArray();
				beltInventory.Inventory.RemoveAll();
				ItemData[] array2 = array;
				foreach (ItemData val2 in array2)
				{
					int num2 = val2.m_gridPos.x + val2.m_gridPos.y * 8;
					if (num2 >= 5)
					{
						num2 += 6;
					}
					if (!ValidSlot(num2, val2, allowSavedTrinket: true) || !beltInventory.Inventory.AddItem(val2, new Vector2i(num2 % 8, num2 / 8)))
					{
						throw new ArgumentException("Invalid legacy belt item");
					}
				}
			}
			foreach (ItemData allItem in beltInventory.Inventory.GetAllItems())
			{
				if (!ValidSlot(allItem.m_gridPos.x + allItem.m_gridPos.y * 8, allItem, allowSavedTrinket: true))
				{
					throw new ArgumentException("Invalid belt item or slot");
				}
			}
			return beltInventory;
		}

		internal void PromoteSavedKeys()
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			ItemData[] array = (from i in Inventory.GetAllItems()
				where i.m_gridPos.x + i.m_gridPos.y * 8 >= 21
				select i).ToArray();
			foreach (ItemData val in array)
			{
				int num2 = Enumerable.Range(11, 10).FirstOrDefault((int s) => Get(s) == null);
				if (num2 != 0)
				{
					Inventory.RemoveItem(val);
					Inventory.AddItem(val, new Vector2i(num2 % 8, num2 / 8));
					continue;
				}
				break;
			}
		}

		public static string PackItem(ItemData item)
		{
			//IL_0008: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			Inventory val = new Inventory("Transfer", (Sprite)null, 1, 1);
			ItemData val2 = item.Clone();
			val2.m_stack = 1;
			val2.m_equipped = false;
			val.AddItem(val2);
			ZPackage val3 = new ZPackage();
			val.Save(val3);
			return Convert.ToBase64String(val3.GetArray());
		}

		public static ItemData UnpackItem(string value)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			if (value.Length > 65536)
			{
				throw new ArgumentException("Item exceeds limit");
			}
			Inventory val = new Inventory("Transfer", (Sprite)null, 1, 1);
			val.Load(new ZPackage(Convert.FromBase64String(value)));
			if (val.GetAllItems().Count != 1 || val.GetAllItems()[0].m_stack != 1)
			{
				throw new ArgumentException("Invalid item transfer");
			}
			return val.GetAllItems()[0];
		}
	}
	public static class BeltNetwork
	{
		private sealed class Pending
		{
			public int Action;

			public int Slot;

			public long Revision;

			public string BeltId = "";

			public string Transaction = "";

			public string Payload = "";

			public string Receipt = "";

			public bool Acknowledged;

			public string Encode()
			{
				//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_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				ZPackage val = new ZPackage();
				val.Write(Action);
				val.Write(Slot);
				val.Write(Revision);
				val.Write(Transaction);
				val.Write(Payload);
				val.Write(Receipt);
				val.Write(Acknowledged);
				val.Write(BeltId);
				return Convert.ToBase64String(val.GetArray());
			}

			public static Pending Decode(string value)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Expected O, but got Unknown
				ZPackage val = new ZPackage(Convert.FromBase64String(value));
				return new Pending
				{
					Action = val.ReadInt(),
					Slot = val.ReadInt(),
					Revision = val.ReadLong(),
					Transaction = val.ReadString(),
					Payload = val.ReadString(),
					Receipt = val.ReadString(),
					Acknowledged = val.ReadBool(),
					BeltId = ((val.GetPos() < val.GetArray().Length) ? val.ReadString() : "")
				};
			}
		}

		[HarmonyPatch(typeof(Game), "Shutdown")]
		private static class LogoutPolicy
		{
			private static void Prefix()
			{
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				Persistence.Flush();
				if (Plugin.KeepOnLogout.Value)
				{
					return;
				}
				if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer() && Object.op_Implicit((Object)(object)ZNetScene.instance))
				{
					KeyValuePair<long, (long, ZDOID, Vector3)>[] array = Online.ToArray();
					for (int i = 0; i < array.Length; i++)
					{
						KeyValuePair<long, (long, ZDOID, Vector3)> keyValuePair = array[i];
						DropContents(keyValuePair.Key, keyValuePair.Value.Item3);
					}
				}
				Player localPlayer = Player.m_localPlayer;
				if (Object.op_Implicit((Object)(object)localPlayer))
				{
					localPlayer.m_customData["branchofyore.odinsbelt.state"] = new BeltInventory().Encode();
				}
				Persistence.Flush();
			}
		}

		private const string RequestRpc = "branchofyore.odinsbelt.request";

		private const string ReplyRpc = "branchofyore.odinsbelt.reply";

		private const string SnapshotRpc = "branchofyore.odinsbelt.snapshot";

		public const string SaveKey = "branchofyore.odinsbelt.state";

		public const string PendingKey = "branchofyore.odinsbelt.pending";

		private static readonly Dictionary<long, BeltInventory> ServerStates = new Dictionary<long, BeltInventory>();

		private static readonly Dictionary<long, BeltInventory> ClientStates = new Dictionary<long, BeltInventory>();

		private static readonly Dictionary<long, (long peer, ZDOID player, Vector3 position)> Online = new Dictionary<long, (long, ZDOID, Vector3)>();

		private static readonly HashSet<long> Dead = new HashSet<long>();

		private static readonly HashSet<long> Committing = new HashSet<long>();

		private static readonly Dictionary<long, string> RecordOwners = new Dictionary<long, string>();

		private static readonly Dictionary<long, string> SelectedIds = new Dictionary<long, string>();

		private static readonly Dictionary<long, string> ServerSelectedIds = new Dictionary<long, string>();

		private static readonly Dictionary<long, BeltInventory> EquippedStates = new Dictionary<long, BeltInventory>();

		private static readonly Dictionary<string, BeltInventory> Records = new Dictionary<string, BeltInventory>();

		private static readonly Dictionary<long, HashSet<string>> HeldIds = new Dictionary<long, HashSet<string>>();

		private static readonly Dictionary<ItemData, (string blob, BeltInventory state)> DecodedItems = new Dictionary<ItemData, (string, BeltInventory)>();

		private static ItemData? selectedItem;

		private static string synchronizedId = "";

		private static string synchronizedEquipped = "";

		private static string synchronizedHeld = "";

		public const string ItemIdKey = "branchofyore.odinsbelt.belt-id";

		public const string ItemStateKey = "branchofyore.odinsbelt.contents";

		private static ZRoutedRpc? registered;

		private static long world;

		private static float nextSync;

		private static float nextRetry;

		private static Pending? pending;

		private static long localId;

		private static bool awaitingSync;

		private static string syncTransaction = "";

		public static string LastMessage = "";

		public static bool Busy => pending != null;

		public static bool Ready
		{
			get
			{
				if (!awaitingSync && Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					ItemData val = CurrentItem(Player.m_localPlayer);
					if (val != null && SelectedIds.TryGetValue(Player.m_localPlayer.GetPlayerID(), out string value))
					{
						return value == Identity(val);
					}
				}
				return false;
			}
		}

		public static long ServerId
		{
			get
			{
				if (ZRoutedRpc.instance != null)
				{
					return (long)AccessTools.Method(typeof(ZRoutedRpc), "GetServerPeerID", (Type[])null, (Type[])null).Invoke(ZRoutedRpc.instance, null);
				}
				return 0L;
			}
		}

		private static BeltInventory Contents(ItemData item)
		{
			string value;
			string text = (item.m_customData.TryGetValue("branchofyore.odinsbelt.contents", out value) ? value : "");
			if (!DecodedItems.TryGetValue(item, out (string, BeltInventory) value2) || value2.Item1 != text)
			{
				value2 = (text, BeltInventory.Decode(text));
				DecodedItems[item] = value2;
			}
			value2.Item2.NativeEquipped = item.m_equipped;
			return value2.Item2;
		}

		private static string Owned(Player p)
		{
			return string.Join(",", from id in (from i in ((Humanoid)p).GetInventory().GetAllItems()
					where BeltInventory.Prefab(i) == "OdinsBelt"
					select i).Select(Identity).Distinct()
				orderby id
				select id);
		}

		public static string Identity(ItemData item)
		{
			if (!item.m_customData.TryGetValue("branchofyore.odinsbelt.belt-id", out var value) || !Guid.TryParseExact(value, "N", out var _))
			{
				value = (item.m_customData["branchofyore.odinsbelt.belt-id"] = Guid.NewGuid().ToString("N"));
			}
			return value;
		}

		private static ItemData? EquippedItem(Player p)
		{
			return ((IEnumerable<ItemData>)((Humanoid)p).GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => BeltInventory.Prefab(i) == "OdinsBelt" && i.m_equipped));
		}

		private static ItemData? CurrentItem(Player p)
		{
			if (BeltUI.Open && selectedItem != null && ((Humanoid)p).GetInventory().ContainsItem(selectedItem))
			{
				return selectedItem;
			}
			ItemData? obj = EquippedItem(p);
			if (obj == null)
			{
				if (selectedItem == null || !((Humanoid)p).GetInventory().ContainsItem(selectedItem))
				{
					return ((IEnumerable<ItemData>)((Humanoid)p).GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => BeltInventory.Prefab(i) == "OdinsBelt"));
				}
				obj = selectedItem;
			}
			return obj;
		}

		public static void SynchronizeSelected()
		{
			if (registered != null && Object.op_Implicit((Object)(object)Player.m_localPlayer) && !Busy && !Ready)
			{
				SendSync(Player.m_localPlayer);
			}
		}

		public static bool Select(ItemData item)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || Busy || !((Humanoid)localPlayer).GetInventory().ContainsItem(item) || BeltInventory.Prefab(item) != "OdinsBelt")
			{
				return false;
			}
			selectedItem = item;
			Identity(item);
			synchronizedId = "";
			awaitingSync = false;
			return true;
		}

		public static BeltInventory? Selected(Player p)
		{
			ItemData val = CurrentItem(p);
			if (val == null)
			{
				return null;
			}
			string text = Identity(val);
			if (SelectedIds.TryGetValue(p.GetPlayerID(), out string value) && value == text && ClientStates.TryGetValue(p.GetPlayerID(), out BeltInventory value2))
			{
				value2.NativeEquipped = val.m_equipped;
				return value2;
			}
			return Contents(val);
		}

		public static BeltInventory? For(Player player)
		{
			if ((Object)(object)player == (Object)(object)Player.m_localPlayer)
			{
				ItemData val = EquippedItem(player) ?? CurrentItem(player);
				if (val == null)
				{
					return new BeltInventory();
				}
				return Contents(val);
			}
			if (!EquippedStates.TryGetValue(player.GetPlayerID(), out BeltInventory value))
			{
				return null;
			}
			return value;
		}

		public static void Update()
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || ZRoutedRpc.instance == null || !Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				return;
			}
			if (registered != ZRoutedRpc.instance || world != ZNet.instance.GetWorldUID())
			{
				registered = ZRoutedRpc.instance;
				world = ZNet.instance.GetWorldUID();
				SelectedIds.Clear();
				ServerSelectedIds.Clear();
				EquippedStates.Clear();
				Records.Clear();
				HeldIds.Clear();
				DecodedItems.Clear();
				selectedItem = null;
				synchronizedId = (synchronizedEquipped = (synchronizedHeld = ""));
				awaitingSync = false;
				syncTransaction = "";
				ServerStates.Clear();
				ClientStates.Clear();
				Online.Clear();
				Dead.Clear();
				Committing.Clear();
				RecordOwners.Clear();
				pending = null;
				localId = 0L;
				registered.Register<ZPackage>("branchofyore.odinsbelt.request", (Action<long, ZPackage>)ReceiveRequest);
				registered.Register<ZPackage>("branchofyore.odinsbelt.reply", (Action<long, ZPackage>)ReceiveReply);
				registered.Register<ZPackage>("branchofyore.odinsbelt.snapshot", (Action<long, ZPackage>)ReceiveSnapshot);
				Keyring.Discover();
			}
			if (ZNet.instance.IsServer())
			{
				ObservePlayers();
			}
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || localPlayer.GetPlayerID() == 0L)
			{
				return;
			}
			if (localId != localPlayer.GetPlayerID())
			{
				localId = localPlayer.GetPlayerID();
				pending = null;
				Persistence.RestoreClient(localPlayer);
				if (localPlayer.m_customData.TryGetValue("branchofyore.odinsbelt.pending", out var value))
				{
					try
					{
						pending = Pending.Decode(value);
					}
					catch (Exception ex)
					{
						Plugin.Instance.Warn("Cannot restore pending belt transfer: " + ex.Message);
					}
				}
				if (pending != null && pending.BeltId == "")
				{
					ItemData val = CurrentItem(localPlayer);
					if (val != null)
					{
						pending.BeltId = Identity(val);
					}
				}
				nextSync = 0f;
			}
			Pending? obj = pending;
			if (obj != null && obj.Acknowledged)
			{
				CompletePending(localPlayer);
			}
			if (!Busy && For(localPlayer)?.Get(0) != null)
			{
				Request(2);
			}
			if (!Busy || !ClientStates.ContainsKey(localId))
			{
				if (!awaitingSync)
				{
					string text = synchronizedId;
					ItemData val2 = CurrentItem(localPlayer);
					if (!(text != ((val2 != null) ? Identity(val2) : "")))
					{
						string text2 = synchronizedEquipped;
						ItemData val3 = EquippedItem(localPlayer);
						if (!(text2 != ((val3 != null) ? Identity(val3) : "")) && !(synchronizedHeld != Owned(localPlayer)) && SelectedIds.TryGetValue(localId, out string value2) && !(value2 != synchronizedId) && ClientStates.ContainsKey(localId))
						{
							goto IL_0373;
						}
					}
				}
				if (Time.unscaledTime >= nextSync)
				{
					nextSync = Time.unscaledTime + 2f;
					SendSync(localPlayer);
				}
			}
			goto IL_0373;
			IL_0373:
			if (pending != null && !pending.Acknowledged && ClientStates.ContainsKey(localId) && Time.unscaledTime >= nextRetry)
			{
				nextRetry = Time.unscaledTime + 2f;
				Send(pending);
			}
		}

		public static bool PrepareTransfer(ItemData item)
		{
			if (BeltInventory.Prefab(item) != "OdinsBelt")
			{
				return true;
			}
			if (pending != null && Identity(item) == pending.BeltId)
			{
				LastMessage = "Wait for the item transfer to finish.";
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)localPlayer))
			{
				SavePlayer(localPlayer);
			}
			BeltUI.Close();
			return true;
		}

		private static void SavePlayer(Player p)
		{
			if (pending != null)
			{
				p.m_customData["branchofyore.odinsbelt.pending"] = pending.Encode();
			}
			else
			{
				p.m_customData.Remove("branchofyore.odinsbelt.pending");
			}
			if (ClientStates.TryGetValue(p.GetPlayerID(), out BeltInventory value) && SelectedIds.TryGetValue(p.GetPlayerID(), out string beltId))
			{
				string value2;
				ItemData val = ((IEnumerable<ItemData>)((Humanoid)p).GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => i.m_customData.TryGetValue("branchofyore.odinsbelt.belt-id", out value2) && value2 == beltId));
				if (val != null)
				{
					val.m_customData["branchofyore.odinsbelt.contents"] = value.Encode();
				}
			}
			Persistence.SaveClient(p);
		}

		private static void SendSync(Player p)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			string value3;
			ItemData val = ((pending != null && !pending.Acknowledged) ? ((IEnumerable<ItemData>)((Humanoid)p).GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => i.m_customData.TryGetValue("branchofyore.odinsbelt.belt-id", out value3) && value3 == pending.BeltId)) : null) ?? CurrentItem(p);
			string text = ((val != null) ? Identity(val) : "");
			if (!awaitingSync || synchronizedId != text)
			{
				syncTransaction = Guid.NewGuid().ToString("N");
			}
			awaitingSync = true;
			ZPackage val2 = new ZPackage();
			val2.Write(0);
			val2.Write(((Character)p).GetZDOID());
			val2.Write(syncTransaction);
			val2.Write(0L);
			val2.Write(0);
			ItemData val3 = val;
			string text2 = ((val3 != null) ? Identity(val3) : "");
			if (val3 != null && !val3.m_customData.ContainsKey("branchofyore.odinsbelt.contents") && !p.m_customData.ContainsKey("branchofyore.odinsbelt.state.migrated") && p.m_customData.TryGetValue("branchofyore.odinsbelt.state", out var value))
			{
				val3.m_customData["branchofyore.odinsbelt.contents"] = value;
				p.m_customData["branchofyore.odinsbelt.state.migrated"] = text2;
			}
			val2.Write((val3 != null && val3.m_customData.TryGetValue("branchofyore.odinsbelt.contents", out var value2)) ? value2 : "");
			WriteIdentity(val2, p, text2);
			synchronizedHeld = Owned(p);
			synchronizedId = text2;
			ItemData val4 = EquippedItem(p);
			synchronizedEquipped = ((val4 != null) ? Identity(val4) : "");
			registered.InvokeRoutedRPC(ServerId, "branchofyore.odinsbelt.request", new object[1] { val2 });
		}

		public static bool Store(ItemData item, int slot)
		{
			Player localPlayer = Player.m_localPlayer;
			BeltInventory beltInventory = (Object.op_Implicit((Object)(object)localPlayer) ? Selected(localPlayer) : null);
			if (!Object.op_Implicit((Object)(object)localPlayer) || registered == null || slot <= 0 || slot >= 21 || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting() || beltInventory == null || !Ready || pending != null || !((Humanoid)localPlayer).GetInventory().ContainsItem(item) || CurrentItem(localPlayer) == null || !SelectedIds.TryGetValue(localPlayer.GetPlayerID(), out string value) || value != Identity(CurrentItem(localPlayer)) || beltInventory.Get(slot) != null || !Plugin.ItemEnabled(item))
			{
				return false;
			}
			ItemData val = item.Clone();
			val.m_stack = 1;
			if (!BeltInventory.ValidSlot(slot, val))
			{
				return false;
			}
			((Humanoid)localPlayer).RemoveEquipAction(item);
			((Humanoid)localPlayer).UnequipItem(item, false);
			string payload = BeltInventory.PackItem(val);
			if (!((Humanoid)localPlayer).GetInventory().RemoveItem(item, 1))
			{
				return false;
			}
			if (Request(1, slot, payload))
			{
				return true;
			}
			((Humanoid)localPlayer).GetInventory().AddItem(val);
			return false;
		}

		public static bool Request(int action, int slot = 0, string payload = "")
		{
			Player localPlayer = Player.m_localPlayer;
			BeltInventory beltInventory = (Object.op_Implicit((Object)(object)localPlayer) ? Selected(localPlayer) : null);
			if (!Object.op_Implicit((Object)(object)localPlayer) || registered == null || beltInventory == null || !Ready || pending != null || ((Character)localPlayer).IsDead() || CurrentItem(localPlayer) == null || !SelectedIds.TryGetValue(localPlayer.GetPlayerID(), out string value) || value != Identity(CurrentItem(localPlayer)))
			{
				return false;
			}
			if (action == 2 && (beltInventory.Get(slot) == null || !((Humanoid)localPlayer).GetInventory().CanAddItem(beltInventory.Get(slot), -1)))
			{
				return false;
			}
			pending = new Pending
			{
				Action = action,
				Slot = slot,
				Payload = payload,
				Revision = beltInventory.Revision,
				BeltId = Identity(CurrentItem(localPlayer)),
				Transaction = Guid.NewGuid().ToString("N")
			};
			LastMessage = "";
			SavePlayer(localPlayer);
			nextRetry = Time.unscaledTime + 2f;
			Send(pending);
			return true;
		}

		private static void Send(Pending request)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)localPlayer) && registered != null)
			{
				ZPackage val = new ZPackage();
				val.Write(request.Action);
				val.Write(((Character)localPlayer).GetZDOID());
				val.Write(request.Transaction);
				val.Write(request.Revision);
				val.Write(request.Slot);
				val.Write(request.Payload);
				WriteIdentity(val, localPlayer, request.BeltId);
				registered.InvokeRoutedRPC(ServerId, "branchofyore.odinsbelt.request", new object[1] { val });
			}
		}

		private static void WriteIdentity(ZPackage pkg, Player p, string id)
		{
			pkg.Write(id);
			pkg.Write(Owned(p));
			ItemData val = EquippedItem(p);
			pkg.Write((val != null) ? Identity(val) : "");
			pkg.Write((val != null && val.m_customData.TryGetValue("branchofyore.odinsbelt.contents", out var value)) ? value : "");
		}

		private static string RecordPath(long id)
		{
			return BeltPath(ServerSelectedIds[id]);
		}

		private static string BeltPath(string id)
		{
			return Path.Combine(Paths.ConfigPath, "OdinsBelt", world.ToString(), "items", id + ".belt");
		}

		private static BeltInventory Canonical(string id, string imported)
		{
			if (Records.TryGetValue(id, out BeltInventory value))
			{
				return value;
			}
			string path = BeltPath(id);
			value = (File.Exists(path) ? BeltInventory.Decode(File.ReadAllText(path)) : BeltInventory.Decode(imported));
			Records[id] = value;
			return value;
		}

		private static string Account(long sender)
		{
			if (sender == ServerId)
			{
				return "local";
			}
			string hostName = ZNet.instance.GetPeer(sender).m_rpc.GetSocket().GetHostName();
			using SHA256 sHA = SHA256.Create();
			return BitConverter.ToString(sHA.ComputeHash(Encoding.UTF8.GetBytes(hostName))).Replace("-", "");
		}

		private static void Persist(long id, BeltInventory state)
		{
			Persistence.Write(RecordPath(id), Encoding.UTF8.GetBytes(state.Encode()));
		}

		private static BeltInventory Load(long id, string imported)
		{
			BeltInventory beltInventory = Canonical(ServerSelectedIds[id], imported);
			ServerStates[id] = beltInventory;
			return beltInventory;
		}

		private static bool Authorized(long sender, ZDOID pid, out ZDO player)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			player = ZDOMan.instance.GetZDO(pid);
			if (player == null || player.GetOwner() != sender || player.GetLong(ZDOVars.s_playerID, 0L) == 0L)
			{
				return false;
			}
			if (sender == ServerId)
			{
				if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					return ((Character)Player.m_localPlayer).GetZDOID() == pid;
				}
				return false;
			}
			ZNetPeer peer = ZNet.instance.GetPeer(sender);
			if (peer == null || !peer.IsReady())
			{
				return false;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(player.GetPrefab());
			if (!Object.op_Implicit((Object)(object)prefab) || !Object.op_Implicit((Object)(object)prefab.GetComponent<Player>()))
			{
				return false;
			}
			if (peer.m_characterID == pid || peer.m_characterID == ZDOID.None)
			{
				return true;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID);
			if (zDO != null)
			{
				return zDO.GetBool(ZDOVars.s_dead, false);
			}
			return true;
		}

		private static void ReceiveRequest(long sender, ZPackage pkg)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer())
			{
				return;
			}
			try
			{
				if (pkg.GetArray().Length > 300000)
				{
					return;
				}
				int num = pkg.ReadInt();
				ZDOID val = pkg.ReadZDOID();
				string tx = pkg.ReadString();
				long num2 = pkg.ReadLong();
				int num3 = pkg.ReadInt();
				string text = pkg.ReadString();
				string beltId = pkg.ReadString();
				string text2 = pkg.ReadString();
				string equippedId = pkg.ReadString();
				string imported = pkg.ReadString();
				if (((beltId == "") ? ((byte)num != 0) : (!Guid.TryParseExact(beltId, "N", out var result))) || (equippedId != "" && !Guid.TryParseExact(equippedId, "N", out result)) || !Authorized(sender, val, out ZDO player))
				{
					return;
				}
				long id = player.GetLong(ZDOVars.s_playerID, 0L);
				if (Online.TryGetValue(id, out (long, ZDOID, Vector3) value) && value.Item1 != sender)
				{
					return;
				}
				HashSet<string> hashSet = new HashSet<string>(text2.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries));
				if (hashSet.Count > 300 || (beltId != "" && !hashSet.Contains(beltId)) || (equippedId != "" && !hashSet.Contains(equippedId)) || hashSet.Any((string key) => !Guid.TryParseExact(key, "N", out var _)) || HeldIds.Any<KeyValuePair<long, HashSet<string>>>((KeyValuePair<long, HashSet<string>> pair) => pair.Key != id && Online.ContainsKey(pair.Key) && pair.Value.Contains(beltId)))
				{
					return;
				}
				HeldIds[id] = hashSet;
				string text3 = Account(sender);
				if (RecordOwners.TryGetValue(id, out string value2) && value2 != text3)
				{
					ServerStates.Remove(id);
				}
				RecordOwners[id] = text3;
				if (Committing.Contains(id))
				{
					return;
				}
				ServerSelectedIds[id] = beltId;
				BeltInventory state = ((beltId != "") ? Load(id, (num == 0) ? text : "") : new BeltInventory());
				ServerStates[id] = state;
				state.NativeEquipped = NativeEquipped(player) && equippedId == beltId;
				BeltInventory beltInventory = ((equippedId != "" && NativeEquipped(player)) ? BeltInventory.Decode(Canonical(equippedId, imported).Encode()) : new BeltInventory());
				beltInventory.NativeEquipped = equippedId != "" && NativeEquipped(player);
				EquippedStates[id] = beltInventory;
				Online[id] = (sender, val, player.GetPosition());
				if (num == 0)
				{
					long[] array = Online.Keys.ToArray();
					foreach (long num5 in array)
					{
						if (ServerStates.TryGetValue(num5, out BeltInventory value3))
						{
							Snapshot(sender, num5, value3);
						}
					}
					Snapshot(0L, id, state);
					Reply(sender, id, tx, accepted: true, state, "", "");
					return;
				}
				if (tx.Length != 32 || !Guid.TryParseExact(tx, "N", out result) || Committing.Contains(id))
				{
					return;
				}
				if (state.LastTransaction == tx)
				{
					Reply(sender, id, tx, accepted: true, state, state.LastReceipt, "");
					return;
				}
				if (player.GetBool(ZDOVars.s_dead, false) || num2 != state.Revision || num3 < 0 || num3 >= 43)
				{
					Reply(sender, id, tx, accepted: false, state, "", "Belt changed. Please try again.");
					return;
				}
				BeltInventory next = BeltInventory.Decode(state.Encode());
				string receipt = "";
				bool flag = false;
				if (num == 1 && num3 > 0 && num3 < 21 && text.Length <= 65536)
				{
					ItemData item = BeltInventory.UnpackItem(text);
					flag = Plugin.ItemEnabled(item) && next.Put(num3, item);
				}
				else
				{
					if (num == 2 || num == 4)
					{
						ItemData val2 = next.Get(num3);
						if (val2 != null && (num == 2 || num3 >= 11))
						{
							if (num == 2)
							{
								receipt = BeltInventory.PackItem(val2);
							}
							next.Inventory.RemoveItem(val2);
							flag = true;
							goto IL_07b4;
						}
					}
					if (num == 3)
					{
						int num6 = next.FindUtility("Lantern");
						if (num6 != 0 && Plugin.LanternEnabled.Value)
						{
							next.ActiveSlots ^= 1 << num6;
							flag = true;
							goto IL_07b4;
						}
					}
					if (num == 6 && num3 >= 1 && num3 <= 10)
					{
						ItemData val3 = next.Get(num3);
						if (val3 != null && Plugin.ItemEnabled(val3))
						{
							next.ActiveSlots ^= 1 << num3;
							flag = true;
							goto IL_07b4;
						}
					}
					if (num == 7 && int.TryParse(text, out var result2) && result2 > 0 && result2 < 21 && num3 > 0 && num3 < 21)
					{
						ItemData val4 = next.Get(num3);
						ItemData val5 = next.Get(result2);
						if (val4 != null && BeltInventory.ValidSlot(result2, val4) && (val5 == null || BeltInventory.ValidSlot(num3, val5)))
						{
							bool flag2 = next.IsActive(num3);
							bool flag3 = next.IsActive(result2);
							next.Inventory.RemoveItem(val4);
							if (val5 != null)
							{
								next.Inventory.RemoveItem(val5);
							}
							next.Put(result2, val4);
							if (val5 != null)
							{
								next.Put(num3, val5);
							}
							if (num3 < 11 && result2 < 11)
							{
								next.ActiveSlots &= ~((1 << num3) | (1 << result2));
								if (flag2)
								{
									next.ActiveSlots |= 1 << result2;
								}
								if (flag3)
								{
									next.ActiveSlots |= 1 << num3;
								}
							}
							flag = true;
						}
					}
				}
				goto IL_07b4;
				IL_07b4:
				if (!flag)
				{
					Reply(sender, id, tx, accepted: false, state, "", "That item cannot go in this slot.");
					return;
				}
				next.PromoteSavedKeys();
				next.LanternOn = next.FindUtility("Lantern", activeOnly: true) != 0;
				next.Revision++;
				next.LastTransaction = tx;
				next.LastReceipt = receipt;
				ServerStates[id] = next;
				Records[beltId] = next;
				Committing.Add(id);
				Persistence.Write(RecordPath(id), Encoding.UTF8.GetBytes(next.Encode()), delegate
				{
					Committing.Remove(id);
					if (equippedId == beltId && NativeEquipped(player))
					{
						BeltInventory beltInventory2 = BeltInventory.Decode(next.Encode());
						beltInventory2.NativeEquipped = true;
						EquippedStates[id] = beltInventory2;
					}
					Snapshot(0L, id, next);
					Reply(sender, id, tx, accepted: true, next, receipt, "");
				}, delegate
				{
					ServerStates[id] = state;
					Records[beltId] = state;
					Committing.Remove(id);
					Reply(sender, id, tx, accepted: false, state, "", "Could not save belt. Please try again.");
				});
			}
			catch (Exception ex)
			{
				Plugin.Instance.Warn("Belt request rejected: " + ex.Message);
			}
		}

		private static void Snapshot(long peer, long id, BeltInventory state)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(id);
			val.Write(state.Encode());
			val.Write(ServerSelectedIds[id]);
			val.Write(EquippedStates.TryGetValue(id, out BeltInventory value) ? value.Encode() : "");
			registered.InvokeRoutedRPC(peer, "branchofyore.odinsbelt.snapshot", new object[1] { val });
		}

		private static void Reply(long peer, long id, string transaction, bool accepted, BeltInventory state, string receipt, string message)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(id);
			val.Write(transaction);
			val.Write(accepted);
			val.Write(state.Encode());
			val.Write(receipt);
			val.Write(message);
			val.Write(ServerSelectedIds[id]);
			registered.InvokeRoutedRPC(peer, "branchofyore.odinsbelt.reply", new object[1] { val });
		}

		private static void ReceiveSnapshot(long sender, ZPackage pkg)
		{
			if (sender != ServerId || pkg.GetArray().Length > 300000)
			{
				return;
			}
			try
			{
				long num = pkg.ReadLong();
				BeltInventory beltInventory = BeltInventory.Decode(pkg.ReadString());
				string text = pkg.ReadString();
				BeltInventory value = BeltInventory.Decode(pkg.ReadString());
				EquippedStates[num] = value;
				if (!SelectedIds.TryGetValue(num, out string value2) || value2 != text || !ClientStates.TryGetValue(num, out BeltInventory value3) || beltInventory.Revision >= value3.Revision)
				{
					SelectedIds[num] = text;
					ClientStates[num] = beltInventory;
					Player localPlayer = Player.m_localPlayer;
					if (Object.op_Implicit((Object)(object)localPlayer) && localPlayer.GetPlayerID() == num)
					{
						SavePlayer(localPlayer);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Instance.Warn("Invalid belt snapshot: " + ex.Message);
			}
		}

		private static void ReceiveReply(long sender, ZPackage pkg)
		{
			if (sender != ServerId || pkg.GetArray().Length > 400000)
			{
				return;
			}
			try
			{
				long num = pkg.ReadLong();
				string text = pkg.ReadString();
				bool flag = pkg.ReadBool();
				BeltInventory beltInventory = BeltInventory.Decode(pkg.ReadString());
				string text2 = pkg.ReadString();
				LastMessage = pkg.ReadString();
				string text3 = pkg.ReadString();
				Player localPlayer = Player.m_localPlayer;
				if (!Object.op_Implicit((Object)(object)localPlayer) || num != localPlayer.GetPlayerID())
				{
					return;
				}
				if (text == syncTransaction)
				{
					if (!flag)
					{
						awaitingSync = true;
						BeltUI.Refresh();
						return;
					}
					awaitingSync = false;
				}
				if (!SelectedIds.TryGetValue(num, out string value) || value != text3 || !ClientStates.TryGetValue(num, out BeltInventory value2) || beltInventory.Revision >= value2.Revision)
				{
					SelectedIds[num] = text3;
					ClientStates[num] = beltInventory;
				}
				if (pending != null && pending.Transaction == text)
				{
					pending.Acknowledged = true;
					pending.Receipt = (flag ? text2 : ((pending.Action == 1) ? pending.Payload : ""));
					SavePlayer(localPlayer);
					CompletePending(localPlayer);
				}
				else
				{
					SavePlayer(localPlayer);
				}
				BeltUI.Refresh();
			}
			catch (Exception ex)
			{
				Plugin.Instance.Warn("Cannot apply belt reply: " + ex.Message);
			}
		}

		private static void CompletePending(Player p)
		{
			if (pending == null || !pending.Acknowledged)
			{
				return;
			}
			ItemData delivered = null;
			if (!string.IsNullOrEmpty(pending.Receipt))
			{
				ItemData val = BeltInventory.UnpackItem(pending.Receipt);
				if (!((Humanoid)p).GetInventory().CanAddItem(val, -1) || !((Humanoid)p).GetInventory().AddItem(val))
				{
					LastMessage = "Make room in your inventory to receive the item.";
					return;
				}
				delivered = val;
			}
			try
			{
				BeltDragAndDrop.TransferFinished(pending.Action, pending.Slot, delivered);
			}
			catch (Exception ex)
			{
				Plugin.Instance.Warn("Could not place the received item in the selected slot: " + ex.Message);
			}
			pending = null;
			SavePlayer(p);
			BeltUI.Refresh();
		}

		private static void ObservePlayers()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			KeyValuePair<long, (long, ZDOID, Vector3)>[] array = Online.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<long, (long, ZDOID, Vector3)> keyValuePair = array[i];
				ZDO zDO = ZDOMan.instance.GetZDO(keyValuePair.Value.Item2);
				bool num;
				if (keyValuePair.Value.Item1 != ServerId)
				{
					num = ZNet.instance.GetPeer(keyValuePair.Value.Item1) != null;
				}
				else
				{
					if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
					{
						goto IL_008b;
					}
					num = ((Character)Player.m_localPlayer).GetZDOID() == keyValuePair.Value.Item2;
				}
				if (num)
				{
					if (zDO != null)
					{
						BeltInventory state = ServerStates[keyValuePair.Key];
						if (!NativeEquipped(zDO) && EquippedStates.TryGetValue(keyValuePair.Key, out BeltInventory value) && value.NativeEquipped)
						{
							value.NativeEquipped = false;
							Snapshot(0L, keyValuePair.Key, state);
						}
						Online[keyValuePair.Key] = (keyValuePair.Value.Item1, keyValuePair.Value.Item2, zDO.GetPosition());
						if (zDO.GetBool(ZDOVars.s_dead, false))
						{
							Dead.Add(keyValuePair.Key);
						}
						else
						{
							Dead.Remove(keyValuePair.Key);
						}
					}
					continue;
				}
				goto IL_008b;
				IL_008b:
				if (!Plugin.KeepOnLogout.Value)
				{
					DropContents(keyValuePair.Key, keyValuePair.Value.Item3);
				}
				Online.Remove(keyValuePair.Key);
				HeldIds.Remove(keyValuePair.Key);
				Dead.Remove(keyValuePair.Key);
			}
		}

		public static bool NativeEquipped(ZDO player)
		{
			return player.GetInt(ZDOVars.s_utilityItem, 0) == StringExtensionMethods.GetStableHashCode("OdinsBelt");
		}

		private static void DropContents(long id, Vector3 position)
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			if (ServerStates.TryGetValue(id, out BeltInventory value) && value.Inventory.GetAllItems().Count != 0)
			{
				ItemData[] array = (from i in value.Inventory.GetAllItems()
					select i.Clone()).ToArray();
				BeltInventory beltInventory = new BeltInventory
				{
					Revision = value.Revision + 1,
					LanternOn = value.LanternOn,
					LastTransaction = value.LastTransaction,
					LastReceipt = value.LastReceipt
				};
				Persist(id, beltInventory);
				Records[ServerSelectedIds[id]] = beltInventory;
				ServerStates[id] = beltInventory;
				Snapshot(0L, id, beltInventory);
				for (int num = 0; num < array.Length; num++)
				{
					ItemDrop.DropItem(array[num], 1, position + Vector3.up + new Vector3((float)(num % 3) * 0.15f, 0f, (float)(num / 3) * 0.15f), Quaternion.identity);
				}
			}
		}
	}
	public static class BeltUI
	{
		[HarmonyPatch(typeof(Humanoid), "UnequipItem")]
		private static class CloseOnUnequip
		{
			private static void Postfix(Humanoid __instance, ItemData item)
			{
				if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && item != null && BeltInventory.Prefab(item) == "OdinsBelt" && !item.m_equipped)
				{
					Close();
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")]
		private static class RightClick
		{
			private static bool Prefix(InventoryGrid grid, ItemData item)
			{
				Player localPlayer = Player.m_localPlayer;
				if (!Object.op_Implicit((Object)(object)localPlayer) || item == null || grid.GetInventory() != ((Humanoid)localPlayer).GetInventory())
				{
					return true;
				}
				string text = BeltInventory.Prefab(item);
				if (text == "OdinsBelt")
				{
					return true;
				}
				if (!Open)
				{
					return true;
				}
				if (BeltInventory.IsUtility(item))
				{
					BeltInventory state = BeltNetwork.Selected(localPlayer);
					if (state != null)
					{
						int num = Enumerable.Range(1, 10).FirstOrDefault((int s) => state.Get(s) == null);
						if (num != 0)
						{
							BeltNetwork.Store(item, num);
						}
					}
					return false;
				}
				if (Keyring.IsKey(text))
				{
					BeltInventory beltInventory = BeltNetwork.Selected(localPlayer);
					if (beltInventory != null)
					{
						for (int num2 = 11; num2 < 21; num2++)
						{
							if (beltInventory.Get(num2) == null)
							{
								BeltNetwork.Store(item, num2);
								break;
							}
						}
					}
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Hide")]
		private static class CloseWithInventory
		{
			private static void Postfix()
			{
				Close();
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Update")]
		private static class OpenBeforeVanillaUse
		{
			private static void Prefix()
			{
				if (InventoryGui.IsVisible() && (ZInput.GetButtonDown("Use") || Input.GetKeyDown((KeyCode)101)) && TryOpenHoveredBelt())
				{
					ZInput.ResetButtonStatus("Use");
				}
			}
		}

		private static GameObject? panel;

		private static Text? hint;

		private static Text? status;

		private static readonly List<(int slot, Button button, Image icon)> Buttons = new List<(int, Button, Image)>();

		private static Text? beltStatus;

		private static readonly Dictionary<int, Button> Activation = new Dictionary<int, Button>();

		private static float nextRefresh;

		public static bool Open
		{
			get
			{
				if (Object.op_Implicit((Object)(object)panel))
				{
					return panel.activeSelf;
				}
				return false;
			}
		}

		public static void Update()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting())
			{
				Close();
			}
			else if ((!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus()) && !Console.IsVisible() && (Open || !TextInput.IsVisible()))
			{
				if (Input.GetKeyDown((KeyCode)101) && InventoryGui.IsVisible())
				{
					TryOpenHoveredBelt();
				}
				if (Open && Input.GetKeyDown((KeyCode)27))
				{
					Close();
				}
				if (Open && Time.unscaledTime >= nextRefresh)
				{
					nextRefresh = Time.unscaledTime + 0.3f;
					Refresh();
				}
			}
		}

		public static void Show(ItemData? item = null)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)GUIManager.CustomGUIFront) || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || (item != null && !BeltNetwork.Select(item)))
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)panel))
			{
				Build();
			}
			panel.SetActive(true);
			BeltNetwork.SynchronizeSelected();
			PositionWindow();
			if (Object.op_Implicit((Object)(object)InventoryGui.instance))
			{
				InventoryGui instance = InventoryGui.instance;
				if (!((Animator)AccessTools.Field(typeof(InventoryGui), "m_animator").GetValue(instance)).GetBool("visible"))
				{
					instance.Show((Container)null, 0);
				}
			}
			Refresh();
		}

		public static void Close()
		{
			BeltDragAndDrop.Cancel();
			if (Object.op_Implicit((Object)(object)panel))
			{
				panel.SetActive(false);
			}
		}

		public static void Clear()
		{
			Close();
			if (Object.op_Implicit((Object)(object)panel))
			{
				Object.Destroy((Object)(object)panel);
			}
			panel = null;
			Buttons.Clear();
			Activation.Clear();
		}

		private static Text Text(string value, float x, float y, float width, float height, int size = 18)
		{
			//IL_001a: 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_0050: 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)
			Text component = GUIManager.Instance.CreateText(value, panel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(x, y), GUIManager.Instance.AveriaSerifBold, size, new Color(1f, 0.84f, 0.51f), true, Color.black, width, height, false).GetComponent<Text>();
			component.alignment = (TextAnchor)4;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private static Button Button(string label, float x, float y, float width, float height, Action click)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			Button component = GUIManager.Instance.CreateButton(label, panel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(x, y), width, height).GetComponent<Button>();
			((UnityEvent)component.onClick).AddListener((UnityAction)delegate
			{
				click();
			});
			return component;
		}

		private static void Build()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			Buttons.Clear();
			panel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(260f, -15f), 420f, 520f, false);
			((Object)panel).name = "UtilityBeltWindow";
			Text("ODIN’S BELT", 0f, 210f, 340f, 32f, 24);
			Button("×", 180f, 210f, 28f, 28f, Close);
			beltStatus = Text("", 0f, 185f, 360f, 18f, 14);
			Text val = Text("UTILITY", 0f, 166f, 360f, 18f);
			Activation.Clear();
			for (int i = 1; i <= 10; i++)
			{
				int slot = i;
				float x = ((i - 1) % 5 - 2) * 74;
				float num = 105 - (i - 1) / 5 * 87;
				Activation[slot] = Button("ON", x, num + 41f, 62f, 18f, delegate
				{
					BeltNetwork.Request(6, slot);
				});
				Slot(slot, x, num, 64f);
			}
			Text val2 = Text("KEYRING", 0f, -30f, 360f, 22f);
			for (int num2 = 0; num2 < 10; num2++)
			{
				Slot(11 + num2, (num2 % 5 - 2) * 74, -80 - num2 / 5 * 70, 64f);
			}
			hint = Text("Drag items in or out. Hover an item for details.", 0f, -207f, 370f, 48f, 13);
			hint.horizontalOverflow = (HorizontalWrapMode)0;
			hint.verticalOverflow = (VerticalWrapMode)0;
			status = Text("", 0f, -237f, 370f, 18f, 12);
			((Component)val).transform.SetAsLastSibling();
			((Component)val2).transform.SetAsLastSibling();
			panel.SetActive(false);
		}

		private static void Slot(int slot, float x, float y, float width)
		{
			//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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00e7: Expected O, but got Unknown
			GameObject val = Object.Instantiate<GameObject>(InventoryGui.instance.m_playerGrid.m_elementPrefab, panel.transform, false);
			((Object)val).name = "BeltCell" + slot;
			RectTransform component = val.GetComponent<RectTransform>();
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			component.anchorMax = val2;
			component.anchorMin = val2;
			component.pivot = new Vector2(0.5f, 0.5f);
			component.anchoredPosition = new Vector2(x, y);
			component.sizeDelta = new Vector2(width, width);
			InventoryElement component2 = val.GetComponent<InventoryElement>();
			component2.Initialize((slot - 1) % 5, (slot - 1) / 5);
			Button button = component2.m_button;
			((UnityEventBase)button.onClick).RemoveAllListeners();
			((UnityEvent)button.onClick).AddListener((UnityAction)delegate
			{
				ClickSlot(slot);
			});
			Image icon = component2.m_icon;
			icon.sprite = null;
			((Behaviour)icon).enabled = false;
			((Graphic)icon).raycastTarget = false;
			TMP_Text[] componentsInChildren = val.GetComponentsInChildren<TMP_Text>(true);
			for (int num = 0; num < componentsInChildren.Length; num++)
			{
				componentsInChildren[num].text = "";
			}
			Image[] array = (Image[])(object)new Image[5] { component2.m_equiped, component2.m_queued, component2.m_noteleport, component2.m_food, component2.m_dropFocus };
			foreach (Image val3 in array)
			{
				if (Object.op_Implicit((Object)(object)val3))
				{
					((Component)val3).gameObject.SetActive(false);
				}
			}
			if (Object.op_Implicit((Object)(object)component2.m_selected))
			{
				component2.m_selected.SetActive(false);
			}
			if (Object.op_Implicit((Object)(object)component2.m_durability))
			{
				((Component)component2.m_durability).gameObject.SetActive(false);
			}
			if (Object.op_Implicit((Object)(object)component2.m_tooltip))
			{
				((Behaviour)component2.m_tooltip).enabled = false;
			}
			UIDragHandler componentInChildren = val.GetComponentInChildren<UIDragHandler>();
			((Component)componentInChildren).gameObject.AddComponent<BeltSlotHover>().Slot = slot;
			componentInChildren.m_onBeginDrag = (Action<UIDragHandler>)Delegate.Combine(componentInChildren.m_onBeginDrag, (Action<UIDragHandler>)delegate
			{
				BeginSlotDrag(slot);
			});
			componentInChildren.m_onReleasedOn = (Action<UIDragHandler>)Delegate.Combine(componentInChildren.m_onReleasedOn, (Action<UIDragHandler>)delegate
			{
				DropOnSlot(slot);
			});
			Buttons.Add((slot, button, icon));
		}

		private static int Actual(int slot)
		{
			return slot;
		}

		public static void Refresh()
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)panel) || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return;
			}
			PositionWindow();
			BeltInventory beltInventory = BeltNetwork.Selected(Player.m_localPlayer);
			if (Object.op_Implicit((Object)(object)beltStatus))
			{
				beltStatus.text = ((beltInventory != null && beltInventory.Equipped) ? "Equipped" : "Right-click the belt in inventory to equip it.");
			}
			foreach (var button in Buttons)
			{
				ItemData val = beltInventory?.Get(Actual(button.slot));
				button.icon.sprite = ((val != null) ? val.GetIcon() : null);
				((Behaviour)button.icon).enabled = val != null;
				((Graphic)button.icon).color = ((BeltDragAndDrop.Holding && BeltDragAndDrop.Origin == Actual(button.slot)) ? Color.gray : Color.white);
				((Selectable)button.button).interactable = beltInventory != null && BeltNetwork.Ready && !BeltNetwork.Busy;
			}
			foreach (KeyValuePair<int, Button> item in Activation)
			{
				ItemData val2 = beltInventory?.Get(item.Key);
				bool flag = val2 != null && Plugin.ItemEnabled(val2);
				((Component)item.Value).gameObject.SetActive(val2 != null);
				((Component)item.Value).GetComponentInChildren<Text>().text = ((flag && beltInventory.IsActive(item.Key)) ? "ON" : "OFF");
				((Graphic)((Component)item.Value).GetComponentInChildren<Text>()).color = (((beltInventory?.IsActive(item.Key) ?? false) && flag) ? new Color(1f, 0.82f, 0.32f) : new Color(0.65f, 0.65f, 0.65f));
				((Selectable)item.Value).interactable = flag && beltInventory != null && beltInventory.Get(item.Key) != null && BeltNetwork.Ready && !BeltNetwork.Busy;
			}
			if (Object.op_Implicit((Object)(object)status))
			{
				status.text = ((beltInventory == null || !BeltNetwork.Ready) ? "Synchronizing belt with server..." : ((beltInventory.OverflowCount > 0) ? (beltInventory.OverflowCount + " saved keys waiting for an empty key slot") : BeltNetwork.LastMessage));
			}
		}

		private static void PositionWindow()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)panel))
			{
				return;
			}
			Transform parent = panel.transform.parent;
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if (val != null)
			{
				Rect rect = val.rect;
				if (!(((Rect)(ref rect)).width <= 0f) && !(((Rect)(ref rect)).height <= 0f))
				{
					float num = Mathf.Min(new float[3]
					{
						1f,
						(((Rect)(ref rect)).width - 24f) / 420f,
						(((Rect)(ref rect)).height - 24f) / 520f
					});
					num = Mathf.Max(0.4f, num);
					panel.transform.localScale = Vector3.one * num;
					float num2 = Mathf.Max(0f, (((Rect)(ref rect)).width - 420f * num) / 2f - 12f);
					float num3 = Mathf.Max(0f, (((Rect)(ref rect)).height - 520f * num) / 2f - 12f);
					panel.GetComponent<RectTransform>().anchoredPosition = new Vector2(Mathf.Clamp(260f, 0f - num2, num2), Mathf.Clamp(-15f, 0f - num3, num3));
				}
			}
		}

		public static void Hover(int slot)
		{
			Player localPlayer = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)localPlayer) && Object.op_Implicit((Object)(object)hint))
			{
				slot = Actual(slot);
				ItemData val = BeltNetwork.Selected(localPlayer)?.Get(slot);
				string text = ((slot >= 11) ? "Keys work automatically while equipped." : "Drag items here. Use ON/OFF to activate.");
				hint.text = ((val != null) ? (Localization.instance.Localize(val.m_shared.m_name) + " — ") : "Empty slot — ") + text;
			}
		}

		private static void ClickSlot(int displaySlot)
		{
			ClickActualSlot(Actual(displaySlot));
		}

		public static void BeginSlotDrag(int displaySlot)
		{
			BeltDragAndDrop.Begin(Actual(displaySlot));
		}

		public static void EndSlotDrag(PointerEventData pointer)
		{
			BeltDragAndDrop.End(pointer);
		}

		public static void DropOnSlot(int displaySlot)
		{
			if (BeltDragAndDrop.Holding)
			{
				if (BeltDragAndDrop.Origin == Actual(displaySlot))
				{
					BeltDragAndDrop.Cancel();
					return;
				}
				BeltNetwork.Request(7, BeltDragAndDrop.Origin, Actual(displaySlot).ToString());
				BeltDragAndDrop.Cancel();
			}
			else
			{
				InventoryGui instance = InventoryGui.instance;
				if (Object.op_Implicit((Object)(object)instance) && AccessTools.Field(typeof(InventoryGui), "m_dragItem").GetValue(instance) != null)
				{
					ClickSlot(displaySlot);
				}
			}
		}

		private static void ClickActualSlot(int slot)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				return;
			}
			BeltInventory beltInventory = BeltNetwork.Selected(localPlayer);
			if (beltInventory == null)
			{
				return;
			}
			if (BeltDragAndDrop.Holding)
			{
				DropOnSlot(slot);
				return;
			}
			InventoryGui instance = InventoryGui.instance;
			ItemData val = (ItemData)(Object.op_Implicit((Object)(object)instance) ? /*isinst with value type is only supported in some contexts*/: null);
			if (val != null)
			{
				if (!((Humanoid)localPlayer).GetInventory().ContainsItem(val))
				{
					BeltNetwork.LastMessage = "Move the item into your own inventory first.";
				}
				else if (BeltNetwork.Store(val, slot))
				{
					AccessTools.Method(typeof(InventoryGui), "SetupDragItem", (Type[])null, (Type[])null)?.Invoke(instance, new object[3] { null, null, 1 });
				}
				else
				{
					BeltNetwork.LastMessage = "That item cannot go in this slot.";
				}
			}
			else if (beltInventory.Get(slot) != null)
			{
				BeltDragAndDrop.Begin(slot);
			}
		}

		private static void AddKey()
		{
			Player localPlayer = Player.m_localPlayer;
			BeltInventory state = (Object.op_Implicit((Object)(object)localPlayer) ? BeltNetwork.Selected(localPlayer) : null);
			if (state != null)
			{
				int num = Enumerable.Range(11, 10).FirstOrDefault((int s) => state.Get(s) == null);
				if (num >= 11)
				{
					ClickActualSlot(num);
				}
				else
				{
					BeltNetwork.LastMessage = "The keyring is full.";
				}
			}
		}

		public static bool TryOpenHoveredBelt()
		{
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			InventoryGui instance = InventoryGui.instance;
			if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)instance) || !InventoryGui.IsVisible())
			{
				return false;
			}
			if ((Object.op_Implicit((Object)(object)Chat.instance) && Chat.instance.HasFocus()) || Console.IsVisible() || (!Open && TextInput.IsVisible()))
			{
				return false;
			}
			GameObject val = (Object.op_Implicit((Object)(object)EventSystem.current) ? EventSystem.current.currentSelectedGameObject : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				InputField component = val.GetComponent<InputField>();
				if (component == null || !component.isFocused)
				{
					TMP_InputField component2 = val.GetComponent<TMP_InputField>();
					if (component2 == null || !component2.isFocused)
					{
						goto IL_00a0;
					}
				}
				return false;
			}
			goto IL_00a0;
			IL_00a0:
			foreach (InventoryGrid item in ((IEnumerable<InventoryGrid>)(object)new InventoryGrid[1] { instance.m_playerGrid }).Concat(((Component)instance).GetComponentsInChildren<InventoryGrid>(true)).Distinct())
			{
				Inventory inventory = item.GetInventory();
				if (inventory == null)
				{
					continue;
				}
				object? obj = AccessTools.Method(typeof(InventoryGrid), "GetHoveredElement", (Type[])null, (Type[])null).Invoke(item, null);
				InventoryElement val2 = (InventoryElement)((obj is InventoryElement) ? obj : null);
				if (Object.op_Implicit((Object)(object)val2))
				{
					ItemData itemAt = inventory.GetItemAt(val2.Position.x, val2.Position.y);
					if (itemAt != null && !(BeltInventory.Prefab(itemAt) != "OdinsBelt") && ((Humanoid)localPlayer).GetInventory().ContainsItem(itemAt))
					{
						Show(itemAt);
						return true;
					}
				}
			}
			return false;
		}
	}
	public sealed class BeltSlotHover : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IEndDragHandler
	{
		public int Slot;

		public void OnPointerEnter(PointerEventData eventData)
		{
			BeltUI.Hover(Slot);
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			BeltUI.EndSlotDrag(eventData);
		}
	}
	internal static class Equipment
	{
		private sealed class QuestState
		{
			internal SharedData Shared;

			in