Decompiled source of ItemDrawers v0.9.0

plugins/ItemDrawers.Core.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ItemDrawers.Core")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+913107a17ca521c047e50107cd807fb5861366ab")]
[assembly: AssemblyProduct("ItemDrawers.Core")]
[assembly: AssemblyTitle("ItemDrawers.Core")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ItemDrawers.Core
{
	public readonly struct IconSize
	{
		public readonly string Name;

		public readonly int Width;

		public readonly int Height;

		public IconSize(string name, int width, int height)
		{
			Name = name;
			Width = width;
			Height = height;
		}
	}
	public readonly struct AtlasRect
	{
		public readonly int X;

		public readonly int Y;

		public readonly int Width;

		public readonly int Height;

		public AtlasRect(int x, int y, int width, int height)
		{
			X = x;
			Y = y;
			Width = width;
			Height = height;
		}
	}
	public sealed class AtlasLayout
	{
		public int Width { get; }

		public int Height { get; }

		public IReadOnlyDictionary<string, AtlasRect> Rects { get; }

		public AtlasLayout(int width, int height, IReadOnlyDictionary<string, AtlasRect> rects)
		{
			Width = width;
			Height = height;
			Rects = rects;
		}

		public bool TryGetUv(string name, out float u0, out float v0, out float u1, out float v1)
		{
			u0 = (v0 = (u1 = (v1 = 0f)));
			if (name == null || !Rects.TryGetValue(name, out var value))
			{
				return false;
			}
			u0 = (float)value.X / (float)Width;
			v0 = (float)value.Y / (float)Height;
			u1 = (float)(value.X + value.Width) / (float)Width;
			v1 = (float)(value.Y + value.Height) / (float)Height;
			return true;
		}
	}
	public static class ChunkSplitter
	{
		public static IReadOnlyList<int> Chunks(int amount, int stackSize)
		{
			List<int> list = new List<int>();
			if (amount <= 0)
			{
				return list;
			}
			int num = ((stackSize < 1) ? 1 : stackSize);
			int num2 = amount;
			while (num2 > 0)
			{
				int num3 = ((num2 < num) ? num2 : num);
				list.Add(num3);
				num2 -= num3;
			}
			return list;
		}
	}
	public static class DrawerMeshBuilder
	{
		private const float UvScale = 1f;

		private static readonly int[] Signs = new int[2] { -1, 1 };

		public static MeshData Build(DrawerProportions p)
		{
			MeshData.Builder builder = new MeshData.Builder();
			float width = p.Width;
			float height = p.Height;
			float depth = p.Depth;
			float num = Math.Min(p.FrameThickness, Math.Min(width, height) / 2f - 0.02f);
			float num2 = Math.Min(p.RecessDepth, depth * 0.5f);
			float bevel = p.Bevel;
			AddChamferBox(builder, 0f, 0f, (0f - num2) / 2f, width, height, depth - num2, bevel);
			float cz = depth / 2f - num2 / 2f;
			AddChamferBox(builder, 0f, height / 2f - num / 2f, cz, width, num, num2, bevel);
			AddChamferBox(builder, 0f, (0f - height) / 2f + num / 2f, cz, width, num, num2, bevel);
			float num3 = height - 2f * num;
			if (num3 > 0.01f)
			{
				AddChamferBox(builder, (0f - width) / 2f + num / 2f, 0f, cz, num, num3, num2, bevel);
				AddChamferBox(builder, width / 2f - num / 2f, 0f, cz, num, num3, num2, bevel);
			}
			AddHandle(builder, p, num, num2);
			return builder.Build();
		}

		private static void AddHandle(MeshData.Builder gb, DrawerProportions p, float frame, float recess)
		{
			float num = p.Depth / 2f - recess;
			float num2 = p.Height - 2f * frame;
			switch (p.Handle)
			{
			case HandleStyle.Bar:
			{
				float w2 = Math.Min(p.HandleWidth, p.Width - 2f * frame - 0.02f);
				float cy = (0f - num2) / 2f + p.HandleSection * 1.4f;
				AddChamferBox(gb, 0f, cy, num + p.HandleProud / 2f, w2, p.HandleSection, p.HandleProud, Math.Min(p.Bevel, p.HandleSection / 2.5f));
				break;
			}
			case HandleStyle.Knobs:
			{
				float num3 = Math.Min(p.HandleWidth / 2f, p.Width / 2f - frame - p.HandleSection);
				for (int i = -1; i <= 1; i += 2)
				{
					AddChamferBox(gb, num3 * (float)i, 0f, num + p.HandleProud / 2f, p.HandleSection, p.HandleSection, p.HandleProud, p.HandleSection / 3f);
				}
				break;
			}
			case HandleStyle.Pull:
			{
				float w = Math.Min(p.HandleWidth, p.Width - 2f * frame);
				AddChamferBox(gb, 0f, (0f - p.Height) / 2f + frame + p.HandleSection / 2f, p.Depth / 2f - p.HandleProud / 2f, w, p.HandleSection, p.HandleProud, p.Bevel);
				break;
			}
			case HandleStyle.None:
				break;
			}
		}

		public static MeshData ChamferBox(float cx, float cy, float cz, float w, float h, float d, float chamfer)
		{
			MeshData.Builder builder = new MeshData.Builder();
			AddChamferBox(builder, cx, cy, cz, w, h, d, chamfer);
			return builder.Build();
		}

		private static void AddChamferBox(MeshData.Builder gb, float cx, float cy, float cz, float w, float h, float d, float chamfer)
		{
			float num = w / 2f;
			float num2 = h / 2f;
			float num3 = d / 2f;
			float num4 = Math.Max(0f, Math.Min(chamfer, Math.Min(num, Math.Min(num2, num3)) * 0.98f));
			float[] extent = new float[3] { num, num2, num3 };
			float[] inner = new float[3]
			{
				num - num4,
				num2 - num4,
				num3 - num4
			};
			float[] centre = new float[3] { cx, cy, cz };
			int[][] array = new int[4][]
			{
				new int[2] { -1, -1 },
				new int[2] { 1, -1 },
				new int[2] { 1, 1 },
				new int[2] { -1, 1 }
			};
			int[] signs;
			for (int i = 0; i < 3; i++)
			{
				signs = Signs;
				foreach (int num5 in signs)
				{
					int num6 = (i + 1) % 3;
					int num7 = (i + 2) % 3;
					float[][] array2 = new float[4][];
					for (int k = 0; k < 4; k++)
					{
						int[] array3 = new int[3];
						array3[i] = num5;
						array3[num6] = array[k][0];
						array3[num7] = array[k][1];
						array2[k] = Point(i, array3);
					}
					float[] array4 = new float[3];
					array4[i] = num5;
					gb.Quad(array2[0], array2[1], array2[2], array2[3], array4, 1f);
				}
			}
			for (int l = 0; l < 3; l++)
			{
				int num8 = (l + 1) % 3;
				int num9 = (l + 2) % 3;
				signs = Signs;
				foreach (int num10 in signs)
				{
					int[] signs2 = Signs;
					foreach (int num11 in signs2)
					{
						float[][] array5 = new float[2][];
						float[][] array6 = new float[2][];
						for (int n = 0; n < 2; n++)
						{
							int[] array7 = new int[3];
							array7[l] = Signs[n];
							array7[num8] = num10;
							array7[num9] = num11;
							array5[n] = Point(num8, array7);
							array6[n] = Point(num9, array7);
						}
						float[] array8 = new float[3];
						array8[num8] = num10;
						array8[num9] = num11;
						gb.Quad(array5[0], array5[1], array6[1], array6[0], array8, 1f);
					}
				}
			}
			signs = Signs;
			foreach (int num12 in signs)
			{
				int[] signs2 = Signs;
				foreach (int num13 in signs2)
				{
					int[] signs3 = Signs;
					foreach (int num15 in signs3)
					{
						int[] s = new int[3] { num12, num13, num15 };
						float[] hint = new float[3] { num12, num13, num15 };
						gb.TriangleHinted(Point(0, s), Point(1, s), Point(2, s), hint, 1f);
					}
				}
			}
			float[] Point(int axis, int[] array10)
			{
				float[] array9 = new float[3];
				for (int num16 = 0; num16 < 3; num16++)
				{
					array9[num16] = centre[num16] + (float)array10[num16] * ((num16 == axis) ? extent[num16] : inner[num16]);
				}
				return array9;
			}
		}
	}
	public readonly struct DrawerOutcome
	{
		public readonly bool Accepted;

		public readonly DrawerSnapshot Result;

		public readonly int MovedToDrawer;

		public readonly int MovedToPlayer;

		public readonly string Rejection;

		private DrawerOutcome(bool accepted, DrawerSnapshot result, int toDrawer, int toPlayer, string rejection)
		{
			Accepted = accepted;
			Result = result;
			MovedToDrawer = toDrawer;
			MovedToPlayer = toPlayer;
			Rejection = rejection;
		}

		public static DrawerOutcome Deposited(DrawerSnapshot result, int moved)
		{
			return new DrawerOutcome(accepted: true, result, moved, 0, null);
		}

		public static DrawerOutcome Withdrew(DrawerSnapshot result, int moved)
		{
			return new DrawerOutcome(accepted: true, result, 0, moved, null);
		}

		public static DrawerOutcome Changed(DrawerSnapshot result)
		{
			return new DrawerOutcome(accepted: true, result, 0, 0, null);
		}

		public static DrawerOutcome Refused(DrawerSnapshot unchanged, string why)
		{
			return new DrawerOutcome(accepted: false, unchanged, 0, 0, why);
		}
	}
	public enum HandleStyle
	{
		None,
		Bar,
		Knobs,
		Pull
	}
	public sealed class DrawerProportions
	{
		public float Width = 0.66f;

		public float Height = 0.66f;

		public float Depth = 0.66f;

		public float FrameThickness = 0.033f;

		public float RecessDepth = 0.0198f;

		public float Bevel = 0.00396f;

		public float HandleWidth = 0.264f;

		public float HandleSection = 0.0429f;

		public float HandleProud = 0.0231f;

		public HandleStyle Handle = HandleStyle.Bar;

		public float LabelScale = 0.98f;

		public float LabelSize
		{
			get
			{
				float num = Width - 2f * FrameThickness;
				float num2 = Height - 2f * FrameThickness;
				if (Handle == HandleStyle.Bar)
				{
					num2 -= HandleSection * 3f;
				}
				float num3 = ((num < num2) ? num : num2) * LabelScale;
				if (!(num3 < 0.05f))
				{
					return num3;
				}
				return 0.05f;
			}
		}
	}
	public readonly struct DrawerSnapshot : IEquatable<DrawerSnapshot>
	{
		public readonly string ItemName;

		public readonly int Amount;

		public bool IsAssigned => !string.IsNullOrEmpty(ItemName);

		public bool IsEmpty => Amount <= 0;

		public DrawerSnapshot(string itemName, int amount)
		{
			ItemName = itemName ?? "";
			Amount = ((amount >= 0) ? amount : 0);
		}

		public bool Equals(DrawerSnapshot other)
		{
			if (string.Equals(ItemName, other.ItemName, StringComparison.Ordinal))
			{
				return Amount == other.Amount;
			}
			return false;
		}

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

		public override int GetHashCode()
		{
			return ((ItemName?.GetHashCode() ?? 0) * 397) ^ Amount;
		}

		public override string ToString()
		{
			if (!IsAssigned)
			{
				return "(empty drawer)";
			}
			return $"{ItemName} x{Amount}";
		}
	}
	public static class DrawerState
	{
		public const string WrongItem = "This drawer holds a different item";

		public const string DrawerFull = "This drawer is full";

		public const string DrawerEmpty = "This drawer has been drained";

		public const string NotAssigned = "This drawer has not been assigned";

		public const string BadCapacity = "This drawer has an invalid capacity";

		public const string NotEmptyYet = "Empty the drawer before clearing it";

		public const string NothingOffered = "Nothing to deposit";

		public static DrawerOutcome Deposit(DrawerSnapshot current, int capacity, string itemName, int offered)
		{
			if (offered <= 0)
			{
				return DrawerOutcome.Refused(current, "Nothing to deposit");
			}
			if (string.IsNullOrEmpty(itemName))
			{
				return DrawerOutcome.Refused(current, "Nothing to deposit");
			}
			if (capacity <= 0)
			{
				return DrawerOutcome.Refused(current, "This drawer has an invalid capacity");
			}
			if (current.IsAssigned && current.ItemName != itemName)
			{
				return DrawerOutcome.Refused(current, "This drawer holds a different item");
			}
			int num = capacity - current.Amount;
			if (num <= 0)
			{
				return DrawerOutcome.Refused(current, "This drawer is full");
			}
			int num2 = ((offered < num) ? offered : num);
			return DrawerOutcome.Deposited(new DrawerSnapshot(itemName, current.Amount + num2), num2);
		}

		public static DrawerOutcome WithdrawStack(DrawerSnapshot current, int maxStackSize)
		{
			if (!current.IsAssigned)
			{
				return DrawerOutcome.Refused(current, "This drawer has not been assigned");
			}
			if (current.IsEmpty)
			{
				return DrawerOutcome.Refused(current, "This drawer has been drained");
			}
			int num = ((maxStackSize < 1) ? 1 : maxStackSize);
			int num2 = ((current.Amount < num) ? current.Amount : num);
			return DrawerOutcome.Withdrew(new DrawerSnapshot(current.ItemName, current.Amount - num2), num2);
		}

		public static DrawerOutcome WithdrawOne(DrawerSnapshot current)
		{
			if (!current.IsAssigned)
			{
				return DrawerOutcome.Refused(current, "This drawer has not been assigned");
			}
			if (current.IsEmpty)
			{
				return DrawerOutcome.Refused(current, "This drawer has been drained");
			}
			return DrawerOutcome.Withdrew(new DrawerSnapshot(current.ItemName, current.Amount - 1), 1);
		}

		public static DrawerOutcome WithdrawExact(DrawerSnapshot current, int requested)
		{
			if (requested <= 0 || !current.IsAssigned || current.IsEmpty)
			{
				return DrawerOutcome.Withdrew(current, 0);
			}
			int num = ((requested < current.Amount) ? requested : current.Amount);
			return DrawerOutcome.Withdrew(new DrawerSnapshot(current.ItemName, current.Amount - num), num);
		}

		public static DrawerOutcome Clear(DrawerSnapshot current)
		{
			if (!current.IsEmpty)
			{
				return DrawerOutcome.Refused(current, "Empty the drawer before clearing it");
			}
			return DrawerOutcome.Changed(new DrawerSnapshot("", 0));
		}

		public static int RefundShortfall(int removed, int accepted)
		{
			int num = removed - accepted;
			if (num <= 0)
			{
				return 0;
			}
			return num;
		}
	}
	public static class DrawerTextureGenerator
	{
		private readonly struct Knot
		{
			public readonly float X;

			public readonly float Y;

			public readonly float Radius;

			public readonly float Strength;

			public Knot(float x, float y, float radius, float strength)
			{
				X = x;
				Y = y;
				Radius = radius;
				Strength = strength;
			}
		}

		public static TextureData Generate(TextureTier tier, int width, int height, int seed)
		{
			if (width < 2 || height < 2)
			{
				throw new ArgumentException($"Texture must be at least 2x2, got {width}x{height}.");
			}
			float[] heights = BuildHeightField(tier, width, height, seed);
			byte[] albedo = BuildAlbedo(tier, heights, width, height);
			byte[] normal = BuildNormal(heights, width, height, NormalStrength(tier));
			return new TextureData(width, height, albedo, normal);
		}

		private static float[] BuildHeightField(TextureTier tier, int width, int height, int seed)
		{
			return tier switch
			{
				TextureTier.Wood => BuildWoodHeight(width, height, seed), 
				TextureTier.Stone => BuildStoneHeight(width, height, seed), 
				TextureTier.BlackMarble => BuildMarbleHeight(width, height, seed), 
				_ => BuildWoodHeight(width, height, seed), 
			};
		}

		private static float[] BuildWoodHeight(int width, int height, int seed)
		{
			float[] array = new float[width * height];
			Knot[] knots = MakeKnots(seed, width, height, 3, 6f, 14f);
			for (int i = 0; i < height; i++)
			{
				for (int j = 0; j < width; j++)
				{
					float num = PeriodicNoise.Fbm(j, i, width, height, seed + 11, 2, 7, 2f, 0.6f) * 1.3f;
					float num2 = (float)i * 7f / (float)height + num;
					float num3 = num2 - (float)Math.Floor(num2);
					float num4 = Math.Min(num3, 1f - num3);
					float num5 = 1f - Clamp01(num4 / 0.08f);
					float num6 = PeriodicNoise.Fbm(j, i, width, height, seed + 23, 4, 48, 2.1f, 0.55f);
					float num7 = PeriodicNoise.Fbm(j, i, width, height, seed + 37, 3, 5);
					float num8 = KnotContribution(knots, j, i, width, height);
					float v = 0.55f + num7 * 0.08f + num6 * 0.018f - num5 * 0.14f + num8;
					array[i * width + j] = Clamp01(v);
				}
			}
			return array;
		}

		private static float[] BuildStoneHeight(int width, int height, int seed)
		{
			float[] array = new float[width * height];
			for (int i = 0; i < height; i++)
			{
				for (int j = 0; j < width; j++)
				{
					float num = PeriodicNoise.Fbm(j, i, width, height, seed + 5, 3, 6);
					float num2 = PeriodicNoise.Fbm(j, i, width, height, seed + 61, 3, 34);
					float v = 0.5f + num * 0.15f + num2 * 0.045f;
					array[i * width + j] = Clamp01(v);
				}
			}
			return array;
		}

		private static float[] BuildMarbleHeight(int width, int height, int seed)
		{
			float[] array = new float[width * height];
			for (int i = 0; i < height; i++)
			{
				for (int j = 0; j < width; j++)
				{
					float value = PeriodicNoise.Fbm(j, i, width, height, seed + 7, 3, 5, 2.3f);
					float num = (float)Math.Pow(Clamp01((1f - Math.Abs(value) - 0.82f) / 0.18f), 2.0);
					float num2 = PeriodicNoise.Fbm(j, i, width, height, seed + 89, 2, 40);
					float v = 0.16f + num * 0.22f + num2 * 0.02f;
					array[i * width + j] = Clamp01(v);
				}
			}
			return array;
		}

		private static Knot[] MakeKnots(int seed, int width, int height, int count, float minRadius, float maxRadius)
		{
			Random random = new Random(seed + 999);
			Knot[] array = new Knot[count];
			float num = (float)width / 2f;
			float num2 = (float)height / 2f;
			float num3 = (float)width * 0.22f;
			float num4 = (float)height * 0.22f;
			for (int i = 0; i < count; i++)
			{
				float num5 = 0f;
				float num6 = 0f;
				for (int j = 0; j < 20; j++)
				{
					num5 = (float)(random.NextDouble() * (double)width);
					num6 = (float)(random.NextDouble() * (double)height);
					if (!(Math.Abs(num5 - num) < num3) || !(Math.Abs(num6 - num2) < num4))
					{
						break;
					}
				}
				float radius = minRadius + (float)random.NextDouble() * (maxRadius - minRadius);
				float strength = 0.03f + (float)random.NextDouble() * 0.03f;
				array[i] = new Knot(num5, num6, radius, strength);
			}
			return array;
		}

		private static float KnotContribution(Knot[] knots, int x, int y, int width, int height)
		{
			float num = 0f;
			for (int i = 0; i < knots.Length; i++)
			{
				Knot knot = knots[i];
				float num2 = PeriodicNoise.ToroidalDistance(x, y, knot.X, knot.Y, width, height);
				if (!(num2 >= knot.Radius))
				{
					float num3 = num2 / knot.Radius;
					float num4 = (float)Math.Pow(1f - num3, 2.0);
					num -= knot.Strength * num4;
				}
			}
			return num;
		}

		private static (float r, float g, float b) HueRatio(TextureTier tier)
		{
			return tier switch
			{
				TextureTier.Wood => (r: 1f, g: 0.84f, b: 0.66f), 
				TextureTier.Stone => (r: 0.97f, g: 0.98f, b: 1f), 
				TextureTier.BlackMarble => (r: 0.86f, g: 0.95f, b: 1f), 
				_ => (r: 1f, g: 0.8f, b: 0.56f), 
			};
		}

		public static float MidLightness(TextureTier tier)
		{
			var (num, num2) = LightnessRange(tier);
			return (num + num2) / 2f;
		}

		private static (float min, float max) LightnessRange(TextureTier tier)
		{
			return tier switch
			{
				TextureTier.Wood => (min: 0.24f, max: 0.6f), 
				TextureTier.Stone => (min: 0.34f, max: 0.64f), 
				TextureTier.BlackMarble => (min: 0.04f, max: 0.3f), 
				_ => (min: 0.28f, max: 0.66f), 
			};
		}

		private static byte[] BuildAlbedo(TextureTier tier, float[] heights, int width, int height)
		{
			(float r, float g, float b) tuple = HueRatio(tier);
			float item = tuple.r;
			float item2 = tuple.g;
			float item3 = tuple.b;
			(float min, float max) tuple2 = LightnessRange(tier);
			float item4 = tuple2.min;
			float item5 = tuple2.max;
			byte[] array = new byte[width * height * 4];
			for (int i = 0; i < heights.Length; i++)
			{
				float num = item4 + heights[i] * (item5 - item4);
				int num2 = i * 4;
				array[num2] = ToByte(num * item);
				array[num2 + 1] = ToByte(num * item2);
				array[num2 + 2] = ToByte(num * item3);
				array[num2 + 3] = byte.MaxValue;
			}
			return array;
		}

		private static float NormalStrength(TextureTier tier)
		{
			return tier switch
			{
				TextureTier.Wood => 3f, 
				TextureTier.Stone => 1.6f, 
				TextureTier.BlackMarble => 1.1f, 
				_ => 2f, 
			};
		}

		private static byte[] BuildNormal(float[] heights, int width, int height, float strength)
		{
			byte[] array = new byte[width * height * 4];
			for (int i = 0; i < height; i++)
			{
				for (int j = 0; j < width; j++)
				{
					float num = At(heights, j - 1, i - 1, width, height);
					float num2 = At(heights, j, i - 1, width, height);
					float num3 = At(heights, j + 1, i - 1, width, height);
					float num4 = At(heights, j - 1, i, width, height);
					float num5 = At(heights, j + 1, i, width, height);
					float num6 = At(heights, j - 1, i + 1, width, height);
					float num7 = At(heights, j, i + 1, width, height);
					float num8 = At(heights, j + 1, i + 1, width, height);
					float num9 = num3 + 2f * num5 + num8 - (num + 2f * num4 + num6);
					float num10 = num6 + 2f * num7 + num8 - (num + 2f * num2 + num3);
					float num11 = (0f - num9) * strength;
					float num12 = (0f - num10) * strength;
					float num13 = 1f;
					float num14 = (float)Math.Sqrt(num11 * num11 + num12 * num12 + num13 * num13);
					num11 /= num14;
					num12 /= num14;
					num13 /= num14;
					int num15 = (i * width + j) * 4;
					array[num15] = ToByte(num11 * 0.5f + 0.5f);
					array[num15 + 1] = ToByte(num12 * 0.5f + 0.5f);
					array[num15 + 2] = ToByte(num13 * 0.5f + 0.5f);
					array[num15 + 3] = byte.MaxValue;
				}
			}
			return array;
		}

		private static float At(float[] field, int x, int y, int width, int height)
		{
			int num = (x % width + width) % width;
			int num2 = (y % height + height) % height;
			return field[num2 * width + num];
		}

		private static float Clamp01(float v)
		{
			if (!(v < 0f))
			{
				if (!(v > 1f))
				{
					return v;
				}
				return 1f;
			}
			return 0f;
		}

		private static byte ToByte(float v)
		{
			v = Clamp01(v);
			return (byte)Math.Round(v * 255f);
		}
	}
	public sealed class HandledRequestCache<T>
	{
		private readonly struct Entry
		{
			public readonly T Result;

			public readonly float RecordedAt;

			public Entry(T result, float recordedAt)
			{
				Result = result;
				RecordedAt = recordedAt;
			}
		}

		private readonly Dictionary<(long Sender, long Id), Entry> _entries = new Dictionary<(long, long), Entry>();

		private readonly float _lifetimeSeconds;

		public int Count => _entries.Count;

		public HandledRequestCache(float lifetimeSeconds)
		{
			_lifetimeSeconds = lifetimeSeconds;
		}

		public bool TryGet(long sender, long id, out T result)
		{
			if (_entries.TryGetValue((sender, id), out var value))
			{
				result = value.Result;
				return true;
			}
			result = default(T);
			return false;
		}

		public void Record(long sender, long id, T result, float now)
		{
			_entries[(sender, id)] = new Entry(result, now);
		}

		public void Prune(float now)
		{
			if (_entries.Count == 0)
			{
				return;
			}
			List<(long, long)> list = null;
			foreach (KeyValuePair<(long, long), Entry> entry in _entries)
			{
				if (now - entry.Value.RecordedAt > _lifetimeSeconds)
				{
					(list ?? (list = new List<(long, long)>())).Add(entry.Key);
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (var item in list)
			{
				_entries.Remove(item);
			}
		}
	}
	public static class IconAtlasPacker
	{
		private const int Padding = 2;

		public static AtlasLayout Pack(IReadOnlyList<IconSize> icons, int maxDimension = 4096)
		{
			if (icons == null)
			{
				throw new ArgumentNullException("icons");
			}
			if (icons.Count == 0)
			{
				return new AtlasLayout(1, 1, new Dictionary<string, AtlasRect>());
			}
			int num = maxDimension - 2;
			foreach (IconSize icon in icons)
			{
				if (icon.Width <= 0 || icon.Height <= 0)
				{
					throw new ArgumentException($"Icon '{icon.Name}' has invalid dimensions {icon.Width}×{icon.Height}. " + "Icon width and height must be positive.");
				}
				if (icon.Width > num || icon.Height > num)
				{
					throw new ArgumentException($"Icon '{icon.Name}' has dimensions {icon.Width}×{icon.Height}, " + $"but maximum icon size for maxDimension={maxDimension} is {num}×{num} " + $"(atlas dimension - {2} pixel padding).");
				}
			}
			List<IconSize> sorted = icons.OrderByDescending((IconSize i) => i.Height).ToList();
			for (int num2 = 64; num2 <= maxDimension; num2 *= 2)
			{
				if (TryPackInto(sorted, num2, out var rects))
				{
					return new AtlasLayout(num2, num2, rects);
				}
			}
			throw new InvalidOperationException($"Cannot fit {icons.Count} icons into a {maxDimension}×{maxDimension} atlas.");
		}

		private static bool TryPackInto(List<IconSize> sorted, int size, out Dictionary<string, AtlasRect> rects)
		{
			rects = new Dictionary<string, AtlasRect>(sorted.Count);
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			foreach (IconSize item in sorted)
			{
				int num4 = item.Width + 2;
				int num5 = item.Height + 2;
				if (num4 > size || num5 > size)
				{
					return false;
				}
				if (num3 + num4 > size)
				{
					num += num2;
					num2 = 0;
					num3 = 0;
				}
				if (num + num5 > size)
				{
					return false;
				}
				rects[item.Name] = new AtlasRect(num3, num, item.Width, item.Height);
				num3 += num4;
				if (num5 > num2)
				{
					num2 = num5;
				}
			}
			return true;
		}
	}
	public sealed class MeshData
	{
		internal sealed class Builder
		{
			private readonly List<float> _pos = new List<float>(4096);

			private readonly List<float> _nor = new List<float>(4096);

			private readonly List<float> _uv = new List<float>(2731);

			public void Triangle(float[] a, float[] b, float[] c, float uvScale)
			{
				float num = b[0] - a[0];
				float num2 = b[1] - a[1];
				float num3 = b[2] - a[2];
				float num4 = c[0] - a[0];
				float num5 = c[1] - a[1];
				float num6 = c[2] - a[2];
				float num7 = num2 * num6 - num3 * num5;
				float num8 = num3 * num4 - num * num6;
				float num9 = num * num5 - num2 * num4;
				float num10 = (float)Math.Sqrt(num7 * num7 + num8 * num8 + num9 * num9);
				if (!(num10 < 1E-09f))
				{
					num7 /= num10;
					num8 /= num10;
					num9 /= num10;
					float num11 = Math.Abs(num7);
					float num12 = Math.Abs(num8);
					float num13 = Math.Abs(num9);
					int num14;
					int num15;
					if (num11 >= num12 && num11 >= num13)
					{
						num14 = 2;
						num15 = 1;
					}
					else if (num12 >= num13)
					{
						num14 = 0;
						num15 = 2;
					}
					else
					{
						num14 = 0;
						num15 = 1;
					}
					float[][] array = new float[3][] { a, b, c };
					foreach (float[] array2 in array)
					{
						_pos.Add(array2[0]);
						_pos.Add(array2[1]);
						_pos.Add(array2[2]);
						_nor.Add(num7);
						_nor.Add(num8);
						_nor.Add(num9);
						_uv.Add(array2[num14] * uvScale);
						_uv.Add(array2[num15] * uvScale);
					}
				}
			}

			public void Quad(float[] a, float[] b, float[] c, float[] d, float[] hint, float uvScale)
			{
				float num = b[0] - a[0];
				float num2 = b[1] - a[1];
				float num3 = b[2] - a[2];
				float num4 = c[0] - a[0];
				float num5 = c[1] - a[1];
				float num6 = c[2] - a[2];
				float num7 = num2 * num6 - num3 * num5;
				float num8 = num3 * num4 - num * num6;
				float num9 = num * num5 - num2 * num4;
				if (num7 * hint[0] + num8 * hint[1] + num9 * hint[2] < 0f)
				{
					float[] array = b;
					b = d;
					d = array;
				}
				Triangle(a, b, c, uvScale);
				Triangle(a, c, d, uvScale);
			}

			public void TriangleHinted(float[] a, float[] b, float[] c, float[] hint, float uvScale)
			{
				float num = b[0] - a[0];
				float num2 = b[1] - a[1];
				float num3 = b[2] - a[2];
				float num4 = c[0] - a[0];
				float num5 = c[1] - a[1];
				float num6 = c[2] - a[2];
				float num7 = num2 * num6 - num3 * num5;
				float num8 = num3 * num4 - num * num6;
				float num9 = num * num5 - num2 * num4;
				if (num7 * hint[0] + num8 * hint[1] + num9 * hint[2] < 0f)
				{
					float[] array = b;
					b = c;
					c = array;
				}
				Triangle(a, b, c, uvScale);
			}

			public MeshData Build()
			{
				return new MeshData(_pos.ToArray(), _nor.ToArray(), _uv.ToArray());
			}
		}

		public float[] Vertices { get; }

		public float[] Normals { get; }

		public float[] Uvs { get; }

		public int VertexCount => Vertices.Length / 3;

		public int TriangleCount => VertexCount / 3;

		public MeshData(float[] vertices, float[] normals, float[] uvs)
		{
			Vertices = vertices;
			Normals = normals;
			Uvs = uvs;
		}
	}
	public readonly struct MirrorDelta : IEquatable<MirrorDelta>
	{
		public readonly int Withdraw;

		public static readonly MirrorDelta None = new MirrorDelta(0);

		private MirrorDelta(int withdraw)
		{
			Withdraw = withdraw;
		}

		public static MirrorDelta WithdrawOf(int amount)
		{
			return new MirrorDelta(amount);
		}

		public bool Equals(MirrorDelta other)
		{
			return Withdraw == other.Withdraw;
		}

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

		public override int GetHashCode()
		{
			return Withdraw;
		}

		public override string ToString()
		{
			if (Withdraw <= 0)
			{
				return "None";
			}
			return $"Withdraw({Withdraw})";
		}
	}
	public static class MirrorReconciliation
	{
		public static MirrorDelta Compute(string mirrorItemName, int mirrorTotal, string mirroredBaselineItemName, int mirroredBaselineAmount, string zdoItemName, int zdoAmount)
		{
			if (mirrorItemName != mirroredBaselineItemName)
			{
				return MirrorDelta.None;
			}
			if (mirroredBaselineItemName != zdoItemName)
			{
				return MirrorDelta.None;
			}
			int num = mirrorTotal - mirroredBaselineAmount;
			if (num >= 0)
			{
				return MirrorDelta.None;
			}
			int num2 = -num;
			int num3 = ((num2 < zdoAmount) ? num2 : zdoAmount);
			if (num3 > 0)
			{
				return MirrorDelta.WithdrawOf(num3);
			}
			return MirrorDelta.None;
		}
	}
	public sealed class PendingRequest<T>
	{
		public readonly long Id;

		public readonly T Payload;

		public int Attempts;

		public float Deadline;

		public PendingRequest(long id, T payload, int attempts, float deadline)
		{
			Id = id;
			Payload = payload;
			Attempts = attempts;
			Deadline = deadline;
		}
	}
	public sealed class PendingRequestLedger<T>
	{
		private readonly Dictionary<long, PendingRequest<T>> _pending = new Dictionary<long, PendingRequest<T>>();

		private readonly float _timeoutSeconds;

		private readonly int _maxAttempts;

		public int Count => _pending.Count;

		public PendingRequestLedger(float timeoutSeconds, int maxAttempts)
		{
			_timeoutSeconds = timeoutSeconds;
			_maxAttempts = maxAttempts;
		}

		public void Add(long id, T payload, float now)
		{
			_pending[id] = new PendingRequest<T>(id, payload, 1, now + _timeoutSeconds);
		}

		public bool TryComplete(long id, out T payload)
		{
			if (_pending.TryGetValue(id, out var value))
			{
				payload = value.Payload;
				_pending.Remove(id);
				return true;
			}
			payload = default(T);
			return false;
		}

		public bool Remove(long id, out T payload)
		{
			if (_pending.TryGetValue(id, out var value))
			{
				payload = value.Payload;
				_pending.Remove(id);
				return true;
			}
			payload = default(T);
			return false;
		}

		public IEnumerable<KeyValuePair<long, T>> All()
		{
			foreach (KeyValuePair<long, PendingRequest<T>> item in _pending)
			{
				yield return new KeyValuePair<long, T>(item.Key, item.Value.Payload);
			}
		}

		public void Tick(float now, Action<long, T> retry, Action<long, T> giveUp)
		{
			List<long> list = null;
			foreach (KeyValuePair<long, PendingRequest<T>> item in _pending)
			{
				if (!(now < item.Value.Deadline))
				{
					(list ?? (list = new List<long>())).Add(item.Key);
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (long item2 in list)
			{
				PendingRequest<T> pendingRequest = _pending[item2];
				if (pendingRequest.Attempts >= _maxAttempts)
				{
					_pending.Remove(item2);
					giveUp(item2, pendingRequest.Payload);
				}
				else
				{
					pendingRequest.Attempts++;
					pendingRequest.Deadline = now + _timeoutSeconds;
					retry(item2, pendingRequest.Payload);
				}
			}
		}
	}
	public static class PeriodicNoise
	{
		public static float Sample(float x, float y, int cells, int seed)
		{
			if (cells < 1)
			{
				cells = 1;
			}
			float num = (float)Math.Floor(x);
			float num2 = (float)Math.Floor(y);
			int num3 = Mod((int)num, cells);
			int num4 = Mod((int)num2, cells);
			int x2 = Mod(num3 + 1, cells);
			int y2 = Mod(num4 + 1, cells);
			float t = x - num;
			float t2 = y - num2;
			float t3 = Fade(t);
			float t4 = Fade(t2);
			float a = HashValue(num3, num4, seed);
			float b = HashValue(x2, num4, seed);
			float a2 = HashValue(num3, y2, seed);
			float b2 = HashValue(x2, y2, seed);
			float a3 = Lerp(a, b, t3);
			float b3 = Lerp(a2, b2, t3);
			return Lerp(a3, b3, t4);
		}

		public static float Fbm(float px, float py, int width, int height, int seed, int octaves, int baseCells, float lacunarity = 2f, float gain = 0.5f)
		{
			float num = 0f;
			float num2 = 1f;
			float num3 = 0f;
			int num4 = Math.Max(1, baseCells);
			for (int i = 0; i < octaves; i++)
			{
				float x = px * (float)num4 / (float)width;
				float y = py * (float)num4 / (float)height;
				num += Sample(x, y, num4, seed + i * 101) * num2;
				num3 += num2;
				num2 *= gain;
				num4 = Math.Max(1, (int)Math.Round((float)num4 * lacunarity));
			}
			if (!(num3 > 0f))
			{
				return 0f;
			}
			return num / num3;
		}

		public static float ToroidalDistance(float ax, float ay, float bx, float by, int width, int height)
		{
			float num = WrapDelta(ax - bx, width);
			float num2 = WrapDelta(ay - by, height);
			return (float)Math.Sqrt(num * num + num2 * num2);
		}

		private static float WrapDelta(float d, int period)
		{
			d %= (float)period;
			if (d > (float)period / 2f)
			{
				d -= (float)period;
			}
			if (d < (float)(-period) / 2f)
			{
				d += (float)period;
			}
			return d;
		}

		private static int Mod(int a, int m)
		{
			int num = a % m;
			if (num >= 0)
			{
				return num;
			}
			return num + m;
		}

		private static float Fade(float t)
		{
			return t * t * t * (t * (t * 6f - 15f) + 10f);
		}

		private static float Lerp(float a, float b, float t)
		{
			return a + t * (b - a);
		}

		private static float HashValue(int x, int y, int seed)
		{
			int num = x * 374761393 + y * 668265263 + seed * 1274126177;
			int num2 = (num ^ (num >>> 13)) * 1274126177;
			return (float)(uint)(num2 ^ (num2 >>> 16)) / 4.2949673E+09f * 2f - 1f;
		}
	}
	public sealed class RequestIdGenerator
	{
		private long _next;

		public RequestIdGenerator(long seed)
		{
			_next = seed;
		}

		public long Next()
		{
			return ++_next;
		}
	}
	public sealed class SpatialGrid<T>
	{
		private readonly struct Cell : IEquatable<Cell>
		{
			public readonly int X;

			public readonly int Y;

			public readonly int Z;

			public Cell(int x, int y, int z)
			{
				X = x;
				Y = y;
				Z = z;
			}

			public bool Equals(Cell o)
			{
				if (X == o.X && Y == o.Y)
				{
					return Z == o.Z;
				}
				return false;
			}

			public override bool Equals(object o)
			{
				if (o is Cell o2)
				{
					return Equals(o2);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (X * 73856093) ^ (Y * 19349663) ^ (Z * 83492791);
			}
		}

		private readonly float _cellSize;

		private readonly Dictionary<Cell, List<T>> _cells = new Dictionary<Cell, List<T>>();

		private readonly Dictionary<T, (Cell cell, float x, float y, float z)> _index = new Dictionary<T, (Cell, float, float, float)>();

		public int Count => _index.Count;

		public SpatialGrid(float cellSize)
		{
			if (cellSize <= 0f)
			{
				throw new ArgumentOutOfRangeException("cellSize");
			}
			_cellSize = cellSize;
		}

		private Cell CellOf(float x, float y, float z)
		{
			return new Cell((int)Math.Floor(x / _cellSize), (int)Math.Floor(y / _cellSize), (int)Math.Floor(z / _cellSize));
		}

		public void Insert(T item, float x, float y, float z)
		{
			if (_index.ContainsKey(item))
			{
				Move(item, x, y, z);
				return;
			}
			Cell cell = CellOf(x, y, z);
			if (!_cells.TryGetValue(cell, out var value))
			{
				value = new List<T>(4);
				_cells[cell] = value;
			}
			value.Add(item);
			_index[item] = (cell, x, y, z);
		}

		public bool Remove(T item)
		{
			if (!_index.TryGetValue(item, out (Cell, float, float, float) value))
			{
				return false;
			}
			if (_cells.TryGetValue(value.Item1, out var value2))
			{
				value2.Remove(item);
				if (value2.Count == 0)
				{
					_cells.Remove(value.Item1);
				}
			}
			_index.Remove(item);
			return true;
		}

		public void Move(T item, float x, float y, float z)
		{
			Remove(item);
			Insert(item, x, y, z);
		}

		public void Query(float x, float y, float z, float radius, List<T> results)
		{
			if (results == null)
			{
				throw new ArgumentNullException("results");
			}
			if (radius <= 0f)
			{
				return;
			}
			int num = (int)Math.Ceiling(radius / _cellSize);
			Cell cell = CellOf(x, y, z);
			float num2 = radius * radius;
			for (int i = -num; i <= num; i++)
			{
				for (int j = -num; j <= num; j++)
				{
					for (int k = -num; k <= num; k++)
					{
						Cell key = new Cell(cell.X + i, cell.Y + j, cell.Z + k);
						if (!_cells.TryGetValue(key, out var value))
						{
							continue;
						}
						for (int l = 0; l < value.Count; l++)
						{
							T val = value[l];
							(Cell cell, float x, float y, float z) tuple = _index[val];
							float num3 = tuple.x - x;
							float num4 = tuple.y - y;
							float num5 = tuple.z - z;
							if (num3 * num3 + num4 * num4 + num5 * num5 <= num2)
							{
								results.Add(val);
							}
						}
					}
				}
			}
		}
	}
	public sealed class TextureData
	{
		public int Width { get; }

		public int Height { get; }

		public byte[] Albedo { get; }

		public byte[] Normal { get; }

		public TextureData(int width, int height, byte[] albedo, byte[] normal)
		{
			Width = width;
			Height = height;
			Albedo = albedo;
			Normal = normal;
		}
	}
	public enum TextureTier
	{
		Wood,
		Stone,
		BlackMarble
	}
}

plugins/ItemDrawers.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using ItemDrawers.Core;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ItemDrawers")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+913107a17ca521c047e50107cd807fb5861366ab")]
[assembly: AssemblyProduct("ItemDrawers")]
[assembly: AssemblyTitle("ItemDrawers")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ItemDrawers.Game
{
	internal static class ContainerBridge
	{
		[HarmonyPatch(typeof(Container), "Awake")]
		private static class AwakePatch
		{
			private static bool Prepare()
			{
				return ValheimCompat.RequireMethod(typeof(Container), "Awake");
			}

			private static bool Prefix(Container __instance)
			{
				return !(__instance is DrawerComponent);
			}
		}

		[HarmonyPatch(typeof(Container), "GetInventory")]
		private static class GetInventoryPatch
		{
			private static bool Prepare()
			{
				return ValheimCompat.RequireMethod(typeof(Container), "GetInventory");
			}

			private static void Prefix(Container __instance)
			{
				if (__instance is DrawerComponent drawerComponent)
				{
					drawerComponent.RefreshMirror();
				}
			}

			private static void Postfix(Container __instance, ref Inventory __result)
			{
				if (__instance is DrawerComponent drawerComponent)
				{
					__result = drawerComponent.MirrorInventory;
				}
			}
		}

		[HarmonyPatch(typeof(Container), "Save")]
		private static class SavePatch
		{
			private static bool Prepare()
			{
				return ValheimCompat.RequireMethod(typeof(Container), "Save");
			}

			private static bool Prefix(Container __instance)
			{
				return !(__instance is DrawerComponent);
			}
		}

		[HarmonyPatch(typeof(Container), "Load")]
		private static class LoadPatch
		{
			private static bool Prepare()
			{
				return ValheimCompat.RequireMethod(typeof(Container), "Load");
			}

			private static bool Prefix(Container __instance)
			{
				return !(__instance is DrawerComponent);
			}
		}
	}
	internal static class DebugCommands
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__2_0;

			public static ConsoleEvent <>9__2_1;

			internal void <Register>b__2_0(ConsoleEventArgs args)
			{
				//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c5: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d8: 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_00e4: Expected O, but got Unknown
				//IL_0112: Unknown result type (might be due to invalid IL or missing references)
				//IL_0114: Unknown result type (might be due to invalid IL or missing references)
				//IL_0127: Unknown result type (might be due to invalid IL or missing references)
				//IL_012c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0131: Unknown result type (might be due to invalid IL or missing references)
				//IL_014a: Unknown result type (might be due to invalid IL or missing references)
				//IL_014f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0154: Unknown result type (might be due to invalid IL or missing references)
				//IL_0157: Unknown result type (might be due to invalid IL or missing references)
				//IL_015b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0160: Unknown result type (might be due to invalid IL or missing references)
				//IL_0165: Unknown result type (might be due to invalid IL or missing references)
				//IL_016a: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)Player.m_localPlayer == (Object)null)
				{
					return;
				}
				int num = ((args.Length > 1) ? int.Parse(args[1]) : 10);
				int num2 = ((args.Length > 2) ? int.Parse(args[2]) : 10);
				DrawerTier drawerTier = DrawerTier.Wood;
				if (args.Length > 3)
				{
					if (args[3].Equals("stone", StringComparison.OrdinalIgnoreCase))
					{
						drawerTier = DrawerTier.Stone;
					}
					else if (args[3].StartsWith("black", StringComparison.OrdinalIgnoreCase))
					{
						drawerTier = DrawerTier.BlackMarble;
					}
				}
				GameObject prefab = ZNetScene.instance.GetPrefab(DrawerTiers.PrefabName(drawerTier));
				if ((Object)(object)prefab == (Object)null)
				{
					args.Context.AddString("Drawer prefab not found");
					return;
				}
				Transform transform = ((Component)Player.m_localPlayer).transform;
				Vector3 val = transform.position + transform.forward * 6f;
				Vector3 right = transform.right;
				int num3 = 0;
				DrawerProportions val2 = new DrawerProportions();
				float num4 = val2.Width + 0.02f;
				float num5 = val2.Height + 0.02f;
				for (int i = 0; i < num2; i++)
				{
					for (int j = 0; j < num; j++)
					{
						Vector3 val3 = val + right * (((float)j - (float)(num - 1) / 2f) * num4) + Vector3.up * ((float)i * num5 + val2.Height / 2f);
						DrawerComponent component = Object.Instantiate<GameObject>(prefab, val3, Quaternion.LookRotation(-transform.forward, Vector3.up)).GetComponent<DrawerComponent>();
						if ((Object)(object)component != (Object)null)
						{
							string itemName = SampleItems[(j + i * num) % SampleItems.Length];
							component.TryDepositExternally(itemName, 250 + (j * 7 + i * 13) % 500, out var _);
						}
						num3++;
					}
				}
				args.Context.AddString($"Built {num3} drawers ({num}x{num2}, {drawerTier})");
			}

			internal void <Register>b__2_1(ConsoleEventArgs args)
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				int count = DrawerComponent.All.Count;
				int num = 0;
				int num2 = 0;
				foreach (DrawerComponent item in DrawerComponent.All)
				{
					DrawerSnapshot snapshot = item.Snapshot;
					if (((DrawerSnapshot)(ref snapshot)).IsAssigned)
					{
						num++;
					}
					num2 += snapshot.Amount;
				}
				args.Context.AddString($"drawers loaded : {count}");
				args.Context.AddString($"assigned       : {num}");
				args.Context.AddString($"items held     : {num2}");
				args.Context.AddString($"atlas built    : {DrawerIconAtlas.IsBuilt}");
			}
		}

		private static readonly string[] SampleItems = new string[6] { "Wood", "Stone", "Coal", "Iron", "Resin", "Flint" };

		private const float WallGap = 0.02f;

		public static void Register()
		{
			//IL_0033: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_006c: 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_0062: Expected O, but got Unknown
			object obj = <>c.<>9__2_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
					//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
					//IL_00c5: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
					//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
					//IL_00d8: 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_00e4: Expected O, but got Unknown
					//IL_0112: Unknown result type (might be due to invalid IL or missing references)
					//IL_0114: Unknown result type (might be due to invalid IL or missing references)
					//IL_0127: Unknown result type (might be due to invalid IL or missing references)
					//IL_012c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0131: Unknown result type (might be due to invalid IL or missing references)
					//IL_014a: Unknown result type (might be due to invalid IL or missing references)
					//IL_014f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0154: Unknown result type (might be due to invalid IL or missing references)
					//IL_0157: Unknown result type (might be due to invalid IL or missing references)
					//IL_015b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0160: Unknown result type (might be due to invalid IL or missing references)
					//IL_0165: Unknown result type (might be due to invalid IL or missing references)
					//IL_016a: Unknown result type (might be due to invalid IL or missing references)
					if (!((Object)(object)Player.m_localPlayer == (Object)null))
					{
						int num = ((args.Length > 1) ? int.Parse(args[1]) : 10);
						int num2 = ((args.Length > 2) ? int.Parse(args[2]) : 10);
						DrawerTier drawerTier = DrawerTier.Wood;
						if (args.Length > 3)
						{
							if (args[3].Equals("stone", StringComparison.OrdinalIgnoreCase))
							{
								drawerTier = DrawerTier.Stone;
							}
							else if (args[3].StartsWith("black", StringComparison.OrdinalIgnoreCase))
							{
								drawerTier = DrawerTier.BlackMarble;
							}
						}
						GameObject prefab = ZNetScene.instance.GetPrefab(DrawerTiers.PrefabName(drawerTier));
						if ((Object)(object)prefab == (Object)null)
						{
							args.Context.AddString("Drawer prefab not found");
						}
						else
						{
							Transform transform = ((Component)Player.m_localPlayer).transform;
							Vector3 val3 = transform.position + transform.forward * 6f;
							Vector3 right = transform.right;
							int num3 = 0;
							DrawerProportions val4 = new DrawerProportions();
							float num4 = val4.Width + 0.02f;
							float num5 = val4.Height + 0.02f;
							for (int i = 0; i < num2; i++)
							{
								for (int j = 0; j < num; j++)
								{
									Vector3 val5 = val3 + right * (((float)j - (float)(num - 1) / 2f) * num4) + Vector3.up * ((float)i * num5 + val4.Height / 2f);
									DrawerComponent component = Object.Instantiate<GameObject>(prefab, val5, Quaternion.LookRotation(-transform.forward, Vector3.up)).GetComponent<DrawerComponent>();
									if ((Object)(object)component != (Object)null)
									{
										string itemName = SampleItems[(j + i * num) % SampleItems.Length];
										component.TryDepositExternally(itemName, 250 + (j * 7 + i * 13) % 500, out var _);
									}
									num3++;
								}
							}
							args.Context.AddString($"Built {num3} drawers ({num}x{num2}, {drawerTier})");
						}
					}
				};
				<>c.<>9__2_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("rid_wall", "rid_wall <cols> <rows> [wood|stone|blackmarble] - build a test wall of drawers", (ConsoleEvent)obj, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj2 = <>c.<>9__2_1;
			if (obj2 == null)
			{
				ConsoleEvent val2 = delegate(ConsoleEventArgs args)
				{
					//IL_0023: Unknown result type (might be due to invalid IL or missing references)
					//IL_0028: Unknown result type (might be due to invalid IL or missing references)
					//IL_0038: Unknown result type (might be due to invalid IL or missing references)
					int count = DrawerComponent.All.Count;
					int num = 0;
					int num2 = 0;
					foreach (DrawerComponent item in DrawerComponent.All)
					{
						DrawerSnapshot snapshot = item.Snapshot;
						if (((DrawerSnapshot)(ref snapshot)).IsAssigned)
						{
							num++;
						}
						num2 += snapshot.Amount;
					}
					args.Context.AddString($"drawers loaded : {count}");
					args.Context.AddString($"assigned       : {num}");
					args.Context.AddString($"items held     : {num2}");
					args.Context.AddString($"atlas built    : {DrawerIconAtlas.IsBuilt}");
				};
				<>c.<>9__2_1 = val2;
				obj2 = (object)val2;
			}
			new ConsoleCommand("rid_stats", "rid_stats - report drawer counts and rendering cost", (ConsoleEvent)obj2, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}
	}
	public class DrawerComponent : Container, Interactable, Hoverable
	{
		public static readonly List<DrawerComponent> All = new List<DrawerComponent>();

		private const string KeyPrefab = "Prefab";

		private const string KeyAmount = "Amount";

		private static readonly int KeyPrefabHash = StringExtensionMethods.GetStableHashCode("Prefab");

		private static readonly int KeyAmountHash = StringExtensionMethods.GetStableHashCode("Amount");

		private static readonly int CreatorHash = StringExtensionMethods.GetStableHashCode("creator");

		internal const string CommitFailedMessage = "Try again";

		internal const string RpcReqWithdraw = "RID_ReqWithdraw";

		internal const string RpcGrantWithdraw = "RID_GrantWithdraw";

		internal const string RpcReqDeposit = "RID_ReqDeposit";

		internal const string RpcGrantDeposit = "RID_GrantDeposit";

		private const string RpcReqClear = "RID_ReqClear";

		internal const float RequestTimeoutSeconds = 5f;

		internal const int MaxRequestAttempts = 3;

		private const float HandledRequestLifetimeSeconds = 60f;

		private readonly HandledRequestCache<(string ItemName, int Amount)> _handledWithdrawals = new HandledRequestCache<(string, int)>(60f);

		private readonly HandledRequestCache<int> _handledDeposits = new HandledRequestCache<int>(60f);

		private ZNetView _view;

		private ZDOID _zdoId = ZDOID.None;

		private Inventory _mirror;

		private DrawerSnapshot _mirrored = new DrawerSnapshot("", 0);

		private bool _applyingMirror;

		private bool _mirrorNeedsRebuild;

		internal ZDOID ZdoId => _zdoId;

		internal DrawerTier Tier { get; private set; }

		public DrawerRenderer Face { get; private set; }

		public DrawerSnapshot Snapshot
		{
			get
			{
				//IL_0021: 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)
				if (!((Object)(object)_view != (Object)null) || !_view.IsValid())
				{
					return new DrawerSnapshot("", 0);
				}
				return new DrawerSnapshot(_view.GetZDO().GetString(KeyPrefabHash, ""), _view.GetZDO().GetInt(KeyAmountHash, 0));
			}
		}

		public int Capacity => DrawerConfig.CapacityFor(Tier);

		internal DrawerSnapshot MirroredBaseline => _mirrored;

		internal string DiagId
		{
			get
			{
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_view != (Object)null) || !_view.IsValid())
				{
					return ((Object)((Component)this).gameObject).name + "#(no ZDO)";
				}
				return $"{((Object)((Component)this).gameObject).name}#{_view.GetZDO().m_uid}";
			}
		}

		internal Inventory MirrorInventory
		{
			get
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Expected O, but got Unknown
				if (_mirror == null)
				{
					_mirror = new Inventory("drawer", (Sprite)null, 1, 1);
					Inventory mirror = _mirror;
					mirror.m_onChanged = (Action)Delegate.Combine(mirror.m_onChanged, new Action(OnMirrorChanged));
				}
				return _mirror;
			}
		}

		private void Awake()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			_view = ((Component)this).GetComponent<ZNetView>();
			Face = ((Component)this).GetComponentInChildren<DrawerRenderer>();
			if (!((Object)(object)_view == (Object)null) && _view.IsValid())
			{
				_zdoId = _view.GetZDO().m_uid;
				Tier = TierFromPrefabName(((Object)((Component)this).gameObject).name);
				try
				{
					AccessTools.FieldRefAccess<Container, ZNetView>((Container)(object)this, "m_nview") = _view;
				}
				catch (Exception ex)
				{
					DrawerPlugin.Log.LogError((object)("Could not set Container.m_nview; this drawer stays inert. See the compatibility check at startup. " + ex.GetType().Name + ": " + ex.Message));
					return;
				}
				((Container)this).Awake();
				EnsureCreator();
				WearNTear component = ((Component)this).GetComponent<WearNTear>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDrawerDestroyed));
				}
				_view.Register<long, int>("RID_ReqWithdraw", (Action<long, long, int>)RPC_RequestWithdraw);
				_view.Register<long, string, int>("RID_GrantWithdraw", (Action<long, long, string, int>)RPC_GrantWithdraw);
				_view.Register<long, string, int>("RID_ReqDeposit", (Action<long, long, string, int>)RPC_RequestDeposit);
				_view.Register<long, int>("RID_GrantDeposit", (Action<long, long, int>)RPC_GrantDeposit);
				_view.Register("RID_ReqClear", (Action<long>)RPC_RequestClear);
				All.Add(this);
				DrawerManager.Instance?.Register(this);
			}
		}

		private void EnsureCreator()
		{
			if ((Object)(object)_view == (Object)null || !_view.IsValid())
			{
				return;
			}
			ZDO zDO = _view.GetZDO();
			if (_view.IsOwner() && zDO.GetLong(CreatorHash, 0L) == 0L)
			{
				PlayerProfile val = (((Object)(object)Game.instance != (Object)null) ? Game.instance.GetPlayerProfile() : null);
				if (val != null)
				{
					zDO.Set(CreatorHash, val.GetPlayerID());
				}
			}
		}

		private void OnDestroy()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			All.Remove(this);
			DrawerManager.Instance?.Unregister(this);
			if (!((ZDOID)(ref _zdoId)).IsNone())
			{
				DrawerManager.Instance?.ResolvePendingForDrawer(_zdoId);
			}
		}

		private void OnDrawerDestroyed()
		{
			//IL_001d: 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_002c: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_view == (Object)null) && _view.IsOwner())
			{
				DrawerSnapshot snapshot = Snapshot;
				if (((DrawerSnapshot)(ref snapshot)).IsAssigned && snapshot.Amount > 0)
				{
					ItemFacts.SpillAtPosition(((Component)this).transform.position, snapshot.ItemName, snapshot.Amount);
				}
			}
		}

		private static DrawerTier TierFromPrefabName(string name)
		{
			DrawerTier[] all = DrawerTiers.All;
			foreach (DrawerTier drawerTier in all)
			{
				if (name.StartsWith(DrawerTiers.PrefabName(drawerTier)))
				{
					return drawerTier;
				}
			}
			return DrawerTier.Wood;
		}

		private bool WriteOwned(DrawerSnapshot expected, DrawerSnapshot next)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner())
			{
				return false;
			}
			ZDO zDO = _view.GetZDO();
			DrawerSnapshot val = default(DrawerSnapshot);
			((DrawerSnapshot)(ref val))..ctor(zDO.GetString(KeyPrefabHash, ""), zDO.GetInt(KeyAmountHash, 0));
			if (!((DrawerSnapshot)(ref val)).Equals(expected))
			{
				return false;
			}
			zDO.Set(KeyPrefabHash, next.ItemName);
			zDO.Set(KeyAmountHash, next.Amount, false);
			DrawerManager.Instance?.MarkDirty(this);
			RefreshFace();
			return true;
		}

		public void RefreshFace()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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)
			if (!((Object)(object)Face == (Object)null))
			{
				DrawerSnapshot snapshot = Snapshot;
				Face.Show(snapshot.ItemName, snapshot.Amount);
			}
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (hold)
			{
				return false;
			}
			Player val = (Player)(object)((user is Player) ? user : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			DrawerSnapshot snapshot = Snapshot;
			bool button = ZInput.GetButton("Crouch");
			bool button2 = ZInput.GetButton("Run");
			if (button)
			{
				if (!((DrawerSnapshot)(ref snapshot)).IsAssigned)
				{
					return true;
				}
				if (((DrawerSnapshot)(ref snapshot)).IsEmpty)
				{
					RequestClear(snapshot);
					return true;
				}
				BeginWithdraw(val, snapshot, DrawerState.WithdrawOne(snapshot));
				return true;
			}
			if (button2)
			{
				return DepositEverythingMatching(val, snapshot);
			}
			int num = ItemFacts.MaxStackSize(snapshot.ItemName);
			BeginWithdraw(val, snapshot, DrawerState.WithdrawStack(snapshot, num));
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			//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_00ba: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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)
			//IL_00d8: 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_0110: Unknown result type (might be due to invalid IL or missing references)
			Player val = (Player)(object)((user is Player) ? user : null);
			if ((Object)(object)val == (Object)null || item == null)
			{
				return false;
			}
			if ((Object)(object)_view == (Object)null || !_view.IsValid())
			{
				((Character)val).Message((MessageType)2, "Try again", 0, (Sprite)null, false);
				return true;
			}
			if (item.m_shared.m_maxStackSize <= 1)
			{
				((Character)val).Message((MessageType)2, "Drawers only hold stackable items", 0, (Sprite)null, false);
				return true;
			}
			string text = ItemFacts.PrefabNameOf(item);
			if (text == null)
			{
				((Character)val).Message((MessageType)2, "Cannot identify this item", 0, (Sprite)null, false);
				return true;
			}
			DrawerSnapshot snapshot = Snapshot;
			if (((DrawerSnapshot)(ref snapshot)).IsAssigned && snapshot.ItemName != text)
			{
				((Character)val).Message((MessageType)2, "This drawer holds " + ItemFacts.LocalizedName(snapshot.ItemName), 0, (Sprite)null, false);
				return true;
			}
			DrawerOutcome val2 = DrawerState.Deposit(snapshot, Capacity, text, item.m_stack);
			if (!val2.Accepted)
			{
				((Character)val).Message((MessageType)2, val2.Rejection, 0, (Sprite)null, false);
				return true;
			}
			if (!((Humanoid)val).GetInventory().RemoveItem(item, val2.MovedToDrawer))
			{
				((Character)val).Message((MessageType)2, "Could not remove item", 0, (Sprite)null, false);
				return true;
			}
			RequestDeposit(val, text, val2.MovedToDrawer, announce: false);
			return true;
		}

		private bool DepositEverythingMatching(Player player, DrawerSnapshot current)
		{
			//IL_0074: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_view == (Object)null || !_view.IsValid())
			{
				((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false);
				return true;
			}
			if (!((DrawerSnapshot)(ref current)).IsAssigned)
			{
				((Character)player).Message((MessageType)2, "This drawer has not been assigned", 0, (Sprite)null, false);
				return true;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			List<ItemData> list = new List<ItemData>();
			int num = 0;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (!(ItemFacts.PrefabNameOf(allItem) != current.ItemName))
				{
					list.Add(allItem);
					num += allItem.m_stack;
				}
			}
			if (num <= 0)
			{
				((Character)player).Message((MessageType)2, "You have none of those", 0, (Sprite)null, false);
				return true;
			}
			DrawerOutcome val = DrawerState.Deposit(current, Capacity, current.ItemName, num);
			if (!val.Accepted)
			{
				((Character)player).Message((MessageType)2, val.Rejection, 0, (Sprite)null, false);
				return true;
			}
			int movedToDrawer = val.MovedToDrawer;
			int num2 = 0;
			foreach (ItemData item in list)
			{
				if (num2 >= movedToDrawer)
				{
					break;
				}
				int num3 = ((item.m_stack < movedToDrawer - num2) ? item.m_stack : (movedToDrawer - num2));
				if (inventory.RemoveItem(item, num3))
				{
					num2 += num3;
				}
			}
			if (num2 <= 0)
			{
				((Character)player).Message((MessageType)2, "You have none of those", 0, (Sprite)null, false);
				return true;
			}
			RequestDeposit(player, current.ItemName, num2, announce: true);
			return true;
		}

		private void BeginWithdraw(Player player, DrawerSnapshot current, DrawerOutcome outcome)
		{
			//IL_0000: 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_000a: 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_0048: 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 (!outcome.Accepted)
			{
				((Character)player).Message((MessageType)2, outcome.Rejection, 0, (Sprite)null, false);
			}
			else if (outcome.MovedToPlayer > 0)
			{
				if ((Object)(object)ItemFacts.Drop(current.ItemName) == (Object)null)
				{
					((Character)player).Message((MessageType)2, "Cannot identify this item", 0, (Sprite)null, false);
				}
				else
				{
					RequestWithdraw(player, current.ItemName, outcome.MovedToPlayer);
				}
			}
		}

		private void RequestWithdraw(Player player, string itemName, int requested)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_view == (Object)null || !_view.IsValid() || requested <= 0)
			{
				return;
			}
			if (_view.IsOwner())
			{
				DrawerSnapshot snapshot = Snapshot;
				DrawerOutcome val = DrawerState.WithdrawExact(snapshot, requested);
				if (val.MovedToPlayer > 0 && WriteOwned(snapshot, val.Result))
				{
					ItemFacts.GiveToPlayer(player, snapshot.ItemName, val.MovedToPlayer);
				}
				return;
			}
			DrawerManager instance = DrawerManager.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				long owner = _view.GetZDO().GetOwner();
				if (owner == 0L)
				{
					((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false);
					return;
				}
				long id = instance.NextRequestId();
				instance.AddPendingWithdrawal(id, new PendingWithdrawal(_zdoId, owner, player, requested, ((Component)player).transform.position));
				SendWithdrawRequestRpc(id, owner, requested);
			}
		}

		internal void SendWithdrawRequestRpc(long id, long targetOwner, int requested)
		{
			if ((Object)(object)_view != (Object)null && _view.IsValid())
			{
				_view.InvokeRPC(targetOwner, "RID_ReqWithdraw", new object[2] { id, requested });
			}
		}

		private void RPC_RequestWithdraw(long sender, long id, int requested)
		{
			//IL_0083: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner())
			{
				return;
			}
			_handledWithdrawals.Prune(Time.time);
			(string, int) tuple = default((string, int));
			if (_handledWithdrawals.TryGet(sender, id, ref tuple))
			{
				_view.InvokeRPC(sender, "RID_GrantWithdraw", new object[3] { id, tuple.Item1, tuple.Item2 });
				return;
			}
			DrawerSnapshot snapshot = Snapshot;
			int num = 0;
			if (((DrawerSnapshot)(ref snapshot)).IsAssigned && (Object)(object)ItemFacts.Drop(snapshot.ItemName) != (Object)null)
			{
				DrawerOutcome val = DrawerState.WithdrawExact(snapshot, requested);
				if (val.MovedToPlayer > 0 && WriteOwned(snapshot, val.Result))
				{
					num = val.MovedToPlayer;
				}
			}
			_handledWithdrawals.Record(sender, id, (snapshot.ItemName, num), Time.time);
			_view.InvokeRPC(sender, "RID_GrantWithdraw", new object[3] { id, snapshot.ItemName, num });
		}

		private void RPC_GrantWithdraw(long sender, long id, string itemName, int granted)
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			DrawerManager instance = DrawerManager.Instance;
			if ((Object)(object)instance == (Object)null || !instance.TryCompleteWithdrawal(id, out var payload))
			{
				return;
			}
			if (sender != payload.TargetOwner)
			{
				DrawerPlugin.Log.LogWarning((object)$"RPC_GrantWithdraw: reply for request {id} came from peer {sender}, not the pinned target {payload.TargetOwner}.");
			}
			int num = ((granted >= 0) ? Math.Min(granted, payload.Requested) : 0);
			if (granted != num)
			{
				DrawerPlugin.Log.LogWarning((object)$"RPC_GrantWithdraw: request {id} asked for {payload.Requested} but was granted {granted}; clamped to {num}.");
			}
			if (num > 0)
			{
				if ((Object)(object)payload.Player != (Object)null)
				{
					ItemFacts.GiveToPlayer(payload.Player, itemName, num);
				}
				else
				{
					ItemFacts.SpillAtPosition(payload.PlayerPosition, itemName, num);
				}
			}
		}

		private void RequestDeposit(Player player, string itemName, int removed, bool announce)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_0064: 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_00c6: 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_0071: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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)
			if (removed <= 0)
			{
				return;
			}
			if ((Object)(object)_view == (Object)null || !_view.IsValid())
			{
				ItemFacts.SpillAtPosition(((Component)player).transform.position, itemName, removed);
				((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false);
				return;
			}
			if (_view.IsOwner())
			{
				DrawerSnapshot snapshot = Snapshot;
				DrawerOutcome val = DrawerState.Deposit(snapshot, Capacity, itemName, removed);
				int num = ((val.Accepted && WriteOwned(snapshot, val.Result)) ? val.MovedToDrawer : 0);
				int num2 = DrawerState.RefundShortfall(removed, num);
				if (num2 > 0)
				{
					ItemFacts.GiveToPlayer(player, itemName, num2);
				}
				if (announce)
				{
					AnnounceDeposit(player, itemName, num);
				}
				return;
			}
			DrawerManager instance = DrawerManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				ItemFacts.SpillAtPosition(((Component)player).transform.position, itemName, removed);
				((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false);
				return;
			}
			long owner = _view.GetZDO().GetOwner();
			if (owner == 0L)
			{
				ItemFacts.SpillAtPosition(((Component)player).transform.position, itemName, removed);
				((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false);
			}
			else
			{
				long id = instance.NextRequestId();
				instance.AddPendingDeposit(id, new PendingDeposit(_zdoId, owner, player, itemName, removed, ((Component)player).transform.position, announce));
				SendDepositRequestRpc(id, owner, itemName, removed);
			}
		}

		internal void SendDepositRequestRpc(long id, long targetOwner, string itemName, int removed)
		{
			if ((Object)(object)_view != (Object)null && _view.IsValid())
			{
				_view.InvokeRPC(targetOwner, "RID_ReqDeposit", new object[3] { id, itemName, removed });
			}
		}

		private void RPC_RequestDeposit(long sender, long id, string itemName, int amount)
		{
			//IL_0075: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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)
			if (!((Object)(object)_view == (Object)null) && _view.IsValid() && _view.IsOwner())
			{
				_handledDeposits.Prune(Time.time);
				int num = default(int);
				if (_handledDeposits.TryGet(sender, id, ref num))
				{
					_view.InvokeRPC(sender, "RID_GrantDeposit", new object[2] { id, num });
					return;
				}
				DrawerSnapshot snapshot = Snapshot;
				DrawerOutcome val = DrawerState.Deposit(snapshot, Capacity, itemName, amount);
				int num2 = ((val.Accepted && WriteOwned(snapshot, val.Result)) ? val.MovedToDrawer : 0);
				_handledDeposits.Record(sender, id, num2, Time.time);
				_view.InvokeRPC(sender, "RID_GrantDeposit", new object[2] { id, num2 });
			}
		}

		private void RPC_GrantDeposit(long sender, long id, int accepted)
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			DrawerManager instance = DrawerManager.Instance;
			if ((Object)(object)instance == (Object)null || !instance.TryCompleteDeposit(id, out var payload))
			{
				return;
			}
			if (sender != payload.TargetOwner)
			{
				DrawerPlugin.Log.LogWarning((object)$"RPC_GrantDeposit: reply for request {id} came from peer {sender}, not the pinned target {payload.TargetOwner}.");
			}
			int num = ((accepted >= 0) ? Math.Min(accepted, payload.Removed) : 0);
			if (accepted != num)
			{
				DrawerPlugin.Log.LogWarning((object)$"RPC_GrantDeposit: request {id} offered {payload.Removed} but {accepted} was reported accepted; clamped to {num}.");
			}
			int num2 = DrawerState.RefundShortfall(payload.Removed, num);
			if (num2 > 0)
			{
				if ((Object)(object)payload.Player != (Object)null)
				{
					ItemFacts.GiveToPlayer(payload.Player, payload.ItemName, num2);
				}
				else
				{
					ItemFacts.SpillAtPosition(payload.PlayerPosition, payload.ItemName, num2);
				}
			}
			if (payload.Announce && (Object)(object)payload.Player != (Object)null)
			{
				AnnounceDeposit(payload.Player, payload.ItemName, num);
			}
		}

		private static void AnnounceDeposit(Player player, string itemName, int accepted)
		{
			if (accepted > 0)
			{
				((Character)player).Message((MessageType)1, $"Stored {accepted} {ItemFacts.LocalizedName(itemName)}", 0, (Sprite)null, false);
			}
		}

		private void RequestClear(DrawerSnapshot current)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_view == (Object)null || !_view.IsValid())
			{
				return;
			}
			if (_view.IsOwner())
			{
				DrawerOutcome val = DrawerState.Clear(current);
				if (val.Accepted)
				{
					WriteOwned(current, val.Result);
				}
			}
			else
			{
				_view.InvokeRPC("RID_ReqClear", Array.Empty<object>());
			}
		}

		private void RPC_RequestClear(long sender)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0036: 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_0040: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_view == (Object)null) && _view.IsValid() && _view.IsOwner())
			{
				DrawerSnapshot snapshot = Snapshot;
				DrawerOutcome val = DrawerState.Clear(snapshot);
				if (val.Accepted)
				{
					WriteOwned(snapshot, val.Result);
				}
			}
		}

		public bool TryWithdrawExternally(int requested, out int taken)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_004a: 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)
			taken = 0;
			if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner())
			{
				return false;
			}
			DrawerSnapshot snapshot = Snapshot;
			DrawerOutcome val = DrawerState.WithdrawExact(snapshot, requested);
			if (val.MovedToPlayer <= 0)
			{
				return false;
			}
			if (!WriteOwned(snapshot, val.Result))
			{
				return false;
			}
			taken = val.MovedToPlayer;
			return true;
		}

		public bool TryDepositExternally(string itemName, int amount, out int accepted)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			accepted = 0;
			if (!ItemFacts.IsStorable(itemName))
			{
				return false;
			}
			if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner())
			{
				return false;
			}
			DrawerSnapshot snapshot = Snapshot;
			DrawerOutcome val = DrawerState.Deposit(snapshot, Capacity, itemName, amount);
			if (!val.Accepted || val.MovedToDrawer <= 0)
			{
				return false;
			}
			if (!WriteOwned(snapshot, val.Result))
			{
				return false;
			}
			accepted = val.MovedToDrawer;
			return true;
		}

		internal void RefreshMirror()
		{
			//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_0020: 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)
			DrawerSnapshot current = EffectiveMirrorSnapshot();
			if (_mirrorNeedsRebuild || !((DrawerSnapshot)(ref current)).Equals(_mirrored))
			{
				RebuildMirror(current);
				_mirrorNeedsRebuild = false;
			}
		}

		private DrawerSnapshot EffectiveMirrorSnapshot()
		{
			//IL_002e: 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)
			if (!((Object)(object)_view != (Object)null) || !_view.IsValid() || !_view.IsOwner())
			{
				return new DrawerSnapshot("", 0);
			}
			return Snapshot;
		}

		private void RebuildMirror(DrawerSnapshot current)
		{
			//IL_008c: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			_applyingMirror = true;
			try
			{
				Inventory mirrorInventory = MirrorInventory;
				mirrorInventory.RemoveAll();
				if (((DrawerSnapshot)(ref current)).IsAssigned && !((DrawerSnapshot)(ref current)).IsEmpty)
				{
					GameObject val = ItemFacts.Prefab(current.ItemName);
					if ((Object)(object)val != (Object)null)
					{
						ItemDrop component = val.GetComponent<ItemDrop>();
						if ((Object)(object)component != (Object)null)
						{
							ItemData val2 = component.m_itemData.Clone();
							val2.m_stack = current.Amount;
							val2.m_dropPrefab = val;
							val2.m_gridPos = new Vector2i(0, 0);
							val2.m_worldLevel = (byte)Game.m_worldLevel;
							mirrorInventory.AddItem(val2);
						}
					}
				}
				_mirrored = current;
			}
			finally
			{
				_applyingMirror = false;
			}
		}

		private void OnMirrorChanged()
		{
			//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_005d: 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_0069: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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)
			if (!_applyingMirror)
			{
				ItemData itemAt = _mirror.GetItemAt(0, 0);
				string text = ((itemAt != null) ? (ItemFacts.PrefabNameOf(itemAt) ?? "") : "");
				int num = itemAt?.m_stack ?? 0;
				DrawerSnapshot snapshot = Snapshot;
				MirrorDelta val = MirrorReconciliation.Compute(text, num, _mirrored.ItemName, _mirrored.Amount, snapshot.ItemName, snapshot.Amount);
				if (val.Withdraw > 0 && !TryWithdrawExternally(val.Withdraw, out var _))
				{
					_mirrorNeedsRebuild = true;
				}
				else
				{
					_mirrored = new DrawerSnapshot(text, num);
				}
			}
		}

		public string GetHoverText()
		{
			//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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			DrawerSnapshot snapshot = Snapshot;
			if (!((DrawerSnapshot)(ref snapshot)).IsAssigned)
			{
				return Localization.instance.Localize(DrawerTiers.DisplayName(Tier) + "\n[<color=yellow><b>1-8</b></color>] Store an item");
			}
			string arg = ItemFacts.LocalizedName(snapshot.ItemName);
			return Localization.instance.Localize($"{arg}  <color=orange>{snapshot.Amount}</color>/{Capacity}\n" + "[<color=yellow><b>E</b></color>] Take stack\n[<color=yellow><b>Ctrl+E</b></color>] Take one\n[<color=yellow><b>Shift+E</b></color>] Store all");
		}

		public string GetHoverName()
		{
			return DrawerTiers.DisplayName(Tier);
		}
	}
	[HarmonyPatch(typeof(Container), "CanBeRemoved")]
	internal static class DrawerCanBeRemovedPatch
	{
		private static bool Prepare()
		{
			return ValheimCompat.RequireMethod(typeof(Container), "CanBeRemoved");
		}

		private static bool Prefix(Container __instance, ref bool __result)
		{
			//IL_000e: 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)
			if (!(__instance is DrawerComponent drawerComponent))
			{
				return true;
			}
			DrawerSnapshot snapshot = drawerComponent.Snapshot;
			__result = ((DrawerSnapshot)(ref snapshot)).IsEmpty;
			return false;
		}
	}
	public static class DrawerConfig
	{
		public static ConfigEntry<int> WoodCapacity;

		public static ConfigEntry<int> StoneCapacity;

		public static ConfigEntry<int> BlackMarbleCapacity;

		public static ConfigEntry<bool> AutoPickupEnabled;

		public static ConfigEntry<float> PickupRadius;

		public static ConfigEntry<float> PickupScanRange;

		public static ConfigEntry<float> PickupInterval;

		public static ConfigEntry<float> LabelDistance;

		public static void Bind(ConfigFile config)
		{
			//IL_001e: 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_002b: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_0092: 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_009f: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Expected O, but got Unknown
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Expected O, but got Unknown
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Expected O, but got Unknown
			WoodCapacity = config.Bind<int>("Capacity", "Wood", 1000, new ConfigDescription("How many items a wood drawer holds.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			StoneCapacity = config.Bind<int>("Capacity", "Stone", 2000, new ConfigDescription("How many items a stone drawer holds.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			BlackMarbleCapacity = config.Bind<int>("Capacity", "BlackMarble", 10000, new ConfigDescription("How many items a black marble drawer holds.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			AutoPickupEnabled = config.Bind<bool>("Pickup", "Enabled", true, new ConfigDescription("Drawers absorb matching items dropped nearby.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			PickupRadius = config.Bind<float>("Pickup", "Radius", 40f, new ConfigDescription("How far from a drawer a dropped item is absorbed, in metres.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			PickupScanRange = config.Bind<float>("Pickup", "ScanRange", 40f, new ConfigDescription("How far around you dropped items are considered at all. One query covers every drawer, so this is cheap.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			PickupInterval = config.Bind<float>("Pickup", "Interval", 0.5f, new ConfigDescription("Seconds between pickup passes.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			LabelDistance = config.Bind<float>("Display", "LabelDistance", 30f, "Beyond this distance drawer icons and counts switch off. A wall of text nobody can read is wasted work.");
		}

		public static int CapacityFor(DrawerTier tier)
		{
			return tier switch
			{
				DrawerTier.Wood => WoodCapacity?.Value ?? DrawerTiers.DefaultCapacity(tier), 
				DrawerTier.Stone => StoneCapacity?.Value ?? DrawerTiers.DefaultCapacity(tier), 
				DrawerTier.BlackMarble => BlackMarbleCapacity?.Value ?? DrawerTiers.DefaultCapacity(tier), 
				_ => DrawerTiers.DefaultCapacity(tier), 
			};
		}
	}
	internal static class DrawerFont
	{
		private static TMP_FontAsset _cached;

		private static bool _loggedFailure;

		public static TMP_FontAsset Shared
		{
			get
			{
				if ((Object)(object)_cached != (Object)null)
				{
					return _cached;
				}
				TMP_FontAsset val = ((GUIManager.Instance != null) ? GUIManager.Instance.TMP_AveriaSansLibre : null);
				if ((Object)(object)val != (Object)null)
				{
					_cached = val;
					return _cached;
				}
				TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>();
				foreach (TMP_Text val2 in array)
				{
					if ((Object)(object)val2 != (Object)null && (Object)(object)val2.font != (Object)null)
					{
						_cached = val2.font;
						return _cached;
					}
				}
				TMP_FontAsset[] array2 = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
				if (array2.Length != 0)
				{
					_cached = array2[0];
					return _cached;
				}
				try
				{
					TMP_FontAsset defaultFontAsset = TMP_Settings.defaultFontAsset;
					if ((Object)(object)defaultFontAsset != (Object)null)
					{
						_cached = defaultFontAsset;
						return _cached;
					}
				}
				catch (Exception)
				{
				}
				if (!_loggedFailure)
				{
					_loggedFailure = true;
					DrawerPlugin.Log.LogError((object)"No TMP font asset found anywhere (checked Jotunn.GUIManager.TMP_AveriaSansLibre, every live TMP_Text, Resources.FindObjectsOfTypeAll<TMP_FontAsset>, and TMP_Settings.defaultFontAsset). Drawer count labels will not render any text until this resolves. This mod ships no font of its own by design.");
				}
				return null;
			}
		}
	}
	public static class DrawerIconAtlas
	{
		private static AtlasLayout _layout;

		private static Texture2D _texture;

		private static bool _buildFailureLogged;

		private static readonly string[] ShaderCandidates = new string[3] { "Unlit/Transparent", "Sprites/Default", "UI/Default" };

		public static Material SharedMaterial { get; private set; }

		public static bool IsBuilt
		{
			get
			{
				if (_layout != null)
				{
					return (Object)(object)SharedMaterial != (Object)null;
				}
				return false;
			}
		}

		public static void Build()
		{
			if (IsBuilt)
			{
				return;
			}
			try
			{
				BuildInternal();
			}
			catch (Exception arg)
			{
				_layout = null;
				SharedMaterial = null;
				if (!_buildFailureLogged)
				{
					_buildFailureLogged = true;
					DrawerPlugin.Log.LogError((object)("Icon atlas build threw; leaving it unbuilt. Will keep retrying quietly on " + $"later calls, but will not log this again: {arg}"));
				}
			}
		}

		private static void BuildInternal()
		{
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: 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_01d7: Expected O, but got Unknown
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				DrawerPlugin.Log.LogWarning((object)"ObjectDB not ready; icon atlas deferred.");
				return;
			}
			List<IconSize> list = new List<IconSize>();
			Dictionary<string, Sprite> dictionary = new Dictionary<string, Sprite>();
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				ItemDrop val = (((Object)(object)item == (Object)null) ? null : item.GetComponent<ItemDrop>());
				if (!((Object)(object)val == (Object)null) && val.m_itemData.m_shared.m_maxStackSize > 1)
				{
					Sprite icon;
					try
					{
						icon = val.m_itemData.GetIcon();
					}
					catch (Exception ex)
					{
						DrawerPlugin.Log.LogWarning((object)("Skipping '" + ((Object)item).name + "' in the icon atlas: GetIcon() threw (" + ex.GetType().Name + ": " + ex.Message + ")."));
						continue;
					}
					if (!((Object)(object)icon == (Object)null) && !((Object)(object)icon.texture == (Object)null) && !dictionary.ContainsKey(((Object)item).name))
					{
						dictionary[((Object)item).name] = icon;
						string name = ((Object)item).name;
						Rect textureRect = icon.textureRect;
						int num = (int)((Rect)(ref textureRect)).width;
						textureRect = icon.textureRect;
						list.Add(new IconSize(name, num, (int)((Rect)(ref textureRect)).height));
					}
				}
			}
			if (list.Count == 0)
			{
				DrawerPlugin.Log.LogError((object)"Icon atlas build found 0 storable items in ObjectDB.m_items -- called too early, before item registration finished. Not marking the atlas built; a later call to Build() (see DrawerIconAtlas.TryGetUv's retry) will try again.");
				return;
			}
			_layout = IconAtlasPacker.Pack((IReadOnlyList<IconSize>)list, 4096);
			_texture = new Texture2D(_layout.Width, _layout.Height, (TextureFormat)4, true)
			{
				name = "rid_icon_atlas",
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1
			};
			Color32[] pixels = (Color32[])(object)new Color32[_layout.Width * _layout.Height];
			_texture.SetPixels32(pixels);
			foreach (KeyValuePair<string, AtlasRect> rect in _layout.Rects)
			{
				if (dictionary.TryGetValue(rect.Key, out var value) && TryReadSprite(value, out var pixels2, out var width, out var height))
				{
					_texture.SetPixels32(rect.Value.X, rect.Value.Y, width, height, pixels2);
				}
			}
			_texture.Apply(true, true);
			string source;
			Shader val2 = ResolveIconShader(out source);
			if ((Object)(object)val2 == (Object)null)
			{
				DrawerPlugin.Log.LogError((object)("No usable shader found for the drawer icon atlas material (tried " + string.Join(", ", ShaderCandidates) + "). Drawer icons will not render until this is fixed."));
				Object.Destroy((Object)(object)_texture);
				_texture = null;
				_layout = null;
			}
			else
			{
				SharedMaterial = new Material(val2)
				{
					name = "rid_icon_material",
					mainTexture = (Texture)(object)_texture
				};
				SharedMaterial.renderQueue = 2450;
				DrawerPlugin.Log.LogInfo((object)($"Icon atlas built: {_layout.Rects.Count} icons in {_layout.Width}x{_layout.Height}, " + "material shader = " + source));
			}
		}

		private static Shader ResolveIconShader(out string source)
		{
			string[] shaderCandidates = ShaderCandidates;
			foreach (string text in shaderCandidates)
			{
				Shader val = Shader.Find(text);
				if ((Object)(object)val != (Object)null)
				{
					source = "Shader.Find(\"" + text + "\")";
					return val;
				}
				DrawerPlugin.Log.LogWarning((object)("Shader.Find(\"" + text + "\") returned null; trying next candidate."));
			}
			source = null;
			return null;
		}

		private static bool TryReadSprite(Sprite sprite, out Color32[] pixels, out int width, out int height)
		{
			//IL_0004: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			pixels = null;
			Rect textureRect = sprite.textureRect;
			width = Mathf.RoundToInt(((Rect)(ref textureRect)).width);
			height = Mathf.RoundToInt(((Rect)(ref textureRect)).height);
			if (width <= 0 || height <= 0)
			{
				return false;
			}
			RenderTexture active = RenderTexture.active;
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)sprite.texture).width, ((Texture)sprite.texture).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)0);
			try
			{
				Graphics.Blit((Texture)(object)sprite.texture, temporary);
				RenderTexture.active = temporary;
				Texture2D val = new Texture2D(width, height, (TextureFormat)4, false);
				val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)width, (float)height), 0, 0);
				val.Apply();
				pixels = val.GetPixels32();
				Object.Destroy((Object)(object)val);
				return true;
			}
			catch (Exception ex)
			{
				DrawerPlugin.Log.LogWarning((object)("Could not read icon for atlas: " + ex.Message));
				return false;
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
		}

		public static bool TryGetUv(string item, out Vector2 min, out Vector2 max)
		{
			//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_000c: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			min = Vector2.zero;
			max = Vector2.one;
			if (!IsBuilt)
			{
				Build();
			}
			if (_layout == null)
			{
				return false;
			}
			float num = default(float);
			float num2 = default(float);
			float num3 = default(float);
			float num4 = default(float);
			if (!_layout.TryGetUv(item, ref num, ref num2, ref num3, ref num4))
			{
				return false;
			}
			min = new Vector2(num, num2);
			max = new Vector2(num3, num4);
			return true;
		}
	}
	internal sealed class PendingWithdrawal
	{
		public readonly ZDOID DrawerId;

		public readonly long TargetOwner;

		public readonly Player Player;

		public readonly int Requested;

		public readonly Vector3 PlayerPosition;

		public PendingWithdrawal(ZDOID drawerId, long targetOwner, Player player, int requested, Vector3 playerPosition)
		{
			//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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			DrawerId = drawerId;
			TargetOwner = targetOwner;
			Player = player;
			Requested = requested;
			PlayerPosition = playerPosition;
		}
	}
	internal sealed class PendingDeposit
	{
		public readonly ZDOID DrawerId;

		public readonly long TargetOwner;

		public readonly Player Player;

		public readonly string ItemName;

		public readonly int Removed;

		public readonly Vector3 PlayerPosition;

		public readonly bool Announce;

		public PendingDeposit(ZDOID drawerId, long targetOwner, Player player, string itemName, int removed, Vector3 playerPosition, bool announce)
		{
			//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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			DrawerId = drawerId;
			TargetOwner = targetOwner;
			Player = player;
			ItemName = itemName;
			Removed = removed;
			PlayerPosition = playerPosition;
			Announce = announce;
		}
	}
	public class DrawerManager : MonoBehaviour
	{
		private readonly SpatialGrid<DrawerComponent> _grid = new SpatialGrid<DrawerComponent>(8f);

		private readonly List<DrawerComponent> _all = new List<DrawerComponent>();

		private readonly HashSet<DrawerComponent> _dirty = new HashSet<DrawerComponent>();

		private float _cullTimer;

		private int _syncCursor;

		private float _pickupTimer;

		private readonly List<DrawerComponent> _pickupScratch = new List<DrawerComponent>(16);

		private readonly RequestIdGenerator _requestIds = new RequestIdGenerator(DateTimeOffset.UtcNow.Ticks);

		private readonly PendingRequestLedger<PendingWithdrawal> _pendingWithdrawals = new PendingRequestLedger<PendingWithdrawal>(5f, 3);

		private readonly PendingRequestLedger<PendingDeposit> _pendingDeposits = new PendingRequestLedger<PendingDeposit>(5f, 3);

		public static DrawerManager Instance { get; private set; }

		public static void Create()
		{
			//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_001e: Expected O, but got Unknown
			if (!((Object)(object)Instance != (Object)null))
			{
				GameObject val = new GameObject("RidDrawerManager");
				Object.DontDestroyOnLoad((Object)val);
				Instance = val.AddComponent<DrawerManager>();
			}
		}

		public long NextRequestId()
		{
			return _requestIds.Next();
		}

		internal void AddPendingWithdrawal(long id, PendingWithdrawal payload)
		{
			_pendingWithdrawals.Add(id, payload, Time.time);
		}

		internal void AddPendingDeposit(long id, PendingDeposit payload)
		{
			_pendingDeposits.Add(id, payload, Time.time);
		}

		internal bool TryCompleteWithdrawal(long id, out PendingWithdrawal payload)
		{
			return _pendingWithdrawals.TryComplete(id, ref payload);
		}

		internal bool TryCompleteDeposit(long id, out PendingDeposit payload)
		{
			return _pendingDeposits.TryComplete(id, ref payload);
		}

		public void ResolvePendingForDrawer(ZDOID drawerId)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			ResolveMatching(_pendingWithdrawals, drawerId, (PendingWithdrawal p) => p.DrawerId, GiveUpWithdrawal);
			ResolveMatching(_pendingDeposits, drawerId, (PendingDeposit p) => p.DrawerId, GiveUpDeposit);
		}

		private static void ResolveMatching<T>(PendingRequestLedger<T> ledger, ZDOID drawerId, Func<T, ZDOID> drawerOf, Action<long, T> onResolved)
		{
			//IL_001f: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			List<long> list = null;
			foreach (KeyValuePair<long, T> item in ledger.All())
			{
				ZDOID val = drawerOf(item.Value);
				if (((ZDOID)(ref val)).Equals(drawerId))
				{
					(list ?? (list = new List<long>())).Add(item.Key);
				}
			}
			if (list == null)
			{
				return;
			}
			T arg = default(T);
			foreach (long item2 in list)
			{
				if (ledger.Remove(item2, ref arg))
				{
					onResolved(item2, arg);
				}
			}
		}

		internal void DrainPendingDepositsBeforeSave()
		{
			List<long> list = null;
			foreach (KeyValuePair<long, PendingDeposit> item in _pendingDeposits.All())
			{
				(list ?? (list = new List<long>())).Add(item.Key);
			}
			if (list == null)
			{
				return;
			}
			PendingDeposit payload = default(PendingDeposit);
			foreach (long item2 in list)
			{
				if (_pendingDeposits.Remove(item2, ref payload))
				{
					GiveUpDeposit(item2, payload);
				}
			}
		}

		private void OnApplicationQuit()
		{
			DrainPendingDepositsBeforeSave();
		}

		public void Register(DrawerComponent drawer)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)drawer == (Object)null) && !_all.Contains(drawer))
			{
				_all.Add(drawer);
				Vector3 position = ((Component)drawer).transform.position;
				_grid.Insert(drawer, position.x, position.y, position.z);
				MarkDirty(drawer);
			}
		}

		public void Unregister(DrawerComponent drawer)
		{
			if (!((Object)(object)drawer == (Object)null))
			{
				_all.Remove(drawer);
				_dirty.Remove(drawer);
				_grid.Remove(drawer);
			}
		}

		public void MarkDirty(DrawerComponent drawer)
		{
			if ((Object)(object)drawer != (Object)null)
			{
				_dirty.Add(drawer);
			}
		}

		public void QueryNear(Vector3 position, float radius, List<DrawerComponent> results)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			_grid.Query(position.x, position.y, position.z, radius, results);
		}

		private void Update()
		{
			if (_dirty.Count > 0)
			{
				FlushDirty();
			}
			SyncSomeFaces();
			if (_pendingWithdrawals.Count > 0)
			{
				_pendingWithdrawals.Tick(Time.time, (Action<long, PendingWithdrawal>)RetryWithdrawal, (Action<long, PendingWithdrawal>)GiveUpWithdrawal);
			}
			if (_pendingDeposits.Count > 0)
			{
				_pendingDeposits.Tick(Time.time, (Action<long, PendingDeposit>)RetryDeposit, (Action<long, PendingDeposit>)GiveUpDeposit);
			}
			_cullTimer -= Time.deltaTime;
			if (_cullTimer <= 0f)
			{
				_cullTimer = 0.5f;
				UpdateLabelVisibility();
			}
			_pickupTimer -= Time.deltaTime;
			if (_pickupTimer <= 0f)
			{
				_pickupTimer = DrawerConfig.PickupInterval.Value;
				if (DrawerConfig.AutoPickupEnabled.Value)
				{
					RunAutoPickup();
				}
			}
		}

		private void RunAutoPickup()
		{
			//IL_004d: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || _all.Count == 0)
			{
				return;
			}
			List<ItemDrop> s_instances = ItemDrop.s_instances;
			if (s_instances == null || s_instances.Count == 0)
			{
				return;
			}
			float value = DrawerConfig.PickupRadius.Value;
			float value2 = DrawerConfig.PickupScanRange.Value;
			float num = value2 * value2;
			Vector3 position = ((Component)localPlayer).transform.position;
			for (int i = 0; i < s_instances.Count; i++)
			{
				ItemDrop val = s_instances[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Vector3 val2 = ((Component)val).transform.position - position;
				if (((Vector3)(ref val2)).sqrMagnitude > num || (Object)(object)val.m_nview == (Object)null || !val.m_nview.IsValid() || !val.m_nview.IsOwner() || val.m_itemData == null || val.m_itemData.m_shared.m_maxStackSize <= 1)
				{
					continue;
				}
				string text = (((Object)(object)val.m_itemData.m_dropPrefab != (Object)null) ? ((Object)val.m_itemData.m_dropPrefab).name : ((Object)val).name.Replace("(Clone)", ""));
				_pickupScratch.Clear();
				QueryNear(((Component)val).transform.position, value, _pickupScratch);
				for (int j = 0; j < _pickupScratch.Count; j++)
				{
					DrawerComponent drawerComponent = _pickupScratch[j];
					if ((Object)(object)drawerComponent == (Object)null)
					{
						continue;
					}
					DrawerSnapshot snapshot = drawerComponent.Snapshot;
					if (((DrawerSnapshot)(ref snapshot)).IsAssigned && !(snapshot.ItemName != text) && drawerComponent.TryDepositExternally(text, val.m_itemData.m_stack, out var accepted) && accepted > 0)
					{
						ItemData itemData = val.m_itemData;
						itemData.m_stack -= accepted;
						if (val.m_itemData.m_stack <= 0)
						{
							ZNetScene.instance.Destroy(((Component)val).gameObject);
						}
						else
						{
							val.Save();
						}
						break;
					}
				}
			}
		}

		private static DrawerComponent FindLive(ZDOID drawerId)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			List<DrawerComponent> all = DrawerComponent.All;
			for (int i = 0; i < all.Count; i++)
			{
				if ((Object)(object)all[i] != (Object)null)
				{
					ZDOID zdoId = all[i].ZdoId;
					if (((ZDOID)(ref zdoId)).Equals(drawerId))
					{
						return all[i];
					}
				}
			}
			return null;
		}

		private void RetryWithdrawal(long id, PendingWithdrawal payload)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			DrawerComponent drawerComponent = FindLive(payload.DrawerId);
			if ((Object)(object)drawerComponent == (Object)null)
			{
				GiveUpWithdrawal(id, payload);
				PendingWithdrawal pendingWithdrawal = default(PendingWithdrawal);
				_pendingWithdrawals.Remove(id, ref pendingWithdrawal);
			}
			else
			{
				drawerComponent.SendWithdrawRequestRpc(id, payload.TargetOwner, payload.Requested);
			}
		}

		private void RetryDeposit(long id, PendingDeposit payload)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			DrawerComponent drawerComponent = FindLive(payload.DrawerId);
			if ((Object)(object)drawerComponent == (Object)null)
			{
				GiveUpDeposit(id, payload);
				PendingDeposit pendingDeposit = default(PendingDeposit);
				_pendingDeposits.Remove(id, ref pendingDeposit);
			}
			else
			{
				drawerComponent.SendDepositRequestRpc(id, payload.TargetOwner, payload.ItemName, payload.Removed);
			}
		}

		private static void GiveUpWithdrawal(long id, PendingWithdrawal payload)
		{
			Player player = payload.Player;
			if (player != null)
			{
				((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false);
			}
		}

		private static void GiveUpDeposit(long id, PendingDeposit payload)
		{
			//IL_002a: 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)
			if (payload.Removed > 0)
			{
				ItemFacts.SpillAtPosition(((Object)(object)payload.Player != (Object)null) ? ((Component)payload.Player).transform.position : payload.PlayerPosition, payload.ItemName, payload.Removed);
			}
			Player player = payload.Player;
			if (player != null)
			{
				((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false);
			}
		}

		private void FlushDirty()
		{
			foreach (DrawerComponent item in _dirty)
			{
				if ((Object)(object)item != (Object)null)
				{
					item.RefreshFace();
				}
			}
			_dirty.Clear();
		}

		private void SyncSomeFaces()
		{
			if (_all.Count == 0)
			{
				return;
			}
			int num = Mathf.Max(1, _all.Count / 30);
			for (int i = 0; i < num; i++)
			{
				if (_syncCursor >= _all.Count)
				{
					_syncCursor = 0;
				}
				DrawerComponent drawerComponent = _all[_syncCursor++];
				if (!((Object)(object)drawerComponent == (Object)null))
				{
					if ((Object)(object)drawerComponent.Face != (Object)null && drawerComponent.Face.NeedsFont)
					{
						drawerComponent.Face.TryConfigureCountText();
					}
					drawerComponent.RefreshFace();
				}
			}
		}

		private void UpdateLabelVisibility()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return;
			}
			Vector3 position = ((Component)main).transform.position;
			float value = DrawerConfig.LabelDistance.Value;
			float num = value * value;
			for (int i = 0; i < _all.Count; i++)
			{
				DrawerComponent drawerComponent = _all[i];
				if (!((Object)(object)drawerComponent == (Object)null))
				{
					DrawerRenderer face = drawerComponent.Face;
					if (face != null)
					{
						Vector3 val = ((Component)drawerComponent).transform.position - position;
						face.SetLabelVisible(((Vector3)(ref val)).sqrMagnitude <= num);
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(Game), "Shutdown")]
	internal static class GameShutdownPatch
	{
		private static bool Prepare()
		{
			return ValheimCompat.RequireMethod(typeof(Game), "Shutdown");
		}

		private static void Prefix()
		{
			DrawerManager.Instance?.DrainPendingDepositsBeforeSave();
		}
	}
	public static class DrawerMaterialTextures
	{
		private const int Size = 512;

		private const int WoodSeed = 1;

		private const int StoneSeed = 2;

		private const int MarbleSeed = 3;

		private static readonly Dictionary<DrawerTier, (Texture2D albedo, Texture2D normal)> _cache = new Dictionary<DrawerTier, (Texture2D, Texture2D)>();

		private static readonly Dictionary<DrawerTier, byte[]> _albedoBytes = new Dictionary<DrawerTier, byte[]>();

		private static readonly Dictionary<(DrawerTier, int), Texture2D> _brightCache = new Dictionary<(DrawerTier, int), Texture2D>();

		private static Texture2D _metal;

		public static (Texture2D albedo, Texture2D normal) Get(DrawerTier tier)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (_cache.TryGetValue(tier, out (Texture2D, Texture2D) value))
			{
				return value;
			}
			TextureData val = DrawerTextureGenerator.Generate(ToTextureTier(tier), 512, 512, SeedFor(tier));
			_albedoBytes[tier] = val.Albedo;
			(Texture2D, Texture2D) tuple = (BuildTexture(val.Albedo, "albedo", tier, linear: false), BuildTexture(val.Normal, "normal", tier, linear: true));
			_cache[tier] = tuple;
			return tuple;
		}

		public static Texture2D GetAtLightness(DrawerTier tier, float target)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			Get(tier);
			int num = Mathf.RoundToInt(target * 1000f);
			if (_brightCache.TryGetValue((tier, num), out var value))
			{
				return value;
			}
			float num2 = DrawerTextureGenerator.MidLightness(ToTextureTier(tier));
			float num3 = ((num2 > 0.0001f) ? (target / num2) : 1f);
			byte[] array = _albedoBytes[tier];
			byte[] array2 = new byte[array.Length];
			for (int i = 0; i < array.Length; i += 4)
			{
				array2[i] = Saturate((float)(int)array[i] * num3);
				array2[i + 1] = Saturate((float)(int)array[i + 1] * num3);
				array2[i + 2] = Saturate((float)(int)array[i + 2] * num3);
				array2[i + 3] = array[i + 3];
			}
			Texture2D val = BuildTexture(array2, $"albedo_bright{num}", tier, linear: false);
			_brightCache[(tier, num)] = val;
			return val;
		}

		private static byte Saturate(float v)
		{
			return (byte)((v >= 255f) ? 255f : ((v <= 0f) ? 0f : v));
		}

		public static Texture2D Metal()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			if ((Object)(object)_metal != (Object)null)
			{
				return _metal;
			}
			byte[] array = new byte[64];
			for (int i = 0; i < array.Length; i += 4)
			{
				array[i] = 197;
				array[i + 1] = 205;
				array[i + 2] = 214;
				array[i + 3] = byte.MaxValue;
			}
			_metal = new Texture2D(4, 4, (TextureFormat)4, true, false)
			{
				name = "rid_handle_metal",
				wrapMode = (TextureWrapMode)0,
				filterMode = (FilterMode)1
			};
			_metal.SetPixelData<byte>(array, 0, 0);
			_metal.Apply(true, true);
			return _metal;
		}

		private static TextureTier ToTextureTier(DrawerTier tier)
		{
			return (TextureTier)(tier switch
			{
				DrawerTier.Wood => 0, 
				DrawerTier.Stone => 1, 
				DrawerTier.BlackMarble => 2, 
				_ => 0, 
			});
		}

		private static int SeedFor(DrawerTier tier)
		{
			return tier switch
			{
				DrawerTier.Wood => 1, 
				DrawerTier.Stone => 2, 
				DrawerTier.BlackMarble => 3, 
				_ => 1, 
			};
		}

		private static Texture2D BuildTexture(byte[] rgba, string kind, DrawerTier tier, bool linear)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			Texture2D val = new Texture2D(512, 512, (TextureFormat)4, true, linear)
			{
				name = $"rid_drawer_{tier}_{kind}",
				wrapMode = (TextureWrapMode)0,
				filterMode = (FilterMode)1
			};
			val.SetPixelData<byte>(rgba, 0, 0);
			val.Apply(true, true);
			return val;
		}
	}
	internal static class MeshDataExtensions
	{
		public static Mesh ToUnityMesh(this MeshData data, string name)
		{
			//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_0092: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Expected O, but got Unknown
			Vector3[] array = (Vector3[])(object)new Vector3[data.VertexCount];
			Vector3[] array2 = (Vector3[])(object)new Vector3[data.VertexCount];
			Vector2[] array3 = (Vector2[])(object)new Vector2[data.VertexCount];
			int[] array4 = new int[data.VertexCount];
			for (int i = 0; i < data.VertexCount; i++)
			{
				array[i] = new Vector3(data.Vertices[i * 3], data.Vertices[i * 3 + 1], data.Vertices[i * 3 + 2]);
				array2[i] = new Vector3(data.Normals[i * 3], data.Normals[i * 3 + 1], data.Normals[i * 3 + 2]);
				array3[i] = new Vector2(data.Uvs[i * 2], data.Uvs[i * 2 + 1]);
			}
			for (int j = 0; j < data.TriangleCount; j++)
			{
				array4[j * 3] = j * 3;
				array4[j * 3 + 1] = j * 3 + 1;
				array4[j * 3 + 2] = j * 3 + 2;
			}
			Mesh val = new Mesh
			{
				name = name
			};
			val.SetVertices(array);
			val.SetNormals(array2);
			val.SetUVs(0, array3);
			val.SetTriangles(array4, 0);
			val.RecalculateTangents();
			val.RecalculateBounds();
			val.UploadMeshData(false);
			return val;
		}
	}
	public static class DrawerPieces
	{
		private static Mesh _sharedMesh;

		private static GameObject _prefabTemplateContainer;

		private static Mesh _sharedHandleMesh;

		private const float FaceplateLightness = 0.16f;

		private static GameObject PrefabTemplateContainer()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			if ((Object)(object)_prefabTemplateContainer == (Object)null)
			{
				_prefabTemplateContainer = new GameObject("rid_prefab_template_container");
				_prefabTemplateContainer.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)_prefabTemplateContainer);
			}
			return _prefabTemplateContainer;
		}

		public static void RegisterAll()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			DrawerProportions val = new DrawerProportions();
			_sharedMesh = DrawerMeshBuilder.Build(new DrawerProportions
			{
				Handle = (HandleStyle)0
			}).ToUnityMesh("rid_drawer");
			_sharedHandleMesh = BuildHandleMesh(val);
			DrawerTier[] all = DrawerTiers.All;
			foreach (DrawerTier drawerTier in all)
			{
				try
				{
					RegisterOne(drawerTier, val);
				}
				catch (Exception arg)
				{
					DrawerPlugin.Log.LogError((object)$"{drawerTier}: registration threw and was skipped: {arg}");
				}
			}
		}

		private static Mesh BuildHandleMesh(DrawerProportions p)
		{
			float num = Math.Min(p.FrameThickness, Math.Min(p.Width, p.Height) / 2f - 0.02f);
			float num2 = Math.Min(p.RecessDepth, p.Depth * 0.5f);
			float num3 = p.Depth / 2f - num2;
			float num4 = Math.Min(p.HandleWidth, p.Width - 2f * num - 0.02f);
			float num5 = Math.Min(p.Bevel, p.HandleSection / 2.5f);
			return DrawerMeshBuilder.ChamferBox(0f, HandleCenterY(p, num), num3 + p.HandleProud / 2f, num4, p.HandleSection, p.HandleProud, num5).ToUnityMesh("rid_drawer_handle");
		}

		private static float HandleCenterY(DrawerProportions p, float frame)
		{
			return (0f - (p.Height - 2f * frame)) / 2f + p.HandleSection * 2.4f;
		}

		private static void RegisterOne(DrawerTier tier, DrawerProportions proportions)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_007f: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			GameObject val = BuildPrefab(tier, _sharedMesh, proportions);
			if (!((Object)(object)val == (Object)null))
			{
				PieceConfig val2 = new PieceConfig
				{
					Name = DrawerTiers.DisplayName(tier),
					Description = "Holds a great many of a single item.",
					PieceTable = PieceTables.Hammer,
					CraftingStation = CraftingStations.Workbench,
					Requirements = ((IEnumerable<(string, int)>)DrawerTiers.Recipe(tier)).Select((Func<(string, int), RequirementConfig>)(((string Item, int Amount) r) => new RequirementConfig(r.Item, r.Amount, 0, true))).ToArray()
				};
				CustomPiece val3 = new CustomPiece(val, false, val2);
				if (!val3.IsValid())
				{
					DrawerPlugin.Log.LogError((object)(DrawerTiers.PrefabName(tier) + " FAILED Jotunn validation; not registered. See the Jotunn error immediately above for which check failed."));
				}
				else if (!PieceManager.Instance.AddPiece(val3))
				{
					DrawerPlugin.Log.LogError((object)("AddPiece rejected " + DrawerTiers.PrefabName(tier) + "."));
				}
				else
				{
					DrawerPlugin.Log.LogInfo((object)("Registered " + DrawerTiers.PrefabName(tier)));
				}
			}
		}

		public static GameObject BuildPrefab(DrawerTier tier, Mesh sharedMesh, DrawerProportions proportions)
		{
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Expected O, but got Unknown
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Expected O, but got Unknown
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_048f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0444: Unknown result type (might be due to invalid IL or missing references)
			//IL_0449: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Expected O, but got Unknown
			//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e9: Expected O, but got Unknown
			//IL_0616: Unknown result type (might be due to invalid IL or missing references)
			//IL_0621: Unknown result type (might be due to invalid IL or missing references)
			//IL_0590: Unknown result type (might be due to invalid IL or missing references)
			//IL_0595: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a8: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = null;
			MeshRenderer val2 = null;
			Piece val3 = null;
			string arg = null;
			string[] array = DrawerTiers.MaterialDonors(tier);
			foreach (string text in array)
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab(text);
				if ((Object)(object)prefab == (Object)null)
				{
					DrawerPlugin.Log.LogInfo((object)$"{tier}: donor '{text}' not found, trying next.");
					continue;
				}
				MeshRenderer componentInChildren = prefab.GetComponentInChildren<MeshRenderer>();
				Piece component = prefab.GetComponent<Piece>();
				if ((Object)(object)componentInChildren == (Object)null || (Object)(object)((Renderer)componentInChildren).sharedMaterial == (Object)null || (Object)(object)component == (Object)null || (Object)(object)component.m_icon == (Object)null)
				{
					DrawerPlugin.Log.LogInfo((object)($"{tier}: donor '{text}' unusable " + "(renderer=" + (((Object)(object)componentInChildren == (Object)null) ? "none" : "ok") + ", material=" + (((Object)(object)componentInChildren == (Object)null || (Object)(object)((Renderer)componentInChildren).sharedMaterial == (Object)null) ? "none" : "ok") + ", piece=" + (((Object)(object)component == (Object)null) ? "none" : "ok") + ", icon=" + (((Object)(object)component == (Object)null || (Object)(object)component.m_icon == (Object)null) ? "none" : "ok") + "), trying next."));
					continue;
				}
				val = prefab;
				val2 = componentInChildren;
				val3 = component;
				arg = text;
				break;
			}
			if ((Object)(object)val == (Object)null)
			{
				DrawerPlugin.Log.LogError((object)($"No usable material donor for {tier}. Tried: " + string.Join(", ", DrawerTiers.MaterialDonors(tier)) + ". This tier will be missing from the build menu."));
				return null;
			}
			GameObject val4 = new GameObject(DrawerTiers.PrefabName(tier));
			val4.transform.SetParent(PrefabTemplateContainer().transform, false);
			GameObject val5 = new GameObject("body");
			val5.transform.SetParent(val4.transform, false);
			val5.AddComponent<MeshFilter>().sharedMesh = sharedMesh;
			MeshRenderer val6 = val5.AddComponent<MeshRenderer>();
			Material val7 = new Material(((Renderer)val2).sharedMaterial.shader)
			{
				name = $"rid_drawer_{tier}_mat"
			};
			if (val7.HasProperty("_Color"))
			{
				val7.SetColor("_Color", Color.white);
			}
			bool flag = val7.HasProperty("_TriplanarScale");
			bool flag2 = false;
			if (flag)
			{
				val7.EnableKeyword("_TRIPLANARMAP_ON");
				val7.SetFloat("_TriplanarScale", 1f);
				flag2 = val7.HasProperty("_TriplanarLocalPos");
				if (flag2)
				{
					val7.SetFloat("_TriplanarLocalPos", 1f);
				}
				else
				{
					DrawerPlugin.Log.LogWarning((object)($"{tier}: shader has no _TriplanarLocalPos; triplanar mapping " + "will stay projected in world space, which makes each placed drawer's surfaces sample the normal map differently."));
				}
			}
			else
			{
				DrawerPlugin.Log.LogWarning((object)$"{tier}: shader has no _TriplanarScale; leaving UV mapping in place.");
			}
			(Texture2D albedo, Texture2D normal) tuple = DrawerMaterialTextures.Get(tier);
			Texture2D item = tuple.albedo;
			Texture2D item2 = tuple.normal;
			bool flag3 = val7.HasProperty("_MainTex");
			if (flag3)
			{
				val7.SetTexture("_MainTex", (Texture)(object)item);
			}
			bool flag4 = val7.HasProperty("_BumpMap");
			if (flag4)
			{
				val7.SetTexture("_BumpMap", (Texture)(object)item2);
				val7.EnableKeyword("_NORMALMAP");
			}
			string text2 = ((flag3 && flag4) ? "albedo+normal" : (flag3 ? "albedo only (shader has no _BumpMap)" : "NONE (shader has neither _MainTex nor _BumpMap)"));
			DrawerPlugin.Log.LogInfo((object)($"{tier}: donor='{arg}', shader='{((Object)((Renderer)val2).sharedMaterial.shader).name}', " + "triplanar=" + (flag ? "on" : "off") + ", triplanarLocalPos=" + (flag2 ? "on" : "off") + ", textures=" + text2 + ", keywords=[" + string.Join(",", val7.shaderKeywords) + "]"));
			((Renderer)val6).sharedMaterial = val7;
			((Renderer)val6).shadowCastingMode = (ShadowCastingMode)1;
			Material val8 = null;
			if (flag3)
			{
				val8 = new Material(val7)
				{
					name = ((Object)val7).name + "_faceplate"
				};
				val8.SetTexture("_MainTex", (Texture)(object)DrawerMaterialTextures.GetAtLightness(tier, 0.16f));
			}
			val4.AddComponent<BoxCollider>().size = new Vector3(0.66f, 0.66f, 0.66f);
			AddSnapPoints(val4, proportions);
			val4.AddComponent<ZNetView>().m_persistent = true;
			val4.AddComponent<DrawerComponent>();
			if ((Object)(object)_sharedHandleMesh != (Object)null && flag3)
			{
				Material val9 = new Material(val7)
				{
					name = ((Object)val7).name + "_handle"
				};
				val9.SetTexture("_MainTex", (Texture)(object)DrawerMaterialTextures.Metal());
				if (val9.HasProperty("_BumpMap"))
				{
					val9.SetTexture("_BumpMap", (Texture)null);
					val9.DisableKeyword("_NORMALMAP");
				}
				array = new string[2] { "_Glossiness", "_Smoothness" };
				foreach (string text3 in array)
				{
					if (val9.HasProperty(text3))
					{
						val9.SetFloat(text3, 0.65f);
					}
				}
				if (val9.HasProperty("_Metallic"))
				{
					val9.SetFloat("_Metallic", 0.8f);
				}
				GameObject val10 = new GameObject("handle");
				val10.transform.SetParent(val4.transform, false);
				val10.AddComponent<MeshFilter>().sharedMesh = _sharedHandleMesh;
				MeshRenderer obj = val10.AddComponent<MeshRende