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(); ((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(); ((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(); ((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(); ((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(); 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 HudX; internal static ConfigEntry HudY; internal static ConfigEntry HudSize; internal static ConfigEntry HiddenUntilFirstFavor; internal static ConfigEntry MaxEnvMinutes; internal static ConfigEntry 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("Favors", "HudX", 0f, "Horizontal offset (px) of the favor counter from the bottom-centre of the small minimap."); HudY = ((BaseUnityPlugin)this).Config.Bind("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("Favors", "HudSize", 28f, "Icon height in px; the number scales with it."); HiddenUntilFirstFavor = ((BaseUnityPlugin)this).Config.Bind("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("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("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("Reef_FavorCount", (Action)Receivers.OnFavorCount); instance.Register("Reef_SetEnv", (Action)Receivers.OnSetEnv); instance.Register("Reef_SetWind", (Action)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"); } } } }