Decompiled source of Killfeed v0.3.1

Killfeed.dll

Decompiled 5 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Bloodstone.API;
using Cpp2IL.Core.Extensions;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Microsoft.CodeAnalysis;
using ProjectM;
using ProjectM.Network;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using VampireCommandFramework;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Killfeed")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("PvP Leaderboard and Killfeed Announcements.")]
[assembly: AssemblyFileVersion("0.3.1.0")]
[assembly: AssemblyInformationalVersion("0.3.1+1.Branch.main.Sha.08dd5b38f4f81d1d82d25dd0b313b55a2ad849db")]
[assembly: AssemblyProduct("Killfeed")]
[assembly: AssemblyTitle("Killfeed")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.1.0")]
[module: UnverifiableCode]
[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;
		}
	}
}
internal static class ECSExtensions
{
	internal static void With<T>(this Entity entity, ActionRef<T> action) where T : struct
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		T val = entity.RW<T>();
		action.Invoke(ref val);
		EntityManager entityManager = VWorld.Game.EntityManager;
		((EntityManager)(ref entityManager)).SetComponentData<T>(entity, val);
	}

	internal static bool Has<T>(this Entity entity) where T : struct
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: 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_001f: Unknown result type (might be due to invalid IL or missing references)
		int num = TypeIndex.op_Implicit(TypeManager.GetTypeIndex(Il2CppType.Of<T>()));
		EntityManager entityManager = VWorld.Game.EntityManager;
		return ((EntityManager)(ref entityManager)).HasComponentRaw(entity, TypeIndex.op_Implicit(num));
	}

	internal static bool Has<T>(this Entity entity, out T value) where T : struct
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		if (entity.Has<T>())
		{
			value = entity.Read<T>();
			return true;
		}
		value = default(T);
		return false;
	}

	internal unsafe static T RW<T>(this Entity entity) where T : struct
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: 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_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		int num = TypeIndex.op_Implicit(TypeManager.GetTypeIndex(Il2CppType.Of<T>()));
		EntityManager entityManager = VWorld.Game.EntityManager;
		T* componentDataRawRW = (T*)((EntityManager)(ref entityManager)).GetComponentDataRawRW(entity, TypeIndex.op_Implicit(num));
		if (componentDataRawRW == null)
		{
			throw new InvalidOperationException($"Failure to access ReadWrite <{typeof(T).Name}> typeIndex({num}) on entity({entity}).");
		}
		return *componentDataRawRW;
	}

	internal unsafe static T Read<T>(this Entity entity) where T : struct
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: 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_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		int num = TypeIndex.op_Implicit(TypeManager.GetTypeIndex(Il2CppType.Of<T>()));
		EntityManager entityManager = VWorld.Game.EntityManager;
		T* componentDataRawRO = (T*)((EntityManager)(ref entityManager)).GetComponentDataRawRO(entity, TypeIndex.op_Implicit(num));
		if (componentDataRawRO == null)
		{
			throw new InvalidOperationException($"Failure to access ReadOnly <{typeof(T).Name}> typeIndex({num}) on entity({entity}).");
		}
		return *componentDataRawRO;
	}
}
namespace Killfeed
{
	public class Commands
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<DataStore.PlayerStatistics, int> <>9__0_0;

			public static Func<string, string> <>9__0_1;

			public static Func<DataStore.PlayerStatistics, string> <>9__0_2;

			public static Func<DataStore.PlayerStatistics, int> <>9__1_0;

			public static Func<DataStore.PlayerStatistics, int, (DataStore.PlayerStatistics stats, int rank)> <>9__1_1;

			internal int <TopCommand>b__0_0(DataStore.PlayerStatistics k)
			{
				return k.Kills;
			}

			internal string <TopCommand>b__0_1(string name)
			{
				return new string(MiscExtensions.Repeat<char>('\t', 6 - name.Length / 5).ToArray());
			}

			internal string <TopCommand>b__0_2(DataStore.PlayerStatistics k)
			{
				return $"\t<color={"#dda"}><b>{k.Kills,-3}</b> / {k.Deaths,3}</color>\t{Markup.Highlight(k.LastName)}";
			}

			internal int <KillfeedCommand>b__1_0(DataStore.PlayerStatistics k)
			{
				return k.Kills;
			}

			internal (DataStore.PlayerStatistics stats, int rank) <KillfeedCommand>b__1_1(DataStore.PlayerStatistics stats, int rank)
			{
				return (stats, rank);
			}
		}

		[Command("killfeed leaderboard", "kf top", null, null, null, false)]
		public void TopCommand(ChatCommandContext ctx)
		{
			int num = 10;
			int num2 = 5;
			DataStore.PlayerStatistics[] array = DataStore.PlayerDatas.Values.OrderByDescending((DataStore.PlayerStatistics k) => k.Kills).Take(num).ToArray();
			num2 = ((num2 > array.Length) ? array.Length : num2);
			num = ((num > array.Length) ? array.Length : num);
			if (<>c.<>9__0_1 == null)
			{
				<>c.<>9__0_1 = (string name) => new string(MiscExtensions.Repeat<char>('\t', 6 - name.Length / 5).ToArray());
			}
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = new StringBuilder();
			stringBuilder2.AppendLine("");
			StringBuilder stringBuilder3 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder3;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(33, 1, stringBuilder3);
			handler.AppendFormatted(Markup.Prefix);
			handler.AppendLiteral(" <size=18><u>Top Kills</u></size>");
			stringBuilder4.AppendLine(ref handler);
			Func<DataStore.PlayerStatistics, string> func = (DataStore.PlayerStatistics k) => $"\t<color={"#dda"}><b>{k.Kills,-3}</b> / {k.Deaths,3}</color>\t{Markup.Highlight(k.LastName)}";
			for (int i = 0; i < num2; i++)
			{
				DataStore.PlayerStatistics arg = array[i];
				stringBuilder3 = stringBuilder;
				StringBuilder stringBuilder5 = stringBuilder3;
				handler = new StringBuilder.AppendInterpolatedStringHandler(2, 2, stringBuilder3);
				handler.AppendFormatted(i + 1);
				handler.AppendLiteral(". ");
				handler.AppendFormatted(func(arg));
				stringBuilder5.AppendLine(ref handler);
			}
			for (int j = num2; j < num; j++)
			{
				DataStore.PlayerStatistics arg2 = array[j];
				stringBuilder3 = stringBuilder2;
				StringBuilder stringBuilder6 = stringBuilder3;
				handler = new StringBuilder.AppendInterpolatedStringHandler(2, 2, stringBuilder3);
				handler.AppendFormatted(j + 1);
				handler.AppendLiteral(". ");
				handler.AppendFormatted(func(arg2));
				stringBuilder6.AppendLine(ref handler);
			}
			ctx.Reply(stringBuilder.ToString());
			ctx.Reply(stringBuilder2.ToString());
		}

		[Command("killfeed", "kf", null, "Shows Killfeed info", null, false)]
		public void KillfeedCommand(ChatCommandContext ctx)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			ulong platformId = ctx.User.PlatformId;
			if (!DataStore.PlayerDatas.TryGetValue(platformId, out var _))
			{
				throw ctx.Error("You have no stats yet!");
			}
			(DataStore.PlayerStatistics, int) tuple = DataStore.PlayerDatas.Values.OrderByDescending((DataStore.PlayerStatistics k) => k.Kills).Select((DataStore.PlayerStatistics stats, int rank) => (stats, rank)).First<(DataStore.PlayerStatistics, int)>(((DataStore.PlayerStatistics stats, int rank) u) => u.stats.SteamId == ctx.User.PlatformId);
			DataStore.PlayerStatistics item = tuple.Item1;
			int item2 = tuple.Item2;
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(36, 2, stringBuilder2);
			handler.AppendFormatted(Markup.Prefix);
			handler.AppendLiteral(" <size=21><u>Killfeed Stats for ");
			handler.AppendFormatted(Markup.Highlight(item.LastName));
			handler.AppendLiteral("</u>");
			stringBuilder3.AppendLine(ref handler);
			string value2 = Markup.Highlight($"{item2 + 1}") + " / " + Markup.Secondary(DataStore.PlayerDatas.Count);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(13, 1, stringBuilder2);
			handler.AppendLiteral("Rank: ");
			handler.AppendFormatted(value2);
			handler.AppendLiteral("</size>");
			stringBuilder4.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder5 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(7, 1, stringBuilder2);
			handler.AppendLiteral("Kills: ");
			handler.AppendFormatted(Markup.Highlight(item.Kills));
			stringBuilder5.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder6 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(8, 1, stringBuilder2);
			handler.AppendLiteral("Deaths: ");
			handler.AppendFormatted(Markup.Highlight(item.Deaths));
			stringBuilder6.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder7 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(16, 1, stringBuilder2);
			handler.AppendLiteral("Current Streak: ");
			handler.AppendFormatted(Markup.Highlight(item.CurrentStreak));
			stringBuilder7.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder8 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(16, 1, stringBuilder2);
			handler.AppendLiteral("Highest Streak: ");
			handler.AppendFormatted(Markup.Highlight(item.HighestStreak));
			stringBuilder8.AppendLine(ref handler);
			ctx.Reply(stringBuilder.ToString());
		}
	}
	public class DataStore
	{
		public record struct PlayerStatistics(ulong SteamId, string LastName, int Kills, int Deaths, int CurrentStreak, int HighestStreak, string LastClanName, int CurrentLevel, int MaxLevel)
		{
			public string FormattedName
			{
				get
				{
					string text = Markup.Highlight(LastName);
					if (Settings.IncludeLevel)
					{
						if (!Settings.UseMaxLevel)
						{
							return text + " (" + Markup.Secondary(CurrentLevel) + ")";
						}
						return text + " (" + Markup.Secondary(MaxLevel) + "*)";
					}
					return text ?? "";
				}
			}

			private static string SafeCSVName(string s)
			{
				return s.Replace(",", "");
			}

			public string ToCsv()
			{
				return $"{SteamId},{SafeCSVName(LastName)},{Kills},{Deaths},{CurrentStreak},{HighestStreak},{SafeCSVName(LastClanName)},{CurrentLevel},{MaxLevel}";
			}

			public static PlayerStatistics Parse(string csv)
			{
				string[] array = csv.Split(',');
				PlayerStatistics result = default(PlayerStatistics);
				result.SteamId = ulong.Parse(array[0]);
				result.LastName = array[1];
				result.Kills = int.Parse(array[2]);
				result.Deaths = int.Parse(array[3]);
				result.CurrentStreak = int.Parse(array[4]);
				result.HighestStreak = int.Parse(array[5]);
				result.LastClanName = ((array.Length > 6) ? array[6] : "");
				result.CurrentLevel = ((array.Length > 7) ? int.Parse(array[7]) : (-1));
				result.MaxLevel = ((array.Length > 8) ? int.Parse(array[8]) : (-1));
				return result;
			}
		}

		public record struct EventData(ulong VictimId, ulong KillerId, float3 Location, long Timestamp, int VictimLevel, int KillerLevel)
		{
			public string ToCsv()
			{
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				return $"{VictimId},{KillerId},{Location.x},{Location.y},{Location.z},{Timestamp},{VictimLevel},{KillerLevel}";
			}

			public static EventData Parse(string csv)
			{
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				string[] array = csv.Split(',');
				EventData result = default(EventData);
				result.VictimId = ulong.Parse(array[0]);
				result.KillerId = ulong.Parse(array[1]);
				result.Location = new float3(float.Parse(array[2]), float.Parse(array[3]), float.Parse(array[4]));
				result.Timestamp = long.Parse(array[5]);
				result.VictimLevel = ((array.Length > 6) ? int.Parse(array[6]) : 0);
				result.KillerLevel = ((array.Length > 7) ? int.Parse(array[7]) : 0);
				return result;
			}

			[CompilerGenerated]
			private readonly bool PrintMembers(StringBuilder builder)
			{
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				builder.Append("VictimId = ");
				builder.Append(VictimId.ToString());
				builder.Append(", KillerId = ");
				builder.Append(KillerId.ToString());
				builder.Append(", Location = ");
				float3 location = Location;
				builder.Append(((object)(float3)(ref location)).ToString());
				builder.Append(", Timestamp = ");
				builder.Append(Timestamp.ToString());
				builder.Append(", VictimLevel = ");
				builder.Append(VictimLevel.ToString());
				builder.Append(", KillerLevel = ");
				builder.Append(KillerLevel.ToString());
				return true;
			}
		}

		public static List<EventData> Events = new List<EventData>();

		public static Dictionary<ulong, PlayerStatistics> PlayerDatas = new Dictionary<ulong, PlayerStatistics>();

		private static readonly Random _rand = new Random();

		private const string EVENTS_FILE_NAME = "events.v1.csv";

		private const string EVENTS_FILE_PATH = "BepInEx/config/Killfeed/events.v1.csv";

		private const string STATS_FILE_NAME = "stats.v1.csv";

		private const string STATS_FILE_PATH = "BepInEx/config/Killfeed/stats.v1.csv";

		private static EventData GenerateTestEvent()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			EventData result = default(EventData);
			result.VictimId = (ulong)_rand.NextInt64();
			result.KillerId = (ulong)_rand.NextInt64();
			result.Location = new float3((float)_rand.NextDouble(), (float)_rand.NextDouble(), (float)_rand.NextDouble());
			result.Timestamp = DateTime.UtcNow.AddMinutes(_rand.Next(-10000, 10000)).Ticks;
			return result;
		}

		public static void GenerateNTestData(int count)
		{
			for (int i = 0; i < count; i++)
			{
				Events.Add(GenerateTestEvent());
			}
		}

		public static void WriteToDisk()
		{
			string directoryName = Path.GetDirectoryName("BepInEx/config/Killfeed/events.v1.csv");
			if (!Directory.Exists(directoryName))
			{
				Directory.CreateDirectory(directoryName);
			}
			using StreamWriter streamWriter = new StreamWriter("BepInEx/config/Killfeed/events.v1.csv", append: false);
			foreach (EventData @event in Events)
			{
				streamWriter.WriteLine(@event.ToCsv());
			}
			using StreamWriter streamWriter2 = new StreamWriter("BepInEx/config/Killfeed/stats.v1.csv", append: false);
			foreach (PlayerStatistics value in PlayerDatas.Values)
			{
				streamWriter2.WriteLine(value.ToCsv());
			}
		}

		public static void LoadFromDisk()
		{
			Events.Clear();
			PlayerDatas.Clear();
			LoadEventData();
			LoadPlayerData();
		}

		private static void LoadEventData()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			if (!File.Exists("BepInEx/config/Killfeed/events.v1.csv"))
			{
				return;
			}
			using StreamReader streamReader = new StreamReader("BepInEx/config/Killfeed/events.v1.csv");
			bool flag = default(bool);
			while (!streamReader.EndOfStream)
			{
				string text = streamReader.ReadLine();
				if (string.IsNullOrWhiteSpace(text))
				{
					continue;
				}
				try
				{
					Events.Add(EventData.Parse(text));
				}
				catch (Exception)
				{
					ManualLogSource logger = Plugin.Logger;
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(30, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to parse event line: \"");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\"");
					}
					logger.LogError(val);
				}
			}
		}

		private static void LoadPlayerData()
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			if (!File.Exists("BepInEx/config/Killfeed/stats.v1.csv"))
			{
				return;
			}
			using StreamReader streamReader = new StreamReader("BepInEx/config/Killfeed/stats.v1.csv");
			bool flag = default(bool);
			while (!streamReader.EndOfStream)
			{
				string text = streamReader.ReadLine();
				if (string.IsNullOrWhiteSpace(text))
				{
					continue;
				}
				try
				{
					PlayerStatistics playerStatistics = PlayerStatistics.Parse(text);
					if (PlayerDatas.TryGetValue(playerStatistics.SteamId, out var value))
					{
						ManualLogSource logger = Plugin.Logger;
						BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(47, 2, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Duplicate player data found, overwriting ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<PlayerStatistics>(value);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" with ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<PlayerStatistics>(playerStatistics);
						}
						logger.LogWarning(val);
					}
					PlayerDatas[playerStatistics.SteamId] = playerStatistics;
				}
				catch (Exception)
				{
					ManualLogSource logger2 = Plugin.Logger;
					BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(31, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed to parse player line: \"");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("\"");
					}
					logger2.LogError(val2);
				}
			}
		}

		public static void RegisterKillEvent(PlayerCharacter victim, PlayerCharacter killer, float3 location, int victimLevel, int killerLevel)
		{
			//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_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			User val = victim.UserEntity.Read<User>();
			User val2 = killer.UserEntity.Read<User>();
			ManualLogSource logger = Plugin.Logger;
			bool flag = default(bool);
			BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(1, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(victimLevel);
				((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(killerLevel);
			}
			logger.LogWarning(val3);
			EventData item = new EventData(val.PlatformId, val2.PlatformId, location, DateTime.UtcNow.Ticks, victimLevel, killerLevel);
			Events.Add(item);
			PlayerStatistics victimUser = UpsertName(val.PlatformId, ((object)(FixedString64Bytes)(ref val.CharacterName)).ToString(), ((object)(FixedString32Bytes)(ref victim.SmartClanName)).ToString(), victimLevel);
			PlayerStatistics killerUser = UpsertName(val2.PlatformId, ((object)(FixedString64Bytes)(ref val2.CharacterName)).ToString(), ((object)(FixedString32Bytes)(ref killer.SmartClanName)).ToString(), killerLevel);
			RecordKill(val2.PlatformId);
			int lostStreakAmount = RecordDeath(val.PlatformId);
			AnnounceKill(victimUser, killerUser, lostStreakAmount);
			WriteToDisk();
			static PlayerStatistics UpsertName(ulong steamId, string name, string clanName, int level)
			{
				if (PlayerDatas.TryGetValue(steamId, out var value))
				{
					value.LastName = name;
					value.LastClanName = clanName;
					value.CurrentLevel = level;
					value.MaxLevel = Math.Max(value.MaxLevel, level);
					PlayerDatas[steamId] = value;
				}
				else
				{
					PlayerDatas[steamId] = new PlayerStatistics
					{
						LastName = name,
						SteamId = steamId,
						LastClanName = clanName,
						CurrentLevel = level,
						MaxLevel = level
					};
				}
				return PlayerDatas[steamId];
			}
		}

		private static void AnnounceKill(PlayerStatistics victimUser, PlayerStatistics killerUser, int lostStreakAmount)
		{
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			if (Settings.AnnounceKills)
			{
				string formattedName = victimUser.FormattedName;
				string formattedName2 = killerUser.FormattedName;
				string text = ((lostStreakAmount > Settings.AnnounceKillstreakLostMinimum) ? $"{formattedName2} ended {formattedName}'s {Markup.Secondary(lostStreakAmount)} kill streak!" : (formattedName2 + " killed " + formattedName + "!"));
				string text2 = killerUser.CurrentStreak switch
				{
					5 => "<size=18>" + formattedName2 + " is on a killing spree!", 
					10 => "<size=19>" + formattedName2 + " is on a rampage!", 
					15 => "<size=20>" + formattedName2 + " is dominating!", 
					20 => "<size=21>" + formattedName2 + " is unstoppable!", 
					25 => "<size=22>" + formattedName2 + " is godlike!", 
					30 => "<size=24>" + formattedName2 + " is WICKED SICK!", 
					_ => null, 
				};
				ServerChatUtils.SendSystemMessageToAllClients(VWorld.Server.EntityManager, Markup.Prefix + text);
				if (!string.IsNullOrEmpty(text2) && Settings.AnnounceKillstreak)
				{
					ServerChatUtils.SendSystemMessageToAllClients(VWorld.Server.EntityManager, Markup.Prefix + text2);
				}
			}
		}

		private static int RecordDeath(ulong platformId)
		{
			int result = 0;
			if (PlayerDatas.TryGetValue(platformId, out var value))
			{
				value.Deaths++;
				result = value.CurrentStreak;
				value.CurrentStreak = 0;
				PlayerDatas[platformId] = value;
			}
			else
			{
				PlayerDatas[platformId] = new PlayerStatistics
				{
					Deaths = 1,
					SteamId = platformId
				};
			}
			return result;
		}

		private static void RecordKill(ulong steamId)
		{
			if (PlayerDatas.TryGetValue(steamId, out var value))
			{
				value.Kills++;
				value.CurrentStreak++;
				value.HighestStreak = math.max(value.HighestStreak, value.CurrentStreak);
				PlayerDatas[steamId] = value;
			}
			else
			{
				PlayerDatas[steamId] = new PlayerStatistics
				{
					Kills = 1,
					CurrentStreak = 1,
					HighestStreak = 1,
					SteamId = steamId
				};
			}
		}
	}
	internal static class Markup
	{
		public const string HighlightColor = "#def";

		public const string SecondaryColor = "#dda";

		public static string Prefix = Format.Bold(Format.Color("[kf] ", "#ed1"));

		public static string Highlight(int i)
		{
			return Highlight(i.ToString());
		}

		public static string Highlight(string s)
		{
			return Format.Color(Format.Bold(s), "#def");
		}

		public static string Secondary(int i)
		{
			return Secondary(i.ToString());
		}

		public static string Secondary(string s)
		{
			return Format.Color(Format.Bold(s), "#dda");
		}
	}
	[BepInPlugin("gg.deca.Killfeed", "Killfeed", "0.3.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[Reloadable]
	public class Plugin : BasePlugin
	{
		private Harmony _harmony;

		public static ManualLogSource Logger;

		public override void Load()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			Logger = ((BasePlugin)this).Log;
			ManualLogSource log = ((BasePlugin)this).Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(27, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Plugin ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("gg.deca.Killfeed");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" version ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("0.3.1");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is loaded!");
			}
			log.LogInfo(val);
			_harmony = new Harmony("gg.deca.Killfeed");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			CommandRegistry.RegisterAll();
			Settings.Initialize(((BasePlugin)this).Config);
			DataStore.LoadFromDisk();
		}

		public override bool Unload()
		{
			CommandRegistry.UnregisterAssembly();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			return true;
		}
	}
	internal class Settings
	{
		internal static bool AnnounceKills { get; private set; }

		internal static int AnnounceKillstreakLostMinimum { get; private set; }

		internal static bool AnnounceKillstreak { get; private set; }

		internal static bool IncludeLevel { get; private set; }

		internal static bool UseMaxLevel { get; private set; }

		internal static void Initialize(ConfigFile config)
		{
			AnnounceKills = config.Bind<bool>("General", "AnnounceKills", true, "Announce kills in chat").Value;
			AnnounceKillstreakLostMinimum = config.Bind<int>("General", "AnnounceKillstreakLostMinimum", 3, "Minimum killstreak count that must be lost to be announced.").Value;
			AnnounceKillstreak = config.Bind<bool>("General", "AnnounceKillstreak", true, "Announce killstreaks in chat").Value;
			IncludeLevel = config.Bind<bool>("General", "IncludeLevel", true, "Include player gear levels in announcements.").Value;
			UseMaxLevel = config.Bind<bool>("General", "UseMaxLevel", false, "Use max gear level instead of current gear level.").Value;
		}
	}
	[HarmonyPatch(typeof(VampireDownedServerEventSystem), "OnUpdate")]
	public static class VampireDownedHook
	{
		public static void Prefix(VampireDownedServerEventSystem __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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)
			EntityQuery _query_1174204813_ = __instance.__query_1174204813_0;
			Enumerator<Entity> enumerator = ((EntityQuery)(ref _query_1174204813_)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)).GetEnumerator();
			while (enumerator.MoveNext())
			{
				ProcessVampireDowned(enumerator.Current);
			}
		}

		private static void ProcessVampireDowned(Entity entity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Expected O, but got Unknown
			//IL_00f9: 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)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: 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_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			Entity entity2 = default(Entity);
			if (!VampireDownedServerEventSystem.TryFindRootOwner(entity, 1, VWorld.Server.EntityManager, ref entity2))
			{
				Plugin.Logger.LogMessage((object)"Couldn't get victim entity");
				return;
			}
			Entity entity3 = default(Entity);
			if (!VampireDownedServerEventSystem.TryFindRootOwner(entity.Read<VampireDownedBuff>().Source, 1, VWorld.Server.EntityManager, ref entity3))
			{
				Plugin.Logger.LogMessage((object)"Couldn't get victim entity");
				return;
			}
			PlayerCharacter val = entity2.Read<PlayerCharacter>();
			ManualLogSource logger = Plugin.Logger;
			bool flag = default(bool);
			BepInExMessageLogInterpolatedStringHandler val2 = new BepInExMessageLogInterpolatedStringHandler(10, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<FixedString64Bytes>(val.Name);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" is victim");
			}
			logger.LogMessage(val2);
			if (entity3.Has<UnitLevel>())
			{
				ManualLogSource logger2 = Plugin.Logger;
				BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(46, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<FixedString64Bytes>(val.Name);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" was killed by a unit. [Not currently tracked]");
				}
				logger2.LogInfo(val3);
				return;
			}
			if (!entity3.Has<PlayerCharacter>())
			{
				ManualLogSource logger3 = Plugin.Logger;
				BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(121, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Killer could not be identified for ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<FixedString64Bytes>(val.Name);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(", if you know how to reproduce this please contact deca on discord or report on github");
				}
				logger3.LogWarning(val4);
				return;
			}
			PlayerCharacter val5 = entity3.Read<PlayerCharacter>();
			if (val5.UserEntity == val.UserEntity)
			{
				ManualLogSource logger4 = Plugin.Logger;
				BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(43, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<FixedString64Bytes>(val.Name);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" killed themselves. [Not currently tracked]");
				}
				logger4.LogInfo(val3);
			}
			else
			{
				LocalToWorld val6 = entity2.Read<LocalToWorld>();
				Equipment value;
				int victimLevel = (entity2.Has<Equipment>(out value) ? ((int)Math.Round(((Equipment)(ref value)).GetFullLevel())) : (-1));
				Equipment value2;
				int killerLevel = (entity3.Has<Equipment>(out value2) ? ((int)Math.Round(((Equipment)(ref value2)).GetFullLevel())) : (-1));
				DataStore.RegisterKillEvent(val, val5, ((LocalToWorld)(ref val6)).Position, victimLevel, killerLevel);
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "gg.deca.Killfeed";

		public const string PLUGIN_NAME = "Killfeed";

		public const string PLUGIN_VERSION = "0.3.1";
	}
}