using System; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("MagiCorp.ValheimTickProfiler.Client")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+8a7348b5dbdb8712868f3841af346c25901bdbff")] [assembly: AssemblyProduct("MagiCorp.ValheimTickProfiler.Client")] [assembly: AssemblyTitle("MagiCorp.ValheimTickProfiler.Client")] [assembly: AssemblyVersion("1.0.0.0")] namespace MagiCorp.ValheimTickProfiler.Client; [BepInPlugin("magicorp.valheim.tickprofiler.client", "MagiCorp Valheim Tick Profiler Client Overlay", "0.2.5")] [BepInProcess("valheim.exe")] public sealed class TickProfilerClientOverlay : BaseUnityPlugin { public const string PluginGuid = "magicorp.valheim.tickprofiler.client"; public const string PluginName = "MagiCorp Valheim Tick Profiler Client Overlay"; public const string PluginVersion = "0.2.5"; private const string RpcHello = "MagiCorp_TickProfiler_Hello_v1"; private const string RpcSnapshot = "MagiCorp_TickProfiler_Snapshot_v1"; private ConfigEntry _toggleKey; private ConfigEntry _visibleByDefault; private ConfigEntry _fontSize; private ConfigEntry _x; private ConfigEntry _y; private ConfigEntry _width; private ConfigEntry _uiScale; private bool _visible; private bool _rpcRegistered; private ZRoutedRpc _registeredRpcInstance; private long _lastHelloTicks; private string _snapshot = string.Empty; private DateTime _snapshotUtc = DateTime.MinValue; private GUIStyle _textStyle; private bool _loggedFirstSnapshot; private bool _loggedPeerIdFailure; private static readonly MethodInfo GetServerPeerIdMethod = typeof(ZRoutedRpc).GetMethod("GetServerPeerID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private void Awake() { //IL_0143: Unknown result type (might be due to invalid IL or missing references) _toggleKey = ((BaseUnityPlugin)this).Config.Bind("Client UI", "ToggleKey", (KeyCode)289, "Show or hide the server TickProfiler overlay."); _visibleByDefault = ((BaseUnityPlugin)this).Config.Bind("Client UI", "VisibleByDefault", false, "Show the overlay when Valheim starts."); _fontSize = ((BaseUnityPlugin)this).Config.Bind("Client UI", "FontSize", 14, "Overlay font size."); _x = ((BaseUnityPlugin)this).Config.Bind("Client UI", "X", 16f, "Overlay X position in pixels."); _y = ((BaseUnityPlugin)this).Config.Bind("Client UI", "Y", 16f, "Overlay Y position in pixels."); _width = ((BaseUnityPlugin)this).Config.Bind("Client UI", "Width", 820f, "Overlay width at 1080p before UI scaling."); _uiScale = ((BaseUnityPlugin)this).Config.Bind("Client UI", "UIScale", 0f, "Overlay scale. 0 = automatic based on vertical resolution (1x at 1080p, 2x at 4K)."); _visible = _visibleByDefault.Value; ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded in process {2}. Toggle: {3}", "MagiCorp Valheim Tick Profiler Client Overlay", "0.2.5", Process.GetCurrentProcess().ProcessName, _toggleKey.Value)); } private void Update() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) TryRegisterRpc(); if (TogglePressed()) { _visible = !_visible; ((BaseUnityPlugin)this).Logger.LogInfo((object)("TickProfiler overlay " + (_visible ? "shown" : "hidden") + " via " + ((object)_toggleKey.Value/*cast due to .constrained prefix*/).ToString() + ".")); } long timestamp = Stopwatch.GetTimestamp(); if (_rpcRegistered && (double)(timestamp - _lastHelloTicks) / (double)Stopwatch.Frequency >= 10.0) { SendHello(); } } private void TryRegisterRpc() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null) { _rpcRegistered = false; _registeredRpcInstance = null; } else if (!_rpcRegistered || _registeredRpcInstance != instance) { _rpcRegistered = false; _registeredRpcInstance = null; try { instance.Register("MagiCorp_TickProfiler_Snapshot_v1", (Action)OnSnapshot); _registeredRpcInstance = instance; _rpcRegistered = true; _lastHelloTicks = 0L; ((BaseUnityPlugin)this).Logger.LogInfo((object)"TickProfiler snapshot RPC registered on current ZRoutedRpc instance."); SendHello(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("TickProfiler overlay RPC registration failed: " + ex.Message)); } } } private void SendHello() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null) { return; } long serverPeerId = GetServerPeerId(instance); if (serverPeerId == 0L) { return; } try { instance.InvokeRoutedRPC(serverPeerId, "MagiCorp_TickProfiler_Hello_v1", Array.Empty()); _lastHelloTicks = Stopwatch.GetTimestamp(); ((BaseUnityPlugin)this).Logger.LogDebug((object)("TickProfiler hello sent to server peer " + serverPeerId + ".")); } catch { } } private long GetServerPeerId(ZRoutedRpc routed) { if (routed == null || GetServerPeerIdMethod == null) { return 0L; } try { return (GetServerPeerIdMethod.Invoke(routed, null) is long num) ? num : 0; } catch (Exception ex) { if (!_loggedPeerIdFailure) { _loggedPeerIdFailure = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)("TickProfiler could not resolve the server peer ID: " + ex.GetBaseException().Message)); } return 0L; } } private void OnSnapshot(long sender, string text) { if (string.IsNullOrEmpty(text)) { return; } ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { long serverPeerId = GetServerPeerId(instance); if (serverPeerId != 0L && sender != serverPeerId) { return; } } _snapshot = text; _snapshotUtc = DateTime.UtcNow; if (!_loggedFirstSnapshot) { _loggedFirstSnapshot = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"TickProfiler first server snapshot received."); } } private bool TogglePressed() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) try { return ZInput.GetKeyDown(_toggleKey.Value, true); } catch (Exception ex) { try { return Input.GetKeyDown(_toggleKey.Value); } catch { ((BaseUnityPlugin)this).Logger.LogWarning((object)("TickProfiler toggle input failed: " + ex.Message)); return false; } } } private void OnGUI() { //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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_008d: 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_00a0: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_028f: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) if (!_visible) { return; } float num = ((_uiScale.Value > 0f) ? Mathf.Clamp(_uiScale.Value, 0.75f, 4f) : Mathf.Clamp((float)Screen.height / 1080f, 1f, 3f)); int fontSize = Math.Max(10, Mathf.RoundToInt((float)_fontSize.Value * num)); if (_textStyle == null) { _textStyle = new GUIStyle(GUI.skin.label) { richText = false, wordWrap = false, alignment = (TextAnchor)0 }; _textStyle.normal.textColor = Color.white; } _textStyle.fontSize = fontSize; string text; if (string.IsNullOrEmpty(_snapshot)) { text = "SERVER TICK PROFILER\nWaiting for TickProfiler data from this server...\nToggle " + ((object)_toggleKey.Value/*cast due to .constrained prefix*/).ToString(); } else { double num2 = Math.Max(0.0, (DateTime.UtcNow - _snapshotUtc).TotalSeconds); float num3 = -1f; try { if ((Object)(object)ZNet.instance != (Object)null) { num3 = ZNet.instance.GetServerPing() * 1000f; } } catch { } text = _snapshot + "\n\nAge " + num2.ToString("F1", CultureInfo.InvariantCulture) + "s" + ((num3 >= 0f) ? (" Ping " + num3.ToString("F0", CultureInfo.InvariantCulture) + "ms") : string.Empty) + " Toggle " + ((object)_toggleKey.Value/*cast due to .constrained prefix*/).ToString(); } int num4 = text.Count((char c) => c == '\n') + 1; float num5 = _x.Value * num; float num6 = _y.Value * num; float val = 520f * num; float num7 = Math.Min(Math.Max(val, _width.Value * num), Math.Max(val, (float)Screen.width - num5 - 12f * num)); float num8 = 20f * num + (float)num4 * ((float)_textStyle.fontSize + 5f * num); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(num5, num6, num7, num8); GUI.Box(val2, GUIContent.none); GUI.Label(new Rect(((Rect)(ref val2)).x + 10f * num, ((Rect)(ref val2)).y + 8f * num, ((Rect)(ref val2)).width - 20f * num, ((Rect)(ref val2)).height - 16f * num), text, _textStyle); } }