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 ItemMarkers v1.0.0
ItemMarkers.dll
Decompiled 14 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ItemMarkers.Core; using Microsoft.CodeAnalysis; using RoR2; using RoR2.Artifacts; using RoR2.UI; using TMPro; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Morslord")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ItemMarkers")] [assembly: AssemblyTitle("ItemMarkers")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 ItemMarkers { public sealed class DiamondGraphic : MaskableGraphic { private Color borderColor; private bool border; public void SetColors(Color fill, bool hasBorder, Color outline) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_001d: Unknown result type (might be due to invalid IL or missing references) if (!(((Graphic)this).color == fill) || border != hasBorder || !(borderColor == outline)) { ((Graphic)this).color = fill; border = hasBorder; borderColor = outline; ((Graphic)this).SetVerticesDirty(); } } protected override void OnPopulateMesh(VertexHelper mesh) { //IL_0007: 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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: 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_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: 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_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: 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_0184: 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_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: 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_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) mesh.Clear(); Rect pixelAdjustedRect = ((Graphic)this).GetPixelAdjustedRect(); Vector2 center = ((Rect)(ref pixelAdjustedRect)).center; float num = Mathf.Min(((Rect)(ref pixelAdjustedRect)).width, ((Rect)(ref pixelAdjustedRect)).height) * 0.5f; float num2 = (border ? Mathf.Max(0f, num - 1.25f) : num); Vector2[] array = (Vector2[])(object)new Vector2[4] { Vector2.up, Vector2.right, Vector2.down, Vector2.left }; mesh.AddVert(Vector2.op_Implicit(center), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero)); for (int i = 0; i < 4; i++) { mesh.AddVert(Vector2.op_Implicit(center + array[i] * num2), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero)); } for (int j = 0; j < 4; j++) { mesh.AddTriangle(0, j + 1, (j + 1) % 4 + 1); } if (border) { for (int k = 0; k < 4; k++) { int num3 = (k + 1) % 4; int currentVertCount = mesh.currentVertCount; mesh.AddVert(Vector2.op_Implicit(center + array[k] * num), Color32.op_Implicit(borderColor), Vector4.op_Implicit(Vector2.zero)); mesh.AddVert(Vector2.op_Implicit(center + array[num3] * num), Color32.op_Implicit(borderColor), Vector4.op_Implicit(Vector2.zero)); mesh.AddVert(Vector2.op_Implicit(center + array[num3] * num2), Color32.op_Implicit(borderColor), Vector4.op_Implicit(Vector2.zero)); mesh.AddVert(Vector2.op_Implicit(center + array[k] * num2), Color32.op_Implicit(borderColor), Vector4.op_Implicit(Vector2.zero)); mesh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2); mesh.AddTriangle(currentVertCount, currentVertCount + 2, currentVertCount + 3); } } } } internal sealed class HudMarkerLayer : IDisposable { private readonly HUD hud; private readonly RectTransform root; private readonly List<MarkerView> views = new List<MarkerView>(60); private readonly NearestMarkers<MarkerTarget> nearest = new NearestMarkers<MarkerTarget>(); private readonly TMP_FontAsset? font; private readonly PickupIconCache icons; public bool IsValid { get { if (Object.op_Implicit((Object)(object)hud) && Object.op_Implicit((Object)(object)root) && Object.op_Implicit((Object)(object)hud.mainContainer)) { return (Object)(object)((Transform)root).parent == (Object)(object)hud.mainContainer.transform; } return false; } } public HudMarkerLayer(HUD hud, PickupIconCache icons) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) this.hud = hud; this.icons = icons; GameObject val = new GameObject("Morslord.ItemMarkers.Hud", new Type[1] { typeof(RectTransform) }); val.layer = hud.mainContainer.layer; root = val.GetComponent<RectTransform>(); ((Transform)root).SetParent(hud.mainContainer.transform, false); root.anchorMin = Vector2.zero; root.anchorMax = Vector2.one; root.offsetMin = (root.offsetMax = Vector2.zero); TMP_Text componentInChildren = ((Component)hud).GetComponentInChildren<TMP_Text>(true); font = (Object.op_Implicit((Object)(object)componentInChildren) ? componentInChildren.font : TMP_Settings.defaultFontAsset); } public void Select(List<MarkerTarget> targets, MarkerSettings settings) { //IL_0078: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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_00aa: 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) nearest.Clear(); Camera val = (Object.op_Implicit((Object)(object)hud.cameraRigController) ? hud.cameraRigController.sceneCam : null); if ((Object)(object)val == (Object)null || !Object.op_Implicit((Object)(object)val)) { Hide(); return; } Vector3 val2 = (Object.op_Implicit((Object)(object)hud.targetBodyObject) ? hud.targetBodyObject.transform.position : ((Component)val).transform.position); foreach (MarkerTarget target in targets) { if (target.IsAlive) { Vector3 val3 = target.Source.transform.position - val2; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (MarkerRules.ShouldShowAtDistance(sqrMagnitude, settings.HideWithinDistance.Value)) { nearest.Consider(target, sqrMagnitude, target.Identity, settings.MaximumMarkers.Value); } } } while (views.Count < nearest.Count) { views.Add(new MarkerView(root, font, icons)); } for (int i = 0; i < views.Count; i++) { if (i < nearest.Count) { views[i].Bind(nearest[i]); } else { views[i].Hide(); } } } public void Render(MarkerSettings settings) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0102: 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_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0178: 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_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) Camera val = (Object.op_Implicit((Object)(object)hud.cameraRigController) ? hud.cameraRigController.sceneCam : null); if ((Object)(object)val == (Object)null || !Object.op_Implicit((Object)(object)val) || !((Behaviour)val).isActiveAndEnabled || !hud.mainContainer.activeInHierarchy || !Object.op_Implicit((Object)(object)Run.instance) || settings.MaximumMarkers.Value == 0) { Hide(); return; } Vector3 val2 = (Object.op_Implicit((Object)(object)hud.targetBodyObject) ? hud.targetBodyObject.transform.position : ((Component)val).transform.position); float num = MarkerRules.ScaleFromPercent(settings.MarkerSize.Value); for (int i = 0; i < nearest.Count; i++) { MarkerTarget markerTarget = nearest[i]; if (markerTarget.IsAlive && i < MarkerRules.ClampLimit(settings.MaximumMarkers.Value)) { MarkerCategory category = markerTarget.Category; UniquePickup pickup = markerTarget.Pickup; if (settings.Allows(category, ((UniquePickup)(ref pickup)).isTempItem, markerTarget.Pickup.isRental)) { Vector3 val3 = markerTarget.Source.transform.position - val2; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (!MarkerRules.ShouldShowAtDistance(sqrMagnitude, settings.HideWithinDistance.Value)) { views[i].Hide(); continue; } Vector3 val4 = val.WorldToViewportPoint(markerTarget.Position); float x = val4.x; float y = val4.y; float z = val4.z; Rect rect = root.rect; float width = ((Rect)(ref rect)).width; rect = root.rect; if (!MarkerProjection.TryPlace(x, y, z, width, ((Rect)(ref rect)).height, 45f * num, 48f * num, out var placement)) { views[i].Hide(); continue; } float distance = Mathf.Sqrt(sqrMagnitude); views[i].Show(new Vector2(placement.X, placement.Y), num, distance); continue; } } views[i].Hide(); } } public void Hide() { foreach (MarkerView view in views) { view.Hide(); } } public void Dispose() { if (Object.op_Implicit((Object)(object)root)) { Object.Destroy((Object)(object)((Component)root).gameObject); } views.Clear(); nearest.Clear(); } } internal sealed class MarkerView { private readonly RectTransform root; private readonly Image image; private readonly RawImage textureImage; private readonly DiamondGraphic diamond; private readonly TextMeshProUGUI distanceLabel; private readonly PickupIconCache icons; private int previousDistance = -1; public MarkerView(RectTransform parent, TMP_FontAsset? font, PickupIconCache icons) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0148: 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_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) this.icons = icons; root = MakeRect("Marker", (Transform)(object)parent, new Vector2(90f, 84f), Vector2.zero); image = ((Component)MakeRect("Item Icon", (Transform)(object)root, new Vector2(32f, 32f), new Vector2(0f, 6f))).gameObject.AddComponent<Image>(); image.preserveAspect = true; ((Graphic)image).raycastTarget = false; textureImage = ((Component)MakeRect("Item Texture", (Transform)(object)root, new Vector2(32f, 32f), new Vector2(0f, 6f))).gameObject.AddComponent<RawImage>(); ((Graphic)textureImage).raycastTarget = false; diamond = ((Component)MakeRect("Command Diamond", (Transform)(object)root, new Vector2(18f, 18f), new Vector2(0f, 6f))).gameObject.AddComponent<DiamondGraphic>(); ((Graphic)diamond).raycastTarget = false; distanceLabel = ((Component)MakeRect("Distance", (Transform)(object)root, new Vector2(90f, 22f), new Vector2(0f, -22f))).gameObject.AddComponent<TextMeshProUGUI>(); if (Object.op_Implicit((Object)(object)font)) { ((TMP_Text)distanceLabel).font = font; } ((TMP_Text)distanceLabel).fontSize = 14f; ((TMP_Text)distanceLabel).alignment = (TextAlignmentOptions)514; ((Graphic)distanceLabel).color = Color.white; ((Graphic)distanceLabel).raycastTarget = false; ((TMP_Text)distanceLabel).enableWordWrapping = false; Shadow obj = ((Component)distanceLabel).gameObject.AddComponent<Shadow>(); obj.effectColor = Color.black; obj.effectDistance = new Vector2(1f, -1f); Hide(); } public void Bind(MarkerTarget target) { //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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) Sprite val = (target.Command ? null : icons.Resolve(target.Definition)); image.sprite = val; ((Behaviour)image).enabled = !target.Command && Object.op_Implicit((Object)(object)val); textureImage.texture = target.Definition.iconTexture; ((Behaviour)textureImage).enabled = !target.Command && !Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)target.Definition.iconTexture); ((Behaviour)diamond).enabled = target.Command; if (target.Command) { Color fill = (target.LunarEquipment ? Color32.op_Implicit(ColorCatalog.GetColor((ColorIndex)5)) : target.Definition.baseColor); diamond.SetColors(fill, target.LunarEquipment, Color32.op_Implicit(ColorCatalog.GetColor((ColorIndex)4))); } } public void Show(Vector2 position, float scale, float distance) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!((Component)root).gameObject.activeSelf) { ((Component)root).gameObject.SetActive(true); } root.anchoredPosition = position; ((Transform)root).localScale = Vector3.one * scale; int num = Mathf.Max(0, Mathf.RoundToInt(distance)); if (num != previousDistance) { ((TMP_Text)distanceLabel).SetText("{0:0} m", (float)num); previousDistance = num; } } public void Hide() { if (((Component)root).gameObject.activeSelf) { ((Component)root).gameObject.SetActive(false); } } private static RectTransform MakeRect(string name, Transform parent, Vector2 size, Vector2 offset) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) RectTransform component = new GameObject(name, new Type[1] { typeof(RectTransform) }) { layer = ((Component)parent).gameObject.layer }.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); component.pivot = val; Vector2 anchorMin = (component.anchorMax = val); component.anchorMin = anchorMin; component.sizeDelta = size; component.anchoredPosition = offset; return component; } } internal readonly struct MarkerTarget { public Component Source { get; } public UniquePickup Pickup { get; } public bool Command { get; } public PickupDef Definition { get; } public MarkerCategory Category { get; } public bool LunarEquipment { get; } public int Identity { get; } public bool IsAlive { get { //IL_0049: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)Source) && Source.gameObject.activeInHierarchy) { if (!Command) { return ((GenericPickupController)Source).pickup == Pickup; } return ((PickupPickerController)Source).available; } return false; } } public Vector3 Position => Source.transform.position + Vector3.up * 0.8f; public MarkerTarget(Component source, UniquePickup pickup, bool command, PickupDef definition, MarkerCategory category, bool lunarEquipment) { //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) Source = source; Pickup = pickup; Command = command; Definition = definition; Category = category; LunarEquipment = lunarEquipment; Identity = ((Object)source).GetInstanceID(); } } internal static class PickupDiscovery { private static readonly FieldInfo? CommandPrefab = typeof(CommandArtifactManager).GetField("commandCubePrefab", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); public static void Collect(List<MarkerTarget> targets, MarkerSettings settings) { //IL_002c: 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_00bf: Unknown result type (might be due to invalid IL or missing references) targets.Clear(); foreach (GenericPickupController instances in InstanceTracker.GetInstancesList<GenericPickupController>()) { if (Object.op_Implicit((Object)(object)instances) && ((Behaviour)instances).isActiveAndEnabled && TryDescribe(instances.pickup, settings, out PickupDef def, out MarkerCategory category, out bool lunarEquipment)) { targets.Add(new MarkerTarget((Component)(object)instances, instances.pickup, command: false, def, category, lunarEquipment)); } } foreach (PickupPickerController instances2 in InstanceTracker.GetInstancesList<PickupPickerController>()) { if (Object.op_Implicit((Object)(object)instances2) && ((Behaviour)instances2).isActiveAndEnabled && instances2.available && IsCommandEssence(instances2) && TryDescribeCommand(instances2, settings, out UniquePickup pickup, out PickupDef def2, out MarkerCategory category2, out bool lunar)) { targets.Add(new MarkerTarget((Component)(object)instances2, pickup, command: true, def2, category2, lunar)); } } } private static bool TryDescribe(UniquePickup pickup, MarkerSettings settings, out PickupDef? def, out MarkerCategory category, out bool lunarEquipment) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) def = PickupCatalog.GetPickupDef(pickup.pickupIndex); category = MarkerCategory.Unknown; lunarEquipment = false; if (def == null) { return false; } if ((int)def.equipmentIndex != -1) { EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(def.equipmentIndex); if (!Object.op_Implicit((Object)(object)equipmentDef)) { return false; } lunarEquipment = equipmentDef.isLunar; category = MarkerCategory.Equipment; } else if ((int)def.itemIndex != -1) { ItemDef itemDef = ItemCatalog.GetItemDef(def.itemIndex); if (!Object.op_Implicit((Object)(object)itemDef) || itemDef.hidden) { return false; } category = MarkerRules.Classify(((object)itemDef.tier/*cast due to .constrained prefix*/).ToString(), equipment: false); } return settings.Allows(category, ((UniquePickup)(ref pickup)).isTempItem, pickup.isRental); } private static bool TryDescribeCommand(PickupPickerController picker, MarkerSettings settings, out UniquePickup pickup, out PickupDef? def, out MarkerCategory category, out bool lunar) { //IL_0001: 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) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0109: 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_007c: Unknown result type (might be due to invalid IL or missing references) pickup = default(UniquePickup); def = null; category = MarkerCategory.Unknown; lunar = false; bool flag = false; if (picker.options == null) { return false; } Option[] options = picker.options; for (int i = 0; i < options.Length; i++) { Option val = options[i]; if (val.available && TryDescribe(val.pickup, settings, out PickupDef def2, out MarkerCategory category2, out bool lunarEquipment)) { if (flag && (category != category2 || lunar != lunarEquipment || ((UniquePickup)(ref pickup)).isTempItem != ((UniquePickup)(ref val.pickup)).isTempItem || pickup.isRental != val.pickup.isRental)) { return false; } if (!flag) { pickup = val.pickup; def = def2; category = category2; lunar = lunarEquipment; flag = true; } } } if (flag && picker.pickupThatGeneratedOptions.HasValue) { UniquePickup value = picker.pickupThatGeneratedOptions.Value; if (!settings.Allows(category, ((UniquePickup)(ref value)).isTempItem, value.isRental)) { return false; } pickup.isRental |= value.isRental; if (((UniquePickup)(ref value)).isTempItem) { pickup.decayValue = value.decayValue; } } return flag; } private static bool IsCommandEssence(PickupPickerController picker) { //IL_005c: 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_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_0075: Unknown result type (might be due to invalid IL or missing references) if (picker.isDelusionChoice || picker.isRebirthChoice) { return false; } object? obj = CommandPrefab?.GetValue(null); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val == (Object)null || !Object.op_Implicit((Object)(object)val)) { return false; } NetworkIdentity component = val.GetComponent<NetworkIdentity>(); NetworkIdentity component2 = ((Component)picker).GetComponent<NetworkIdentity>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component2)) { NetworkHash128 assetId = component.assetId; if (((NetworkHash128)(ref assetId)).IsValid()) { assetId = component.assetId; if (((NetworkHash128)(ref assetId)).Equals(component2.assetId)) { if (!CreatesPickup((UnityEventBase?)(object)picker.onPickupSelected, picker)) { return CreatesPickup((UnityEventBase?)(object)picker.onUniquePickupSelected, picker); } return true; } } } return false; } private static bool CreatesPickup(UnityEventBase? selectionEvent, PickupPickerController picker) { if (selectionEvent == null) { return false; } for (int i = 0; i < selectionEvent.GetPersistentEventCount(); i++) { if (selectionEvent.GetPersistentTarget(i) == (Object)(object)picker && selectionEvent.GetPersistentMethodName(i) == "CreatePickup") { return true; } } return false; } } internal sealed class PickupIconCache { private sealed class SpriteRequest : IAssetRequest<Sprite>, IDisposable { private AsyncOperationHandle<Sprite> handle; private bool released; public bool IsDone { get { if (!released && handle.IsValid()) { return handle.IsDone; } return false; } } public Sprite? Asset { get { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 if (!IsDone || (int)handle.Status != 1) { return null; } return handle.Result; } } public Exception? Error { get { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 if (!IsDone || (int)handle.Status != 2) { return null; } return handle.OperationException ?? new InvalidOperationException("Addressable sprite load failed."); } } public SpriteRequest(object key) { //IL_0008: 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) handle = Addressables.LoadAssetAsync<Sprite>(key); } public void Dispose() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!released) { released = true; if (handle.IsValid()) { Addressables.Release<Sprite>(handle); } handle = default(AsyncOperationHandle<Sprite>); } } } private readonly AsyncAssetCache<object, Sprite> sprites; private readonly ManualLogSource log; private int failures; public PickupIconCache(ManualLogSource log) { this.log = log; sprites = new AsyncAssetCache<object, Sprite>((object key) => new SpriteRequest(key), ReportFailure); } public Sprite? Resolve(PickupDef definition) { Sprite icon = definition.GetIcon(); if (Object.op_Implicit((Object)(object)icon)) { return icon; } AssetReferenceT<Sprite> iconReference = definition.GetIconReference(); if (iconReference == null || !((AssetReference)iconReference).RuntimeKeyIsValid()) { return null; } return sprites.Get(((AssetReference)iconReference).RuntimeKey); } public void Clear() { sprites.Clear(); failures = 0; } private void ReportFailure(object key, Exception error) { if (failures < 5) { log.LogWarning((object)("ItemMarkers could not load/release pickup icon '" + key?.ToString() + "': " + error)); } else if (failures == 5) { log.LogWarning((object)"Further pickup icon errors are suppressed until the next run."); } failures++; } } internal static class OptionalOptionsMenu { public const string Guid = "com.rune580.riskofoptions"; private static Texture2D? modIconTexture; private static Sprite? modIcon; public static void Register(MarkerSettings settings, ManualLogSource log) { if (!Chainloader.PluginInfos.TryGetValue("com.rune580.riskofoptions", out var value)) { return; } try { Assembly assembly = ((object)value.Instance).GetType().Assembly; Type type = RequiredType(assembly, "RiskOfOptions.ModSettingsManager"); Type type2 = RequiredType(assembly, "RiskOfOptions.Options.BaseOption"); MethodInfo add = type.GetMethod("AddOption", new Type[3] { type2, typeof(string), typeof(string) }) ?? throw new MissingMethodException("RiskOfOptions.ModSettingsManager.AddOption"); object optionConfig = NewConfig(assembly, "IntSliderConfig", ("min", 0), ("max", 60)); object optionConfig2 = NewConfig(assembly, "IntSliderConfig", ("min", 0), ("max", 50), ("formatString", "{0} m")); object optionConfig3 = NewConfig(assembly, "StepSliderConfig", ("min", 50f), ("max", 200f), ("increment", 5f), ("remapManualInputToStep", true)); Add("IntSliderOption", (ConfigEntryBase)(object)settings.MaximumMarkers, optionConfig); Add("StepSliderOption", (ConfigEntryBase)(object)settings.MarkerSize, optionConfig3); Add("IntSliderOption", (ConfigEntryBase)(object)settings.HideWithinDistance, optionConfig2); Add("CheckBoxOption", (ConfigEntryBase)(object)settings.ShowTemporary); Add("CheckBoxOption", (ConfigEntryBase)(object)settings.ShowEthereal); foreach (ConfigEntry<bool> value2 in settings.Categories.Values) { Add("CheckBoxOption", (ConfigEntryBase)(object)value2); } type.GetMethod("SetModDescription", new Type[3] { typeof(string), typeof(string), typeof(string) })?.Invoke(null, new object[3] { "Client-side ground item and Command essence markers by Morslord.", "com.morslord.itemmarkers", "ItemMarkers" }); RegisterIcon(type, log); log.LogInfo((object)("Registered " + (5 + settings.Categories.Count) + " ItemMarkers options in RiskOfOptions.")); void Add(string optionName, ConfigEntryBase entry, object? obj2 = null) { Type type3 = RequiredType(assembly, "RiskOfOptions.Options." + optionName); object obj = ((obj2 == null) ? Activator.CreateInstance(type3, entry) : Activator.CreateInstance(type3, entry, obj2)); add.Invoke(null, new object[3] { obj, "com.morslord.itemmarkers", "ItemMarkers" }); } } catch (Exception ex) { log.LogError((object)("RiskOfOptions registration failed. BepInEx configuration remains available. " + ex)); } } private static void RegisterIcon(Type manager, ManualLogSource log) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) try { MethodInfo methodInfo = manager.GetMethod("SetModIcon", new Type[3] { typeof(Sprite), typeof(string), typeof(string) }) ?? throw new MissingMethodException("RiskOfOptions.ModSettingsManager.SetModIcon(Sprite, string, string)"); if (!Object.op_Implicit((Object)(object)modIcon)) { using Stream stream = typeof(OptionalOptionsMenu).Assembly.GetManifestResourceStream("ItemMarkers.Resources.ModIcon.png") ?? throw new InvalidOperationException("Embedded ItemMarkers mod icon is missing."); using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); Texture2D val = (modIconTexture = new Texture2D(2, 2, (TextureFormat)4, false)); if (!ImageConversion.LoadImage(val, memoryStream.ToArray(), true)) { throw new InvalidOperationException("Embedded ItemMarkers mod icon could not be decoded as PNG."); } ((Object)val).name = "ItemMarkers Mod Icon"; ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; modIcon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); if (!Object.op_Implicit((Object)(object)modIcon)) { throw new InvalidOperationException("Could not create ItemMarkers mod icon sprite."); } ((Object)modIcon).name = "ItemMarkers Mod Icon"; } methodInfo.Invoke(null, new object[3] { modIcon, "com.morslord.itemmarkers", "ItemMarkers" }); log.LogInfo((object)"Registered embedded ItemMarkers mod icon in RiskOfOptions."); } catch (Exception ex) { ReleaseIcon(); log.LogWarning((object)("RiskOfOptions mod icon registration failed; settings remain available. " + ex)); } } public static void ReleaseIcon() { if (Object.op_Implicit((Object)(object)modIcon)) { Object.Destroy((Object)(object)modIcon); } if (Object.op_Implicit((Object)(object)modIconTexture)) { Object.Destroy((Object)(object)modIconTexture); } modIcon = null; modIconTexture = null; } private static Type RequiredType(Assembly assembly, string name) { return assembly.GetType(name, throwOnError: true); } private static object NewConfig(Assembly assembly, string name, params (string name, object value)[] values) { Type type = RequiredType(assembly, "RiskOfOptions.OptionConfigs." + name); object obj = Activator.CreateInstance(type); for (int i = 0; i < values.Length; i++) { (string, object) tuple = values[i]; (type.GetField(tuple.Item1) ?? throw new MissingFieldException(type.FullName, tuple.Item1)).SetValue(obj, tuple.Item2); } return obj; } } [BepInPlugin("com.morslord.itemmarkers", "ItemMarkers", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class ItemMarkersPlugin : BaseUnityPlugin { public const string PluginGuid = "com.morslord.itemmarkers"; public const string PluginName = "ItemMarkers"; public const string PluginVersion = "1.0.0"; public const string ConfigFileName = "local.itemmarkers.cfg"; private MarkerSettings settings; private PickupIconCache? icons; private Run? iconRun; private readonly List<MarkerTarget> targets = new List<MarkerTarget>(128); private readonly Dictionary<HUD, HudMarkerLayer> layers = new Dictionary<HUD, HudMarkerLayer>(); private readonly List<HUD> staleHuds = new List<HUD>(); private float nextSweep; private float nextErrorLog; private void Awake() { try { settings = new MarkerSettings(OpenMarkerConfig()); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not initialize local.itemmarkers.cfg; ItemMarkers is disabled to avoid replacing existing settings. " + ex)); ((Behaviour)this).enabled = false; return; } icons = new PickupIconCache(((BaseUnityPlugin)this).Logger); ((BaseUnityPlugin)this).Logger.LogInfo((object)"ItemMarkers 1.0.0 by Morslord initialized. Local HUD only."); } private ConfigFile OpenMarkerConfig() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown string text = Path.Combine(Paths.ConfigPath, "local.itemmarkers.cfg"); string text2 = Path.Combine(Paths.ConfigPath, "com.morslord.itemmarkers.cfg"); if (!File.Exists(text) && File.Exists(text2)) { File.Copy(text2, text, overwrite: false); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Copied existing settings to local.itemmarkers.cfg; the original configuration is retained."); } return new ConfigFile(text, true, ((BaseUnityPlugin)this).Info.Metadata); } private void Start() { OptionalOptionsMenu.Register(settings, ((BaseUnityPlugin)this).Logger); } private void LateUpdate() { try { if (iconRun != Run.instance) { ClearLayers(); icons?.Clear(); iconRun = Run.instance; } if (!Object.op_Implicit((Object)(object)Run.instance) || HUD.readOnlyInstanceList.Count == 0 || MarkerRules.ClampLimit(settings.MaximumMarkers.Value) == 0) { ClearLayers(); targets.Clear(); nextSweep = 0f; return; } if (Time.unscaledTime >= nextSweep) { nextSweep = Time.unscaledTime + 0.2f; PickupDiscovery.Collect(targets, settings); RefreshHuds(); foreach (HudMarkerLayer value in layers.Values) { value.Select(targets, settings); } } foreach (HudMarkerLayer value2 in layers.Values) { value2.Render(settings); } } catch (Exception ex) { ClearLayers(); targets.Clear(); nextSweep = Time.unscaledTime + 2f; if (Time.unscaledTime >= nextErrorLog) { nextErrorLog = Time.unscaledTime + 10f; ((BaseUnityPlugin)this).Logger.LogError((object)("ItemMarkers HUD update failed; retrying discovery after two seconds. " + ex)); } } } private void RefreshHuds() { staleHuds.Clear(); foreach (KeyValuePair<HUD, HudMarkerLayer> layer in layers) { if (!Object.op_Implicit((Object)(object)layer.Key) || !layer.Value.IsValid || !HUD.readOnlyInstanceList.Contains(layer.Key)) { staleHuds.Add(layer.Key); } } foreach (HUD staleHud in staleHuds) { layers[staleHud].Dispose(); layers.Remove(staleHud); } foreach (HUD readOnlyInstance in HUD.readOnlyInstanceList) { if (Object.op_Implicit((Object)(object)readOnlyInstance) && Object.op_Implicit((Object)(object)readOnlyInstance.mainContainer) && Object.op_Implicit((Object)(object)readOnlyInstance.cameraRigController) && !layers.ContainsKey(readOnlyInstance)) { layers.Add(readOnlyInstance, new HudMarkerLayer(readOnlyInstance, icons)); } } } private void OnDisable() { ClearLayers(); icons?.Clear(); iconRun = null; } private void OnDestroy() { ClearLayers(); icons?.Clear(); iconRun = null; OptionalOptionsMenu.ReleaseIcon(); } private void ClearLayers() { foreach (HudMarkerLayer value in layers.Values) { value.Dispose(); } layers.Clear(); } } internal sealed class MarkerSettings { public readonly ConfigEntry<int> MaximumMarkers; public readonly ConfigEntry<float> MarkerSize; public readonly ConfigEntry<int> HideWithinDistance; public readonly ConfigEntry<bool> ShowTemporary; public readonly ConfigEntry<bool> ShowEthereal; public readonly Dictionary<MarkerCategory, ConfigEntry<bool>> Categories = new Dictionary<MarkerCategory, ConfigEntry<bool>>(); public MarkerSettings(ConfigFile config) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown MaximumMarkers = config.Bind<int>("Markers", "Maximum Markers", 60, new ConfigDescription("Maximum simultaneous markers, including Command essences.\n\n0 hides all markers. The nearest eligible pickups are preferred.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 60), Array.Empty<object>())); MarkerSize = config.Bind<float>("Markers", "Marker Size", 100f, new ConfigDescription("Marker size as a percentage.\n\nApplies to the icon or diamond and the distance label. Steps of 5 percent.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(50f, 200f), Array.Empty<object>())); HideWithinDistance = config.Bind<int>("Markers", "Hide Within Distance", 5, new ConfigDescription("Hide item and Command essence markers when closer than this distance in meters.\n\n0 disables proximity hiding. Steps of 1 meter. Nearby hidden pickups do not use marker slots.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50), Array.Empty<object>())); ShowTemporary = config.Bind<bool>("Item Variants", "Temporary Items", true, "Show temporary items with a decay duration.\n\nThe item's category filter must also be enabled."); ShowEthereal = config.Bind<bool>("Item Variants", "Ethereal Items", true, "Show Ethereal items that last for the current stage.\n\nThe item's category filter must also be enabled. This filter is separate from temporary items."); foreach (MarkerCategory value in Enum.GetValues(typeof(MarkerCategory))) { if (value != MarkerCategory.Unknown) { Categories.Add(value, config.Bind<bool>("Item Categories", value.ToString(), true, "Show " + value.ToString() + " pickups and their Command essences.\n\nTemporary and Ethereal variants must also pass their respective filters.")); } } } public bool Allows(MarkerCategory category, bool temporary, bool ethereal) { ConfigEntry<bool> value; return MarkerRules.Allows(category, Categories.TryGetValue(category, out value) && value.Value, temporary, ethereal, ShowTemporary.Value, ShowEthereal.Value); } } } namespace ItemMarkers.Core { public interface IAssetRequest<TAsset> : IDisposable where TAsset : class { bool IsDone { get; } TAsset? Asset { get; } Exception? Error { get; } } public sealed class AsyncAssetCache<TKey, TAsset> where TKey : notnull where TAsset : class { private sealed class Entry { public IAssetRequest<TAsset>? Request; public bool FailureReported; } private readonly Dictionary<TKey, Entry> entries = new Dictionary<TKey, Entry>(); private readonly Func<TKey, IAssetRequest<TAsset>> load; private readonly Action<TKey, Exception> reportError; public AsyncAssetCache(Func<TKey, IAssetRequest<TAsset>> load, Action<TKey, Exception> reportError) { this.load = load; this.reportError = reportError; } public TAsset? Get(TKey key) { if (!entries.TryGetValue(key, out Entry value)) { value = new Entry(); entries.Add(key, value); try { value.Request = load(key); } catch (Exception error) { ReportOnce(key, value, error); } } IAssetRequest<TAsset> request = value.Request; if (request == null || !request.IsDone) { return null; } if (request.Error != null) { ReportOnce(key, value, request.Error); return null; } TAsset? asset = request.Asset; if (asset == null) { ReportOnce(key, value, new InvalidOperationException("Asset load completed without an asset.")); } return asset; } public void Clear() { foreach (KeyValuePair<TKey, Entry> entry in entries) { try { entry.Value.Request?.Dispose(); } catch (Exception arg) { reportError(entry.Key, arg); } } entries.Clear(); } private void ReportOnce(TKey key, Entry entry, Exception error) { if (!entry.FailureReported) { entry.FailureReported = true; reportError(key, error); } } } public enum MarkerCategory { Unknown, White, Green, Red, Boss, Lunar, Void, Hallowed, Hex, Pages, Equipment } public static class MarkerRules { public static MarkerCategory Classify(string tier, bool equipment) { if (equipment) { return MarkerCategory.Equipment; } switch (tier) { case "Tier1": return MarkerCategory.White; case "Tier2": return MarkerCategory.Green; case "Tier3": return MarkerCategory.Red; case "Boss": return MarkerCategory.Boss; case "Lunar": return MarkerCategory.Lunar; case "Cursed": return MarkerCategory.Hallowed; case "Hex": return MarkerCategory.Hex; case "Page": return MarkerCategory.Pages; default: if (!tier.StartsWith("Void", StringComparison.Ordinal)) { return MarkerCategory.Unknown; } return MarkerCategory.Void; } } public static bool Allows(MarkerCategory category, bool categoryEnabled, bool temporary, bool ethereal, bool showTemporary, bool showEthereal) { if (category != MarkerCategory.Unknown && categoryEnabled && (!temporary || showTemporary)) { return !ethereal || showEthereal; } return false; } public static int ClampLimit(int value) { return Math.Max(0, Math.Min(60, value)); } public static bool ShouldShowAtDistance(float distanceSquared, int hideWithinMeters) { if (!IsFinite(distanceSquared) || distanceSquared < 0f) { return false; } int num = Math.Max(0, Math.Min(50, hideWithinMeters)); if (num != 0) { return distanceSquared >= (float)(num * num); } return true; } public static float ScaleFromPercent(float value) { if (!IsFinite(value)) { return 1f; } return (float)Math.Round(Math.Max(50f, Math.Min(200f, value)) / 5f, MidpointRounding.AwayFromZero) * 0.05f; } public static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } } public readonly struct MarkerPlacement { public float X { get; } public float Y { get; } public bool AtEdge { get; } public MarkerPlacement(float x, float y, bool atEdge) { X = x; Y = y; AtEdge = atEdge; } } public static class MarkerProjection { public static bool TryPlace(float viewportX, float viewportY, float depth, float width, float height, float marginX, float marginY, out MarkerPlacement placement) { placement = default(MarkerPlacement); if (!MarkerRules.IsFinite(viewportX) || !MarkerRules.IsFinite(viewportY) || !MarkerRules.IsFinite(depth) || !MarkerRules.IsFinite(width) || !MarkerRules.IsFinite(height) || width <= 0f || height <= 0f) { return false; } float num = (viewportX - 0.5f) * width; float num2 = (viewportY - 0.5f) * height; float num3 = Math.Max(1f, width / 2f - marginX); float num4 = Math.Max(1f, height / 2f - marginY); bool flag = depth <= 0f || Math.Abs(num) > num3 || Math.Abs(num2) > num4; if (depth <= 0f) { num = 0f - num; num2 = 0f - num2; } if (flag) { if (Math.Abs(num) + Math.Abs(num2) < 0.001f) { num2 = -1f; } float num5 = Math.Max(Math.Abs(num) / num3, Math.Abs(num2) / num4); num /= num5; num2 /= num5; } placement = new MarkerPlacement(num, num2, flag); if (MarkerRules.IsFinite(num)) { return MarkerRules.IsFinite(num2); } return false; } } public sealed class NearestMarkers<T> { private readonly List<(T value, float distance, int identity)> entries = new List<(T, float, int)>(60); public int Count => entries.Count; public T this[int index] => entries[index].value; public void Clear() { entries.Clear(); } public void Consider(T value, float distanceSquared, int identity, int limit) { limit = MarkerRules.ClampLimit(limit); if (limit == 0 || !MarkerRules.IsFinite(distanceSquared) || distanceSquared < 0f) { return; } int i; for (i = 0; i < entries.Count && (entries[i].distance < distanceSquared || (entries[i].distance == distanceSquared && entries[i].identity < identity)); i++) { } if (i < limit) { entries.Insert(i, (value, distanceSquared, identity)); if (entries.Count > limit) { entries.RemoveAt(entries.Count - 1); } } } } }