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 CDEV ChestUpgrade v0.1.0
plugins/CDEV.ChestUpgrade/CDEV.ChestUpgrade.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CDEV.ChestUpgrade.UI; using HarmonyLib; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("CDEV.ChestUpgrade")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+efb24945142928ac03192750576c1d4fe797e026")] [assembly: AssemblyProduct("CDEV.ChestUpgrade")] [assembly: AssemblyTitle("CDEV.ChestUpgrade")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CDEV.ChestUpgrade { internal static class ChestLevels { private sealed class Built { internal int Width; internal int Height; internal string Prefab; } internal const int BuiltLevel = 1; internal static readonly int LevelKey = StringExtensionMethods.GetStableHashCode("cdev.chestupgrade.level"); internal static readonly int BuiltKey = StringExtensionMethods.GetStableHashCode("cdev.chestupgrade.built"); private static readonly ConditionalWeakTable<Container, Built> BuiltSizes = new ConditionalWeakTable<Container, Built>(); private static HashSet<string> _excluded; private static List<float> _capacity; internal static int MaxLevel => 1 + Capacity().Count; internal static bool IsUpgradable(Container container) { if ((Object)(object)container == (Object)null || container.m_inventory == null || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid()) { return false; } if ((Object)(object)container.m_piece == (Object)null || (Object)(object)container.m_wagon != (Object)null || (Object)(object)container.m_rootObjectOverride != (Object)null || container.m_autoDestroyEmpty || container.m_nview.GetZDO().GetLong(ZDOVars.s_creator, 0L) == 0L || (Object)(object)((Component)container).GetComponent<TombStone>() != (Object)null) { return false; } return !Excluded().Contains(PrefabName(container)); } internal static string PrefabName(Container container) { if (BuiltSizes.TryGetValue(container, out var value) && value.Prefab != null) { return value.Prefab; } string prefabName = Utils.GetPrefabName(((Component)container).gameObject); if (value != null) { value.Prefab = prefabName; } return prefabName; } internal static int GetLevel(Container container) { ZDO val = (((Object)(object)container != (Object)null && (Object)(object)container.m_nview != (Object)null) ? container.m_nview.GetZDO() : null); if (val == null) { return 1; } return Mathf.Clamp(val.GetInt(LevelKey, 1), 1, MaxLevel); } internal static Vector2i SizeFor(int builtWidth, int builtHeight, int level) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: 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) List<float> list = Capacity(); level = Mathf.Clamp(level, 1, 1 + list.Count); int num = builtWidth * builtHeight; int num2 = Mathf.Max(builtWidth, ModConfig.MaxColumns.Value); float num3 = (float)ModConfig.CountTolerance.Value / 100f; Vector2i val = default(Vector2i); ((Vector2i)(ref val))..ctor(builtWidth, builtHeight); for (int i = 2; i <= level; i++) { float num4 = (float)num * list[i - 1 - 1]; int num5 = val.x * val.y; int num6 = 0; int num7 = 0; int num8 = 0; int num9 = 0; float num10 = float.MaxValue; float num11 = float.MaxValue; for (int j = val.x; j <= num2; j++) { int num12 = Mathf.Max(1, Mathf.FloorToInt(num4 / (float)j)); for (int k = num12; k <= num12 + 1; k++) { int num13 = j * k; if (num13 > num5) { float num14 = Mathf.Abs((float)num13 - num4); if (num6 == 0 || num14 < num10 - 0.001f || (Mathf.Abs(num14 - num10) <= 0.001f && (num13 > num6 * num7 || (num13 == num6 * num7 && j > num6)))) { num6 = j; num7 = k; num10 = num14; } if (num14 <= num3 * num4 + 0.001f && (num8 == 0 || j > num8 || num14 < num11 - 0.001f || (Mathf.Abs(num14 - num11) <= 0.001f && num13 > num8 * num9))) { num8 = j; num9 = k; num11 = num14; } } } } if (num8 > 0) { ((Vector2i)(ref val))..ctor(num8, num9); } else if (num6 > 0) { ((Vector2i)(ref val))..ctor(num6, num7); } else { ((Vector2i)(ref val))..ctor(val.x, num5 / val.x + 1); } } return val; } internal static Vector2i SizeFor(Container container, int level) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) Built built = BuiltSize(container); return SizeFor(built.Width, built.Height, level); } internal static int SlotsFor(Container container, int level) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) Vector2i val = SizeFor(container, level); return val.x * val.y; } internal static void RememberBuilt(Container container) { BuiltSizes.Remove(container); BuiltSizes.Add(container, new Built { Width = container.m_width, Height = container.m_height }); } internal static void StoreBuilt(Container container, ZDO zdo) { if (zdo.GetInt(BuiltKey, 0) == 0) { Built built = BuiltSize(container); zdo.Set(BuiltKey, built.Width * 1000 + built.Height, false); } } private static Built BuiltSize(Container container) { if (BuiltSizes.TryGetValue(container, out var value)) { return value; } ZDO val = (((Object)(object)container.m_nview != (Object)null) ? container.m_nview.GetZDO() : null); int num = ((val != null) ? val.GetInt(BuiltKey, 0) : 0); value = ((num > 0) ? new Built { Width = num / 1000, Height = num % 1000 } : new Built { Width = container.m_width, Height = container.m_height }); BuiltSizes.Remove(container); BuiltSizes.Add(container, value); return value; } internal static void Apply(Container container) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)container == (Object)null) && container.m_inventory != null && IsUpgradable(container)) { Vector2i val = SizeFor(container, GetLevel(container)); ChestVisuals.Refresh(container); if (container.m_width != val.x) { container.m_width = val.x; } if (container.m_height != val.y) { container.m_height = val.y; } Inventory inventory = container.m_inventory; int num = val.x; List<ItemData> allItems = inventory.GetAllItems(); for (int i = 0; i < allItems.Count; i++) { num = Mathf.Max(num, allItems[i].m_gridPos.x + 1); } if (inventory.m_width < num) { inventory.m_width = num; } if (inventory.GetHeight() < val.y) { inventory.SetHeight(val.y); } } } internal static void InvalidateExcluded() { _excluded = null; } internal static void InvalidateCapacity() { _capacity = null; } private static List<float> Capacity() { if (_capacity != null) { return _capacity; } List<float> list = new List<float>(); string[] array = ModConfig.CapacityByLevel.Value.Split(new char[3] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { if (float.TryParse(text.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && result > 1f && list.Count < 9) { list.Add(result); } } if (list.Count == 0) { list.AddRange(new float[3] { 1.5f, 2f, 3f }); } _capacity = list; return _capacity; } private static HashSet<string> Excluded() { if (_excluded == null) { _excluded = new HashSet<string>(StringComparer.OrdinalIgnoreCase); string[] array = ModConfig.ExcludedChests.Value.Split(new char[3] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { _excluded.Add(text.Trim()); } } return _excluded; } } internal sealed class ChestVisuals : MonoBehaviour { private sealed class Shape { internal Bounds Bounds; internal Vector3[] Vertices; internal int[] Triangles; internal readonly Dictionary<int, List<Vector2>> Hulls = new Dictionary<int, List<Vector2>>(); } private const float ChainWidth = 0.05f; private const float MeshWidth = 0.17f; private const float MeshLength = 0.96f; private const float CullScreenHeight = 0.03f; private static readonly Color[] Tint = (Color[])(object)new Color[3] { new Color(0.62f, 0.38f, 0.2f), new Color(0.45f, 0.52f, 0.72f), new Color(0.78f, 0.62f, 0.28f) }; private static readonly List<ChestVisuals> Instances = new List<ChestVisuals>(); private const int ChecksPerFrame = 16; private static int _cursor; private static readonly Dictionary<string, Shape> Shapes = new Dictionary<string, Shape>(); private static readonly Dictionary<int, Material> Materials = new Dictionary<int, Material>(); private static Mesh _chainMesh; private static Material _chainMaterial; private static bool _searched; private Container _container; private GameObject _trim; private Mesh _merged; private int _shownLevel = -1; private uint _seenRevision = uint.MaxValue; internal static void Attach(Container container) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 if (!((Object)(object)container == (Object)null) && (int)SystemInfo.graphicsDeviceType != 4 && !((Object)(object)((Component)container).GetComponent<ChestVisuals>() != (Object)null)) { ChestVisuals chestVisuals = ((Component)container).gameObject.AddComponent<ChestVisuals>(); chestVisuals._container = container; Instances.Add(chestVisuals); chestVisuals.Show(); } } internal static void Refresh(Container container) { ChestVisuals chestVisuals = default(ChestVisuals); if ((Object)(object)container != (Object)null && ((Component)container).TryGetComponent<ChestVisuals>(ref chestVisuals)) { chestVisuals.Show(); } } internal static void RefreshAll() { foreach (ChestVisuals instance in Instances) { if ((Object)(object)instance != (Object)null) { instance.Show(); } } } internal static void Tick() { int count = Instances.Count; for (int i = 0; i < 16 && i < count; i++) { if (_cursor >= Instances.Count) { _cursor = 0; } ChestVisuals chestVisuals = Instances[_cursor++]; if (!((Object)(object)chestVisuals == (Object)null) && !((Object)(object)chestVisuals._container == (Object)null) && !((Object)(object)chestVisuals._container.m_nview == (Object)null)) { ZDO zDO = chestVisuals._container.m_nview.GetZDO(); if (zDO != null && zDO.DataRevision != chestVisuals._seenRevision) { chestVisuals._seenRevision = zDO.DataRevision; ChestLevels.Apply(chestVisuals._container); chestVisuals.Show(); } } } } private void Show() { int num = ((!ModConfig.ShowLevelOnChest.Value || !ChestLevels.IsUpgradable(_container)) ? 1 : ChestLevels.GetLevel(_container)); if (num != _shownLevel) { _shownLevel = num; Clear(); if (num > 1) { Build(num); } } } private void Clear() { if ((Object)(object)_trim != (Object)null) { Object.Destroy((Object)(object)_trim); _trim = null; } if ((Object)(object)_merged != (Object)null) { Object.Destroy((Object)(object)_merged); _merged = null; } } private void OnDestroy() { Instances.Remove(this); Clear(); } private void Build(int level) { //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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Expected O, but got Unknown //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Expected O, but got Unknown //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Expected O, but got Unknown //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_0309: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) Material val = MaterialFor(level); Shape shape = ShapeOf(); if ((Object)(object)val == (Object)null || shape == null) { return; } Bounds bounds = shape.Bounds; float num = 0.29411766f; float segment = 0.96f * num; float offset = 0.025f; float anchorY = ((Bounds)(ref bounds)).min.y + ((Bounds)(ref bounds)).size.y * 0.84f; float num2 = ((Bounds)(ref bounds)).size.y * 0.6f; Vector2 centre = default(Vector2); ((Vector2)(ref centre))..ctor(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).center.z); float num3 = Mathf.Atan2(((Bounds)(ref bounds)).extents.z, ((Bounds)(ref bounds)).extents.x); float[] array = new float[4] { num3, (float)Math.PI - num3, (float)Math.PI + num3, (float)Math.PI * 2f - num3 }; Random random = new Random(((object)Unsafe.As<ZDOID, ZDOID>(ref (((Object)(object)_container.m_nview != (Object)null) ? _container.m_nview.GetZDO() : null)?.m_uid)/*cast due to .constrained prefix*/).GetHashCode() ?? 0); List<Matrix4x4> list = new List<Matrix4x4>(); int num4 = level - 1; for (int i = 0; i < num4; i++) { for (int j = 0; j < 4; j++) { float sag = num2 * (0.16f + 0.2f * (float)i) * (0.85f + 0.3f * (float)random.NextDouble()); float toAngle = ((j == 3) ? (array[0] + (float)Math.PI * 2f) : array[j + 1]); Hang(list, shape, centre, array[j], toAngle, anchorY, sag, num, segment, offset); } } _trim = new GameObject("CDEV_ChestUpgrade_Chains"); _trim.layer = ((Component)this).gameObject.layer; _trim.transform.SetParent(((Component)this).transform, false); List<Renderer> list2 = new List<Renderer>(); if (_chainMesh.isReadable) { CombineInstance[] array2 = (CombineInstance[])(object)new CombineInstance[list.Count]; for (int k = 0; k < list.Count; k++) { int num5 = k; CombineInstance val2 = default(CombineInstance); ((CombineInstance)(ref val2)).mesh = _chainMesh; ((CombineInstance)(ref val2)).transform = list[k]; array2[num5] = val2; } _merged = new Mesh { name = "CDEV_ChestUpgrade_Chains", indexFormat = (IndexFormat)1 }; _merged.CombineMeshes(array2, true, true); list2.Add(AddRenderer(_trim, _merged, val)); } else { foreach (Matrix4x4 item in list) { Matrix4x4 current = item; GameObject val3 = new GameObject("Chain") { layer = ((Component)this).gameObject.layer }; val3.transform.SetParent(_trim.transform, false); val3.transform.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref current)).GetColumn(3)); val3.transform.localRotation = ((Matrix4x4)(ref current)).rotation; val3.transform.localScale = ((Matrix4x4)(ref current)).lossyScale; list2.Add(AddRenderer(val3, _chainMesh, val)); } } LODGroup val4 = _trim.AddComponent<LODGroup>(); val4.SetLODs((LOD[])(object)new LOD[1] { new LOD(0.03f, list2.ToArray()) }); val4.RecalculateBounds(); } private static Renderer AddRenderer(GameObject go, Mesh mesh, Material material) { go.AddComponent<MeshFilter>().sharedMesh = mesh; MeshRenderer val = go.AddComponent<MeshRenderer>(); ((Renderer)val).sharedMaterial = material; ((Renderer)val).shadowCastingMode = (ShadowCastingMode)0; return (Renderer)(object)val; } private static void Hang(List<Matrix4x4> pieces, Shape shape, Vector2 centre, float fromAngle, float toAngle, float anchorY, float sag, float scale, float segment, float offset) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: 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_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017d: 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) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) Vector3[] array = (Vector3[])(object)new Vector3[33]; float[] array2 = new float[33]; Vector2 val = default(Vector2); for (int i = 0; i <= 32; i++) { float num = (float)i / 32f; float num2 = anchorY - sag * 4f * num * (1f - num); float num3 = Mathf.Lerp(fromAngle, toAngle, num); ((Vector2)(ref val))..ctor(Mathf.Cos(num3), Mathf.Sin(num3)); Vector2 val2 = Outline(shape, centre, val, num2) + val * offset; array[i] = new Vector3(val2.x, num2, val2.y); array2[i] = ((i == 0) ? 0f : (array2[i - 1] + Vector3.Distance(array[i - 1], array[i]))); } float num4 = array2[32]; if (num4 < 0.01f) { return; } int num5 = Mathf.Max(1, Mathf.RoundToInt(num4 / segment)); for (int j = 0; j < num5; j++) { Vector3 val3 = PointAt(array, array2, num4 * (float)j / (float)num5); Vector3 val4 = PointAt(array, array2, num4 * (float)(j + 1) / (float)num5); Vector3 val5 = val4 - val3; float magnitude = ((Vector3)(ref val5)).magnitude; if (!(magnitude < 0.001f)) { Quaternion val6 = Quaternion.FromToRotation(Vector3.up, val5 / magnitude) * Quaternion.AngleAxis((j % 2 == 0) ? 0f : 90f, Vector3.up); pieces.Add(Matrix4x4.TRS((val3 + val4) / 2f, val6, new Vector3(scale, magnitude / 0.96f, scale))); } } } private static Vector3 PointAt(Vector3[] points, float[] lengths, float distance) { //IL_0052: 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_001f: 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) for (int i = 1; i < points.Length; i++) { if (lengths[i] >= distance) { float num = lengths[i] - lengths[i - 1]; return Vector3.Lerp(points[i - 1], points[i], (num > 0f) ? ((distance - lengths[i - 1]) / num) : 0f); } } return points[^1]; } private static Vector2 Outline(Shape shape, Vector2 centre, Vector2 dir, float y) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0137: 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) List<Vector2> list = HullAt(shape, y); if (list != null) { float num = -1f; for (int i = 0; i < list.Count; i++) { if (RaySegment(centre, dir, list[i], list[(i + 1) % list.Count], out var dist) && dist > num) { num = dist; } } if (num > 0f) { return centre + dir * num; } } Bounds bounds = shape.Bounds; float num2 = Mathf.Max(0.05f, ((Bounds)(ref bounds)).extents.x - Mathf.Min(0.07f, ((Bounds)(ref bounds)).extents.x * 0.1f)); float num3 = Mathf.Max(0.05f, ((Bounds)(ref bounds)).extents.z - Mathf.Min(0.07f, ((Bounds)(ref bounds)).extents.z * 0.1f)); float num4 = ((Mathf.Abs(dir.x) > 0.0001f) ? (num2 / Mathf.Abs(dir.x)) : float.MaxValue); float num5 = ((Mathf.Abs(dir.y) > 0.0001f) ? (num3 / Mathf.Abs(dir.y)) : float.MaxValue); return centre + dir * Mathf.Min(num4, num5); } private static bool RaySegment(Vector2 origin, Vector2 dir, Vector2 a, Vector2 c, out float dist) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) dist = 0f; Vector2 val = c - a; float num = dir.x * val.y - dir.y * val.x; if (Mathf.Abs(num) < 1E-06f) { return false; } Vector2 val2 = a - origin; float num2 = (val2.x * val.y - val2.y * val.x) / num; float num3 = (val2.x * dir.y - val2.y * dir.x) / num; if (num2 < 0f || num3 < -0.0001f || num3 > 1.0001f) { return false; } dist = num2; return true; } private static List<Vector2> HullAt(Shape shape, float y) { //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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: 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_0150: 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_015e: Unknown result type (might be due to invalid IL or missing references) if (shape.Vertices == null) { return null; } int key = Mathf.RoundToInt(y * 100f); if (shape.Hulls.TryGetValue(key, out var value)) { return value; } Vector3[] vertices = shape.Vertices; int[] triangles = shape.Triangles; List<Vector2> list = new List<Vector2>(); for (int i = 0; i + 2 < triangles.Length; i += 3) { for (int j = 0; j < 3; j++) { Vector3 val = vertices[triangles[i + j]]; Vector3 val2 = vertices[triangles[i + (j + 1) % 3]]; if ((val.y - y) * (val2.y - y) <= 0f && Mathf.Abs(val.y - val2.y) > 1E-05f) { Vector3 val3 = Vector3.Lerp(val, val2, (y - val.y) / (val2.y - val.y)); list.Add(new Vector2(val3.x, val3.z)); } } } List<Vector2> list2 = ((list.Count >= 3) ? ConvexHull(list) : null); float num = 0.04f; while (num <= 0.32f && (list2 == null || list2.Count < 3)) { list.Clear(); Vector3[] array = vertices; foreach (Vector3 val4 in array) { if (Mathf.Abs(val4.y - y) <= num) { list.Add(new Vector2(val4.x, val4.z)); } } list2 = ((list.Count >= 3) ? ConvexHull(list) : null); num *= 2f; } if (list2 != null && list2.Count < 3) { list2 = null; } shape.Hulls[key] = list2; return list2; } private static List<Vector2> ConvexHull(List<Vector2> pts) { //IL_005c: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_009a: Unknown result type (might be due to invalid IL or missing references) pts.Sort((Vector2 p, Vector2 q) => (p.x == q.x) ? p.y.CompareTo(q.y) : p.x.CompareTo(q.x)); List<Vector2> list = new List<Vector2>(pts.Count + 1); for (int num = 0; num < 2; num++) { int count = list.Count; for (int num2 = 0; num2 < pts.Count; num2++) { Vector2 val = ((num == 0) ? pts[num2] : pts[pts.Count - 1 - num2]); while (list.Count >= count + 2 && Cross(list[list.Count - 2], list[list.Count - 1], val) <= 0f) { list.RemoveAt(list.Count - 1); } list.Add(val); } list.RemoveAt(list.Count - 1); } return list; } private static float Cross(Vector2 o, Vector2 a, Vector2 b) { //IL_0000: 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_000d: 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_001b: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) return (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x); } private Shape ShapeOf() { //IL_0031: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: 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_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) string key = ChestLevels.PrefabName(_container); if (Shapes.TryGetValue(key, out var value)) { return value; } List<Vector3> list = new List<Vector3>(); List<int> list2 = new List<int>(); bool flag = true; bool flag2 = false; Bounds bounds = default(Bounds); Matrix4x4 worldToLocalMatrix = ((Component)this).transform.worldToLocalMatrix; MeshFilter[] componentsInChildren = ((Component)this).GetComponentsInChildren<MeshFilter>(false); foreach (MeshFilter val in componentsInChildren) { MeshRenderer component = ((Component)val).GetComponent<MeshRenderer>(); if ((Object)(object)val.sharedMesh == (Object)null || (Object)(object)component == (Object)null || !((Renderer)component).enabled || (int)((Renderer)component).shadowCastingMode == 0 || ((Object)(object)_trim != (Object)null && ((Component)val).transform.IsChildOf(_trim.transform)) || ((Object)(object)_container.m_closed != (Object)null && ((Component)val).transform.IsChildOf(_container.m_closed.transform)) || ((Object)(object)_container.m_open != (Object)null && ((Component)val).transform.IsChildOf(_container.m_open.transform)) || ((Object)val).name.IndexOf("top", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)val).name.IndexOf("lod", StringComparison.OrdinalIgnoreCase) >= 0) { continue; } Mesh sharedMesh = val.sharedMesh; Matrix4x4 val2 = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix; Bounds bounds2 = sharedMesh.bounds; for (int j = 0; j < 8; j++) { Vector3 val3 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(new Vector3(((j & 1) == 0) ? ((Bounds)(ref bounds2)).min.x : ((Bounds)(ref bounds2)).max.x, ((j & 2) == 0) ? ((Bounds)(ref bounds2)).min.y : ((Bounds)(ref bounds2)).max.y, ((j & 4) == 0) ? ((Bounds)(ref bounds2)).min.z : ((Bounds)(ref bounds2)).max.z)); if (!flag2) { ((Bounds)(ref bounds))..ctor(val3, Vector3.zero); flag2 = true; } else { ((Bounds)(ref bounds)).Encapsulate(val3); } } if (!flag || !sharedMesh.isReadable) { flag = false; continue; } int count = list.Count; Vector3[] vertices = sharedMesh.vertices; foreach (Vector3 val4 in vertices) { list.Add(((Matrix4x4)(ref val2)).MultiplyPoint3x4(val4)); } int[] triangles = sharedMesh.triangles; foreach (int num in triangles) { list2.Add(count + num); } } if (!flag2 || ((Bounds)(ref bounds)).size.x < 0.05f || ((Bounds)(ref bounds)).size.y < 0.05f || ((Bounds)(ref bounds)).size.z < 0.05f) { return null; } value = new Shape { Bounds = bounds, Vertices = ((flag && list.Count > 0) ? list.ToArray() : null), Triangles = ((flag && list.Count > 0) ? list2.ToArray() : null) }; Shapes[key] = value; return value; } private static Material MaterialFor(int level) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (Materials.TryGetValue(level, out var value) && (Object)(object)value != (Object)null) { return value; } if (!FindChain()) { return null; } Material val = new Material(_chainMaterial) { name = "CDEV_ChestUpgrade_Chain" + level }; if (val.HasProperty("_Color")) { val.SetColor("_Color", Tint[Mathf.Clamp(level - 2, 0, Tint.Length - 1)]); } Materials[level] = val; return val; } private static bool FindChain() { if ((Object)(object)_chainMesh != (Object)null && (Object)(object)_chainMaterial != (Object)null) { return true; } if (_searched || (Object)(object)ZNetScene.instance == (Object)null) { return false; } _searched = true; GameObject prefab = ZNetScene.instance.GetPrefab("piece_cauldron"); if ((Object)(object)prefab != (Object)null) { MeshFilter[] componentsInChildren = prefab.GetComponentsInChildren<MeshFilter>(true); foreach (MeshFilter val in componentsInChildren) { MeshRenderer component = ((Component)val).GetComponent<MeshRenderer>(); if ((Object)(object)val.sharedMesh != (Object)null && (Object)(object)component != (Object)null && (Object)(object)((Renderer)component).sharedMaterial != (Object)null && ((Object)val.sharedMesh).name.StartsWith("chain", StringComparison.OrdinalIgnoreCase)) { _chainMesh = val.sharedMesh; _chainMaterial = ((Renderer)component).sharedMaterial; return true; } } } ChestUpgradePlugin.Log.LogWarning((object)"No chain mesh found on piece_cauldron; upgraded chests show no chains."); return false; } } internal static class ModConfig { internal static ConfigEntry<string> CapacityByLevel; internal static ConfigEntry<int> MaxColumns; internal static ConfigEntry<int> CountTolerance; internal static ConfigEntry<float> CostMultiplier; internal static ConfigEntry<string> CostByLevel; internal static ConfigEntry<string> CostOverrides; internal static ConfigEntry<bool> RequireStation; internal static ConfigEntry<bool> RefundOnDestroy; internal static ConfigEntry<bool> NoCostChestsDropNothing; internal static ConfigEntry<string> ExcludedChests; internal static ConfigEntry<bool> CenterVertically; internal static ConfigEntry<bool> ShowLevelOnChest; internal 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown //IL_0140: 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_014c: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Expected O, but got Unknown //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Expected O, but got Unknown //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Expected O, but got Unknown //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Expected O, but got Unknown //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Expected O, but got Unknown //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Expected O, but got Unknown //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_025e: 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_0273: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Expected O, but got Unknown //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Expected O, but got Unknown //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Expected O, but got Unknown //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Expected O, but got Unknown //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Expected O, but got Unknown //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Expected O, but got Unknown //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Expected O, but got Unknown CapacityByLevel = config.Bind<string>("Upgrades", "CapacityByLevel", "1.5, 2, 3", new ConfigDescription("Capacity of levels 2, 3, 4, ... as multiples of what the chest holds when built, separated by commas; their number is the number of upgrades (1.5, 2, 3 = levels 2 to 4: a 10-slot chest gets 15, 20, 30). Each level is laid out as full rows, as wide as possible (see MaxColumns), as close to that count as full rows allow.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = 30 } })); CostByLevel = config.Bind<string>("Costs", "CostByLevel", "1, 1.5, 3", new ConfigDescription("What the upgrades to levels 2, 3, 4, ... cost, as multiples of the base cost, separated by commas (1, 1.5, 3: a wood chest built from 10 wood costs 10, 15 and 30 wood; 1, 2, 4 = the game's tool upgrades). Levels past the list cost twice the level before. Amounts are rounded, halves up.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = 25 } })); MaxColumns = config.Bind<int>("Upgrades", "MaxColumns", 8, new ConfigDescription("Widest an upgraded chest gets (8 = the width of the chest window). A chest never gets narrower than it was, so items keep their cells.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 8), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = 15 } })); CountTolerance = config.Bind<int>("Upgrades", "CountTolerance", 10, new ConfigDescription("How far (in percent) a level's slot count may miss its CapacityByLevel target so the chest can be wider. Of the layouts of full rows within this margin the widest wins (10: a 15-slot chest gets 24 / 32 / 48 in rows of 8 instead of 25 / 30 / 45 in rows of 5); 0 = the count as close as full rows allow, whatever the shape.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = 14 } })); ExcludedChests = config.Bind<string>("Upgrades", "ExcludedChests", "", new ConfigDescription("Prefab names of chests that cannot be upgraded, separated by commas (e.g. piece_chest_private).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = 10 } })); ShowLevelOnChest = config.Bind<bool>("Display", "ShowLevelOnChest", true, "Client: an upgraded chest has chains hung round it, one per upgrade, in its level's metal (bronze 2, iron 3, gold 4), seen from every side. Local to this machine."); CenterVertically = config.Bind<bool>("Display", "CenterVertically", true, "Client: a chest with fewer rows than the chest window shows always sits in the middle of the window, as vanilla means it to (vanilla checks only once, when the chest opens). Local to this machine."); CostMultiplier = config.Bind<float>("Costs", "CostMultiplier", 1f, new ConfigDescription("Base cost of a chest without an override = its build materials times this; CostByLevel scales it per level.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = 30 } })); CostByLevel = config.Bind<string>("Costs", "CostByLevel", "1, 1.5, 3", new ConfigDescription("What the upgrades to levels 2, 3, 4, ... cost, as multiples of the base cost, separated by commas (1, 1.5, 3: a wood chest built from 10 wood costs 10, 15 and 30 wood; 1, 2, 4 = the game's tool upgrades). Levels past the list cost twice the level before. Amounts are rounded, halves up.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = 25 } })); CostOverrides = config.Bind<string>("Costs", "CostOverrides", "", new ConfigDescription("Own per-level costs for some chests: prefab=Item:amount,Item:amount; next prefab=... (e.g. piece_chest_wood=Wood:10,Resin:5; piece_chest=FineWood:10,Iron:2). Item names are prefab names. The amounts are the base cost: CostByLevel still applies, CostMultiplier does not.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = 20 } })); RequireStation = config.Bind<bool>("Costs", "RequireStation", true, new ConfigDescription("Upgrading needs the chest's own crafting station (the one it is built with) within its build range, at level 2 for chest level 2, level 3 for level 3 and so on - like upgrading a tool.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = 10 } })); RefundOnDestroy = config.Bind<bool>("Costs", "RefundOnDestroy", true, new ConfigDescription("A torn down or destroyed chest drops what every level it reached costs (levels 2, 3, ... at today's prices), next to its build materials.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = 0 } })); NoCostChestsDropNothing = config.Bind<bool>("Costs", "NoCostChestsDropNothing", true, new ConfigDescription("A chest placed with the nocost cheat drops no build materials when torn down or destroyed (vanilla drops them, marked as cheated). Upgrade levels done for free never give anything back either.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = -10 } })); CostMultiplier.SettingChanged += delegate { UpgradeRecipes.Invalidate(); }; CostOverrides.SettingChanged += delegate { UpgradeRecipes.Invalidate(); }; CostByLevel.SettingChanged += delegate { UpgradeRecipes.Invalidate(); }; ExcludedChests.SettingChanged += delegate { ChestLevels.InvalidateExcluded(); }; CapacityByLevel.SettingChanged += delegate { ChestLevels.InvalidateCapacity(); ChestVisuals.RefreshAll(); }; ShowLevelOnChest.SettingChanged += delegate { ChestVisuals.RefreshAll(); }; } } [BepInPlugin("cdev.chestupgrade", "CDEV.ChestUpgrade", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class ChestUpgradePlugin : BaseUnityPlugin { internal static ManualLogSource Log; private Harmony _harmony; private void Awake() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ModConfig.Bind(((BaseUnityPlugin)this).Config); _harmony = new Harmony("cdev.chestupgrade"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); } private void Update() { UpgradeService.Tick(); UpgradePanel.Tick(); ChestVisuals.Tick(); } private void OnDestroy() { UpgradePanel.DestroyAll(); UpgradeService.UnregisterAll(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class Translations { private const string Prefix = "$cdev_cu_"; private static readonly string[] Keys = new string[12] { "maxlevel", "upgraded", "failed", "needstation", "hover", "title", "levelword", "slotsword", "requires", "stationhave", "upgrade", "short" }; private static readonly Dictionary<string, string[]> Languages = new Dictionary<string, string[]> { ["English"] = new string[12] { "Maximum level", "Chest upgraded to level {0}", "Upgrade failed - materials returned", "Needs {0} level {1} nearby", "Level {0}/{1}", "Chest upgrade", "Level", "Slots", "Requires", "lv {0}/{1}", "Upgrade", "Not enough materials" }, ["Russian"] = new string[12] { "Максимальный уровень", "Сундук улучшен до уровня {0}", "Улучшение не удалось - материалы возвращены", "Нужен {0} уровня {1} рядом", "Уровень {0}/{1}", "Улучшение сундука", "Уровень", "Ячеек", "Требуется", "ур. {0}/{1}", "Улучшить", "Не хватает материалов" }, ["Ukrainian"] = new string[12] { "Максимальний рівень", "Скриню покращено до рівня {0}", "Покращення не вдалося - матеріали повернуто", "Потрібен {0} рівня {1} поруч", "Рівень {0}/{1}", "Покращення скрині", "Рівень", "Комірок", "Потрібно", "рів. {0}/{1}", "Покращити", "Не вистачає матеріалів" }, ["German"] = new string[12] { "Maximale Stufe", "Truhe auf Stufe {0} verbessert", "Verbesserung fehlgeschlagen - Materialien zurückgegeben", "Benötigt {0} Stufe {1} in der Nähe", "Stufe {0}/{1}", "Truhe verbessern", "Stufe", "Plätze", "Benötigt", "St. {0}/{1}", "Verbessern", "Nicht genug Materialien" }, ["French"] = new string[12] { "Niveau maximum", "Coffre amélioré au niveau {0}", "Échec de l'amélioration - matériaux rendus", "Nécessite {0} niveau {1} à proximité", "Niveau {0}/{1}", "Amélioration du coffre", "Niveau", "Emplacements", "Requis", "niv. {0}/{1}", "Améliorer", "Matériaux insuffisants" }, ["Spanish"] = new string[12] { "Nivel máximo", "Cofre mejorado al nivel {0}", "Mejora fallida - materiales devueltos", "Requiere {0} de nivel {1} cerca", "Nivel {0}/{1}", "Mejora del cofre", "Nivel", "Espacios", "Requiere", "niv. {0}/{1}", "Mejorar", "Materiales insuficientes" }, ["Italian"] = new string[12] { "Livello massimo", "Baule migliorato al livello {0}", "Miglioramento fallito - materiali restituiti", "Serve {0} di livello {1} nelle vicinanze", "Livello {0}/{1}", "Miglioramento del baule", "Livello", "Slot", "Richiede", "liv. {0}/{1}", "Migliora", "Materiali insufficienti" }, ["Portuguese_Brazilian"] = new string[12] { "Nível máximo", "Baú melhorado para o nível {0}", "A melhoria falhou - materiais devolvidos", "Requer {0} nível {1} por perto", "Nível {0}/{1}", "Melhoria do baú", "Nível", "Espaços", "Requer", "nív. {0}/{1}", "Melhorar", "Materiais insuficientes" }, ["Portuguese_European"] = new string[12] { "Nível máximo", "Baú melhorado para o nível {0}", "A melhoria falhou - materiais devolvidos", "Requer {0} de nível {1} por perto", "Nível {0}/{1}", "Melhoria do baú", "Nível", "Espaços", "Requer", "nív. {0}/{1}", "Melhorar", "Materiais insuficientes" }, ["Polish"] = new string[12] { "Maksymalny poziom", "Skrzynia ulepszona do poziomu {0}", "Ulepszenie nieudane - materiały zwrócone", "Wymaga {0} poziomu {1} w pobliżu", "Poziom {0}/{1}", "Ulepszenie skrzyni", "Poziom", "Miejsca", "Wymaga", "poz. {0}/{1}", "Ulepsz", "Za mało materiałów" }, ["Czech"] = new string[12] { "Maximální úroveň", "Truhla vylepšena na úroveň {0}", "Vylepšení selhalo - materiál vrácen", "Vyžaduje {0} úrovně {1} poblíž", "Úroveň {0}/{1}", "Vylepšení truhly", "Úroveň", "Místa", "Vyžaduje", "úr. {0}/{1}", "Vylepšit", "Nedostatek materiálu" }, ["Slovak"] = new string[12] { "Maximálna úroveň", "Truhlica vylepšená na úroveň {0}", "Vylepšenie zlyhalo - materiál vrátený", "Vyžaduje {0} úrovne {1} nablízku", "Úroveň {0}/{1}", "Vylepšenie truhlice", "Úroveň", "Miesta", "Vyžaduje", "úr. {0}/{1}", "Vylepšiť", "Nedostatok materiálu" }, ["Hungarian"] = new string[12] { "Maximális szint", "Láda fejlesztve: {0}. szint", "A fejlesztés nem sikerült - anyagok visszaadva", "Kell: {0} ({1}. szint) a közelben", "Szint {0}/{1}", "Láda fejlesztése", "Szint", "Helyek", "Szükséges", "szint {0}/{1}", "Fejlesztés", "Nincs elég anyag" }, ["Dutch"] = new string[12] { "Maximaal niveau", "Kist verbeterd naar niveau {0}", "Verbeteren mislukt - materialen teruggegeven", "Vereist {0} niveau {1} in de buurt", "Niveau {0}/{1}", "Kist verbeteren", "Niveau", "Vakken", "Vereist", "niv. {0}/{1}", "Verbeteren", "Niet genoeg materialen" }, ["Swedish"] = new string[12] { "Maxnivå", "Kistan uppgraderad till nivå {0}", "Uppgraderingen misslyckades - material återlämnat", "Kräver {0} nivå {1} i närheten", "Nivå {0}/{1}", "Uppgradera kista", "Nivå", "Platser", "Kräver", "nv. {0}/{1}", "Uppgradera", "Inte tillräckligt med material" }, ["Norwegian"] = new string[12] { "Maksnivå", "Kisten oppgradert til nivå {0}", "Oppgradering mislyktes - materialer returnert", "Krever {0} nivå {1} i nærheten", "Nivå {0}/{1}", "Oppgradere kiste", "Nivå", "Plasser", "Krever", "nv. {0}/{1}", "Oppgrader", "Ikke nok materialer" }, ["Danish"] = new string[12] { "Maksimalt niveau", "Kisten opgraderet til niveau {0}", "Opgradering mislykkedes - materialer returneret", "Kræver {0} niveau {1} i nærheden", "Niveau {0}/{1}", "Opgradér kiste", "Niveau", "Pladser", "Kræver", "niv. {0}/{1}", "Opgradér", "Ikke nok materialer" }, ["Finnish"] = new string[12] { "Enimmäistaso", "Arkku päivitetty tasolle {0}", "Päivitys epäonnistui - materiaalit palautettu", "Vaatii lähelle: {0}, taso {1}", "Taso {0}/{1}", "Arkun päivitys", "Taso", "Paikat", "Vaatii", "taso {0}/{1}", "Päivitä", "Materiaalit eivät riitä" }, ["Icelandic"] = new string[12] { "Hámarksstig", "Kista uppfærð í stig {0}", "Uppfærsla mistókst - efni skilað", "Þarf {0} á stigi {1} nálægt", "Stig {0}/{1}", "Uppfæra kistu", "Stig", "Hólf", "Þarf", "st. {0}/{1}", "Uppfæra", "Ekki nóg efni" }, ["Turkish"] = new string[12] { "Maksimum seviye", "Sandık {0}. seviyeye yükseltildi", "Yükseltme başarısız - malzemeler iade edildi", "Yakında {1}. seviye {0} gerekli", "Seviye {0}/{1}", "Sandık yükseltme", "Seviye", "Yuva", "Gerekli", "sv. {0}/{1}", "Yükselt", "Yeterli malzeme yok" }, ["Romanian"] = new string[12] { "Nivel maxim", "Cufăr îmbunătățit la nivelul {0}", "Îmbunătățirea a eșuat - materiale returnate", "Necesită {0} nivelul {1} în apropiere", "Nivel {0}/{1}", "Îmbunătățire cufăr", "Nivel", "Sloturi", "Necesită", "niv. {0}/{1}", "Îmbunătățește", "Materiale insuficiente" }, ["Bulgarian"] = new string[12] { "Максимално ниво", "Сандъкът е подобрен до ниво {0}", "Подобрението не успя - материалите са върнати", "Нужен е {0} ниво {1} наблизо", "Ниво {0}/{1}", "Подобрение на сандък", "Ниво", "Места", "Изисква", "ниво {0}/{1}", "Подобри", "Няма достатъчно материали" }, ["Macedonian"] = new string[12] { "Максимално ниво", "Ковчегот е подобрен на ниво {0}", "Подобрувањето не успеа - материјалите се вратени", "Потребен е {0} ниво {1} во близина", "Ниво {0}/{1}", "Подобрување на ковчег", "Ниво", "Места", "Потребно", "ниво {0}/{1}", "Подобри", "Нема доволно материјали" }, ["Serbian"] = new string[12] { "Maksimalni nivo", "Kovčeg unapređen na nivo {0}", "Unapređenje nije uspelo - materijali vraćeni", "Potreban je {0} nivoa {1} u blizini", "Nivo {0}/{1}", "Unapređenje kovčega", "Nivo", "Mesta", "Potrebno", "niv. {0}/{1}", "Unapredi", "Nema dovoljno materijala" }, ["Croatian"] = new string[12] { "Maksimalna razina", "Škrinja nadograđena na razinu {0}", "Nadogradnja nije uspjela - materijali vraćeni", "Potreban je {0} razine {1} u blizini", "Razina {0}/{1}", "Nadogradnja škrinje", "Razina", "Mjesta", "Potrebno", "raz. {0}/{1}", "Nadogradi", "Nema dovoljno materijala" }, ["Lithuanian"] = new string[12] { "Didžiausias lygis", "Skrynia patobulinta iki {0} lygio", "Patobulinti nepavyko - medžiagos grąžintos", "Reikia {0} ({1} lygio) netoliese", "Lygis {0}/{1}", "Skrynios tobulinimas", "Lygis", "Vietos", "Reikia", "lyg. {0}/{1}", "Patobulinti", "Nepakanka medžiagų" }, ["Latvian"] = new string[12] { "Maksimālais līmenis", "Lāde uzlabota līdz {0}. līmenim", "Uzlabošana neizdevās - materiāli atgriezti", "Nepieciešams {0} ({1}. līmenis) tuvumā", "Līmenis {0}/{1}", "Lādes uzlabošana", "Līmenis", "Vietas", "Nepieciešams", "līm. {0}/{1}", "Uzlabot", "Nepietiek materiālu" }, ["Greek"] = new string[12] { "Μέγιστο επίπεδο", "Το σεντούκι αναβαθμίστηκε στο επίπεδο {0}", "Η αναβάθμιση απέτυχε - τα υλικά επιστράφηκαν", "Απαιτείται {0} επιπέδου {1} κοντά", "Επίπεδο {0}/{1}", "Αναβάθμιση σεντουκιού", "Επίπεδο", "Θέσεις", "Απαιτείται", "επ. {0}/{1}", "Αναβάθμιση", "Δεν υπάρχουν αρκετά υλικά" }, ["Georgian"] = new string[12] { "მაქსიმალური დონე", "ზანდუკი გაუმჯობესდა {0} დონემდე", "გაუმჯობესება ვერ მოხერხდა - მასალები დაბრუნდა", "საჭიროა {0}, დონე {1}, ახლოს", "დონე {0}/{1}", "ზანდუკის გაუმჯობესება", "დონე", "უჯრები", "საჭიროა", "დონე {0}/{1}", "გაუმჯობესება", "არ არის საკმარისი მასალა" }, ["Chinese"] = new string[12] { "最高等级", "箱子已升级到 {0} 级", "升级失败 - 材料已退还", "附近需要 {1} 级{0}", "等级 {0}/{1}", "箱子升级", "等级", "格子", "需要", "{0}/{1} 级", "升级", "材料不足" }, ["Chinese_Trad"] = new string[12] { "最高等級", "箱子已升級到 {0} 級", "升級失敗 - 材料已退還", "附近需要 {1} 級{0}", "等級 {0}/{1}", "箱子升級", "等級", "格子", "需要", "{0}/{1} 級", "升級", "材料不足" }, ["Japanese"] = new string[12] { "最大レベル", "チェストをレベル {0} に強化しました", "強化に失敗しました - 素材を返却しました", "近くにレベル {1} の{0}が必要です", "レベル {0}/{1}", "チェストの強化", "レベル", "スロット", "必要", "Lv {0}/{1}", "強化", "素材が足りません" }, ["Korean"] = new string[12] { "최대 레벨", "상자가 {0} 레벨로 업그레이드되었습니다", "업그레이드 실패 - 재료가 반환되었습니다", "근처에 {1} 레벨 {0} 필요", "레벨 {0}/{1}", "상자 업그레이드", "레벨", "칸", "필요", "Lv {0}/{1}", "업그레이드", "재료가 부족합니다" }, ["Hindi"] = new string[12] { "अध\u093fकतम स\u094dतर", "स\u0902द\u0942क स\u094dतर {0} तक उन\u094dनत ह\u0941आ", "उन\u094dनयन व\u093fफल - स\u093eमग\u094dर\u0940 ल\u094cट\u093eई गई", "प\u093eस म\u0947\u0902 स\u094dतर {1} क\u093e {0} च\u093eह\u093fए", "स\u094dतर {0}/{1}", "स\u0902द\u0942क उन\u094dनयन", "स\u094dतर", "ख\u093eन\u0947", "आवश\u094dयक", "स\u094dतर {0}/{1}", "उन\u094dनत कर\u0947\u0902", "पर\u094dय\u093eप\u094dत स\u093eमग\u094dर\u0940 नह\u0940\u0902" }, ["Thai"] = new string[12] { "ระด\u0e31บส\u0e39งส\u0e38ด", "อ\u0e31ปเกรดห\u0e35บเป\u0e47นระด\u0e31บ {0} แล\u0e49ว", "อ\u0e31ปเกรดล\u0e49มเหลว - ค\u0e37นว\u0e31สด\u0e38แล\u0e49ว", "ต\u0e49องม\u0e35{0}ระด\u0e31บ {1} ใกล\u0e49ๆ", "ระด\u0e31บ {0}/{1}", "อ\u0e31ปเกรดห\u0e35บ", "ระด\u0e31บ", "ช\u0e48อง", "ต\u0e49องการ", "ระด\u0e31บ {0}/{1}", "อ\u0e31ปเกรด", "ว\u0e31สด\u0e38ไม\u0e48พอ" } }; private static string _language; private static Dictionary<string, string> _table; internal static string Text(string key) { if (key != null && key.StartsWith("$cdev_cu_")) { if (!Table().TryGetValue(key.Substring("$cdev_cu_".Length), out var value)) { return key; } return value; } if (Localization.instance == null) { return key; } return Localization.instance.Localize(key); } private static Dictionary<string, string> Table() { string text = ((Localization.instance != null) ? Localization.instance.GetSelectedLanguage() : "English"); if (_table != null && text == _language) { return _table; } _language = text; string[] array = Languages["English"]; if (!Languages.TryGetValue(text, out var value)) { value = array; } _table = new Dictionary<string, string>(); for (int i = 0; i < Keys.Length; i++) { _table[Keys[i]] = ((i < value.Length) ? value[i] : array[i]); } return _table; } } internal sealed class UpgradeRecipe { internal readonly Requirement[] Resources; internal readonly CraftingStation Station; internal UpgradeRecipe(Requirement[] resources, CraftingStation station) { Resources = resources; Station = station; } internal static int Amount(Requirement req, int targetLevel) { if (targetLevel <= 1 || req.m_amountPerLevel <= 0) { return 0; } double value = (double)req.m_amountPerLevel * UpgradeRecipes.Factor(targetLevel); return Math.Max(1, (int)Math.Round(value, MidpointRounding.AwayFromZero)); } internal static int RequiredStationLevel(int targetLevel) { return Mathf.Max(1, targetLevel); } } internal static class UpgradeRecipes { private static readonly Dictionary<string, UpgradeRecipe> Cache = new Dictionary<string, UpgradeRecipe>(); private static Dictionary<string, List<KeyValuePair<string, int>>> _overrides; private static readonly HashSet<string> Warned = new HashSet<string>(); private static List<float> _factors; internal static void Invalidate() { Cache.Clear(); _overrides = null; _factors = null; } internal static double Factor(int targetLevel) { if (_factors == null) { _factors = new List<float>(); string[] array = ModConfig.CostByLevel.Value.Split(new char[3] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { if (float.TryParse(text.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && result > 0f) { _factors.Add(result); } } if (_factors.Count == 0) { _factors.AddRange(new float[3] { 1f, 1.5f, 3f }); } } int num = targetLevel - 1 - 1; if (num >= _factors.Count) { return (double)_factors[_factors.Count - 1] * Math.Pow(2.0, num - _factors.Count + 1); } return _factors[num]; } internal static UpgradeRecipe For(Container container) { if ((Object)(object)container == (Object)null || (Object)(object)container.m_piece == (Object)null || (Object)(object)ObjectDB.instance == (Object)null) { return null; } string text = ChestLevels.PrefabName(container); if (!Cache.TryGetValue(text, out var value)) { value = Build(text, container.m_piece); Cache[text] = value; } return value; } private static UpgradeRecipe Build(string prefab, Piece piece) { List<Requirement> list = new List<Requirement>(); if (Overrides().TryGetValue(prefab, out var value)) { foreach (KeyValuePair<string, int> item in value) { ItemDrop val = FindItem(item.Key); if ((Object)(object)val != (Object)null && item.Value > 0) { list.Add(PerLevel(val, item.Value)); } } } else if (piece.m_resources != null) { float value2 = ModConfig.CostMultiplier.Value; Requirement[] resources = piece.m_resources; foreach (Requirement val2 in resources) { if (val2 != null && (Object)(object)val2.m_resItem != (Object)null && val2.m_amount > 0) { list.Add(PerLevel(val2.m_resItem, Mathf.Max(1, Mathf.RoundToInt((float)val2.m_amount * value2)))); } } } return new UpgradeRecipe(list.ToArray(), piece.m_craftingStation); } private static Requirement PerLevel(ItemDrop item, int amountPerLevel) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown return new Requirement { m_resItem = item, m_amount = 0, m_amountPerLevel = amountPerLevel, m_recover = true }; } private static ItemDrop FindItem(string name) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null && Warned.Add(name)) { ChestUpgradePlugin.Log.LogWarning((object)("CostOverrides: no item prefab named '" + name + "'; left out.")); } return val; } private static Dictionary<string, List<KeyValuePair<string, int>>> Overrides() { if (_overrides != null) { return _overrides; } _overrides = new Dictionary<string, List<KeyValuePair<string, int>>>(StringComparer.OrdinalIgnoreCase); string[] array = ModConfig.CostOverrides.Value.Split(new char[2] { ';', '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { int num = text.IndexOf('='); string text2 = ((num > 0) ? text.Substring(0, num).Trim() : ""); if (text2.Length == 0) { if (text.Trim().Length > 0 && Warned.Add(text)) { ChestUpgradePlugin.Log.LogWarning((object)("CostOverrides: '" + text.Trim() + "' is not prefab=Item:amount,...; ignored.")); } continue; } List<KeyValuePair<string, int>> list = new List<KeyValuePair<string, int>>(); string[] array2 = text.Substring(num + 1).Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text3 in array2) { string[] array3 = text3.Split(new char[1] { ':' }); if (array3.Length == 2 && int.TryParse(array3[1].Trim(), out var result) && array3[0].Trim().Length > 0) { list.Add(new KeyValuePair<string, int>(array3[0].Trim(), result)); } else if (Warned.Add(text3)) { ChestUpgradePlugin.Log.LogWarning((object)("CostOverrides: '" + text3.Trim() + "' in '" + text2 + "' is not Item:amount; ignored.")); } } _overrides[text2] = list; } return _overrides; } } internal sealed class UpgradeCheck { internal Container Container; internal int Level; internal int Target; internal bool AtMax; internal UpgradeRecipe Recipe; internal bool Free; internal bool StationNeeded; internal int StationLevel; internal int RequiredStationLevel; internal bool ResourcesOk; internal bool Pending; internal bool StationOk { get { if (StationNeeded) { return StationLevel >= RequiredStationLevel; } return true; } } internal bool CanUpgrade { get { if (!AtMax && !Pending && Recipe != null && StationOk) { return ResourcesOk; } return false; } } } internal static class UpgradeService { private sealed class Pending { internal int Target; internal string Spent; internal float Sent; } private const string RpcRequest = "CDEV_ChestUpgrade_Request"; private const string RpcResult = "CDEV_ChestUpgrade_Result"; private const float ReplyTimeout = 6f; private static readonly Dictionary<ZDOID, Pending> Waiting = new Dictionary<ZDOID, Pending>(); private static readonly List<ZDOID> Expired = new List<ZDOID>(); private static readonly HashSet<ZNetView> Registered = new HashSet<ZNetView>(); private static readonly int RefundedKey = StringExtensionMethods.GetStableHashCode("cdev.chestupgrade.refunded"); private static readonly int PaidKey = StringExtensionMethods.GetStableHashCode("cdev.chestupgrade.paid"); private static int _pruneAt = 256; internal static void RegisterRpcs(Container container) { ZNetView nview = container.m_nview; if ((Object)(object)nview == (Object)null || nview.GetZDO() == null || (Object)(object)container.m_piece == (Object)null || Registered.Contains(nview)) { return; } nview.Register<int, bool>("CDEV_ChestUpgrade_Request", (Action<long, int, bool>)delegate(long sender, int target, bool paid) { OnRequest(container, sender, target, paid); }); nview.Register<int, bool>("CDEV_ChestUpgrade_Result", (Action<long, int, bool>)delegate(long sender, int target, bool ok) { OnResult(container, target, ok); }); Registered.Add(nview); if (Registered.Count >= _pruneAt) { Registered.RemoveWhere((ZNetView view) => (Object)(object)view == (Object)null); _pruneAt = Mathf.Max(256, Registered.Count * 2); } } internal static void UnregisterAll() { foreach (ZNetView item in Registered) { if ((Object)(object)item != (Object)null) { item.Unregister("CDEV_ChestUpgrade_Request"); item.Unregister("CDEV_ChestUpgrade_Result"); } } Registered.Clear(); Waiting.Clear(); } internal static void Evaluate(Container container, Player player, UpgradeCheck check) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) RegisterRpcs(container); check.Container = container; check.Level = ChestLevels.GetLevel(container); check.Target = check.Level + 1; check.AtMax = check.Level >= ChestLevels.MaxLevel; check.Recipe = UpgradeRecipes.For(container); check.Pending = (Object)(object)container.m_nview != (Object)null && container.m_nview.GetZDO() != null && Waiting.ContainsKey(container.m_nview.GetZDO().m_uid); check.Free = player.NoCostCheat() || ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey((GlobalKeys)24)); CraftingStation val = check.Recipe?.Station; check.StationNeeded = ModConfig.RequireStation.Value && (Object)(object)val != (Object)null && (!((Object)(object)ZoneSystem.instance != (Object)null) || !ZoneSystem.instance.GetGlobalKey((GlobalKeys)27)); check.RequiredStationLevel = UpgradeRecipe.RequiredStationLevel(check.Target); check.StationLevel = (check.StationNeeded ? StationLevelNear(val.m_name, ((Component)container).transform.position) : 0); check.ResourcesOk = check.Free || (check.Recipe != null && HaveResources(((Humanoid)player).GetInventory(), check.Recipe, check.Target)); } internal static int StationLevelNear(string stationName, Vector3 point) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) int num = 0; foreach (CraftingStation allStation in CraftingStation.m_allStations) { if (!((Object)(object)allStation == (Object)null) && !(allStation.m_name != stationName)) { float stationBuildRange = allStation.GetStationBuildRange(); Vector3 val = ((Component)allStation).transform.position - point; if (((Vector3)(ref val)).sqrMagnitude <= stationBuildRange * stationBuildRange) { num = Mathf.Max(num, allStation.GetLevel(true)); } } } return num; } private static bool HaveResources(Inventory inventory, UpgradeRecipe recipe, int target) { Requirement[] resources = recipe.Resources; foreach (Requirement val in resources) { int num = UpgradeRecipe.Amount(val, target); if (num > 0 && inventory.CountItems(val.m_resItem.m_itemData.m_shared.m_name, -1, true) < num) { return false; } } return true; } internal static void TryUpgrade(Container container, Player player) { //IL_0115: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null || (Object)(object)player == (Object)null || !ChestLevels.IsUpgradable(container)) { return; } UpgradeCheck upgradeCheck = new UpgradeCheck(); Evaluate(container, player, upgradeCheck); if (upgradeCheck.Pending) { return; } if (upgradeCheck.AtMax) { ((Character)player).Message((MessageType)2, Translations.Text("$cdev_cu_maxlevel"), 0, (Sprite)null, false); return; } if (!upgradeCheck.StationOk) { ((Character)player).Message((MessageType)2, string.Format(Translations.Text("$cdev_cu_needstation"), Translations.Text(upgradeCheck.Recipe.Station.m_name), upgradeCheck.RequiredStationLevel), 0, (Sprite)null, false); return; } if (!upgradeCheck.ResourcesOk) { ((Character)player).Message((MessageType)2, Translations.Text("$cdev_cu_short"), 0, (Sprite)null, false); return; } string spent = (upgradeCheck.Free ? "" : Consume(((Humanoid)player).GetInventory(), upgradeCheck.Recipe, upgradeCheck.Target)); if (container.m_nview.IsOwner()) { Finish(container, upgradeCheck.Target, ApplyOnOwner(container, upgradeCheck.Target, !upgradeCheck.Free), spent); return; } Waiting[container.m_nview.GetZDO().m_uid] = new Pending { Target = upgradeCheck.Target, Spent = spent, Sent = Time.time }; container.m_nview.InvokeRPC("CDEV_ChestUpgrade_Request", new object[2] { upgradeCheck.Target, !upgradeCheck.Free }); } private static string Consume(Inventory inventory, UpgradeRecipe recipe, int target) { StringBuilder stringBuilder = new StringBuilder(); Requirement[] resources = recipe.Resources; foreach (Requirement val in resources) { int num = UpgradeRecipe.Amount(val, target); if (num > 0) { inventory.RemoveItem(val.m_resItem.m_itemData.m_shared.m_name, num, -1, true); if (stringBuilder.Length > 0) { stringBuilder.Append(','); } stringBuilder.Append(Utils.GetPrefabName(((Component)val.m_resItem).gameObject)).Append(':').Append(num); } } return stringBuilder.ToString(); } private static bool ApplyOnOwner(Container container, int target, bool paid) { if (!container.m_nview.IsOwner() || !ChestLevels.IsUpgradable(container) || target > ChestLevels.MaxLevel || ChestLevels.GetLevel(container) != target - 1) { return false; } ZDO zDO = container.m_nview.GetZDO(); ChestLevels.StoreBuilt(container, zDO); zDO.Set(ChestLevels.LevelKey, target, false); int num = zDO.GetInt(PaidKey, 0); num = (paid ? (num | (1 << target)) : (num & ~(1 << target))); zDO.Set(PaidKey, num, false); ChestLevels.Apply(container); return true; } private static void OnRequest(Container container, long sender, int target, bool paid) { try { bool flag = ApplyOnOwner(container, target, paid); container.m_nview.InvokeRPC(sender, "CDEV_ChestUpgrade_Result", new object[2] { target, flag }); } catch (Exception ex) { ChestUpgradePlugin.Log.LogError((object)("Upgrade request failed: " + ex)); } } private static void OnResult(Container container, int target, bool ok) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) ZDO val = (((Object)(object)container.m_nview != (Object)null) ? container.m_nview.GetZDO() : null); if (val != null && Waiting.TryGetValue(val.m_uid, out var value) && value.Target == target) { Waiting.Remove(val.m_uid); Finish(container, target, ok, value.Spent); } } private static void Finish(Container container, int target, bool ok, string spent) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (ok) { ChestLevels.Apply(container); Piece piece = container.m_piece; if (piece != null) { EffectList placeEffect = piece.m_placeEffect; if (placeEffect != null) { placeEffect.Create(((Component)piece).transform.position, ((Component)piece).transform.rotation, (Transform)null, 1f, -1, ZDOID.None); } } if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, string.Format(Translations.Text("$cdev_cu_upgraded"), target), 0, (Sprite)null, false); } } else if ((Object)(object)localPlayer != (Object)null) { GiveBack(localPlayer, spent); ((Character)localPlayer).Message((MessageType)2, Translations.Text("$cdev_cu_failed"), 0, (Sprite)null, false); } } internal static void Tick() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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) if (Waiting.Count == 0) { return; } float time = Time.time; foreach (KeyValuePair<ZDOID, Pending> item in Waiting) { if (time - item.Value.Sent >= 6f) { Expired.Add(item.Key); } } foreach (ZDOID item2 in Expired) { Pending pending = Waiting[item2]; Waiting.Remove(item2); ZDO val = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(item2) : null); if (val == null) { ChestUpgradePlugin.Log.LogWarning((object)$"No reply to an upgrade of a chest that no longer exists ({item2}); nothing returned."); continue; } bool flag = val.GetInt(ChestLevels.LevelKey, 1) >= pending.Target; GameObject val2 = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.FindInstance(item2) : null); Container val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<Container>() : null); if (flag && (Object)(object)val3 != (Object)null) { Finish(val3, pending.Target, ok: true, pending.Spent); } else if (!flag && (Object)(object)Player.m_localPlayer != (Object)null) { GiveBack(Player.m_localPlayer, pending.Spent); ((Character)Player.m_localPlayer).Message((MessageType)2, Translations.Text("$cdev_cu_failed"), 0, (Sprite)null, false); } } Expired.Clear(); } private static void GiveBack(Player player, string spent) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = ((Humanoid)player).GetInventory(); foreach (KeyValuePair<GameObject, int> item in Parse(spent)) { ItemDrop component = item.Key.GetComponent<ItemDrop>(); int num = ((!((Object)(object)component != (Object)null)) ? 1 : Mathf.Max(1, component.m_itemData.m_shared.m_maxStackSize)); int num2 = item.Value; while (num2 > 0) { int num3 = Mathf.Min(num2, num); if (!inventory.CanAddItem(item.Key, num3) || !inventory.AddItem(item.Key, num3)) { break; } num2 -= num3; } if (num2 > 0) { SpawnDrops(item.Key, num2, ((Component)player).transform.position + Vector3.up); } } } internal static void DropUpgradeCost(Piece piece) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) Container val = (((Object)(object)piece != (Object)null) ? ((Component)piece).GetComponent<Container>() : null); if (!ModConfig.RefundOnDestroy.Value || (Object)(object)val == (Object)null || !ChestLevels.IsUpgradable(val)) { return; } ZDO zDO = piece.m_nview.GetZDO(); int level = ChestLevels.GetLevel(val); if (level <= 1 || zDO.GetBool(RefundedKey, false) || ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey(piece.FreeBuildKey()))) { return; } UpgradeRecipe upgradeRecipe = UpgradeRecipes.For(val); if (upgradeRecipe == null) { return; } if (piece.m_nview.IsOwner()) { zDO.Set(RefundedKey, true); } Vector3 at = ((Component)piece).transform.position + Vector3.up * piece.m_returnResourceHeightOffset; foreach (KeyValuePair<GameObject, int> item in UpgradeCost(upgradeRecipe, level, zDO.GetInt(PaidKey, 0))) { SpawnDrops(item.Key, item.Value, at); } } internal static bool BuiltForFree(Piece piece) { if (!ModConfig.NoCostChestsDropNothing.Value || (Object)(object)piece == (Object)null || (Object)(object)piece.m_nview == (Object)null || piece.m_nview.GetZDO() == null) { return false; } Container component = ((Component)piece).GetComponent<Container>(); if ((Object)(object)component != (Object)null && ChestLevels.IsUpgradable(component)) { return piece.m_nview.GetZDO().GetBool(ZDOVars.s_cheated, false); } return false; } internal static Dictionary<GameObject, int> UpgradeCost(UpgradeRecipe recipe, int level, int paidMask) { Dictionary<GameObject, int> dictionary = new Dictionary<GameObject, int>(); for (int i = 2; i <= level; i++) { if ((paidMask & (1 << i)) == 0) { continue; } Requirement[] resources = recipe.Resources; foreach (Requirement val in resources) { int num = UpgradeRecipe.Amount(val, i); if (num > 0) { GameObject gameObject = ((Component)val.m_resItem).gameObject; dictionary.TryGetValue(gameObject, out var value); dictionary[gameObject] = value + num; } } } return dictionary; } private static void SpawnDrops(GameObject prefab, int amount, Vector3 at) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //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_004f: Unknown result type (might be due to invalid IL or missing references) ItemDrop component = prefab.GetComponent<ItemDrop>(); int num = ((!((Object)(object)component != (Object)null)) ? 1 : Mathf.Max(1, component.m_itemData.m_shared.m_maxStackSize)); while (amount > 0) { int num2 = Mathf.Min(amount, num); amount -= num2; GameObject val = Object.Instantiate<GameObject>(prefab, at + Random.insideUnitSphere * 0.3f, Quaternion.identity); ItemDrop component2 = val.GetComponent<ItemDrop>(); if ((Object)(object)component2 != (Object)null) { component2.SetStack(num2); ItemDrop.OnCreateNew(component2, false); } } } private static Dictionary<GameObject, int> Parse(string spent) { Dictionary<GameObject, int> dictionary = new Dictionary<GameObject, int>(); if (string.IsNullOrEmpty(spent) || (Object)(object)ObjectDB.instance == (Object)null) { return dictionary; } string[] array = spent.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { int num = text.LastIndexOf(':'); if (num > 0 && int.TryParse(text.Substring(num + 1), out var result) && result > 0) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text.Substring(0, num)); if ((Object)(object)itemPrefab == (Object)null) { ChestUpgradePlugin.Log.LogWarning((object)("Material '" + text + "' has no item prefab; not returned.")); continue; } dictionary.TryGetValue(itemPrefab, out var value); dictionary[itemPrefab] = value + result; } } return dictionary; } } internal static class BuildInfo { public const string Name = "CDEV.ChestUpgrade"; public const string Guid = "cdev.chestupgrade"; public const string Version = "0.1.0"; } } namespace CDEV.ChestUpgrade.UI { internal static class HeaderName { private const float StarSize = 22f; private const float StarGap = 2f; private const float NameGap = 8f; private static readonly Color Grey = new Color(0.32f, 0.3f, 0.28f, 0.95f); private static readonly Color DefaultGold = new Color(1f, 0.713f, 0.361f, 1f); private static TMP_Text _name; private static bool _saved; private static Vector2 _anchorMin; private static Vector2 _anchorMax; private static Vector2 _pivot; private static Vector2 _position; private static Vector2 _size; private static TextAlignmentOptions _alignment; private static bool _autoSize; private static float _fontSize; private static float _fontSizeMin; private static float _fontSizeMax; private static TextOverflowModes _overflow; private static GameObject _stars; private static readonly List<Image> Stars = new List<Image>(); private static Color _gold = DefaultGold; private static readonly Color LockedTitle = new Color(0.75f, 0.72f, 0.68f); private static Container _tipFor; private static int _tipIndex = -1; private static string _tipTitle; private static string _tipText; internal static void Show(InventoryGui gui, Container container, int level, int maxLevel, float left, float right) { //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0130: 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_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Expected O, but got Unknown //IL_0263: 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_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0402: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Unknown result type (might be due to invalid IL or missing references) TMP_Text containerName = gui.m_containerName; if ((Object)(object)containerName == (Object)null) { return; } if ((Object)(object)_name != (Object)(object)containerName) { _name = containerName; _saved = false; _stars = null; Stars.Clear(); } RectTransform rectTransform = containerName.rectTransform; if (!_saved) { _anchorMin = rectTransform.anchorMin; _anchorMax = rectTransform.anchorMax; _pivot = rectTransform.pivot; _position = rectTransform.anchoredPosition; _size = rectTransform.sizeDelta; _alignment = containerName.alignment; _autoSize = containerName.enableAutoSizing; _fontSize = containerName.fontSize; _fontSizeMin = containerName.fontSizeMin; _fontSizeMax = containerName.fontSizeMax; _overflow = containerName.overflowMode; _saved = true; rectTransform.anchorMin = new Vector2(0f, _anchorMin.y); rectTransform.anchorMax = new Vector2(0f, _anchorMax.y); rectTransform.pivot = new Vector2(0f, _pivot.y); rectTransform.anchoredPosition = new Vector2(left, _position.y); containerName.alignment = (TextAlignmentOptions)((_alignment & 0xFF00) | 1); containerName.enableAutoSizing = true; containerName.fontSizeMax = (_autoSize ? _fontSizeMax : _fontSize); containerName.fontSizeMin = Mathf.Min(16f, containerName.fontSizeMax); containerName.overflowMode = (TextOverflowModes)1; } Rect rect = ((RectTransform)((Transform)rectTransform).parent).rect; float width = ((Rect)(ref rect)).width; float num = (float)maxLevel * 22f + (float)(maxLevel - 1) * 2f; float num2 = Mathf.Max(60f, width - left - right - 8f - num); float num3 = Mathf.Max(_size.y, containerName.fontSizeMax * 1.2f); if (!Mathf.Approximately(rectTransform.sizeDelta.x, num2) || !Mathf.Approximately(rectTransform.sizeDelta.y, num3)) { rectTransform.sizeDelta = new Vector2(num2, num3); } EnsureStars(gui, maxLevel); _stars.SetActive(true); int hovered = StarHover.Hovered; for (int i = 0; i < Stars.Count; i++) { Color val = ((i < level) ? _gold : Grey); ((Graphic)Stars[i]).color = ((i == hovered) ? Color.Lerp(val, Color.white, (i < level) ? 0.35f : 0.45f) : val); } if (hovered >= 0 && hovered < maxLevel && (Object)(object)container != (Object)null) { if ((Object)(object)container != (Object)(object)_tipFor || hovered != _tipIndex) { Vector2i val2 = ChestLevels.SizeFor(container, hovered + 1); _tipFor = container; _tipIndex = hovered; _tipTitle = Translations.Text("$cdev_cu_levelword") + " "