Decompiled source of ValynBeehiveClearance v0.2.1

plugins/ValynBeehiveClearance.dll

Decompiled 2 weeks ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ValynMods
{
	internal sealed class HudLabel
	{
		private GameObject label;

		private Component textComponent;

		private PropertyInfo textProperty;

		private Hud owner;

		private static readonly FieldInfo StaminaText = typeof(Hud).GetField("m_staminaText");

		private readonly Vector2 position;

		internal HudLabel(float y)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			position = new Vector2(20f, 0f - y);
		}

		internal void Show(string text)
		{
			//IL_0144: 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_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: 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_01d2: Unknown result type (might be due to invalid IL or missing references)
			Hud instance = Hud.instance;
			if ((Object)(object)instance == (Object)null || StaminaText == null || StaminaText.GetValue(instance) == null)
			{
				Hide();
				return;
			}
			if ((Object)(object)label == (Object)null || (Object)(object)owner != (Object)(object)instance)
			{
				if ((Object)(object)label != (Object)null)
				{
					Object.Destroy((Object)(object)label);
				}
				owner = instance;
				object? value = StaminaText.GetValue(instance);
				Component val = (Component)((value is Component) ? value : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				label = Object.Instantiate<GameObject>(val.gameObject, ((Component)instance).transform, false);
				((Object)label).name = "Valyn mod indicator";
				textComponent = label.GetComponent(((object)val).GetType());
				textProperty = ((object)textComponent)?.GetType().GetProperty("text");
				Transform transform = label.transform;
				RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if ((Object)(object)val2 != (Object)null)
				{
					Vector2 val3 = default(Vector2);
					((Vector2)(ref val3))..ctor(0f, 1f);
					val2.anchorMax = val3;
					val2.anchorMin = val3;
					val2.pivot = new Vector2(0f, 1f);
					val2.anchoredPosition = position;
					val2.sizeDelta = new Vector2(310f, 32f);
					((Transform)val2).localScale = Vector3.one;
				}
				PropertyInfo propertyInfo = ((object)textComponent)?.GetType().GetProperty("color");
				if (propertyInfo != null)
				{
					propertyInfo.SetValue(textComponent, Color.cyan);
				}
			}
			if (!((Object)(object)label == (Object)null) && !(textProperty == null))
			{
				label.SetActive(true);
				textProperty.SetValue(textComponent, text);
			}
		}

		internal void Hide()
		{
			if ((Object)(object)label != (Object)null)
			{
				label.SetActive(false);
			}
		}

		internal void Destroy()
		{
			if ((Object)(object)label != (Object)null)
			{
				Object.Destroy((Object)(object)label);
			}
			label = null;
			owner = null;
		}
	}
}
namespace ValynMods.BeehiveClearance
{
	[BepInPlugin("valyn.mods.beehiveclearance", "Beehive Clearance", "0.2.1")]
	public sealed class BeehiveClearance : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(Beehive), "GetHoverText")]
		private static class HoverPatch
		{
			private static void Postfix(Beehive __instance, ref string __result)
			{
				Hover(__instance, ref __result);
			}
		}

		private static BeehiveClearance instance;

		private static readonly FieldInfo GhostField = AccessTools.Field(typeof(Player), "m_placementGhost");

		private static readonly MethodInfo SelectedPieceMethod = AccessTools.Method(typeof(Player), "GetSelectedPiece", (Type[])null, (Type[])null);

		private static readonly Type CoverType = Type.GetType("Cover, assembly_utils");

		private static readonly MethodInfo CoverMethod = CoverType?.GetMethod("GetCoverForPoint", new Type[4]
		{
			typeof(Vector3),
			typeof(float).MakeByRefType(),
			typeof(bool).MakeByRefType(),
			typeof(float)
		});

		private readonly HudLabel previewLabel = new HudLabel(170f);

		private ConfigEntry<bool> showPlacementRing;

		private ConfigEntry<float> placementRingRadius;

		private Harmony harmony;

		private LineRenderer ring;

		private Material ringMaterial;

		private Beehive lastHovered;

		private float hoverUntil;

		private string status;

		private float nextSample;

		private bool preview;

		private bool hasEnoughSpace;

		private bool loggedPrefabFallback;

		private bool ringWarning;

		private void Awake()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			instance = this;
			showPlacementRing = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Show placement status ring", true, "Show a small green/red ring around the beehive ghost. Its color follows the real open-space check.");
			placementRingRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Placement ring radius", 0.65f, "Visual size in meters. The open-space percentage is directional, not a fixed clearance distance.");
			harmony = new Harmony("valyn.mods.beehiveclearance");
			harmony.PatchAll(typeof(BeehiveClearance).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)((CoverMethod == null) ? "Beehive Clearance loaded; cover calculation unavailable for this game build." : "Beehive Clearance loaded"));
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			previewLabel.Destroy();
			if ((Object)(object)ring != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)ring).gameObject);
			}
			if ((Object)(object)ringMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)ringMaterial);
			}
			instance = null;
		}

		private static bool Evaluate(Vector3 point, out float cover)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			cover = 0f;
			if (CoverMethod == null)
			{
				return false;
			}
			try
			{
				object[] array = new object[4] { point, 0f, false, 0.5f };
				CoverMethod.Invoke(null, array);
				cover = (float)array[1];
				return true;
			}
			catch (Exception ex)
			{
				BeehiveClearance beehiveClearance = instance;
				if (beehiveClearance != null)
				{
					((BaseUnityPlugin)beehiveClearance).Logger.LogWarning((object)("Beehive cover check failed: " + ex.Message));
				}
				return false;
			}
		}

		internal static void Hover(Beehive hive, ref string result)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (instance != null && !((Object)(object)hive == (Object)null))
			{
				instance.lastHovered = hive;
				instance.hoverUntil = Time.time + 0.25f;
				if (!((Object)(object)hive.m_coverPoint == (Object)null) && Evaluate(hive.m_coverPoint.position, out var cover))
				{
					float maxCover = hive.m_maxCover;
					string text = ((maxCover <= 0f || cover < maxCover) ? "green" : "red");
					result = result + "\n<color=" + text + ">Open space: " + Mathf.RoundToInt((1f - cover) * 100f) + "% (needs >" + Mathf.RoundToInt((1f - maxCover) * 100f) + "%)</color>";
				}
			}
		}

		private void Update()
		{
			//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_00a3: 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_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: 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_0125: 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_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: 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)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
			{
				status = null;
				HideRing();
				return;
			}
			Beehive val = null;
			preview = false;
			object? obj = GhostField?.GetValue(localPlayer);
			GameObject val2 = (GameObject)((obj is GameObject) ? obj : null);
			Vector3 point = Vector3.zero;
			if ((Object)(object)val2 != (Object)null && val2.activeInHierarchy)
			{
				val = val2.GetComponentInChildren<Beehive>(true);
				if ((Object)(object)val != (Object)null && (Object)(object)val.m_coverPoint != (Object)null)
				{
					point = val.m_coverPoint.position;
					preview = true;
				}
				else
				{
					object? obj2 = SelectedPieceMethod?.Invoke(localPlayer, null);
					Piece val3 = (Piece)((obj2 is Piece) ? obj2 : null);
					val = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponentInChildren<Beehive>(true) : null);
					if ((Object)(object)val != (Object)null && (Object)(object)val.m_coverPoint != (Object)null)
					{
						Vector3 val4 = ((Component)val3).transform.InverseTransformPoint(val.m_coverPoint.position);
						point = val2.transform.TransformPoint(val4);
						preview = true;
						if (!loggedPrefabFallback)
						{
							loggedPrefabFallback = true;
							((BaseUnityPlugin)this).Logger.LogInfo((object)"Beehive placement preview using selected piece and ghost position");
						}
					}
				}
			}
			if ((Object)(object)val == (Object)null && Time.time < hoverUntil && (Object)(object)lastHovered != (Object)null)
			{
				val = lastHovered;
			}
			if ((Object)(object)val == (Object)null || (Object)(object)val.m_coverPoint == (Object)null)
			{
				status = null;
				HideRing();
				return;
			}
			if (!preview)
			{
				point = val.m_coverPoint.position;
				HideRing();
			}
			if (Time.time >= nextSample)
			{
				nextSample = Time.time + 0.1f;
				if (Evaluate(point, out var cover))
				{
					float maxCover = val.m_maxCover;
					hasEnoughSpace = maxCover <= 0f || cover < maxCover;
					status = (preview ? "Placement: " : "Hive: ") + Mathf.RoundToInt((1f - cover) * 100f) + "% open (needs >" + Mathf.RoundToInt((1f - maxCover) * 100f) + "%); " + (hasEnoughSpace ? "enough space" : "needs more open space");
				}
				else
				{
					status = "Hive cover check unavailable";
				}
			}
			if (preview && showPlacementRing.Value && status != "Hive cover check unavailable")
			{
				DrawRing(val2.transform.position + Vector3.up * 0.12f, hasEnoughSpace);
			}
			else
			{
				HideRing();
			}
		}

		private void LateUpdate()
		{
			if (status == null)
			{
				previewLabel.Hide();
			}
			else
			{
				previewLabel.Show(status);
			}
		}

		private void DrawRing(Vector3 center, bool works)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ring == (Object)null)
			{
				GameObject val = new GameObject("Beehive placement status ring");
				val.layer = 2;
				ring = val.AddComponent<LineRenderer>();
				Shader val2 = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color");
				if ((Object)(object)val2 == (Object)null)
				{
					if (!ringWarning)
					{
						ringWarning = true;
						((BaseUnityPlugin)this).Logger.LogWarning((object)"No compatible shader found for the beehive placement ring");
					}
					Object.Destroy((Object)(object)val);
					ring = null;
					return;
				}
				ringMaterial = new Material(val2);
				((Renderer)ring).material = ringMaterial;
				ring.useWorldSpace = true;
				ring.loop = true;
				ring.positionCount = 48;
				LineRenderer obj = ring;
				float startWidth = (ring.endWidth = 0.04f);
				obj.startWidth = startWidth;
			}
			((Renderer)ring).enabled = true;
			LineRenderer obj2 = ring;
			Color startColor = (ring.endColor = (works ? Color.green : Color.red));
			obj2.startColor = startColor;
			float num2 = Mathf.Clamp(placementRingRadius.Value, 0.3f, 3f);
			for (int i = 0; i < ring.positionCount; i++)
			{
				float num3 = (float)i * 2f * MathF.PI / (float)ring.positionCount;
				ring.SetPosition(i, center + new Vector3(Mathf.Cos(num3) * num2, 0f, Mathf.Sin(num3) * num2));
			}
		}

		private void HideRing()
		{
			if ((Object)(object)ring != (Object)null)
			{
				((Renderer)ring).enabled = false;
			}
		}
	}
}