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 RossItemDrawers v1.0.7
plugins/ItemDrawers.Core.dll
Decompiled 4 hours 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+2fb60d9584e8b8b8ea0c17c4691cc1491e88cacf")] [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 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 RecipeSpec { public IReadOnlyList<(string Item, int Amount)> Requirements { get; } public string Error { get; } public bool Ok => Error == null; private RecipeSpec(IReadOnlyList<(string, int)> requirements, string error) { Requirements = requirements; Error = error; } public static RecipeSpec Parse(string text) { if (string.IsNullOrWhiteSpace(text)) { return Fail("recipe is empty"); } List<(string, int)> list = new List<(string, int)>(); HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); string[] array = text.Split(','); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length != 0) { int num = text2.IndexOf(':'); if (num <= 0) { return Fail("'" + text2 + "' is not Item:Count"); } string text3 = text2.Substring(0, num).Trim(); string s = text2.Substring(num + 1).Trim(); if (text3.Length == 0) { return Fail("'" + text2 + "' has no item name"); } if (!int.TryParse(s, out var result)) { return Fail("'" + text2 + "' has a non-numeric count"); } if (result <= 0) { return Fail("'" + text2 + "' must have a count above zero"); } if (!hashSet.Add(text3)) { return Fail("'" + text3 + "' is listed more than once"); } list.Add((text3, result)); } } if (list.Count == 0) { return Fail("recipe is empty"); } return new RecipeSpec(list, null); } public static string Format(IReadOnlyList<(string Item, int Amount)> requirements) { List<string> list = new List<string>(requirements.Count); foreach (var requirement in requirements) { list.Add($"{requirement.Item}:{requirement.Amount}"); } return string.Join(",", list); } private static RecipeSpec Fail(string error) { return new RecipeSpec(Array.Empty<(string, int)>(), error); } } 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 readonly struct StackSplitPlan { public readonly int[] TopUps; public readonly int[] NewStacks; public readonly int Remainder; public int Placed { get { int num = 0; int[] topUps = TopUps; foreach (int num2 in topUps) { num += num2; } topUps = NewStacks; foreach (int num3 in topUps) { num += num3; } return num; } } public StackSplitPlan(int[] topUps, int[] newStacks, int remainder) { TopUps = topUps; NewStacks = newStacks; Remainder = remainder; } } public static class StackSplit { public static StackSplitPlan Plan(IReadOnlyList<int> partialFreeSpace, int emptySlots, int incoming, int maxStackSize, bool firstStackToTarget) { int num = ((maxStackSize < 1) ? 1 : maxStackSize); int num2 = partialFreeSpace?.Count ?? 0; int[] array = new int[num2]; List<int> list = new List<int>(); int num3 = ((incoming >= 0) ? incoming : 0); int num4 = ((emptySlots >= 0) ? emptySlots : 0); if (firstStackToTarget && num3 > 0 && num4 > 0) { int num5 = ((num3 < num) ? num3 : num); list.Add(num5); num3 -= num5; num4--; } for (int i = 0; i < num2; i++) { if (num3 <= 0) { break; } int num6 = partialFreeSpace[i]; if (num6 > 0) { num3 -= (array[i] = ((num3 < num6) ? num3 : num6)); } } while (num3 > 0 && num4 > 0) { int num7 = ((num3 < num) ? num3 : num); list.Add(num7); num3 -= num7; num4--; } return new StackSplitPlan(array, list.ToArray(), num3); } } 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 } public enum ViewFlushAction { Wait, Claim, Reconcile } public static class ViewFlushPolicy { public const float SettleSeconds = 1f; public const float ClaimRetrySeconds = 2f; public static bool MayWriteAfterOwnerChange(float ownerRevisionAge, long previousOwner, long thisPeer) { if (previousOwner == 0L) { return true; } if (previousOwner == thisPeer) { return true; } return ownerRevisionAge >= 1f; } public static ViewFlushAction Decide(bool isOwner, float ownerRevisionAge, bool claimAlreadyMade, float jitterSeconds) { if (isOwner) { if (!(ownerRevisionAge >= 1f)) { return ViewFlushAction.Wait; } return ViewFlushAction.Reconcile; } if (!claimAlreadyMade) { return ViewFlushAction.Claim; } if (!(ownerRevisionAge >= 2f + jitterSeconds)) { return ViewFlushAction.Wait; } return ViewFlushAction.Claim; } } public static class ViewLayout { public const int DefaultSlotCount = 8; public static int[] Compute(bool assigned, int amount, int capacity, int maxStackSize, int slotCount = 8) { if (!assigned || amount <= 0 || slotCount <= 0) { return Array.Empty<int>(); } int num = ((maxStackSize < 1) ? 1 : maxStackSize); long num2 = (long)capacity - (long)amount; long num3 = ((num2 < 0) ? 0 : num2); for (int num4 = ((amount < slotCount) ? amount : slotCount); num4 >= 2; num4--) { int[] array = Distribute(amount, num, num4, num3); if (array != null && Room(array, num) <= num3) { return array; } } return new int[1] { amount }; } public static long Room(IReadOnlyList<int> slots, int maxStackSize) { int num = ((maxStackSize < 1) ? 1 : maxStackSize); long num2 = 0L; for (int i = 0; i < slots.Count; i++) { if (slots[i] < num) { num2 += num - slots[i]; } } return num2; } private static int[] Distribute(int amount, int max, int n, long allowedRoom) { int num = n - 1; long num2 = (long)num * (long)max - allowedRoom; long num3 = ((num2 > num) ? num2 : num); if (num3 > amount - 1) { return null; } int num4 = (int)(num3 / num); int num5 = (int)(num3 % num); int[] array = new int[n]; array[0] = amount - (int)num3; for (int i = 1; i < n; i++) { array[i] = num4 + ((i - 1 < num5) ? 1 : 0); } return array; } } public readonly struct ViewReconcileOutcome { public readonly DrawerSnapshot Result; public readonly int Credited; public readonly int Debited; public readonly int SpillDrawerItem; public readonly int SpillForeign; public readonly int Unbacked; public bool AmountChanged { get { if (Credited <= 0) { return Debited > 0; } return true; } } public ViewReconcileOutcome(DrawerSnapshot result, int credited, int debited, int spillDrawerItem, int spillForeign, int unbacked) { Result = result; Credited = credited; Debited = debited; SpillDrawerItem = spillDrawerItem; SpillForeign = spillForeign; Unbacked = unbacked; } } public static class ViewReconciliation { public static ViewReconcileOutcome Apply(DrawerSnapshot current, int capacity, int baseline, int viewItemTotal, int foreignCount) { int spillForeign = ((foreignCount >= 0) ? foreignCount : 0); long num = (long)((viewItemTotal >= 0) ? viewItemTotal : 0) - (long)((baseline >= 0) ? baseline : 0); if (num > 0) { int num2 = (int)((num > int.MaxValue) ? int.MaxValue : num); DrawerOutcome drawerOutcome = DrawerState.Deposit(current, capacity, current.ItemName, num2); int num3 = (drawerOutcome.Accepted ? drawerOutcome.MovedToDrawer : 0); return new ViewReconcileOutcome(drawerOutcome.Accepted ? drawerOutcome.Result : current, num3, 0, DrawerState.RefundShortfall(num2, num3), spillForeign, 0); } if (num < 0) { int num4 = (int)((-num > int.MaxValue) ? int.MaxValue : (-num)); DrawerOutcome drawerOutcome2 = DrawerState.WithdrawExact(current, num4); int movedToPlayer = drawerOutcome2.MovedToPlayer; return new ViewReconcileOutcome(drawerOutcome2.Result, 0, movedToPlayer, 0, spillForeign, num4 - movedToPlayer); } return new ViewReconcileOutcome(current, 0, 0, 0, spillForeign, 0); } } }
plugins/ItemDrawers.dll
Decompiled 4 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; 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 Jotunn.Utils; 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("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+2fb60d9584e8b8b8ea0c17c4691cc1491e88cacf")] [assembly: AssemblyProduct("ItemDrawers")] [assembly: AssemblyTitle("ItemDrawers")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.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 bool Prefix(Container __instance, ref Inventory __result) { if (!(__instance is DrawerComponent drawerComponent)) { return true; } __result = drawerComponent.GetViewInventory(); return false; } } [HarmonyPatch(typeof(Container), "Save")] private static class SavePatch { private static bool Prepare() { return ValheimCompat.RequireMethod(typeof(Container), "Save"); } private static bool Prefix(Container __instance) { if (!(__instance is DrawerComponent drawerComponent)) { return true; } drawerComponent.SaveView(); return false; } } [HarmonyPatch(typeof(Container), "Load")] private static class LoadPatch { private static bool Prepare() { return ValheimCompat.RequireMethod(typeof(Container), "Load"); } private static bool Prefix(Container __instance, ref bool __result) { if (!(__instance is DrawerComponent drawerComponent)) { return true; } __result = drawerComponent.LoadView(); return false; } } private static bool? _viewPatchesApplied; internal static bool ViewPatchesApplied { get { if (!_viewPatchesApplied.HasValue) { _viewPatchesApplied = HasOwnPrefix("GetInventory") && HasOwnPrefix("Save") && HasOwnPrefix("Load"); } return _viewPatchesApplied.Value; } } private static bool HasOwnPrefix(string methodName) { MethodInfo methodInfo = AccessTools.Method(typeof(Container), methodName, (Type[])null, (Type[])null); Patches val = ((methodInfo == null) ? null : Harmony.GetPatchInfo((MethodBase)methodInfo)); if (val == null) { return false; } foreach (Patch prefix in val.Prefixes) { if (prefix.owner == "com.rossdwest.itemdrawers") { return true; } } return false; } } 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; public static ConsoleEvent <>9__2_2; public static ConsoleEvent <>9__2_3; public static ConsoleEvent <>9__2_4; 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}"); } internal void <Register>b__2_2(ConsoleEventArgs args) { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00ce: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { args.Context.AddString("no local player"); return; } float num = 20f; if (args.Length > 1 && float.TryParse(args[1], out var result)) { num = result; } long sessionID = ZDOMan.GetSessionID(); args.Context.AddString($"my session id : {sessionID}"); args.Context.AddString("name zdoAmount owner isOwner viewCount"); int num2 = 0; int num3 = 0; foreach (DrawerComponent item in DrawerComponent.All) { if ((Object)(object)item == (Object)null) { continue; } Vector3 val = ((Component)item).transform.position - ((Component)localPlayer).transform.position; if (((Vector3)(ref val)).sqrMagnitude > num * num) { continue; } DrawerSnapshot snapshot = item.Snapshot; ZNetView component = ((Component)item).GetComponent<ZNetView>(); ZDO val2 = (((Object)(object)component != (Object)null) ? component.GetZDO() : null); long num4 = ((val2 != null) ? val2.GetOwner() : (-1)); bool flag = (Object)(object)component != (Object)null && component.IsValid() && component.IsOwner(); bool flag2 = item.View != null && item.View.CannotResolve(snapshot); Inventory inventory = ((Container)item).GetInventory(); int num5 = 0; if (inventory != null) { foreach (ItemData allItem in inventory.GetAllItems()) { num5 += allItem.m_stack; } } string text = ((num4 == 0L) ? "0 (nobody)" : ((num4 == sessionID) ? $"{num4} (me)" : num4.ToString())); args.Context.AddString(string.Format("{0} {1} {2} {3} ", ((DrawerSnapshot)(ref snapshot)).IsAssigned ? snapshot.ItemName : "<empty>", snapshot.Amount, text, flag) + (flag2 ? $"{num5} (item unresolved on this client)" : num5.ToString())); if (!flag2 && num5 != snapshot.Amount) { num3++; } num2++; } args.Context.AddString($"-- {num2} drawer(s) within {num}m, {num3} with a view change not yet reconciled"); } internal void <Register>b__2_3(ConsoleEventArgs args) { //IL_007d: 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_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_0329: Unknown result type (might be due to invalid IL or missing references) //IL_056b: Unknown result type (might be due to invalid IL or missing references) <>c__DisplayClass2_0 <>c__DisplayClass2_ = default(<>c__DisplayClass2_0); <>c__DisplayClass2_.args = args; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { <>c__DisplayClass2_.args.Context.AddString("no local player"); return; } float num = 40f; if (<>c__DisplayClass2_.args.Length > 1 && float.TryParse(<>c__DisplayClass2_.args[1], out var result)) { num = result; } Smelter val = null; float num2 = float.MaxValue; Smelter[] array = Object.FindObjectsByType<Smelter>((FindObjectsSortMode)0); foreach (Smelter val2 in array) { float num3 = Vector3.Distance(((Component)val2).transform.position, ((Component)localPlayer).transform.position); if (num3 < num2) { num2 = num3; val = val2; } } if ((Object)(object)val == (Object)null) { <Register>g__Out|2_5("no smelter/kiln loaded", ref <>c__DisplayClass2_); return; } ZNetView component = ((Component)val).GetComponent<ZNetView>(); <Register>g__Out|2_5($"smelter {((Object)val).name} at {num2:F1}m isOwner={(Object)(object)component != (Object)null && component.IsValid() && component.IsOwner()} " + $"maxOre={val.m_maxOre} queue={val.GetQueueSize()} Game.m_worldLevel={Game.m_worldLevel}", ref <>c__DisplayClass2_); foreach (ItemConversion item in val.m_conversion) { <Register>g__Out|2_5(" conversion from " + ((Object)item.m_from).name + " (" + item.m_from.m_itemData.m_shared.m_name + ")", ref <>c__DisplayClass2_); } IList list = null; list = (Type.GetType("OttoFuel.OttoFuelPlugin, OttoFuel")?.GetField("ContainerList", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(null) as IList; <Register>g__Out|2_5((list == null) ? "OttoFuel ContainerList: not found" : $"OttoFuel ContainerList: {list.Count} entries", ref <>c__DisplayClass2_); Container[] array2 = Object.FindObjectsByType<Container>((FindObjectsSortMode)0); foreach (Container val3 in array2) { float num4 = Vector3.Distance(((Component)val).transform.position, ((Component)val3).transform.position); if (num4 >= num) { continue; } Inventory inventory = val3.GetInventory(); ZNetView component2 = ((Component)val3).GetComponent<ZNetView>(); <Register>g__Out|2_5($"-- {((Object)val3).name} at {num4:F1}m from smelter", ref <>c__DisplayClass2_); <Register>g__Out|2_5(" inOttoList=" + ((list == null) ? "?" : list.Contains(val3).ToString()) + " " + $"pieceInParent={(Object)(object)((Component)val3).GetComponentInParent<Piece>() != (Object)null} inventoryNull={inventory == null} " + $"checkAccess={val3.CheckAccess(localPlayer.GetPlayerID())} inUse={val3.IsInUse()} " + $"wardAccess={PrivateArea.CheckAccess(((Component)val3).transform.position, 0f, false, false)} " + $"zdoValid={(Object)(object)component2 != (Object)null && component2.IsValid()} isOwner={(Object)(object)component2 != (Object)null && component2.IsValid() && component2.IsOwner()}", ref <>c__DisplayClass2_); if (inventory == null) { continue; } <Register>g__Out|2_5($" grid {inventory.GetWidth()}x{inventory.GetHeight()} items={inventory.GetAllItems().Count}", ref <>c__DisplayClass2_); val3.Load(); foreach (ItemConversion item2 in val.m_conversion) { List<ItemData> list2 = new List<ItemData>(); inventory.GetAllItems(item2.m_from.m_itemData.m_shared.m_name, list2); if (list2.Count == 0) { continue; } foreach (ItemData item3 in list2) { <Register>g__Out|2_5($" GetAllItems({item2.m_from.m_itemData.m_shared.m_name}): stack={item3.m_stack} worldLevel={item3.m_worldLevel} " + string.Format("dropPrefab={0} quality={1}", ((Object)(object)item3.m_dropPrefab != (Object)null) ? ((Object)item3.m_dropPrefab).name : "NULL", item3.m_quality), ref <>c__DisplayClass2_); } } foreach (ItemData allItem in inventory.GetAllItems()) { <Register>g__Out|2_5($" item {allItem.m_shared.m_name} stack={allItem.m_stack} worldLevel={allItem.m_worldLevel} " + string.Format("dropPrefab={0} pos={1}", ((Object)(object)allItem.m_dropPrefab != (Object)null) ? ((Object)allItem.m_dropPrefab).name : "NULL", allItem.m_gridPos), ref <>c__DisplayClass2_); } } } internal void <Register>b__2_4(ConsoleEventArgs args) { <>c__DisplayClass2_1 <>c__DisplayClass2_ = default(<>c__DisplayClass2_1); <>c__DisplayClass2_.args = args; if (<>c__DisplayClass2_.args.Length > 1 && <>c__DisplayClass2_.args[1] == "reset") { DrawerDiagnostics.Reset(); <>c__DisplayClass2_.args.Context.AddString("rid_diag: counters reset"); return; } <Register>g__Line|2_6($"refused (ownership unsettled) : {DrawerDiagnostics.RefusedUnsettled}", ref <>c__DisplayClass2_); <Register>g__Line|2_6($"ownership changes seen : {DrawerDiagnostics.OwnershipChanges}", ref <>c__DisplayClass2_); <Register>g__Line|2_6($"claims made by this client : {DrawerDiagnostics.ClaimsMade}", ref <>c__DisplayClass2_); <Register>g__Line|2_6($"unowned drawers claimed : {DrawerDiagnostics.UnownedClaims}", ref <>c__DisplayClass2_); <Register>g__Line|2_6($"withdrawals deferred : {DrawerDiagnostics.DeferredWithdraws}", ref <>c__DisplayClass2_); <Register>g__Line|2_6($"claims held for the player : {DrawerDiagnostics.ClaimsHeldForPlayer}", ref <>c__DisplayClass2_); <Register>g__Line|2_6($"withdraw requests sent : {DrawerDiagnostics.RequestsSent}", ref <>c__DisplayClass2_); <Register>g__Line|2_6($" granted : {DrawerDiagnostics.GrantsReceived}", ref <>c__DisplayClass2_); <Register>g__Line|2_6($" gave up : {DrawerDiagnostics.GrantsGivenUp}", ref <>c__DisplayClass2_); <Register>g__Line|2_6($" still outstanding : {DrawerDiagnostics.OutstandingRequests}", ref <>c__DisplayClass2_); <Register>g__Line|2_6($"grant latency mean/max ms : {DrawerDiagnostics.MeanGrantLatencyMs:F0} / {DrawerDiagnostics.MaxGrantLatencyMs:F0}", ref <>c__DisplayClass2_); } } [StructLayout(LayoutKind.Auto)] [CompilerGenerated] private struct <>c__DisplayClass2_0 { public ConsoleEventArgs args; } [StructLayout(LayoutKind.Auto)] [CompilerGenerated] private struct <>c__DisplayClass2_1 { public ConsoleEventArgs args; } 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 //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_00d4: Expected O, but got Unknown //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010d: 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 val6 = transform.position + transform.forward * 6f; Vector3 right = transform.right; int num3 = 0; DrawerProportions val7 = new DrawerProportions(); float num4 = val7.Width + 0.02f; float num5 = val7.Height + 0.02f; for (int i = 0; i < num2; i++) { for (int j = 0; j < num; j++) { Vector3 val8 = val6 + right * (((float)j - (float)(num - 1) / 2f) * num4) + Vector3.up * ((float)i * num5 + val7.Height / 2f); DrawerComponent component = Object.Instantiate<GameObject>(prefab, val8, 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); object obj3 = <>c.<>9__2_2; if (obj3 == null) { ConsoleEvent val3 = delegate(ConsoleEventArgs args) { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00ce: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { args.Context.AddString("no local player"); } else { float num = 20f; if (args.Length > 1 && float.TryParse(args[1], out var result)) { num = result; } long sessionID = ZDOMan.GetSessionID(); args.Context.AddString($"my session id : {sessionID}"); args.Context.AddString("name zdoAmount owner isOwner viewCount"); int num2 = 0; int num3 = 0; foreach (DrawerComponent item2 in DrawerComponent.All) { if (!((Object)(object)item2 == (Object)null)) { Vector3 val6 = ((Component)item2).transform.position - ((Component)localPlayer).transform.position; if (!(((Vector3)(ref val6)).sqrMagnitude > num * num)) { DrawerSnapshot snapshot = item2.Snapshot; ZNetView component = ((Component)item2).GetComponent<ZNetView>(); ZDO val7 = (((Object)(object)component != (Object)null) ? component.GetZDO() : null); long num4 = ((val7 != null) ? val7.GetOwner() : (-1)); bool flag = (Object)(object)component != (Object)null && component.IsValid() && component.IsOwner(); bool flag2 = item2.View != null && item2.View.CannotResolve(snapshot); Inventory inventory = ((Container)item2).GetInventory(); int num5 = 0; if (inventory != null) { foreach (ItemData allItem in inventory.GetAllItems()) { num5 += allItem.m_stack; } } string text = ((num4 == 0L) ? "0 (nobody)" : ((num4 == sessionID) ? $"{num4} (me)" : num4.ToString())); args.Context.AddString(string.Format("{0} {1} {2} {3} ", ((DrawerSnapshot)(ref snapshot)).IsAssigned ? snapshot.ItemName : "<empty>", snapshot.Amount, text, flag) + (flag2 ? $"{num5} (item unresolved on this client)" : num5.ToString())); if (!flag2 && num5 != snapshot.Amount) { num3++; } num2++; } } } args.Context.AddString($"-- {num2} drawer(s) within {num}m, {num3} with a view change not yet reconciled"); } }; <>c.<>9__2_2 = val3; obj3 = (object)val3; } new ConsoleCommand("rid_owners", "rid_owners [radius] - who owns nearby drawers, and what automation sees", (ConsoleEvent)obj3, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj4 = <>c.<>9__2_3; if (obj4 == null) { ConsoleEvent val4 = delegate(ConsoleEventArgs args) { //IL_007d: 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_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_0329: Unknown result type (might be due to invalid IL or missing references) //IL_056b: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { args.Context.AddString("no local player"); } else { float num = 40f; if (args.Length > 1 && float.TryParse(args[1], out var result)) { num = result; } Smelter val6 = null; float num2 = float.MaxValue; Smelter[] array = Object.FindObjectsByType<Smelter>((FindObjectsSortMode)0); foreach (Smelter val7 in array) { float num3 = Vector3.Distance(((Component)val7).transform.position, ((Component)localPlayer).transform.position); if (num3 < num2) { num2 = num3; val6 = val7; } } if ((Object)(object)val6 == (Object)null) { Out("no smelter/kiln loaded"); } else { ZNetView component = ((Component)val6).GetComponent<ZNetView>(); Out($"smelter {((Object)val6).name} at {num2:F1}m isOwner={(Object)(object)component != (Object)null && component.IsValid() && component.IsOwner()} " + $"maxOre={val6.m_maxOre} queue={val6.GetQueueSize()} Game.m_worldLevel={Game.m_worldLevel}"); foreach (ItemConversion item3 in val6.m_conversion) { Out(" conversion from " + ((Object)item3.m_from).name + " (" + item3.m_from.m_itemData.m_shared.m_name + ")"); } IList list = null; list = (Type.GetType("OttoFuel.OttoFuelPlugin, OttoFuel")?.GetField("ContainerList", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(null) as IList; Out((list == null) ? "OttoFuel ContainerList: not found" : $"OttoFuel ContainerList: {list.Count} entries"); Container[] array2 = Object.FindObjectsByType<Container>((FindObjectsSortMode)0); foreach (Container val8 in array2) { float num4 = Vector3.Distance(((Component)val6).transform.position, ((Component)val8).transform.position); if (!(num4 >= num)) { Inventory inventory = val8.GetInventory(); ZNetView component2 = ((Component)val8).GetComponent<ZNetView>(); Out($"-- {((Object)val8).name} at {num4:F1}m from smelter"); Out(" inOttoList=" + ((list == null) ? "?" : list.Contains(val8).ToString()) + " " + $"pieceInParent={(Object)(object)((Component)val8).GetComponentInParent<Piece>() != (Object)null} inventoryNull={inventory == null} " + $"checkAccess={val8.CheckAccess(localPlayer.GetPlayerID())} inUse={val8.IsInUse()} " + $"wardAccess={PrivateArea.CheckAccess(((Component)val8).transform.position, 0f, false, false)} " + $"zdoValid={(Object)(object)component2 != (Object)null && component2.IsValid()} isOwner={(Object)(object)component2 != (Object)null && component2.IsValid() && component2.IsOwner()}"); if (inventory != null) { Out($" grid {inventory.GetWidth()}x{inventory.GetHeight()} items={inventory.GetAllItems().Count}"); val8.Load(); foreach (ItemConversion item4 in val6.m_conversion) { List<ItemData> list2 = new List<ItemData>(); inventory.GetAllItems(item4.m_from.m_itemData.m_shared.m_name, list2); if (list2.Count != 0) { foreach (ItemData item5 in list2) { Out($" GetAllItems({item4.m_from.m_itemData.m_shared.m_name}): stack={item5.m_stack} worldLevel={item5.m_worldLevel} " + string.Format("dropPrefab={0} quality={1}", ((Object)(object)item5.m_dropPrefab != (Object)null) ? ((Object)item5.m_dropPrefab).name : "NULL", item5.m_quality)); } } } foreach (ItemData allItem2 in inventory.GetAllItems()) { Out($" item {allItem2.m_shared.m_name} stack={allItem2.m_stack} worldLevel={allItem2.m_worldLevel} " + string.Format("dropPrefab={0} pos={1}", ((Object)(object)allItem2.m_dropPrefab != (Object)null) ? ((Object)allItem2.m_dropPrefab).name : "NULL", allItem2.m_gridPos)); } } } } } } void Out(string line) { args.Context.AddString(line); Debug.Log((object)("[rid_probe] " + line)); } }; <>c.<>9__2_3 = val4; obj4 = (object)val4; } new ConsoleCommand("rid_probe", "rid_probe [range] - replay OttoFuel's container checks for the nearest smelter/kiln", (ConsoleEvent)obj4, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj5 = <>c.<>9__2_4; if (obj5 == null) { ConsoleEvent val5 = delegate(ConsoleEventArgs args) { if (args.Length > 1 && args[1] == "reset") { DrawerDiagnostics.Reset(); args.Context.AddString("rid_diag: counters reset"); } else { Line($"refused (ownership unsettled) : {DrawerDiagnostics.RefusedUnsettled}"); Line($"ownership changes seen : {DrawerDiagnostics.OwnershipChanges}"); Line($"claims made by this client : {DrawerDiagnostics.ClaimsMade}"); Line($"unowned drawers claimed : {DrawerDiagnostics.UnownedClaims}"); Line($"withdrawals deferred : {DrawerDiagnostics.DeferredWithdraws}"); Line($"claims held for the player : {DrawerDiagnostics.ClaimsHeldForPlayer}"); Line($"withdraw requests sent : {DrawerDiagnostics.RequestsSent}"); Line($" granted : {DrawerDiagnostics.GrantsReceived}"); Line($" gave up : {DrawerDiagnostics.GrantsGivenUp}"); Line($" still outstanding : {DrawerDiagnostics.OutstandingRequests}"); Line($"grant latency mean/max ms : {DrawerDiagnostics.MeanGrantLatencyMs:F0} / {DrawerDiagnostics.MaxGrantLatencyMs:F0}"); } void Line(string text) { args.Context.AddString(text); DrawerPlugin.Log.LogInfo((object)("rid_diag: " + text)); } }; <>c.<>9__2_4 = val5; obj5 = (object)val5; } new ConsoleCommand("rid_diag", "rid_diag [reset] - withdraw contention counters since the last reset", (ConsoleEvent)obj5, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } [CompilerGenerated] internal static void <Register>g__Out|2_5(string line, ref <>c__DisplayClass2_0 P_1) { P_1.args.Context.AddString(line); Debug.Log((object)("[rid_probe] " + line)); } [CompilerGenerated] internal static void <Register>g__Line|2_6(string text, ref <>c__DisplayClass2_1 P_1) { P_1.args.Context.AddString(text); DrawerPlugin.Log.LogInfo((object)("rid_diag: " + text)); } } public class DrawerComponent : Container, Interactable, Hoverable { internal enum DepositRoute { Owned, Claiming, Foreign, Unavailable } 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 bool _loggedUnresolvedPending; private const float DeferredWithdrawTimeout = 3f; internal const float OwnershipSettleSeconds = 1f; private ushort _ownerRevisionSeen; private float _ownerRevisionSince; private long _previousOwner; private float _lastPlayerActionAt = float.NegativeInfinity; private float _viewClaimHeldSince = float.NegativeInfinity; private const float PlayerPriorityWindow = 2f; private const float ViewClaimHoldCap = 6f; private long _ownerSeen; private bool _viewClaimMade; private bool _reconcileDeferred; private string _deferredPriorItemName; internal ZDOID ZdoId => _zdoId; internal DrawerTier Tier { get; private set; } internal DrawerView View { 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 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 string ViewDiag { get { if (View == null) { return "no view"; } return View.Describe(); } } 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()) { return; } _zdoId = _view.GetZDO().m_uid; Tier = TierFromPrefabName(((Object)((Component)this).gameObject).name); ResetOwnershipClock(); 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; } if (InventoryAccess.Available) { View = new DrawerView(this, _view); } if (View != null && ContainerBridge.ViewPatchesApplied) { try { AccessTools.FieldRefAccess<Container, Inventory>((Container)(object)this, "m_inventory") = View.Inventory; } catch (Exception ex2) { DrawerPlugin.Log.LogError((object)("Could not set Container.m_inventory; mods that read it directly will not see this drawer. " + ex2.GetType().Name + ": " + ex2.Message)); } } EnsureCreator(); ((Container)this).Awake(); 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_003c: Unknown result type (might be due to invalid IL or missing references) FlushView(teardown: true); All.Remove(this); DrawerManager.Instance?.Unregister(this); if (!((ZDOID)(ref _zdoId)).IsNone()) { DrawerManager.Instance?.ResolvePendingForDrawer(_zdoId); } } private void OnDrawerDestroyed() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_view == (Object)null) && _view.IsOwner()) { ReconcileView(null, force: true); 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_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; } WriteState(next); ReconcileView(val.ItemName); return true; } private void WriteState(DrawerSnapshot next) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = _view.GetZDO(); zDO.Set(KeyPrefabHash, next.ItemName); zDO.Set(KeyAmountHash, next.Amount, false); DrawerManager.Instance?.MarkDirty(this); RefreshFace(); } 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_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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_006d: 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_005b: 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_0050: 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; } NotePlayerAction(); 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00d8: 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_00f9: 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; } NotePlayerAction(); DrawerSnapshot snapshot = Snapshot; if (((DrawerSnapshot)(ref snapshot)).IsAssigned) { return false; } if ((Object)(object)_view == (Object)null || !_view.IsValid()) { ((Character)val).Message((MessageType)2, "Try again", 0, (Sprite)null, false); return true; } if (RefuseWhileUnsettled(val)) { 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; } 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0182: 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 (RefuseWhileUnsettled(player)) { 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_view == (Object)null || !_view.IsValid() || requested <= 0) { return; } NotePlayerAction(); if (_view.IsOwner()) { if (!OwnershipSettled()) { DrawerManager instance = DrawerManager.Instance; if ((Object)(object)instance != (Object)null) { DrawerDiagnostics.DeferredWithdraws++; instance.DeferWithdraw(this, player, requested, 3f); return; } } WithdrawAsOwner(player, requested); return; } DrawerManager instance2 = DrawerManager.Instance; if ((Object)(object)instance2 == (Object)null) { return; } long owner = _view.GetZDO().GetOwner(); if (owner == 0L) { DrawerDiagnostics.UnownedClaims++; _view.ClaimOwnership(); if (_view.IsOwner()) { WithdrawAsOwner(player, requested); } else { ((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false); } } else { long id = instance2.NextRequestId(); instance2.AddPendingWithdrawal(id, new PendingWithdrawal(_zdoId, owner, player, requested, ((Component)player).transform.position)); SendWithdrawRequestRpc(id, owner, requested); } } internal bool TryCompleteDeferredWithdraw(Player player, int requested) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_view == (Object)null || !_view.IsValid()) { return true; } if (!_view.IsOwner()) { RequestWithdraw(player, Snapshot.ItemName, requested); return true; } if (!OwnershipSettled()) { return false; } WithdrawAsOwner(player, requested); return true; } private void WithdrawAsOwner(Player player, int requested) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_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_0019: 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_0025: 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_0034: 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) if (!RefuseWhileUnsettled(player)) { DrawerSnapshot snapshot = Snapshot; DrawerOutcome val = DrawerState.WithdrawExact(snapshot, requested); if (val.MovedToPlayer > 0 && WriteOwned(snapshot, val.Result)) { ItemFacts.GiveToPlayer(player, snapshot.ItemName, val.MovedToPlayer); } } } internal void SendWithdrawRequestRpc(long id, long targetOwner, int requested) { if ((Object)(object)_view != (Object)null && _view.IsValid()) { DrawerDiagnostics.RequestSent(id, Time.time); _view.InvokeRPC(targetOwner, "RID_ReqWithdraw", new object[2] { id, requested }); } } private void RPC_RequestWithdraw(long sender, long id, int requested) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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 }); } else { if (!OwnershipSettled()) { 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_00db: 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; } DrawerDiagnostics.GrantReceived(id, Time.time); 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) 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); bool num = OwnershipSettled(); if (!num) { ((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false); } int num2 = ((num && val.Accepted && WriteOwned(snapshot, val.Result)) ? val.MovedToDrawer : 0); int num3 = DrawerState.RefundShortfall(removed, num2); if (num3 > 0) { ItemFacts.GiveToPlayer(player, itemName, num3); } if (announce) { AnnounceDeposit(player, itemName, num2); } 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) 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 }); } else if (OwnershipSettled()) { 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_view == (Object)null || !_view.IsValid()) { return; } if (_view.IsOwner()) { if (!OwnershipSettled()) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Try again", 0, (Sprite)null, false); } } else { 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_0032: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_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) if (!((Object)(object)_view == (Object)null) && _view.IsValid() && _view.IsOwner() && OwnershipSettled()) { DrawerSnapshot snapshot = Snapshot; DrawerOutcome val = DrawerState.Clear(snapshot); if (val.Accepted) { WriteOwned(snapshot, val.Result); } } } public bool TryWithdrawExternally(int requested, out int taken) { //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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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) taken = 0; if ((Object)(object)_view == (Object)null || !_view.IsValid()) { return false; } if (!_view.IsOwner()) { _view.ClaimOwnership(); return false; } if (!OwnershipSettled()) { 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; } internal DepositRoute ResolveDepositRoute() { if ((Object)(object)_view == (Object)null || !_view.IsValid()) { return DepositRoute.Unavailable; } if (_view.IsOwner()) { if (!OwnershipSettled()) { return DepositRoute.Claiming; } return DepositRoute.Owned; } ZDO zDO = _view.GetZDO(); if (zDO == null) { return DepositRoute.Unavailable; } if (zDO.GetOwner() == 0L) { _view.ClaimOwnership(); return DepositRoute.Claiming; } return DepositRoute.Foreign; } internal bool TrySubmitForeignDeposit(string itemName, int amount, Vector3 refundPosition, out int submitted) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) submitted = 0; if (!ItemFacts.IsStorable(itemName)) { return false; } if ((Object)(object)_view == (Object)null || !_view.IsValid()) { return false; } ZDO zDO = _view.GetZDO(); if (zDO == null) { return false; } long owner = zDO.GetOwner(); if (owner == 0L) { return false; } DrawerOutcome val = DrawerState.Deposit(Snapshot, Capacity, itemName, amount); if (!val.Accepted || val.MovedToDrawer <= 0) { return false; } DrawerManager instance = DrawerManager.Instance; if ((Object)(object)instance == (Object)null) { return false; } long id = instance.NextRequestId(); instance.AddPendingDeposit(id, new PendingDeposit(_zdoId, owner, null, itemName, val.MovedToDrawer, refundPosition, announce: false)); SendDepositRequestRpc(id, owner, itemName, val.MovedToDrawer); submitted = val.MovedToDrawer; 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 Inventory GetViewInventory() { return View?.GetForCaller(); } internal void SaveView() { if (View != null && (View.IsDirty || View.HasUnflushedChange())) { View.MarkDirty(); } } internal bool LoadView() { if (View != null) { return View.RefreshFromZdo(); } return false; } private float ClaimJitterSeconds() { return Mathf.Abs((float)((ZDOMan.GetSessionID() ^ (((ZDOID)(ref _zdoId)).UserID * 31) ^ ((ZDOID)(ref _zdoId)).ID) % 500)) / 1000f; } private void NotePlayerAction() { _lastPlayerActionAt = Time.time; } private void ResetOwnershipClock() { _ownerRevisionSeen = (ushort)(((Object)(object)_view != (Object)null && _view.IsValid()) ? _view.GetZDO().OwnerRevision : 0); _ownerSeen = (((Object)(object)_view != (Object)null && _view.IsValid()) ? _view.GetZDO().GetOwner() : 0); _previousOwner = _ownerSeen; _ownerRevisionSince = Time.time; } private float OwnerRevisionAge() { ushort ownerRevision = _view.GetZDO().OwnerRevision; if (ownerRevision != _ownerRevisionSeen) { if (_ownerRevisionSeen != 0) { DrawerDiagnostics.OwnershipChanges++; } _previousOwner = _ownerSeen; _ownerSeen = _view.GetZDO().GetOwner(); _ownerRevisionSeen = ownerRevision; _ownerRevisionSince = Time.time; } return Time.time - _ownerRevisionSince; } private bool RefuseWhileUnsettled(Player player) { if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner() || OwnershipSettled()) { return false; } DrawerDiagnostics.RefusedUnsettled++; DrawerDiagnostics.LogRefusal(_previousOwner, ZDOMan.GetSessionID(), OwnerRevisionAge()); if (player != null) { ((Character)player).Message((MessageType)2, "Try again", 0, (Sprite)null, false); } return true; } internal bool OwnershipSettled() { if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner()) { return false; } return ViewFlushPolicy.MayWriteAfterOwnerChange(OwnerRevisionAge(), _previousOwner, ZDOMan.GetSessionID()); } internal void FlushView(bool teardown = false) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Invalid comparison between Unknown and I4 //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Invalid comparison between Unknown and I4 if (View == null || !View.IsDirty || (Object)(object)_view == (Object)null || !_view.IsValid()) { return; } if (!View.HasUnflushedChange()) { View.ClearDirty(); _viewClaimMade = false; return; } if (teardown) { View.WriteDeltaToZdo(); _viewClaimMade = false; return; } DrawerManager instance = DrawerManager.Instance; ViewFlushAction val = ViewFlushPolicy.Decide(_view.IsOwner(), OwnerRevisionAge(), _viewClaimMade, ClaimJitterSeconds()); if ((int)val == 1 && Time.time - _lastPlayerActionAt < 2f) { if (float.IsNegativeInfinity(_viewClaimHeldSince)) { _viewClaimHeldSince = Time.time; } if (Time.time - _viewClaimHeldSince < 6f) { DrawerDiagnostics.ClaimsHeldForPlayer++; instance?.MarkViewDirty(this); return; } } else { _viewClaimHeldSince = float.NegativeInfinity; } if ((int)val != 0) { if ((int)val == 1) { DrawerDiagnostics.ClaimsMade++; _view.ClaimOwnership(); _viewClaimMade = true; instance?.MarkViewDirty(this); } else { ReconcileView(); } } else { instance?.MarkViewDirty(this); } } internal bool ViewNeedsReconcile() { if (View != null && (Object)(object)_view != (Object)null && _view.IsValid() && _view.IsOwner()) { if (!_reconcileDeferred) { return View.NeedsReconcile(); } return true; } return false; } internal void ReconcileView(string priorItemName = null, bool force = false) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //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_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0155: 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_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) if (View == null || (Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner()) { return; } if (!force && !OwnershipSettled()) { _reconcileDeferred = true; if (!string.IsNullOrEmpty(priorItemName) && _deferredPriorItemName == null) { _deferredPriorItemName = priorItemName; } return; } if (priorItemName == null) { priorItemName = _deferredPriorItemName; } _reconcileDeferred = false; _deferredPriorItemName = null; _viewClaimMade = false; DrawerSnapshot snapshot = Snapshot; if (View.CannotResolve(snapshot)) { ReconcileUnresolved(snapshot); return; } _loggedUnresolvedPending = false; string itemName = ((!((DrawerSnapshot)(ref snapshot)).IsAssigned && !string.IsNullOrEmpty(priorItemName)) ? priorItemName : snapshot.ItemName); if (!View.TryReadForReconcile(itemName, out var itemTotal, out var baseline, out var foreign)) { View.Publish(snapshot); return; } if (itemTotal < 0) { baseline -= itemTotal; itemTotal = 0; } int num = 0; foreach (KeyValuePair<string, int> item in foreign) { num += item.Value; } ViewReconcileOutcome val = ViewReconciliation.Apply(snapshot, Capacity, baseline, itemTotal, num); if (!((DrawerSnapshot)(ref val.Result)).Equals(snapshot)) { WriteState(val.Result); } View.Publish(val.Result); Vector3 position = ((Component)this).transform.position; if (val.SpillDrawerItem > 0) { ItemFacts.SpillAtPosition(position, itemName, val.SpillDrawerItem); } foreach (KeyValuePair<string, int> item2 in foreign) { if ((Object)(object)ItemFacts.Prefab(item2.Key) != (Object)null) { ItemFacts.SpillAtPosition(position, item2.Key, item2.Value); } else { DrawerPlugin.Log.LogWarning((object)$"{DiagId}: {item2.Value} of unidentifiable item '{item2.Key}' left in the drawer's view could not be returned."); } } if (val.Unbacked > 0) { DrawerPlugin.Log.LogWarning((object)($"{DiagId}: {val.Unbacked} {snapshot.ItemName} were taken through the view beyond what the drawer held " + "(another player changed it at the same moment).")); } } private void ReconcileUnresolved(DrawerSnapshot current) { //IL_0006: 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_003a: Unknown result type (might be due to invalid IL or missing references) switch (View.InspectForUnresolvedOwner(current.Amount)) { case DrawerView.UnresolvedViewState.PendingChanges: if (!_loggedUnresolvedPending) { _loggedUnresolvedPending = true; DrawerPlugin.Log.LogWarning((object)(DiagId + ": this client cannot resolve item '" + current.ItemName + "', so a change made through the drawer's container view is left unreconciled for an owner that can.")); } break; case DrawerView.UnresolvedViewState.AlreadyPublished: break; default: View.Publish(current); break; } } 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_003c: 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) 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); string text = ((snapshot.Amount > 0) ? "[<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" : "[<color=yellow><b>Ctrl+E</b></color>] Unassign\n[<color=yellow><b>Shift+E</b></color>] Store all"); return Localization.instance.Localize($"{arg} <color=orange>{snapshot.Amount}</color>/{Capacity}\n" + text); } 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; } } [HarmonyPatch(typeof(Piece), "SetCreator")] internal static class PieceSetCreatorPatch { private static bool Prepare() { return ValheimCompat.RequireMethod(typeof(Piece), "SetCreator"); } private static void Prefix(Piece __instance, long uid) { if (__instance.m_creator == uid && (Object)(object)((Component)__instance).GetComponent<DrawerComponent>() != (Object)null) { __instance.m_creator = 0L; } } } 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; private static readonly Dictionary<DrawerTier, ConfigEntry<string>> Recipes = new Dictionary<DrawerTier, ConfigEntry<string>>(); 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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Expected O, but got Unknown //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Expected O, but got Unknown //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Expected O, but got Unknown //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Expected O, but got Unknown //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Expected O, but got Unknown //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: 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 } })); DrawerTier[] all = DrawerTiers.All; for (int i = 0; i < all.Length; i++) { DrawerTier drawerTier = all[i]; Recipes[drawerTier] = config.Bind<string>("Recipe", drawerTier.ToString(), RecipeSpec.Format(DrawerTiers.Recipe(drawerTier)), new ConfigDescription("Build cost, as Item:Count separated by commas -- e.g. FineWood:5,Stone:10. Names are PREFAB names (FineWood, BlackMarble, RoundLog), not the names shown in game. An unparseable or unknown-item recipe is logged and the default is used instead. Takes effect on restart.", (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 IReadOnlyList<(string Item, int Amount)> RecipeFor(DrawerTier tier) { IReadOnlyList<(string, int)> readOnlyList = DrawerTiers.Recipe(tier); if (!Recipes.TryGetValue(tier, out var value) || value == null) { return readOnlyList; } RecipeSpec val = RecipeSpec.Parse(value.Value); string text = (val.Ok ? UnknownItem(val.Requirements) : val.Error); if (text == null) { return val.Requirements; } DrawerPlugin.Log.LogWarning((object)($"Recipe.{tier} is not usable ({text}); using the default " + RecipeSpec.Format(readOnlyList) + " instead.")); return readOnlyList; } private static string UnknownItem(IReadOnlyList<(string Item, int Amount)> requirements) { PrefabManager instance = PrefabManager.Instance; if (instance == null) { return null; } foreach (var requirement in requirements) { if ((Object)(object)instance.GetPrefab(requirement.Item) == (Object)null) { return "no item named '" + requirement.Item + "'"; } } return null; } 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 DrawerDiagnostics { public static int RefusedUnsettled; public static int OwnershipChanges; public static int ClaimsMade; public static int RequestsSent; public static int UnownedClaims; public static int DeferredWithdraws; public static int ClaimsHeldForPlayer; public static int GrantsReceived; public static int GrantsGivenUp; private static double _grantLatencyTotalMs; private static double _grantLatencyMaxMs; private static readonly Dictionary<long, float> _sentAt = new Dictionary<long, float>(); private const int RefusalLogLimit = 15; private static int _refusalsLogged; public static double MeanGrantLatencyMs { get { if (GrantsReceived <= 0) { return 0.0; } return _grantLatencyTotalMs / (double)GrantsReceived; } } public static double MaxGrantLatencyMs => _grantLatencyMaxMs; public static int OutstandingRequests => _sentAt.Count; public static void RequestSent(long id, float now) { RequestsSent++; _sentAt[id] = now; } public static void GrantReceived(long id, float now) { GrantsReceived++; if (_sentAt.TryGetValue(id, out var value)) { _sentAt.Remove(id); double num = (double)(now - value) * 1000.0; _grantLatencyTotalMs += num; if (num > _grantLatencyMaxMs) { _grantLatencyMaxMs = num; } } } public static void RequestClosed(long id) { _sentAt.Remove(id); } public static void LogRefusal(long previousOwner, long thisPeer, float ownerRevisionAge) { if (_refusalsLogged < 15) { _refusalsLogged++; string arg = ((previousOwner == 0L) ? "nobody" : ((previousOwner == thisPeer) ? "this client" : $"peer {previousOwner}")); DrawerPlugin.Log.LogInfo((object)($"Withdraw refused ({RefusedUnsettled} so far): ownership came from {arg} " + $"{ownerRevisionAge:F2}s ago." + ((_refusalsLogged == 15) ? " Further refusals will not be logged; use rid_diag for totals." : ""))); } } public static void Reset() { RefusedUnsettled = 0; OwnershipChanges = 0; ClaimsMade = 0; RequestsSent = 0; UnownedClaims = 0; DeferredWithdraws = 0; ClaimsHeldForPlayer = 0; GrantsReceived = 0; GrantsGivenUp = 0; _grantLatencyTotalMs = 0.0; _grantLatencyMaxMs = 0.0; _sentAt.Clear(); _refusalsLogged = 0; } } 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_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Expected O, but got Unknown //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Expected O, but got Unknown //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0169: 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>(); List<string> list2 = new List<string>(); 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) { continue; } Sprite val2; try { val2 = ItemFacts.SafeIcon(val.m_itemData, out var variantOutOfRange); if (variantOutOfRange) { list2.Add(((Object)item).name); } } catch (Exception ex) { DrawerPlugin.Log.LogWarning((object)("Skipping '" + ((Object)item).name + "' in the icon atlas: reading its icon threw (" + ex.GetType().Name + ": " + ex.Message + ").")); continue; } if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.texture == (Object)null) && !dictionary.ContainsKey(((Object)item).name)) { dictionary[((Object)item).name] = val2; string name = ((Object)item).name; Rect textureRect = val2.textureRect; int num = (int)((Rect)(ref textureRect)).width; textureRect = val2.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