Decompiled source of AccuracyShower v1.0.1

Hikaria.AccuracyShower.dll

Decompiled 2 years ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using Agents;
using BepInEx;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Utils;
using GTFO.API;
using GameData;
using Gear;
using Hikaria.AccuracyShower.Extensions;
using Hikaria.AccuracyShower.Features;
using Hikaria.AccuracyShower.Handlers;
using Hikaria.AccuracyShower.Managers;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Player;
using SNetwork;
using TMPro;
using TheArchive;
using TheArchive.Core;
using TheArchive.Core.Attributes;
using TheArchive.Core.Attributes.Feature.Settings;
using TheArchive.Core.FeaturesAPI;
using TheArchive.Core.Models;
using TheArchive.Interfaces;
using TheArchive.Loader;
using TheArchive.Utilities;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Hikaria.AccuracyShower")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Hikaria.AccuracyShower")]
[assembly: AssemblyTitle("Hikaria.AccuracyShower")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Hikaria.AccuracyShower
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("Hikaria.AccuracyShower", "AccuracyShower", "1.0.1")]
	public class EntryPoint : BasePlugin, IArchiveModule
	{
		public static EntryPoint Instance { get; private set; }

		public bool ApplyHarmonyPatches => false;

		public bool UsesLegacyPatches => false;

		public ArchiveLegacyPatcher Patcher { get; set; }

		public override void Load()
		{
			Instance = this;
			ArchiveMod.RegisterArchiveModule(typeof(EntryPoint));
			Logs.LogMessage("OK");
		}

		public void Init()
		{
		}

		public void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
		}

		public void OnLateUpdate()
		{
		}

		public void OnExit()
		{
		}
	}
	internal static class Logs
	{
		private static IArchiveLogger _logger;

		private static IArchiveLogger Logger => _logger ?? (_logger = LoaderWrapper.CreateLoggerInstance("Hikaria.AccuracyShower", ConsoleColor.White));

		public static void LogDebug(object data)
		{
			Logger.Debug(data.ToString());
		}

		public static void LogError(object data)
		{
			Logger.Error(data.ToString());
		}

		public static void LogInfo(object data)
		{
			Logger.Info(data.ToString());
		}

		public static void LogMessage(object data)
		{
			Logger.Msg(ConsoleColor.White, data.ToString());
		}

		public static void LogWarning(object data)
		{
			Logger.Warning(data.ToString());
		}

		public static void LogNotice(object data)
		{
			Logger.Notice(data.ToString());
		}

		public static void LogSuccess(object data)
		{
			Logger.Success(data.ToString());
		}

		public static void LogException(Exception ex)
		{
			Logger.Exception(ex);
		}
	}
	public static class PluginInfo
	{
		public const string GUID = "Hikaria.AccuracyShower";

		public const string NAME = "AccuracyShower";

		public const string VERSION = "1.0.1";
	}
}
namespace Hikaria.AccuracyShower.Managers
{
	public static class AccuracyManager
	{
		[StructLayout(LayoutKind.Sequential, Size = 1)]
		private struct pBroadcastListenAccuracyData
		{
		}

		public struct pAccuracyData
		{
			public pPlayer m_player;

			public uint m_Hitted;

			public uint m_Shotted;

			public uint m_WeakspotHitted;

			public pAccuracyData(SNet_Player player, uint hitted, uint shotted, uint weakspotHitted)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				m_player = default(pPlayer);
				((pPlayer)(ref m_player)).SetPlayer(player);
				m_Hitted = hitted;
				m_Shotted = shotted;
				m_WeakspotHitted = weakspotHitted;
			}
		}

		public static bool IsMasterHasAcc => AccuracyDataListeners.Any((KeyValuePair<ulong, SNet_Player> p) => p.Key == SNet.Master.Lookup);

		private static Dictionary<ulong, SNet_Player> AccuracyDataListeners { get; set; } = new Dictionary<ulong, SNet_Player>();


		private static Dictionary<ulong, SNet_Player> LobbyPlayers { get; set; } = new Dictionary<ulong, SNet_Player>();


		internal static void Setup()
		{
			NetworkAPI.RegisterEvent<pAccuracyData>(typeof(pAccuracyData).FullName, (Action<ulong, pAccuracyData>)ReceiveAccuracyData);
			NetworkAPI.RegisterEvent<pBroadcastListenAccuracyData>(typeof(pBroadcastListenAccuracyData).FullName, (Action<ulong, pBroadcastListenAccuracyData>)ReceiveBroadcastListenAccuracyData);
		}

		private static void ReceiveBroadcastListenAccuracyData(ulong senderID, pBroadcastListenAccuracyData data)
		{
			SNet_Player val = default(SNet_Player);
			if (SNet.Core.TryGetPlayer(senderID, ref val, true))
			{
				AccuracyDataListeners.TryAdd(val.Lookup, val);
				AccuracyUpdater.MarkAllAccuracyDataNeedUpdate();
			}
		}

		private static void ReceiveAccuracyData(ulong senderID, pAccuracyData data)
		{
			SNet_Player val = default(SNet_Player);
			if ((Object)(object)AccuracyUpdater.Instance != (Object)null && ((pPlayer)(ref data.m_player)).TryGetPlayer(ref val) && !val.IsLocal)
			{
				AccuracyUpdater.Instance.UpdateAccuracyData(data);
			}
		}

		internal static void SendAccuracyData(AccuracyUpdater.AccuracyData data)
		{
			NetworkAPI.InvokeEvent<pAccuracyData>(typeof(pAccuracyData).FullName, data.GetAccuracyData(), AccuracyDataListeners.Values.ToList(), (SNet_ChannelType)4);
		}

		internal static void BroadcastAccuracyDataListener()
		{
			NetworkAPI.InvokeEvent<pBroadcastListenAccuracyData>(typeof(pBroadcastListenAccuracyData).FullName, default(pBroadcastListenAccuracyData), (SNet_ChannelType)4);
		}

		internal static void OnSessionMemberChanged(SNet_Player player, Hikaria.AccuracyShower.Features.AccuracyShower.SessionMemberEvent playerEvent)
		{
			switch (playerEvent)
			{
			case Hikaria.AccuracyShower.Features.AccuracyShower.SessionMemberEvent.JoinSessionHub:
				LobbyPlayers.TryAdd(player.Lookup, player);
				if (player.IsLocal)
				{
					AccuracyDataListeners.TryAdd(player.Lookup, player);
				}
				AccuracyUpdater.RegisterPlayer(player);
				break;
			case Hikaria.AccuracyShower.Features.AccuracyShower.SessionMemberEvent.LeftSessionHub:
				LobbyPlayers.Remove(player.Lookup);
				if (player.IsLocal)
				{
					AccuracyDataListeners.Clear();
					AccuracyUpdater.UnregisterAllPlayers();
				}
				else
				{
					AccuracyDataListeners.Remove(player.Lookup);
					AccuracyUpdater.UnregisterPlayer(player.Lookup);
				}
				break;
			}
		}

		public static bool IsAccuracyListener(ulong lookup)
		{
			return AccuracyDataListeners.ContainsKey(lookup);
		}

		public static bool IsLobbyPlayer(ulong lookup)
		{
			return LobbyPlayers.ContainsKey(lookup);
		}
	}
}
namespace Hikaria.AccuracyShower.Handlers
{
	public class AccuracyUpdater : MonoBehaviour
	{
		public class AccuracyData
		{
			internal SNet_Player m_Owner;

			internal uint m_Hitted;

			internal uint m_Shotted;

			internal uint m_WeakspotHitted;

			internal AccuracyData(SNet_Player player)
			{
				m_Owner = player;
				m_Hitted = 0u;
				m_Shotted = 0u;
				m_WeakspotHitted = 0u;
			}

			internal void Set(AccuracyManager.pAccuracyData data)
			{
				SNet_Player owner = default(SNet_Player);
				((pPlayer)(ref data.m_player)).TryGetPlayer(ref owner);
				m_Owner = owner;
				m_Hitted = data.m_Hitted;
				m_Shotted = data.m_Shotted;
				m_WeakspotHitted = data.m_WeakspotHitted;
			}

			internal void AddShotted(uint count)
			{
				m_Shotted += count;
			}

			internal void AddHitted(uint count)
			{
				m_Hitted += count;
			}

			internal void AddWeakspotHitted(uint count)
			{
				m_WeakspotHitted += count;
			}

			public SNet_Player GetOwner()
			{
				return m_Owner;
			}

			public uint GetHitted()
			{
				return m_Hitted;
			}

			public uint GetWeakspotHitted()
			{
				return m_WeakspotHitted;
			}

			public uint GetShotted()
			{
				return m_Shotted;
			}

			public string GetAccuracyText()
			{
				//IL_015b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_023d: Unknown result type (might be due to invalid IL or missing references)
				//IL_029d: Unknown result type (might be due to invalid IL or missing references)
				//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
				if (!m_Owner.HasCharacterSlot)
				{
					return string.Format(Hikaria.AccuracyShower.Features.AccuracyShower.Settings.ShowFormat, "-", "-", "-", 0, 0, 0);
				}
				string text = ((AccuracyManager.IsAccuracyListener(m_Owner.Lookup) || (AccuracyManager.IsMasterHasAcc && m_Owner.IsBot) || m_Owner.IsLocal) ? "" : "*");
				string text2 = (UseGenericName ? Hikaria.AccuracyShower.Features.AccuracyShower.Settings.CharacterNames[m_Owner.CharacterIndex].Name : m_Owner.NickName.RemoveHtmlTags());
				if (m_Shotted == 0)
				{
					return text + string.Format(Hikaria.AccuracyShower.Features.AccuracyShower.Settings.ShowFormat, text2, "-%", "-%", 0, 0, 0);
				}
				return text + string.Format(Hikaria.AccuracyShower.Features.AccuracyShower.Settings.ShowFormat, text2, $"<{SColorExtensions.ToHexString(Hikaria.AccuracyShower.Features.AccuracyShower.Settings.FontColors.HittedRatioColor)}>{100 * m_Hitted / m_Shotted}%</color>", (m_Hitted == 0) ? "-" : $"<{SColorExtensions.ToHexString(Hikaria.AccuracyShower.Features.AccuracyShower.Settings.FontColors.WeakspotHittedRatioColor)}>{100 * m_WeakspotHitted / m_Hitted}%</color>", $"<{SColorExtensions.ToHexString(Hikaria.AccuracyShower.Features.AccuracyShower.Settings.FontColors.WeakspotHittedColor)}>{m_WeakspotHitted}>", $"<{SColorExtensions.ToHexString(Hikaria.AccuracyShower.Features.AccuracyShower.Settings.FontColors.HittedColor)}>{m_Hitted}</color>", $"<{SColorExtensions.ToHexString(Hikaria.AccuracyShower.Features.AccuracyShower.Settings.FontColors.ShottedColor)}>{m_Shotted}</color>");
			}

			public AccuracyManager.pAccuracyData GetAccuracyData()
			{
				return new AccuracyManager.pAccuracyData(m_Owner, m_Hitted, m_Shotted, m_WeakspotHitted);
			}
		}

		private static int _offsetX = 0;

		private static int _offsetY = 0;

		private static bool _enable = true;

		private static bool _showOthersAcc = true;

		private static bool _showBotsAcc = false;

		private static string _showFormat = "{0}: {1}/{2}({4}/{5})";

		private static bool _useGenericName = true;

		private static bool _isSetup;

		private static Dictionary<ulong, Coroutine> RegisterPlayerCoroutines = new Dictionary<ulong, Coroutine>();

		public static AccuracyUpdater Instance { get; private set; }

		public static int OffsetX
		{
			get
			{
				return _offsetX;
			}
			set
			{
				_offsetX = value;
				if (IsSetup)
				{
					UpdateVisible();
				}
			}
		}

		public static int OffsetY
		{
			get
			{
				return _offsetY;
			}
			set
			{
				_offsetY = value;
				if (IsSetup)
				{
					UpdateVisible();
				}
			}
		}

		public static bool Enabled
		{
			get
			{
				return _enable;
			}
			internal set
			{
				if (IsSetup)
				{
					MarkAllAccuracyDataNeedUpdate();
				}
				_enable = value;
			}
		}

		public static bool ShowOtherPlayersAcc
		{
			get
			{
				return _showOthersAcc;
			}
			internal set
			{
				if (IsSetup)
				{
					MarkAllAccuracyDataNeedUpdate();
				}
				_showOthersAcc = value;
			}
		}

		public static bool ShowBotsAcc
		{
			get
			{
				return _showBotsAcc;
			}
			internal set
			{
				if (IsSetup)
				{
					MarkAllAccuracyDataNeedUpdate();
				}
				_showBotsAcc = value;
			}
		}

		public static string ShowFormat
		{
			get
			{
				return _showFormat;
			}
			set
			{
				if (IsSetup)
				{
					MarkAllAccuracyDataNeedUpdate();
				}
				_showFormat = value;
			}
		}

		public static bool UseGenericName
		{
			get
			{
				return _useGenericName;
			}
			set
			{
				if (IsSetup)
				{
					MarkAllAccuracyDataNeedUpdate();
				}
				_useGenericName = value;
			}
		}

		public static Dictionary<int, Hikaria.AccuracyShower.Features.AccuracyShower.PlayerNameEntry> CharacterNamesLookup { get; set; } = new Dictionary<int, Hikaria.AccuracyShower.Features.AccuracyShower.PlayerNameEntry>
		{
			{
				0,
				new Hikaria.AccuracyShower.Features.AccuracyShower.PlayerNameEntry("Wood", "RED")
			},
			{
				1,
				new Hikaria.AccuracyShower.Features.AccuracyShower.PlayerNameEntry("Dauda", "GRE")
			},
			{
				2,
				new Hikaria.AccuracyShower.Features.AccuracyShower.PlayerNameEntry("Hackett", "BLU")
			},
			{
				3,
				new Hikaria.AccuracyShower.Features.AccuracyShower.PlayerNameEntry("Bishop", "PUR")
			}
		};


		public static bool IsSetup
		{
			get
			{
				return _isSetup;
			}
			private set
			{
				_isSetup = value;
			}
		}

		private static Dictionary<int, TextMeshPro> AccuracyTextMeshes { get; set; } = new Dictionary<int, TextMeshPro>();


		private static Dictionary<ulong, AccuracyData> AccuracyDataLookup { get; set; } = new Dictionary<ulong, AccuracyData>();


		private static Dictionary<ulong, bool> AccuracyDataNeedUpdate { get; set; } = new Dictionary<ulong, bool>();


		private static Dictionary<int, bool> AccuracyTextMeshesVisible { get; set; } = new Dictionary<int, bool>();


		private static Dictionary<ulong, int> AccuracyRegisteredCharacterIndex { get; set; } = new Dictionary<ulong, int>();


		private void Awake()
		{
			Instance = this;
			Setup();
			MonoBehaviourExtensions.StartCoroutine((MonoBehaviour)(object)this, UpdateAccuracyDataCoroutine());
		}

		private void Setup()
		{
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Expected O, but got Unknown
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			if (IsSetup)
			{
				return;
			}
			AccuracyTextMeshesVisible[0] = false;
			AccuracyTextMeshesVisible[1] = false;
			AccuracyTextMeshesVisible[2] = false;
			AccuracyTextMeshesVisible[3] = false;
			PUI_Inventory inventory = GuiManager.Current.m_playerLayer.Inventory;
			foreach (RectTransform componentsInChild in ((Component)inventory.m_iconDisplay).GetComponentsInChildren<RectTransform>(true))
			{
				if (!(((Object)componentsInChild).name == "Background Fade"))
				{
					continue;
				}
				TextMeshPro slim_archetypeName = inventory.m_inventorySlots[(InventorySlot)10].m_slim_archetypeName;
				for (int i = 0; i < 4; i++)
				{
					GameObject val = Object.Instantiate<GameObject>(((Component)componentsInChild).gameObject, ((Transform)componentsInChild).parent);
					RectTransform component = val.GetComponent<RectTransform>();
					val.gameObject.SetActive(true);
					foreach (Transform componentsInChild2 in val.GetComponentsInChildren<Transform>(true))
					{
						if (((Object)componentsInChild2).name == "TimerShowObject")
						{
							((Component)componentsInChild2).gameObject.active = false;
						}
					}
					val.transform.localPosition = new Vector3(-70f + (float)OffsetX, (float)(-62 + OffsetY + -35 * i), 0f);
					AccuracyTextMeshes[i] = Object.Instantiate<TextMeshPro>(slim_archetypeName);
					GameObject val2 = new GameObject($"AccuracyShower{i}")
					{
						layer = 5,
						hideFlags = (HideFlags)61
					};
					val2.transform.SetParent(((Component)component).transform, false);
					TextMeshPro obj = AccuracyTextMeshes[i];
					((TMP_Text)obj).m_width = ((TMP_Text)obj).m_width * 2f;
					AccuracyTextMeshes[i].transform.SetParent(val2.transform, false);
					((Component)AccuracyTextMeshes[i]).GetComponent<RectTransform>().anchoredPosition = new Vector2(-5f, 9f);
					((TMP_Text)AccuracyTextMeshes[i]).SetText("-: -%/-%(0/0)", true);
					((TMP_Text)AccuracyTextMeshes[i]).ForceMeshUpdate(false, false);
				}
				break;
			}
			MarkAllAccuracyDataNeedUpdate();
			IsSetup = true;
		}

		internal static void CheckAndSetVisible()
		{
			if (!SNet.IsMaster)
			{
				foreach (ulong item in AccuracyDataLookup.Keys.ToList())
				{
					if (!AccuracyManager.IsAccuracyListener(item) && AccuracyRegisteredCharacterIndex.TryGetValue(item, out var value))
					{
						SetVisible(value, visible: false, update: false);
					}
				}
			}
			else
			{
				foreach (KeyValuePair<ulong, int> item2 in AccuracyRegisteredCharacterIndex)
				{
					SetVisible(item2.Value, visible: true, update: false);
				}
			}
			UpdateVisible();
		}

		internal static void RegisterPlayer(SNet_Player player)
		{
			if (RegisterPlayerCoroutines.ContainsKey(player.Lookup))
			{
				((MonoBehaviour)Instance).StopCoroutine(RegisterPlayerCoroutines[player.Lookup]);
			}
			MonoBehaviourExtensions.StartCoroutine((MonoBehaviour)(object)Instance, RegisterPlayerCoroutine(player));
		}

		private static IEnumerator RegisterPlayerCoroutine(SNet_Player player)
		{
			WaitForSecondsRealtime yielder = new WaitForSecondsRealtime(1f);
			while (!player.HasCharacterSlot || player.CharacterIndex == -1)
			{
				yield return yielder;
			}
			AccuracyRegisteredCharacterIndex[player.Lookup] = player.CharacterIndex;
			AccuracyDataLookup[player.Lookup] = new AccuracyData(player);
			AccuracyDataNeedUpdate[player.Lookup] = true;
		}

		private IEnumerator UpdateAccuracyDataCoroutine()
		{
			WaitForSecondsRealtime yielder = new WaitForSecondsRealtime(3f);
			while (true)
			{
				foreach (AccuracyData item in AccuracyDataLookup.Values.ToList())
				{
					SNet_Player owner = item.m_Owner;
					if (!AccuracyDataNeedUpdate[owner.Lookup] || !AccuracyRegisteredCharacterIndex.TryGetValue(owner.Lookup, out var value))
					{
						continue;
					}
					UpdateAccuracyData(value, item.GetAccuracyText());
					AccuracyDataNeedUpdate[owner.Lookup] = false;
					if ((SNet.IsMaster && (owner.IsBot || !AccuracyManager.IsAccuracyListener(owner.Lookup))) || owner.IsLocal)
					{
						AccuracyManager.SendAccuracyData(item);
					}
					if (NeedShowAccuracy(owner))
					{
						if (!AccuracyTextMeshesVisible[value])
						{
							SetVisible(value, visible: true);
						}
					}
					else if (AccuracyTextMeshesVisible[value])
					{
						SetVisible(value, visible: false);
					}
				}
				yield return yielder;
			}
		}

		internal void UpdateAccuracyData(AccuracyManager.pAccuracyData data)
		{
			SNet_Player val = default(SNet_Player);
			if (((pPlayer)(ref data.m_player)).TryGetPlayer(ref val))
			{
				AccuracyDataLookup[val.Lookup].Set(data);
				AccuracyDataNeedUpdate[val.Lookup] = true;
			}
		}

		private void UpdateAccuracyData(int index, string text)
		{
			if (AccuracyTextMeshes.TryGetValue(index, out var value))
			{
				((TMP_Text)value).SetText(text, true);
				((TMP_Text)value).ForceMeshUpdate(false, false);
			}
		}

		internal static void MarkAllAccuracyDataNeedUpdate()
		{
			foreach (ulong item in AccuracyDataNeedUpdate.Keys.ToList())
			{
				AccuracyDataNeedUpdate[item] = true;
			}
		}

		internal static void MarkAccuracyDataNeedUpdate(ulong lookup)
		{
			AccuracyDataNeedUpdate[lookup] = true;
		}

		internal static void DoClear()
		{
			foreach (ulong item in AccuracyDataLookup.Keys.ToList())
			{
				AccuracyData accuracyData = AccuracyDataLookup[item];
				accuracyData.m_Hitted = 0u;
				accuracyData.m_Shotted = 0u;
				accuracyData.m_WeakspotHitted = 0u;
				AccuracyDataNeedUpdate[item] = true;
			}
		}

		internal static void SetVisible(int index, bool visible, bool update = true)
		{
			AccuracyTextMeshesVisible[index] = Enabled && visible;
			if (update)
			{
				UpdateVisible();
			}
		}

		private static void UpdateVisible()
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < 4; i++)
			{
				if (!AccuracyTextMeshesVisible.ContainsKey(i))
				{
					continue;
				}
				int num = 0;
				for (int j = 0; j < 4; j++)
				{
					if (j <= i && !AccuracyTextMeshesVisible[j])
					{
						num++;
					}
				}
				if (AccuracyTextMeshesVisible[i])
				{
					((Component)AccuracyTextMeshes[i].transform.parent.parent).transform.localPosition = new Vector3(-70f + (float)OffsetX, -62f + (float)OffsetY + -35f * (float)(i - num), 0f);
				}
				else
				{
					((Component)AccuracyTextMeshes[i].transform.parent.parent).transform.localPosition = new Vector3(-70f, 1000f, 0f);
				}
			}
		}

		internal static void UnregisterAllPlayers()
		{
			foreach (ulong key in AccuracyRegisteredCharacterIndex.Keys)
			{
				UnregisterPlayer(key);
			}
			UpdateVisible();
		}

		internal static void UnregisterPlayer(ulong lookup)
		{
			if (AccuracyRegisteredCharacterIndex.ContainsKey(lookup))
			{
				SetVisible(AccuracyRegisteredCharacterIndex[lookup], visible: false);
			}
			AccuracyDataLookup.Remove(lookup);
			AccuracyDataNeedUpdate.Remove(lookup);
			AccuracyRegisteredCharacterIndex.Remove(lookup);
		}

		internal static void AddHitted(ulong lookup, uint count)
		{
			if (AccuracyDataLookup.ContainsKey(lookup))
			{
				AccuracyDataLookup[lookup].AddHitted(count);
			}
		}

		internal static void AddShotted(ulong lookup, uint count)
		{
			if (AccuracyDataLookup.ContainsKey(lookup))
			{
				AccuracyDataLookup[lookup].AddShotted(count);
			}
		}

		internal static void AddWeakspotHitted(ulong lookup, uint count)
		{
			if (AccuracyDataLookup.ContainsKey(lookup))
			{
				AccuracyDataLookup[lookup].AddWeakspotHitted(count);
			}
		}

		public static bool TryGetPlayerAccuracyData(SNet_Player player, out AccuracyData data)
		{
			return AccuracyDataLookup.TryGetValue(player.Lookup, out data);
		}

		private static bool NeedShowAccuracy(SNet_Player player)
		{
			if (!Hikaria.AccuracyShower.Features.AccuracyShower.Settings.Enabled || (!player.IsLocal && !ShowOtherPlayersAcc) || (player.IsBot && !ShowBotsAcc))
			{
				return false;
			}
			if (!AccuracyManager.IsAccuracyListener(player.Lookup) && !player.IsLocal && (!player.IsBot || !AccuracyManager.IsMasterHasAcc))
			{
				return AccuracyManager.IsMasterHasAcc;
			}
			return true;
		}
	}
}
namespace Hikaria.AccuracyShower.Features
{
	[EnableFeatureByDefault]
	[DisallowInGameToggle]
	public class AccuracyShower : Feature
	{
		public class AccuracyShowerSettings
		{
			[FSDisplayName("启用")]
			public bool Enabled
			{
				get
				{
					return AccuracyUpdater.Enabled;
				}
				set
				{
					AccuracyUpdater.Enabled = value;
				}
			}

			[FSDisplayName("显示其他玩家的命中率")]
			public bool ShowOtherPlayersAcc
			{
				get
				{
					return AccuracyUpdater.ShowOtherPlayersAcc;
				}
				set
				{
					AccuracyUpdater.ShowOtherPlayersAcc = value;
				}
			}

			[FSDisplayName("显示机器人玩家的命中率")]
			public bool ShowBotsAcc
			{
				get
				{
					return AccuracyUpdater.ShowBotsAcc;
				}
				set
				{
					AccuracyUpdater.ShowBotsAcc = value;
				}
			}

			[FSDisplayName("显示格式")]
			[FSDescription("{0}: 玩家名称, {1}: 命中率, {2}: 弱点命中率, {3}: 弱点命中次数, {4}: 命中次数, {5}: 弹丸击发次数")]
			public string ShowFormat
			{
				get
				{
					return AccuracyUpdater.ShowFormat;
				}
				set
				{
					AccuracyUpdater.ShowFormat = value;
				}
			}

			[FSDisplayName("使用通用玩家名称")]
			[FSDescription("若此项为 False, 则使用玩家名称")]
			public bool UseGenericName
			{
				get
				{
					return AccuracyUpdater.UseGenericName;
				}
				set
				{
					AccuracyUpdater.UseGenericName = value;
				}
			}

			[FSDisplayName("通用玩家名称设置")]
			[FSReadOnly(true)]
			public List<PlayerNameEntry> CharacterNames
			{
				get
				{
					return AccuracyUpdater.CharacterNamesLookup.Values.ToList();
				}
				set
				{
				}
			}

			[FSDisplayName("显示位置设置")]
			public PositionSettings Position { get; set; } = new PositionSettings();


			[FSDisplayName("显示颜色设置")]
			public ColorSettings FontColors { get; set; } = new ColorSettings();

		}

		public class PlayerNameEntry
		{
			private string _name;

			[FSSeparator]
			[FSDisplayName("人物")]
			[FSReadOnly(true)]
			public string Character { get; set; }

			[FSDisplayName("名称")]
			public string Name
			{
				get
				{
					return _name;
				}
				set
				{
					if (AccuracyUpdater.IsSetup)
					{
						AccuracyUpdater.MarkAllAccuracyDataNeedUpdate();
					}
					_name = value;
				}
			}

			public PlayerNameEntry(string character, string name)
			{
				Character = character;
				Name = name;
			}
		}

		public class PositionSettings
		{
			[FSDisplayName("横向偏移量")]
			[FSDescription("单位: 像素")]
			public int OffsetX
			{
				get
				{
					return AccuracyUpdater.OffsetX;
				}
				set
				{
					AccuracyUpdater.OffsetX = value;
				}
			}

			[FSDisplayName("纵向向偏移量")]
			[FSDescription("单位: 像素")]
			public int OffsetY
			{
				get
				{
					return AccuracyUpdater.OffsetY;
				}
				set
				{
					AccuracyUpdater.OffsetY = value;
				}
			}
		}

		public class ColorSettings
		{
			[FSDisplayName("命中率颜色")]
			public SColor WeakspotHittedRatioColor { get; set; } = new SColor(0.7206f, 0.7206f, 0.7206f, (float?)0.3137f);


			[FSDisplayName("弱点命中率颜色")]
			public SColor HittedRatioColor { get; set; } = new SColor(0.7206f, 0.7206f, 0.7206f, (float?)0.3137f);


			[FSDisplayName("弱点命中次数颜色")]
			public SColor WeakspotHittedColor { get; set; } = new SColor(0.7206f, 0.7206f, 0.7206f, (float?)0.3137f);


			[FSDisplayName("命中次数颜色")]
			public SColor HittedColor { get; set; } = new SColor(0.7206f, 0.7206f, 0.7206f, (float?)0.3137f);


			[FSDisplayName("弹丸击发次数颜色")]
			public SColor ShottedColor { get; set; } = new SColor(0.7206f, 0.7206f, 0.7206f, (float?)0.3137f);

		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		public class CM_PageRundown_New__Setup__Postfix
		{
			private static void Postfix()
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Expected O, but got Unknown
				if (!IsSetup)
				{
					GameObject val = new GameObject("AccuracyShower");
					Object.DontDestroyOnLoad((Object)(object)val);
					if ((Object)(object)val.GetComponent<AccuracyUpdater>() == (Object)null)
					{
						val.AddComponent<AccuracyUpdater>();
					}
					IsSetup = true;
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class SNet_GlobalManager__Setup__Patch
		{
			private static void Postfix()
			{
				SNet_Events.OnMasterChanged += Action.op_Implicit((Action)OnMasterChanged);
				SNet_Events.OnPlayerEvent += Action<SNet_Player, SNet_PlayerEvent, SNet_PlayerEventReason>.op_Implicit((Action<SNet_Player, SNet_PlayerEvent, SNet_PlayerEventReason>)OnPlayerEvent);
			}
		}

		public enum SessionMemberEvent
		{
			JoinSessionHub,
			LeftSessionHub
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class SentryGunInstance_Firing_Bullets__FireBullet__Patch
		{
			private static void Prefix()
			{
				IsSentryGunFire = true;
			}

			private static void Postfix()
			{
				IsSentryGunFire = false;
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class SentryGunInstance_Firing_Bullets__UpdateFireShotgunSemi__Patch
		{
			private static void Prefix()
			{
				IsSentryGunFire = true;
			}

			private static void Postfix()
			{
				IsSentryGunFire = false;
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class PlayerSync__SyncInventoryStatus__Patch
		{
			private static void Prefix(PlayerSync __instance)
			{
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: 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_003b: Invalid comparison between Unknown and I4
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Invalid comparison between Unknown and I4
				SNet_Player owner = __instance.m_agent.Owner;
				if (!owner.IsLocal && SNet.IsMaster && !owner.IsBot && !AccuracyManager.IsAccuracyListener(owner.Lookup))
				{
					InventorySlot wieldedSlot = __instance.GetWieldedSlot();
					if ((int)wieldedSlot == 1 || (int)wieldedSlot == 2)
					{
						LastWieldValidSlot[owner.Lookup] = wieldedSlot;
					}
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class PlayerInventorySynced__GetSync__Patch
		{
			private static void Prefix(PlayerInventorySynced __instance)
			{
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: Invalid comparison between Unknown and I4
				//IL_0076: Unknown result type (might be due to invalid IL or missing references)
				//IL_0078: Invalid comparison between Unknown and I4
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Invalid comparison between Unknown and I4
				//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)((PlayerInventoryBase)__instance).Owner == (Object)null)
				{
					return;
				}
				SNet_Player owner = ((PlayerInventoryBase)__instance).Owner.Owner;
				if (!SNet.IsMaster || owner.IsBot || owner.IsLocal || AccuracyManager.IsAccuracyListener(owner.Lookup))
				{
					return;
				}
				InventorySlot wieldedSlot = ((PlayerInventoryBase)__instance).Owner.Inventory.WieldedSlot;
				if ((int)wieldedSlot == 3)
				{
					return;
				}
				uint num = (uint)((PlayerInventoryBase)__instance).Owner.Sync.FireCountSync;
				InventorySlot value;
				if ((Object)(object)((PlayerInventoryBase)__instance).WieldedItem != (Object)null && ((int)wieldedSlot == 1 || (int)wieldedSlot == 2))
				{
					BulletWeaponSynced val = ((Il2CppObjectBase)((PlayerInventoryBase)__instance).WieldedItem).TryCast<BulletWeaponSynced>();
					if ((Object)(object)val != (Object)null)
					{
						ShotgunSynced val2 = ((Il2CppObjectBase)val).TryCast<ShotgunSynced>();
						if ((Object)(object)val2 != (Object)null && ((ItemEquippable)val2).ArchetypeData != null)
						{
							num *= (uint)((ItemEquippable)val2).ArchetypeData.ShotgunBulletCount;
						}
					}
				}
				else if (LastWieldValidSlot.TryGetValue(owner.Lookup, out value))
				{
					PlayerBackpack val3 = default(PlayerBackpack);
					BackpackItem val4 = default(BackpackItem);
					if (!PlayerBackpackManager.TryGetBackpack(owner, ref val3) || !val3.TryGetBackpackItem(value, ref val4))
					{
						return;
					}
					BulletWeaponSynced val5 = ((Il2CppObjectBase)val4.Instance).TryCast<BulletWeaponSynced>();
					if ((Object)(object)val5 != (Object)null)
					{
						ShotgunSynced val6 = ((Il2CppObjectBase)val5).TryCast<ShotgunSynced>();
						if ((Object)(object)val6 != (Object)null && ((ItemEquippable)val6).ArchetypeData != null)
						{
							num *= (uint)((ItemEquippable)val6).ArchetypeData.ShotgunBulletCount;
						}
					}
					else
					{
						Logs.LogError("Not BulletWeapon but fire bullets?");
					}
				}
				AccuracyUpdater.AddShotted(owner.Lookup, num);
				AccuracyUpdater.MarkAccuracyDataNeedUpdate(owner.Lookup);
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class Dam_EnemyDamageBase__ReceiveBulletDamage__Patch
		{
			private static void Postfix(Dam_EnemyDamageBase __instance, pBulletDamageData data)
			{
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Invalid comparison between Unknown and I4
				Agent val = default(Agent);
				if (IsSentryGunFire || !((pAgent)(ref data.source)).TryGet(ref val))
				{
					return;
				}
				PlayerAgent val2 = ((Il2CppObjectBase)val).TryCast<PlayerAgent>();
				if ((Object)(object)val2 == (Object)null)
				{
					return;
				}
				SNet_Player owner = val2.Owner;
				if (!AccuracyManager.IsAccuracyListener(owner.Lookup) && !owner.IsLocal && !owner.IsBot)
				{
					if ((int)((Il2CppArrayBase<Dam_EnemyDamageLimb>)(object)__instance.DamageLimbs)[(int)data.limbID].m_type == 1)
					{
						AccuracyUpdater.AddWeakspotHitted(owner.Lookup, 1u);
					}
					AccuracyUpdater.AddHitted(owner.Lookup, 1u);
					AccuracyUpdater.MarkAccuracyDataNeedUpdate(owner.Lookup);
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class BulletWeaponSynced__Fire__Patch
		{
			private static void Prefix(BulletWeaponSynced __instance)
			{
				if (((Item)__instance).Owner.Owner.IsBot && SNet.IsMaster)
				{
					CanCalc = true;
					IsInWeaponFire = true;
					IsPiercingBullet = false;
					BulletPiercingLimit = 1;
					HitCount = 0u;
					BulletHitCalledCount = 0;
					BulletsCountPerFire = 1;
					ArchetypeDataBlock archetypeData = ((ItemEquippable)__instance).ArchetypeData;
					if (archetypeData != null)
					{
						IsPiercingBullet = archetypeData.PiercingBullets;
						BulletPiercingLimit = (archetypeData.PiercingBullets ? archetypeData.PiercingDamageCountLimit : 0);
					}
				}
			}

			private static void Postfix(BulletWeapon __instance)
			{
				if (((Item)__instance).Owner.Owner.IsBot && SNet.IsMaster)
				{
					CanCalc = false;
					IsInWeaponFire = false;
					SNet_Player owner = ((Item)__instance).Owner.Owner;
					AccuracyUpdater.AddShotted(owner.Lookup, (uint)BulletsCountPerFire);
					AccuracyUpdater.AddHitted(owner.Lookup, HitCount);
					AccuracyUpdater.MarkAccuracyDataNeedUpdate(owner.Lookup);
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class ShotgunSynced__Fire__Patch
		{
			private static void Prefix(Shotgun __instance)
			{
				if (((Item)__instance).Owner.Owner.IsBot && SNet.IsMaster)
				{
					CanCalc = true;
					IsInWeaponFire = true;
					IsPiercingBullet = false;
					BulletPiercingLimit = 1;
					HitCount = 0u;
					BulletHitCalledCount = 0;
					BulletsCountPerFire = 1;
					ArchetypeDataBlock archetypeData = ((ItemEquippable)__instance).ArchetypeData;
					if (archetypeData != null)
					{
						IsPiercingBullet = archetypeData.PiercingBullets;
						BulletPiercingLimit = (archetypeData.PiercingBullets ? archetypeData.PiercingDamageCountLimit : 0);
						BulletsCountPerFire = archetypeData.ShotgunBulletCount;
					}
				}
			}

			private static void Postfix(BulletWeapon __instance)
			{
				if (((Item)__instance).Owner.Owner.IsBot && SNet.IsMaster)
				{
					CanCalc = false;
					IsInWeaponFire = false;
					SNet_Player owner = ((Item)__instance).Owner.Owner;
					AccuracyUpdater.AddShotted(owner.Lookup, (uint)BulletsCountPerFire);
					AccuracyUpdater.AddHitted(owner.Lookup, HitCount);
					AccuracyUpdater.MarkAccuracyDataNeedUpdate(owner.Lookup);
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class BulletWeapon__Fire__Patch
		{
			private static void Prefix(BulletWeapon __instance)
			{
				if (IsWeaponOwner(__instance))
				{
					CanCalc = true;
					IsInWeaponFire = true;
					IsPiercingBullet = false;
					BulletPiercingLimit = 1;
					HitCount = 0u;
					BulletHitCalledCount = 0;
					BulletsCountPerFire = 1;
					ArchetypeDataBlock archetypeData = ((ItemEquippable)__instance).ArchetypeData;
					if (archetypeData != null)
					{
						IsPiercingBullet = archetypeData.PiercingBullets;
						BulletPiercingLimit = (archetypeData.PiercingBullets ? archetypeData.PiercingDamageCountLimit : 0);
					}
				}
			}

			private static void Postfix(BulletWeapon __instance)
			{
				if (IsWeaponOwner(__instance))
				{
					CanCalc = false;
					IsInWeaponFire = false;
					SNet_Player owner = ((Item)__instance).Owner.Owner;
					AccuracyUpdater.AddShotted(owner.Lookup, (uint)BulletsCountPerFire);
					AccuracyUpdater.AddHitted(owner.Lookup, HitCount);
					AccuracyUpdater.MarkAccuracyDataNeedUpdate(owner.Lookup);
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class Shotgun__Fire__Patch
		{
			private static void Prefix(Shotgun __instance)
			{
				if (IsWeaponOwner((BulletWeapon)(object)__instance))
				{
					CanCalc = true;
					IsInWeaponFire = true;
					IsPiercingBullet = false;
					BulletPiercingLimit = 1;
					HitCount = 0u;
					BulletHitCalledCount = 0;
					BulletsCountPerFire = 1;
					ArchetypeDataBlock archetypeData = ((ItemEquippable)__instance).ArchetypeData;
					if (archetypeData != null)
					{
						IsPiercingBullet = archetypeData.PiercingBullets;
						BulletPiercingLimit = (archetypeData.PiercingBullets ? archetypeData.PiercingDamageCountLimit : 0);
						BulletsCountPerFire = archetypeData.ShotgunBulletCount;
					}
				}
			}

			private static void Postfix(Shotgun __instance)
			{
				if (IsWeaponOwner((BulletWeapon)(object)__instance))
				{
					CanCalc = false;
					IsInWeaponFire = false;
					SNet_Player owner = ((Item)__instance).Owner.Owner;
					AccuracyUpdater.AddShotted(owner.Lookup, (uint)BulletsCountPerFire);
					AccuracyUpdater.AddHitted(owner.Lookup, HitCount);
					AccuracyUpdater.MarkAccuracyDataNeedUpdate(owner.Lookup);
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class Dam_EnemyDamageLimb__BulletDamage__Patch
		{
			private static void Postfix(Dam_EnemyDamageLimb __instance, Agent sourceAgent)
			{
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Invalid comparison between Unknown and I4
				if (CanCalc && !((Object)(object)sourceAgent == (Object)null))
				{
					PlayerAgent val = ((Il2CppObjectBase)sourceAgent).TryCast<PlayerAgent>();
					if ((Object)(object)val != (Object)null && (int)__instance.m_type == 1)
					{
						AccuracyUpdater.AddWeakspotHitted(val.Owner.Lookup, 1u);
					}
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class BulletWeapon__BulletHit__Patch
		{
			private static bool CanCalcHitted;

			private static void Postfix(bool __result)
			{
				if (!IsInWeaponFire || IsSentryGunFire || !CanCalc || BulletHitCalledCount >= BulletsCountPerFire)
				{
					return;
				}
				if (IsPiercingBullet)
				{
					if (BulletHitCalledCount % BulletPiercingLimit == 0)
					{
						CanCalcHitted = true;
					}
				}
				else
				{
					CanCalcHitted = true;
				}
				BulletHitCalledCount++;
				if (__result && CanCalcHitted)
				{
					HitCount++;
					CanCalcHitted = false;
				}
			}
		}

		private static uint HitCount;

		private static int BulletPiercingLimit;

		private static int BulletsCountPerFire;

		private static int BulletHitCalledCount;

		private static bool IsPiercingBullet;

		private static bool IsInWeaponFire;

		private static bool CanCalc;

		public override string Name => "AccuracyShower";

		public override string Group => Group.op_Implicit(FeatureGroups.Hud);

		[FeatureConfig]
		public static AccuracyShowerSettings Settings { get; set; }

		public static bool IsSetup { get; private set; }

		public static bool IsSentryGunFire { get; private set; }

		private static Dictionary<ulong, InventorySlot> LastWieldValidSlot { get; set; } = new Dictionary<ulong, InventorySlot>();


		public override void OnGameStateChanged(int state)
		{
			if (state == 5)
			{
				AccuracyUpdater.DoClear();
			}
		}

		public override void Init()
		{
			ClassInjector.RegisterTypeInIl2Cpp<AccuracyUpdater>(false);
			AccuracyManager.Setup();
		}

		private static void OnPlayerEvent(SNet_Player player, SNet_PlayerEvent playerEvent, SNet_PlayerEventReason reason)
		{
			//IL_0005: 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)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			AccuracyManager.BroadcastAccuracyDataListener();
			if ((int)playerEvent != 0)
			{
				if ((int)playerEvent == 5)
				{
					AccuracyManager.OnSessionMemberChanged(player, SessionMemberEvent.JoinSessionHub);
					return;
				}
				if ((int)playerEvent != 6)
				{
					return;
				}
			}
			AccuracyManager.OnSessionMemberChanged(player, SessionMemberEvent.LeftSessionHub);
		}

		private static void OnMasterChanged()
		{
			AccuracyUpdater.CheckAndSetVisible();
		}

		private static bool IsWeaponOwner(BulletWeapon weapon)
		{
			if ((Object)(object)weapon == (Object)null || (Object)(object)((Item)weapon).Owner == (Object)null || (Object)(object)((Item)weapon).Owner.Owner == (Object)null)
			{
				return false;
			}
			return ((Item)weapon).Owner.Owner.IsLocal;
		}
	}
}
namespace Hikaria.AccuracyShower.Extensions
{
	internal static class StringExts
	{
		public static string RemoveHtmlTags(this string htmlString)
		{
			string pattern = "<.*?>";
			return Regex.Replace(htmlString, pattern, string.Empty);
		}
	}
}