using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using SpaceCraft; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = "")] [assembly: AssemblyCompany("StorageCapacityDisplay")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2+ecdd65ea4c865da89993b1bd0cff03ebb79cedaf")] [assembly: AssemblyProduct("StorageCapacityDisplay")] [assembly: AssemblyTitle("StorageCapacityDisplay")] [assembly: AssemblyVersion("1.0.2.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace StorageCapacityDisplay { public sealed class CapacityDisplay : MonoBehaviour { private Plugin plugin; private InventoryAssociatedProxy proxy; private InventoryAssociated associated; private InventoriesHandler handler; private Inventory inventory; private bool watching; private bool pending; private bool dirty = true; private bool disposed; private bool suspended = true; private int generation; private int lastUsed = -1; private int lastTotal = -1; private float nextSample; private float nextRequest; private float nextVisual; private string lastFormat; private GameObject visual; private TextMeshProUGUI text; private Transform visualTransform; private Plugin.TextMaterial material; private bool billboard; private TextMeshProUGUI nameplate; private Canvas nameplateCanvas; private readonly List nameplateCandidates = new List(); private readonly Vector3[] corners = (Vector3[])(object)new Vector3[4]; private float nextPlacement; internal void Initialize(Plugin owner, InventoryAssociatedProxy inventoryProxy, InventoryAssociated inventoryAssociated) { plugin = owner; proxy = inventoryProxy; associated = inventoryAssociated; } internal void Tick(Plugin.TickContext context, ref int requestBudget, ref int visualBudget) { //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) if (disposed || (Object)(object)plugin == (Object)null) { return; } float now = context.Now; InventoriesHandler val = context.Handler; if (!context.Enabled || !((Component)this).gameObject.activeInHierarchy || (Object)(object)val == (Object)null || !((NetworkBehaviour)val).IsSpawned) { Suspend(); return; } if ((Object)(object)handler != (Object)(object)val) { Suspend(); handler = val; } suspended = false; if (inventory == null) { if (!pending && now >= nextRequest && requestBudget > 0) { requestBudget--; Resolve(now); } return; } if ((Object)(object)text == (Object)null && now >= nextVisual && visualBudget > 0) { visualBudget--; nextVisual = now + 2f; CreateVisual(); } if ((Object)(object)text == (Object)null) { return; } if (now >= nextPlacement && visualBudget > 0) { visualBudget--; nextPlacement = now + 2f; RefreshPlacement(); } int num; if (context.HasCamera) { if (context.NearbyOnly) { Vector3 val2 = context.CameraPosition - visualTransform.position; num = ((((Vector3)(ref val2)).sqrMagnitude <= context.DistanceSquared) ? 1 : 0); } else { num = 1; } } else { num = 0; } bool flag = (byte)num != 0; SetVisible(flag); if (flag && (dirty || now >= nextSample || lastFormat != context.Format)) { dirty = false; nextSample = now + 1f; int num2 = CapacityText.UsedSlots(inventory); int size = inventory.GetSize(); if (num2 != lastUsed || size != lastTotal || lastFormat != context.Format) { lastUsed = num2; lastTotal = size; lastFormat = context.Format; ((TMP_Text)text).text = CapacityText.Format(lastFormat, num2, size); } } } private void Resolve(float now) { nextRequest = now + 2f; if ((Object)(object)proxy != (Object)null) { if (((NetworkBehaviour)proxy).IsSpawned) { pending = true; int epoch = generation; InventoriesHandler requestedHandler = handler; proxy.GetInventory((Action)delegate(Inventory value, WorldObject worldObject) { Resolved(value, epoch, requestedHandler); }); } } else { if (!((Object)(object)associated != (Object)null) || associated.GetInventoryId() < 0) { return; } int inventoryId = associated.GetInventoryId(); Inventory inventoryById = handler.GetInventoryById(inventoryId); if (((NetworkBehaviour)handler).IsServer) { Bind(inventoryById); return; } pending = true; int epoch2 = generation; InventoriesHandler requestedHandler2 = handler; handler.GetInventoryById(inventoryId, (Action)delegate(Inventory value) { Resolved(value, epoch2, requestedHandler2); }, (HashSet)null); } } private void Resolved(Inventory value, int epoch, InventoriesHandler requestedHandler) { if ((Object)(object)this == (Object)null || disposed || generation != epoch || (Object)(object)handler != (Object)(object)requestedHandler) { return; } pending = false; if ((Object)(object)plugin == (Object)null || !plugin.EnabledSetting.Value || !((Component)this).gameObject.activeInHierarchy) { return; } try { Bind(value); } catch (Exception ex) { Suspend(); plugin.Warn(ex); } } private void Bind(Inventory value) { if (value != null && value != inventory) { Unbind(); inventory = value; plugin.Register(inventory.GetId(), this); Inventory obj = inventory; obj.inventoryContentModified = (Action)Delegate.Combine(obj.inventoryContentModified, new Action(ContentChanged)); dirty = true; lastUsed = (lastTotal = -1); if ((Object)(object)handler != (Object)null && ((NetworkBehaviour)handler).IsSpawned && !((NetworkBehaviour)handler).IsServer) { handler.BeginInventoryWatch(inventory); watching = true; handler.CheckInventoryWatchAndDirty(inventory); } } } internal void Snapshot(InventoriesHandler sourceHandler, Inventory value) { if (!((Object)(object)handler != (Object)(object)sourceHandler) && inventory != null && inventory.GetId() == value.GetId()) { if (value != inventory) { Inventory obj = inventory; obj.inventoryContentModified = (Action)Delegate.Remove(obj.inventoryContentModified, new Action(ContentChanged)); inventory = value; Inventory obj2 = inventory; obj2.inventoryContentModified = (Action)Delegate.Combine(obj2.inventoryContentModified, new Action(ContentChanged)); } dirty = true; } } private void ContentChanged(WorldObject item, bool added) { dirty = true; } private void Unbind() { Inventory val = inventory; bool num = watching; inventory = null; watching = false; if (val != null) { val.inventoryContentModified = (Action)Delegate.Remove(val.inventoryContentModified, new Action(ContentChanged)); if ((Object)(object)plugin != (Object)null) { plugin.Unregister(val.GetId(), this); } } if (num && val != null && (Object)(object)handler != (Object)null && ((NetworkBehaviour)handler).IsSpawned) { handler.StopInventoryWatch(val); } } internal void Suspend() { if (suspended) { return; } suspended = true; generation++; pending = false; SetVisible(visible: false); try { Unbind(); } catch (Exception ex) { if ((Object)(object)plugin != (Object)null) { plugin.Warn(ex); } } } private void SetVisible(bool visible) { if ((Object)(object)visual == (Object)null || visual.activeSelf == visible) { return; } visual.SetActive(visible); if (billboard && !((Object)(object)plugin == (Object)null)) { if (visible) { plugin.AddBillboard(visualTransform); } else { plugin.RemoveBillboard(visualTransform); } } } private void CreateVisual() { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Expected O, but got Unknown //IL_016e: 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_0174: 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_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0189: 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_0190: 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_0234: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)visual != (Object)null) { SetVisible(visible: false); Object.Destroy((Object)(object)visual); } ReleaseMaterial(); visual = null; visualTransform = null; billboard = false; FindNameplate(); TextMeshProUGUI val = nameplate; TMP_FontAsset val2 = (((Object)(object)val != (Object)null && (Object)(object)((TMP_Text)val).font != (Object)null) ? ((TMP_Text)val).font : TMP_Settings.defaultFontAsset); if (!((Object)(object)val2 == (Object)null)) { visual = new GameObject("StorageCapacityDisplay.Counter", new Type[2] { typeof(RectTransform), typeof(Canvas) }); visualTransform = visual.transform; visual.SetActive(false); visual.transform.SetParent(((Component)this).transform, false); Canvas component = visual.GetComponent(); component.renderMode = (RenderMode)2; component.overrideSorting = false; RectTransform val3 = (RectTransform)visual.transform; val3.sizeDelta = new Vector2(600f, 100f); PositionVisual(); nextPlacement = Time.unscaledTime + 2f; GameObject val4 = new GameObject("Capacity", new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); val4.transform.SetParent((Transform)(object)val3, false); RectTransform val5 = (RectTransform)val4.transform; val5.anchorMin = Vector2.zero; val5.anchorMax = Vector2.one; Vector2 offsetMin = (val5.offsetMax = Vector2.zero); val5.offsetMin = offsetMin; text = val4.GetComponent(); ((TMP_Text)text).font = val2; material = plugin.GetTextMaterial(val2); ((TMP_Text)text).fontSharedMaterial = material.Value; ((TMP_Text)text).fontSize = 64f; ((TMP_Text)text).enableAutoSizing = true; ((TMP_Text)text).fontSizeMin = 18f; ((TMP_Text)text).fontSizeMax = 64f; ((Graphic)text).color = new Color(0.87f, 0.96f, 1f, 1f); ((TMP_Text)text).alignment = (TextAlignmentOptions)514; ((TMP_Text)text).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)text).overflowMode = (TextOverflowModes)1; ((TMP_Text)text).richText = false; ((Graphic)text).raycastTarget = false; lastUsed = (lastTotal = -1); dirty = true; } } private void FindNameplate() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Invalid comparison between Unknown and I4 nameplate = null; nameplateCanvas = null; ((Component)this).GetComponentsInChildren(true, nameplateCandidates); foreach (WorldObjectText nameplateCandidate in nameplateCandidates) { if ((Object)(object)nameplateCandidate == (Object)null || (Object)(object)nameplateCandidate.textContainer == (Object)null) { continue; } Canvas componentInParent = ((Component)nameplateCandidate.textContainer).GetComponentInParent(true); if (!((Object)(object)componentInParent == (Object)null) && (int)componentInParent.renderMode == 2) { nameplate = nameplateCandidate.textContainer; nameplateCanvas = componentInParent; if (((Component)nameplate).gameObject.activeInHierarchy) { break; } } } nameplateCandidates.Clear(); } private void RefreshPlacement() { if (billboard || (Object)(object)nameplate == (Object)null || (Object)(object)nameplateCanvas == (Object)null) { FindNameplate(); } PositionVisual(); } private void PositionVisual() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010d: 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_012b: 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_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: 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_0057: 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_0073: 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_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: 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_00f1: 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) float width = 0.6f; Vector3 position = default(Vector3); bool flag = false; if ((Object)(object)nameplate != (Object)null && (Object)(object)nameplateCanvas != (Object)null && (int)nameplateCanvas.renderMode == 2) { ((TMP_Text)nameplate).rectTransform.GetWorldCorners(corners); flag = CounterPlacement.TryNameplate(corners[0], corners[3], ((TMP_Text)nameplate).transform.up, ((TMP_Text)nameplate).transform.forward, out position, out width); } bool flag2 = billboard; billboard = !flag; if (flag) { if (visualTransform.position != position) { visualTransform.position = position; } Quaternion rotation = ((TMP_Text)nameplate).transform.rotation; if (visualTransform.rotation != rotation) { visualTransform.rotation = rotation; } } else if (!flag2) { Bounds val = LocalBounds(); visualTransform.localPosition = new Vector3(((Bounds)(ref val)).center.x, ((Bounds)(ref val)).max.y + 0.12f, ((Bounds)(ref val)).center.z); } if (flag2 != billboard) { if (billboard && visual.activeSelf) { plugin.AddBillboard(visualTransform); } else { plugin.RemoveBillboard(visualTransform); } } Vector3 lossyScale = ((Component)this).transform.lossyScale; float num = width / 600f; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(num / Mathf.Max(Mathf.Abs(lossyScale.x), 0.0001f), num / Mathf.Max(Mathf.Abs(lossyScale.y), 0.0001f), num / Mathf.Max(Mathf.Abs(lossyScale.z), 0.0001f)); if (visualTransform.localScale != val2) { visualTransform.localScale = val2; } } private Bounds LocalBounds() { //IL_0002: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) Bounds result = default(Bounds); ((Bounds)(ref result))..ctor(Vector3.zero, new Vector3(0.6f, 0.8f, 0.6f)); bool flag = false; Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!(val is MeshRenderer) && !(val is SkinnedMeshRenderer)) { continue; } Bounds localBounds = val.localBounds; for (int j = 0; j < 8; j++) { Vector3 val2 = ((Bounds)(ref localBounds)).center + Vector3.Scale(((Bounds)(ref localBounds)).extents, new Vector3((float)(((j & 1) != 0) ? 1 : (-1)), (float)(((j & 2) != 0) ? 1 : (-1)), (float)(((j & 4) != 0) ? 1 : (-1)))); Vector3 val3 = ((Component)this).transform.InverseTransformPoint(((Component)val).transform.TransformPoint(val2)); if (!flag) { ((Bounds)(ref result))..ctor(val3, Vector3.zero); flag = true; } else { ((Bounds)(ref result)).Encapsulate(val3); } } } return result; } private void OnDisable() { try { Suspend(); } catch (Exception ex) { if ((Object)(object)plugin != (Object)null) { plugin.Warn(ex); } } } private void OnDestroy() { Dispose(); } private void ReleaseMaterial() { Plugin.TextMaterial textMaterial = material; material = null; if ((Object)(object)plugin != (Object)null) { plugin.ReleaseTextMaterial(textMaterial); } } internal void Dispose() { if (disposed) { return; } disposed = true; try { Suspend(); } catch (Exception ex) { if ((Object)(object)plugin != (Object)null) { plugin.Warn(ex); } } if ((Object)(object)visual != (Object)null) { Object.Destroy((Object)(object)visual); } ReleaseMaterial(); } } internal static class CapacityText { internal static int UsedSlots(Inventory inventory) { return inventory.GetInsideWorldObjects().Count; } internal static string Format(string format, int used, int total) { if (string.IsNullOrWhiteSpace(format)) { format = "{used} / {total}"; } return format.Replace("{used}", used.ToString(CultureInfo.InvariantCulture)).Replace("{total}", total.ToString(CultureInfo.InvariantCulture)); } } internal static class CounterPlacement { internal static bool TryNameplate(Vector3 bottomLeft, Vector3 bottomRight, Vector3 up, Vector3 forward, out Vector3 position, out float width) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_0082: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); width = 0.6f; float num = Vector3.Distance(bottomLeft, bottomRight); if (float.IsNaN(num) || float.IsInfinity(num) || num < 0.001f) { return false; } width = Mathf.Clamp(num, 0.3f, 1.2f); position = (bottomLeft + bottomRight) * 0.5f - up * (width / 12f + 0.015f) - forward * 0.012f; return true; } } [BepInPlugin("noxie.planetcrafter.storagecapacitydisplay", "Storage Capacity Display", "1.0.2")] [BepInProcess("Planet Crafter.exe")] public sealed class Plugin : BaseUnityPlugin { internal struct TickContext { internal InventoriesHandler Handler; internal bool Enabled; internal bool HasCamera; internal bool NearbyOnly; internal Vector3 CameraPosition; internal float Now; internal float DistanceSquared; internal string Format; } internal sealed class TextMaterial { internal Material Source; internal Material Value; internal int References; } public const string Id = "noxie.planetcrafter.storagecapacitydisplay"; internal static Plugin Instance; internal ConfigEntry EnabledSetting; internal ConfigEntry NearbyOnly; internal ConfigEntry MaxDistance; internal ConfigEntry Format; private Camera viewCamera; private readonly List displays = new List(); private readonly SubscriberIndex subscriptions = new SubscriberIndex(); private readonly List billboards = new List(); private readonly Dictionary materials = new Dictionary(); private Harmony harmony; private float nextWarning; private bool ready; private bool discover = true; private int tickCursor; private void Awake() { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown Instance = this; EnabledSetting = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Show storage capacity counters."); Format = ((BaseUnityPlugin)this).Config.Bind("General", "DisplayFormat", "{used} / {total}", "Plain text. Tokens: {used}, {total}."); NearbyOnly = ((BaseUnityPlugin)this).Config.Bind("General", "ShowOnlyWhenNearby", false, "Hide counters beyond MaxDisplayDistance. Otherwise use normal world rendering."); MaxDistance = ((BaseUnityPlugin)this).Config.Bind("General", "MaxDisplayDistance", 20f, new ConfigDescription("Display range in metres when ShowOnlyWhenNearby is enabled.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 200f), Array.Empty())); harmony = new Harmony("noxie.planetcrafter.storagecapacitydisplay"); try { harmony.PatchAll(typeof(Plugin).Assembly); ready = true; ((MonoBehaviour)this).StartCoroutine(Tick()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Storage Capacity Display 1.0.2 loaded. Container discovery and inventory snapshot Harmony patches applied; read-only counters enabled."); } catch (Exception ex) { harmony.UnpatchSelf(); ((BaseUnityPlugin)this).Logger.LogError((object)("Storage Capacity Display startup failed; its patches were removed. " + ex)); } } internal void Discover(ActionOpenable action) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!ready || (Object)(object)action == (Object)null || action.notAContainer) { return; } Scene scene = ((Component)action).gameObject.scene; if (!((Scene)(ref scene)).IsValid()) { return; } try { InventoryAssociatedProxy componentInParent = ((Component)action).GetComponentInParent(); InventoryAssociated componentInParent2 = ((Component)action).GetComponentInParent(); Component val = (Component)(((Object)(object)componentInParent != (Object)null) ? ((object)componentInParent) : ((object)componentInParent2)); if (!((Object)(object)val == (Object)null) && !((Object)(object)val.GetComponentInParent() != (Object)null)) { CapacityDisplay component = val.GetComponent(); if (!((Object)(object)component != (Object)null)) { component = val.gameObject.AddComponent(); component.Initialize(this, componentInParent, componentInParent2); displays.Add(component); } } } catch (Exception ex) { Warn(ex); } } internal void Register(int id, CapacityDisplay display) { subscriptions.Add(id, display); } internal void Unregister(int id, CapacityDisplay display) { subscriptions.Remove(id, display); } internal void AddBillboard(Transform target) { if (!billboards.Contains(target)) { billboards.Add(target); } } internal void RemoveBillboard(Transform target) { billboards.Remove(target); } internal TextMaterial GetTextMaterial(TMP_FontAsset font) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown Material material = ((TMP_Asset)font).material; if (materials.TryGetValue(material, out var value)) { value.References++; return value; } Material val = new Material(material); val.SetFloat("unity_GUIZTestMode", 4f); if (val.HasProperty("_ZTestMode")) { val.SetFloat("_ZTestMode", 4f); } value = new TextMaterial { Source = material, Value = val, References = 1 }; materials.Add(material, value); return value; } internal void ReleaseTextMaterial(TextMaterial material) { if (material != null && --material.References == 0) { materials.Remove(material.Source); if ((Object)(object)material.Value != (Object)null) { Object.Destroy((Object)(object)material.Value); } } } internal void Snapshot(InventoriesHandler handler, Inventory inventory) { if (inventory == null || !subscriptions.TryGet(inventory.GetId(), out var subscribers)) { return; } foreach (CapacityDisplay item in subscribers) { if ((Object)(object)item != (Object)null) { item.Snapshot(handler, inventory); } } } private IEnumerator Tick() { WaitForSecondsRealtime delay = new WaitForSecondsRealtime(0.2f); while (ready) { if (discover) { discover = false; ActionOpenable[] array = Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0); foreach (ActionOpenable action in array) { Discover(action); } } viewCamera = Camera.main; bool flag = (Object)(object)viewCamera != (Object)null; float value = MaxDistance.Value; TickContext context = new TickContext { Handler = InventoriesHandler.Instance, Enabled = EnabledSetting.Value, HasCamera = flag, NearbyOnly = NearbyOnly.Value, CameraPosition = (flag ? ((Component)viewCamera).transform.position : Vector3.zero), Now = Time.unscaledTime, DistanceSquared = value * value, Format = Format.Value }; int requestBudget = 4; int visualBudget = 4; for (int num = displays.Count - 1; num >= 0; num--) { if ((Object)(object)displays[num] == (Object)null) { displays.RemoveAt(num); } } int count = displays.Count; for (int j = 0; j < count; j++) { CapacityDisplay capacityDisplay = displays[(tickCursor + j) % count]; try { capacityDisplay.Tick(context, ref requestBudget, ref visualBudget); } catch (Exception ex) { capacityDisplay.Suspend(); Warn(ex); } } tickCursor = ((count != 0) ? ((tickCursor + 4) % count) : 0); yield return delay; } } private void LateUpdate() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (!ready || billboards.Count == 0 || (Object)(object)viewCamera == (Object)null) { return; } Quaternion rotation = ((Component)viewCamera).transform.rotation; for (int num = billboards.Count - 1; num >= 0; num--) { Transform val = billboards[num]; if ((Object)(object)val == (Object)null) { billboards.RemoveAt(num); } else if (val.rotation != rotation) { val.rotation = rotation; } } } internal void Warn(Exception ex) { if (!(Time.unscaledTime < nextWarning)) { nextWarning = Time.unscaledTime + 30f; ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not refresh a storage counter; container gameplay is unaffected. " + ex)); } } private void OnDestroy() { ready = false; ((MonoBehaviour)this).StopAllCoroutines(); foreach (CapacityDisplay display in displays) { if ((Object)(object)display != (Object)null) { display.Dispose(); Object.Destroy((Object)(object)display); } } displays.Clear(); subscriptions.Clear(); billboards.Clear(); foreach (TextMaterial value in materials.Values) { if ((Object)(object)value.Value != (Object)null) { Object.Destroy((Object)(object)value.Value); } } materials.Clear(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } [HarmonyPatch(typeof(ActionOpenable), "Start")] internal static class ContainerStarted { private static void Postfix(ActionOpenable __instance) { Plugin.Instance?.Discover(__instance); } } [HarmonyPatch(typeof(InventoriesHandler), "UpdateOrCreateInventoryFromMessage")] internal static class InventorySnapshot { private static void Postfix(InventoriesHandler __instance, Inventory __result) { try { Plugin.Instance?.Snapshot(__instance, __result); } catch (Exception ex) { Plugin.Instance?.Warn(ex); } } } internal sealed class SubscriberIndex where T : class { private readonly Dictionary> entries = new Dictionary>(); internal int Count => entries.Count; internal void Add(int id, T subscriber) { if (!entries.TryGetValue(id, out var value)) { value = new HashSet(); entries.Add(id, value); } value.Add(subscriber); } internal void Remove(int id, T subscriber) { if (entries.TryGetValue(id, out var value)) { value.Remove(subscriber); if (value.Count == 0) { entries.Remove(id); } } } internal bool TryGet(int id, out HashSet subscribers) { return entries.TryGetValue(id, out subscribers); } internal void Clear() { entries.Clear(); } } }