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 ItemDrawers v0.9.0
plugins/ItemDrawers.Core.dll
Decompiled 2 months 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+913107a17ca521c047e50107cd807fb5861366ab")] [assembly: AssemblyProduct("ItemDrawers.Core")] [assembly: AssemblyTitle("ItemDrawers.Core")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ItemDrawers.Core { public readonly struct IconSize { public readonly string Name; public readonly int Width; public readonly int Height; public IconSize(string name, int width, int height) { Name = name; Width = width; Height = height; } } public readonly struct AtlasRect { public readonly int X; public readonly int Y; public readonly int Width; public readonly int Height; public AtlasRect(int x, int y, int width, int height) { X = x; Y = y; Width = width; Height = height; } } public sealed class AtlasLayout { public int Width { get; } public int Height { get; } public IReadOnlyDictionary<string, AtlasRect> Rects { get; } public AtlasLayout(int width, int height, IReadOnlyDictionary<string, AtlasRect> rects) { Width = width; Height = height; Rects = rects; } public bool TryGetUv(string name, out float u0, out float v0, out float u1, out float v1) { u0 = (v0 = (u1 = (v1 = 0f))); if (name == null || !Rects.TryGetValue(name, out var value)) { return false; } u0 = (float)value.X / (float)Width; v0 = (float)value.Y / (float)Height; u1 = (float)(value.X + value.Width) / (float)Width; v1 = (float)(value.Y + value.Height) / (float)Height; return true; } } public static class ChunkSplitter { public static IReadOnlyList<int> Chunks(int amount, int stackSize) { List<int> list = new List<int>(); if (amount <= 0) { return list; } int num = ((stackSize < 1) ? 1 : stackSize); int num2 = amount; while (num2 > 0) { int num3 = ((num2 < num) ? num2 : num); list.Add(num3); num2 -= num3; } return list; } } public static class DrawerMeshBuilder { private const float UvScale = 1f; private static readonly int[] Signs = new int[2] { -1, 1 }; public static MeshData Build(DrawerProportions p) { MeshData.Builder builder = new MeshData.Builder(); float width = p.Width; float height = p.Height; float depth = p.Depth; float num = Math.Min(p.FrameThickness, Math.Min(width, height) / 2f - 0.02f); float num2 = Math.Min(p.RecessDepth, depth * 0.5f); float bevel = p.Bevel; AddChamferBox(builder, 0f, 0f, (0f - num2) / 2f, width, height, depth - num2, bevel); float cz = depth / 2f - num2 / 2f; AddChamferBox(builder, 0f, height / 2f - num / 2f, cz, width, num, num2, bevel); AddChamferBox(builder, 0f, (0f - height) / 2f + num / 2f, cz, width, num, num2, bevel); float num3 = height - 2f * num; if (num3 > 0.01f) { AddChamferBox(builder, (0f - width) / 2f + num / 2f, 0f, cz, num, num3, num2, bevel); AddChamferBox(builder, width / 2f - num / 2f, 0f, cz, num, num3, num2, bevel); } AddHandle(builder, p, num, num2); return builder.Build(); } private static void AddHandle(MeshData.Builder gb, DrawerProportions p, float frame, float recess) { float num = p.Depth / 2f - recess; float num2 = p.Height - 2f * frame; switch (p.Handle) { case HandleStyle.Bar: { float w2 = Math.Min(p.HandleWidth, p.Width - 2f * frame - 0.02f); float cy = (0f - num2) / 2f + p.HandleSection * 1.4f; AddChamferBox(gb, 0f, cy, num + p.HandleProud / 2f, w2, p.HandleSection, p.HandleProud, Math.Min(p.Bevel, p.HandleSection / 2.5f)); break; } case HandleStyle.Knobs: { float num3 = Math.Min(p.HandleWidth / 2f, p.Width / 2f - frame - p.HandleSection); for (int i = -1; i <= 1; i += 2) { AddChamferBox(gb, num3 * (float)i, 0f, num + p.HandleProud / 2f, p.HandleSection, p.HandleSection, p.HandleProud, p.HandleSection / 3f); } break; } case HandleStyle.Pull: { float w = Math.Min(p.HandleWidth, p.Width - 2f * frame); AddChamferBox(gb, 0f, (0f - p.Height) / 2f + frame + p.HandleSection / 2f, p.Depth / 2f - p.HandleProud / 2f, w, p.HandleSection, p.HandleProud, p.Bevel); break; } case HandleStyle.None: break; } } public static MeshData ChamferBox(float cx, float cy, float cz, float w, float h, float d, float chamfer) { MeshData.Builder builder = new MeshData.Builder(); AddChamferBox(builder, cx, cy, cz, w, h, d, chamfer); return builder.Build(); } private static void AddChamferBox(MeshData.Builder gb, float cx, float cy, float cz, float w, float h, float d, float chamfer) { float num = w / 2f; float num2 = h / 2f; float num3 = d / 2f; float num4 = Math.Max(0f, Math.Min(chamfer, Math.Min(num, Math.Min(num2, num3)) * 0.98f)); float[] extent = new float[3] { num, num2, num3 }; float[] inner = new float[3] { num - num4, num2 - num4, num3 - num4 }; float[] centre = new float[3] { cx, cy, cz }; int[][] array = new int[4][] { new int[2] { -1, -1 }, new int[2] { 1, -1 }, new int[2] { 1, 1 }, new int[2] { -1, 1 } }; int[] signs; for (int i = 0; i < 3; i++) { signs = Signs; foreach (int num5 in signs) { int num6 = (i + 1) % 3; int num7 = (i + 2) % 3; float[][] array2 = new float[4][]; for (int k = 0; k < 4; k++) { int[] array3 = new int[3]; array3[i] = num5; array3[num6] = array[k][0]; array3[num7] = array[k][1]; array2[k] = Point(i, array3); } float[] array4 = new float[3]; array4[i] = num5; gb.Quad(array2[0], array2[1], array2[2], array2[3], array4, 1f); } } for (int l = 0; l < 3; l++) { int num8 = (l + 1) % 3; int num9 = (l + 2) % 3; signs = Signs; foreach (int num10 in signs) { int[] signs2 = Signs; foreach (int num11 in signs2) { float[][] array5 = new float[2][]; float[][] array6 = new float[2][]; for (int n = 0; n < 2; n++) { int[] array7 = new int[3]; array7[l] = Signs[n]; array7[num8] = num10; array7[num9] = num11; array5[n] = Point(num8, array7); array6[n] = Point(num9, array7); } float[] array8 = new float[3]; array8[num8] = num10; array8[num9] = num11; gb.Quad(array5[0], array5[1], array6[1], array6[0], array8, 1f); } } } signs = Signs; foreach (int num12 in signs) { int[] signs2 = Signs; foreach (int num13 in signs2) { int[] signs3 = Signs; foreach (int num15 in signs3) { int[] s = new int[3] { num12, num13, num15 }; float[] hint = new float[3] { num12, num13, num15 }; gb.TriangleHinted(Point(0, s), Point(1, s), Point(2, s), hint, 1f); } } } float[] Point(int axis, int[] array10) { float[] array9 = new float[3]; for (int num16 = 0; num16 < 3; num16++) { array9[num16] = centre[num16] + (float)array10[num16] * ((num16 == axis) ? extent[num16] : inner[num16]); } return array9; } } } public readonly struct DrawerOutcome { public readonly bool Accepted; public readonly DrawerSnapshot Result; public readonly int MovedToDrawer; public readonly int MovedToPlayer; public readonly string Rejection; private DrawerOutcome(bool accepted, DrawerSnapshot result, int toDrawer, int toPlayer, string rejection) { Accepted = accepted; Result = result; MovedToDrawer = toDrawer; MovedToPlayer = toPlayer; Rejection = rejection; } public static DrawerOutcome Deposited(DrawerSnapshot result, int moved) { return new DrawerOutcome(accepted: true, result, moved, 0, null); } public static DrawerOutcome Withdrew(DrawerSnapshot result, int moved) { return new DrawerOutcome(accepted: true, result, 0, moved, null); } public static DrawerOutcome Changed(DrawerSnapshot result) { return new DrawerOutcome(accepted: true, result, 0, 0, null); } public static DrawerOutcome Refused(DrawerSnapshot unchanged, string why) { return new DrawerOutcome(accepted: false, unchanged, 0, 0, why); } } public enum HandleStyle { None, Bar, Knobs, Pull } public sealed class DrawerProportions { public float Width = 0.66f; public float Height = 0.66f; public float Depth = 0.66f; public float FrameThickness = 0.033f; public float RecessDepth = 0.0198f; public float Bevel = 0.00396f; public float HandleWidth = 0.264f; public float HandleSection = 0.0429f; public float HandleProud = 0.0231f; public HandleStyle Handle = HandleStyle.Bar; public float LabelScale = 0.98f; public float LabelSize { get { float num = Width - 2f * FrameThickness; float num2 = Height - 2f * FrameThickness; if (Handle == HandleStyle.Bar) { num2 -= HandleSection * 3f; } float num3 = ((num < num2) ? num : num2) * LabelScale; if (!(num3 < 0.05f)) { return num3; } return 0.05f; } } } public readonly struct DrawerSnapshot : IEquatable<DrawerSnapshot> { public readonly string ItemName; public readonly int Amount; public bool IsAssigned => !string.IsNullOrEmpty(ItemName); public bool IsEmpty => Amount <= 0; public DrawerSnapshot(string itemName, int amount) { ItemName = itemName ?? ""; Amount = ((amount >= 0) ? amount : 0); } public bool Equals(DrawerSnapshot other) { if (string.Equals(ItemName, other.ItemName, StringComparison.Ordinal)) { return Amount == other.Amount; } return false; } public override bool Equals(object obj) { if (obj is DrawerSnapshot other) { return Equals(other); } return false; } public override int GetHashCode() { return ((ItemName?.GetHashCode() ?? 0) * 397) ^ Amount; } public override string ToString() { if (!IsAssigned) { return "(empty drawer)"; } return $"{ItemName} x{Amount}"; } } public static class DrawerState { public const string WrongItem = "This drawer holds a different item"; public const string DrawerFull = "This drawer is full"; public const string DrawerEmpty = "This drawer has been drained"; public const string NotAssigned = "This drawer has not been assigned"; public const string BadCapacity = "This drawer has an invalid capacity"; public const string NotEmptyYet = "Empty the drawer before clearing it"; public const string NothingOffered = "Nothing to deposit"; public static DrawerOutcome Deposit(DrawerSnapshot current, int capacity, string itemName, int offered) { if (offered <= 0) { return DrawerOutcome.Refused(current, "Nothing to deposit"); } if (string.IsNullOrEmpty(itemName)) { return DrawerOutcome.Refused(current, "Nothing to deposit"); } if (capacity <= 0) { return DrawerOutcome.Refused(current, "This drawer has an invalid capacity"); } if (current.IsAssigned && current.ItemName != itemName) { return DrawerOutcome.Refused(current, "This drawer holds a different item"); } int num = capacity - current.Amount; if (num <= 0) { return DrawerOutcome.Refused(current, "This drawer is full"); } int num2 = ((offered < num) ? offered : num); return DrawerOutcome.Deposited(new DrawerSnapshot(itemName, current.Amount + num2), num2); } public static DrawerOutcome WithdrawStack(DrawerSnapshot current, int maxStackSize) { if (!current.IsAssigned) { return DrawerOutcome.Refused(current, "This drawer has not been assigned"); } if (current.IsEmpty) { return DrawerOutcome.Refused(current, "This drawer has been drained"); } int num = ((maxStackSize < 1) ? 1 : maxStackSize); int num2 = ((current.Amount < num) ? current.Amount : num); return DrawerOutcome.Withdrew(new DrawerSnapshot(current.ItemName, current.Amount - num2), num2); } public static DrawerOutcome WithdrawOne(DrawerSnapshot current) { if (!current.IsAssigned) { return DrawerOutcome.Refused(current, "This drawer has not been assigned"); } if (current.IsEmpty) { return DrawerOutcome.Refused(current, "This drawer has been drained"); } return DrawerOutcome.Withdrew(new DrawerSnapshot(current.ItemName, current.Amount - 1), 1); } public static DrawerOutcome WithdrawExact(DrawerSnapshot current, int requested) { if (requested <= 0 || !current.IsAssigned || current.IsEmpty) { return DrawerOutcome.Withdrew(current, 0); } int num = ((requested < current.Amount) ? requested : current.Amount); return DrawerOutcome.Withdrew(new DrawerSnapshot(current.ItemName, current.Amount - num), num); } public static DrawerOutcome Clear(DrawerSnapshot current) { if (!current.IsEmpty) { return DrawerOutcome.Refused(current, "Empty the drawer before clearing it"); } return DrawerOutcome.Changed(new DrawerSnapshot("", 0)); } public static int RefundShortfall(int removed, int accepted) { int num = removed - accepted; if (num <= 0) { return 0; } return num; } } public static class DrawerTextureGenerator { private readonly struct Knot { public readonly float X; public readonly float Y; public readonly float Radius; public readonly float Strength; public Knot(float x, float y, float radius, float strength) { X = x; Y = y; Radius = radius; Strength = strength; } } public static TextureData Generate(TextureTier tier, int width, int height, int seed) { if (width < 2 || height < 2) { throw new ArgumentException($"Texture must be at least 2x2, got {width}x{height}."); } float[] heights = BuildHeightField(tier, width, height, seed); byte[] albedo = BuildAlbedo(tier, heights, width, height); byte[] normal = BuildNormal(heights, width, height, NormalStrength(tier)); return new TextureData(width, height, albedo, normal); } private static float[] BuildHeightField(TextureTier tier, int width, int height, int seed) { return tier switch { TextureTier.Wood => BuildWoodHeight(width, height, seed), TextureTier.Stone => BuildStoneHeight(width, height, seed), TextureTier.BlackMarble => BuildMarbleHeight(width, height, seed), _ => BuildWoodHeight(width, height, seed), }; } private static float[] BuildWoodHeight(int width, int height, int seed) { float[] array = new float[width * height]; Knot[] knots = MakeKnots(seed, width, height, 3, 6f, 14f); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { float num = PeriodicNoise.Fbm(j, i, width, height, seed + 11, 2, 7, 2f, 0.6f) * 1.3f; float num2 = (float)i * 7f / (float)height + num; float num3 = num2 - (float)Math.Floor(num2); float num4 = Math.Min(num3, 1f - num3); float num5 = 1f - Clamp01(num4 / 0.08f); float num6 = PeriodicNoise.Fbm(j, i, width, height, seed + 23, 4, 48, 2.1f, 0.55f); float num7 = PeriodicNoise.Fbm(j, i, width, height, seed + 37, 3, 5); float num8 = KnotContribution(knots, j, i, width, height); float v = 0.55f + num7 * 0.08f + num6 * 0.018f - num5 * 0.14f + num8; array[i * width + j] = Clamp01(v); } } return array; } private static float[] BuildStoneHeight(int width, int height, int seed) { float[] array = new float[width * height]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { float num = PeriodicNoise.Fbm(j, i, width, height, seed + 5, 3, 6); float num2 = PeriodicNoise.Fbm(j, i, width, height, seed + 61, 3, 34); float v = 0.5f + num * 0.15f + num2 * 0.045f; array[i * width + j] = Clamp01(v); } } return array; } private static float[] BuildMarbleHeight(int width, int height, int seed) { float[] array = new float[width * height]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { float value = PeriodicNoise.Fbm(j, i, width, height, seed + 7, 3, 5, 2.3f); float num = (float)Math.Pow(Clamp01((1f - Math.Abs(value) - 0.82f) / 0.18f), 2.0); float num2 = PeriodicNoise.Fbm(j, i, width, height, seed + 89, 2, 40); float v = 0.16f + num * 0.22f + num2 * 0.02f; array[i * width + j] = Clamp01(v); } } return array; } private static Knot[] MakeKnots(int seed, int width, int height, int count, float minRadius, float maxRadius) { Random random = new Random(seed + 999); Knot[] array = new Knot[count]; float num = (float)width / 2f; float num2 = (float)height / 2f; float num3 = (float)width * 0.22f; float num4 = (float)height * 0.22f; for (int i = 0; i < count; i++) { float num5 = 0f; float num6 = 0f; for (int j = 0; j < 20; j++) { num5 = (float)(random.NextDouble() * (double)width); num6 = (float)(random.NextDouble() * (double)height); if (!(Math.Abs(num5 - num) < num3) || !(Math.Abs(num6 - num2) < num4)) { break; } } float radius = minRadius + (float)random.NextDouble() * (maxRadius - minRadius); float strength = 0.03f + (float)random.NextDouble() * 0.03f; array[i] = new Knot(num5, num6, radius, strength); } return array; } private static float KnotContribution(Knot[] knots, int x, int y, int width, int height) { float num = 0f; for (int i = 0; i < knots.Length; i++) { Knot knot = knots[i]; float num2 = PeriodicNoise.ToroidalDistance(x, y, knot.X, knot.Y, width, height); if (!(num2 >= knot.Radius)) { float num3 = num2 / knot.Radius; float num4 = (float)Math.Pow(1f - num3, 2.0); num -= knot.Strength * num4; } } return num; } private static (float r, float g, float b) HueRatio(TextureTier tier) { return tier switch { TextureTier.Wood => (r: 1f, g: 0.84f, b: 0.66f), TextureTier.Stone => (r: 0.97f, g: 0.98f, b: 1f), TextureTier.BlackMarble => (r: 0.86f, g: 0.95f, b: 1f), _ => (r: 1f, g: 0.8f, b: 0.56f), }; } public static float MidLightness(TextureTier tier) { var (num, num2) = LightnessRange(tier); return (num + num2) / 2f; } private static (float min, float max) LightnessRange(TextureTier tier) { return tier switch { TextureTier.Wood => (min: 0.24f, max: 0.6f), TextureTier.Stone => (min: 0.34f, max: 0.64f), TextureTier.BlackMarble => (min: 0.04f, max: 0.3f), _ => (min: 0.28f, max: 0.66f), }; } private static byte[] BuildAlbedo(TextureTier tier, float[] heights, int width, int height) { (float r, float g, float b) tuple = HueRatio(tier); float item = tuple.r; float item2 = tuple.g; float item3 = tuple.b; (float min, float max) tuple2 = LightnessRange(tier); float item4 = tuple2.min; float item5 = tuple2.max; byte[] array = new byte[width * height * 4]; for (int i = 0; i < heights.Length; i++) { float num = item4 + heights[i] * (item5 - item4); int num2 = i * 4; array[num2] = ToByte(num * item); array[num2 + 1] = ToByte(num * item2); array[num2 + 2] = ToByte(num * item3); array[num2 + 3] = byte.MaxValue; } return array; } private static float NormalStrength(TextureTier tier) { return tier switch { TextureTier.Wood => 3f, TextureTier.Stone => 1.6f, TextureTier.BlackMarble => 1.1f, _ => 2f, }; } private static byte[] BuildNormal(float[] heights, int width, int height, float strength) { byte[] array = new byte[width * height * 4]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { float num = At(heights, j - 1, i - 1, width, height); float num2 = At(heights, j, i - 1, width, height); float num3 = At(heights, j + 1, i - 1, width, height); float num4 = At(heights, j - 1, i, width, height); float num5 = At(heights, j + 1, i, width, height); float num6 = At(heights, j - 1, i + 1, width, height); float num7 = At(heights, j, i + 1, width, height); float num8 = At(heights, j + 1, i + 1, width, height); float num9 = num3 + 2f * num5 + num8 - (num + 2f * num4 + num6); float num10 = num6 + 2f * num7 + num8 - (num + 2f * num2 + num3); float num11 = (0f - num9) * strength; float num12 = (0f - num10) * strength; float num13 = 1f; float num14 = (float)Math.Sqrt(num11 * num11 + num12 * num12 + num13 * num13); num11 /= num14; num12 /= num14; num13 /= num14; int num15 = (i * width + j) * 4; array[num15] = ToByte(num11 * 0.5f + 0.5f); array[num15 + 1] = ToByte(num12 * 0.5f + 0.5f); array[num15 + 2] = ToByte(num13 * 0.5f + 0.5f); array[num15 + 3] = byte.MaxValue; } } return array; } private static float At(float[] field, int x, int y, int width, int height) { int num = (x % width + width) % width; int num2 = (y % height + height) % height; return field[num2 * width + num]; } private static float Clamp01(float v) { if (!(v < 0f)) { if (!(v > 1f)) { return v; } return 1f; } return 0f; } private static byte ToByte(float v) { v = Clamp01(v); return (byte)Math.Round(v * 255f); } } public sealed class HandledRequestCache<T> { private readonly struct Entry { public readonly T Result; public readonly float RecordedAt; public Entry(T result, float recordedAt) { Result = result; RecordedAt = recordedAt; } } private readonly Dictionary<(long Sender, long Id), Entry> _entries = new Dictionary<(long, long), Entry>(); private readonly float _lifetimeSeconds; public int Count => _entries.Count; public HandledRequestCache(float lifetimeSeconds) { _lifetimeSeconds = lifetimeSeconds; } public bool TryGet(long sender, long id, out T result) { if (_entries.TryGetValue((sender, id), out var value)) { result = value.Result; return true; } result = default(T); return false; } public void Record(long sender, long id, T result, float now) { _entries[(sender, id)] = new Entry(result, now); } public void Prune(float now) { if (_entries.Count == 0) { return; } List<(long, long)> list = null; foreach (KeyValuePair<(long, long), Entry> entry in _entries) { if (now - entry.Value.RecordedAt > _lifetimeSeconds) { (list ?? (list = new List<(long, long)>())).Add(entry.Key); } } if (list == null) { return; } foreach (var item in list) { _entries.Remove(item); } } } public static class IconAtlasPacker { private const int Padding = 2; public static AtlasLayout Pack(IReadOnlyList<IconSize> icons, int maxDimension = 4096) { if (icons == null) { throw new ArgumentNullException("icons"); } if (icons.Count == 0) { return new AtlasLayout(1, 1, new Dictionary<string, AtlasRect>()); } int num = maxDimension - 2; foreach (IconSize icon in icons) { if (icon.Width <= 0 || icon.Height <= 0) { throw new ArgumentException($"Icon '{icon.Name}' has invalid dimensions {icon.Width}×{icon.Height}. " + "Icon width and height must be positive."); } if (icon.Width > num || icon.Height > num) { throw new ArgumentException($"Icon '{icon.Name}' has dimensions {icon.Width}×{icon.Height}, " + $"but maximum icon size for maxDimension={maxDimension} is {num}×{num} " + $"(atlas dimension - {2} pixel padding)."); } } List<IconSize> sorted = icons.OrderByDescending((IconSize i) => i.Height).ToList(); for (int num2 = 64; num2 <= maxDimension; num2 *= 2) { if (TryPackInto(sorted, num2, out var rects)) { return new AtlasLayout(num2, num2, rects); } } throw new InvalidOperationException($"Cannot fit {icons.Count} icons into a {maxDimension}×{maxDimension} atlas."); } private static bool TryPackInto(List<IconSize> sorted, int size, out Dictionary<string, AtlasRect> rects) { rects = new Dictionary<string, AtlasRect>(sorted.Count); int num = 0; int num2 = 0; int num3 = 0; foreach (IconSize item in sorted) { int num4 = item.Width + 2; int num5 = item.Height + 2; if (num4 > size || num5 > size) { return false; } if (num3 + num4 > size) { num += num2; num2 = 0; num3 = 0; } if (num + num5 > size) { return false; } rects[item.Name] = new AtlasRect(num3, num, item.Width, item.Height); num3 += num4; if (num5 > num2) { num2 = num5; } } return true; } } public sealed class MeshData { internal sealed class Builder { private readonly List<float> _pos = new List<float>(4096); private readonly List<float> _nor = new List<float>(4096); private readonly List<float> _uv = new List<float>(2731); public void Triangle(float[] a, float[] b, float[] c, float uvScale) { float num = b[0] - a[0]; float num2 = b[1] - a[1]; float num3 = b[2] - a[2]; float num4 = c[0] - a[0]; float num5 = c[1] - a[1]; float num6 = c[2] - a[2]; float num7 = num2 * num6 - num3 * num5; float num8 = num3 * num4 - num * num6; float num9 = num * num5 - num2 * num4; float num10 = (float)Math.Sqrt(num7 * num7 + num8 * num8 + num9 * num9); if (!(num10 < 1E-09f)) { num7 /= num10; num8 /= num10; num9 /= num10; float num11 = Math.Abs(num7); float num12 = Math.Abs(num8); float num13 = Math.Abs(num9); int num14; int num15; if (num11 >= num12 && num11 >= num13) { num14 = 2; num15 = 1; } else if (num12 >= num13) { num14 = 0; num15 = 2; } else { num14 = 0; num15 = 1; } float[][] array = new float[3][] { a, b, c }; foreach (float[] array2 in array) { _pos.Add(array2[0]); _pos.Add(array2[1]); _pos.Add(array2[2]); _nor.Add(num7); _nor.Add(num8); _nor.Add(num9); _uv.Add(array2[num14] * uvScale); _uv.Add(array2[num15] * uvScale); } } } public void Quad(float[] a, float[] b, float[] c, float[] d, float[] hint, float uvScale) { float num = b[0] - a[0]; float num2 = b[1] - a[1]; float num3 = b[2] - a[2]; float num4 = c[0] - a[0]; float num5 = c[1] - a[1]; float num6 = c[2] - a[2]; float num7 = num2 * num6 - num3 * num5; float num8 = num3 * num4 - num * num6; float num9 = num * num5 - num2 * num4; if (num7 * hint[0] + num8 * hint[1] + num9 * hint[2] < 0f) { float[] array = b; b = d; d = array; } Triangle(a, b, c, uvScale); Triangle(a, c, d, uvScale); } public void TriangleHinted(float[] a, float[] b, float[] c, float[] hint, float uvScale) { float num = b[0] - a[0]; float num2 = b[1] - a[1]; float num3 = b[2] - a[2]; float num4 = c[0] - a[0]; float num5 = c[1] - a[1]; float num6 = c[2] - a[2]; float num7 = num2 * num6 - num3 * num5; float num8 = num3 * num4 - num * num6; float num9 = num * num5 - num2 * num4; if (num7 * hint[0] + num8 * hint[1] + num9 * hint[2] < 0f) { float[] array = b; b = c; c = array; } Triangle(a, b, c, uvScale); } public MeshData Build() { return new MeshData(_pos.ToArray(), _nor.ToArray(), _uv.ToArray()); } } public float[] Vertices { get; } public float[] Normals { get; } public float[] Uvs { get; } public int VertexCount => Vertices.Length / 3; public int TriangleCount => VertexCount / 3; public MeshData(float[] vertices, float[] normals, float[] uvs) { Vertices = vertices; Normals = normals; Uvs = uvs; } } public readonly struct MirrorDelta : IEquatable<MirrorDelta> { public readonly int Withdraw; public static readonly MirrorDelta None = new MirrorDelta(0); private MirrorDelta(int withdraw) { Withdraw = withdraw; } public static MirrorDelta WithdrawOf(int amount) { return new MirrorDelta(amount); } public bool Equals(MirrorDelta other) { return Withdraw == other.Withdraw; } public override bool Equals(object obj) { if (obj is MirrorDelta other) { return Equals(other); } return false; } public override int GetHashCode() { return Withdraw; } public override string ToString() { if (Withdraw <= 0) { return "None"; } return $"Withdraw({Withdraw})"; } } public static class MirrorReconciliation { public static MirrorDelta Compute(string mirrorItemName, int mirrorTotal, string mirroredBaselineItemName, int mirroredBaselineAmount, string zdoItemName, int zdoAmount) { if (mirrorItemName != mirroredBaselineItemName) { return MirrorDelta.None; } if (mirroredBaselineItemName != zdoItemName) { return MirrorDelta.None; } int num = mirrorTotal - mirroredBaselineAmount; if (num >= 0) { return MirrorDelta.None; } int num2 = -num; int num3 = ((num2 < zdoAmount) ? num2 : zdoAmount); if (num3 > 0) { return MirrorDelta.WithdrawOf(num3); } return MirrorDelta.None; } } public sealed class PendingRequest<T> { public readonly long Id; public readonly T Payload; public int Attempts; public float Deadline; public PendingRequest(long id, T payload, int attempts, float deadline) { Id = id; Payload = payload; Attempts = attempts; Deadline = deadline; } } public sealed class PendingRequestLedger<T> { private readonly Dictionary<long, PendingRequest<T>> _pending = new Dictionary<long, PendingRequest<T>>(); private readonly float _timeoutSeconds; private readonly int _maxAttempts; public int Count => _pending.Count; public PendingRequestLedger(float timeoutSeconds, int maxAttempts) { _timeoutSeconds = timeoutSeconds; _maxAttempts = maxAttempts; } public void Add(long id, T payload, float now) { _pending[id] = new PendingRequest<T>(id, payload, 1, now + _timeoutSeconds); } public bool TryComplete(long id, out T payload) { if (_pending.TryGetValue(id, out var value)) { payload = value.Payload; _pending.Remove(id); return true; } payload = default(T); return false; } public bool Remove(long id, out T payload) { if (_pending.TryGetValue(id, out var value)) { payload = value.Payload; _pending.Remove(id); return true; } payload = default(T); return false; } public IEnumerable<KeyValuePair<long, T>> All() { foreach (KeyValuePair<long, PendingRequest<T>> item in _pending) { yield return new KeyValuePair<long, T>(item.Key, item.Value.Payload); } } public void Tick(float now, Action<long, T> retry, Action<long, T> giveUp) { List<long> list = null; foreach (KeyValuePair<long, PendingRequest<T>> item in _pending) { if (!(now < item.Value.Deadline)) { (list ?? (list = new List<long>())).Add(item.Key); } } if (list == null) { return; } foreach (long item2 in list) { PendingRequest<T> pendingRequest = _pending[item2]; if (pendingRequest.Attempts >= _maxAttempts) { _pending.Remove(item2); giveUp(item2, pendingRequest.Payload); } else { pendingRequest.Attempts++; pendingRequest.Deadline = now + _timeoutSeconds; retry(item2, pendingRequest.Payload); } } } } public static class PeriodicNoise { public static float Sample(float x, float y, int cells, int seed) { if (cells < 1) { cells = 1; } float num = (float)Math.Floor(x); float num2 = (float)Math.Floor(y); int num3 = Mod((int)num, cells); int num4 = Mod((int)num2, cells); int x2 = Mod(num3 + 1, cells); int y2 = Mod(num4 + 1, cells); float t = x - num; float t2 = y - num2; float t3 = Fade(t); float t4 = Fade(t2); float a = HashValue(num3, num4, seed); float b = HashValue(x2, num4, seed); float a2 = HashValue(num3, y2, seed); float b2 = HashValue(x2, y2, seed); float a3 = Lerp(a, b, t3); float b3 = Lerp(a2, b2, t3); return Lerp(a3, b3, t4); } public static float Fbm(float px, float py, int width, int height, int seed, int octaves, int baseCells, float lacunarity = 2f, float gain = 0.5f) { float num = 0f; float num2 = 1f; float num3 = 0f; int num4 = Math.Max(1, baseCells); for (int i = 0; i < octaves; i++) { float x = px * (float)num4 / (float)width; float y = py * (float)num4 / (float)height; num += Sample(x, y, num4, seed + i * 101) * num2; num3 += num2; num2 *= gain; num4 = Math.Max(1, (int)Math.Round((float)num4 * lacunarity)); } if (!(num3 > 0f)) { return 0f; } return num / num3; } public static float ToroidalDistance(float ax, float ay, float bx, float by, int width, int height) { float num = WrapDelta(ax - bx, width); float num2 = WrapDelta(ay - by, height); return (float)Math.Sqrt(num * num + num2 * num2); } private static float WrapDelta(float d, int period) { d %= (float)period; if (d > (float)period / 2f) { d -= (float)period; } if (d < (float)(-period) / 2f) { d += (float)period; } return d; } private static int Mod(int a, int m) { int num = a % m; if (num >= 0) { return num; } return num + m; } private static float Fade(float t) { return t * t * t * (t * (t * 6f - 15f) + 10f); } private static float Lerp(float a, float b, float t) { return a + t * (b - a); } private static float HashValue(int x, int y, int seed) { int num = x * 374761393 + y * 668265263 + seed * 1274126177; int num2 = (num ^ (num >>> 13)) * 1274126177; return (float)(uint)(num2 ^ (num2 >>> 16)) / 4.2949673E+09f * 2f - 1f; } } public sealed class RequestIdGenerator { private long _next; public RequestIdGenerator(long seed) { _next = seed; } public long Next() { return ++_next; } } public sealed class SpatialGrid<T> { private readonly struct Cell : IEquatable<Cell> { public readonly int X; public readonly int Y; public readonly int Z; public Cell(int x, int y, int z) { X = x; Y = y; Z = z; } public bool Equals(Cell o) { if (X == o.X && Y == o.Y) { return Z == o.Z; } return false; } public override bool Equals(object o) { if (o is Cell o2) { return Equals(o2); } return false; } public override int GetHashCode() { return (X * 73856093) ^ (Y * 19349663) ^ (Z * 83492791); } } private readonly float _cellSize; private readonly Dictionary<Cell, List<T>> _cells = new Dictionary<Cell, List<T>>(); private readonly Dictionary<T, (Cell cell, float x, float y, float z)> _index = new Dictionary<T, (Cell, float, float, float)>(); public int Count => _index.Count; public SpatialGrid(float cellSize) { if (cellSize <= 0f) { throw new ArgumentOutOfRangeException("cellSize"); } _cellSize = cellSize; } private Cell CellOf(float x, float y, float z) { return new Cell((int)Math.Floor(x / _cellSize), (int)Math.Floor(y / _cellSize), (int)Math.Floor(z / _cellSize)); } public void Insert(T item, float x, float y, float z) { if (_index.ContainsKey(item)) { Move(item, x, y, z); return; } Cell cell = CellOf(x, y, z); if (!_cells.TryGetValue(cell, out var value)) { value = new List<T>(4); _cells[cell] = value; } value.Add(item); _index[item] = (cell, x, y, z); } public bool Remove(T item) { if (!_index.TryGetValue(item, out (Cell, float, float, float) value)) { return false; } if (_cells.TryGetValue(value.Item1, out var value2)) { value2.Remove(item); if (value2.Count == 0) { _cells.Remove(value.Item1); } } _index.Remove(item); return true; } public void Move(T item, float x, float y, float z) { Remove(item); Insert(item, x, y, z); } public void Query(float x, float y, float z, float radius, List<T> results) { if (results == null) { throw new ArgumentNullException("results"); } if (radius <= 0f) { return; } int num = (int)Math.Ceiling(radius / _cellSize); Cell cell = CellOf(x, y, z); float num2 = radius * radius; for (int i = -num; i <= num; i++) { for (int j = -num; j <= num; j++) { for (int k = -num; k <= num; k++) { Cell key = new Cell(cell.X + i, cell.Y + j, cell.Z + k); if (!_cells.TryGetValue(key, out var value)) { continue; } for (int l = 0; l < value.Count; l++) { T val = value[l]; (Cell cell, float x, float y, float z) tuple = _index[val]; float num3 = tuple.x - x; float num4 = tuple.y - y; float num5 = tuple.z - z; if (num3 * num3 + num4 * num4 + num5 * num5 <= num2) { results.Add(val); } } } } } } } public sealed class TextureData { public int Width { get; } public int Height { get; } public byte[] Albedo { get; } public byte[] Normal { get; } public TextureData(int width, int height, byte[] albedo, byte[] normal) { Width = width; Height = height; Albedo = albedo; Normal = normal; } } public enum TextureTier { Wood, Stone, BlackMarble } }
plugins/ItemDrawers.dll
Decompiled 2 months ago
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.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ItemDrawers")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+913107a17ca521c047e50107cd807fb5861366ab")] [assembly: AssemblyProduct("ItemDrawers")] [assembly: AssemblyTitle("ItemDrawers")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ItemDrawers.Game { internal static class ContainerBridge { [HarmonyPatch(typeof(Container), "Awake")] private static class AwakePatch { private static bool Prepare() { return ValheimCompat.RequireMethod(typeof(Container), "Awake"); } private static bool Prefix(Container __instance) { return !(__instance is DrawerComponent); } } [HarmonyPatch(typeof(Container), "GetInventory")] private static class GetInventoryPatch { private static bool Prepare() { return ValheimCompat.RequireMethod(typeof(Container), "GetInventory"); } private static void Prefix(Container __instance) { if (__instance is DrawerComponent drawerComponent) { drawerComponent.RefreshMirror(); } } private static void Postfix(Container __instance, ref Inventory __result) { if (__instance is DrawerComponent drawerComponent) { __result = drawerComponent.MirrorInventory; } } } [HarmonyPatch(typeof(Container), "Save")] private static class SavePatch { private static bool Prepare() { return ValheimCompat.RequireMethod(typeof(Container), "Save"); } private static bool Prefix(Container __instance) { return !(__instance is DrawerComponent); } } [HarmonyPatch(typeof(Container), "Load")] private static class LoadPatch { private static bool Prepare() { return ValheimCompat.RequireMethod(typeof(Container), "Load"); } private static bool Prefix(Container __instance) { return !(__instance is DrawerComponent); } } } internal static class DebugCommands { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__2_0; public static ConsoleEvent <>9__2_1; internal void <Register>b__2_0(ConsoleEventArgs args) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } int num = ((args.Length > 1) ? int.Parse(args[1]) : 10); int num2 = ((args.Length > 2) ? int.Parse(args[2]) : 10); DrawerTier drawerTier = DrawerTier.Wood; if (args.Length > 3) { if (args[3].Equals("stone", StringComparison.OrdinalIgnoreCase)) { drawerTier = DrawerTier.Stone; } else if (args[3].StartsWith("black", StringComparison.OrdinalIgnoreCase)) { drawerTier = DrawerTier.BlackMarble; } } GameObject prefab = ZNetScene.instance.GetPrefab(DrawerTiers.PrefabName(drawerTier)); if ((Object)(object)prefab == (Object)null) { args.Context.AddString("Drawer prefab not found"); return; } Transform transform = ((Component)Player.m_localPlayer).transform; Vector3 val = transform.position + transform.forward * 6f; Vector3 right = transform.right; int num3 = 0; DrawerProportions val2 = new DrawerProportions(); float num4 = val2.Width + 0.02f; float num5 = val2.Height + 0.02f; for (int i = 0; i < num2; i++) { for (int j = 0; j < num; j++) { Vector3 val3 = val + right * (((float)j - (float)(num - 1) / 2f) * num4) + Vector3.up * ((float)i * num5 + val2.Height / 2f); DrawerComponent component = Object.Instantiate<GameObject>(prefab, val3, Quaternion.LookRotation(-transform.forward, Vector3.up)).GetComponent<DrawerComponent>(); if ((Object)(object)component != (Object)null) { string itemName = SampleItems[(j + i * num) % SampleItems.Length]; component.TryDepositExternally(itemName, 250 + (j * 7 + i * 13) % 500, out var _); } num3++; } } args.Context.AddString($"Built {num3} drawers ({num}x{num2}, {drawerTier})"); } internal void <Register>b__2_1(ConsoleEventArgs args) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) int count = DrawerComponent.All.Count; int num = 0; int num2 = 0; foreach (DrawerComponent item in DrawerComponent.All) { DrawerSnapshot snapshot = item.Snapshot; if (((DrawerSnapshot)(ref snapshot)).IsAssigned) { num++; } num2 += snapshot.Amount; } args.Context.AddString($"drawers loaded : {count}"); args.Context.AddString($"assigned : {num}"); args.Context.AddString($"items held : {num2}"); args.Context.AddString($"atlas built : {DrawerIconAtlas.IsBuilt}"); } } private static readonly string[] SampleItems = new string[6] { "Wood", "Stone", "Coal", "Iron", "Resin", "Flint" }; private const float WallGap = 0.02f; public static void Register() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown object obj = <>c.<>9__2_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Player.m_localPlayer == (Object)null)) { int num = ((args.Length > 1) ? int.Parse(args[1]) : 10); int num2 = ((args.Length > 2) ? int.Parse(args[2]) : 10); DrawerTier drawerTier = DrawerTier.Wood; if (args.Length > 3) { if (args[3].Equals("stone", StringComparison.OrdinalIgnoreCase)) { drawerTier = DrawerTier.Stone; } else if (args[3].StartsWith("black", StringComparison.OrdinalIgnoreCase)) { drawerTier = DrawerTier.BlackMarble; } } GameObject prefab = ZNetScene.instance.GetPrefab(DrawerTiers.PrefabName(drawerTier)); if ((Object)(object)prefab == (Object)null) { args.Context.AddString("Drawer prefab not found"); } else { Transform transform = ((Component)Player.m_localPlayer).transform; Vector3 val3 = transform.position + transform.forward * 6f; Vector3 right = transform.right; int num3 = 0; DrawerProportions val4 = new DrawerProportions(); float num4 = val4.Width + 0.02f; float num5 = val4.Height + 0.02f; for (int i = 0; i < num2; i++) { for (int j = 0; j < num; j++) { Vector3 val5 = val3 + right * (((float)j - (float)(num - 1) / 2f) * num4) + Vector3.up * ((float)i * num5 + val4.Height / 2f); DrawerComponent component = Object.Instantiate<GameObject>(prefab, val5, Quaternion.LookRotation(-transform.forward, Vector3.up)).GetComponent<DrawerComponent>(); if ((Object)(object)component != (Object)null) { string itemName = SampleItems[(j + i * num) % SampleItems.Length]; component.TryDepositExternally(itemName, 250 + (j * 7 + i * 13) % 500, out var _); } num3++; } } args.Context.AddString($"Built {num3} drawers ({num}x{num2}, {drawerTier})"); } } }; <>c.<>9__2_0 = val; obj = (object)val; } new ConsoleCommand("rid_wall", "rid_wall <cols> <rows> [wood|stone|blackmarble] - build a test wall of drawers", (ConsoleEvent)obj, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj2 = <>c.<>9__2_1; if (obj2 == null) { ConsoleEvent val2 = delegate(ConsoleEventArgs args) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) int count = DrawerComponent.All.Count; int num = 0; int num2 = 0; foreach (DrawerComponent item in DrawerComponent.All) { DrawerSnapshot snapshot = item.Snapshot; if (((DrawerSnapshot)(ref snapshot)).IsAssigned) { num++; } num2 += snapshot.Amount; } args.Context.AddString($"drawers loaded : {count}"); args.Context.AddString($"assigned : {num}"); args.Context.AddString($"items held : {num2}"); args.Context.AddString($"atlas built : {DrawerIconAtlas.IsBuilt}"); }; <>c.<>9__2_1 = val2; obj2 = (object)val2; } new ConsoleCommand("rid_stats", "rid_stats - report drawer counts and rendering cost", (ConsoleEvent)obj2, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } } public class DrawerComponent : Container, Interactable, Hoverable { public static readonly List<DrawerComponent> All = new List<DrawerComponent>(); private const string KeyPrefab = "Prefab"; private const string KeyAmount = "Amount"; private static readonly int KeyPrefabHash = StringExtensionMethods.GetStableHashCode("Prefab"); private static readonly int KeyAmountHash = StringExtensionMethods.GetStableHashCode("Amount"); private static readonly int CreatorHash = StringExtensionMethods.GetStableHashCode("creator"); internal const string CommitFailedMessage = "Try again"; internal const string RpcReqWithdraw = "RID_ReqWithdraw"; internal const string RpcGrantWithdraw = "RID_GrantWithdraw"; internal const string RpcReqDeposit = "RID_ReqDeposit"; internal const string RpcGrantDeposit = "RID_GrantDeposit"; private const string RpcReqClear = "RID_ReqClear"; internal const float RequestTimeoutSeconds = 5f; internal const int MaxRequestAttempts = 3; private const float HandledRequestLifetimeSeconds = 60f; private readonly HandledRequestCache<(string ItemName, int Amount)> _handledWithdrawals = new HandledRequestCache<(string, int)>(60f); private readonly HandledRequestCache<int> _handledDeposits = new HandledRequestCache<int>(60f); private ZNetView _view; private ZDOID _zdoId = ZDOID.None; private Inventory _mirror; private DrawerSnapshot _mirrored = new DrawerSnapshot("", 0); private bool _applyingMirror; private bool _mirrorNeedsRebuild; internal ZDOID ZdoId => _zdoId; internal DrawerTier Tier { get; private set; } public DrawerRenderer Face { get; private set; } public DrawerSnapshot Snapshot { get { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_view != (Object)null) || !_view.IsValid()) { return new DrawerSnapshot("", 0); } return new DrawerSnapshot(_view.GetZDO().GetString(KeyPrefabHash, ""), _view.GetZDO().GetInt(KeyAmountHash, 0)); } } public int Capacity => DrawerConfig.CapacityFor(Tier); internal DrawerSnapshot MirroredBaseline => _mirrored; internal string DiagId { get { //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_view != (Object)null) || !_view.IsValid()) { return ((Object)((Component)this).gameObject).name + "#(no ZDO)"; } return $"{((Object)((Component)this).gameObject).name}#{_view.GetZDO().m_uid}"; } } internal Inventory MirrorInventory { get { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown if (_mirror == null) { _mirror = new Inventory("drawer", (Sprite)null, 1, 1); Inventory mirror = _mirror; mirror.m_onChanged = (Action)Delegate.Combine(mirror.m_onChanged, new Action(OnMirrorChanged)); } return _mirror; } } private void Awake() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) _view = ((Component)this).GetComponent<ZNetView>(); Face = ((Component)this).GetComponentInChildren<DrawerRenderer>(); if (!((Object)(object)_view == (Object)null) && _view.IsValid()) { _zdoId = _view.GetZDO().m_uid; Tier = TierFromPrefabName(((Object)((Component)this).gameObject).name); try { AccessTools.FieldRefAccess<Container, ZNetView>((Container)(object)this, "m_nview") = _view; } catch (Exception ex) { DrawerPlugin.Log.LogError((object)("Could not set Container.m_nview; this drawer stays inert. See the compatibility check at startup. " + ex.GetType().Name + ": " + ex.Message)); return; } ((Container)this).Awake(); EnsureCreator(); WearNTear component = ((Component)this).GetComponent<WearNTear>(); if ((Object)(object)component != (Object)null) { component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDrawerDestroyed)); } _view.Register<long, int>("RID_ReqWithdraw", (Action<long, long, int>)RPC_RequestWithdraw); _view.Register<long, string, int>("RID_GrantWithdraw", (Action<long, long, string, int>)RPC_GrantWithdraw); _view.Register<long, string, int>("RID_ReqDeposit", (Action<long, long, string, int>)RPC_RequestDeposit); _view.Register<long, int>("RID_GrantDeposit", (Action<long, long, int>)RPC_GrantDeposit); _view.Register("RID_ReqClear", (Action<long>)RPC_RequestClear); All.Add(this); DrawerManager.Instance?.Register(this); } } private void EnsureCreator() { if ((Object)(object)_view == (Object)null || !_view.IsValid()) { return; } ZDO zDO = _view.GetZDO(); if (_view.IsOwner() && zDO.GetLong(CreatorHash, 0L) == 0L) { PlayerProfile val = (((Object)(object)Game.instance != (Object)null) ? Game.instance.GetPlayerProfile() : null); if (val != null) { zDO.Set(CreatorHash, val.GetPlayerID()); } } } private void OnDestroy() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) All.Remove(this); DrawerManager.Instance?.Unregister(this); if (!((ZDOID)(ref _zdoId)).IsNone()) { DrawerManager.Instance?.ResolvePendingForDrawer(_zdoId); } } private void OnDrawerDestroyed() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_view == (Object)null) && _view.IsOwner()) { DrawerSnapshot snapshot = Snapshot; if (((DrawerSnapshot)(ref snapshot)).IsAssigned && snapshot.Amount > 0) { ItemFacts.SpillAtPosition(((Component)this).transform.position, snapshot.ItemName, snapshot.Amount); } } } private static DrawerTier TierFromPrefabName(string name) { DrawerTier[] all = DrawerTiers.All; foreach (DrawerTier drawerTier in all) { if (name.StartsWith(DrawerTiers.PrefabName(drawerTier))) { return drawerTier; } } return DrawerTier.Wood; } private bool WriteOwned(DrawerSnapshot expected, DrawerSnapshot next) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner()) { return false; } ZDO zDO = _view.GetZDO(); DrawerSnapshot val = default(DrawerSnapshot); ((DrawerSnapshot)(ref val))..ctor(zDO.GetString(KeyPrefabHash, ""), zDO.GetInt(KeyAmountHash, 0)); if (!((DrawerSnapshot)(ref val)).Equals(expected)) { return false; } zDO.Set(KeyPrefabHash, next.ItemName); zDO.Set(KeyAmountHash, next.Amount, false); DrawerManager.Instance?.MarkDirty(this); RefreshFace(); return true; } public void RefreshFace() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Face == (Object)null)) { DrawerSnapshot snapshot = Snapshot; Face.Show(snapshot.ItemName, snapshot.Amount); } } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (hold) { return false; } Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)val == (Object)null) { return false; } DrawerSnapshot snapshot = Snapshot; bool button = ZInput.GetButton("Crouch"); bool button2 = ZInput.GetButton("Run"); if (button) { if (!((DrawerSnapshot)(ref snapshot)).IsAssigned) { return true; } if (((DrawerSnapshot)(ref snapshot)).IsEmpty) { RequestClear(snapshot); return true; } BeginWithdraw(val, snapshot, DrawerState.WithdrawOne(snapshot)); return true; } if (button2) { return DepositEverythingMatching(val, snapshot); } int num = ItemFacts.MaxStackSize(snapshot.ItemName); BeginWithdraw(val, snapshot, DrawerState.WithdrawStack(snapshot, num)); return true; } public bool UseItem(Humanoid user, ItemData item) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)val == (Object)null || item == null) { return false; } if ((Object)(object)_view == (Object)null || !_view.IsValid()) { ((Character)val).Message((MessageType)2, "Try again", 0, (Sprite)null, false); return true; } if (item.m_shared.m_maxStackSize <= 1) { ((Character)val).Message((MessageType)2, "Drawers only hold stackable items", 0, (Sprite)null, false); return true; } string text = ItemFacts.PrefabNameOf(item); if (text == null) { ((Character)val).Message((MessageType)2, "Cannot identify this item", 0, (Sprite)null, false); return true; } DrawerSnapshot snapshot = Snapshot; if (((DrawerSnapshot)(ref snapshot)).IsAssigned && snapshot.ItemName != text) { ((Character)val).Message((MessageType)2, "This drawer holds " + ItemFacts.LocalizedName(snapshot.ItemName), 0, (Sprite)null, false); return true; } DrawerOutcome val2 = DrawerState.Deposit(snapshot, Capacity, text, item.m_stack); if (!val2.Accepted) { ((Character)val).Message((MessageType)2, val2.Rejection, 0, (Sprite)null, false); return true; } if (!((Humanoid)val).GetInventory().RemoveItem(item, val2.MovedToDrawer)) { ((Character)val).Message((MessageType)2, "Could not remove item", 0, (Sprite)null, false); return true; } RequestDeposit(val, text, val2.MovedToDrawer, announce: false); return true; } private bool DepositEverythingMatching(Player player, DrawerSnapshot current) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_view == (Object)null || !_view.IsValid()) { ((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false); return true; } if (!((DrawerSnapshot)(ref current)).IsAssigned) { ((Character)player).Message((MessageType)2, "This drawer has not been assigned", 0, (Sprite)null, false); return true; } Inventory inventory = ((Humanoid)player).GetInventory(); List<ItemData> list = new List<ItemData>(); int num = 0; foreach (ItemData allItem in inventory.GetAllItems()) { if (!(ItemFacts.PrefabNameOf(allItem) != current.ItemName)) { list.Add(allItem); num += allItem.m_stack; } } if (num <= 0) { ((Character)player).Message((MessageType)2, "You have none of those", 0, (Sprite)null, false); return true; } DrawerOutcome val = DrawerState.Deposit(current, Capacity, current.ItemName, num); if (!val.Accepted) { ((Character)player).Message((MessageType)2, val.Rejection, 0, (Sprite)null, false); return true; } int movedToDrawer = val.MovedToDrawer; int num2 = 0; foreach (ItemData item in list) { if (num2 >= movedToDrawer) { break; } int num3 = ((item.m_stack < movedToDrawer - num2) ? item.m_stack : (movedToDrawer - num2)); if (inventory.RemoveItem(item, num3)) { num2 += num3; } } if (num2 <= 0) { ((Character)player).Message((MessageType)2, "You have none of those", 0, (Sprite)null, false); return true; } RequestDeposit(player, current.ItemName, num2, announce: true); return true; } private void BeginWithdraw(Player player, DrawerSnapshot current, DrawerOutcome outcome) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (!outcome.Accepted) { ((Character)player).Message((MessageType)2, outcome.Rejection, 0, (Sprite)null, false); } else if (outcome.MovedToPlayer > 0) { if ((Object)(object)ItemFacts.Drop(current.ItemName) == (Object)null) { ((Character)player).Message((MessageType)2, "Cannot identify this item", 0, (Sprite)null, false); } else { RequestWithdraw(player, current.ItemName, outcome.MovedToPlayer); } } } private void RequestWithdraw(Player player, string itemName, int requested) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_view == (Object)null || !_view.IsValid() || requested <= 0) { return; } if (_view.IsOwner()) { DrawerSnapshot snapshot = Snapshot; DrawerOutcome val = DrawerState.WithdrawExact(snapshot, requested); if (val.MovedToPlayer > 0 && WriteOwned(snapshot, val.Result)) { ItemFacts.GiveToPlayer(player, snapshot.ItemName, val.MovedToPlayer); } return; } DrawerManager instance = DrawerManager.Instance; if (!((Object)(object)instance == (Object)null)) { long owner = _view.GetZDO().GetOwner(); if (owner == 0L) { ((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false); return; } long id = instance.NextRequestId(); instance.AddPendingWithdrawal(id, new PendingWithdrawal(_zdoId, owner, player, requested, ((Component)player).transform.position)); SendWithdrawRequestRpc(id, owner, requested); } } internal void SendWithdrawRequestRpc(long id, long targetOwner, int requested) { if ((Object)(object)_view != (Object)null && _view.IsValid()) { _view.InvokeRPC(targetOwner, "RID_ReqWithdraw", new object[2] { id, requested }); } } private void RPC_RequestWithdraw(long sender, long id, int requested) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner()) { return; } _handledWithdrawals.Prune(Time.time); (string, int) tuple = default((string, int)); if (_handledWithdrawals.TryGet(sender, id, ref tuple)) { _view.InvokeRPC(sender, "RID_GrantWithdraw", new object[3] { id, tuple.Item1, tuple.Item2 }); return; } DrawerSnapshot snapshot = Snapshot; int num = 0; if (((DrawerSnapshot)(ref snapshot)).IsAssigned && (Object)(object)ItemFacts.Drop(snapshot.ItemName) != (Object)null) { DrawerOutcome val = DrawerState.WithdrawExact(snapshot, requested); if (val.MovedToPlayer > 0 && WriteOwned(snapshot, val.Result)) { num = val.MovedToPlayer; } } _handledWithdrawals.Record(sender, id, (snapshot.ItemName, num), Time.time); _view.InvokeRPC(sender, "RID_GrantWithdraw", new object[3] { id, snapshot.ItemName, num }); } private void RPC_GrantWithdraw(long sender, long id, string itemName, int granted) { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) DrawerManager instance = DrawerManager.Instance; if ((Object)(object)instance == (Object)null || !instance.TryCompleteWithdrawal(id, out var payload)) { return; } if (sender != payload.TargetOwner) { DrawerPlugin.Log.LogWarning((object)$"RPC_GrantWithdraw: reply for request {id} came from peer {sender}, not the pinned target {payload.TargetOwner}."); } int num = ((granted >= 0) ? Math.Min(granted, payload.Requested) : 0); if (granted != num) { DrawerPlugin.Log.LogWarning((object)$"RPC_GrantWithdraw: request {id} asked for {payload.Requested} but was granted {granted}; clamped to {num}."); } if (num > 0) { if ((Object)(object)payload.Player != (Object)null) { ItemFacts.GiveToPlayer(payload.Player, itemName, num); } else { ItemFacts.SpillAtPosition(payload.PlayerPosition, itemName, num); } } } private void RequestDeposit(Player player, string itemName, int removed, bool announce) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (removed <= 0) { return; } if ((Object)(object)_view == (Object)null || !_view.IsValid()) { ItemFacts.SpillAtPosition(((Component)player).transform.position, itemName, removed); ((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false); return; } if (_view.IsOwner()) { DrawerSnapshot snapshot = Snapshot; DrawerOutcome val = DrawerState.Deposit(snapshot, Capacity, itemName, removed); int num = ((val.Accepted && WriteOwned(snapshot, val.Result)) ? val.MovedToDrawer : 0); int num2 = DrawerState.RefundShortfall(removed, num); if (num2 > 0) { ItemFacts.GiveToPlayer(player, itemName, num2); } if (announce) { AnnounceDeposit(player, itemName, num); } return; } DrawerManager instance = DrawerManager.Instance; if ((Object)(object)instance == (Object)null) { ItemFacts.SpillAtPosition(((Component)player).transform.position, itemName, removed); ((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false); return; } long owner = _view.GetZDO().GetOwner(); if (owner == 0L) { ItemFacts.SpillAtPosition(((Component)player).transform.position, itemName, removed); ((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false); } else { long id = instance.NextRequestId(); instance.AddPendingDeposit(id, new PendingDeposit(_zdoId, owner, player, itemName, removed, ((Component)player).transform.position, announce)); SendDepositRequestRpc(id, owner, itemName, removed); } } internal void SendDepositRequestRpc(long id, long targetOwner, string itemName, int removed) { if ((Object)(object)_view != (Object)null && _view.IsValid()) { _view.InvokeRPC(targetOwner, "RID_ReqDeposit", new object[3] { id, itemName, removed }); } } private void RPC_RequestDeposit(long sender, long id, string itemName, int amount) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_view == (Object)null) && _view.IsValid() && _view.IsOwner()) { _handledDeposits.Prune(Time.time); int num = default(int); if (_handledDeposits.TryGet(sender, id, ref num)) { _view.InvokeRPC(sender, "RID_GrantDeposit", new object[2] { id, num }); return; } DrawerSnapshot snapshot = Snapshot; DrawerOutcome val = DrawerState.Deposit(snapshot, Capacity, itemName, amount); int num2 = ((val.Accepted && WriteOwned(snapshot, val.Result)) ? val.MovedToDrawer : 0); _handledDeposits.Record(sender, id, num2, Time.time); _view.InvokeRPC(sender, "RID_GrantDeposit", new object[2] { id, num2 }); } } private void RPC_GrantDeposit(long sender, long id, int accepted) { //IL_00de: Unknown result type (might be due to invalid IL or missing references) DrawerManager instance = DrawerManager.Instance; if ((Object)(object)instance == (Object)null || !instance.TryCompleteDeposit(id, out var payload)) { return; } if (sender != payload.TargetOwner) { DrawerPlugin.Log.LogWarning((object)$"RPC_GrantDeposit: reply for request {id} came from peer {sender}, not the pinned target {payload.TargetOwner}."); } int num = ((accepted >= 0) ? Math.Min(accepted, payload.Removed) : 0); if (accepted != num) { DrawerPlugin.Log.LogWarning((object)$"RPC_GrantDeposit: request {id} offered {payload.Removed} but {accepted} was reported accepted; clamped to {num}."); } int num2 = DrawerState.RefundShortfall(payload.Removed, num); if (num2 > 0) { if ((Object)(object)payload.Player != (Object)null) { ItemFacts.GiveToPlayer(payload.Player, payload.ItemName, num2); } else { ItemFacts.SpillAtPosition(payload.PlayerPosition, payload.ItemName, num2); } } if (payload.Announce && (Object)(object)payload.Player != (Object)null) { AnnounceDeposit(payload.Player, payload.ItemName, num); } } private static void AnnounceDeposit(Player player, string itemName, int accepted) { if (accepted > 0) { ((Character)player).Message((MessageType)1, $"Stored {accepted} {ItemFacts.LocalizedName(itemName)}", 0, (Sprite)null, false); } } private void RequestClear(DrawerSnapshot current) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_view == (Object)null || !_view.IsValid()) { return; } if (_view.IsOwner()) { DrawerOutcome val = DrawerState.Clear(current); if (val.Accepted) { WriteOwned(current, val.Result); } } else { _view.InvokeRPC("RID_ReqClear", Array.Empty<object>()); } } private void RPC_RequestClear(long sender) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_view == (Object)null) && _view.IsValid() && _view.IsOwner()) { DrawerSnapshot snapshot = Snapshot; DrawerOutcome val = DrawerState.Clear(snapshot); if (val.Accepted) { WriteOwned(snapshot, val.Result); } } } public bool TryWithdrawExternally(int requested, out int taken) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) taken = 0; if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner()) { return false; } DrawerSnapshot snapshot = Snapshot; DrawerOutcome val = DrawerState.WithdrawExact(snapshot, requested); if (val.MovedToPlayer <= 0) { return false; } if (!WriteOwned(snapshot, val.Result)) { return false; } taken = val.MovedToPlayer; return true; } public bool TryDepositExternally(string itemName, int amount, out int accepted) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) accepted = 0; if (!ItemFacts.IsStorable(itemName)) { return false; } if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner()) { return false; } DrawerSnapshot snapshot = Snapshot; DrawerOutcome val = DrawerState.Deposit(snapshot, Capacity, itemName, amount); if (!val.Accepted || val.MovedToDrawer <= 0) { return false; } if (!WriteOwned(snapshot, val.Result)) { return false; } accepted = val.MovedToDrawer; return true; } internal void RefreshMirror() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) DrawerSnapshot current = EffectiveMirrorSnapshot(); if (_mirrorNeedsRebuild || !((DrawerSnapshot)(ref current)).Equals(_mirrored)) { RebuildMirror(current); _mirrorNeedsRebuild = false; } } private DrawerSnapshot EffectiveMirrorSnapshot() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_view != (Object)null) || !_view.IsValid() || !_view.IsOwner()) { return new DrawerSnapshot("", 0); } return Snapshot; } private void RebuildMirror(DrawerSnapshot current) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) _applyingMirror = true; try { Inventory mirrorInventory = MirrorInventory; mirrorInventory.RemoveAll(); if (((DrawerSnapshot)(ref current)).IsAssigned && !((DrawerSnapshot)(ref current)).IsEmpty) { GameObject val = ItemFacts.Prefab(current.ItemName); if ((Object)(object)val != (Object)null) { ItemDrop component = val.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { ItemData val2 = component.m_itemData.Clone(); val2.m_stack = current.Amount; val2.m_dropPrefab = val; val2.m_gridPos = new Vector2i(0, 0); val2.m_worldLevel = (byte)Game.m_worldLevel; mirrorInventory.AddItem(val2); } } } _mirrored = current; } finally { _applyingMirror = false; } } private void OnMirrorChanged() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (!_applyingMirror) { ItemData itemAt = _mirror.GetItemAt(0, 0); string text = ((itemAt != null) ? (ItemFacts.PrefabNameOf(itemAt) ?? "") : ""); int num = itemAt?.m_stack ?? 0; DrawerSnapshot snapshot = Snapshot; MirrorDelta val = MirrorReconciliation.Compute(text, num, _mirrored.ItemName, _mirrored.Amount, snapshot.ItemName, snapshot.Amount); if (val.Withdraw > 0 && !TryWithdrawExternally(val.Withdraw, out var _)) { _mirrorNeedsRebuild = true; } else { _mirrored = new DrawerSnapshot(text, num); } } } public string GetHoverText() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) DrawerSnapshot snapshot = Snapshot; if (!((DrawerSnapshot)(ref snapshot)).IsAssigned) { return Localization.instance.Localize(DrawerTiers.DisplayName(Tier) + "\n[<color=yellow><b>1-8</b></color>] Store an item"); } string arg = ItemFacts.LocalizedName(snapshot.ItemName); return Localization.instance.Localize($"{arg} <color=orange>{snapshot.Amount}</color>/{Capacity}\n" + "[<color=yellow><b>E</b></color>] Take stack\n[<color=yellow><b>Ctrl+E</b></color>] Take one\n[<color=yellow><b>Shift+E</b></color>] Store all"); } public string GetHoverName() { return DrawerTiers.DisplayName(Tier); } } [HarmonyPatch(typeof(Container), "CanBeRemoved")] internal static class DrawerCanBeRemovedPatch { private static bool Prepare() { return ValheimCompat.RequireMethod(typeof(Container), "CanBeRemoved"); } private static bool Prefix(Container __instance, ref bool __result) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (!(__instance is DrawerComponent drawerComponent)) { return true; } DrawerSnapshot snapshot = drawerComponent.Snapshot; __result = ((DrawerSnapshot)(ref snapshot)).IsEmpty; return false; } } public static class DrawerConfig { public static ConfigEntry<int> WoodCapacity; public static ConfigEntry<int> StoneCapacity; public static ConfigEntry<int> BlackMarbleCapacity; public static ConfigEntry<bool> AutoPickupEnabled; public static ConfigEntry<float> PickupRadius; public static ConfigEntry<float> PickupScanRange; public static ConfigEntry<float> PickupInterval; public static ConfigEntry<float> LabelDistance; public static void Bind(ConfigFile config) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Expected O, but got Unknown //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown WoodCapacity = config.Bind<int>("Capacity", "Wood", 1000, new ConfigDescription("How many items a wood drawer holds.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); StoneCapacity = config.Bind<int>("Capacity", "Stone", 2000, new ConfigDescription("How many items a stone drawer holds.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); BlackMarbleCapacity = config.Bind<int>("Capacity", "BlackMarble", 10000, new ConfigDescription("How many items a black marble drawer holds.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); AutoPickupEnabled = config.Bind<bool>("Pickup", "Enabled", true, new ConfigDescription("Drawers absorb matching items dropped nearby.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); PickupRadius = config.Bind<float>("Pickup", "Radius", 40f, new ConfigDescription("How far from a drawer a dropped item is absorbed, in metres.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); PickupScanRange = config.Bind<float>("Pickup", "ScanRange", 40f, new ConfigDescription("How far around you dropped items are considered at all. One query covers every drawer, so this is cheap.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); PickupInterval = config.Bind<float>("Pickup", "Interval", 0.5f, new ConfigDescription("Seconds between pickup passes.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); LabelDistance = config.Bind<float>("Display", "LabelDistance", 30f, "Beyond this distance drawer icons and counts switch off. A wall of text nobody can read is wasted work."); } public static int CapacityFor(DrawerTier tier) { return tier switch { DrawerTier.Wood => WoodCapacity?.Value ?? DrawerTiers.DefaultCapacity(tier), DrawerTier.Stone => StoneCapacity?.Value ?? DrawerTiers.DefaultCapacity(tier), DrawerTier.BlackMarble => BlackMarbleCapacity?.Value ?? DrawerTiers.DefaultCapacity(tier), _ => DrawerTiers.DefaultCapacity(tier), }; } } internal static class DrawerFont { private static TMP_FontAsset _cached; private static bool _loggedFailure; public static TMP_FontAsset Shared { get { if ((Object)(object)_cached != (Object)null) { return _cached; } TMP_FontAsset val = ((GUIManager.Instance != null) ? GUIManager.Instance.TMP_AveriaSansLibre : null); if ((Object)(object)val != (Object)null) { _cached = val; return _cached; } TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>(); foreach (TMP_Text val2 in array) { if ((Object)(object)val2 != (Object)null && (Object)(object)val2.font != (Object)null) { _cached = val2.font; return _cached; } } TMP_FontAsset[] array2 = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); if (array2.Length != 0) { _cached = array2[0]; return _cached; } try { TMP_FontAsset defaultFontAsset = TMP_Settings.defaultFontAsset; if ((Object)(object)defaultFontAsset != (Object)null) { _cached = defaultFontAsset; return _cached; } } catch (Exception) { } if (!_loggedFailure) { _loggedFailure = true; DrawerPlugin.Log.LogError((object)"No TMP font asset found anywhere (checked Jotunn.GUIManager.TMP_AveriaSansLibre, every live TMP_Text, Resources.FindObjectsOfTypeAll<TMP_FontAsset>, and TMP_Settings.defaultFontAsset). Drawer count labels will not render any text until this resolves. This mod ships no font of its own by design."); } return null; } } } public static class DrawerIconAtlas { private static AtlasLayout _layout; private static Texture2D _texture; private static bool _buildFailureLogged; private static readonly string[] ShaderCandidates = new string[3] { "Unlit/Transparent", "Sprites/Default", "UI/Default" }; public static Material SharedMaterial { get; private set; } public static bool IsBuilt { get { if (_layout != null) { return (Object)(object)SharedMaterial != (Object)null; } return false; } } public static void Build() { if (IsBuilt) { return; } try { BuildInternal(); } catch (Exception arg) { _layout = null; SharedMaterial = null; if (!_buildFailureLogged) { _buildFailureLogged = true; DrawerPlugin.Log.LogError((object)("Icon atlas build threw; leaving it unbuilt. Will keep retrying quietly on " + $"later calls, but will not log this again: {arg}")); } } } private static void BuildInternal() { //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Expected O, but got Unknown //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ObjectDB.instance == (Object)null) { DrawerPlugin.Log.LogWarning((object)"ObjectDB not ready; icon atlas deferred."); return; } List<IconSize> list = new List<IconSize>(); Dictionary<string, Sprite> dictionary = new Dictionary<string, Sprite>(); foreach (GameObject item in ObjectDB.instance.m_items) { ItemDrop val = (((Object)(object)item == (Object)null) ? null : item.GetComponent<ItemDrop>()); if (!((Object)(object)val == (Object)null) && val.m_itemData.m_shared.m_maxStackSize > 1) { Sprite icon; try { icon = val.m_itemData.GetIcon(); } catch (Exception ex) { DrawerPlugin.Log.LogWarning((object)("Skipping '" + ((Object)item).name + "' in the icon atlas: GetIcon() threw (" + ex.GetType().Name + ": " + ex.Message + ").")); continue; } if (!((Object)(object)icon == (Object)null) && !((Object)(object)icon.texture == (Object)null) && !dictionary.ContainsKey(((Object)item).name)) { dictionary[((Object)item).name] = icon; string name = ((Object)item).name; Rect textureRect = icon.textureRect; int num = (int)((Rect)(ref textureRect)).width; textureRect = icon.textureRect; list.Add(new IconSize(name, num, (int)((Rect)(ref textureRect)).height)); } } } if (list.Count == 0) { DrawerPlugin.Log.LogError((object)"Icon atlas build found 0 storable items in ObjectDB.m_items -- called too early, before item registration finished. Not marking the atlas built; a later call to Build() (see DrawerIconAtlas.TryGetUv's retry) will try again."); return; } _layout = IconAtlasPacker.Pack((IReadOnlyList<IconSize>)list, 4096); _texture = new Texture2D(_layout.Width, _layout.Height, (TextureFormat)4, true) { name = "rid_icon_atlas", wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; Color32[] pixels = (Color32[])(object)new Color32[_layout.Width * _layout.Height]; _texture.SetPixels32(pixels); foreach (KeyValuePair<string, AtlasRect> rect in _layout.Rects) { if (dictionary.TryGetValue(rect.Key, out var value) && TryReadSprite(value, out var pixels2, out var width, out var height)) { _texture.SetPixels32(rect.Value.X, rect.Value.Y, width, height, pixels2); } } _texture.Apply(true, true); string source; Shader val2 = ResolveIconShader(out source); if ((Object)(object)val2 == (Object)null) { DrawerPlugin.Log.LogError((object)("No usable shader found for the drawer icon atlas material (tried " + string.Join(", ", ShaderCandidates) + "). Drawer icons will not render until this is fixed.")); Object.Destroy((Object)(object)_texture); _texture = null; _layout = null; } else { SharedMaterial = new Material(val2) { name = "rid_icon_material", mainTexture = (Texture)(object)_texture }; SharedMaterial.renderQueue = 2450; DrawerPlugin.Log.LogInfo((object)($"Icon atlas built: {_layout.Rects.Count} icons in {_layout.Width}x{_layout.Height}, " + "material shader = " + source)); } } private static Shader ResolveIconShader(out string source) { string[] shaderCandidates = ShaderCandidates; foreach (string text in shaderCandidates) { Shader val = Shader.Find(text); if ((Object)(object)val != (Object)null) { source = "Shader.Find(\"" + text + "\")"; return val; } DrawerPlugin.Log.LogWarning((object)("Shader.Find(\"" + text + "\") returned null; trying next candidate.")); } source = null; return null; } private static bool TryReadSprite(Sprite sprite, out Color32[] pixels, out int width, out int height) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) pixels = null; Rect textureRect = sprite.textureRect; width = Mathf.RoundToInt(((Rect)(ref textureRect)).width); height = Mathf.RoundToInt(((Rect)(ref textureRect)).height); if (width <= 0 || height <= 0) { return false; } RenderTexture active = RenderTexture.active; RenderTexture temporary = RenderTexture.GetTemporary(((Texture)sprite.texture).width, ((Texture)sprite.texture).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)0); try { Graphics.Blit((Texture)(object)sprite.texture, temporary); RenderTexture.active = temporary; Texture2D val = new Texture2D(width, height, (TextureFormat)4, false); val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)width, (float)height), 0, 0); val.Apply(); pixels = val.GetPixels32(); Object.Destroy((Object)(object)val); return true; } catch (Exception ex) { DrawerPlugin.Log.LogWarning((object)("Could not read icon for atlas: " + ex.Message)); return false; } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); } } public static bool TryGetUv(string item, out Vector2 min, out Vector2 max) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) min = Vector2.zero; max = Vector2.one; if (!IsBuilt) { Build(); } if (_layout == null) { return false; } float num = default(float); float num2 = default(float); float num3 = default(float); float num4 = default(float); if (!_layout.TryGetUv(item, ref num, ref num2, ref num3, ref num4)) { return false; } min = new Vector2(num, num2); max = new Vector2(num3, num4); return true; } } internal sealed class PendingWithdrawal { public readonly ZDOID DrawerId; public readonly long TargetOwner; public readonly Player Player; public readonly int Requested; public readonly Vector3 PlayerPosition; public PendingWithdrawal(ZDOID drawerId, long targetOwner, Player player, int requested, Vector3 playerPosition) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) DrawerId = drawerId; TargetOwner = targetOwner; Player = player; Requested = requested; PlayerPosition = playerPosition; } } internal sealed class PendingDeposit { public readonly ZDOID DrawerId; public readonly long TargetOwner; public readonly Player Player; public readonly string ItemName; public readonly int Removed; public readonly Vector3 PlayerPosition; public readonly bool Announce; public PendingDeposit(ZDOID drawerId, long targetOwner, Player player, string itemName, int removed, Vector3 playerPosition, bool announce) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) DrawerId = drawerId; TargetOwner = targetOwner; Player = player; ItemName = itemName; Removed = removed; PlayerPosition = playerPosition; Announce = announce; } } public class DrawerManager : MonoBehaviour { private readonly SpatialGrid<DrawerComponent> _grid = new SpatialGrid<DrawerComponent>(8f); private readonly List<DrawerComponent> _all = new List<DrawerComponent>(); private readonly HashSet<DrawerComponent> _dirty = new HashSet<DrawerComponent>(); private float _cullTimer; private int _syncCursor; private float _pickupTimer; private readonly List<DrawerComponent> _pickupScratch = new List<DrawerComponent>(16); private readonly RequestIdGenerator _requestIds = new RequestIdGenerator(DateTimeOffset.UtcNow.Ticks); private readonly PendingRequestLedger<PendingWithdrawal> _pendingWithdrawals = new PendingRequestLedger<PendingWithdrawal>(5f, 3); private readonly PendingRequestLedger<PendingDeposit> _pendingDeposits = new PendingRequestLedger<PendingDeposit>(5f, 3); public static DrawerManager Instance { get; private set; } public static void Create() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)Instance != (Object)null)) { GameObject val = new GameObject("RidDrawerManager"); Object.DontDestroyOnLoad((Object)val); Instance = val.AddComponent<DrawerManager>(); } } public long NextRequestId() { return _requestIds.Next(); } internal void AddPendingWithdrawal(long id, PendingWithdrawal payload) { _pendingWithdrawals.Add(id, payload, Time.time); } internal void AddPendingDeposit(long id, PendingDeposit payload) { _pendingDeposits.Add(id, payload, Time.time); } internal bool TryCompleteWithdrawal(long id, out PendingWithdrawal payload) { return _pendingWithdrawals.TryComplete(id, ref payload); } internal bool TryCompleteDeposit(long id, out PendingDeposit payload) { return _pendingDeposits.TryComplete(id, ref payload); } public void ResolvePendingForDrawer(ZDOID drawerId) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) ResolveMatching(_pendingWithdrawals, drawerId, (PendingWithdrawal p) => p.DrawerId, GiveUpWithdrawal); ResolveMatching(_pendingDeposits, drawerId, (PendingDeposit p) => p.DrawerId, GiveUpDeposit); } private static void ResolveMatching<T>(PendingRequestLedger<T> ledger, ZDOID drawerId, Func<T, ZDOID> drawerOf, Action<long, T> onResolved) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) List<long> list = null; foreach (KeyValuePair<long, T> item in ledger.All()) { ZDOID val = drawerOf(item.Value); if (((ZDOID)(ref val)).Equals(drawerId)) { (list ?? (list = new List<long>())).Add(item.Key); } } if (list == null) { return; } T arg = default(T); foreach (long item2 in list) { if (ledger.Remove(item2, ref arg)) { onResolved(item2, arg); } } } internal void DrainPendingDepositsBeforeSave() { List<long> list = null; foreach (KeyValuePair<long, PendingDeposit> item in _pendingDeposits.All()) { (list ?? (list = new List<long>())).Add(item.Key); } if (list == null) { return; } PendingDeposit payload = default(PendingDeposit); foreach (long item2 in list) { if (_pendingDeposits.Remove(item2, ref payload)) { GiveUpDeposit(item2, payload); } } } private void OnApplicationQuit() { DrainPendingDepositsBeforeSave(); } public void Register(DrawerComponent drawer) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)drawer == (Object)null) && !_all.Contains(drawer)) { _all.Add(drawer); Vector3 position = ((Component)drawer).transform.position; _grid.Insert(drawer, position.x, position.y, position.z); MarkDirty(drawer); } } public void Unregister(DrawerComponent drawer) { if (!((Object)(object)drawer == (Object)null)) { _all.Remove(drawer); _dirty.Remove(drawer); _grid.Remove(drawer); } } public void MarkDirty(DrawerComponent drawer) { if ((Object)(object)drawer != (Object)null) { _dirty.Add(drawer); } } public void QueryNear(Vector3 position, float radius, List<DrawerComponent> results) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) _grid.Query(position.x, position.y, position.z, radius, results); } private void Update() { if (_dirty.Count > 0) { FlushDirty(); } SyncSomeFaces(); if (_pendingWithdrawals.Count > 0) { _pendingWithdrawals.Tick(Time.time, (Action<long, PendingWithdrawal>)RetryWithdrawal, (Action<long, PendingWithdrawal>)GiveUpWithdrawal); } if (_pendingDeposits.Count > 0) { _pendingDeposits.Tick(Time.time, (Action<long, PendingDeposit>)RetryDeposit, (Action<long, PendingDeposit>)GiveUpDeposit); } _cullTimer -= Time.deltaTime; if (_cullTimer <= 0f) { _cullTimer = 0.5f; UpdateLabelVisibility(); } _pickupTimer -= Time.deltaTime; if (_pickupTimer <= 0f) { _pickupTimer = DrawerConfig.PickupInterval.Value; if (DrawerConfig.AutoPickupEnabled.Value) { RunAutoPickup(); } } } private void RunAutoPickup() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || _all.Count == 0) { return; } List<ItemDrop> s_instances = ItemDrop.s_instances; if (s_instances == null || s_instances.Count == 0) { return; } float value = DrawerConfig.PickupRadius.Value; float value2 = DrawerConfig.PickupScanRange.Value; float num = value2 * value2; Vector3 position = ((Component)localPlayer).transform.position; for (int i = 0; i < s_instances.Count; i++) { ItemDrop val = s_instances[i]; if ((Object)(object)val == (Object)null) { continue; } Vector3 val2 = ((Component)val).transform.position - position; if (((Vector3)(ref val2)).sqrMagnitude > num || (Object)(object)val.m_nview == (Object)null || !val.m_nview.IsValid() || !val.m_nview.IsOwner() || val.m_itemData == null || val.m_itemData.m_shared.m_maxStackSize <= 1) { continue; } string text = (((Object)(object)val.m_itemData.m_dropPrefab != (Object)null) ? ((Object)val.m_itemData.m_dropPrefab).name : ((Object)val).name.Replace("(Clone)", "")); _pickupScratch.Clear(); QueryNear(((Component)val).transform.position, value, _pickupScratch); for (int j = 0; j < _pickupScratch.Count; j++) { DrawerComponent drawerComponent = _pickupScratch[j]; if ((Object)(object)drawerComponent == (Object)null) { continue; } DrawerSnapshot snapshot = drawerComponent.Snapshot; if (((DrawerSnapshot)(ref snapshot)).IsAssigned && !(snapshot.ItemName != text) && drawerComponent.TryDepositExternally(text, val.m_itemData.m_stack, out var accepted) && accepted > 0) { ItemData itemData = val.m_itemData; itemData.m_stack -= accepted; if (val.m_itemData.m_stack <= 0) { ZNetScene.instance.Destroy(((Component)val).gameObject); } else { val.Save(); } break; } } } } private static DrawerComponent FindLive(ZDOID drawerId) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) List<DrawerComponent> all = DrawerComponent.All; for (int i = 0; i < all.Count; i++) { if ((Object)(object)all[i] != (Object)null) { ZDOID zdoId = all[i].ZdoId; if (((ZDOID)(ref zdoId)).Equals(drawerId)) { return all[i]; } } } return null; } private void RetryWithdrawal(long id, PendingWithdrawal payload) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) DrawerComponent drawerComponent = FindLive(payload.DrawerId); if ((Object)(object)drawerComponent == (Object)null) { GiveUpWithdrawal(id, payload); PendingWithdrawal pendingWithdrawal = default(PendingWithdrawal); _pendingWithdrawals.Remove(id, ref pendingWithdrawal); } else { drawerComponent.SendWithdrawRequestRpc(id, payload.TargetOwner, payload.Requested); } } private void RetryDeposit(long id, PendingDeposit payload) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) DrawerComponent drawerComponent = FindLive(payload.DrawerId); if ((Object)(object)drawerComponent == (Object)null) { GiveUpDeposit(id, payload); PendingDeposit pendingDeposit = default(PendingDeposit); _pendingDeposits.Remove(id, ref pendingDeposit); } else { drawerComponent.SendDepositRequestRpc(id, payload.TargetOwner, payload.ItemName, payload.Removed); } } private static void GiveUpWithdrawal(long id, PendingWithdrawal payload) { Player player = payload.Player; if (player != null) { ((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false); } } private static void GiveUpDeposit(long id, PendingDeposit payload) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (payload.Removed > 0) { ItemFacts.SpillAtPosition(((Object)(object)payload.Player != (Object)null) ? ((Component)payload.Player).transform.position : payload.PlayerPosition, payload.ItemName, payload.Removed); } Player player = payload.Player; if (player != null) { ((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false); } } private void FlushDirty() { foreach (DrawerComponent item in _dirty) { if ((Object)(object)item != (Object)null) { item.RefreshFace(); } } _dirty.Clear(); } private void SyncSomeFaces() { if (_all.Count == 0) { return; } int num = Mathf.Max(1, _all.Count / 30); for (int i = 0; i < num; i++) { if (_syncCursor >= _all.Count) { _syncCursor = 0; } DrawerComponent drawerComponent = _all[_syncCursor++]; if (!((Object)(object)drawerComponent == (Object)null)) { if ((Object)(object)drawerComponent.Face != (Object)null && drawerComponent.Face.NeedsFont) { drawerComponent.Face.TryConfigureCountText(); } drawerComponent.RefreshFace(); } } } private void UpdateLabelVisibility() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return; } Vector3 position = ((Component)main).transform.position; float value = DrawerConfig.LabelDistance.Value; float num = value * value; for (int i = 0; i < _all.Count; i++) { DrawerComponent drawerComponent = _all[i]; if (!((Object)(object)drawerComponent == (Object)null)) { DrawerRenderer face = drawerComponent.Face; if (face != null) { Vector3 val = ((Component)drawerComponent).transform.position - position; face.SetLabelVisible(((Vector3)(ref val)).sqrMagnitude <= num); } } } } } [HarmonyPatch(typeof(Game), "Shutdown")] internal static class GameShutdownPatch { private static bool Prepare() { return ValheimCompat.RequireMethod(typeof(Game), "Shutdown"); } private static void Prefix() { DrawerManager.Instance?.DrainPendingDepositsBeforeSave(); } } public static class DrawerMaterialTextures { private const int Size = 512; private const int WoodSeed = 1; private const int StoneSeed = 2; private const int MarbleSeed = 3; private static readonly Dictionary<DrawerTier, (Texture2D albedo, Texture2D normal)> _cache = new Dictionary<DrawerTier, (Texture2D, Texture2D)>(); private static readonly Dictionary<DrawerTier, byte[]> _albedoBytes = new Dictionary<DrawerTier, byte[]>(); private static readonly Dictionary<(DrawerTier, int), Texture2D> _brightCache = new Dictionary<(DrawerTier, int), Texture2D>(); private static Texture2D _metal; public static (Texture2D albedo, Texture2D normal) Get(DrawerTier tier) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (_cache.TryGetValue(tier, out (Texture2D, Texture2D) value)) { return value; } TextureData val = DrawerTextureGenerator.Generate(ToTextureTier(tier), 512, 512, SeedFor(tier)); _albedoBytes[tier] = val.Albedo; (Texture2D, Texture2D) tuple = (BuildTexture(val.Albedo, "albedo", tier, linear: false), BuildTexture(val.Normal, "normal", tier, linear: true)); _cache[tier] = tuple; return tuple; } public static Texture2D GetAtLightness(DrawerTier tier, float target) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) Get(tier); int num = Mathf.RoundToInt(target * 1000f); if (_brightCache.TryGetValue((tier, num), out var value)) { return value; } float num2 = DrawerTextureGenerator.MidLightness(ToTextureTier(tier)); float num3 = ((num2 > 0.0001f) ? (target / num2) : 1f); byte[] array = _albedoBytes[tier]; byte[] array2 = new byte[array.Length]; for (int i = 0; i < array.Length; i += 4) { array2[i] = Saturate((float)(int)array[i] * num3); array2[i + 1] = Saturate((float)(int)array[i + 1] * num3); array2[i + 2] = Saturate((float)(int)array[i + 2] * num3); array2[i + 3] = array[i + 3]; } Texture2D val = BuildTexture(array2, $"albedo_bright{num}", tier, linear: false); _brightCache[(tier, num)] = val; return val; } private static byte Saturate(float v) { return (byte)((v >= 255f) ? 255f : ((v <= 0f) ? 0f : v)); } public static Texture2D Metal() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown if ((Object)(object)_metal != (Object)null) { return _metal; } byte[] array = new byte[64]; for (int i = 0; i < array.Length; i += 4) { array[i] = 197; array[i + 1] = 205; array[i + 2] = 214; array[i + 3] = byte.MaxValue; } _metal = new Texture2D(4, 4, (TextureFormat)4, true, false) { name = "rid_handle_metal", wrapMode = (TextureWrapMode)0, filterMode = (FilterMode)1 }; _metal.SetPixelData<byte>(array, 0, 0); _metal.Apply(true, true); return _metal; } private static TextureTier ToTextureTier(DrawerTier tier) { return (TextureTier)(tier switch { DrawerTier.Wood => 0, DrawerTier.Stone => 1, DrawerTier.BlackMarble => 2, _ => 0, }); } private static int SeedFor(DrawerTier tier) { return tier switch { DrawerTier.Wood => 1, DrawerTier.Stone => 2, DrawerTier.BlackMarble => 3, _ => 1, }; } private static Texture2D BuildTexture(byte[] rgba, string kind, DrawerTier tier, bool linear) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown Texture2D val = new Texture2D(512, 512, (TextureFormat)4, true, linear) { name = $"rid_drawer_{tier}_{kind}", wrapMode = (TextureWrapMode)0, filterMode = (FilterMode)1 }; val.SetPixelData<byte>(rgba, 0, 0); val.Apply(true, true); return val; } } internal static class MeshDataExtensions { public static Mesh ToUnityMesh(this MeshData data, string name) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown Vector3[] array = (Vector3[])(object)new Vector3[data.VertexCount]; Vector3[] array2 = (Vector3[])(object)new Vector3[data.VertexCount]; Vector2[] array3 = (Vector2[])(object)new Vector2[data.VertexCount]; int[] array4 = new int[data.VertexCount]; for (int i = 0; i < data.VertexCount; i++) { array[i] = new Vector3(data.Vertices[i * 3], data.Vertices[i * 3 + 1], data.Vertices[i * 3 + 2]); array2[i] = new Vector3(data.Normals[i * 3], data.Normals[i * 3 + 1], data.Normals[i * 3 + 2]); array3[i] = new Vector2(data.Uvs[i * 2], data.Uvs[i * 2 + 1]); } for (int j = 0; j < data.TriangleCount; j++) { array4[j * 3] = j * 3; array4[j * 3 + 1] = j * 3 + 1; array4[j * 3 + 2] = j * 3 + 2; } Mesh val = new Mesh { name = name }; val.SetVertices(array); val.SetNormals(array2); val.SetUVs(0, array3); val.SetTriangles(array4, 0); val.RecalculateTangents(); val.RecalculateBounds(); val.UploadMeshData(false); return val; } } public static class DrawerPieces { private static Mesh _sharedMesh; private static GameObject _prefabTemplateContainer; private static Mesh _sharedHandleMesh; private const float FaceplateLightness = 0.16f; private static GameObject PrefabTemplateContainer() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)_prefabTemplateContainer == (Object)null) { _prefabTemplateContainer = new GameObject("rid_prefab_template_container"); _prefabTemplateContainer.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_prefabTemplateContainer); } return _prefabTemplateContainer; } public static void RegisterAll() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown DrawerProportions val = new DrawerProportions(); _sharedMesh = DrawerMeshBuilder.Build(new DrawerProportions { Handle = (HandleStyle)0 }).ToUnityMesh("rid_drawer"); _sharedHandleMesh = BuildHandleMesh(val); DrawerTier[] all = DrawerTiers.All; foreach (DrawerTier drawerTier in all) { try { RegisterOne(drawerTier, val); } catch (Exception arg) { DrawerPlugin.Log.LogError((object)$"{drawerTier}: registration threw and was skipped: {arg}"); } } } private static Mesh BuildHandleMesh(DrawerProportions p) { float num = Math.Min(p.FrameThickness, Math.Min(p.Width, p.Height) / 2f - 0.02f); float num2 = Math.Min(p.RecessDepth, p.Depth * 0.5f); float num3 = p.Depth / 2f - num2; float num4 = Math.Min(p.HandleWidth, p.Width - 2f * num - 0.02f); float num5 = Math.Min(p.Bevel, p.HandleSection / 2.5f); return DrawerMeshBuilder.ChamferBox(0f, HandleCenterY(p, num), num3 + p.HandleProud / 2f, num4, p.HandleSection, p.HandleProud, num5).ToUnityMesh("rid_drawer_handle"); } private static float HandleCenterY(DrawerProportions p, float frame) { return (0f - (p.Height - 2f * frame)) / 2f + p.HandleSection * 2.4f; } private static void RegisterOne(DrawerTier tier, DrawerProportions proportions) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown GameObject val = BuildPrefab(tier, _sharedMesh, proportions); if (!((Object)(object)val == (Object)null)) { PieceConfig val2 = new PieceConfig { Name = DrawerTiers.DisplayName(tier), Description = "Holds a great many of a single item.", PieceTable = PieceTables.Hammer, CraftingStation = CraftingStations.Workbench, Requirements = ((IEnumerable<(string, int)>)DrawerTiers.Recipe(tier)).Select((Func<(string, int), RequirementConfig>)(((string Item, int Amount) r) => new RequirementConfig(r.Item, r.Amount, 0, true))).ToArray() }; CustomPiece val3 = new CustomPiece(val, false, val2); if (!val3.IsValid()) { DrawerPlugin.Log.LogError((object)(DrawerTiers.PrefabName(tier) + " FAILED Jotunn validation; not registered. See the Jotunn error immediately above for which check failed.")); } else if (!PieceManager.Instance.AddPiece(val3)) { DrawerPlugin.Log.LogError((object)("AddPiece rejected " + DrawerTiers.PrefabName(tier) + ".")); } else { DrawerPlugin.Log.LogInfo((object)("Registered " + DrawerTiers.PrefabName(tier))); } } } public static GameObject BuildPrefab(DrawerTier tier, Mesh sharedMesh, DrawerProportions proportions) { //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Expected O, but got Unknown //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Expected O, but got Unknown //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_048f: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_0449: Unknown result type (might be due to invalid IL or missing references) //IL_0462: Expected O, but got Unknown //IL_04cb: Unknown result type (might be due to invalid IL or missing references) //IL_04d0: Unknown result type (might be due to invalid IL or missing references) //IL_04e9: Expected O, but got Unknown //IL_0616: Unknown result type (might be due to invalid IL or missing references) //IL_0621: Unknown result type (might be due to invalid IL or missing references) //IL_0590: Unknown result type (might be due to invalid IL or missing references) //IL_0595: Unknown result type (might be due to invalid IL or missing references) //IL_05a8: Unknown result type (might be due to invalid IL or missing references) GameObject val = null; MeshRenderer val2 = null; Piece val3 = null; string arg = null; string[] array = DrawerTiers.MaterialDonors(tier); foreach (string text in array) { GameObject prefab = PrefabManager.Instance.GetPrefab(text); if ((Object)(object)prefab == (Object)null) { DrawerPlugin.Log.LogInfo((object)$"{tier}: donor '{text}' not found, trying next."); continue; } MeshRenderer componentInChildren = prefab.GetComponentInChildren<MeshRenderer>(); Piece component = prefab.GetComponent<Piece>(); if ((Object)(object)componentInChildren == (Object)null || (Object)(object)((Renderer)componentInChildren).sharedMaterial == (Object)null || (Object)(object)component == (Object)null || (Object)(object)component.m_icon == (Object)null) { DrawerPlugin.Log.LogInfo((object)($"{tier}: donor '{text}' unusable " + "(renderer=" + (((Object)(object)componentInChildren == (Object)null) ? "none" : "ok") + ", material=" + (((Object)(object)componentInChildren == (Object)null || (Object)(object)((Renderer)componentInChildren).sharedMaterial == (Object)null) ? "none" : "ok") + ", piece=" + (((Object)(object)component == (Object)null) ? "none" : "ok") + ", icon=" + (((Object)(object)component == (Object)null || (Object)(object)component.m_icon == (Object)null) ? "none" : "ok") + "), trying next.")); continue; } val = prefab; val2 = componentInChildren; val3 = component; arg = text; break; } if ((Object)(object)val == (Object)null) { DrawerPlugin.Log.LogError((object)($"No usable material donor for {tier}. Tried: " + string.Join(", ", DrawerTiers.MaterialDonors(tier)) + ". This tier will be missing from the build menu.")); return null; } GameObject val4 = new GameObject(DrawerTiers.PrefabName(tier)); val4.transform.SetParent(PrefabTemplateContainer().transform, false); GameObject val5 = new GameObject("body"); val5.transform.SetParent(val4.transform, false); val5.AddComponent<MeshFilter>().sharedMesh = sharedMesh; MeshRenderer val6 = val5.AddComponent<MeshRenderer>(); Material val7 = new Material(((Renderer)val2).sharedMaterial.shader) { name = $"rid_drawer_{tier}_mat" }; if (val7.HasProperty("_Color")) { val7.SetColor("_Color", Color.white); } bool flag = val7.HasProperty("_TriplanarScale"); bool flag2 = false; if (flag) { val7.EnableKeyword("_TRIPLANARMAP_ON"); val7.SetFloat("_TriplanarScale", 1f); flag2 = val7.HasProperty("_TriplanarLocalPos"); if (flag2) { val7.SetFloat("_TriplanarLocalPos", 1f); } else { DrawerPlugin.Log.LogWarning((object)($"{tier}: shader has no _TriplanarLocalPos; triplanar mapping " + "will stay projected in world space, which makes each placed drawer's surfaces sample the normal map differently.")); } } else { DrawerPlugin.Log.LogWarning((object)$"{tier}: shader has no _TriplanarScale; leaving UV mapping in place."); } (Texture2D albedo, Texture2D normal) tuple = DrawerMaterialTextures.Get(tier); Texture2D item = tuple.albedo; Texture2D item2 = tuple.normal; bool flag3 = val7.HasProperty("_MainTex"); if (flag3) { val7.SetTexture("_MainTex", (Texture)(object)item); } bool flag4 = val7.HasProperty("_BumpMap"); if (flag4) { val7.SetTexture("_BumpMap", (Texture)(object)item2); val7.EnableKeyword("_NORMALMAP"); } string text2 = ((flag3 && flag4) ? "albedo+normal" : (flag3 ? "albedo only (shader has no _BumpMap)" : "NONE (shader has neither _MainTex nor _BumpMap)")); DrawerPlugin.Log.LogInfo((object)($"{tier}: donor='{arg}', shader='{((Object)((Renderer)val2).sharedMaterial.shader).name}', " + "triplanar=" + (flag ? "on" : "off") + ", triplanarLocalPos=" + (flag2 ? "on" : "off") + ", textures=" + text2 + ", keywords=[" + string.Join(",", val7.shaderKeywords) + "]")); ((Renderer)val6).sharedMaterial = val7; ((Renderer)val6).shadowCastingMode = (ShadowCastingMode)1; Material val8 = null; if (flag3) { val8 = new Material(val7) { name = ((Object)val7).name + "_faceplate" }; val8.SetTexture("_MainTex", (Texture)(object)DrawerMaterialTextures.GetAtLightness(tier, 0.16f)); } val4.AddComponent<BoxCollider>().size = new Vector3(0.66f, 0.66f, 0.66f); AddSnapPoints(val4, proportions); val4.AddComponent<ZNetView>().m_persistent = true; val4.AddComponent<DrawerComponent>(); if ((Object)(object)_sharedHandleMesh != (Object)null && flag3) { Material val9 = new Material(val7) { name = ((Object)val7).name + "_handle" }; val9.SetTexture("_MainTex", (Texture)(object)DrawerMaterialTextures.Metal()); if (val9.HasProperty("_BumpMap")) { val9.SetTexture("_BumpMap", (Texture)null); val9.DisableKeyword("_NORMALMAP"); } array = new string[2] { "_Glossiness", "_Smoothness" }; foreach (string text3 in array) { if (val9.HasProperty(text3)) { val9.SetFloat(text3, 0.65f); } } if (val9.HasProperty("_Metallic")) { val9.SetFloat("_Metallic", 0.8f); } GameObject val10 = new GameObject("handle"); val10.transform.SetParent(val4.transform, false); val10.AddComponent<MeshFilter>().sharedMesh = _sharedHandleMesh; MeshRenderer obj = val10.AddComponent<MeshRende