Decompiled source of ReefClient v0.2.0

ReefClient.dll

Decompiled 4 days ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("ReefClient")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+c0754c0a7526fe1ae34325f6fa9165f64fd15bfa")]
[assembly: AssemblyProduct("ReefClient")]
[assembly: AssemblyTitle("ReefClient")]
[assembly: AssemblyVersion("0.2.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 ReefClient
{
	internal static class FavorHud
	{
		private static int count = -1;

		private static GameObject root;

		private static Image icon;

		private static TMP_Text label;

		private static Sprite sprite;

		private static bool spriteTried;

		private static float builtSize = -1f;

		internal static bool EverReceived => count >= 0;

		internal static int Count => count;

		internal static void Set(int n)
		{
			count = Math.Max(0, n);
			if ((Object)(object)label != (Object)null)
			{
				label.text = count.ToString();
			}
		}

		internal static void Tick()
		{
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_smallRoot == (Object)null)
			{
				root = null;
				icon = null;
				label = null;
				return;
			}
			if ((Object)(object)root == (Object)null || builtSize != ReefClientPlugin.HudSize.Value)
			{
				try
				{
					Build(instance);
				}
				catch (Exception ex)
				{
					ReefClientPlugin.Log.LogWarning((object)("favor hud: " + ex.GetType().Name + ": " + ex.Message));
					return;
				}
			}
			bool flag = EverReceived || !ReefClientPlugin.HiddenUntilFirstFavor.Value;
			if (root.activeSelf != flag)
			{
				root.SetActive(flag);
			}
		}

		private static void Build(Minimap mm)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_0140: 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_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root != (Object)null)
			{
				Object.Destroy((Object)(object)root);
			}
			float num = Mathf.Clamp(ReefClientPlugin.HudSize.Value, 8f, 128f);
			builtSize = ReefClientPlugin.HudSize.Value;
			root = new GameObject("ReefFavors", new Type[1] { typeof(RectTransform) });
			RectTransform component = root.GetComponent<RectTransform>();
			((Transform)component).SetParent(mm.m_smallRoot.transform, false);
			component.anchorMin = new Vector2(0.5f, 0f);
			component.anchorMax = new Vector2(0.5f, 0f);
			component.pivot = new Vector2(0.5f, 1f);
			component.anchoredPosition = new Vector2(ReefClientPlugin.HudX.Value, ReefClientPlugin.HudY.Value);
			component.sizeDelta = new Vector2(num * 3f, num);
			GameObject val = new GameObject("Icon", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			RectTransform component2 = val.GetComponent<RectTransform>();
			((Transform)component2).SetParent((Transform)(object)component, false);
			component2.anchorMin = new Vector2(0f, 0.5f);
			component2.anchorMax = new Vector2(0f, 0.5f);
			component2.pivot = new Vector2(0f, 0.5f);
			component2.anchoredPosition = new Vector2(num * 0.5f, 0f);
			component2.sizeDelta = new Vector2(num, num);
			icon = val.GetComponent<Image>();
			((Graphic)icon).raycastTarget = false;
			icon.preserveAspect = true;
			Sprite val2 = LoadSprite();
			if ((Object)(object)val2 != (Object)null)
			{
				icon.sprite = val2;
			}
			else
			{
				((Graphic)icon).color = new Color(0.95f, 0.8f, 0.35f, 0.9f);
			}
			GameObject val3 = new GameObject("Count", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(TextMeshProUGUI)
			});
			RectTransform component3 = val3.GetComponent<RectTransform>();
			((Transform)component3).SetParent((Transform)(object)component, false);
			component3.anchorMin = new Vector2(0f, 0f);
			component3.anchorMax = new Vector2(1f, 1f);
			component3.pivot = new Vector2(0f, 0.5f);
			component3.offsetMin = new Vector2(num * 1.65f, 0f);
			component3.offsetMax = new Vector2(0f, 0f);
			label = (TMP_Text)(object)val3.GetComponent<TextMeshProUGUI>();
			TMP_Text biomeNameSmall = mm.m_biomeNameSmall;
			if ((Object)(object)biomeNameSmall != (Object)null)
			{
				label.font = biomeNameSmall.font;
				label.fontSharedMaterial = biomeNameSmall.fontSharedMaterial;
				((Graphic)label).color = ((Graphic)biomeNameSmall).color;
			}
			else
			{
				((Graphic)label).color = new Color(0.95f, 0.85f, 0.5f, 1f);
			}
			label.fontSize = num * 0.85f;
			label.alignment = (TextAlignmentOptions)4097;
			label.textWrappingMode = (TextWrappingModes)0;
			((Graphic)label).raycastTarget = false;
			label.text = ((count >= 0) ? count.ToString() : "");
			ReefClientPlugin.Log.LogInfo((object)("favor hud built under the minimap (size " + num + ", offset " + ReefClientPlugin.HudX.Value + "," + ReefClientPlugin.HudY.Value + ", sprite " + (((Object)(object)val2 != (Object)null) ? "eye.png" : "fallback") + ")"));
		}

		private static Sprite LoadSprite()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sprite != (Object)null || spriteTried)
			{
				return sprite;
			}
			spriteTried = true;
			try
			{
				using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ReefClient.Resources.eye.png");
				if (stream == null)
				{
					ReefClientPlugin.Log.LogWarning((object)"favor hud: embedded eye.png not found");
					return null;
				}
				byte[] array = new byte[stream.Length];
				int num;
				for (int i = 0; i < array.Length; i += num)
				{
					num = stream.Read(array, i, array.Length - i);
					if (num <= 0)
					{
						break;
					}
				}
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				MethodInfo method = typeof(ImageConversion).GetMethod("LoadImage", new Type[2]
				{
					typeof(Texture2D),
					typeof(byte[])
				});
				if (method == null)
				{
					ReefClientPlugin.Log.LogWarning((object)"favor hud: ImageConversion.LoadImage(Texture2D, byte[]) not found");
					return null;
				}
				if (!(bool)method.Invoke(null, new object[2] { val, array }))
				{
					ReefClientPlugin.Log.LogWarning((object)"favor hud: eye.png did not decode");
					return null;
				}
				((Texture)val).filterMode = (FilterMode)1;
				sprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
				return sprite;
			}
			catch (Exception ex)
			{
				ReefClientPlugin.Log.LogWarning((object)("favor hud sprite: " + ex.GetType().Name + ": " + ex.Message));
				return null;
			}
		}
	}
	[BepInPlugin("reef.client", "Reef Client", "0.2.0")]
	public class ReefClientPlugin : BaseUnityPlugin
	{
		public const string GUID = "reef.client";

		public const string NAME = "Reef Client";

		public const string VERSION = "0.2.0";

		public const string BUILD = "reef";

		internal static ManualLogSource Log;

		internal static ConfigEntry<float> HudX;

		internal static ConfigEntry<float> HudY;

		internal static ConfigEntry<float> HudSize;

		internal static ConfigEntry<bool> HiddenUntilFirstFavor;

		internal static ConfigEntry<float> MaxEnvMinutes;

		internal static ConfigEntry<bool> SendChatCopy;

		private Harmony harmony;

		private void Awake()
		{
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			HudX = ((BaseUnityPlugin)this).Config.Bind<float>("Favors", "HudX", 0f, "Horizontal offset (px) of the favor counter from the bottom-centre of the small minimap.");
			HudY = ((BaseUnityPlugin)this).Config.Bind<float>("Favors", "HudY", -6f, "Vertical offset (px) of the favor counter from the bottom edge of the small minimap (negative = below).");
			HudSize = ((BaseUnityPlugin)this).Config.Bind<float>("Favors", "HudSize", 28f, "Icon height in px; the number scales with it.");
			HiddenUntilFirstFavor = ((BaseUnityPlugin)this).Config.Bind<bool>("Favors", "HiddenUntilFirstFavor", true, "true = nothing is drawn until the server has sent a favor count at least once this game session.");
			MaxEnvMinutes = ((BaseUnityPlugin)this).Config.Bind<float>("Weather", "MaxEnvMinutes", 60f, "Safety: a forced sky (Reef_SetEnv) clears itself after this many real minutes even if the server never sends the reset. 0 = never.");
			SendChatCopy = ((BaseUnityPlugin)this).Config.Bind<bool>("Chat", "SendCopyToServer", true, "Send a copy of every chat line you type to the server (Reef_Chat) so the director hears you even when you play alone. Chat is never READ by this plugin.");
			harmony = new Harmony("reef.client");
			harmony.PatchAll(typeof(ZNetAwakePatch));
			harmony.PatchAll(typeof(ChatSendPatch));
			Log.LogInfo((object)"Reef Client 0.2.0 loaded (build: reef)");
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		private void Update()
		{
			Receivers.Tick();
			FavorHud.Tick();
		}
	}
	[HarmonyPatch(typeof(ZNet), "Awake")]
	internal static class ZNetAwakePatch
	{
		private static void Postfix(ZNet __instance)
		{
			try
			{
				if (__instance.IsDedicated())
				{
					ReefClientPlugin.Log.LogInfo((object)"dedicated server: ReefClient registers nothing");
					return;
				}
				ZRoutedRpc instance = ZRoutedRpc.instance;
				if (instance == null)
				{
					ReefClientPlugin.Log.LogWarning((object)"ZRoutedRpc.instance is null after ZNet.Awake — receivers not registered");
					return;
				}
				instance.Register<int>("Reef_FavorCount", (Action<long, int>)Receivers.OnFavorCount);
				instance.Register<string>("Reef_SetEnv", (Action<long, string>)Receivers.OnSetEnv);
				instance.Register<float, float, float>("Reef_SetWind", (Action<long, float, float, float>)Receivers.OnSetWind);
				ReefClientPlugin.Log.LogInfo((object)"receivers registered: Reef_FavorCount, Reef_SetEnv, Reef_SetWind");
			}
			catch (Exception ex)
			{
				ReefClientPlugin.Log.LogWarning((object)("register: " + ex.GetType().Name + ": " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(Chat), "SendText", new Type[]
	{
		typeof(Type),
		typeof(string)
	})]
	internal static class ChatSendPatch
	{
		private static void Postfix(Type type, string text)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected I4, but got Unknown
			try
			{
				if (ReefClientPlugin.SendChatCopy.Value && (int)type != 3 && !string.IsNullOrEmpty(text))
				{
					ZNet instance = ZNet.instance;
					if (!((Object)(object)instance == (Object)null) && !instance.IsServer() && ZRoutedRpc.instance != null)
					{
						ZRoutedRpc.instance.InvokeRoutedRPC("Reef_Chat", new object[2]
						{
							(int)type,
							text
						});
					}
				}
			}
			catch (Exception ex)
			{
				ReefClientPlugin.Log.LogWarning((object)("Reef_Chat: " + ex.GetType().Name + ": " + ex.Message));
			}
		}
	}
	internal static class Receivers
	{
		private static float windDeadline = -1f;

		private static float envDeadline = -1f;

		private static string heldEnv = "";

		internal static void OnFavorCount(long sender, int n)
		{
			ReefClientPlugin.Log.LogInfo((object)("Reef_FavorCount " + n + " (from " + sender + ")"));
			FavorHud.Set(n);
		}

		internal static void OnSetEnv(long sender, string name)
		{
			name = name ?? "";
			EnvMan instance = EnvMan.instance;
			if ((Object)(object)instance == (Object)null)
			{
				ReefClientPlugin.Log.LogWarning((object)("Reef_SetEnv '" + name + "': no EnvMan"));
				return;
			}
			instance.m_debugEnv = name;
			heldEnv = name;
			float value = ReefClientPlugin.MaxEnvMinutes.Value;
			envDeadline = ((name.Length > 0 && value > 0f) ? (Time.realtimeSinceStartup + value * 60f) : (-1f));
			ReefClientPlugin.Log.LogInfo((object)("Reef_SetEnv '" + name + "' (from " + sender + ")" + ((name.Length == 0) ? " → natural sky" : "")));
		}

		internal static void OnSetWind(long sender, float angle, float intensity, float minutes)
		{
			EnvMan instance = EnvMan.instance;
			if ((Object)(object)instance == (Object)null)
			{
				ReefClientPlugin.Log.LogWarning((object)"Reef_SetWind: no EnvMan");
				return;
			}
			if (minutes <= 0f)
			{
				instance.ResetDebugWind();
				windDeadline = -1f;
				ReefClientPlugin.Log.LogInfo((object)("Reef_SetWind reset (from " + sender + ")"));
				return;
			}
			instance.SetDebugWind(angle, intensity);
			windDeadline = Time.realtimeSinceStartup + Mathf.Min(minutes, 1440f) * 60f;
			ReefClientPlugin.Log.LogInfo((object)("Reef_SetWind angle=" + angle + " intensity=" + intensity + " for " + minutes + " min (from " + sender + ")"));
		}

		internal static void Tick()
		{
			EnvMan instance = EnvMan.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (windDeadline > 0f && realtimeSinceStartup >= windDeadline)
			{
				windDeadline = -1f;
				instance.ResetDebugWind();
				ReefClientPlugin.Log.LogInfo((object)"wind hold expired → natural wind");
			}
			if (envDeadline > 0f && realtimeSinceStartup >= envDeadline)
			{
				envDeadline = -1f;
				if (instance.m_debugEnv == heldEnv)
				{
					instance.m_debugEnv = "";
				}
				ReefClientPlugin.Log.LogInfo((object)"sky hold expired (MaxEnvMinutes) → natural sky");
			}
		}
	}
}