Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of GrillspettItemDrawers v1.0.0
plugins/ItemDrawers.Core.dll
Decompiled a month agousing 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+7be62b9b999934a60580658f7b1b2e447be02a32")] [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 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 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 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 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 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 a month ago
The result has been truncated due to the large size, download it to view full contents!
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.Events; 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+7be62b9b999934a60580658f7b1b2e447be02a32")] [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 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); } } internal static class DrawerAssignUI { [CompilerGenerated] private static class <>O { public static UnityAction <0>__Close; } private const float PanelWidth = 260f; private const float PanelHeight = 340f; private const float RowHeight = 32f; private static GameObject _panel; private static Transform _content; private static readonly List<GameObject> _rows = new List<GameObject>(); private static DrawerComponent _openDrawer; private static Player _openPlayer; public static bool IsOpen { get { if ((Object)(object)_panel != (Object)null) { return _panel.activeSelf; } return false; } } public static void EnsureBuilt() { //IL_003e: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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_00bb: 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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0144: 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_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Expected O, but got Unknown if (!((Object)(object)_panel != (Object)null) && GUIManager.Instance != null && !((Object)(object)GUIManager.CustomGUIFront == (Object)null)) { GUIManager instance = GUIManager.Instance; _panel = instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 260f, 340f); _panel.SetActive(false); ((Object)instance.CreateText("Assign item", _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -18f), instance.AveriaSerifBold, 18, Color.white, true, Color.black, 240f, 24f, false)).name = "Title"; GameObject obj = instance.CreateScrollView(_panel.transform, false, true, 8f, 2f, ColorBlock.defaultColorBlock, new Color(0f, 0f, 0f, 0.4f), 240f, 250f); RectTransform val = (RectTransform)obj.transform; val.anchorMin = new Vector2(0.5f, 1f); val.anchorMax = new Vector2(0.5f, 1f); val.pivot = new Vector2(0.5f, 1f); val.anchoredPosition = new Vector2(0f, -48f); _content = obj.transform.Find("Scroll View/Viewport/Content"); ButtonClickedEvent onClick = instance.CreateButton("Cancel", _panel.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 20f), 100f, 28f).GetComponent<Button>().onClick; object obj2 = <>O.<0>__Close; if (obj2 == null) { UnityAction val2 = Close; <>O.<0>__Close = val2; obj2 = (object)val2; } ((UnityEvent)onClick).AddListener((UnityAction)obj2); } } public static void Open(DrawerComponent drawer, Player player) { //IL_0021: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown EnsureBuilt(); if ((Object)(object)_panel == (Object)null || (Object)(object)_content == (Object)null) { return; } DrawerSnapshot snapshot = drawer.Snapshot; if (((DrawerSnapshot)(ref snapshot)).IsAssigned) { ((Character)player).Message((MessageType)2, "Already holds " + ItemFacts.LocalizedName(snapshot.ItemName) + " -- Shift+Interact to add more", 0, (Sprite)null, false); return; } Dictionary<string, int> dictionary = ItemFacts.StorableItemCounts(((Humanoid)player).GetInventory()); if (dictionary.Count == 0) { ((Character)player).Message((MessageType)2, "Nothing storable to assign", 0, (Sprite)null, false); return; } ClearRows(); foreach (KeyValuePair<string, int> item in dictionary.OrderBy((KeyValuePair<string, int> kv) => ItemFacts.LocalizedName(kv.Key))) { string itemName = item.Key; int value = item.Value; GameObject val = GUIManager.Instance.CreateButton($"{ItemFacts.LocalizedName(itemName)} x{value}", _content, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), Vector2.zero, 220f, 32f); LayoutElement obj = val.AddComponent<LayoutElement>(); obj.preferredHeight = 32f; obj.minHeight = 32f; AddRowIcon(val, itemName); ((UnityEvent)val.GetComponent<Button>().onClick).AddListener((UnityAction)delegate { OnRowClicked(itemName); }); _rows.Add(val); } _openDrawer = drawer; _openPlayer = player; _panel.SetActive(true); GUIManager.BlockInput(true); } public static void Close() { if (!((Object)(object)_panel == (Object)null) && _panel.activeSelf) { _panel.SetActive(false); GUIManager.BlockInput(false); _openDrawer = null; _openPlayer = null; ClearRows(); } } public static void CloseIfShowing(DrawerComponent drawer) { if ((Object)(object)_openDrawer == (Object)(object)drawer) { Close(); } } private static void OnRowClicked(string itemName) { DrawerComponent openDrawer = _openDrawer; Player openPlayer = _openPlayer; Close(); if ((Object)(object)openDrawer != (Object)null && (Object)(object)openPlayer != (Object)null) { openDrawer.AssignAndDeposit(openPlayer, itemName); } } private static void ClearRows() { foreach (GameObject row in _rows) { if ((Object)(object)row != (Object)null) { Object.Destroy((Object)(object)row); } } _rows.Clear(); } private static void AddRowIcon(GameObject row, string itemName) { //IL_002b: 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_0042: 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_004d: 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_0062: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) float num = 24f; GameObject val = new GameObject("Icon", new Type[2] { typeof(RectTransform), typeof(Image) }); val.transform.SetParent(row.transform, false); RectTransform val2 = (RectTransform)val.transform; val2.anchorMin = new Vector2(0f, 0.5f); val2.anchorMax = new Vector2(0f, 0.5f); val2.pivot = new Vector2(0f, 0.5f); val2.anchoredPosition = new Vector2(4f, 0f); val2.sizeDelta = new Vector2(num, num); Image component = val.GetComponent<Image>(); component.sprite = ItemFacts.Icon(itemName); component.preserveAspect = true; val.SetActive((Object)(object)component.sprite != (Object)null); Text componentInChildren = row.GetComponentInChildren<Text>(); if ((Object)(object)componentInChildren != (Object)null) { RectTransform rectTransform = ((Graphic)componentInChildren).rectTransform; rectTransform.offsetMin = new Vector2(4f + num + 4f, rectTransform.offsetMin.y); } } } public class DrawerComponent : Container, Interactable, Hoverable { public static readonly List<DrawerComponent> All = new List<DrawerComponent>(); private const string KeyAssignedItem = "AssignedItem"; private static readonly int AssignedItemHash = StringExtensionMethods.GetStableHashCode("AssignedItem"); private const string OldKeyPrefab = "Prefab"; private const string OldKeyAmount = "Amount"; private static readonly int OldPrefabHash = StringExtensionMethods.GetStableHashCode("Prefab"); private static readonly int OldAmountHash = StringExtensionMethods.GetStableHashCode("Amount"); private static readonly int CreatorHash = StringExtensionMethods.GetStableHashCode("creator"); internal const string CommitFailedMessage = "Try again"; private static readonly ConditionalWeakTable<Inventory, DrawerComponent> InventoryOwners = new ConditionalWeakTable<Inventory, DrawerComponent>(); private ZNetView _view; private ZDOID _zdoId = ZDOID.None; private bool _enforcingType; 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_0050: 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) if ((Object)(object)_view == (Object)null || !_view.IsValid()) { return new DrawerSnapshot("", 0); } string text = _view.GetZDO().GetString(AssignedItemHash, ""); if (string.IsNullOrEmpty(text)) { return new DrawerSnapshot("", 0); } Inventory inventory = ((Container)this).GetInventory(); int num = ((inventory != null) ? ItemFacts.CountByPrefab(inventory, text) : 0); return new DrawerSnapshot(text, num); } } public int Capacity => DrawerConfig.SlotsFor(Tier) * ItemFacts.MaxStackSize(Snapshot.ItemName); internal string DiagId { get { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!((ZDOID)(ref _zdoId)).IsNone()) { return $"{((Object)((Component)this).gameObject).name}#{_zdoId}"; } return ((Object)((Component)this).gameObject).name; } } internal static bool InventoryOwnersLookup(Inventory inventory, out DrawerComponent drawer) { return InventoryOwners.TryGetValue(inventory, out drawer); } 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) //IL_008b: 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); base.m_width = DrawerConfig.SlotsFor(Tier); base.m_height = 1; base.m_name = DrawerTiers.DisplayName(Tier); base.m_privacy = (PrivacySetting)2; EnsureCreator(); ((Container)this).Awake(); Inventory inventory = ((Container)this).GetInventory(); if (inventory != null) { InventoryOwners.Remove(inventory); InventoryOwners.Add(inventory, this); MigrateOldFormatIfNeeded(inventory); All.Add(this); DrawerManager.Instance?.Register(this); } } } private void MigrateOldFormatIfNeeded(Inventory inventory) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner()) { return; } ZDO zDO = _view.GetZDO(); string text = zDO.GetString(OldPrefabHash, ""); if (string.IsNullOrEmpty(text)) { return; } int num = zDO.GetInt(OldAmountHash, 0); if (num > 0 && ItemFacts.IsStorable(text)) { int num2 = DepositByPrefab(inventory, text, num); int num3 = num - num2; if (num3 > 0) { ItemFacts.SpillAtPosition(((Component)this).transform.position, text, num3); } } zDO.Set(AssignedItemHash, text); zDO.Set(OldAmountHash, 0, false); zDO.Set(OldPrefabHash, ""); DrawerPlugin.Log.LogInfo((object)$"Migrated drawer '{DiagId}' from the old single-stack format ({num} {text})."); } 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() { All.Remove(this); DrawerManager.Instance?.Unregister(this); DrawerAssignUI.CloseIfShowing(this); DrawerTakeAmountUI.CloseIfShowing(this); } 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; } 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); } } private void ClaimForWrite() { if ((Object)(object)_view != (Object)null && _view.IsValid() && !_view.IsOwner()) { _view.ClaimOwnership(); } } private static int RemoveByPrefab(Inventory inv, string itemName, int amount) { if (amount <= 0) { return 0; } int num = 0; foreach (ItemData item in new List<ItemData>(inv.GetAllItems())) { if (num >= amount) { break; } if (!(ItemFacts.PrefabNameOf(item) != itemName)) { int num2 = Math.Min(item.m_stack, amount - num); if (inv.RemoveItem(item, num2)) { num += num2; } } } return num; } private static int DepositByPrefab(Inventory inv, string itemName, int amount) { GameObject val = ItemFacts.Prefab(itemName); if ((Object)(object)val == (Object)null || amount <= 0) { return 0; } int num = ItemFacts.MaxStackSize(itemName); int num2 = ItemFacts.CountByPrefab(inv, itemName); foreach (int item in ChunkSplitter.Chunks(amount, num)) { inv.AddItem(val, item); } return ItemFacts.CountByPrefab(inv, itemName) - num2; } public bool Interact(Humanoid user, bool hold, bool alt) { //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_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_015c: 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) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) if (hold) { return false; } Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)val == (Object)null) { return false; } if ((Object)(object)_view == (Object)null || !_view.IsValid()) { return false; } ClaimForWrite(); DrawerSnapshot snapshot = Snapshot; Inventory inventory = ((Container)this).GetInventory(); if (inventory == null) { return true; } bool button = ZInput.GetButton("Crouch"); bool button2 = ZInput.GetButton("Run"); if (button && button2) { if (!((DrawerSnapshot)(ref snapshot)).IsAssigned || ((DrawerSnapshot)(ref snapshot)).IsEmpty) { return true; } if (!DrawerAssignUI.IsOpen && !DrawerTakeAmountUI.IsOpen) { DrawerTakeAmountUI.Open(this, val, snapshot); } return true; } if (button) { if (!((DrawerSnapshot)(ref snapshot)).IsAssigned) { return true; } if (((DrawerSnapshot)(ref snapshot)).IsEmpty) { _view.GetZDO().Set(AssignedItemHash, ""); RefreshFace(); return true; } if ((Object)(object)ItemFacts.Drop(snapshot.ItemName) == (Object)null) { ((Character)val).Message((MessageType)2, "Cannot identify this item", 0, (Sprite)null, false); return true; } int num = RemoveByPrefab(inventory, snapshot.ItemName, 1); if (num > 0) { ItemFacts.GiveToPlayer(val, snapshot.ItemName, num); RefreshFace(); } return true; } if (button2) { return DepositEverythingMatching(val, snapshot); } if (!((DrawerSnapshot)(ref snapshot)).IsAssigned) { return true; } if ((Object)(object)ItemFacts.Drop(snapshot.ItemName) == (Object)null) { ((Character)val).Message((MessageType)2, "Cannot identify this item", 0, (Sprite)null, false); return true; } int val2 = ItemFacts.MaxStackSize(snapshot.ItemName); int num2 = RemoveByPrefab(inventory, snapshot.ItemName, Math.Min(val2, snapshot.Amount)); if (num2 > 0) { ItemFacts.GiveToPlayer(val, snapshot.ItemName, num2); RefreshFace(); } return true; } public bool UseItem(Humanoid user, ItemData item) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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; } ClaimForWrite(); 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; } Inventory inventory = ((Container)this).GetInventory(); if (inventory == null) { ((Character)val).Message((MessageType)2, "Try again", 0, (Sprite)null, false); return true; } bool flag = !((DrawerSnapshot)(ref snapshot)).IsAssigned; if (flag) { _view.GetZDO().Set(AssignedItemHash, text); } int num = DepositByPrefab(inventory, text, item.m_stack); if (num <= 0) { if (flag) { _view.GetZDO().Set(AssignedItemHash, ""); } ((Character)val).Message((MessageType)2, "This drawer is full", 0, (Sprite)null, false); return true; } ((Humanoid)val).GetInventory().RemoveItem(item, num); RefreshFace(); return true; } private bool DepositEverythingMatching(Player player, DrawerSnapshot current) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (!((DrawerSnapshot)(ref current)).IsAssigned) { ((Character)player).Message((MessageType)2, "Not assigned yet", 0, (Sprite)null, false); return true; } return DepositAllOfItemInternal(player, current.ItemName, announce: true); } public void AssignAndDeposit(Player player, string itemName) { if (!string.IsNullOrEmpty(itemName)) { DepositAllOfItemInternal(player, itemName, announce: false); } } private bool DepositAllOfItemInternal(Player player, string itemName, bool announce) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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()) { ((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false); return true; } ClaimForWrite(); DrawerSnapshot snapshot = Snapshot; if (((DrawerSnapshot)(ref snapshot)).IsAssigned && snapshot.ItemName != itemName) { ((Character)player).Message((MessageType)2, "This drawer holds " + ItemFacts.LocalizedName(snapshot.ItemName), 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) != itemName) && !ExtraSlotsCompat.IsInReservedSlot(allItem)) { 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; } Inventory inventory2 = ((Container)this).GetInventory(); if (inventory2 == null) { ((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false); return true; } bool flag = !((DrawerSnapshot)(ref snapshot)).IsAssigned; if (flag) { _view.GetZDO().Set(AssignedItemHash, itemName); } int num2 = DepositByPrefab(inventory2, itemName, num); if (num2 <= 0) { if (flag) { _view.GetZDO().Set(AssignedItemHash, ""); } ((Character)player).Message((MessageType)2, "This drawer is full", 0, (Sprite)null, false); return true; } int num3 = num2; foreach (ItemData item in list) { if (num3 <= 0) { break; } int num4 = ((item.m_stack < num3) ? item.m_stack : num3); if (inventory.RemoveItem(item, num4)) { num3 -= num4; } } RefreshFace(); if (announce) { ((Character)player).Message((MessageType)1, $"Stored {num2} {ItemFacts.LocalizedName(itemName)}", 0, (Sprite)null, false); } return true; } public bool TryWithdrawExact(Player player, string itemName, int amount) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) if ((Object)(object)_view == (Object)null || !_view.IsValid() || (Object)(object)player == (Object)null) { return false; } DrawerSnapshot snapshot = Snapshot; if (!((DrawerSnapshot)(ref snapshot)).IsAssigned || snapshot.ItemName != itemName || amount <= 0) { return false; } if ((Object)(object)ItemFacts.Drop(itemName) == (Object)null) { return false; } ClaimForWrite(); Inventory inventory = ((Container)this).GetInventory(); if (inventory == null) { return false; } int num = RemoveByPrefab(inventory, itemName, Math.Min(amount, snapshot.Amount)); if (num <= 0) { return false; } ItemFacts.GiveToPlayer(player, itemName, num); RefreshFace(); return true; } public bool TryWithdrawExternally(int requested, out int taken) { //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_002d: 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) taken = 0; DrawerSnapshot snapshot = Snapshot; if (!((DrawerSnapshot)(ref snapshot)).IsAssigned || requested <= 0) { return false; } Inventory inventory = ((Container)this).GetInventory(); if (inventory == null) { return false; } ClaimForWrite(); taken = RemoveByPrefab(inventory, snapshot.ItemName, Math.Min(requested, snapshot.Amount)); if (taken <= 0) { return false; } RefreshFace(); return true; } public bool TryDepositExternally(string itemName, int amount, out int accepted) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) accepted = 0; if (!ItemFacts.IsStorable(itemName) || amount <= 0) { return false; } DrawerSnapshot snapshot = Snapshot; if (((DrawerSnapshot)(ref snapshot)).IsAssigned && snapshot.ItemName != itemName) { return false; } Inventory inventory = ((Container)this).GetInventory(); if (inventory == null || (Object)(object)_view == (Object)null || !_view.IsValid()) { return false; } ClaimForWrite(); bool flag = !((DrawerSnapshot)(ref snapshot)).IsAssigned; if (flag) { _view.GetZDO().Set(AssignedItemHash, itemName); } accepted = DepositByPrefab(inventory, itemName, amount); if (accepted <= 0) { if (flag) { _view.GetZDO().Set(AssignedItemHash, ""); } return false; } RefreshFace(); return true; } internal void EnforceSingleItemType() { //IL_014b: Unknown result type (might be due to invalid IL or missing references) if (_enforcingType || (Object)(object)_view == (Object)null || !_view.IsValid()) { return; } Inventory inventory = ((Container)this).GetInventory(); if (inventory == null) { return; } _enforcingType = true; try { ClaimForWrite(); ZDO zDO = _view.GetZDO(); string text = zDO.GetString(AssignedItemHash, ""); if (string.IsNullOrEmpty(text)) { string text2 = null; foreach (ItemData allItem in inventory.GetAllItems()) { text2 = ItemFacts.PrefabNameOf(allItem); if (text2 != null) { break; } } if (text2 == null) { return; } text = text2; zDO.Set(AssignedItemHash, text); } List<ItemData> list = null; foreach (ItemData allItem2 in inventory.GetAllItems()) { if (!(ItemFacts.PrefabNameOf(allItem2) == text)) { (list ?? (list = new List<ItemData>())).Add(allItem2); } } if (list == null) { return; } foreach (ItemData item in list) { string text3 = ItemFacts.PrefabNameOf(item); int stack = item.m_stack; inventory.RemoveItem(item); if (text3 != null) { ItemFacts.SpillAtPosition(((Component)this).transform.position, text3, stack); } } RefreshFace(); } finally { _enforcingType = false; } } 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_004f: 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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) DrawerSnapshot snapshot = Snapshot; if (!((DrawerSnapshot)(ref snapshot)).IsAssigned) { string text = ((object)DrawerConfig.AssignKey.Value/*cast due to .constrained prefix*/).ToString(); return Localization.instance.Localize(DrawerTiers.DisplayName(Tier) + "\n[<color=yellow><b>" + text + "</b></color>] Assign from inventory\n[<color=yellow><b>1-8</b></color>] Assign from hotbar"); } 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\n[<color=yellow><b>Ctrl+Shift+E</b></color>] Take amount"); } public string GetHoverName() { return DrawerTiers.DisplayName(Tier); } } [HarmonyPatch(typeof(Inventory), "Changed", new Type[] { typeof(bool), typeof(bool) })] internal static class DrawerTypeEnforcementPatch { private static bool Prepare() { return ValheimCompat.RequireMethod(typeof(Inventory), "Changed"); } private static void Postfix(Inventory __instance) { if (DrawerComponent.InventoryOwnersLookup(__instance, out var drawer)) { drawer.EnforceSingleItemType(); } } } [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) { if (!(__instance is DrawerComponent drawerComponent)) { return true; } Inventory inventory = ((Container)drawerComponent).GetInventory(); __result = inventory == null || inventory.NrOfItems() == 0; return false; } } public static class DrawerConfig { public static ConfigEntry<int> WoodSlots; public static ConfigEntry<int> StoneSlots; public static ConfigEntry<int> BlackMarbleSlots; 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 ConfigEntry<KeyCode> AssignKey; public static void Bind(ConfigFile config) { //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_002c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_005a: 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_0067: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected O, but got Unknown //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Expected O, but got Unknown //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Expected O, but got Unknown WoodSlots = config.Bind<int>("Slots", "Wood", DrawerTiers.DefaultSlots(DrawerTier.Wood), new ConfigDescription("How many real item slots a wood drawer has.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); StoneSlots = config.Bind<int>("Slots", "Stone", DrawerTiers.DefaultSlots(DrawerTier.Stone), new ConfigDescription("How many real item slots a stone drawer has.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); BlackMarbleSlots = config.Bind<int>("Slots", "BlackMarble", DrawerTiers.DefaultSlots(DrawerTier.BlackMarble), new ConfigDescription("How many real item slots a black marble drawer has.", (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."); AssignKey = config.Bind<KeyCode>("Controls", "AssignDrawerKey", (KeyCode)111, "Key to open a picker, while looking at an unassigned drawer, listing what you're carrying so you can assign it without needing a hotbar slot. Already-assigned drawers are unaffected -- use Shift+Interact to add more of what they already hold."); } public static int SlotsFor(DrawerTier tier) { return tier switch { DrawerTier.Wood => WoodSlots?.Value ?? DrawerTiers.DefaultSlots(tier), DrawerTier.Stone => StoneSlots?.Value ?? DrawerTiers.DefaultSlots(tier), DrawerTier.BlackMarble => BlackMarbleSlots?.Value ?? DrawerTiers.DefaultSlots(tier), _ => DrawerTiers.DefaultSlots(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; } } 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); 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 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(); CheckAssignDrawerKey(); DrawerTakeAmountUI.PollKeyboardInput(); _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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0171: 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_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); DrawerComponent drawerComponent = null; for (int j = 0; j < _pickupScratch.Count; j++) { DrawerComponent drawerComponent2 = _pickupScratch[j]; if (!((Object)(object)drawerComponent2 == (Object)null)) { DrawerSnapshot snapshot = drawerComponent2.Snapshot; if (((DrawerSnapshot)(ref snapshot)).IsAssigned && !(snapshot.ItemName != text)) { drawerComponent = drawerComponent2; break; } } } if ((Object)(object)drawerComponent == (Object)null) { continue; } int accepted; if (!val.CanPickup(true)) { val.RequestOwn(); } else if (drawerComponent.TryDepositExternally(text, val.m_itemData.m_stack, out 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(); } } } } 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 CheckAssignDrawerKey() { string assignDrawerButtonName = DrawerPlugin.AssignDrawerButtonName; if (assignDrawerButtonName == null || !ZInput.GetButtonDown(assignDrawerButtonName) || DrawerAssignUI.IsOpen || DrawerTakeAmountUI.IsOpen) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { GameObject hoverObject = ((Humanoid)localPlayer).GetHoverObject(); DrawerComponent drawerComponent = ((hoverObject != null) ? hoverObject.GetComponent<DrawerComponent>() : null); if ((Object)(object)drawerComponent != (Object)null) { DrawerAssignUI.Open(drawerComponent, localPlayer); } } } 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); } } } } } 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<MeshRenderer>(); ((Renderer)obj).sharedMaterial = val9; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1; } DrawerRenderer.Attach(val4, proportions, val8); Piece obj2 = val4.AddComponent<Piece>(); obj2.m_name = DrawerTiers.DisplayName(tier); obj2.m_description = "Holds a great many of a single item."; obj2.m_icon = RenderIconFromMesh(sharedMesh, val7, tier) ?? val3.m_icon; obj2.m_enabled = true; obj2.m_category = (PieceCategory)4; obj2.m_usage = (UsageTagFlags)1152; obj2.m_comfort = 0; WearNTear obj3 = val4.AddComponent<WearNTear>(); obj3.m_health = ((tier == DrawerTier.Wood) ? 200f : 400f); obj3.m_noSupportWear = false; obj3.m_noRoofWear = tier != DrawerTier.Wood; obj3.m_destroyedEffect = val.GetComponent<WearNTear>()?.m_destroyedEffect; obj3.m_hitEffect = val.GetComponent<WearNTear>()?.m_hitEffect; return val4; } private static void AddSnapPoints(GameObject go, DrawerProportions p) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) float num = p.Width / 2f; float num2 = p.Height / 2f; float num3 = p.Depth / 2f; Vector3[] array = (Vector3[])(object)new Vector3[6] { new Vector3(0f, num2, 0f), new Vector3(0f, 0f - num2, 0f), new Vector3(num, 0f, 0f), new Vector3(0f - num, 0f, 0f), new Vector3(0f, 0f, num3), new Vector3(0f, 0f, 0f - num3) }; List<Vector3> list = new List<Vector3>(8); float[] array2 = new float[2] { -1f, 1f }; foreach (float num4 in array2) { float[] array3 = new float[2] { -1f, 1f }; foreach (float num5 in array3) { float[] array4 = new float[2] { -1f, 1f }; foreach (float num6 in array4) { list.Add(new Vector3(num4 * num, num5 * num2, num6 * num3)); } } } int num7 = 1; Vector3[] array5 = array; foreach (Vector3 localPosition in array5) { GameObject val = new GameObject($"snappoint_{num7++}") { tag = "snappoint" }; val.transform.SetParent(go.transform, false); val.transform.localPosition = localPosition; } foreach (Vector3 item in list) { GameObject val2 = new GameObject($"snappoint_{num7++}") { tag = "snappoint" }; val2.transform.SetParent(go.transform, false); val2.transform.localPosition = item; } } private static Sprite RenderIconFromMesh(Mesh mesh, Material material, DrawerTier tier) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //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_0027: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("rid_icon_source"); try { GameObject val2 = new GameObject("body"); val2.transform.SetParent(val.transform, false); val2.AddComponent<MeshFilter>().sharedMesh = mesh; ((Renderer)val2.AddComponent<MeshRenderer>()).sharedMaterial = material; return RenderIcon(val, tier); } finally { Object.Destroy((Object)(object)val); } } private static Sprite RenderIcon(GameObject prefab, DrawerTier tier) { //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_0007: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown try { RenderRequest val = new RenderRequest(prefab) { Rotation = RenderManager.IsometricRotation, Width = 128, Height = 128 }; Sprite obj = RenderManager.Instance.Render(val); if ((Object)(object)obj == (Object)null) { DrawerPlugin.Log.LogWarning((object)$"RenderManager returned no sprite for {tier}; falling back to donor icon."); } return obj; } catch (Exception ex) { DrawerPlugin.Log.LogWarning((object)$"RenderManager threw rendering {tier}'s icon ({ex.Message}); falling back to donor icon."); return null; } } } [BepInPlugin("com.grillspett.itemdrawers", "GrillspettItemDrawers", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class DrawerPlugin : BaseUnityPlugin { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Converter<Piece, string> <>9__14_2; public static ConsoleEvent <>9__14_0; internal void <RegisterDiagCommand>b__14_0(ConsoleEventArgs args) { //IL_06aa: Unknown result type (might be due to invalid IL or missing references) //IL_06b1: 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_0431: Unknown result type (might be due to invalid IL or missing references) //IL_05ec: Unknown result type (might be due to invalid IL or missing references) //IL_05f1: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0550: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) <>c__DisplayClass14_0 <>c__DisplayClass14_ = default(<>c__DisplayClass14_0); <>c__DisplayClass14_.args = args; DrawerTier[] all = DrawerTiers.All; for (int i = 0; i < all.Length; i++) { string text = DrawerTiers.PrefabName(all[i]); <RegisterDiagCommand>g__Say|14_1("--- " + text + " ---", ref <>c__DisplayClass14_); GameObject prefab = PrefabManager.Instance.GetPrefab(text); Piece val = (((Object)(object)prefab == (Object)null) ? null : prefab.GetComponent<Piece>()); if ((Object)(object)val == (Object)null) { <RegisterDiagCommand>g__Say|14_1("prefab or Piece MISSING", ref <>c__DisplayClass14_); continue; } <RegisterDiagCommand>g__Say|14_1(string.Format("m_enabled={0} m_category={1} m_name='{2}' m_icon={3}", val.m_enabled, val.m_category, val.m_name, ((Object)(object)val.m_icon == (Object)null) ? "NULL" : ((Object)val.m_icon).name), ref <>c__DisplayClass14_); <RegisterDiagCommand>g__Say|14_1($"m_usage={val.m_usage} (this is what 1.0's build-menu tabs filter on)", ref <>c__DisplayClass14_); <RegisterDiagCommand>g__Say|14_1("m_craftingStation=" + (((Object)(object)val.m_craftingStation == (Object)null) ? "none" : val.m_craftingStation.m_name), ref <>c__DisplayClass14_); Requirement[] resources = val.m_resources; <RegisterDiagCommand>g__Say|14_1($"requirements={((resources != null) ? resources.Length : 0)}", ref <>c__DisplayClass14_); if (resources != null) { Requirement[] array = resources; foreach (Requirement val2 in array) { <RegisterDiagCommand>g__Say|14_1(string.Format(" res={0} x{1}", ((Object)(object)val2.m_resItem == (Object)null) ? "UNRESOLVED" : val2.m_resItem.m_itemData.m_shared.m_name, val2.m_amount), ref <>c__DisplayClass14_); } } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { <RegisterDiagCommand>g__Say|14_1("no local player", ref <>c__DisplayClass14_); continue; } <RegisterDiagCommand>g__Say|14_1($"IsRecipeKnown('{val.m_name}')={localPlayer.IsRecipeKnown(val.m_name)}", ref <>c__DisplayClass14_); <RegisterDiagCommand>g__Say|14_1($"HaveRequirements(IsKnown)={localPlayer.HaveRequirements(val, (RequirementMode)1)}", ref <>c__DisplayClass14_); if ((Object)(object)val.m_craftingStation != (Object)null) { bool flag = localPlayer.m_knownStations.ContainsKey(val.m_craftingStation.m_name); bool flag2 = Object.op_Implicit((Object)(object)CraftingStation.HaveBuildStationInRange(val.m_craftingStation.m_name, ((Component)localPlayer).transform.position)); <RegisterDiagCommand>g__Say|14_1($"station '{val.m_craftingStation.m_name}': known={flag} inRange={flag2}" + (flag ? "" : " <-- BLOCKS IsKnown; build a workbench and stand near it"), ref <>c__DisplayClass14_); } <RegisterDiagCommand>g__Say|14_1($"HaveRequirements(CanBuild)={localPlayer.HaveRequirements(val, (RequirementMode)0)}", ref <>c__DisplayClass14_); PieceTable pieceTable = PieceManager.Instance.GetPieceTable(PieceTables.Hammer); PieceTable buildPieces = localPlayer.m_buildPieces; <RegisterDiagCommand>g__Say|14_1("jotunnTable=" + (((Object)(object)pieceTable == (Object)null) ? "null" : ((Object)pieceTable).name) + " playerTable=" + (((Object)(object)buildPieces == (Object)null) ? "null" : ((Object)buildPieces).name) + " " + $"SAME INSTANCE={pieceTable == buildPieces}", ref <>c__DisplayClass14_); if ((Object)(object)buildPieces == (Object)null) { <RegisterDiagCommand>g__Say|14_1("player has no build table equipped", ref <>c__DisplayClass14_); } else { <RegisterDiagCommand>g__Say|14_1($"[player table] in m_pieces={buildPieces.m_pieces.Contains(prefab)} " + $"in m_enabledPieces={buildPieces.m_enabledPieces.Contains(val)} " + $"in m_availablePieces={buildPieces.m_availablePieces.Contains(val)}", ref <>c__DisplayClass14_); } } Player localPlayer2 = Player.m_localPlayer; PieceTable val3 = (((Object)(object)localPlayer2 == (Object)null) ? null : localPlayer2.m_buildPieces); if ((Object)(object)val3 == (Object)null) { <RegisterDiagCommand>g__Say|14_1("no player / no build table for category dump", ref <>c__DisplayClass14_); } else { <RegisterDiagCommand>g__Say|14_1($"[player table] selectedCategory={val3.GetSelectedCategory()} " + "categories=[" + string.Join(", ", val3.m_categories) + "]", ref <>c__DisplayClass14_); for (int k = 0; k < val3.m_availablePiecesByCategory.Count; k++) { List<Piece> list = val3.m_availablePiecesByCategory[k]; if (list.Count != 0) { List<string> values = list.ConvertAll((Piece p) => (!((Object)(object)p == (Object)null)) ? p.m_name : "<null>"); <RegisterDiagCommand>g__Say|14_1(string.Format("[player table] bucket {0} ({1}) x{2}: {3}", k, (object)(PieceCategory)k, list.Count, string.Join(" | ", values)), ref <>c__DisplayClass14_); } } } <RegisterDiagCommand>g__Say|14_1("--- Drawer inventories (nearby) ---", ref <>c__DisplayClass14_); if ((Object)(object)localPlayer2 == (Object)null || (Object)(object)DrawerManager.Instance == (Object)null) { <RegisterDiagCommand>g__Say|14_1("no local player or DrawerManager -- cannot enumerate nearby drawers", ref <>c__DisplayClass14_); return; } List<DrawerComponent> list2 = new List<DrawerComponent>(); DrawerManager.Instance.QueryNear(((Component)localPlayer2).transform.position, 20f, list2); <RegisterDiagCommand>g__Say|14_1($"drawers within 20m of player: {list2.Count} (DrawerComponent.All total: {DrawerComponent.All.Count})", ref <>c__DisplayClass14_); foreach (DrawerComponent item in list2) { bool flag3 = DrawerComponent.All.Contains(item); Inventory inventory = ((Container)item).GetInventory(); string text2 = ((inventory == null) ? "GetInventory()=NULL <-- base.Awake() likely did not run for this drawer" : $"GetInventory()=non-null, {inventory.NrOfItems()} real stack(s), {inventory.GetWidth()} slot(s) total"); DrawerSnapshot snapshot = item.Snapshot; string text3 = "unknown"; string text4 = "unknown"; try { ZNetView val4 = AccessTools.FieldRefAccess<Container, ZNetView>((Container)(object)item, "m_nview"); if (