Decompiled source of EventChatNotifications v0.4.1

EventChatNotifications.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;

[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("EventChatNotifications")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EventChatNotifications")]
[assembly: AssemblyTitle("EventChatNotifications")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 EventChatNotifications
{
	[BepInPlugin("sbg.eventchatnotifications", "EventChatNotifications", "0.4.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string ModGuid = "sbg.eventchatnotifications";

		public const string ModName = "EventChatNotifications";

		public const string ModVersion = "0.4.1";

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			new Harmony("sbg.eventchatnotifications").PatchAll();
			FirstPlaceTracker.Hook();
			Log.LogInfo((object)"EventChatNotifications v0.4.1 loaded.");
		}

		private void OnDestroy()
		{
			FirstPlaceTracker.Unhook();
		}
	}
	internal static class FirstPlaceTracker
	{
		private enum Metric
		{
			BestHoleScore,
			LongestChipIn,
			AvgFinishTime,
			ItemPickups,
			KORatio
		}

		private static readonly Metric[] AllMetrics = new Metric[5]
		{
			Metric.BestHoleScore,
			Metric.LongestChipIn,
			Metric.AvgFinishTime,
			Metric.ItemPickups,
			Metric.KORatio
		};

		private static readonly Dictionary<Metric, ulong> CurrentLeader = new Dictionary<Metric, ulong>();

		private static bool subscribed;

		internal static void Hook()
		{
			if (!subscribed)
			{
				CourseManager.PlayerStatesChanged += OnPlayerStatesChanged;
				subscribed = true;
			}
		}

		internal static void Unhook()
		{
			if (subscribed)
			{
				CourseManager.PlayerStatesChanged -= OnPlayerStatesChanged;
				CurrentLeader.Clear();
				subscribed = false;
			}
		}

		private static void OnPlayerStatesChanged(Operation<PlayerState> op, int index, PlayerState changed)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			SyncList<PlayerState> playerStates = CourseManager.PlayerStates;
			if (playerStates == null)
			{
				return;
			}
			int num = 0;
			for (int i = 0; i < playerStates.Count; i++)
			{
				if (!playerStates[i].isSpectator && playerStates[i].isConnected)
				{
					num++;
				}
			}
			if (num >= 2)
			{
				Metric[] allMetrics = AllMetrics;
				foreach (Metric metric in allMetrics)
				{
					Reconcile(playerStates, metric);
				}
			}
		}

		private static void Reconcile(SyncList<PlayerState> states, Metric metric)
		{
			if (TryComputeLeader(states, metric, out var leaderGuid, out var valueLabel))
			{
				ulong value;
				bool flag = CurrentLeader.TryGetValue(metric, out value);
				if (!flag || value != leaderGuid)
				{
					CurrentLeader[metric] = leaderGuid;
					string text = Narrator.PlayerNameFromGuid(leaderGuid);
					string text2 = MetricLabel(metric);
					Narrator.Post(flag ? (text + " took first on " + text2 + " from " + Narrator.PlayerNameFromGuid(value) + " — " + valueLabel + ".") : (text + " took first on " + text2 + " — " + valueLabel + "."));
				}
			}
		}

		private static bool TryComputeLeader(SyncList<PlayerState> states, Metric metric, out ulong leaderGuid, out string valueLabel)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			leaderGuid = 0uL;
			valueLabel = null;
			bool flag = false;
			ulong num = 0uL;
			int num2 = int.MaxValue;
			float num3 = 0f;
			int num4 = 0;
			for (int i = 0; i < states.Count; i++)
			{
				PlayerState val = states[i];
				if (val.isSpectator || !val.isConnected || !IsEligible(val, metric))
				{
					continue;
				}
				bool flag2;
				if (!flag)
				{
					flag2 = true;
				}
				else if (UsesIntComparison(metric))
				{
					int num5 = ReadInt(val, metric);
					flag2 = (LowerIsBetter(metric) ? (num5 < num4) : (num5 > num4));
				}
				else
				{
					float num6 = ReadFloat(val, metric);
					flag2 = (LowerIsBetter(metric) ? (num6 < num3) : (num6 > num3));
				}
				if (flag2)
				{
					num = val.playerGuid;
					num2 = val.joinIndex;
					flag = true;
					if (UsesIntComparison(metric))
					{
						num4 = ReadInt(val, metric);
					}
					else
					{
						num3 = ReadFloat(val, metric);
					}
				}
				else if (HasTie(val, metric, num4, num3) && val.joinIndex < num2)
				{
					num = val.playerGuid;
					num2 = val.joinIndex;
				}
			}
			if (!flag)
			{
				return false;
			}
			leaderGuid = num;
			valueLabel = FormatValue(states, num, metric, num4, num3);
			return true;
		}

		private static bool IsEligible(PlayerState s, Metric metric)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Invalid comparison between Unknown and I4
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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)
			switch (metric)
			{
			case Metric.BestHoleScore:
				return (int)s.bestHoleScore > 0;
			case Metric.LongestChipIn:
				return s.longestChipIn > float.MinValue;
			case Metric.AvgFinishTime:
				if (s.avgFinishTime > 0f)
				{
					return s.finishes > 0;
				}
				return false;
			case Metric.ItemPickups:
				return s.itemPickups > 0;
			case Metric.KORatio:
				return s.matchKnockouts > 0;
			default:
				return false;
			}
		}

		private static bool UsesIntComparison(Metric m)
		{
			if (m != 0)
			{
				return m == Metric.ItemPickups;
			}
			return true;
		}

		private static bool LowerIsBetter(Metric m)
		{
			return m == Metric.AvgFinishTime;
		}

		private static int ReadInt(PlayerState s, Metric m)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected I4, but got Unknown
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			return m switch
			{
				Metric.BestHoleScore => (int)s.bestHoleScore, 
				Metric.ItemPickups => s.itemPickups, 
				_ => 0, 
			};
		}

		private static float ReadFloat(PlayerState s, Metric m)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			return m switch
			{
				Metric.LongestChipIn => s.longestChipIn, 
				Metric.AvgFinishTime => s.avgFinishTime, 
				Metric.KORatio => ComputeKORatio(s), 
				_ => 0f, 
			};
		}

		private static float ComputeKORatio(PlayerState s)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Max(1, s.matchKnockedOut);
			return (float)s.matchKnockouts / (float)num;
		}

		private static bool HasTie(PlayerState s, Metric metric, int bestInt, float bestFloat)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (UsesIntComparison(metric))
			{
				return ReadInt(s, metric) == bestInt;
			}
			return Mathf.Approximately(ReadFloat(s, metric), bestFloat);
		}

		private static string FormatValue(SyncList<PlayerState> states, ulong leaderGuid, Metric metric, int bestInt, float bestFloat)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			switch (metric)
			{
			case Metric.BestHoleScore:
				return DescribeStrokesUnderPar((StrokesUnderParType)bestInt);
			case Metric.LongestChipIn:
				return $"{Mathf.RoundToInt(bestFloat)}m";
			case Metric.AvgFinishTime:
				return $"{bestFloat:0.0}s";
			case Metric.ItemPickups:
				return bestInt.ToString();
			case Metric.KORatio:
			{
				for (int i = 0; i < states.Count; i++)
				{
					if (states[i].playerGuid == leaderGuid)
					{
						PlayerState val = states[i];
						return $"{bestFloat:0.00} ({val.matchKnockouts}/{val.matchKnockedOut})";
					}
				}
				return bestFloat.ToString("0.00");
			}
			default:
				return string.Empty;
			}
		}

		private static string MetricLabel(Metric m)
		{
			return m switch
			{
				Metric.BestHoleScore => "best hole", 
				Metric.LongestChipIn => "longest chip-in", 
				Metric.AvgFinishTime => "average finish time", 
				Metric.ItemPickups => "item pickups", 
				Metric.KORatio => "K/O ratio", 
				_ => "stat", 
			};
		}

		private static string DescribeStrokesUnderPar(StrokesUnderParType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected I4, but got Unknown
			return (type - 1) switch
			{
				5 => "Hole in One", 
				4 => "Condor", 
				3 => "Albatross", 
				2 => "Eagle", 
				1 => "Birdie", 
				0 => "Par", 
				_ => "—", 
			};
		}
	}
	internal static class Narrator
	{
		private const string Prefix = "<color=#9aa6ff><b>[Match]</b></color> ";

		internal static void Post(string message)
		{
			if (string.IsNullOrEmpty(message))
			{
				return;
			}
			try
			{
				TextChatUi.ShowMessage("<color=#9aa6ff><b>[Match]</b></color> " + message);
			}
			catch
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("[chat-fallback] " + message));
				}
			}
		}

		internal static string PlayerNameFromGuid(ulong guid)
		{
			PlayerInfo localPlayerInfo = GameManager.LocalPlayerInfo;
			if ((Object)(object)localPlayerInfo != (Object)null && (Object)(object)localPlayerInfo.PlayerId != (Object)null && localPlayerInfo.PlayerId.Guid == guid)
			{
				return localPlayerInfo.PlayerId.PlayerNameNoRichText;
			}
			if (GameManager.RemotePlayers != null)
			{
				foreach (PlayerInfo remotePlayer in GameManager.RemotePlayers)
				{
					if (!((Object)(object)remotePlayer == (Object)null) && !((Object)(object)remotePlayer.PlayerId == (Object)null) && remotePlayer.PlayerId.Guid == guid)
					{
						return remotePlayer.PlayerId.PlayerNameNoRichText;
					}
				}
			}
			return "Someone";
		}

		internal static string DescribeStrokesUnderPar(StrokesUnderParType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected I4, but got Unknown
			return (type - 2) switch
			{
				4 => "scored a hole in one!", 
				2 => "landed an albatross!", 
				1 => "landed an eagle!", 
				0 => "landed a birdie!", 
				3 => "pulled off a condor!", 
				_ => null, 
			};
		}
	}
	[HarmonyPatch(typeof(InfoFeed), "UserCode_RpcShowMessage__StrokesMessageData")]
	internal static class Patch_StrokesMessage
	{
		private static void Postfix(StrokesMessageData messageData)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			string text = Narrator.DescribeStrokesUnderPar(messageData.strokesUnderParType);
			if (text != null)
			{
				Narrator.Post(Narrator.PlayerNameFromGuid(messageData.playerGuid) + " " + text);
			}
		}
	}
	[HarmonyPatch(typeof(InfoFeed), "UserCode_RpcShowMessage__SpeedrunMessageData")]
	internal static class Patch_SpeedrunMessage
	{
		private static void Postfix(SpeedrunMessageData messageData)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			Narrator.Post(Narrator.PlayerNameFromGuid(messageData.playerGuid) + " sprinted through the hole — that was fast!");
		}
	}
}