using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ShipStats")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Azumatt")]
[assembly: AssemblyProduct("ShipStats")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: AssemblyFileVersion("1.0.4")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.4.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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]
[Microsoft.CodeAnalysis.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;
}
}
}
namespace ShipStats
{
[HarmonyPatch(typeof(Hud), "Awake")]
internal static class HudAwakePatch
{
public static GameObject Go;
public static GameObject Go2;
public static TextMeshProUGUI contentText;
public static TextMeshProUGUI contentText2;
private static void Postfix(Hud __instance)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
ShipStatsPlugin.ShipStatsLogger.LogDebugIfBuildDebug("Hud.Awake Postfix started");
Go = new GameObject("AzuShipStatsPlayerControlled");
Go.transform.SetParent(Utils.FindChild(__instance.m_shipHudRoot.transform, "Controls", (IterativeSearchType)0), false);
Go2 = Object.Instantiate<GameObject>(Go, Hud.instance.m_rootObject.transform, false);
((Object)Go2).name = "AzuShipStatsPlayerOnBoard";
AddTheComponents(Go);
AddTheComponents(Go2);
ShipStatsPlugin.ShipStatsLogger.LogDebugIfBuildDebug("UI elements created and components added");
}
public static void AddTheComponents(GameObject gameObject)
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Expected O, but got Unknown
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Expected O, but got Unknown
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
ShipStatsPlugin.ShipStatsLogger.LogDebugIfBuildDebug("Adding components to " + ((Object)gameObject).name);
RectTransform obj = gameObject.AddComponent<RectTransform>();
((Graphic)gameObject.AddComponent<Image>()).color = ShipStatsPlugin.PanelColor.Value;
VerticalLayoutGroup val = gameObject.AddComponent<VerticalLayoutGroup>();
((LayoutGroup)val).padding = new RectOffset(5, 5, 5, 5);
ContentSizeFitter obj2 = gameObject.AddComponent<ContentSizeFitter>();
obj2.horizontalFit = (FitMode)2;
obj2.verticalFit = (FitMode)2;
GameObject val2 = new GameObject(((Object)gameObject).name + "Content");
val2.transform.SetParent(((Component)val).transform);
if (((Object)gameObject).name.EndsWith("PlayerControlled", StringComparison.Ordinal))
{
contentText = val2.AddComponent<TextMeshProUGUI>();
((Graphic)contentText).color = ShipStatsPlugin.TextColor.Value;
((TMP_Text)contentText).font = MessageHud.instance.m_messageCenterText.font;
((TMP_Text)contentText).overflowMode = (TextOverflowModes)0;
((TMP_Text)contentText).fontSize = ShipStatsPlugin.FontSize.Value;
((Behaviour)contentText).enabled = true;
((TMP_Text)contentText).alignment = (TextAlignmentOptions)514;
}
else
{
contentText2 = val2.AddComponent<TextMeshProUGUI>();
((Graphic)contentText2).color = ShipStatsPlugin.TextColor.Value;
((TMP_Text)contentText2).font = MessageHud.instance.m_messageCenterText.font;
((TMP_Text)contentText2).overflowMode = (TextOverflowModes)0;
((TMP_Text)contentText2).fontSize = ShipStatsPlugin.FontSize.Value;
((Behaviour)contentText2).enabled = true;
((TMP_Text)contentText2).alignment = (TextAlignmentOptions)514;
}
gameObject.AddComponent<UIUpdater>();
obj.anchoredPosition = ShipStatsPlugin.AnchoredPosition.Value;
gameObject.SetActive(false);
ShipStatsPlugin.ShipStatsLogger.LogDebugIfBuildDebug("Components added to " + ((Object)gameObject).name);
}
}
[HarmonyPatch(typeof(Ship), "OnTriggerEnter")]
internal static class ShipOnTriggerEnterPatch
{
private static void Postfix(Ship __instance, Collider collider)
{
ShipStatsPlugin.ShipStatsLogger.LogDebugIfBuildDebug("Ship.OnTriggerEnter started");
Player component = ((Component)collider).GetComponent<Player>();
if (!Object.op_Implicit((Object)(object)component))
{
ShipStatsPlugin.ShipStatsLogger.LogDebugIfBuildDebug("No player component found");
return;
}
if (!((Object)(object)component == (Object)(object)Player.m_localPlayer))
{
ShipStatsPlugin.ShipStatsLogger.LogDebugIfBuildDebug("Player is not local player");
return;
}
HudAwakePatch.Go.SetActive(true);
ShipStatsPlugin.ShipStatsLogger.LogDebugIfBuildDebug("AzuShipStatsPlayerControlled UI set active");
}
}
[HarmonyPatch(typeof(Ship))]
internal static class ShipOnTriggerExitDestroyedPatch
{
[HarmonyPostfix]
[HarmonyPatch("OnTriggerExit")]
private static void Postfix1(Ship __instance, Collider collider)
{
ShipStatsPlugin.ShipStatsLogger.LogDebugIfBuildDebug("Ship.OnTriggerExit started");
Player component = ((Component)collider).GetComponent<Player>();
if (!Object.op_Implicit((Object)(object)component))
{
ShipStatsPlugin.ShipStatsLogger.LogDebugIfBuildDebug("No player component found");
return;
}
if (!((Object)(object)component == (Object)(object)Player.m_localPlayer))
{
ShipStatsPlugin.ShipStatsLogger.LogDebugIfBuildDebug("Player is not local player");
return;
}
HudAwakePatch.Go.SetActive(false);
HudAwakePatch.Go2.SetActive(false);
ShipStatsPlugin.ShipStatsLogger.LogDebugIfBuildDebug("UI elements set inactive");
}
[HarmonyPostfix]
[HarmonyPatch("OnDestroyed")]
private static void Postfix2()
{
HudAwakePatch.Go.SetActive(false);
HudAwakePatch.Go2.SetActive(false);
ShipStatsPlugin.ShipStatsLogger.LogDebugIfBuildDebug("UI elements set inactive on ship destruction");
}
}
public class UIUpdater : MonoBehaviour
{
internal Vector3 size;
internal Vector2 offset;
internal Transform rectransform;
private const float knotsMultiplier = 1.94384f;
private const float mphMultiplier = 2.237f;
private void Start()
{
rectransform = (Transform)(object)((Component)this).GetComponent<RectTransform>();
}
private void Update()
{
//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
//IL_014e: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: 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_015c: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Player.m_localPlayer == (Object)null)
{
((TMP_Text)HudAwakePatch.contentText).text = "";
((TMP_Text)HudAwakePatch.contentText2).text = "";
return;
}
Ship val = (((Object)(object)Player.m_localPlayer.GetControlledShip() != (Object)null) ? Player.m_localPlayer.GetControlledShip() : (((Object)(object)((Character)Player.m_localPlayer).GetStandingOnShip() != (Object)null) ? ((Character)Player.m_localPlayer).GetStandingOnShip() : null));
if ((Object)(object)val == (Object)null)
{
((TMP_Text)HudAwakePatch.contentText).text = "";
((TMP_Text)HudAwakePatch.contentText2).text = "";
return;
}
float num = EnvMan.instance.GetWindIntensity() * 1.94384f * 10f;
float num2 = Mathf.Abs(val.GetSpeed());
float num3 = Mathf.Abs(num2 * 2.237f);
float num4 = Mathf.Abs(num2 * 1.94384f);
float num5 = 0f;
float num6 = 0f;
WearNTear val2 = default(WearNTear);
((Component)val).TryGetComponent<WearNTear>(ref val2);
if (Object.op_Implicit((Object)(object)val2) && val.m_nview.IsValid() && !((double)val.m_nview.GetZDO().GetFloat("health", val2.m_health) <= 0.0))
{
num6 = val2.m_health;
num5 = val.m_nview.GetZDO().GetFloat("health", val2.m_health);
}
Vector3 windDir = EnvMan.instance.GetWindDir();
float num7 = Mathf.Atan2(windDir.x, windDir.z) * 57.29578f + 180f;
string text = (((double)num7 >= 337.5 || (double)num7 < 22.5) ? "N" : (((double)num7 < 67.5) ? "NE" : (((double)num7 < 112.5) ? "E" : (((double)num7 < 157.5) ? "SE" : (((double)num7 < 202.5) ? "S" : (((double)num7 < 247.5) ? "SW" : ((!((double)num7 < 292.5)) ? "NW" : "W")))))));
Inventory val3 = ((Component)val).GetComponentInChildren<Container>()?.m_inventory;
string text2;
try
{
text2 = string.Format(ShipStatsPlugin.TextFormat.Value, num4, num3, num, num7, text, (val3 == null) ? "" : $"Ship Inventory: {val3?.m_inventory.Count}/{val3?.m_width * val3?.m_height} ({((val3 != null) ? new float?(val3.SlotsUsedPercentage()) : null):0.#}%)", (num5 > 0f) ? $"Ship Health: {num5:0}/{num6:0}" : "");
}
catch
{
text2 = "Error in Text Format";
}
((TMP_Text)HudAwakePatch.contentText).text = text2;
((TMP_Text)HudAwakePatch.contentText2).text = text2;
Camera mainCamera = Utils.GetMainCamera();
if (!((Object)(object)mainCamera == (Object)null))
{
HudAwakePatch.Go2.transform.position = mainCamera.WorldToScreenPoint(val.m_controlGuiPos.position);
}
}
}
[BepInPlugin("Azumatt.ShipStats", "ShipStats", "1.0.4")]
public class ShipStatsPlugin : BaseUnityPlugin
{
public enum Toggle
{
On = 1,
Off = 0
}
private class ConfigurationManagerAttributes
{
[UsedImplicitly]
public int? Order;
[UsedImplicitly]
public bool? Browsable;
[UsedImplicitly]
public string? Category;
[UsedImplicitly]
public Action<ConfigEntryBase>? CustomDrawer;
}
private class AcceptableShortcuts : AcceptableValueBase
{
public AcceptableShortcuts()
: base(typeof(KeyboardShortcut))
{
}
public override object Clamp(object value)
{
return value;
}
public override bool IsValid(object value)
{
return true;
}
public override string ToDescriptionString()
{
return "# Acceptable values: " + string.Join(", ", UnityInput.Current.SupportedKeyCodes);
}
}
internal const string ModName = "ShipStats";
internal const string ModVersion = "1.0.4";
internal const string Author = "Azumatt";
private const string ModGUID = "Azumatt.ShipStats";
private static string ConfigFileName = "Azumatt.ShipStats.cfg";
private static string ConfigFileFullPath;
internal static string ConnectionError;
private readonly Harmony _harmony = new Harmony("Azumatt.ShipStats");
public static readonly ManualLogSource ShipStatsLogger;
public static ConfigEntry<int> FontSize;
public static ConfigEntry<Color> TextColor;
public static ConfigEntry<string> TextFormat;
public static ConfigEntry<Vector2> AnchoredPosition;
public static ConfigEntry<Color> PanelColor;
public void Awake()
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
FontSize = config("1 - Text", "Stats Font Size", 15, "Font Size of the stats text. Default is 15.");
TextColor = config<Color>("1 - Text", "Stats Text Color", new Color(1f, 1f, 1f, 1f), "Color of the stats text. Default is white.");
TextFormat = TextEntryConfig("1 - Text", "Stats Text Format", "Ship Speed:\n\t{0:0.#} knots\n\t{1:0.#} mph\nWind Speed: {2:0.#} knots\nWind Direction: {3:0.#}° {4}\n{5}\n{6}", "{0} is ship speed in knots\n{1} is ship speed in mph\n{2} is wind speed in knots\n{3} is wind direction in degrees\n{4} is wind direction in cardinal directions\n{5} is ship inventory count and percent\n{6} is the ship health");
AnchoredPosition = config<Vector2>("2 - UI", "Stats Anchored Position", new Vector2(200f, -27f), "Anchored position of the stats text. Please note that this is relative to the rudder icon. Default is 200,-27.");
PanelColor = config<Color>("2 - UI", "UI Background Color", new Color(0f, 0f, 0f, 0.5f), "Color of panel background. Default is black with half transparency.");
FontSize.SettingChanged += delegate
{
UIElementChanged();
};
TextColor.SettingChanged += delegate
{
UIElementChanged();
};
AnchoredPosition.SettingChanged += delegate
{
UIElementChanged();
};
PanelColor.SettingChanged += delegate
{
UIElementChanged();
};
Assembly executingAssembly = Assembly.GetExecutingAssembly();
_harmony.PatchAll(executingAssembly);
SetupWatcher();
}
private void UIElementChanged()
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)HudAwakePatch.contentText != (Object)null)
{
((TMP_Text)HudAwakePatch.contentText).fontSize = FontSize.Value;
((Graphic)HudAwakePatch.contentText).color = TextColor.Value;
}
if ((Object)(object)HudAwakePatch.contentText2 != (Object)null)
{
((TMP_Text)HudAwakePatch.contentText2).fontSize = FontSize.Value;
((Graphic)HudAwakePatch.contentText2).color = TextColor.Value;
}
if ((Object)(object)HudAwakePatch.Go != (Object)null)
{
((Graphic)HudAwakePatch.Go.GetComponent<Image>()).color = PanelColor.Value;
HudAwakePatch.Go.GetComponent<RectTransform>().anchoredPosition = AnchoredPosition.Value;
}
}
private void OnDestroy()
{
((BaseUnityPlugin)this).Config.Save();
}
private void SetupWatcher()
{
FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName);
fileSystemWatcher.Changed += ReadConfigValues;
fileSystemWatcher.Created += ReadConfigValues;
fileSystemWatcher.Renamed += ReadConfigValues;
fileSystemWatcher.IncludeSubdirectories = true;
fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
fileSystemWatcher.EnableRaisingEvents = true;
}
private void ReadConfigValues(object sender, FileSystemEventArgs e)
{
if (!File.Exists(ConfigFileFullPath))
{
return;
}
try
{
ShipStatsLogger.LogDebug((object)"ReadConfigValues called");
((BaseUnityPlugin)this).Config.Reload();
}
catch
{
ShipStatsLogger.LogError((object)("There was an issue loading your " + ConfigFileName));
ShipStatsLogger.LogError((object)"Please check your config entries for spelling and format!");
}
}
private ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description)
{
return ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, description);
}
private ConfigEntry<T> config<T>(string group, string name, T value, string description)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected O, but got Unknown
return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
}
private ConfigEntry<T> TextEntryConfig<T>(string group, string name, T value, string desc)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Expected O, but got Unknown
ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
{
CustomDrawer = TextAreaDrawer
};
return config(group, name, value, new ConfigDescription(desc, (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
}
internal static void TextAreaDrawer(ConfigEntryBase entry)
{
GUILayout.ExpandHeight(true);
GUILayout.ExpandWidth(true);
entry.BoxedValue = GUILayout.TextArea((string)entry.BoxedValue, (GUILayoutOption[])(object)new GUILayoutOption[2]
{
GUILayout.ExpandWidth(true),
GUILayout.ExpandHeight(true)
});
}
static ShipStatsPlugin()
{
string configPath = Paths.ConfigPath;
char directorySeparatorChar = Path.DirectorySeparatorChar;
ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName;
ConnectionError = "";
ShipStatsLogger = Logger.CreateLogSource("ShipStats");
FontSize = null;
TextColor = null;
TextFormat = null;
AnchoredPosition = null;
PanelColor = null;
}
}
public static class LoggerExtentions
{
public static void LogDebugIfBuildDebug(this ManualLogSource logger, string message)
{
}
public static void LogWarningIfBuildDebug(this ManualLogSource logger, string message)
{
}
public static void LogErrorIfBuildDebug(this ManualLogSource logger, string message)
{
}
}
[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
public static class RegisterAndCheckVersion
{
private static void Prefix(ZNetPeer peer, ref ZNet __instance)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Expected O, but got Unknown
ShipStatsPlugin.ShipStatsLogger.LogDebug((object)"Registering version RPC handler");
peer.m_rpc.Register<ZPackage>("ShipStats_VersionCheck", (Action<ZRpc, ZPackage>)RpcHandlers.RPC_ShipStats_Version);
ShipStatsPlugin.ShipStatsLogger.LogInfo((object)"Invoking version check");
ZPackage val = new ZPackage();
val.Write("1.0.4");
peer.m_rpc.Invoke("ShipStats_VersionCheck", new object[1] { val });
}
}
[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
public static class VerifyClient
{
private static bool Prefix(ZRpc rpc, ZPackage pkg, ref ZNet __instance)
{
if (!__instance.IsServer() || RpcHandlers.ValidatedPeers.Contains(rpc))
{
return true;
}
ShipStatsPlugin.ShipStatsLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") never sent version or couldn't due to previous disconnect, disconnecting"));
rpc.Invoke("Error", new object[1] { 3 });
return false;
}
private static void Postfix(ZNet __instance)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "RequestAdminSync", new object[1] { (object)new ZPackage() });
}
}
[HarmonyPatch(typeof(FejdStartup), "ShowConnectError")]
public class ShowConnectionError
{
private static void Postfix(FejdStartup __instance)
{
if (__instance.m_connectionFailedPanel.activeSelf)
{
__instance.m_connectionFailedError.fontSizeMax = 25f;
__instance.m_connectionFailedError.fontSizeMin = 15f;
TMP_Text connectionFailedError = __instance.m_connectionFailedError;
connectionFailedError.text = connectionFailedError.text + "\n" + ShipStatsPlugin.ConnectionError;
}
}
}
[HarmonyPatch(typeof(ZNet), "Disconnect")]
public static class RemoveDisconnectedPeerFromVerified
{
private static void Prefix(ZNetPeer peer, ref ZNet __instance)
{
if (__instance.IsServer())
{
ShipStatsPlugin.ShipStatsLogger.LogInfo((object)("Peer (" + peer.m_rpc.m_socket.GetHostName() + ") disconnected, removing from validated list"));
RpcHandlers.ValidatedPeers.Remove(peer.m_rpc);
}
}
}
public static class RpcHandlers
{
public static readonly List<ZRpc> ValidatedPeers = new List<ZRpc>();
public static void RPC_ShipStats_Version(ZRpc rpc, ZPackage pkg)
{
string text = pkg.ReadString();
ShipStatsPlugin.ShipStatsLogger.LogInfo((object)("Version check, local: 1.0.4, remote: " + text));
if (text != "1.0.4")
{
ShipStatsPlugin.ConnectionError = "ShipStats Installed: 1.0.4\n Needed: " + text;
if (ZNet.instance.IsServer())
{
ShipStatsPlugin.ShipStatsLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") has incompatible version, disconnecting"));
rpc.Invoke("Error", new object[1] { 3 });
}
}
else if (!ZNet.instance.IsServer())
{
ShipStatsPlugin.ShipStatsLogger.LogInfo((object)"Received same version from server!");
}
else
{
ShipStatsPlugin.ShipStatsLogger.LogInfo((object)("Adding peer (" + rpc.m_socket.GetHostName() + ") to validated list"));
ValidatedPeers.Add(rpc);
}
}
}
}