Decompiled source of CrimsonKiller v1.1.1

CrimsonKiller.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CrimsonKiller.Services;
using CrimsonKiller.Structs;
using CrimsonKiller.Utility;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using ProjectM;
using ProjectM.Network;
using Stunlock.Core;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
using VAMP;
using VAMP.Attributes;
using VAMP.Data;
using VAMP.Models;
using VAMP.Services;
using VAMP.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("CrimsonKiller")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Fully customizable kill feeds!")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1+1.Branch.master.Sha.81cb0575c6ce79e0126453d11f07382663ebe944.81cb0575c6ce79e0126453d11f07382663ebe944")]
[assembly: AssemblyProduct("CrimsonKiller")]
[assembly: AssemblyTitle("CrimsonKiller")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.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;
		}
	}
}
public class KillStreak
{
	public Player player;

	public int streak;

	public int multi;

	public DateTime lastKill;

	public KillStreak(Player player, User killed, int streak, int multi)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		this.player = player;
		lastKill = DateTime.Now;
		AddKill(killed);
	}

	public void AddKill(User killed)
	{
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		TimeSpan timeSpan = DateTime.Now - lastKill;
		if (Settings.TimeForMultiKillReset.Value > 0 && timeSpan.TotalSeconds > (double)Settings.TimeForMultiKillReset.Value)
		{
			multi = 0;
		}
		if (Settings.TimeForKillStreakReset.Value > 0 && timeSpan.TotalSeconds > (double)Settings.TimeForKillStreakReset.Value)
		{
			streak = 0;
		}
		streak++;
		multi++;
		if (Settings.ToggleKillStreaks.Value)
		{
			int currentStreak = streak;
			if (Database.KillStreaks.Any((KillToMessagePair k) => k.Key == currentStreak))
			{
				string value = Database.KillStreaks.First((KillToMessagePair k) => k.Key == currentStreak).Value;
				value = Broadcast.ProcessUser("killer", value, EntityUtil.Read<User>(player.User), player);
				value = Broadcast.ProcessUser("died", value, killed, PlayerService.PlayerFromUser(killed));
				ChatUtil.SystemSendAll(value);
			}
		}
		if (Settings.ToggleMultiKills.Value)
		{
			int currentMulti = multi;
			if (Database.MultiKills.Any((KillToMessagePair m) => m.Key == currentMulti))
			{
				string value2 = Database.MultiKills.First((KillToMessagePair m) => m.Key == currentMulti).Value;
				value2 = Broadcast.ProcessUser("killer", value2, EntityUtil.Read<User>(player.User), player);
				value2 = Broadcast.ProcessUser("died", value2, killed, PlayerService.PlayerFromUser(killed));
				ChatUtil.SystemSendAll(value2);
			}
		}
		lastKill = DateTime.Now;
	}
}
namespace CrimsonKiller
{
	[BepInPlugin("CrimsonKiller", "CrimsonKiller", "1.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BasePlugin
	{
		private Harmony _harmony;

		public static Plugin Instance { get; private set; }

		public static Harmony Harmony => Instance._harmony;

		public static ManualLogSource LogInstance => ((BasePlugin)Instance).Log;

		public static Settings Settings { get; private set; }

		public static string ConfigFiles => Path.Combine(Paths.ConfigPath, "CrimsonKiller");

		public Database Database { get; private set; }

		public override void Load()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			Instance = this;
			Settings = default(Settings);
			Settings.InitConfig();
			_harmony = new Harmony("CrimsonKiller");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			Events.OnCoreLoaded = (Action)Delegate.Combine(Events.OnCoreLoaded, new Action(Loaded));
		}

		public void Loaded()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			Database = new Database();
			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>("CrimsonKiller");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" version ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.1.1");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is loaded!");
			}
			log.LogInfo(val);
		}

		public override bool Unload()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			return true;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "CrimsonKiller";

		public const string PLUGIN_NAME = "CrimsonKiller";

		public const string PLUGIN_VERSION = "1.1.1";
	}
}
namespace CrimsonKiller.Utility
{
	public static class RaidTime
	{
		private static readonly List<DayOfWeek> WeekendDays = new List<DayOfWeek>(2)
		{
			DayOfWeek.Saturday,
			DayOfWeek.Sunday
		};

		private static ServerGameSettings serverGameSettings;

		public static bool IsRaidTimeNow()
		{
			return IsRaidTime(DateTime.Now);
		}

		public static bool IsRaidTime(DateTime dateTime)
		{
			//IL_0020: 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_0038: Expected I4, but got Unknown
			if (serverGameSettings == null)
			{
				serverGameSettings = Core.Server.GetExistingSystemManaged<ServerGameSettingsSystem>()._Settings;
			}
			CastleDamageMode castleDamageMode = serverGameSettings.CastleDamageMode;
			switch ((int)castleDamageMode)
			{
			case 0:
				return false;
			case 1:
				return true;
			case 2:
			{
				PlayerInteractionSettings playerInteractionSettings = serverGameSettings.PlayerInteractionSettings;
				StartEndTimeData window = (IsWeekend(dateTime) ? playerInteractionSettings.VSCastleWeekendTime : playerInteractionSettings.VSCastleWeekdayTime);
				return IsInWindow(dateTime, window);
			}
			default:
				return false;
			}
		}

		private static bool IsWeekend(DateTime dateTime)
		{
			return WeekendDays.Contains(dateTime.DayOfWeek);
		}

		private static bool IsInWindow(DateTime dateTime, StartEndTimeData window)
		{
			TimeSpan timeOfDay = dateTime.TimeOfDay;
			TimeSpan timeSpan = new TimeSpan(window.StartHour, window.StartMinute, 0);
			TimeSpan timeSpan2 = new TimeSpan(window.EndHour, window.EndMinute, 0);
			if (timeOfDay >= timeSpan)
			{
				return timeOfDay < timeSpan2;
			}
			return false;
		}
	}
}
namespace CrimsonKiller.Structs
{
	public class Database
	{
		private static string SlayerOldPath = Path.Combine(Plugin.ConfigFiles, "vblood_firsts.json");

		public static string SlayerFile = Path.Combine(FilePaths.WipeData, "ckiller_vblood_firsts.json");

		[FileReload("LoadVBloods")]
		public static string ToggleVBloods = Path.Combine(Plugin.ConfigFiles, "toggle_vbloods.json");

		[FileReload("LoadMessages")]
		public static string MessagesFile = Path.Combine(Plugin.ConfigFiles, "messages.json");

		[FileReload("LoadKillStreaks")]
		public static string KillStreakFile = Path.Combine(Plugin.ConfigFiles, "kill_streaks.json");

		[FileReload("LoadMultiKills")]
		public static string MultiKillFile = Path.Combine(Plugin.ConfigFiles, "multi_kills.json");

		public static Dictionary<ulong, ulong> SlayerList;

		public static Dictionary<int, bool> VBloodToggles;

		public static Dictionary<string, string> Messages;

		public static List<KillToMessagePair> KillStreaks;

		public static List<KillToMessagePair> MultiKills;

		public static List<KillStreak> CurrentStreaks = new List<KillStreak>();

		public Database()
		{
			LoadDatabase();
		}

		private static void LoadDatabase()
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			if (!Directory.Exists(Plugin.ConfigFiles))
			{
				Directory.CreateDirectory(Plugin.ConfigFiles);
			}
			if (Settings.ToggleFirstSlayer.Value)
			{
				if (File.Exists(SlayerOldPath) && !File.Exists(SlayerFile))
				{
					File.Move(SlayerOldPath, SlayerFile);
					ManualLogSource logInstance = Plugin.LogInstance;
					bool flag = default(bool);
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(36, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Moved V Blood Firsts file from ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SlayerOldPath);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" to ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SlayerFile);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
					}
					logInstance.LogInfo(val);
				}
				try
				{
					if (File.Exists(SlayerFile))
					{
						SlayerList = JsonSerializer.Deserialize<Dictionary<ulong, ulong>>(File.ReadAllText(SlayerFile, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)), JsonUtil.PrettyJsonOptions);
					}
					else
					{
						SlayerList = new Dictionary<ulong, ulong>();
						SaveDatabase();
					}
				}
				catch
				{
					SlayerList = new Dictionary<ulong, ulong>();
				}
			}
			LoadVBloods();
			LoadMessages();
			if (Settings.ToggleKillStreaks.Value)
			{
				LoadKillStreaks();
			}
			if (Settings.ToggleMultiKills.Value)
			{
				LoadMultiKills();
			}
		}

		private static void LoadKillStreaks()
		{
			if (File.Exists(KillStreakFile))
			{
				KillStreaks = JsonSerializer.Deserialize<List<KillToMessagePair>>(File.ReadAllText(KillStreakFile));
				return;
			}
			KillStreaks = new List<KillToMessagePair>(6)
			{
				new KillToMessagePair(3, "{killer.name} is on a Killing Spree!"),
				new KillToMessagePair(4, "{killer.name} is Dominating!"),
				new KillToMessagePair(5, "{killer.name} is on a Rampage!"),
				new KillToMessagePair(6, "{killer.name} is Unstoppable!"),
				new KillToMessagePair(10, "{killer.name} is Godlike!"),
				new KillToMessagePair(15, "{killer.name} is committing a Massacre!")
			};
			string contents = JsonSerializer.Serialize(KillStreaks, JsonUtil.PrettyJsonOptions);
			File.WriteAllText(KillStreakFile, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
		}

		private static void LoadVBloods()
		{
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Expected O, but got Unknown
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				if (File.Exists(ToggleVBloods))
				{
					Dictionary<int, bool> dictionary = JsonSerializer.Deserialize<Dictionary<int, bool>>(File.ReadAllText(ToggleVBloods, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)), new JsonSerializerOptions(JsonUtil.PrettyJsonOptions)
					{
						ReadCommentHandling = JsonCommentHandling.Skip
					});
					if (dictionary != null)
					{
						VBloodToggles = dictionary;
						ManualLogSource logInstance = Plugin.LogInstance;
						BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(61, 2, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loaded toggle_vbloods.json with ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(VBloodToggles.Count((KeyValuePair<int, bool> x) => x.Value));
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" toggled on and ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(VBloodToggles.Count((KeyValuePair<int, bool> x) => !x.Value));
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" toggled off.");
						}
						logInstance.LogInfo(val);
					}
					else
					{
						Plugin.LogInstance.LogWarning((object)"Deserialization of toggle_vbloods.json returned null. Creating default toggles.");
						VBloodToggles = VBloods.PrefabToNames.ToDictionary<KeyValuePair<PrefabGUID, (string, string)>, int, bool>(delegate(KeyValuePair<PrefabGUID, (string Long, string Short)> x)
						{
							//IL_0002: 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)
							PrefabGUID key3 = x.Key;
							return ((PrefabGUID)(ref key3)).GuidHash;
						}, (KeyValuePair<PrefabGUID, (string Long, string Short)> _) => true);
						SaveDatabase();
					}
				}
				else
				{
					Plugin.LogInstance.LogInfo((object)"No toggle_vbloods.json file found, creating a new one with all VBloods toggled on.");
					VBloodToggles = VBloods.PrefabToNames.ToDictionary<KeyValuePair<PrefabGUID, (string, string)>, int, bool>(delegate(KeyValuePair<PrefabGUID, (string Long, string Short)> x)
					{
						//IL_0002: 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)
						PrefabGUID key2 = x.Key;
						return ((PrefabGUID)(ref key2)).GuidHash;
					}, (KeyValuePair<PrefabGUID, (string Long, string Short)> _) => true);
					SaveDatabase();
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logInstance2 = Plugin.LogInstance;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(35, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error loading toggle_vbloods.json: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				logInstance2.LogInfo(val);
				ManualLogSource logInstance3 = Plugin.LogInstance;
				val = new BepInExInfoLogInterpolatedStringHandler(12, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error type: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.GetType().Name);
				}
				logInstance3.LogInfo(val);
				ManualLogSource logInstance4 = Plugin.LogInstance;
				val = new BepInExInfoLogInterpolatedStringHandler(13, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Stack trace: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.StackTrace);
				}
				logInstance4.LogInfo(val);
				Plugin.LogInstance.LogInfo((object)"Resetting to default state with all VBloods toggled on.");
				VBloodToggles = VBloods.PrefabToNames.ToDictionary<KeyValuePair<PrefabGUID, (string, string)>, int, bool>(delegate(KeyValuePair<PrefabGUID, (string Long, string Short)> x)
				{
					//IL_0002: 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)
					PrefabGUID key = x.Key;
					return ((PrefabGUID)(ref key)).GuidHash;
				}, (KeyValuePair<PrefabGUID, (string Long, string Short)> _) => true);
			}
		}

		private static void LoadMessages()
		{
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Expected O, but got Unknown
			Dictionary<string, string> dictionary = new Dictionary<string, string>
			{
				{ "Downed", "{killer.clanTag} {killer.name} ({killer.currentLv}) has downed {died.clanTag} {died.name} ({died.currentLv})" },
				{ "Killed", "{killer.clanTag} {killer.name} ({killer.currentLv}) has killed {died.clanTag} {died.name} ({died.currentLv})" },
				{ "KillStolen", "{steal.clanTag} {steal.name} ({steal.currentLv}) stole the kill on {died.clanTag} {died.name} ({died.currentLv}) from {killer.clanTag} {killer.name}" },
				{ "GriefDowned", "{killer.clanTag} {killer.name} ({killer.currentLv}/{killer.recordLv}) has downed {died.clanTag} {died.name} ({died.currentLv}/{died.recordLv})" },
				{ "GriefKilled", "{killer.clanTag} {killer.name} ({killer.currentLv}/{killer.recordLv}) has killed {died.clanTag} {died.name} ({died.currentLv}/{died.recordLv})" },
				{ "GriefKillStolen", "{steal.clanTag} {steal.name} ({steal.currentLv}/{steal.recordLv}) stole the kill on {died.clanTag} {died.name} ({died.currentLv}/{died.recordLv}) from {killer.clanTag} {killer.name} ({killer.currentLv}/{killer.recordLv})" },
				{ "OfflineDowned", "{killer.clanTag} {killer.name} ({killer.currentLv}) downed {died.clanTag} {died.name} ({died.currentLv}) while they slumbered" },
				{ "OfflineKilled", "{killer.clanTag} {killer.name} ({killer.currentLv}) killed {died.clanTag} {died.name} ({died.currentLv}) while they slumbered" },
				{ "OfflineKillStolen", "{steal.clanTag} {steal.name} ({steal.currentLv}) stole the kill on {died.clanTag} {died.name} ({died.currentLv}) from {killer.clanTag} {killer.name}" },
				{ "FirstVBloodKill", "{killer.name} ({killer.currentLv}) was the first to slay {vblood.long}!" },
				{ "VBloodKill", "{killer.name} ({killer.currentLv}) has slain {vblood.short}!" },
				{ "KillStreakEnded", "{died.name}'s kill streak ended!" }
			};
			bool flag = false;
			if (File.Exists(MessagesFile))
			{
				bool flag2 = default(bool);
				try
				{
					Messages = JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText(MessagesFile));
					foreach (KeyValuePair<string, string> item in dictionary)
					{
						if (!Messages.ContainsKey(item.Key))
						{
							Messages[item.Key] = item.Value;
							flag = true;
							ManualLogSource logInstance = Plugin.LogInstance;
							BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(27, 1, ref flag2);
							if (flag2)
							{
								((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Added missing message key: ");
								((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(item.Key);
							}
							logInstance.LogInfo(val);
						}
					}
				}
				catch (Exception ex)
				{
					ManualLogSource logInstance2 = Plugin.LogInstance;
					BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(55, 1, ref flag2);
					if (flag2)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed to load messages.json: ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(". Using default messages.");
					}
					logInstance2.LogWarning(val2);
					Messages = dictionary;
					flag = true;
				}
			}
			else
			{
				Plugin.LogInstance.LogInfo((object)"No messages.json file found, creating a new one with default messages.");
				Messages = dictionary;
				flag = true;
			}
			if (flag)
			{
				string contents = JsonSerializer.Serialize(Messages, JsonUtil.PrettyJsonOptions);
				File.WriteAllText(MessagesFile, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
			}
		}

		private static void LoadMultiKills()
		{
			if (File.Exists(MultiKillFile))
			{
				MultiKills = JsonSerializer.Deserialize<List<KillToMessagePair>>(File.ReadAllText(MultiKillFile));
				return;
			}
			MultiKills = new List<KillToMessagePair>(5)
			{
				new KillToMessagePair(2, "{killer.name} got a Double Kill!"),
				new KillToMessagePair(3, "{killer.name} got a Multi Kill!"),
				new KillToMessagePair(4, "{killer.name} got a Mega Kill!"),
				new KillToMessagePair(5, "{killer.name} got an Ultra Kill!"),
				new KillToMessagePair(6, "{killer.name} got a Monster Kill!")
			};
			string contents = JsonSerializer.Serialize(MultiKills, JsonUtil.PrettyJsonOptions);
			File.WriteAllText(MultiKillFile, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
		}

		public static void SaveDatabase()
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if (Settings.ToggleFirstSlayer.Value)
			{
				string contents = JsonSerializer.Serialize(SlayerList, JsonUtil.PrettyJsonOptions);
				File.WriteAllText(SlayerFile, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
			}
			string s = JsonSerializer.Serialize(VBloodToggles, JsonUtil.PrettyJsonOptions);
			StringBuilder stringBuilder = new StringBuilder();
			using (StringReader stringReader = new StringReader(s))
			{
				Regex regex = new Regex("^\\s*\"(-?\\d+)\"\\s*:\\s*(true|false)");
				string text;
				while ((text = stringReader.ReadLine()) != null)
				{
					Match match = regex.Match(text);
					if (match.Success)
					{
						int num = int.Parse(match.Groups[1].Value);
						string text2 = "Unknown";
						foreach (KeyValuePair<PrefabGUID, (string, string)> prefabToName in VBloods.PrefabToNames)
						{
							PrefabGUID key = prefabToName.Key;
							if (((PrefabGUID)(ref key)).GuidHash == num)
							{
								text2 = prefabToName.Value.Item1;
								break;
							}
						}
						text = text.TrimEnd() + " /* " + text2 + " */";
					}
					stringBuilder.AppendLine(text);
				}
			}
			File.WriteAllText(ToggleVBloods, stringBuilder.ToString(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
		}
	}
	public struct KillToMessagePair
	{
		public int Key { get; set; }

		public string Value { get; set; }

		public KillToMessagePair(int key, string value)
		{
			Key = key;
			Value = value;
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public readonly struct Settings
	{
		private static readonly List<string> OrderedSections = new List<string> { "Config", "Messages", "Options", "Parameters", "StreaksAndMulti" };

		public static ConfigEntry<bool> ToggleMod { get; private set; }

		public static ConfigEntry<bool> ToggleDowned { get; private set; }

		public static ConfigEntry<bool> ToggleKill { get; private set; }

		public static ConfigEntry<bool> ToggleKillSteal { get; private set; }

		public static ConfigEntry<bool> ReplaceGriefDowned { get; private set; }

		public static ConfigEntry<bool> ReplaceGriefKill { get; private set; }

		public static ConfigEntry<bool> ReplaceGriefKillSteal { get; private set; }

		public static ConfigEntry<bool> ReplaceOfflineDowned { get; private set; }

		public static ConfigEntry<bool> ReplaceOfflineKill { get; private set; }

		public static ConfigEntry<bool> ReplaceOfflineKillSteal { get; private set; }

		public static ConfigEntry<bool> ToggleSuicide { get; private set; }

		public static ConfigEntry<bool> ToggleFirstSlayer { get; private set; }

		public static ConfigEntry<bool> ToggleSlayer { get; private set; }

		public static ConfigEntry<bool> RaidsHideRegion { get; private set; }

		public static ConfigEntry<int> DelayPVPMessages { get; private set; }

		public static ConfigEntry<int> DelaySlayerMessages { get; private set; }

		public static ConfigEntry<int> GriefDifference { get; private set; }

		public static ConfigEntry<int> GriefDifferenceFromMax { get; private set; }

		public static ConfigEntry<bool> ToggleKillStreaks { get; private set; }

		public static ConfigEntry<bool> ToggleMultiKills { get; private set; }

		public static ConfigEntry<int> TimeForKillStreakReset { get; private set; }

		public static ConfigEntry<int> TimeForMultiKillReset { get; private set; }

		public static ConfigEntry<bool> ToggleKillStreakEndedMessage { get; private set; }

		public static ConfigEntry<string> PlayerNames { get; private set; }

		public static ConfigEntry<string> PlayerCurrentLevel { get; private set; }

		public static ConfigEntry<string> PlayerRecordLevel { get; private set; }

		public static ConfigEntry<string> ClanNames { get; private set; }

		public static ConfigEntry<string> ClanTags { get; private set; }

		public static ConfigEntry<string> VBloodsShort { get; private set; }

		public static ConfigEntry<string> VBloodsLong { get; private set; }

		public static ConfigEntry<string> RegionLong { get; private set; }

		public static ConfigEntry<string> RegionShort { get; private set; }

		public static void InitConfig()
		{
			ToggleMod = InitConfigEntry(OrderedSections[0], "Toggle", defaultValue: true, "If true the mod will be usable; otherwise it will be disabled.");
			ToggleDowned = InitConfigEntry(OrderedSections[0], "ToggleDowned", defaultValue: true, "If true, the downed message will be sent.");
			ToggleKill = InitConfigEntry(OrderedSections[0], "ToggleKilled", defaultValue: true, "If true, the killed message will be sent.");
			ToggleKillSteal = InitConfigEntry(OrderedSections[0], "ToggleKillStolen", defaultValue: true, "If true, the kill stolen message will be sent.");
			ReplaceGriefDowned = InitConfigEntry(OrderedSections[0], "ReplaceGriefDowned", defaultValue: true, "If true, the grief downed message will be sent. Replaces the normal downed message if both messages are enabled and a player is downed by grief.");
			ReplaceGriefKill = InitConfigEntry(OrderedSections[0], "ReplaceGriefKill", defaultValue: true, "If true, the grief killed message will be sent. Replaces the normal killed message if both messages are enabled and a player is killed by grief.");
			ReplaceGriefKillSteal = InitConfigEntry(OrderedSections[0], "ReplaceGriefKillSteal", defaultValue: true, "If true, the grief kill stolen message will be sent. Replaces the normal kill stolen message if both messages are enabled and a kill of an offline player is stolen by grief.");
			ReplaceOfflineDowned = InitConfigEntry(OrderedSections[0], "ToggleOfflineDowned", defaultValue: true, "If true, the offline downed message will be sent. Replaces the normal downed message if both messages are enabled and an offline player is downed.");
			ReplaceOfflineKill = InitConfigEntry(OrderedSections[0], "ToggleOfflineKill", defaultValue: true, "If true, the offline killed message will be sent. Replaces the normal killed message if both messages are enabled and an offline player is killed.");
			ReplaceOfflineKillSteal = InitConfigEntry(OrderedSections[0], "ToggleOfflineKillSteal", defaultValue: true, "If true, the offline kill stolen message will be sent. Replaces the normal kill stolen message if both messages are enabled and a kill of an offline player is stolen");
			ToggleFirstSlayer = InitConfigEntry(OrderedSections[0], "ToggleFirstVBloodKill", defaultValue: true, "If true, the first V Blood kill message will be sent.");
			ToggleSlayer = InitConfigEntry(OrderedSections[0], "ToggleVBloodKill", defaultValue: true, "If true, the V Blood kill message will be sent.");
			RaidsHideRegion = InitConfigEntry(OrderedSections[2], "RaidsHideRegion", defaultValue: true, "If true, the region will be hidden from messages during Raid Time.");
			DelayPVPMessages = InitConfigEntry(OrderedSections[2], "DelayPvPMessages", 0, "The amount of seconds to delay PvP messages by. Set to 0 to disable.");
			DelaySlayerMessages = InitConfigEntry(OrderedSections[2], "DelayVBloodMessages", 0, "The amount of seconds to delay V Blood kill messages by. Set to 0 to disable.");
			GriefDifference = InitConfigEntry(OrderedSections[2], "GriefDifference", 10, "The level difference required between the griefer’s record level and the victim’s level to trigger a grief message.");
			GriefDifferenceFromMax = InitConfigEntry(OrderedSections[2], "GriefDifferenceFromMax", 5, "The level difference required between the griefer’s record level of 91 (max level) and the victim’s level to trigger a grief message.");
			PlayerNames = InitConfigEntry(OrderedSections[3], "PlayerNames", "<color=#def>{prefix.name}</color>", "Formatting for {player.name}, {killer.name}, {steal.name}. Note: prefix will be replaced by the target player type.");
			PlayerCurrentLevel = InitConfigEntry(OrderedSections[3], "PlayerCurrentLevel", "<color=#fcffdd>{prefix.currentLv}</color>", "Formatting for {player.currentLv}, {killer.currentLv}, {steal.currentLv}. Note: prefix will be replaced by the target player type.");
			PlayerRecordLevel = InitConfigEntry(OrderedSections[3], "PlayerRecordLevel", "<color=#e84343>{prefix.recordLv}</color>", "Formatting for {player.recordLv}, {killer.recordLv}, {steal.recordLv}. Note: prefix will be replaced by the target player type.");
			ClanNames = InitConfigEntry(OrderedSections[3], "ClanNames", "<color=#f5ddff>{prefix.clanName}</color>", "Formatting for {player.clanName}, {killer.clanName}, {steal.clanName}. Note: prefix will be replaced by the target player type.");
			ClanTags = InitConfigEntry(OrderedSections[3], "ClanTags", "<color=#f5ddff>{prefix.clanTag}</color>", "Formatting for {player.clanTag}, {killer.clanTag}, {steal.clanTag}. Note: Clan tags include brackets by default.");
			VBloodsShort = InitConfigEntry(OrderedSections[3], "VBloodsShort", "<b>{vblood.short}</b>", "Formatting for {vblood.short}. Note: V Blood names can be changed in BepInEx/configs/VAMP/Names_VBloods.json.");
			VBloodsLong = InitConfigEntry(OrderedSections[3], "VBloodsLong", "<b>{vblood.long}</b>", "Formatting for {vblood.long}, {vblood}. Note: V Blood names can be changed in BepInEx/configs/VAMP/Names_VBloods.json.");
			RegionLong = InitConfigEntry(OrderedSections[3], "RegionLong", " in <i>{region.long}</i>", "Formatting for {region.long}, {region}. Note: Region names can be changed in BepInEx/configs/VAMP/Names_Regions.json.");
			RegionShort = InitConfigEntry(OrderedSections[3], "RegionShort", "[<i>{region.short}</i>]", "Formatting for {region.short}. Note: Region names can be changed in BepInEx/configs/VAMP/Names_Regions.json.");
			ToggleKillStreaks = InitConfigEntry(OrderedSections[4], "ToggleKillStreaks", defaultValue: true, "If true, the kill streak messages will be sent.");
			ToggleMultiKills = InitConfigEntry(OrderedSections[4], "ToggleMultiKills", defaultValue: false, "If true, the multi kill messages will be sent.");
			TimeForKillStreakReset = InitConfigEntry(OrderedSections[4], "TimeForKillStreakReset", -1, "The time in seconds for the kill streak to reset. Set to -1 to disable.");
			TimeForMultiKillReset = InitConfigEntry(OrderedSections[4], "TimeForMultiKillReset", 180, "The time in seconds for the multi kill streak to reset. Set to -1 to disable.");
			ToggleKillStreakEndedMessage = InitConfigEntry(OrderedSections[4], "ToggleKillStreakEndedMessage", defaultValue: true, "If true, the kill streak ended messages will be sent.");
			ReorderConfigSections();
		}

		private static ConfigEntry<T> InitConfigEntry<T>(string section, string key, T defaultValue, string description)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<T> val = ((BasePlugin)Plugin.Instance).Config.Bind<T>(section, key, defaultValue, description);
			string text = Path.Combine(Paths.ConfigPath, "CrimsonKiller.cfg");
			ConfigEntry<T> val2 = default(ConfigEntry<T>);
			if (File.Exists(text) && new ConfigFile(text, true).TryGetEntry<T>(section, key, ref val2))
			{
				val.Value = val2.Value;
			}
			return val;
		}

		private static void ReorderConfigSections()
		{
			string path = Path.Combine(Paths.ConfigPath, "CrimsonKiller.cfg");
			if (!File.Exists(path))
			{
				return;
			}
			List<string> list = File.ReadAllLines(path).ToList();
			Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
			string text = "";
			foreach (string item in list)
			{
				if (item.StartsWith("["))
				{
					text = item.Trim('[', ']');
					dictionary[text] = new List<string> { item };
				}
				else if (!string.IsNullOrWhiteSpace(text))
				{
					dictionary[text].Add(item);
				}
			}
			using StreamWriter streamWriter = new StreamWriter(path, append: false);
			foreach (string orderedSection in OrderedSections)
			{
				if (!dictionary.ContainsKey(orderedSection))
				{
					continue;
				}
				foreach (string item2 in dictionary[orderedSection])
				{
					streamWriter.WriteLine(item2);
				}
				streamWriter.WriteLine();
			}
		}
	}
}
namespace CrimsonKiller.Services
{
	public static class Broadcast
	{
		private static bool IsGriefKill(DeathTrack death, ulong who)
		{
			Player val = default(Player);
			if (!PlayerService.TryFindBySteam(who, ref val))
			{
				return false;
			}
			Player val2 = default(Player);
			if (!PlayerService.TryFindBySteam(death.victim_id, ref val2))
			{
				return false;
			}
			if (val.RecordLevel == 91)
			{
				if (val.RecordLevel - val2.Level > Settings.GriefDifferenceFromMax.Value)
				{
					return true;
				}
			}
			else if (val.RecordLevel - val2.Level > Settings.GriefDifference.Value)
			{
				return true;
			}
			return false;
		}

		public static void Message(DeathType deathType, DeathTrack death)
		{
			//IL_045a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0470: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Expected O, but got Unknown
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0518: Unknown result type (might be due to invalid IL or missing references)
			//IL_051d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0522: Unknown result type (might be due to invalid IL or missing references)
			//IL_0524: Unknown result type (might be due to invalid IL or missing references)
			//IL_0529: Unknown result type (might be due to invalid IL or missing references)
			//IL_052e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0536: Unknown result type (might be due to invalid IL or missing references)
			//IL_0544: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d6: Expected O, but got Unknown
			//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0401: Unknown result type (might be due to invalid IL or missing references)
			//IL_0507: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Expected O, but got Unknown
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Expected O, but got Unknown
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			string text = "";
			bool flag = default(bool);
			switch (deathType)
			{
			case DeathType.Downed:
				if (Settings.ReplaceOfflineDowned.Value && death.offlined)
				{
					if (!Database.Messages.ContainsKey("OfflineDowned"))
					{
						return;
					}
					text = Database.Messages["OfflineDowned"];
				}
				else if (Settings.ReplaceGriefDowned.Value && IsGriefKill(death, death.killer_id))
				{
					if (!Database.Messages.ContainsKey("GriefDowned"))
					{
						return;
					}
					text = Database.Messages["GriefDowned"];
				}
				else
				{
					if (!Settings.ToggleDowned.Value || !Database.Messages.ContainsKey("Downed"))
					{
						return;
					}
					text = Database.Messages["Downed"];
				}
				break;
			case DeathType.Killed:
				if (Settings.ReplaceOfflineKill.Value && death.offlined)
				{
					if (!Database.Messages.ContainsKey("OfflineKilled"))
					{
						return;
					}
					text = Database.Messages["OfflineKilled"];
				}
				else if (Settings.ReplaceGriefKill.Value && IsGriefKill(death, death.killer_id))
				{
					if (!Database.Messages.ContainsKey("GriefKilled"))
					{
						return;
					}
					text = Database.Messages["GriefKilled"];
				}
				else
				{
					if (!Settings.ToggleKill.Value || !Database.Messages.ContainsKey("Killed"))
					{
						return;
					}
					text = Database.Messages["Killed"];
				}
				break;
			case DeathType.KillStolen:
			{
				if (Settings.ReplaceOfflineKillSteal.Value && death.offlined)
				{
					if (!Database.Messages.ContainsKey("OfflineKillStolen"))
					{
						return;
					}
					text = Database.Messages["OfflineKillStolen"];
				}
				else if (Settings.ReplaceGriefKillSteal.Value && IsGriefKill(death, death.killer_id))
				{
					if (!Database.Messages.ContainsKey("GriefKillStolen"))
					{
						return;
					}
					text = Database.Messages["GriefKillStolen"];
				}
				else
				{
					if (!Settings.ToggleKillSteal.Value || !Database.Messages.ContainsKey("KillStolen"))
					{
						return;
					}
					text = Database.Messages["KillStolen"];
				}
				if (string.IsNullOrEmpty(text))
				{
					Message(DeathType.Killed, death);
					break;
				}
				Player val2 = default(Player);
				if (!PlayerService.TryFindBySteam(death.steal_id, ref val2))
				{
					return;
				}
				if (EntityUtil.Has<User>(val2.User))
				{
					User user = EntityUtil.Read<User>(val2.User);
					text = ProcessUser("steal", text, user, val2);
					break;
				}
				BepInExInfoLogInterpolatedStringHandler val3;
				if (!EntityUtil.Has<User>(val2.User))
				{
					ManualLogSource logInstance = Plugin.LogInstance;
					val3 = new BepInExInfoLogInterpolatedStringHandler(106, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("WARNING: Steal data for ");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<ulong>(death.steal_id);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" does not have a user component! Send VAMPDump/MissingStealKiller.txt to SkyTech6.");
					}
					logInstance.LogInfo(val3);
					return;
				}
				ManualLogSource logInstance2 = Plugin.LogInstance;
				val3 = new BepInExInfoLogInterpolatedStringHandler(106, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("WARNING: Steal data for ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<ulong>(death.steal_id);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" does not have a user component! Send VAMPDump/MissingStealKiller.txt to SkyTech6.");
				}
				logInstance2.LogInfo(val3);
				DevUtil.Dump(val2.User, "MissingStealKiller.txt");
				break;
			}
			case DeathType.VBlood:
			{
				if (Settings.ToggleFirstSlayer.Value && !Database.SlayerList.ContainsKey(death.victim_id))
				{
					if (!Database.Messages.ContainsKey("FirstVBloodKill"))
					{
						return;
					}
					text = Database.Messages["FirstVBloodKill"];
					Database.SlayerList.Add(death.victim_id, death.killer_id);
					Database.SaveDatabase();
				}
				else
				{
					if (!Settings.ToggleSlayer.Value || !Database.Messages.ContainsKey("VBloodKill"))
					{
						return;
					}
					text = Database.Messages["VBloodKill"];
				}
				if (Database.VBloodToggles != null && Database.VBloodToggles.TryGetValue((int)death.victim_id, out var value) && !value)
				{
					return;
				}
				text = ProcessVBlood(text, new PrefabGUID((int)death.victim_id));
				Player val = default(Player);
				if (PlayerService.TryFindBySteam(death.killer_id, ref val))
				{
					text = ProcessUser("killer", text, EntityUtil.Read<User>(val.User), val);
					if (Settings.DelaySlayerMessages.Value > 0)
					{
						Core.StartCoroutine(DelayBroadcast(text, Settings.DelaySlayerMessages.Value));
					}
					else
					{
						ChatUtil.SystemSendAll(text);
					}
				}
				return;
			}
			}
			Player val4 = default(Player);
			Player val5 = default(Player);
			if (!PlayerService.TryFindBySteam(death.victim_id, ref val4) || !PlayerService.TryFindBySteam(death.killer_id, ref val5))
			{
				return;
			}
			if (!EntityUtil.Has<User>(val4.User))
			{
				ManualLogSource logInstance3 = Plugin.LogInstance;
				BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(102, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("WARNING: Victim data for ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<ulong>(death.victim_id);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" does not have a user component! Send VAMPDump/MissingVictim.txt to SkyTech6.");
				}
				logInstance3.LogInfo(val3);
				DevUtil.Dump(val4.User, "MissingVictim.txt");
				return;
			}
			if (!EntityUtil.Has<User>(val5.User))
			{
				ManualLogSource logInstance4 = Plugin.LogInstance;
				BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(102, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("WARNING: Killer data for ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<ulong>(death.killer_id);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" does not have a user component! Send VAMPDump/MissingKiller.txt to SkyTech6.");
				}
				logInstance4.LogInfo(val3);
				DevUtil.Dump(val5.User, "MissingKiller.txt");
				return;
			}
			User user2 = EntityUtil.Read<User>(val4.User);
			User user3 = EntityUtil.Read<User>(val5.User);
			text = ProcessUser("died", text, user2, val4);
			text = ProcessUser("killer", text, user3, val5);
			if (!string.IsNullOrEmpty(text))
			{
				if (Settings.DelayPVPMessages.Value > 0)
				{
					Core.StartCoroutine(DelayBroadcast(text, Settings.DelayPVPMessages.Value));
				}
				else
				{
					ChatUtil.SystemSendAll(text);
				}
			}
		}

		private static string ProcessVBlood(string message, PrefabGUID vblood)
		{
			//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)
			string newValue = VBloods.ToString(vblood);
			string newValue2 = VBloods.ToShortString(vblood);
			message = message.Replace("{vblood.long}", newValue);
			message = message.Replace("{vblood.short}", newValue2);
			message = message.Replace("{vblood}", newValue);
			return message;
		}

		public static string ProcessUser(string prefix, string message, User user, Player player)
		{
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			string text = Settings.PlayerNames.Value.Replace("{prefix", "{" + prefix);
			message = message.Replace("{" + prefix + ".name}", text.Replace("{" + prefix + ".name}", ((FixedString64Bytes)(ref user.CharacterName)).Value ?? ""));
			string text2 = Settings.PlayerCurrentLevel.Value.Replace("{prefix", "{" + prefix);
			message = message.Replace("{" + prefix + ".currentLv}", text2.Replace("{" + prefix + ".currentLv}", $"{player.Level}"));
			string text3 = Settings.PlayerRecordLevel.Value.Replace("{prefix", "{" + prefix);
			message = message.Replace("{" + prefix + ".recordLv}", text3.Replace("{" + prefix + ".recordLv}", $"{player.RecordLevel}"));
			if (Settings.RaidsHideRegion.Value && RaidTime.IsRaidTimeNow())
			{
				message = message.Replace("{region.short}", "");
				message = message.Replace("{region.long}", "");
				message = message.Replace("{region}", "");
			}
			else
			{
				string value = Settings.RegionShort.Value;
				string value2 = Settings.RegionLong.Value;
				message = message.Replace("{region.short}", value.Replace("{region.short}", player.GetWorldZoneString(true)));
				message = message.Replace("{region.long}", value2.Replace("{region.long}", player.GetWorldZoneString(false)));
				message = message.Replace("{region}", value2.Replace("{region.long}", player.GetWorldZoneString(false)));
			}
			if (((Entity)(ref user.ClanEntity._Entity)).Equals(Entity.Null))
			{
				message = message.Replace("{" + prefix + ".clanTag}", "");
				message = message.Replace("{" + prefix + ".clanName}", "");
			}
			else
			{
				ClanTeam val = EntityUtil.Read<ClanTeam>(user.ClanEntity._Entity);
				string text4 = Settings.ClanTags.Value.Replace("{prefix", "{" + prefix);
				string text5 = Settings.ClanNames.Value.Replace("{prefix", "{" + prefix);
				string text6 = message;
				string oldValue = "{" + prefix + ".clanTag}";
				string oldValue2 = "{" + prefix + ".clanTag}";
				FixedString32Bytes smartClanName = ClanUtility.GetSmartClanName(((FixedString64Bytes)(ref val.Name)).Value);
				message = text6.Replace(oldValue, text4.Replace(oldValue2, ((object)(FixedString32Bytes)(ref smartClanName)).ToString()));
				message = message.Replace("{" + prefix + ".clanName}", text5.Replace("{" + prefix + ".clanName}", ((FixedString64Bytes)(ref val.Name)).Value));
			}
			message = Regex.Replace(message, "<(?<tag>\\w+)(=[^>]*)?>\\s*</\\k<tag>>", "", RegexOptions.IgnoreCase);
			return Regex.Replace(message, "\\s+", " ").Trim();
		}

		private static IEnumerator DelayBroadcast(string message, int seconds)
		{
			yield return (object)new WaitForSeconds((float)seconds);
			ChatUtil.SystemSendAll(message);
		}
	}
	public enum DeathType
	{
		Downed,
		Killed,
		KillStolen,
		VBlood
	}
	public struct DeathTrack
	{
		public ulong killer_id;

		public ulong victim_id;

		public float3 location;

		public ulong steal_id;

		public bool offlined;

		public DeathTrack(ulong killer_id, ulong victim_id, float3 location)
		{
			//IL_001e: 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)
			steal_id = 0uL;
			offlined = false;
			this.killer_id = killer_id;
			this.victim_id = victim_id;
			this.location = location;
		}
	}
}
namespace CrimsonKiller.Patches
{
	[HarmonyPatch]
	internal static class DeathEventListenerSystemPatch
	{
		private static List<DeathTrack> Deaths = new List<DeathTrack>();

		private static readonly PrefabGUID siegeGolem = new PrefabGUID(914043867);

		[HarmonyPatch(typeof(DeathEventListenerSystem), "OnUpdate")]
		[HarmonyPostfix]
		private static void Postfix(DeathEventListenerSystem __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_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Expected O, but got Unknown
			//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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: 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)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			EntityQuery deathEventQuery = __instance._DeathEventQuery;
			NativeArray<DeathEvent> val = ((EntityQuery)(ref deathEventQuery)).ToComponentDataArray<DeathEvent>(AllocatorHandle.op_Implicit((Allocator)2));
			try
			{
				Enumerator<DeathEvent> enumerator = val.GetEnumerator();
				PlayerCharacter val2 = default(PlayerCharacter);
				Player val3 = default(Player);
				VBloodConsumeSource val4 = default(VBloodConsumeSource);
				while (enumerator.MoveNext())
				{
					DeathEvent current = enumerator.Current;
					if (!EntityUtil.Has<PlayerCharacter>(current.Killer))
					{
						continue;
					}
					Entity userEntity = EntityUtil.Read<PlayerCharacter>(current.Killer).UserEntity;
					if (EntityUtil.Has<PlayerCharacter>(current.Killer) && EntityUtil.Has<PlayerCharacter>(current.Died))
					{
						Entity diedEntity = EntityUtil.Read<PlayerCharacter>(current.Died).UserEntity;
						if (Deaths.Exists((DeathTrack x) => x.victim_id == EntityUtil.Read<User>(diedEntity).PlatformId))
						{
							DeathTrack deathTrack = Deaths.Find((DeathTrack x) => x.victim_id == EntityUtil.Read<User>(diedEntity).PlatformId);
							float3 value = EntityUtil.Read<Translation>(diedEntity).Value;
							if ((diedEntity == userEntity || EntityUtil.Read<User>(userEntity).PlatformId == deathTrack.killer_id) && math.distance(deathTrack.location, value) < 5f)
							{
								Broadcast.Message(DeathType.Killed, deathTrack);
							}
							else
							{
								deathTrack.steal_id = EntityUtil.Read<User>(userEntity).PlatformId;
								Broadcast.Message(DeathType.KillStolen, deathTrack);
							}
							Deaths.Remove(deathTrack);
						}
						if (!Settings.ToggleKillStreaks.Value)
						{
							continue;
						}
						Player killerPlayer = PlayerService.PlayerFromUser(EntityUtil.Read<User>(userEntity));
						Player deadPlayer = PlayerService.PlayerFromUser(EntityUtil.Read<User>(diedEntity));
						if (Database.CurrentStreaks.Exists((KillStreak x) => ((object)x.player).Equals((object?)deadPlayer)) && Database.CurrentStreaks.Remove(Database.CurrentStreaks.Find((KillStreak x) => ((object)x.player).Equals((object?)deadPlayer))) && Settings.ToggleKillStreakEndedMessage.Value)
						{
							if (!Database.Messages.TryGetValue("KillStreakEnded", out var value2))
							{
								continue;
							}
							value2 = Broadcast.ProcessUser("died", value2, EntityUtil.Read<User>(diedEntity), deadPlayer);
							value2 = Broadcast.ProcessUser("killer", value2, EntityUtil.Read<User>(userEntity), killerPlayer);
							ChatUtil.SystemSendAll(value2);
						}
						if (Database.CurrentStreaks.Exists((KillStreak x) => ((object)x.player).Equals((object?)killerPlayer)))
						{
							Database.CurrentStreaks.First((KillStreak x) => ((object)x.player).Equals((object?)killerPlayer)).AddKill(EntityUtil.Read<User>(diedEntity));
							continue;
						}
						Entity user = killerPlayer.User;
						if (!((Entity)(ref user)).Equals(deadPlayer.User))
						{
							Database.CurrentStreaks.Add(new KillStreak(killerPlayer, EntityUtil.Read<User>(deadPlayer.User), 1, 1));
						}
					}
					else if (EntityUtil.Has<PlayerCharacter>(current.Killer) && EntityUtil.Has<VBloodConsumeSource>(current.Died) && EntityUtil.TryGetComponent<PlayerCharacter>(current.Killer, ref val2) && PlayerService.TryFindByName(val2.Name, ref val3) && EntityUtil.TryGetComponent<VBloodConsumeSource>(current.Died, ref val4))
					{
						DeathTrack death = new DeathTrack(val3.SteamID, (ulong)((PrefabGUID)(ref val4.Source)).GuidHash, val3.Position);
						Broadcast.Message(DeathType.VBlood, death);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logInstance = Plugin.LogInstance;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(44, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("Exited DeathEventListenerSystem hook early: ");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<Exception>(ex);
				}
				logInstance.LogInfo(val5);
			}
			finally
			{
				val.Dispose();
			}
		}

		[HarmonyPatch(typeof(VampireDownedServerEventSystem), "OnUpdate")]
		[HarmonyPrefix]
		private static void Downed(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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: 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();
			Entity val = default(Entity);
			Entity val2 = default(Entity);
			PlayerCharacter val3 = default(PlayerCharacter);
			while (enumerator.MoveNext())
			{
				Entity current = enumerator.Current;
				if (!VampireDownedServerEventSystem.TryFindRootOwner(current, 1, Core.EntityManager, ref val) || !VampireDownedServerEventSystem.TryFindRootOwner(EntityUtil.Read<VampireDownedBuff>(current).Source, 1, Core.EntityManager, ref val2))
				{
					continue;
				}
				PlayerCharacter victim = EntityUtil.Read<PlayerCharacter>(val);
				if (!EntityUtil.Has<UnitLevel>(val2) && EntityUtil.TryGetComponent<PlayerCharacter>(val2, ref val3) && !(val3.UserEntity == victim.UserEntity))
				{
					Deaths.RemoveAll((DeathTrack x) => x.victim_id == EntityUtil.Read<User>(victim.UserEntity).PlatformId);
					float3 value = EntityUtil.Read<Translation>(EntityUtil.Read<User>(victim.UserEntity).LocalCharacter._Entity).Value;
					DeathTrack deathTrack = new DeathTrack(EntityUtil.Read<User>(val3.UserEntity).PlatformId, EntityUtil.Read<User>(victim.UserEntity).PlatformId, value);
					if (!EntityUtil.Read<User>(victim.UserEntity).IsConnected)
					{
						deathTrack.offlined = true;
					}
					Deaths.Add(deathTrack);
					Broadcast.Message(DeathType.Downed, deathTrack);
				}
			}
		}
	}
}